Compare commits
35 Commits
groupchats
...
file_trans
Author | SHA1 | Date | |
---|---|---|---|
adcc32fc49 | |||
61e7aad847 | |||
742d853b11 | |||
39fe859fe5 | |||
2a0895018a | |||
d1437b3445 | |||
59154d081f | |||
99e8691f0b | |||
b0e82dfd08 | |||
3a64121d72 | |||
99f31cc302 | |||
19de605b79 | |||
9e410254bf | |||
e970fbed80 | |||
9ed62d4414 | |||
9516723c7f | |||
52e6ace847 | |||
c7f50af25c | |||
7d8646b432 | |||
883a30f806 | |||
3bd7655203 | |||
fdfc74521b | |||
3db10ead6a | |||
546eb9f042 | |||
08ef8294df | |||
af5db43248 | |||
697a9efb51 | |||
6297da1c69 | |||
e78ba3942b | |||
28cedae342 | |||
3f9a35e164 | |||
babeeb969c | |||
01e6d45232 | |||
c865ae4df6 | |||
59452aa525 |
31
.travis.yml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
language: python
|
||||||
|
python:
|
||||||
|
- "3.4"
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get install -y checkinstall build-essential
|
||||||
|
- sudo apt-get install portaudio19-dev
|
||||||
|
install:
|
||||||
|
- pip install PySide --no-index --find-links https://parkin.github.io/python-wheelhouse/;
|
||||||
|
- python ~/virtualenv/python${TRAVIS_PYTHON_VERSION}/bin/pyside_postinstall.py -install
|
||||||
|
- pip install pyaudio
|
||||||
|
before_script:
|
||||||
|
# Libsodium
|
||||||
|
- git clone git://github.com/jedisct1/libsodium.git
|
||||||
|
- cd libsodium
|
||||||
|
- git checkout tags/1.0.3
|
||||||
|
- ./autogen.sh
|
||||||
|
- ./configure && make -j$(nproc)
|
||||||
|
- sudo checkinstall --install --pkgname libsodium --pkgversion 1.0.0 --nodoc -y
|
||||||
|
- sudo ldconfig
|
||||||
|
- cd ..
|
||||||
|
# Toxcore
|
||||||
|
- git clone https://github.com/irungentoo/toxcore.git
|
||||||
|
- cd toxcore
|
||||||
|
- autoreconf -if
|
||||||
|
- ./configure
|
||||||
|
- make -j$(nproc)
|
||||||
|
- sudo make install
|
||||||
|
- echo '/usr/local/lib/' | sudo tee -a /etc/ld.so.conf.d/locallib.conf
|
||||||
|
- sudo ldconfig
|
||||||
|
- cd ..
|
||||||
|
script: py.test tests/travis.py
|
@ -10,6 +10,8 @@ include toxygen/smileys/animated/config.json
|
|||||||
include toxygen/smileys/starwars/*.gif
|
include toxygen/smileys/starwars/*.gif
|
||||||
include toxygen/smileys/starwars/*.png
|
include toxygen/smileys/starwars/*.png
|
||||||
include toxygen/smileys/starwars/config.json
|
include toxygen/smileys/starwars/config.json
|
||||||
|
include toxygen/smileys/ksk/*.png
|
||||||
|
include toxygen/smileys/ksk/config.json
|
||||||
include toxygen/styles/style.qss
|
include toxygen/styles/style.qss
|
||||||
include toxygen/translations/*.qm
|
include toxygen/translations/*.qm
|
||||||
include toxygen/libs/libtox.dll
|
include toxygen/libs/libtox.dll
|
||||||
|
31
README.md
@ -1,17 +1,22 @@
|
|||||||
# Toxygen
|
# Toxygen
|
||||||
Toxygen is cross-platform [Tox](https://tox.chat/) client written in Python3
|
|
||||||
|
|
||||||
[](https://github.com/xveduk/toxygen/releases/latest)
|
Toxygen is cross-platform [Tox](https://tox.chat/) client written in pure Python3
|
||||||
[](https://github.com/xveduk/toxygen/issues)
|
|
||||||
[](https://raw.githubusercontent.com/xveduk/toxygen/master/LICENSE.md)
|
|
||||||
|
|
||||||
### [Install](/docs/install.md) - [Contribute](/docs/contributing.md) - [Plugins](/docs/plugins.md)
|
[](https://github.com/toxygen-project/toxygen/releases/latest)
|
||||||
|
[](https://github.com/toxygen-project/toxygen/stargazers)
|
||||||
|
[](https://github.com/toxygen-project/toxygen/issues)
|
||||||
|
[](https://raw.githubusercontent.com/toxygen-project/toxygen/master/LICENSE.md)
|
||||||
|
|
||||||
|
### [Install](/docs/install.md) - [Contribute](/docs/contributing.md) - [Plugins](/docs/plugins.md) - [Compile](/docs/compile.md) - [Contact](/docs/contact.md)
|
||||||
|
|
||||||
### Supported OS:
|
### Supported OS:
|
||||||
|
|
||||||
- Windows
|
- Windows
|
||||||
- Linux
|
- Linux
|
||||||
|
- OS X
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
###Features
|
|
||||||
- [x] 1v1 messages
|
- [x] 1v1 messages
|
||||||
- [x] File transfers
|
- [x] File transfers
|
||||||
- [x] Audio
|
- [x] Audio
|
||||||
@ -42,19 +47,17 @@ Toxygen is cross-platform [Tox](https://tox.chat/) client written in Python3
|
|||||||
- [ ] Desktop sharing
|
- [ ] Desktop sharing
|
||||||
- [ ] Group chats
|
- [ ] Group chats
|
||||||
|
|
||||||
###Downloads
|
### Downloads
|
||||||
[Releases](https://github.com/xveduk/toxygen/releases)
|
[Releases](https://github.com/toxygen-project/toxygen/releases)
|
||||||
|
|
||||||
[Download last stable version](https://github.com/xveduk/toxygen/archive/master.zip)
|
[Download last stable version](https://github.com/toxygen-project/toxygen/archive/master.zip)
|
||||||
|
|
||||||
[Download develop version](https://github.com/xveduk/toxygen/archive/develop.zip)
|
[Download develop version](https://github.com/toxygen-project/toxygen/archive/develop.zip)
|
||||||
|
|
||||||
###Screenshots
|
### Screenshots
|
||||||
*Toxygen on Ubuntu and Windows*
|
*Toxygen on Ubuntu and Windows*
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
### Docs
|
||||||
###Docs
|
|
||||||
[Check /docs/ for more info](/docs/)
|
[Check /docs/ for more info](/docs/)
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#Compile Toxygen
|
# Compile Toxygen
|
||||||
|
|
||||||
You can compile Toxygen using [PyInstaller](http://www.pyinstaller.org/)
|
You can compile Toxygen using [PyInstaller](http://www.pyinstaller.org/)
|
||||||
|
|
||||||
@ -7,4 +7,4 @@ Install PyInstaller:
|
|||||||
|
|
||||||
``pyinstaller --windowed --icon images/icon.ico main.py``
|
``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/, /plugins/ (and /libs/libtox.dll, /libs/libsodium.a on Windows) to /dist/main/
|
||||||
|
5
docs/contact.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Contact us:
|
||||||
|
|
||||||
|
1) Using GitHub - open issue
|
||||||
|
|
||||||
|
2) Use Toxygen Tox Group - add bot kalina@toxme.io (or 12EDB939AA529641CE53830B518D6EB30241868EE0E5023C46A372363CAEC91C2C948AEFE4EB)
|
@ -3,33 +3,50 @@
|
|||||||
## Use precompiled binary:
|
## Use precompiled binary:
|
||||||
[Check our releases page](https://github.com/xveduk/toxygen/releases)
|
[Check our releases page](https://github.com/xveduk/toxygen/releases)
|
||||||
|
|
||||||
##Using pip3
|
## Using pip3
|
||||||
|
|
||||||
### Windows (32-bit interpreter)
|
### Windows
|
||||||
|
|
||||||
``pip3.4 install toxygen``
|
``pip3.4 install toxygen``
|
||||||
|
|
||||||
Run app using ``toxygen`` command.
|
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/)
|
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:
|
2. Install PortAudio:
|
||||||
``sudo apt-get install portaudio19-dev``
|
``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``
|
``sudo pip3.4 install toxygen``
|
||||||
4 Run toxygen using ``toxygen`` command.
|
5. Run toxygen using ``toxygen`` command.
|
||||||
|
|
||||||
|
### OS X
|
||||||
|
|
||||||
|
1. Install [toxcore](https://github.com/irungentoo/toxcore/blob/master/INSTALL.md) with toxav support in your system
|
||||||
|
2. Install PortAudio:
|
||||||
|
``brew install portaudio``
|
||||||
|
3. Install toxygen:
|
||||||
|
``pip3 install toxygen``
|
||||||
|
4. Run toxygen using ``toxygen`` command.
|
||||||
|
|
||||||
|
## Packages
|
||||||
|
|
||||||
|
Coming soon.
|
||||||
|
|
||||||
## From source code (recommended for developers)
|
## From source code (recommended for developers)
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
1. [Download and install latest Python 3.4](https://www.python.org/downloads/windows/)
|
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)
|
2. [Install PySide](https://pypi.python.org/pypi/PySide/1.2.4#installing-pyside-on-a-windows-system) (recommended) or [PyQt4](https://riverbankcomputing.com/software/pyqt/download)
|
||||||
3. Install PyAudio: ``pip3.4 install pyaudio``
|
3. Install PyAudio: ``pip3.4 install pyaudio``
|
||||||
4. [Download toxygen](https://github.com/xveduk/toxygen/archive/master.zip)
|
4. [Download toxygen](https://github.com/xveduk/toxygen/archive/master.zip)
|
||||||
5. Unpack archive
|
5. Unpack archive
|
||||||
6. Download latest libtox.dll build, download latest libsodium.a build, put it into \src\libs\
|
6. Download latest libtox.dll build, download latest libsodium.a build, put it into \src\libs\
|
||||||
7. Run \src\main.py.
|
7. Run \toxygen\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)
|
[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)
|
||||||
|
|
||||||
@ -39,21 +56,31 @@ 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)
|
[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
|
### Linux
|
||||||
|
|
||||||
Dependencies:
|
1. Install latest Python3:
|
||||||
|
|
||||||
1. Install latest Python3.4:
|
|
||||||
``sudo apt-get install 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) (``sudo apt-get install python3-pyqt4``).
|
||||||
3. Install [toxcore](https://github.com/irungentoo/toxcore/blob/master/INSTALL.md) with toxav support in your system (install in /usr/lib/)
|
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:
|
4. Install PyAudio:
|
||||||
``sudo apt-get install portaudio19-dev`` and ``sudo apt-get install python3-pyaudio``
|
``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)
|
5. [Download toxygen](https://github.com/xveduk/toxygen/archive/master.zip)
|
||||||
6. Unpack archive
|
6. Unpack archive
|
||||||
7. Run app:
|
7. Run app:
|
||||||
``python3.4 main.py``
|
``python3.4 main.py``
|
||||||
|
|
||||||
## Compile Toxygen
|
Optional: install toxygen using setup.py: ``python3.4 setup.py install``
|
||||||
Check [compile.md](/docs/compile.md) for more info
|
|
||||||
|
### OS X
|
||||||
|
|
||||||
|
1. [Download and install latest Python 3.4](https://www.python.org/downloads/mac-osx/)
|
||||||
|
2. [Install PySide](https://pypi.python.org/pypi/PySide/1.2.4#installing-pyside-on-a-mac-os-x-system) (recommended) or [PyQt4](https://riverbankcomputing.com/software/pyqt/download)
|
||||||
|
3. Install PortAudio:
|
||||||
|
``brew install portaudio``
|
||||||
|
4. Install PyAudio: ``pip3 install pyaudio``
|
||||||
|
5. Install [toxcore](https://github.com/irungentoo/toxcore/blob/master/INSTALL.md) with toxav support in your system
|
||||||
|
6. [Download toxygen](https://github.com/xveduk/toxygen/archive/master.zip)
|
||||||
|
7. Unpack archive
|
||||||
|
8. Run \toxygen\main.py.
|
||||||
|
|
||||||
|
Optional: install toxygen using setup.py: ``python3 setup.py install``
|
||||||
|
@ -12,6 +12,7 @@ All plugin's data should be stored in following structure:
|
|||||||
|---plugin_short_name.py
|
|---plugin_short_name.py
|
||||||
|---/plugin_short_name/
|
|---/plugin_short_name/
|
||||||
|---settings.json
|
|---settings.json
|
||||||
|
|---readme.txt
|
||||||
|---logs.txt
|
|---logs.txt
|
||||||
|---other_files
|
|---other_files
|
||||||
```
|
```
|
||||||
|
32
setup.py
@ -3,14 +3,20 @@ from setuptools.command.install import install
|
|||||||
from platform import system
|
from platform import system
|
||||||
from subprocess import call
|
from subprocess import call
|
||||||
from toxygen.util import program_version
|
from toxygen.util import program_version
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
version = program_version + '.0'
|
version = program_version + '.0'
|
||||||
|
|
||||||
MODULES = ['PyAudio']
|
MODULES = []
|
||||||
|
|
||||||
if system() == 'Windows':
|
if system() in ('Windows', 'Darwin'):
|
||||||
MODULES.append('PySide')
|
MODULES = ['PyAudio', 'PySide']
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
import pyaudio
|
||||||
|
except ImportError:
|
||||||
|
MODULES = ['PyAudio']
|
||||||
|
|
||||||
|
|
||||||
class InstallScript(install):
|
class InstallScript(install):
|
||||||
@ -18,11 +24,25 @@ class InstallScript(install):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
install.run(self)
|
install.run(self)
|
||||||
OS = system()
|
try:
|
||||||
if OS == 'Windows':
|
if system() == 'Windows':
|
||||||
call(["toxygen", "--configure"])
|
call(["toxygen", "--configure"])
|
||||||
elif OS == 'Linux':
|
else:
|
||||||
call(["toxygen", "--clean"])
|
call(["toxygen", "--clean"])
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
params = list(filter(lambda x: x.startswith('--prefix='), sys.argv))
|
||||||
|
if params:
|
||||||
|
path = params[0][len('--prefix='):]
|
||||||
|
if path[-1] not in ('/', '\\'):
|
||||||
|
path += '/'
|
||||||
|
path += 'bin/toxygen'
|
||||||
|
if system() == 'Windows':
|
||||||
|
call([path, "--configure"])
|
||||||
|
else:
|
||||||
|
call([path, "--clean"])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
setup(name='Toxygen',
|
setup(name='Toxygen',
|
||||||
version=version,
|
version=version,
|
||||||
|
4
tests/travis.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
class TestToxygen:
|
||||||
|
|
||||||
|
def test_main(self):
|
||||||
|
import toxygen.main
|
@ -23,7 +23,7 @@ class IncomingCallWidget(widgets.CenteredWidget):
|
|||||||
self.name = widgets.DataLabel(self)
|
self.name = widgets.DataLabel(self)
|
||||||
self.name.setGeometry(QtCore.QRect(90, 20, 300, 25))
|
self.name.setGeometry(QtCore.QRect(90, 20, 300, 25))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily("Times New Roman")
|
font.setFamily(settings.Settings.get_instance['font'])
|
||||||
font.setPointSize(16)
|
font.setPointSize(16)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.name.setFont(font)
|
self.name.setFont(font)
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
import os
|
|
||||||
from settings import *
|
|
||||||
try:
|
|
||||||
from PySide import QtCore, QtGui
|
|
||||||
except ImportError:
|
|
||||||
from PyQt4 import QtCore, QtGui
|
|
||||||
from toxcore_enums_and_consts import TOX_PUBLIC_KEY_SIZE
|
|
||||||
|
|
||||||
|
|
||||||
class BaseContact:
|
|
||||||
"""
|
|
||||||
Class encapsulating TOX contact
|
|
||||||
Properties: name (alias of contact or name), status_message, status (connection status)
|
|
||||||
widget - widget for update
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, status_message, widget, tox_id):
|
|
||||||
"""
|
|
||||||
:param name: name, example: 'Toxygen user'
|
|
||||||
:param status_message: status message, example: 'Toxing on Toxygen'
|
|
||||||
:param widget: ContactItem instance
|
|
||||||
:param tox_id: tox id of contact
|
|
||||||
"""
|
|
||||||
self._name, self._status_message = name, status_message
|
|
||||||
self._status, self._widget = None, widget
|
|
||||||
self._widget.name.setText(name)
|
|
||||||
self._widget.status_message.setText(status_message)
|
|
||||||
self._tox_id = tox_id
|
|
||||||
self.load_avatar()
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Name - current name or alias of user
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def get_name(self):
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
def set_name(self, value):
|
|
||||||
self._name = str(value, 'utf-8')
|
|
||||||
self._widget.name.setText(self._name)
|
|
||||||
self._widget.name.repaint()
|
|
||||||
|
|
||||||
name = property(get_name, set_name)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Status message or group topic
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def get_status_message(self):
|
|
||||||
return self._status_message
|
|
||||||
|
|
||||||
def set_status_message(self, value):
|
|
||||||
self._status_message = str(value, 'utf-8')
|
|
||||||
self._widget.status_message.setText(self._status_message)
|
|
||||||
self._widget.status_message.repaint()
|
|
||||||
|
|
||||||
status_message = property(get_status_message, set_status_message)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Status
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def get_status(self):
|
|
||||||
return self._status
|
|
||||||
|
|
||||||
def set_status(self, value):
|
|
||||||
self._status = value
|
|
||||||
self._widget.connection_status.update(value)
|
|
||||||
|
|
||||||
status = property(get_status, set_status)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# TOX ID. WARNING: for friend it will return public key, for profile - full address
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def get_tox_id(self):
|
|
||||||
return self._tox_id
|
|
||||||
|
|
||||||
tox_id = property(get_tox_id)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Avatars
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def load_avatar(self, default_path='avatar.png'):
|
|
||||||
"""
|
|
||||||
Tries to load avatar of contact or uses default avatar
|
|
||||||
"""
|
|
||||||
avatar_path = '{}.png'.format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
|
|
||||||
os.chdir(ProfileHelper.get_path() + 'avatars/')
|
|
||||||
if not os.path.isfile(avatar_path): # load default image
|
|
||||||
avatar_path = default_path
|
|
||||||
os.chdir(curr_directory() + '/images/')
|
|
||||||
width = self._widget.avatar_label.width()
|
|
||||||
pixmap = QtGui.QPixmap(QtCore.QSize(width, width))
|
|
||||||
pixmap.load(avatar_path)
|
|
||||||
self._widget.avatar_label.setScaledContents(False)
|
|
||||||
self._widget.avatar_label.setPixmap(pixmap.scaled(width, width, QtCore.Qt.KeepAspectRatio))
|
|
||||||
self._widget.avatar_label.repaint()
|
|
||||||
|
|
||||||
def reset_avatar(self):
|
|
||||||
avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
|
|
||||||
if os.path.isfile(avatar_path):
|
|
||||||
os.remove(avatar_path)
|
|
||||||
self.load_avatar()
|
|
||||||
|
|
||||||
def set_avatar(self, avatar):
|
|
||||||
avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
|
|
||||||
with open(avatar_path, 'wb') as f:
|
|
||||||
f.write(avatar)
|
|
||||||
self.load_avatar()
|
|
||||||
|
|
||||||
def get_pixmap(self):
|
|
||||||
return self._widget.avatar_label.pixmap()
|
|
@ -9,6 +9,14 @@ from toxcore_enums_and_consts import *
|
|||||||
from toxav_enums import *
|
from toxav_enums import *
|
||||||
from tox import bin_to_string
|
from tox import bin_to_string
|
||||||
from plugin_support import PluginLoader
|
from plugin_support import PluginLoader
|
||||||
|
import queue
|
||||||
|
import threading
|
||||||
|
import util
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Threads
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class InvokeEvent(QtCore.QEvent):
|
class InvokeEvent(QtCore.QEvent):
|
||||||
@ -33,6 +41,44 @@ _invoker = Invoker()
|
|||||||
def invoke_in_main_thread(fn, *args, **kwargs):
|
def invoke_in_main_thread(fn, *args, **kwargs):
|
||||||
QtCore.QCoreApplication.postEvent(_invoker, InvokeEvent(fn, *args, **kwargs))
|
QtCore.QCoreApplication.postEvent(_invoker, InvokeEvent(fn, *args, **kwargs))
|
||||||
|
|
||||||
|
|
||||||
|
class FileTransfersThread(threading.Thread):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._queue = queue.Queue()
|
||||||
|
self._timeout = 0.01
|
||||||
|
self._continue = True
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def execute(self, function, *args, **kwargs):
|
||||||
|
self._queue.put((function, args, kwargs))
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._continue = False
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while self._continue:
|
||||||
|
try:
|
||||||
|
function, args, kwargs = self._queue.get(timeout=self._timeout)
|
||||||
|
function(*args, **kwargs)
|
||||||
|
except queue.Empty:
|
||||||
|
pass
|
||||||
|
except queue.Full:
|
||||||
|
util.log('Queue is Full in _thread')
|
||||||
|
except Exception as ex:
|
||||||
|
util.log('Exception in _thread: ' + str(ex))
|
||||||
|
|
||||||
|
_thread = FileTransfersThread()
|
||||||
|
|
||||||
|
|
||||||
|
def start():
|
||||||
|
_thread.start()
|
||||||
|
|
||||||
|
|
||||||
|
def stop():
|
||||||
|
_thread.stop()
|
||||||
|
_thread.join()
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Callbacks - current user
|
# Callbacks - current user
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
@ -68,7 +114,7 @@ def friend_status(tox, friend_num, new_status, user_data):
|
|||||||
if friend.status is None and Settings.get_instance()['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']:
|
if friend.status is None and Settings.get_instance()['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']:
|
||||||
sound_notification(SOUND_NOTIFICATION['FRIEND_CONNECTION_STATUS'])
|
sound_notification(SOUND_NOTIFICATION['FRIEND_CONNECTION_STATUS'])
|
||||||
invoke_in_main_thread(friend.set_status, new_status)
|
invoke_in_main_thread(friend.set_status, new_status)
|
||||||
invoke_in_main_thread(profile.send_files, friend_num)
|
invoke_in_main_thread(QtCore.QTimer.singleShot, 5000, lambda: profile.send_files(friend_num))
|
||||||
invoke_in_main_thread(profile.update_filtration)
|
invoke_in_main_thread(profile.update_filtration)
|
||||||
|
|
||||||
|
|
||||||
@ -197,28 +243,15 @@ def file_recv_chunk(tox, friend_number, file_number, position, chunk, length, us
|
|||||||
"""
|
"""
|
||||||
Incoming chunk
|
Incoming chunk
|
||||||
"""
|
"""
|
||||||
if not length:
|
_thread.execute(Profile.get_instance().incoming_chunk, friend_number, file_number, position,
|
||||||
invoke_in_main_thread(Profile.get_instance().incoming_chunk,
|
chunk[:length] if length else None)
|
||||||
friend_number,
|
|
||||||
file_number,
|
|
||||||
position,
|
|
||||||
None)
|
|
||||||
else:
|
|
||||||
Profile.get_instance().incoming_chunk(friend_number, file_number, position, chunk[:length])
|
|
||||||
|
|
||||||
|
|
||||||
def file_chunk_request(tox, friend_number, file_number, position, size, user_data):
|
def file_chunk_request(tox, friend_number, file_number, position, size, user_data):
|
||||||
"""
|
"""
|
||||||
Outgoing chunk
|
Outgoing chunk
|
||||||
"""
|
"""
|
||||||
if size:
|
|
||||||
Profile.get_instance().outgoing_chunk(friend_number, file_number, position, size)
|
Profile.get_instance().outgoing_chunk(friend_number, file_number, position, size)
|
||||||
else:
|
|
||||||
invoke_in_main_thread(Profile.get_instance().outgoing_chunk,
|
|
||||||
friend_number,
|
|
||||||
file_number,
|
|
||||||
position,
|
|
||||||
size)
|
|
||||||
|
|
||||||
|
|
||||||
def file_recv_control(tox, friend_number, file_number, file_control, user_data):
|
def file_recv_control(tox, friend_number, file_number, file_control, user_data):
|
||||||
@ -280,56 +313,12 @@ def callback_audio(toxav, friend_number, samples, audio_samples_per_channel, aud
|
|||||||
"""
|
"""
|
||||||
New audio chunk
|
New audio chunk
|
||||||
"""
|
"""
|
||||||
# print(audio_samples_per_channel, audio_channels_count, rate)
|
|
||||||
Profile.get_instance().call.chunk(
|
Profile.get_instance().call.chunk(
|
||||||
bytes(samples[:audio_samples_per_channel * 2 * audio_channels_count]),
|
bytes(samples[:audio_samples_per_channel * 2 * audio_channels_count]),
|
||||||
audio_channels_count,
|
audio_channels_count,
|
||||||
rate)
|
rate)
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Callbacks - group chats
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_message(window, tray, tox):
|
|
||||||
"""
|
|
||||||
New message in group chat
|
|
||||||
"""
|
|
||||||
def wrapped(tox_link, group_number, peer_id, message_type, message, length, user_data):
|
|
||||||
profile = Profile.get_instance()
|
|
||||||
settings = Settings.get_instance()
|
|
||||||
message = str(message[:length], 'utf-8')
|
|
||||||
invoke_in_main_thread(profile.new_message, group_number, message_type, message, True, peer_id)
|
|
||||||
if not window.isActiveWindow():
|
|
||||||
bl = settings['notify_all_gc'] or profile.name in message
|
|
||||||
name = tox.group_peer_get_name(group_number, peer_id)
|
|
||||||
if settings['notifications'] and profile.status != TOX_USER_STATUS['BUSY'] and (not settings.locked) and bl:
|
|
||||||
invoke_in_main_thread(tray_notification, name, message, tray, window)
|
|
||||||
if settings['sound_notifications'] and bl and profile.status != TOX_USER_STATUS['BUSY']:
|
|
||||||
sound_notification(SOUND_NOTIFICATION['MESSAGE'])
|
|
||||||
invoke_in_main_thread(tray.setIcon, QtGui.QIcon(curr_directory() + '/images/icon_new_messages.png'))
|
|
||||||
return wrapped
|
|
||||||
|
|
||||||
|
|
||||||
def group_invite(tox, friend_number, invite_data, length, user_data):
|
|
||||||
invoke_in_main_thread(Profile.get_instance().process_group_invite,
|
|
||||||
friend_number,
|
|
||||||
bytes(invite_data[:length]))
|
|
||||||
|
|
||||||
|
|
||||||
def group_self_join(tox, group_number, user_data):
|
|
||||||
pr = Profile.get_instance()
|
|
||||||
gc = pr.get_gc_by_number(group_number)
|
|
||||||
invoke_in_main_thread(gc.set_status, TOX_USER_STATUS['NONE'])
|
|
||||||
if not pr.is_active_a_friend() and pr.get_active_number() == group_number:
|
|
||||||
invoke_in_main_thread(pr.set_active)
|
|
||||||
|
|
||||||
|
|
||||||
def group_peer_join(tox, group_number, peer_id, user_data):
|
|
||||||
gc = Profile.get_instance().get_gc_by_number(group_number)
|
|
||||||
gc.add_peer(peer_id)
|
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Callbacks - initialization
|
# Callbacks - initialization
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
@ -366,8 +355,3 @@ def init_callbacks(tox, window, tray):
|
|||||||
tox.callback_friend_lossless_packet(lossless_packet, 0)
|
tox.callback_friend_lossless_packet(lossless_packet, 0)
|
||||||
tox.callback_friend_lossy_packet(lossy_packet, 0)
|
tox.callback_friend_lossy_packet(lossy_packet, 0)
|
||||||
|
|
||||||
tox.callback_group_message(group_message(window, tray, tox), 0)
|
|
||||||
tox.callback_group_invite(group_invite, 0)
|
|
||||||
tox.callback_group_self_join(group_self_join, 0)
|
|
||||||
tox.callback_group_peer_join(group_peer_join, 0)
|
|
||||||
|
|
||||||
|
@ -1,212 +1,113 @@
|
|||||||
|
import os
|
||||||
|
from settings import *
|
||||||
try:
|
try:
|
||||||
from PySide import QtCore, QtGui
|
from PySide import QtCore, QtGui
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
import basecontact
|
from toxcore_enums_and_consts import TOX_PUBLIC_KEY_SIZE
|
||||||
from messages import *
|
|
||||||
from history import *
|
|
||||||
import file_transfers as ft
|
|
||||||
import util
|
|
||||||
|
|
||||||
|
|
||||||
class Contact(basecontact.BaseContact):
|
class Contact:
|
||||||
"""
|
"""
|
||||||
Class encapsulating TOX contact
|
Class encapsulating TOX contact
|
||||||
Properties: name (alias of contact or name), status_message, status (connection status)
|
Properties: name (alias of contact or name), status_message, status (connection status)
|
||||||
widget - widget for update
|
widget - widget for update
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, number, message_getter, name, status_message, widget, tox_id):
|
def __init__(self, name, status_message, widget, tox_id):
|
||||||
"""
|
"""
|
||||||
:param name: name, example: 'Toxygen user'
|
:param name: name, example: 'Toxygen user'
|
||||||
:param status_message: status message, example: 'Toxing on Toxygen'
|
:param status_message: status message, example: 'Toxing on Toxygen'
|
||||||
:param widget: ContactItem instance
|
:param widget: ContactItem instance
|
||||||
:param tox_id: tox id of contact
|
:param tox_id: tox id of contact
|
||||||
"""
|
"""
|
||||||
super().__init__(name, status_message, widget, tox_id)
|
self._name, self._status_message = name, status_message
|
||||||
self._message_getter = message_getter
|
self._status, self._widget = None, widget
|
||||||
self._new_messages = False
|
self._widget.name.setText(name)
|
||||||
self._visible = True
|
self._widget.status_message.setText(status_message)
|
||||||
self._alias = False
|
self._tox_id = tox_id
|
||||||
self._number = number
|
self.load_avatar()
|
||||||
self._corr = []
|
|
||||||
self._unsaved_messages = 0
|
|
||||||
self._history_loaded = self._new_actions = False
|
|
||||||
self._curr_text = ''
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
self.set_visibility(False)
|
|
||||||
del self._widget
|
|
||||||
if hasattr(self, '_message_getter'):
|
|
||||||
del self._message_getter
|
|
||||||
|
|
||||||
def load_corr(self, first_time=True):
|
|
||||||
"""
|
|
||||||
:param first_time: friend became active, load first part of messages
|
|
||||||
"""
|
|
||||||
if (first_time and self._history_loaded) or (not hasattr(self, '_message_getter')):
|
|
||||||
return
|
|
||||||
data = list(self._message_getter.get(PAGE_SIZE))
|
|
||||||
if data is not None and len(data):
|
|
||||||
data.reverse()
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
data = list(map(lambda tupl: TextMessage(*tupl), data))
|
|
||||||
self._corr = data + self._corr
|
|
||||||
self._history_loaded = True
|
|
||||||
|
|
||||||
def get_corr_for_saving(self):
|
|
||||||
"""
|
|
||||||
Get data to save in db
|
|
||||||
:return: list of unsaved messages or []
|
|
||||||
"""
|
|
||||||
messages = list(filter(lambda x: x.get_type() <= 1, self._corr))
|
|
||||||
return list(map(lambda x: x.get_data(), messages[-self._unsaved_messages:])) if self._unsaved_messages else []
|
|
||||||
|
|
||||||
def get_corr(self):
|
|
||||||
return self._corr[:]
|
|
||||||
|
|
||||||
def append_message(self, message):
|
|
||||||
"""
|
|
||||||
:param message: text or file transfer message
|
|
||||||
"""
|
|
||||||
self._corr.append(message)
|
|
||||||
if message.get_type() <= 1:
|
|
||||||
self._unsaved_messages += 1
|
|
||||||
|
|
||||||
def get_last_message_text(self):
|
|
||||||
messages = list(filter(lambda x: x.get_type() <= 1 and x.get_owner() != MESSAGE_OWNER['FRIEND'], self._corr))
|
|
||||||
if messages:
|
|
||||||
return messages[-1].get_data()[0]
|
|
||||||
else:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def get_unsent_messages(self):
|
|
||||||
"""
|
|
||||||
:return list of unsent messages
|
|
||||||
"""
|
|
||||||
messages = filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr)
|
|
||||||
return list(messages)
|
|
||||||
|
|
||||||
def get_unsent_messages_for_saving(self):
|
|
||||||
"""
|
|
||||||
:return list of unsent messages for saving
|
|
||||||
"""
|
|
||||||
messages = filter(lambda x: x.get_type() <= 1 and x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr)
|
|
||||||
return list(map(lambda x: x.get_data(), messages))
|
|
||||||
|
|
||||||
def delete_message(self, time):
|
|
||||||
elem = list(filter(lambda x: type(x) is TextMessage and x.get_data()[2] == time, self._corr))[0]
|
|
||||||
tmp = list(filter(lambda x: x.get_type() <= 1, self._corr))
|
|
||||||
if elem in tmp[-self._unsaved_messages:]:
|
|
||||||
self._unsaved_messages -= 1
|
|
||||||
self._corr.remove(elem)
|
|
||||||
|
|
||||||
def delete_old_messages(self):
|
|
||||||
old = filter(lambda x: x.get_type() in (2, 3) and (x.get_status() >= 2 or x.get_status() is None),
|
|
||||||
self._corr[:-SAVE_MESSAGES])
|
|
||||||
old = list(old)
|
|
||||||
l = max(len(self._corr) - SAVE_MESSAGES, 0) - len(old)
|
|
||||||
self._unsaved_messages -= l
|
|
||||||
self._corr = old + self._corr[-SAVE_MESSAGES:]
|
|
||||||
|
|
||||||
def mark_as_sent(self):
|
|
||||||
try:
|
|
||||||
message = list(filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr))[0]
|
|
||||||
message.mark_as_sent()
|
|
||||||
except Exception as ex:
|
|
||||||
util.log('Mark as sent ex: ' + str(ex))
|
|
||||||
|
|
||||||
def clear_corr(self, save_unsent=False):
|
|
||||||
"""
|
|
||||||
Clear messages list
|
|
||||||
"""
|
|
||||||
if hasattr(self, '_message_getter'):
|
|
||||||
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
|
|
||||||
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))
|
|
||||||
self._unsaved_messages = len(self.get_unsent_messages())
|
|
||||||
|
|
||||||
def get_curr_text(self):
|
|
||||||
return self._curr_text
|
|
||||||
|
|
||||||
def set_curr_text(self, value):
|
|
||||||
self._curr_text = value
|
|
||||||
|
|
||||||
curr_text = property(get_curr_text, set_curr_text)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Visibility in friends' list
|
# name - current name or alias of user
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
def get_visibility(self):
|
def get_name(self):
|
||||||
return self._visible
|
return self._name
|
||||||
|
|
||||||
def set_visibility(self, value):
|
|
||||||
self._visible = value
|
|
||||||
|
|
||||||
visibility = property(get_visibility, set_visibility)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Unread messages and actions
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def get_actions(self):
|
|
||||||
return self._new_actions
|
|
||||||
|
|
||||||
def set_actions(self, value):
|
|
||||||
self._new_actions = value
|
|
||||||
self._widget.connection_status.update(self.status, value)
|
|
||||||
|
|
||||||
actions = property(get_actions, set_actions) # unread messages, incoming files, av calls
|
|
||||||
|
|
||||||
def get_messages(self):
|
|
||||||
return self._new_messages
|
|
||||||
|
|
||||||
def inc_messages(self):
|
|
||||||
self._new_messages += 1
|
|
||||||
self._new_actions = True
|
|
||||||
self._widget.connection_status.update(self.status, True)
|
|
||||||
self._widget.messages.update(self._new_messages)
|
|
||||||
|
|
||||||
def reset_messages(self):
|
|
||||||
self._new_actions = False
|
|
||||||
self._new_messages = 0
|
|
||||||
self._widget.messages.update(self._new_messages)
|
|
||||||
self._widget.connection_status.update(self.status, False)
|
|
||||||
|
|
||||||
messages = property(get_messages)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Number (can be used in toxcore)
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def get_number(self):
|
|
||||||
return self._number
|
|
||||||
|
|
||||||
def set_number(self, value):
|
|
||||||
self._number = value
|
|
||||||
|
|
||||||
number = property(get_number, set_number)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Alias support
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def set_name(self, value):
|
def set_name(self, value):
|
||||||
"""
|
self._name = str(value, 'utf-8')
|
||||||
Set new name or ignore if alias exists
|
self._widget.name.setText(self._name)
|
||||||
:param value: new name
|
self._widget.name.repaint()
|
||||||
"""
|
|
||||||
if not self._alias:
|
|
||||||
super(Contact, self).set_name(value)
|
|
||||||
|
|
||||||
def set_alias(self, alias):
|
name = property(get_name, set_name)
|
||||||
self._alias = bool(alias)
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Status message
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_status_message(self):
|
||||||
|
return self._status_message
|
||||||
|
|
||||||
|
def set_status_message(self, value):
|
||||||
|
self._status_message = str(value, 'utf-8')
|
||||||
|
self._widget.status_message.setText(self._status_message)
|
||||||
|
self._widget.status_message.repaint()
|
||||||
|
|
||||||
|
status_message = property(get_status_message, set_status_message)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Status
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
return self._status
|
||||||
|
|
||||||
|
def set_status(self, value):
|
||||||
|
self._status = value
|
||||||
|
self._widget.connection_status.update(value)
|
||||||
|
|
||||||
|
status = property(get_status, set_status)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# TOX ID. WARNING: for friend it will return public key, for profile - full address
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_tox_id(self):
|
||||||
|
return self._tox_id
|
||||||
|
|
||||||
|
tox_id = property(get_tox_id)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Avatars
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def load_avatar(self):
|
||||||
|
"""
|
||||||
|
Tries to load avatar of contact or uses default avatar
|
||||||
|
"""
|
||||||
|
avatar_path = '{}.png'.format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
|
||||||
|
os.chdir(ProfileHelper.get_path() + 'avatars/')
|
||||||
|
if not os.path.isfile(avatar_path): # load default image
|
||||||
|
avatar_path = 'avatar.png'
|
||||||
|
os.chdir(curr_directory() + '/images/')
|
||||||
|
width = self._widget.avatar_label.width()
|
||||||
|
pixmap = QtGui.QPixmap(avatar_path)
|
||||||
|
self._widget.avatar_label.setPixmap(pixmap.scaled(width, width, QtCore.Qt.KeepAspectRatio,
|
||||||
|
QtCore.Qt.SmoothTransformation))
|
||||||
|
self._widget.avatar_label.repaint()
|
||||||
|
|
||||||
|
def reset_avatar(self):
|
||||||
|
avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
|
||||||
|
if os.path.isfile(avatar_path):
|
||||||
|
os.remove(avatar_path)
|
||||||
|
self.load_avatar()
|
||||||
|
|
||||||
|
def set_avatar(self, avatar):
|
||||||
|
avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(self._tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
|
||||||
|
with open(avatar_path, 'wb') as f:
|
||||||
|
f.write(avatar)
|
||||||
|
self.load_avatar()
|
||||||
|
|
||||||
|
def get_pixmap(self):
|
||||||
|
return self._widget.avatar_label.pixmap()
|
||||||
|
@ -8,8 +8,7 @@ try:
|
|||||||
from PySide import QtCore
|
from PySide import QtCore
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
QtCore.Signal = QtCore.pyqtSignal
|
||||||
# TODO: threads!
|
|
||||||
|
|
||||||
|
|
||||||
TOX_FILE_TRANSFER_STATE = {
|
TOX_FILE_TRANSFER_STATE = {
|
||||||
@ -34,10 +33,13 @@ ALLOWED_FILES = ('toxygen_inline.png', 'utox-inline.png', 'sticker.png')
|
|||||||
|
|
||||||
|
|
||||||
class StateSignal(QtCore.QObject):
|
class StateSignal(QtCore.QObject):
|
||||||
try:
|
|
||||||
signal = QtCore.Signal(int, float, int) # state and progress
|
signal = QtCore.Signal(int, float, int) # state, progress, time in sec
|
||||||
except:
|
|
||||||
signal = QtCore.pyqtSignal(int, float, int) # state and progress - pyqt4
|
|
||||||
|
class TransferFinishedSignal(QtCore.QObject):
|
||||||
|
|
||||||
|
signal = QtCore.Signal(int, int) # friend number, file number
|
||||||
|
|
||||||
|
|
||||||
class FileTransfer(QtCore.QObject):
|
class FileTransfer(QtCore.QObject):
|
||||||
@ -56,6 +58,8 @@ class FileTransfer(QtCore.QObject):
|
|||||||
self._size = float(size)
|
self._size = float(size)
|
||||||
self._done = 0
|
self._done = 0
|
||||||
self._state_changed = StateSignal()
|
self._state_changed = StateSignal()
|
||||||
|
self._finished = TransferFinishedSignal()
|
||||||
|
self._file_id = None
|
||||||
|
|
||||||
def set_tox(self, tox):
|
def set_tox(self, tox):
|
||||||
self._tox = tox
|
self._tox = tox
|
||||||
@ -63,6 +67,9 @@ class FileTransfer(QtCore.QObject):
|
|||||||
def set_state_changed_handler(self, handler):
|
def set_state_changed_handler(self, handler):
|
||||||
self._state_changed.signal.connect(handler)
|
self._state_changed.signal.connect(handler)
|
||||||
|
|
||||||
|
def set_transfer_finished_handler(self, handler):
|
||||||
|
self._finished.signal.connect(handler)
|
||||||
|
|
||||||
def signal(self):
|
def signal(self):
|
||||||
percentage = self._done / self._size if self._size else 0
|
percentage = self._done / self._size if self._size else 0
|
||||||
if self._creation_time is None or not percentage:
|
if self._creation_time is None or not percentage:
|
||||||
@ -71,12 +78,21 @@ class FileTransfer(QtCore.QObject):
|
|||||||
t = ((time() - self._creation_time) / percentage) * (1 - percentage)
|
t = ((time() - self._creation_time) / percentage) * (1 - percentage)
|
||||||
self._state_changed.signal.emit(self.state, percentage, int(t))
|
self._state_changed.signal.emit(self.state, percentage, int(t))
|
||||||
|
|
||||||
|
def finished(self):
|
||||||
|
self._finished.signal.emit(self._friend_number, self._file_number)
|
||||||
|
|
||||||
def get_file_number(self):
|
def get_file_number(self):
|
||||||
return self._file_number
|
return self._file_number
|
||||||
|
|
||||||
def get_friend_number(self):
|
def get_friend_number(self):
|
||||||
return self._friend_number
|
return self._friend_number
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return self._file_id
|
||||||
|
|
||||||
|
def get_path(self):
|
||||||
|
return self._path
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
self.send_control(TOX_FILE_CONTROL['CANCEL'])
|
self.send_control(TOX_FILE_CONTROL['CANCEL'])
|
||||||
if hasattr(self, '_file'):
|
if hasattr(self, '_file'):
|
||||||
@ -122,6 +138,7 @@ class SendTransfer(FileTransfer):
|
|||||||
self.state = TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED']
|
self.state = TOX_FILE_TRANSFER_STATE['OUTGOING_NOT_STARTED']
|
||||||
self._file_number = tox.file_send(friend_number, kind, size, file_id,
|
self._file_number = tox.file_send(friend_number, kind, size, file_id,
|
||||||
bytes(basename(path), 'utf-8') if path else b'')
|
bytes(basename(path), 'utf-8') if path else b'')
|
||||||
|
self._file_id = self.get_file_id()
|
||||||
|
|
||||||
def send_chunk(self, position, size):
|
def send_chunk(self, position, size):
|
||||||
"""
|
"""
|
||||||
@ -136,11 +153,11 @@ class SendTransfer(FileTransfer):
|
|||||||
data = self._file.read(size)
|
data = self._file.read(size)
|
||||||
self._tox.file_send_chunk(self._friend_number, self._file_number, position, data)
|
self._tox.file_send_chunk(self._friend_number, self._file_number, position, data)
|
||||||
self._done += size
|
self._done += size
|
||||||
self.signal()
|
|
||||||
else:
|
else:
|
||||||
if hasattr(self, '_file'):
|
if hasattr(self, '_file'):
|
||||||
self._file.close()
|
self._file.close()
|
||||||
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
||||||
|
self.finished()
|
||||||
self.signal()
|
self.signal()
|
||||||
|
|
||||||
|
|
||||||
@ -180,9 +197,9 @@ class SendFromBuffer(FileTransfer):
|
|||||||
data = self._data[position:position + size]
|
data = self._data[position:position + size]
|
||||||
self._tox.file_send_chunk(self._friend_number, self._file_number, position, data)
|
self._tox.file_send_chunk(self._friend_number, self._file_number, position, data)
|
||||||
self._done += size
|
self._done += size
|
||||||
self.signal()
|
|
||||||
else:
|
else:
|
||||||
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
||||||
|
self.finished()
|
||||||
self.signal()
|
self.signal()
|
||||||
|
|
||||||
|
|
||||||
@ -204,16 +221,23 @@ class SendFromFileBuffer(SendTransfer):
|
|||||||
|
|
||||||
class ReceiveTransfer(FileTransfer):
|
class ReceiveTransfer(FileTransfer):
|
||||||
|
|
||||||
def __init__(self, path, tox, friend_number, size, file_number):
|
def __init__(self, path, tox, friend_number, size, file_number, position=0):
|
||||||
super(ReceiveTransfer, self).__init__(path, tox, friend_number, size, file_number)
|
super(ReceiveTransfer, self).__init__(path, tox, friend_number, size, file_number)
|
||||||
self._file = open(self._path, 'wb')
|
self._file = open(self._path, 'wb')
|
||||||
self._file.truncate(0)
|
self._file_size = position
|
||||||
self._file_size = 0
|
self._file.truncate(position)
|
||||||
|
self._missed = set()
|
||||||
|
self._file_id = self.get_file_id()
|
||||||
|
self._done = position
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
super(ReceiveTransfer, self).cancel()
|
super(ReceiveTransfer, self).cancel()
|
||||||
remove(self._path)
|
remove(self._path)
|
||||||
|
|
||||||
|
def total_size(self):
|
||||||
|
self._missed.add(self._file_size)
|
||||||
|
return min(self._missed)
|
||||||
|
|
||||||
def write_chunk(self, position, data):
|
def write_chunk(self, position, data):
|
||||||
"""
|
"""
|
||||||
Incoming chunk
|
Incoming chunk
|
||||||
@ -225,12 +249,15 @@ class ReceiveTransfer(FileTransfer):
|
|||||||
if data is None:
|
if data is None:
|
||||||
self._file.close()
|
self._file.close()
|
||||||
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
||||||
self.signal()
|
self.finished()
|
||||||
else:
|
else:
|
||||||
data = bytearray(data)
|
data = bytearray(data)
|
||||||
if self._file_size < position:
|
if self._file_size < position:
|
||||||
self._file.seek(0, 2)
|
self._file.seek(0, 2)
|
||||||
self._file.write(b'\0' * (position - self._file_size))
|
self._file.write(b'\0' * (position - self._file_size))
|
||||||
|
self._missed.add(self._file_size)
|
||||||
|
else:
|
||||||
|
self._missed.discard(position)
|
||||||
self._file.seek(position)
|
self._file.seek(position)
|
||||||
self._file.write(data)
|
self._file.write(data)
|
||||||
l = len(data)
|
l = len(data)
|
||||||
@ -258,6 +285,7 @@ class ReceiveToBuffer(FileTransfer):
|
|||||||
self._creation_time = time()
|
self._creation_time = time()
|
||||||
if data is None:
|
if data is None:
|
||||||
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
||||||
|
self.finished()
|
||||||
else:
|
else:
|
||||||
data = bytes(data)
|
data = bytes(data)
|
||||||
l = len(data)
|
l = len(data)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import contact
|
import contact
|
||||||
from messages import *
|
from messages import *
|
||||||
|
from history import *
|
||||||
|
import util
|
||||||
|
import file_transfers as ft
|
||||||
|
|
||||||
|
|
||||||
class Friend(contact.Contact):
|
class Friend(contact.Contact):
|
||||||
@ -7,15 +10,28 @@ class Friend(contact.Contact):
|
|||||||
Friend in list of friends. Can be hidden, properties 'has unread messages' and 'has alias' added
|
Friend in list of friends. Can be hidden, properties 'has unread messages' and 'has alias' added
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, message_getter, number, *args):
|
||||||
"""
|
"""
|
||||||
|
:param message_getter: gets messages from db
|
||||||
:param number: number of friend.
|
:param number: number of friend.
|
||||||
"""
|
"""
|
||||||
super(Friend, self).__init__(*args)
|
super(Friend, self).__init__(*args)
|
||||||
|
self._number = number
|
||||||
|
self._new_messages = False
|
||||||
|
self._visible = True
|
||||||
|
self._alias = False
|
||||||
|
self._message_getter = message_getter
|
||||||
|
self._corr = []
|
||||||
|
self._unsaved_messages = 0
|
||||||
|
self._history_loaded = self._new_actions = False
|
||||||
self._receipts = 0
|
self._receipts = 0
|
||||||
|
self._curr_text = ''
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
super().__del__()
|
self.set_visibility(False)
|
||||||
|
del self._widget
|
||||||
|
if hasattr(self, '_message_getter'):
|
||||||
|
del self._message_getter
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# History support
|
# History support
|
||||||
@ -34,6 +50,108 @@ class Friend(contact.Contact):
|
|||||||
self._receipts -= 1
|
self._receipts -= 1
|
||||||
self.mark_as_sent()
|
self.mark_as_sent()
|
||||||
|
|
||||||
|
def load_corr(self, first_time=True):
|
||||||
|
"""
|
||||||
|
:param first_time: friend became active, load first part of messages
|
||||||
|
"""
|
||||||
|
if (first_time and self._history_loaded) or (not hasattr(self, '_message_getter')):
|
||||||
|
return
|
||||||
|
data = list(self._message_getter.get(PAGE_SIZE))
|
||||||
|
if data is not None and len(data):
|
||||||
|
data.reverse()
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
data = list(map(lambda tupl: TextMessage(*tupl), data))
|
||||||
|
self._corr = data + self._corr
|
||||||
|
self._history_loaded = True
|
||||||
|
|
||||||
|
def load_all_corr(self):
|
||||||
|
data = list(self._message_getter.get_all())
|
||||||
|
if data is not None and len(data):
|
||||||
|
data.reverse()
|
||||||
|
data = list(map(lambda tupl: TextMessage(*tupl), data))
|
||||||
|
self._corr = data + self._corr
|
||||||
|
self._history_loaded = True
|
||||||
|
|
||||||
|
def get_corr_for_saving(self):
|
||||||
|
"""
|
||||||
|
Get data to save in db
|
||||||
|
:return: list of unsaved messages or []
|
||||||
|
"""
|
||||||
|
messages = list(filter(lambda x: x.get_type() <= 1, self._corr))
|
||||||
|
return list(map(lambda x: x.get_data(), messages[-self._unsaved_messages:])) if self._unsaved_messages else []
|
||||||
|
|
||||||
|
def get_corr(self):
|
||||||
|
return self._corr[:]
|
||||||
|
|
||||||
|
def append_message(self, message):
|
||||||
|
"""
|
||||||
|
:param message: text or file transfer message
|
||||||
|
"""
|
||||||
|
self._corr.append(message)
|
||||||
|
if message.get_type() <= 1:
|
||||||
|
self._unsaved_messages += 1
|
||||||
|
|
||||||
|
def get_last_message_text(self):
|
||||||
|
messages = list(filter(lambda x: x.get_type() <= 1 and x.get_owner() != MESSAGE_OWNER['FRIEND'], self._corr))
|
||||||
|
if messages:
|
||||||
|
return messages[-1].get_data()[0]
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def get_unsent_messages(self):
|
||||||
|
"""
|
||||||
|
:return list of unsent messages
|
||||||
|
"""
|
||||||
|
messages = filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr)
|
||||||
|
return list(messages)
|
||||||
|
|
||||||
|
def get_unsent_messages_for_saving(self):
|
||||||
|
"""
|
||||||
|
:return list of unsent messages for saving
|
||||||
|
"""
|
||||||
|
messages = filter(lambda x: x.get_type() <= 1 and x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr)
|
||||||
|
return list(map(lambda x: x.get_data(), messages))
|
||||||
|
|
||||||
|
def delete_message(self, time):
|
||||||
|
elem = list(filter(lambda x: type(x) is TextMessage and x.get_data()[2] == time, self._corr))[0]
|
||||||
|
tmp = list(filter(lambda x: x.get_type() <= 1, self._corr))
|
||||||
|
if elem in tmp[-self._unsaved_messages:]:
|
||||||
|
self._unsaved_messages -= 1
|
||||||
|
self._corr.remove(elem)
|
||||||
|
|
||||||
|
def mark_as_sent(self):
|
||||||
|
try:
|
||||||
|
message = list(filter(lambda x: x.get_owner() == MESSAGE_OWNER['NOT_SENT'], self._corr))[0]
|
||||||
|
message.mark_as_sent()
|
||||||
|
except Exception as ex:
|
||||||
|
util.log('Mark as sent ex: ' + str(ex))
|
||||||
|
|
||||||
|
def clear_corr(self, save_unsent=False):
|
||||||
|
"""
|
||||||
|
Clear messages list
|
||||||
|
"""
|
||||||
|
if hasattr(self, '_message_getter'):
|
||||||
|
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() == 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() == 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())
|
||||||
|
|
||||||
|
def get_curr_text(self):
|
||||||
|
return self._curr_text
|
||||||
|
|
||||||
|
def set_curr_text(self, value):
|
||||||
|
self._curr_text = value
|
||||||
|
|
||||||
|
curr_text = property(get_curr_text, set_curr_text)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# File transfers support
|
# File transfers support
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
@ -62,3 +180,72 @@ class Friend(contact.Contact):
|
|||||||
|
|
||||||
def delete_one_unsent_file(self, time):
|
def delete_one_unsent_file(self, time):
|
||||||
self._corr = list(filter(lambda x: not (type(x) is UnsentFile and x.get_data()[2] == time), self._corr))
|
self._corr = list(filter(lambda x: not (type(x) is UnsentFile and x.get_data()[2] == time), self._corr))
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Alias support
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def set_name(self, value):
|
||||||
|
"""
|
||||||
|
Set new name or ignore if alias exists
|
||||||
|
:param value: new name
|
||||||
|
"""
|
||||||
|
if not self._alias:
|
||||||
|
super(Friend, self).set_name(value)
|
||||||
|
|
||||||
|
def set_alias(self, alias):
|
||||||
|
self._alias = bool(alias)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Visibility in friends' list
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_visibility(self):
|
||||||
|
return self._visible
|
||||||
|
|
||||||
|
def set_visibility(self, value):
|
||||||
|
self._visible = value
|
||||||
|
|
||||||
|
visibility = property(get_visibility, set_visibility)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Unread messages from friend
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_actions(self):
|
||||||
|
return self._new_actions
|
||||||
|
|
||||||
|
def set_actions(self, value):
|
||||||
|
self._new_actions = value
|
||||||
|
self._widget.connection_status.update(self.status, value)
|
||||||
|
|
||||||
|
actions = property(get_actions, set_actions) # unread messages, incoming files, av calls
|
||||||
|
|
||||||
|
def get_messages(self):
|
||||||
|
return self._new_messages
|
||||||
|
|
||||||
|
def inc_messages(self):
|
||||||
|
self._new_messages += 1
|
||||||
|
self._new_actions = True
|
||||||
|
self._widget.connection_status.update(self.status, True)
|
||||||
|
self._widget.messages.update(self._new_messages)
|
||||||
|
|
||||||
|
def reset_messages(self):
|
||||||
|
self._new_actions = False
|
||||||
|
self._new_messages = 0
|
||||||
|
self._widget.messages.update(self._new_messages)
|
||||||
|
self._widget.connection_status.update(self.status, False)
|
||||||
|
|
||||||
|
messages = property(get_messages)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
# Friend's number (can be used in toxcore)
|
||||||
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_number(self):
|
||||||
|
return self._number
|
||||||
|
|
||||||
|
def set_number(self, value):
|
||||||
|
self._number = value
|
||||||
|
|
||||||
|
number = property(get_number, set_number)
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
import contact
|
|
||||||
|
|
||||||
|
|
||||||
class GroupChat(contact.Contact):
|
|
||||||
|
|
||||||
def __init__(self, tox, *args):
|
|
||||||
super().__init__(*args)
|
|
||||||
self._tox = tox
|
|
||||||
|
|
||||||
def load_avatar(self, default_path='group.png'):
|
|
||||||
super().load_avatar(default_path)
|
|
||||||
|
|
||||||
def set_status(self, value):
|
|
||||||
print('In gc set_status')
|
|
||||||
super().set_status(value)
|
|
||||||
self.name = bytes(self._tox.group_get_name(self._number), 'utf-8')
|
|
||||||
self._tox_id = self._tox.group_get_chat_id(self._number)
|
|
||||||
self.status_message = bytes(self._tox.group_get_topic(self._number), 'utf-8')
|
|
||||||
|
|
||||||
def add_peer(self, peer_id):
|
|
||||||
print(peer_id)
|
|
||||||
print(self._tox.group_peer_get_name(self._number, peer_id))
|
|
||||||
|
|
||||||
# TODO: get peers list and add other methods
|
|
||||||
|
|
||||||
def get_peers_list(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
class Peer:
|
|
||||||
|
|
||||||
def __init__(self, peer_id, name, status, role):
|
|
||||||
self._data = (peer_id, name, status, role)
|
|
||||||
|
|
||||||
def get_data(self):
|
|
||||||
return self._data
|
|
@ -8,8 +8,6 @@ from toxencryptsave import ToxEncryptSave
|
|||||||
|
|
||||||
PAGE_SIZE = 42
|
PAGE_SIZE = 42
|
||||||
|
|
||||||
SAVE_MESSAGES = 150
|
|
||||||
|
|
||||||
MESSAGE_OWNER = {
|
MESSAGE_OWNER = {
|
||||||
'ME': 0,
|
'ME': 0,
|
||||||
'FRIEND': 1,
|
'FRIEND': 1,
|
||||||
|
Before Width: | Height: | Size: 4.0 KiB |
@ -6,13 +6,14 @@ import util
|
|||||||
class LibToxCore:
|
class LibToxCore:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if system() == 'Linux':
|
if system() == 'Windows':
|
||||||
# libtoxcore and libsodium must be installed in your os
|
|
||||||
self._libtoxcore = CDLL('libtoxcore.so')
|
|
||||||
elif system() == 'Windows':
|
|
||||||
self._libtoxcore = CDLL(util.curr_directory() + '/libs/libtox.dll')
|
self._libtoxcore = CDLL(util.curr_directory() + '/libs/libtox.dll')
|
||||||
else:
|
else:
|
||||||
raise OSError('Unknown system.')
|
# libtoxcore and libsodium must be installed in your os
|
||||||
|
try:
|
||||||
|
self._libtoxcore = CDLL('libtoxcore.so')
|
||||||
|
except:
|
||||||
|
self._libtoxcore = CDLL(util.curr_directory() + '/libs/libtoxcore.so')
|
||||||
|
|
||||||
def __getattr__(self, item):
|
def __getattr__(self, item):
|
||||||
return self._libtoxcore.__getattr__(item)
|
return self._libtoxcore.__getattr__(item)
|
||||||
@ -21,14 +22,15 @@ class LibToxCore:
|
|||||||
class LibToxAV:
|
class LibToxAV:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if system() == 'Linux':
|
if system() == 'Windows':
|
||||||
# that /usr/lib/libtoxav.so must exists
|
|
||||||
self._libtoxav = CDLL('libtoxav.so')
|
|
||||||
elif system() == 'Windows':
|
|
||||||
# on Windows av api is in libtox.dll
|
# on Windows av api is in libtox.dll
|
||||||
self._libtoxav = CDLL(util.curr_directory() + '/libs/libtox.dll')
|
self._libtoxav = CDLL(util.curr_directory() + '/libs/libtox.dll')
|
||||||
else:
|
else:
|
||||||
raise OSError('Unknown system.')
|
# /usr/lib/libtoxav.so must exists
|
||||||
|
try:
|
||||||
|
self._libtoxav = CDLL('libtoxav.so')
|
||||||
|
except:
|
||||||
|
self._libtoxav = CDLL(util.curr_directory() + '/libs/libtoxav.so')
|
||||||
|
|
||||||
def __getattr__(self, item):
|
def __getattr__(self, item):
|
||||||
return self._libtoxav.__getattr__(item)
|
return self._libtoxav.__getattr__(item)
|
||||||
@ -37,14 +39,15 @@ class LibToxAV:
|
|||||||
class LibToxEncryptSave:
|
class LibToxEncryptSave:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if system() == 'Linux':
|
if system() == 'Windows':
|
||||||
# /usr/lib/libtoxencryptsave.so must exists
|
|
||||||
self._lib_tox_encrypt_save = CDLL('libtoxencryptsave.so')
|
|
||||||
elif system() == 'Windows':
|
|
||||||
# on Windows profile encryption api is in libtox.dll
|
# on Windows profile encryption api is in libtox.dll
|
||||||
self._lib_tox_encrypt_save = CDLL(util.curr_directory() + '/libs/libtox.dll')
|
self._lib_tox_encrypt_save = CDLL(util.curr_directory() + '/libs/libtox.dll')
|
||||||
else:
|
else:
|
||||||
raise OSError('Unknown system.')
|
# /usr/lib/libtoxencryptsave.so must exists
|
||||||
|
try:
|
||||||
|
self._lib_tox_encrypt_save = CDLL('libtoxencryptsave.so')
|
||||||
|
except:
|
||||||
|
self._lib_tox_encrypt_save = CDLL(util.curr_directory() + '/libs/libtoxencryptsave.so')
|
||||||
|
|
||||||
def __getattr__(self, item):
|
def __getattr__(self, item):
|
||||||
return self._lib_tox_encrypt_save.__getattr__(item)
|
return self._lib_tox_encrypt_save.__getattr__(item)
|
||||||
|
@ -3,6 +3,7 @@ try:
|
|||||||
from PySide import QtCore, QtGui
|
from PySide import QtCore, QtGui
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
QtCore.Slot = QtCore.pyqtSlot
|
||||||
import profile
|
import profile
|
||||||
from file_transfers import TOX_FILE_TRANSFER_STATE, PAUSED_FILE_TRANSFERS, DO_NOT_SHOW_ACCEPT_BUTTON, ACTIVE_FILE_TRANSFERS, SHOW_PROGRESS_BAR
|
from file_transfers import TOX_FILE_TRANSFER_STATE, PAUSED_FILE_TRANSFERS, DO_NOT_SHOW_ACCEPT_BUTTON, ACTIVE_FILE_TRANSFERS, SHOW_PROGRESS_BAR
|
||||||
from util import curr_directory, convert_time, curr_time
|
from util import curr_directory, convert_time, curr_time
|
||||||
@ -32,7 +33,7 @@ class MessageEdit(QtGui.QTextBrowser):
|
|||||||
else:
|
else:
|
||||||
self.setHtml(text)
|
self.setHtml(text)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily("Times New Roman")
|
font.setFamily(settings.Settings.get_instance()['font'])
|
||||||
font.setPixelSize(settings.Settings.get_instance()['message_font_size'])
|
font.setPixelSize(settings.Settings.get_instance()['message_font_size'])
|
||||||
font.setBold(False)
|
font.setBold(False)
|
||||||
self.setFont(font)
|
self.setFont(font)
|
||||||
@ -42,10 +43,31 @@ class MessageEdit(QtGui.QTextBrowser):
|
|||||||
|
|
||||||
def contextMenuEvent(self, event):
|
def contextMenuEvent(self, event):
|
||||||
menu = create_menu(self.createStandardContextMenu(event.pos()))
|
menu = create_menu(self.createStandardContextMenu(event.pos()))
|
||||||
|
quote = menu.addAction(QtGui.QApplication.translate("MainWindow", 'Quote selected text', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
quote.triggered.connect(self.quote_text)
|
||||||
|
text = self.textCursor().selection().toPlainText()
|
||||||
|
if not text:
|
||||||
|
quote.setEnabled(False)
|
||||||
|
else:
|
||||||
|
import plugin_support
|
||||||
|
submenu = plugin_support.PluginLoader.get_instance().get_message_menu(menu, text)
|
||||||
|
if len(submenu):
|
||||||
|
plug = menu.addMenu(QtGui.QApplication.translate("MainWindow", 'Plugins', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
plug.addActions(submenu)
|
||||||
menu.popup(event.globalPos())
|
menu.popup(event.globalPos())
|
||||||
menu.exec_(event.globalPos())
|
menu.exec_(event.globalPos())
|
||||||
del menu
|
del menu
|
||||||
|
|
||||||
|
def quote_text(self):
|
||||||
|
text = self.textCursor().selection().toPlainText()
|
||||||
|
if text:
|
||||||
|
import mainscreen
|
||||||
|
window = mainscreen.MainWindow.get_instance()
|
||||||
|
text = '>' + '\n>'.join(text.split('\n'))
|
||||||
|
if window.messageEdit.toPlainText():
|
||||||
|
text = '\n' + text
|
||||||
|
window.messageEdit.appendPlainText(text)
|
||||||
|
|
||||||
def on_anchor_clicked(self, url):
|
def on_anchor_clicked(self, url):
|
||||||
text = str(url.toString())
|
text = str(url.toString())
|
||||||
if text.startswith('tox:'):
|
if text.startswith('tox:'):
|
||||||
@ -108,7 +130,7 @@ class MessageItem(QtGui.QWidget):
|
|||||||
self.name.setGeometry(QtCore.QRect(2, 2, 95, 20))
|
self.name.setGeometry(QtCore.QRect(2, 2, 95, 20))
|
||||||
self.name.setTextFormat(QtCore.Qt.PlainText)
|
self.name.setTextFormat(QtCore.Qt.PlainText)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily("Times New Roman")
|
font.setFamily(settings.Settings.get_instance()['font'])
|
||||||
font.setPointSize(11)
|
font.setPointSize(11)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.name.setFont(font)
|
self.name.setFont(font)
|
||||||
@ -116,8 +138,6 @@ class MessageItem(QtGui.QWidget):
|
|||||||
|
|
||||||
self.time = QtGui.QLabel(self)
|
self.time = QtGui.QLabel(self)
|
||||||
self.time.setGeometry(QtCore.QRect(parent.width() - 50, 0, 50, 20))
|
self.time.setGeometry(QtCore.QRect(parent.width() - 50, 0, 50, 20))
|
||||||
font = QtGui.QFont()
|
|
||||||
font.setFamily("Times New Roman")
|
|
||||||
font.setPointSize(10)
|
font.setPointSize(10)
|
||||||
font.setBold(False)
|
font.setBold(False)
|
||||||
self.time.setFont(font)
|
self.time.setFont(font)
|
||||||
@ -159,6 +179,14 @@ class MessageItem(QtGui.QWidget):
|
|||||||
return True
|
return True
|
||||||
return False
|
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, QtCore.Qt.SmoothTransformation))
|
||||||
|
|
||||||
|
|
||||||
class ContactItem(QtGui.QWidget):
|
class ContactItem(QtGui.QWidget):
|
||||||
"""
|
"""
|
||||||
@ -172,11 +200,12 @@ class ContactItem(QtGui.QWidget):
|
|||||||
self.avatar_label = QtGui.QLabel(self)
|
self.avatar_label = QtGui.QLabel(self)
|
||||||
size = 32 if mode else 64
|
size = 32 if mode else 64
|
||||||
self.avatar_label.setGeometry(QtCore.QRect(3, 4, size, size))
|
self.avatar_label.setGeometry(QtCore.QRect(3, 4, size, size))
|
||||||
self.avatar_label.setScaledContents(True)
|
self.avatar_label.setScaledContents(False)
|
||||||
|
self.avatar_label.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
self.name = DataLabel(self)
|
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))
|
self.name.setGeometry(QtCore.QRect(50 if mode else 75, 3 if mode else 10, 150, 15 if mode else 25))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily("Times New Roman")
|
font.setFamily(settings.Settings.get_instance()['font'])
|
||||||
font.setPointSize(10 if mode else 12)
|
font.setPointSize(10 if mode else 12)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.name.setFont(font)
|
self.name.setFont(font)
|
||||||
@ -233,7 +262,7 @@ class UnreadMessagesCount(QtGui.QWidget):
|
|||||||
self.label.setGeometry(QtCore.QRect(0, 0, 30, 20))
|
self.label.setGeometry(QtCore.QRect(0, 0, 30, 20))
|
||||||
self.label.setVisible(False)
|
self.label.setVisible(False)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily("Times New Roman")
|
font.setFamily(settings.Settings.get_instance()['font'])
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.label.setFont(font)
|
self.label.setFont(font)
|
||||||
@ -269,7 +298,7 @@ class FileTransferItem(QtGui.QListWidget):
|
|||||||
self.name.setGeometry(QtCore.QRect(3, 7, 95, 20))
|
self.name.setGeometry(QtCore.QRect(3, 7, 95, 20))
|
||||||
self.name.setTextFormat(QtCore.Qt.PlainText)
|
self.name.setTextFormat(QtCore.Qt.PlainText)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily("Times New Roman")
|
font.setFamily(settings.Settings.get_instance()['font'])
|
||||||
font.setPointSize(11)
|
font.setPointSize(11)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.name.setFont(font)
|
self.name.setFont(font)
|
||||||
@ -381,7 +410,7 @@ class FileTransferItem(QtGui.QListWidget):
|
|||||||
if time + 1:
|
if time + 1:
|
||||||
m, s = divmod(time, 60)
|
m, s = divmod(time, 60)
|
||||||
self.time_left.setText('{0:02d}:{1:02d}'.format(m, s))
|
self.time_left.setText('{0:02d}:{1:02d}'.format(m, s))
|
||||||
if self.state != state:
|
if self.state != state and self.state in ACTIVE_FILE_TRANSFERS:
|
||||||
if state == TOX_FILE_TRANSFER_STATE['CANCELLED']:
|
if state == TOX_FILE_TRANSFER_STATE['CANCELLED']:
|
||||||
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
||||||
self.cancel.setVisible(False)
|
self.cancel.setVisible(False)
|
||||||
|
@ -57,7 +57,7 @@ class LoginScreen(CenteredWidget):
|
|||||||
self.load_profile.raise_()
|
self.load_profile.raise_()
|
||||||
self.new_name.raise_()
|
self.new_name.raise_()
|
||||||
self.new_profile.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 = QtGui.QFont()
|
||||||
font.setFamily("Impact")
|
font.setFamily("Impact")
|
||||||
font.setPointSize(16)
|
font.setPointSize(16)
|
||||||
|
@ -8,9 +8,10 @@ except ImportError:
|
|||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from bootstrap import node_generator
|
from bootstrap import node_generator
|
||||||
from mainscreen import MainWindow
|
from mainscreen import MainWindow
|
||||||
from callbacks import init_callbacks
|
from callbacks import init_callbacks, stop, start
|
||||||
from util import curr_directory, program_version
|
from util import curr_directory, program_version
|
||||||
import styles.style
|
import styles.style
|
||||||
|
import platform
|
||||||
import toxencryptsave
|
import toxencryptsave
|
||||||
from passwordscreen import PasswordScreen, UnlockAppScreen, SetProfilePasswordScreen
|
from passwordscreen import PasswordScreen, UnlockAppScreen, SetProfilePasswordScreen
|
||||||
from plugin_support import PluginLoader
|
from plugin_support import PluginLoader
|
||||||
@ -52,6 +53,9 @@ class Toxygen:
|
|||||||
app.setWindowIcon(QtGui.QIcon(curr_directory() + '/images/icon.png'))
|
app.setWindowIcon(QtGui.QIcon(curr_directory() + '/images/icon.png'))
|
||||||
self.app = app
|
self.app = app
|
||||||
|
|
||||||
|
if platform.system() == 'Linux':
|
||||||
|
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads)
|
||||||
|
|
||||||
# application color scheme
|
# application color scheme
|
||||||
with open(curr_directory() + '/styles/style.qss') as fl:
|
with open(curr_directory() + '/styles/style.qss') as fl:
|
||||||
dark_style = fl.read()
|
dark_style = fl.read()
|
||||||
@ -121,7 +125,19 @@ class Toxygen:
|
|||||||
set_pass.show()
|
set_pass.show()
|
||||||
self.app.connect(self.app, QtCore.SIGNAL("lastWindowClosed()"), self.app, QtCore.SLOT("quit()"))
|
self.app.connect(self.app, QtCore.SIGNAL("lastWindowClosed()"), self.app, QtCore.SLOT("quit()"))
|
||||||
self.app.exec_()
|
self.app.exec_()
|
||||||
ProfileHelper(Settings.get_default_path(), name).save_profile(self.tox.get_savedata())
|
reply = QtGui.QMessageBox.question(None,
|
||||||
|
'Profile {}'.format(name),
|
||||||
|
QtGui.QApplication.translate("login",
|
||||||
|
'Do you want to save profile in default folder? If no, profile will be saved in program folder',
|
||||||
|
None,
|
||||||
|
QtGui.QApplication.UnicodeUTF8),
|
||||||
|
QtGui.QMessageBox.Yes,
|
||||||
|
QtGui.QMessageBox.No)
|
||||||
|
if reply == QtGui.QMessageBox.Yes:
|
||||||
|
path = Settings.get_default_path()
|
||||||
|
else:
|
||||||
|
path = curr_directory()
|
||||||
|
ProfileHelper(path, name).save_profile(self.tox.get_savedata())
|
||||||
path = Settings.get_default_path()
|
path = Settings.get_default_path()
|
||||||
settings = Settings(name)
|
settings = Settings(name)
|
||||||
if curr_lang in langs:
|
if curr_lang in langs:
|
||||||
@ -222,8 +238,16 @@ class Toxygen:
|
|||||||
self.p = UnlockAppScreen(toxencryptsave.ToxEncryptSave.get_instance(), correct_pass)
|
self.p = UnlockAppScreen(toxencryptsave.ToxEncryptSave.get_instance(), correct_pass)
|
||||||
self.p.show()
|
self.p.show()
|
||||||
|
|
||||||
|
def tray_activated(reason):
|
||||||
|
if reason == QtGui.QSystemTrayIcon.DoubleClick:
|
||||||
|
show_window()
|
||||||
|
|
||||||
|
def close_app():
|
||||||
|
settings.closing = True
|
||||||
|
self.ms.close()
|
||||||
|
|
||||||
m.connect(show, QtCore.SIGNAL("triggered()"), show_window)
|
m.connect(show, QtCore.SIGNAL("triggered()"), show_window)
|
||||||
m.connect(exit, QtCore.SIGNAL("triggered()"), lambda: app.exit())
|
m.connect(exit, QtCore.SIGNAL("triggered()"), close_app)
|
||||||
m.connect(m, QtCore.SIGNAL("aboutToShow()"), lambda: m.aboutToShow())
|
m.connect(m, QtCore.SIGNAL("aboutToShow()"), lambda: m.aboutToShow())
|
||||||
sub.connect(onl, QtCore.SIGNAL("triggered()"), lambda: m.newStatus(0))
|
sub.connect(onl, QtCore.SIGNAL("triggered()"), lambda: m.newStatus(0))
|
||||||
sub.connect(away, QtCore.SIGNAL("triggered()"), lambda: m.newStatus(1))
|
sub.connect(away, QtCore.SIGNAL("triggered()"), lambda: m.newStatus(1))
|
||||||
@ -231,12 +255,14 @@ class Toxygen:
|
|||||||
|
|
||||||
self.tray.setContextMenu(m)
|
self.tray.setContextMenu(m)
|
||||||
self.tray.show()
|
self.tray.show()
|
||||||
|
self.tray.activated.connect(tray_activated)
|
||||||
|
|
||||||
self.ms.show()
|
self.ms.show()
|
||||||
|
|
||||||
plugin_helper = PluginLoader(self.tox, settings) # plugin support
|
plugin_helper = PluginLoader(self.tox, settings) # plugin support
|
||||||
plugin_helper.load()
|
plugin_helper.load()
|
||||||
|
|
||||||
|
start()
|
||||||
# init thread
|
# init thread
|
||||||
self.init = self.InitThread(self.tox, self.ms, self.tray)
|
self.init = self.InitThread(self.tox, self.ms, self.tray)
|
||||||
self.init.start()
|
self.init.start()
|
||||||
@ -256,6 +282,7 @@ class Toxygen:
|
|||||||
self.mainloop.stop = True
|
self.mainloop.stop = True
|
||||||
self.avloop.stop = True
|
self.avloop.stop = True
|
||||||
plugin_helper.stop()
|
plugin_helper.stop()
|
||||||
|
stop()
|
||||||
self.mainloop.wait()
|
self.mainloop.wait()
|
||||||
self.init.wait()
|
self.init.wait()
|
||||||
self.avloop.wait()
|
self.avloop.wait()
|
||||||
@ -415,7 +442,7 @@ def main():
|
|||||||
else: # started with argument(s)
|
else: # started with argument(s)
|
||||||
arg = sys.argv[1]
|
arg = sys.argv[1]
|
||||||
if arg == '--version':
|
if arg == '--version':
|
||||||
print('Toxygen ' + program_version)
|
print('Toxygen v' + program_version)
|
||||||
return
|
return
|
||||||
elif arg == '--help':
|
elif arg == '--help':
|
||||||
print('Usage:\ntoxygen path_to_profile\ntoxygen tox_id\ntoxygen --version')
|
print('Usage:\ntoxygen path_to_profile\ntoxygen tox_id\ntoxygen --version')
|
||||||
|
@ -6,12 +6,14 @@ from list_items import *
|
|||||||
from widgets import MultilineEdit, LineEdit
|
from widgets import MultilineEdit, LineEdit
|
||||||
import plugin_support
|
import plugin_support
|
||||||
from mainscreen_widgets import *
|
from mainscreen_widgets import *
|
||||||
|
import settings
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QtGui.QMainWindow):
|
class MainWindow(QtGui.QMainWindow, Singleton):
|
||||||
|
|
||||||
def __init__(self, tox, reset, tray):
|
def __init__(self, tox, reset, tray):
|
||||||
super(MainWindow, self).__init__()
|
super().__init__()
|
||||||
|
Singleton.__init__(self)
|
||||||
self.reset = reset
|
self.reset = reset
|
||||||
self.tray = tray
|
self.tray = tray
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
@ -29,8 +31,6 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
self.menuProfile = QtGui.QMenu(self.menubar)
|
self.menuProfile = QtGui.QMenu(self.menubar)
|
||||||
self.menuProfile.setObjectName("menuProfile")
|
self.menuProfile.setObjectName("menuProfile")
|
||||||
self.menuGroupChats = QtGui.QMenu(self.menubar)
|
|
||||||
self.menuGroupChats.setObjectName("menuGroupChats")
|
|
||||||
self.menuSettings = QtGui.QMenu(self.menubar)
|
self.menuSettings = QtGui.QMenu(self.menubar)
|
||||||
self.menuSettings.setObjectName("menuSettings")
|
self.menuSettings.setObjectName("menuSettings")
|
||||||
self.menuPlugins = QtGui.QMenu(self.menubar)
|
self.menuPlugins = QtGui.QMenu(self.menubar)
|
||||||
@ -58,12 +58,6 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.pluginData = QtGui.QAction(MainWindow)
|
self.pluginData = QtGui.QAction(MainWindow)
|
||||||
self.importPlugin = QtGui.QAction(MainWindow)
|
self.importPlugin = QtGui.QAction(MainWindow)
|
||||||
self.lockApp = QtGui.QAction(MainWindow)
|
self.lockApp = QtGui.QAction(MainWindow)
|
||||||
self.createGC = QtGui.QAction(MainWindow)
|
|
||||||
self.joinGC = QtGui.QAction(MainWindow)
|
|
||||||
self.gcRequests = QtGui.QAction(MainWindow)
|
|
||||||
self.menuGroupChats.addAction(self.createGC)
|
|
||||||
self.menuGroupChats.addAction(self.joinGC)
|
|
||||||
self.menuGroupChats.addAction(self.gcRequests)
|
|
||||||
self.menuProfile.addAction(self.actionAdd_friend)
|
self.menuProfile.addAction(self.actionAdd_friend)
|
||||||
self.menuProfile.addAction(self.actionSettings)
|
self.menuProfile.addAction(self.actionSettings)
|
||||||
self.menuProfile.addAction(self.lockApp)
|
self.menuProfile.addAction(self.lockApp)
|
||||||
@ -76,7 +70,6 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.menuPlugins.addAction(self.importPlugin)
|
self.menuPlugins.addAction(self.importPlugin)
|
||||||
self.menuAbout.addAction(self.actionAbout_program)
|
self.menuAbout.addAction(self.actionAbout_program)
|
||||||
self.menubar.addAction(self.menuProfile.menuAction())
|
self.menubar.addAction(self.menuProfile.menuAction())
|
||||||
self.menubar.addAction(self.menuGroupChats.menuAction())
|
|
||||||
self.menubar.addAction(self.menuSettings.menuAction())
|
self.menubar.addAction(self.menuSettings.menuAction())
|
||||||
self.menubar.addAction(self.menuPlugins.menuAction())
|
self.menubar.addAction(self.menuPlugins.menuAction())
|
||||||
self.menubar.addAction(self.menuAbout.menuAction())
|
self.menubar.addAction(self.menuAbout.menuAction())
|
||||||
@ -90,12 +83,8 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.actionNotifications.triggered.connect(self.notification_settings)
|
self.actionNotifications.triggered.connect(self.notification_settings)
|
||||||
self.audioSettings.triggered.connect(self.audio_settings)
|
self.audioSettings.triggered.connect(self.audio_settings)
|
||||||
self.pluginData.triggered.connect(self.plugins_menu)
|
self.pluginData.triggered.connect(self.plugins_menu)
|
||||||
|
|
||||||
self.lockApp.triggered.connect(self.lock_app)
|
self.lockApp.triggered.connect(self.lock_app)
|
||||||
self.importPlugin.triggered.connect(self.import_plugin)
|
self.importPlugin.triggered.connect(self.import_plugin)
|
||||||
self.createGC.triggered.connect(self.create_groupchat)
|
|
||||||
self.joinGC.triggered.connect(self.join_groupchat)
|
|
||||||
|
|
||||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||||
|
|
||||||
def languageChange(self, *args, **kwargs):
|
def languageChange(self, *args, **kwargs):
|
||||||
@ -104,14 +93,11 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
def event(self, event):
|
def event(self, event):
|
||||||
if event.type() == QtCore.QEvent.WindowActivate:
|
if event.type() == QtCore.QEvent.WindowActivate:
|
||||||
self.tray.setIcon(QtGui.QIcon(curr_directory() + '/images/icon.png'))
|
self.tray.setIcon(QtGui.QIcon(curr_directory() + '/images/icon.png'))
|
||||||
|
self.messages.repaint()
|
||||||
return super(MainWindow, self).event(event)
|
return super(MainWindow, self).event(event)
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
self.joinGC.setText(QtGui.QApplication.translate("MainWindow", "Join group chat", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.lockApp.setText(QtGui.QApplication.translate("MainWindow", "Lock", None, QtGui.QApplication.UnicodeUTF8))
|
self.lockApp.setText(QtGui.QApplication.translate("MainWindow", "Lock", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.menuGroupChats.setTitle(QtGui.QApplication.translate("MainWindow", "Group chats", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.createGC.setText(QtGui.QApplication.translate("MainWindow", "Create group chat", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.gcRequests.setText(QtGui.QApplication.translate("MainWindow", "Groupchat requests", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.menuPlugins.setTitle(QtGui.QApplication.translate("MainWindow", "Plugins", None, QtGui.QApplication.UnicodeUTF8))
|
self.menuPlugins.setTitle(QtGui.QApplication.translate("MainWindow", "Plugins", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.pluginData.setText(QtGui.QApplication.translate("MainWindow", "List of plugins", None, QtGui.QApplication.UnicodeUTF8))
|
self.pluginData.setText(QtGui.QApplication.translate("MainWindow", "List of plugins", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.menuProfile.setTitle(QtGui.QApplication.translate("MainWindow", "Profile", None, QtGui.QApplication.UnicodeUTF8))
|
self.menuProfile.setTitle(QtGui.QApplication.translate("MainWindow", "Profile", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
@ -142,6 +128,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.messageEdit.setObjectName("messageEdit")
|
self.messageEdit.setObjectName("messageEdit")
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(10)
|
font.setPointSize(10)
|
||||||
|
font.setFamily(settings.Settings.get_instance()['font'])
|
||||||
self.messageEdit.setFont(font)
|
self.messageEdit.setFont(font)
|
||||||
|
|
||||||
self.sendMessageButton = QtGui.QPushButton(Form)
|
self.sendMessageButton = QtGui.QPushButton(Form)
|
||||||
@ -193,11 +180,12 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
Form.setBaseSize(QtCore.QSize(270, 100))
|
Form.setBaseSize(QtCore.QSize(270, 100))
|
||||||
self.avatar_label = Form.avatar_label = QtGui.QLabel(Form)
|
self.avatar_label = Form.avatar_label = QtGui.QLabel(Form)
|
||||||
self.avatar_label.setGeometry(QtCore.QRect(5, 30, 64, 64))
|
self.avatar_label.setGeometry(QtCore.QRect(5, 30, 64, 64))
|
||||||
self.avatar_label.setScaledContents(True)
|
self.avatar_label.setScaledContents(False)
|
||||||
|
self.avatar_label.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
self.name = Form.name = DataLabel(Form)
|
self.name = Form.name = DataLabel(Form)
|
||||||
Form.name.setGeometry(QtCore.QRect(75, 40, 150, 25))
|
Form.name.setGeometry(QtCore.QRect(75, 40, 150, 25))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily("Times New Roman")
|
font.setFamily(settings.Settings.get_instance()['font'])
|
||||||
font.setPointSize(14)
|
font.setPointSize(14)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
Form.name.setFont(font)
|
Form.name.setFont(font)
|
||||||
@ -220,12 +208,12 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
Form.resize(650, 100)
|
Form.resize(650, 100)
|
||||||
self.account_avatar = QtGui.QLabel(Form)
|
self.account_avatar = QtGui.QLabel(Form)
|
||||||
self.account_avatar.setGeometry(QtCore.QRect(10, 30, 64, 64))
|
self.account_avatar.setGeometry(QtCore.QRect(10, 30, 64, 64))
|
||||||
self.account_avatar.setScaledContents(True)
|
self.account_avatar.setScaledContents(False)
|
||||||
self.account_name = DataLabel(Form)
|
self.account_name = DataLabel(Form)
|
||||||
self.account_name.setGeometry(QtCore.QRect(100, 25, 400, 25))
|
self.account_name.setGeometry(QtCore.QRect(100, 25, 400, 25))
|
||||||
self.account_name.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse)
|
self.account_name.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily("Times New Roman")
|
font.setFamily(settings.Settings.get_instance()['font'])
|
||||||
font.setPointSize(14)
|
font.setPointSize(14)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.account_name.setFont(font)
|
self.account_name.setFont(font)
|
||||||
@ -237,11 +225,6 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
font.setBold(False)
|
font.setBold(False)
|
||||||
self.account_status.setFont(font)
|
self.account_status.setFont(font)
|
||||||
self.account_status.setObjectName("account_status")
|
self.account_status.setObjectName("account_status")
|
||||||
|
|
||||||
self.account_status.mouseReleaseEvent = self.show_chat_menu
|
|
||||||
self.account_name.mouseReleaseEvent = self.show_chat_menu
|
|
||||||
self.account_avatar.mouseReleaseEvent = self.show_chat_menu
|
|
||||||
|
|
||||||
self.callButton = QtGui.QPushButton(Form)
|
self.callButton = QtGui.QPushButton(Form)
|
||||||
self.callButton.setGeometry(QtCore.QRect(550, 30, 50, 50))
|
self.callButton.setGeometry(QtCore.QRect(550, 30, 50, 50))
|
||||||
self.callButton.setObjectName("callButton")
|
self.callButton.setObjectName("callButton")
|
||||||
@ -277,7 +260,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.messages.setSpacing(1)
|
self.messages.setSpacing(1)
|
||||||
self.messages.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
|
self.messages.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
|
||||||
self.messages.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
self.messages.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
self.messages.setFocusPolicy(QtCore.Qt.NoFocus)
|
# self.messages.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
|
||||||
def load(pos):
|
def load(pos):
|
||||||
if not pos:
|
if not pos:
|
||||||
@ -285,6 +268,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.messages.verticalScrollBar().setValue(1)
|
self.messages.verticalScrollBar().setValue(1)
|
||||||
self.messages.verticalScrollBar().valueChanged.connect(load)
|
self.messages.verticalScrollBar().valueChanged.connect(load)
|
||||||
self.messages.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
self.messages.setVerticalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel)
|
||||||
|
self.messages.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
|
||||||
|
|
||||||
def initUI(self, tox):
|
def initUI(self, tox):
|
||||||
self.setMinimumSize(920, 500)
|
self.setMinimumSize(920, 500)
|
||||||
@ -341,16 +325,21 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
self.profile = Profile(tox, self)
|
self.profile = Profile(tox, self)
|
||||||
|
|
||||||
def closeEvent(self, *args, **kwargs):
|
def closeEvent(self, event):
|
||||||
self.profile.save_history()
|
self.profile.save_history()
|
||||||
self.profile.close()
|
self.profile.close()
|
||||||
s = Settings.get_instance()
|
s = Settings.get_instance()
|
||||||
s['x'] = self.pos().x()
|
if not s['close_to_tray'] or s.closing:
|
||||||
s['y'] = self.pos().y()
|
s['x'] = self.geometry().x()
|
||||||
|
s['y'] = self.geometry().y()
|
||||||
s['width'] = self.width()
|
s['width'] = self.width()
|
||||||
s['height'] = self.height()
|
s['height'] = self.height()
|
||||||
s.save()
|
s.save()
|
||||||
QtGui.QApplication.closeAllWindows()
|
QtGui.QApplication.closeAllWindows()
|
||||||
|
event.accept()
|
||||||
|
else:
|
||||||
|
event.ignore()
|
||||||
|
self.hide()
|
||||||
|
|
||||||
def resizeEvent(self, *args, **kwargs):
|
def resizeEvent(self, *args, **kwargs):
|
||||||
self.messages.setGeometry(0, 0, self.width() - 270, self.height() - 155)
|
self.messages.setGeometry(0, 0, self.width() - 270, self.height() - 155)
|
||||||
@ -372,6 +361,14 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
if event.key() == QtCore.Qt.Key_Escape:
|
if event.key() == QtCore.Qt.Key_Escape:
|
||||||
self.hide()
|
self.hide()
|
||||||
|
elif event.key() == QtCore.Qt.Key_C and event.modifiers() & QtCore.Qt.ControlModifier and self.messages.selectedIndexes():
|
||||||
|
rows = list(map(lambda x: self.messages.row(x), self.messages.selectedItems()))
|
||||||
|
indexes = (rows[0] - self.messages.count(), rows[-1] - self.messages.count())
|
||||||
|
s = self.profile.export_history(self.profile.active_friend, True, indexes)
|
||||||
|
clipboard = QtGui.QApplication.clipboard()
|
||||||
|
clipboard.setText(s)
|
||||||
|
elif event.key() == QtCore.Qt.Key_Z and event.modifiers() & QtCore.Qt.ControlModifier and self.messages.selectedIndexes():
|
||||||
|
self.messages.clearSelection()
|
||||||
else:
|
else:
|
||||||
super(MainWindow, self).keyPressEvent(event)
|
super(MainWindow, self).keyPressEvent(event)
|
||||||
|
|
||||||
@ -384,7 +381,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
msgBox = QtGui.QMessageBox()
|
msgBox = QtGui.QMessageBox()
|
||||||
msgBox.setWindowTitle(QtGui.QApplication.translate("MainWindow", "About", None, QtGui.QApplication.UnicodeUTF8))
|
msgBox.setWindowTitle(QtGui.QApplication.translate("MainWindow", "About", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
text = (QtGui.QApplication.translate("MainWindow", 'Toxygen is Tox client written on Python.\nVersion: ', None, QtGui.QApplication.UnicodeUTF8))
|
text = (QtGui.QApplication.translate("MainWindow", 'Toxygen is Tox client written on Python.\nVersion: ', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
msgBox.setText(text + util.program_version + '\nGitHub: github.com/xveduk/toxygen/')
|
msgBox.setText(text + util.program_version + '\nGitHub: https://github.com/toxygen-project/toxygen/')
|
||||||
msgBox.exec_()
|
msgBox.exec_()
|
||||||
|
|
||||||
def network_settings(self):
|
def network_settings(self):
|
||||||
@ -396,7 +393,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.p_s.show()
|
self.p_s.show()
|
||||||
|
|
||||||
def add_contact(self, link=''):
|
def add_contact(self, link=''):
|
||||||
self.a_c = AddContact(link)
|
self.a_c = AddContact(link or '')
|
||||||
self.a_c.show()
|
self.a_c.show()
|
||||||
|
|
||||||
def profile_settings(self, *args):
|
def profile_settings(self, *args):
|
||||||
@ -461,19 +458,6 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
120))
|
120))
|
||||||
self.menu.show()
|
self.menu.show()
|
||||||
|
|
||||||
def create_groupchat(self):
|
|
||||||
self.gc = AddGroupchat()
|
|
||||||
self.gc.show()
|
|
||||||
|
|
||||||
def join_groupchat(self):
|
|
||||||
self.gc = JoinGroupchat()
|
|
||||||
self.gc.show()
|
|
||||||
|
|
||||||
def show_chat_menu(self):
|
|
||||||
pr = Profile.get_instance()
|
|
||||||
if not pr.is_active_a_friend():
|
|
||||||
pass # TODO: show list of users in chat
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Messages, calls and file transfers
|
# Messages, calls and file transfers
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
@ -484,8 +468,6 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
def send_file(self):
|
def send_file(self):
|
||||||
self.menu.hide()
|
self.menu.hide()
|
||||||
if not self.profile.is_active_a_friend():
|
|
||||||
return
|
|
||||||
if self.profile.active_friend + 1:
|
if self.profile.active_friend + 1:
|
||||||
choose = QtGui.QApplication.translate("MainWindow", 'Choose file', None, QtGui.QApplication.UnicodeUTF8)
|
choose = QtGui.QApplication.translate("MainWindow", 'Choose file', None, QtGui.QApplication.UnicodeUTF8)
|
||||||
name = QtGui.QFileDialog.getOpenFileName(self, choose, options=QtGui.QFileDialog.DontUseNativeDialog)
|
name = QtGui.QFileDialog.getOpenFileName(self, choose, options=QtGui.QFileDialog.DontUseNativeDialog)
|
||||||
@ -494,8 +476,6 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
def send_screenshot(self, hide=False):
|
def send_screenshot(self, hide=False):
|
||||||
self.menu.hide()
|
self.menu.hide()
|
||||||
if not self.profile.is_active_a_friend():
|
|
||||||
return
|
|
||||||
if self.profile.active_friend + 1:
|
if self.profile.active_friend + 1:
|
||||||
self.sw = ScreenShotWindow(self)
|
self.sw = ScreenShotWindow(self)
|
||||||
self.sw.show()
|
self.sw.show()
|
||||||
@ -514,8 +494,6 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
def send_sticker(self):
|
def send_sticker(self):
|
||||||
self.menu.hide()
|
self.menu.hide()
|
||||||
if not self.profile.is_active_a_friend():
|
|
||||||
return
|
|
||||||
if self.profile.active_friend + 1:
|
if self.profile.active_friend + 1:
|
||||||
self.sticker = StickerWindow(self)
|
self.sticker = StickerWindow(self)
|
||||||
self.sticker.setGeometry(QtCore.QRect(self.x() if Settings.get_instance()['mirror_mode'] else 270 + self.x(),
|
self.sticker.setGeometry(QtCore.QRect(self.x() if Settings.get_instance()['mirror_mode'] else 270 + self.x(),
|
||||||
@ -552,23 +530,19 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
def friend_right_click(self, pos):
|
def friend_right_click(self, pos):
|
||||||
item = self.friends_list.itemAt(pos)
|
item = self.friends_list.itemAt(pos)
|
||||||
num = self.friends_list.indexFromItem(item).row()
|
num = self.friends_list.indexFromItem(item).row()
|
||||||
friend = Profile.get_instance().get_friend_or_gc(num)
|
friend = Profile.get_instance().get_friend(num)
|
||||||
settings = Settings.get_instance()
|
settings = Settings.get_instance()
|
||||||
allowed = friend.tox_id in settings['auto_accept_from_friends']
|
allowed = friend.tox_id in settings['auto_accept_from_friends']
|
||||||
auto = QtGui.QApplication.translate("MainWindow", 'Disallow auto accept', None, QtGui.QApplication.UnicodeUTF8) if allowed else QtGui.QApplication.translate("MainWindow", 'Allow auto accept', None, QtGui.QApplication.UnicodeUTF8)
|
auto = QtGui.QApplication.translate("MainWindow", 'Disallow auto accept', None, QtGui.QApplication.UnicodeUTF8) if allowed else QtGui.QApplication.translate("MainWindow", 'Allow auto accept', None, QtGui.QApplication.UnicodeUTF8)
|
||||||
if item is not None:
|
if item is not None:
|
||||||
self.listMenu = QtGui.QMenu()
|
self.listMenu = QtGui.QMenu()
|
||||||
if type(friend) is Friend:
|
|
||||||
arr = Profile.get_instance().get_all_gc()
|
|
||||||
if arr:
|
|
||||||
gc_menu = self.listMenu.addMenu(QtGui.QApplication.translate("MainWindow", 'Invite to group chat', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
for gc in arr:
|
|
||||||
item = gc_menu.addAction(gc.name)
|
|
||||||
self.connect(item, QtCore.SIGNAL("triggered()"),
|
|
||||||
lambda: Profile.get_instance().invite_friend(gc.number, friend.number))
|
|
||||||
|
|
||||||
set_alias_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Set alias', None, QtGui.QApplication.UnicodeUTF8))
|
set_alias_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Set alias', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
clear_history_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Clear history', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
|
history_menu = self.listMenu.addMenu(QtGui.QApplication.translate("MainWindow", 'Chat history', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
clear_history_item = history_menu.addAction(QtGui.QApplication.translate("MainWindow", 'Clear history', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
export_to_text_item = history_menu.addAction(QtGui.QApplication.translate("MainWindow", 'Export as text', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
export_to_html_item = history_menu.addAction(QtGui.QApplication.translate("MainWindow", 'Export as HTML', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
copy_menu = self.listMenu.addMenu(QtGui.QApplication.translate("MainWindow", 'Copy', None, QtGui.QApplication.UnicodeUTF8))
|
copy_menu = self.listMenu.addMenu(QtGui.QApplication.translate("MainWindow", 'Copy', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
copy_name_item = copy_menu.addAction(QtGui.QApplication.translate("MainWindow", 'Name', None, QtGui.QApplication.UnicodeUTF8))
|
copy_name_item = copy_menu.addAction(QtGui.QApplication.translate("MainWindow", 'Name', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
copy_status_item = copy_menu.addAction(QtGui.QApplication.translate("MainWindow", 'Status message', None, QtGui.QApplication.UnicodeUTF8))
|
copy_status_item = copy_menu.addAction(QtGui.QApplication.translate("MainWindow", 'Status message', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
@ -582,30 +556,17 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
if len(submenu):
|
if len(submenu):
|
||||||
plug = self.listMenu.addMenu(QtGui.QApplication.translate("MainWindow", 'Plugins', None, QtGui.QApplication.UnicodeUTF8))
|
plug = self.listMenu.addMenu(QtGui.QApplication.translate("MainWindow", 'Plugins', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
plug.addActions(submenu)
|
plug.addActions(submenu)
|
||||||
self.connect(remove_item, QtCore.SIGNAL("triggered()"), lambda: self.remove_friend(num))
|
|
||||||
self.connect(auto_accept_item, QtCore.SIGNAL("triggered()"), lambda: self.auto_accept(num, not allowed))
|
|
||||||
else:
|
|
||||||
copy_menu = self.listMenu.addMenu(
|
|
||||||
QtGui.QApplication.translate("MainWindow", 'Copy', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
copy_name_item = copy_menu.addAction(
|
|
||||||
QtGui.QApplication.translate("MainWindow", 'Name', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
copy_status_item = copy_menu.addAction(
|
|
||||||
QtGui.QApplication.translate("MainWindow", 'Topic', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
copy_key_item = copy_menu.addAction(
|
|
||||||
QtGui.QApplication.translate("MainWindow", 'Public key', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
leave_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Leave group', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
set_alias_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Set alias', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
clear_history_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Clear history', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
notes_item = self.listMenu.addAction(QtGui.QApplication.translate("MainWindow", 'Notes', None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.connect(leave_item, QtCore.SIGNAL("triggered()"), lambda: Profile.get_instance().leave_group(num))
|
|
||||||
|
|
||||||
self.connect(notes_item, QtCore.SIGNAL("triggered()"), lambda: self.show_note(friend))
|
|
||||||
self.connect(set_alias_item, QtCore.SIGNAL("triggered()"), lambda: self.set_alias(num))
|
self.connect(set_alias_item, QtCore.SIGNAL("triggered()"), lambda: self.set_alias(num))
|
||||||
|
self.connect(remove_item, QtCore.SIGNAL("triggered()"), lambda: self.remove_friend(num))
|
||||||
|
self.connect(copy_key_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_friend_key(num))
|
||||||
self.connect(clear_history_item, QtCore.SIGNAL("triggered()"), lambda: self.clear_history(num))
|
self.connect(clear_history_item, QtCore.SIGNAL("triggered()"), lambda: self.clear_history(num))
|
||||||
|
self.connect(auto_accept_item, QtCore.SIGNAL("triggered()"), lambda: self.auto_accept(num, not allowed))
|
||||||
|
self.connect(notes_item, QtCore.SIGNAL("triggered()"), lambda: self.show_note(friend))
|
||||||
self.connect(copy_name_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_name(friend))
|
self.connect(copy_name_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_name(friend))
|
||||||
self.connect(copy_status_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_status(friend))
|
self.connect(copy_status_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_status(friend))
|
||||||
self.connect(copy_key_item, QtCore.SIGNAL("triggered()"), lambda: self.copy_friend_key(num))
|
self.connect(export_to_text_item, QtCore.SIGNAL("triggered()"), lambda: self.export_history(num))
|
||||||
|
self.connect(export_to_html_item, QtCore.SIGNAL("triggered()"),
|
||||||
|
lambda: self.export_history(num, False))
|
||||||
parent_position = self.friends_list.mapToGlobal(QtCore.QPoint(0, 0))
|
parent_position = self.friends_list.mapToGlobal(QtCore.QPoint(0, 0))
|
||||||
self.listMenu.move(parent_position + pos)
|
self.listMenu.move(parent_position + pos)
|
||||||
self.listMenu.show()
|
self.listMenu.show()
|
||||||
@ -625,11 +586,25 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.note = MultilineEdit(user, note, save_note)
|
self.note = MultilineEdit(user, note, save_note)
|
||||||
self.note.show()
|
self.note.show()
|
||||||
|
|
||||||
|
def export_history(self, num, as_text=True):
|
||||||
|
s = self.profile.export_history(num, as_text)
|
||||||
|
directory = QtGui.QFileDialog.getExistingDirectory(None,
|
||||||
|
QtGui.QApplication.translate("MainWindow", 'Choose folder',
|
||||||
|
None,
|
||||||
|
QtGui.QApplication.UnicodeUTF8),
|
||||||
|
curr_directory(),
|
||||||
|
QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontUseNativeDialog)
|
||||||
|
|
||||||
|
if directory:
|
||||||
|
name = 'exported_history_{}.{}'.format(convert_time(time.time()), 'txt' if as_text else 'html')
|
||||||
|
with open(directory + '/' + name, 'wt') as fl:
|
||||||
|
fl.write(s)
|
||||||
|
|
||||||
def set_alias(self, num):
|
def set_alias(self, num):
|
||||||
self.profile.set_alias(num)
|
self.profile.set_alias(num)
|
||||||
|
|
||||||
def remove_friend(self, num):
|
def remove_friend(self, num):
|
||||||
self.profile.delete_friend_or_gc(num)
|
self.profile.delete_friend(num)
|
||||||
|
|
||||||
def copy_friend_key(self, num):
|
def copy_friend_key(self, num):
|
||||||
tox_id = self.profile.friend_public_key(num)
|
tox_id = self.profile.friend_public_key(num)
|
||||||
@ -674,4 +649,3 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
def filtering(self):
|
def filtering(self):
|
||||||
self.profile.filtration(self.online_contacts.currentIndex() == 1, self.contact_name.text())
|
self.profile.filtration(self.online_contacts.currentIndex() == 1, self.contact_name.text())
|
||||||
|
|
||||||
|
@ -20,6 +20,11 @@ class MessageArea(QtGui.QPlainTextEdit):
|
|||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
if event.matches(QtGui.QKeySequence.Paste):
|
if event.matches(QtGui.QKeySequence.Paste):
|
||||||
|
mimeData = QtGui.QApplication.clipboard().mimeData()
|
||||||
|
if mimeData.hasUrls():
|
||||||
|
for url in mimeData.urls():
|
||||||
|
self.pasteEvent(url.toString())
|
||||||
|
else:
|
||||||
self.pasteEvent()
|
self.pasteEvent()
|
||||||
elif event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
|
elif event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
|
||||||
modifiers = event.modifiers()
|
modifiers = event.modifiers()
|
||||||
@ -51,9 +56,13 @@ class MessageArea(QtGui.QPlainTextEdit):
|
|||||||
e.accept()
|
e.accept()
|
||||||
|
|
||||||
def dropEvent(self, e):
|
def dropEvent(self, e):
|
||||||
if e.mimeData().hasFormat('text/plain'):
|
if e.mimeData().hasFormat('text/plain') or e.mimeData().hasFormat('text/html'):
|
||||||
e.accept()
|
e.accept()
|
||||||
self.pasteEvent(e.mimeData().text())
|
self.pasteEvent(e.mimeData().text())
|
||||||
|
elif e.mimeData().hasUrls():
|
||||||
|
for url in e.mimeData().urls():
|
||||||
|
self.pasteEvent(url.toString())
|
||||||
|
e.accept()
|
||||||
else:
|
else:
|
||||||
e.ignore()
|
e.ignore()
|
||||||
|
|
||||||
@ -330,7 +339,7 @@ class WelcomeScreen(CenteredWidget):
|
|||||||
self.setWindowTitle(QtGui.QApplication.translate('WelcomeScreen', 'Tip of the day',
|
self.setWindowTitle(QtGui.QApplication.translate('WelcomeScreen', 'Tip of the day',
|
||||||
None, QtGui.QApplication.UnicodeUTF8))
|
None, QtGui.QApplication.UnicodeUTF8))
|
||||||
import random
|
import random
|
||||||
num = random.randint(0, 8)
|
num = random.randint(0, 10)
|
||||||
if num == 0:
|
if num == 0:
|
||||||
text = QtGui.QApplication.translate('WelcomeScreen', 'Press Esc if you want hide app to tray.',
|
text = QtGui.QApplication.translate('WelcomeScreen', 'Press Esc if you want hide app to tray.',
|
||||||
None, QtGui.QApplication.UnicodeUTF8)
|
None, QtGui.QApplication.UnicodeUTF8)
|
||||||
@ -356,12 +365,20 @@ class WelcomeScreen(CenteredWidget):
|
|||||||
None, QtGui.QApplication.UnicodeUTF8)
|
None, QtGui.QApplication.UnicodeUTF8)
|
||||||
elif num == 6:
|
elif num == 6:
|
||||||
text = QtGui.QApplication.translate('WelcomeScreen',
|
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)
|
None, QtGui.QApplication.UnicodeUTF8)
|
||||||
elif num == 7:
|
elif num == 7:
|
||||||
text = QtGui.QApplication.translate('WelcomeScreen',
|
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.',
|
'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)
|
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:
|
else:
|
||||||
text = QtGui.QApplication.translate('WelcomeScreen',
|
text = QtGui.QApplication.translate('WelcomeScreen',
|
||||||
'Set new NoSpam to avoid spam friend requests: Profile -> Settings -> Set new NoSpam.',
|
'Set new NoSpam to avoid spam friend requests: Profile -> Settings -> Set new NoSpam.',
|
||||||
@ -375,4 +392,3 @@ class WelcomeScreen(CenteredWidget):
|
|||||||
s = settings.Settings.get_instance()
|
s = settings.Settings.get_instance()
|
||||||
s['show_welcome_screen'] = False
|
s['show_welcome_screen'] = False
|
||||||
s.save()
|
s.save()
|
||||||
|
|
||||||
|
178
toxygen/menu.py
@ -11,97 +11,6 @@ import toxencryptsave
|
|||||||
import plugin_support
|
import plugin_support
|
||||||
|
|
||||||
|
|
||||||
class AddGroupchat(CenteredWidget):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
self.initUI()
|
|
||||||
self.retranslateUi()
|
|
||||||
self.center()
|
|
||||||
|
|
||||||
def initUI(self):
|
|
||||||
self.setObjectName('AddGC')
|
|
||||||
self.resize(570, 240)
|
|
||||||
self.setMaximumSize(QtCore.QSize(570, 240))
|
|
||||||
self.setMinimumSize(QtCore.QSize(570, 240))
|
|
||||||
self.label = QtGui.QLabel(self)
|
|
||||||
self.label.setGeometry(QtCore.QRect(50, 20, 470, 20))
|
|
||||||
self.createGCButton = QtGui.QPushButton(self)
|
|
||||||
self.createGCButton.setGeometry(QtCore.QRect(50, 190, 470, 30))
|
|
||||||
self.name = LineEdit(self)
|
|
||||||
self.name.setGeometry(QtCore.QRect(50, 40, 470, 27))
|
|
||||||
self.privacy_type = QtGui.QLabel(self)
|
|
||||||
self.privacy_type.setGeometry(QtCore.QRect(50, 70, 470, 20))
|
|
||||||
self.privacy_combobox = QtGui.QComboBox(self)
|
|
||||||
self.privacy_combobox.setGeometry(QtCore.QRect(50, 90, 470, 30))
|
|
||||||
self.pass_label = QtGui.QLabel(self)
|
|
||||||
self.pass_label.setGeometry(QtCore.QRect(50, 130, 470, 20))
|
|
||||||
self.password = LineEdit(self)
|
|
||||||
self.password.setGeometry(QtCore.QRect(50, 150, 470, 27))
|
|
||||||
self.password.setEchoMode(QtGui.QLineEdit.EchoMode.Password)
|
|
||||||
|
|
||||||
self.createGCButton.clicked.connect(self.button_click)
|
|
||||||
QtCore.QMetaObject.connectSlotsByName(self)
|
|
||||||
|
|
||||||
def retranslateUi(self):
|
|
||||||
self.setWindowTitle(QtGui.QApplication.translate('AddGC', "Create group chat", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.createGCButton.setText(QtGui.QApplication.translate("AddGC", "Create", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.label.setText(QtGui.QApplication.translate('AddGC', "Name:", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.privacy_type.setText(QtGui.QApplication.translate('AddGC', "Privacy type:", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.privacy_combobox.addItem(QtGui.QApplication.translate('AddGC', "Public", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.privacy_combobox.addItem(QtGui.QApplication.translate('AddGC', "Private", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.name.setPlaceholderText(QtGui.QApplication.translate('AddGC', "Not empty group name", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.password.setPlaceholderText(QtGui.QApplication.translate('AddGC', "Optional password", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.pass_label.setText(QtGui.QApplication.translate('AddGC', "Password:", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
|
|
||||||
def button_click(self):
|
|
||||||
if self.name.text():
|
|
||||||
Profile.get_instance().create_gc(self.name.text(),
|
|
||||||
self.privacy_combobox.currentIndex() == 0,
|
|
||||||
self.password.text())
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
|
|
||||||
class JoinGroupchat(CenteredWidget):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
self.initUI()
|
|
||||||
self.retranslateUi()
|
|
||||||
self.center()
|
|
||||||
|
|
||||||
def initUI(self):
|
|
||||||
self.setObjectName('AddGC')
|
|
||||||
self.resize(570, 150)
|
|
||||||
self.setMaximumSize(QtCore.QSize(570, 150))
|
|
||||||
self.setMinimumSize(QtCore.QSize(570, 150))
|
|
||||||
self.joinGCButton = QtGui.QPushButton(self)
|
|
||||||
self.joinGCButton.setGeometry(QtCore.QRect(50, 110, 470, 30))
|
|
||||||
self.id = LineEdit(self)
|
|
||||||
self.id.setGeometry(QtCore.QRect(50, 10, 470, 30))
|
|
||||||
self.password = LineEdit(self)
|
|
||||||
self.password.setGeometry(QtCore.QRect(50, 50, 470, 30))
|
|
||||||
self.password.setEchoMode(QtGui.QLineEdit.EchoMode.Password)
|
|
||||||
|
|
||||||
self.joinGCButton.clicked.connect(self.button_click)
|
|
||||||
QtCore.QMetaObject.connectSlotsByName(self)
|
|
||||||
|
|
||||||
def retranslateUi(self):
|
|
||||||
self.setWindowTitle(
|
|
||||||
QtGui.QApplication.translate('JoinGC', "Join group chat", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.joinGCButton.setText(
|
|
||||||
QtGui.QApplication.translate("JoinGC", "Join", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.id.setPlaceholderText(
|
|
||||||
QtGui.QApplication.translate('JoinGC', "Group ID", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.password.setPlaceholderText(
|
|
||||||
QtGui.QApplication.translate('JoinGC', "Optional password", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
|
|
||||||
def button_click(self):
|
|
||||||
if self.id.text():
|
|
||||||
Profile.get_instance().join_gc(self.id.text().strip(), self.password.text())
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
|
|
||||||
class AddContact(CenteredWidget):
|
class AddContact(CenteredWidget):
|
||||||
"""Add contact form"""
|
"""Add contact form"""
|
||||||
|
|
||||||
@ -128,6 +37,7 @@ class AddContact(CenteredWidget):
|
|||||||
self.error_label = DataLabel(self)
|
self.error_label = DataLabel(self)
|
||||||
self.error_label.setGeometry(QtCore.QRect(120, 10, 420, 20))
|
self.error_label.setGeometry(QtCore.QRect(120, 10, 420, 20))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(Settings.get_instance()['font'])
|
||||||
font.setPointSize(10)
|
font.setPointSize(10)
|
||||||
font.setWeight(30)
|
font.setWeight(30)
|
||||||
self.error_label.setFont(font)
|
self.error_label.setFont(font)
|
||||||
@ -142,7 +52,6 @@ class AddContact(CenteredWidget):
|
|||||||
self.message.setObjectName("label_2")
|
self.message.setObjectName("label_2")
|
||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
self.message_edit.setText('Hello! Add me to your contact list please')
|
self.message_edit.setText('Hello! Add me to your contact list please')
|
||||||
font = QtGui.QFont()
|
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.label.setFont(font)
|
self.label.setFont(font)
|
||||||
@ -193,6 +102,7 @@ class ProfileSettings(CenteredWidget):
|
|||||||
self.label = QtGui.QLabel(self)
|
self.label = QtGui.QLabel(self)
|
||||||
self.label.setGeometry(QtCore.QRect(40, 30, 91, 25))
|
self.label.setGeometry(QtCore.QRect(40, 30, 91, 25))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(Settings.get_instance()['font'])
|
||||||
font.setPointSize(18)
|
font.setPointSize(18)
|
||||||
font.setWeight(75)
|
font.setWeight(75)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
@ -354,16 +264,28 @@ class ProfileSettings(CenteredWidget):
|
|||||||
buffer = QtCore.QBuffer(byte_array)
|
buffer = QtCore.QBuffer(byte_array)
|
||||||
buffer.open(QtCore.QIODevice.WriteOnly)
|
buffer.open(QtCore.QIODevice.WriteOnly)
|
||||||
bitmap.save(buffer, 'PNG')
|
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):
|
def export_profile(self):
|
||||||
directory = QtGui.QFileDialog.getExistingDirectory(options=QtGui.QFileDialog.DontUseNativeDialog) + '/'
|
directory = QtGui.QFileDialog.getExistingDirectory(options=QtGui.QFileDialog.DontUseNativeDialog,
|
||||||
|
dir=curr_directory()) + '/'
|
||||||
if directory != '/':
|
if directory != '/':
|
||||||
ProfileHelper.get_instance().export_profile(directory)
|
reply = QtGui.QMessageBox.question(None,
|
||||||
|
QtGui.QApplication.translate("ProfileSettingsForm",
|
||||||
|
'Use new path',
|
||||||
|
None,
|
||||||
|
QtGui.QApplication.UnicodeUTF8),
|
||||||
|
QtGui.QApplication.translate("ProfileSettingsForm",
|
||||||
|
'Do you want to move your profile to this location?',
|
||||||
|
None,
|
||||||
|
QtGui.QApplication.UnicodeUTF8),
|
||||||
|
QtGui.QMessageBox.Yes,
|
||||||
|
QtGui.QMessageBox.No)
|
||||||
settings = Settings.get_instance()
|
settings = Settings.get_instance()
|
||||||
settings.export(directory)
|
settings.export(directory)
|
||||||
profile = Profile.get_instance()
|
profile = Profile.get_instance()
|
||||||
profile.export_history(directory)
|
profile.export_db(directory)
|
||||||
|
ProfileHelper.get_instance().export_profile(directory, reply == QtGui.QMessageBox.Yes)
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
profile = Profile.get_instance()
|
profile = Profile.get_instance()
|
||||||
@ -601,33 +523,29 @@ class NotificationsSettings(CenteredWidget):
|
|||||||
|
|
||||||
def initUI(self):
|
def initUI(self):
|
||||||
self.setObjectName("notificationsForm")
|
self.setObjectName("notificationsForm")
|
||||||
self.resize(350, 200)
|
self.resize(350, 180)
|
||||||
self.setMinimumSize(QtCore.QSize(350, 200))
|
self.setMinimumSize(QtCore.QSize(350, 180))
|
||||||
self.setMaximumSize(QtCore.QSize(350, 200))
|
self.setMaximumSize(QtCore.QSize(350, 180))
|
||||||
self.enableNotifications = QtGui.QCheckBox(self)
|
self.enableNotifications = QtGui.QCheckBox(self)
|
||||||
self.enableNotifications.setGeometry(QtCore.QRect(10, 20, 340, 18))
|
self.enableNotifications.setGeometry(QtCore.QRect(10, 20, 340, 18))
|
||||||
self.callsSound = QtGui.QCheckBox(self)
|
self.callsSound = QtGui.QCheckBox(self)
|
||||||
self.callsSound.setGeometry(QtCore.QRect(10, 120, 340, 18))
|
self.callsSound.setGeometry(QtCore.QRect(10, 120, 340, 18))
|
||||||
self.soundNotifications = QtGui.QCheckBox(self)
|
self.soundNotifications = QtGui.QCheckBox(self)
|
||||||
self.soundNotifications.setGeometry(QtCore.QRect(10, 70, 340, 18))
|
self.soundNotifications.setGeometry(QtCore.QRect(10, 70, 340, 18))
|
||||||
self.gcNotifications = QtGui.QCheckBox(self)
|
|
||||||
self.gcNotifications.setGeometry(QtCore.QRect(10, 170, 340, 18))
|
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
s = Settings.get_instance()
|
||||||
|
font.setFamily(s['font'])
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
self.callsSound.setFont(font)
|
self.callsSound.setFont(font)
|
||||||
self.soundNotifications.setFont(font)
|
self.soundNotifications.setFont(font)
|
||||||
self.enableNotifications.setFont(font)
|
self.enableNotifications.setFont(font)
|
||||||
self.gcNotifications.setFont(font)
|
|
||||||
s = Settings.get_instance()
|
|
||||||
self.enableNotifications.setChecked(s['notifications'])
|
self.enableNotifications.setChecked(s['notifications'])
|
||||||
self.soundNotifications.setChecked(s['sound_notifications'])
|
self.soundNotifications.setChecked(s['sound_notifications'])
|
||||||
self.callsSound.setChecked(s['calls_sound'])
|
self.callsSound.setChecked(s['calls_sound'])
|
||||||
self.gcNotifications.setChecked(s['notify_all_gc'])
|
|
||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
QtCore.QMetaObject.connectSlotsByName(self)
|
QtCore.QMetaObject.connectSlotsByName(self)
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
self.gcNotifications.setText(QtGui.QApplication.translate("notificationsForm", "Enable group chat notifications", None, QtGui.QApplication.UnicodeUTF8))
|
|
||||||
self.setWindowTitle(QtGui.QApplication.translate("notificationsForm", "Notification settings", None, QtGui.QApplication.UnicodeUTF8))
|
self.setWindowTitle(QtGui.QApplication.translate("notificationsForm", "Notification settings", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.enableNotifications.setText(QtGui.QApplication.translate("notificationsForm", "Enable notifications", None, QtGui.QApplication.UnicodeUTF8))
|
self.enableNotifications.setText(QtGui.QApplication.translate("notificationsForm", "Enable notifications", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.callsSound.setText(QtGui.QApplication.translate("notificationsForm", "Enable call\'s sound", None, QtGui.QApplication.UnicodeUTF8))
|
self.callsSound.setText(QtGui.QApplication.translate("notificationsForm", "Enable call\'s sound", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
@ -638,7 +556,6 @@ class NotificationsSettings(CenteredWidget):
|
|||||||
settings['notifications'] = self.enableNotifications.isChecked()
|
settings['notifications'] = self.enableNotifications.isChecked()
|
||||||
settings['sound_notifications'] = self.soundNotifications.isChecked()
|
settings['sound_notifications'] = self.soundNotifications.isChecked()
|
||||||
settings['calls_sound'] = self.callsSound.isChecked()
|
settings['calls_sound'] = self.callsSound.isChecked()
|
||||||
settings['notify_all_gc'] = self.gcNotifications.isChecked()
|
|
||||||
settings.save()
|
settings.save()
|
||||||
|
|
||||||
|
|
||||||
@ -651,19 +568,20 @@ class InterfaceSettings(CenteredWidget):
|
|||||||
|
|
||||||
def initUI(self):
|
def initUI(self):
|
||||||
self.setObjectName("interfaceForm")
|
self.setObjectName("interfaceForm")
|
||||||
self.setMinimumSize(QtCore.QSize(400, 550))
|
self.setMinimumSize(QtCore.QSize(400, 650))
|
||||||
self.setMaximumSize(QtCore.QSize(400, 550))
|
self.setMaximumSize(QtCore.QSize(400, 650))
|
||||||
self.label = QtGui.QLabel(self)
|
self.label = QtGui.QLabel(self)
|
||||||
self.label.setGeometry(QtCore.QRect(30, 10, 370, 20))
|
self.label.setGeometry(QtCore.QRect(30, 10, 370, 20))
|
||||||
|
settings = Settings.get_instance()
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(14)
|
font.setPointSize(14)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
|
font.setFamily(settings['font'])
|
||||||
self.label.setFont(font)
|
self.label.setFont(font)
|
||||||
self.themeSelect = QtGui.QComboBox(self)
|
self.themeSelect = QtGui.QComboBox(self)
|
||||||
self.themeSelect.setGeometry(QtCore.QRect(30, 40, 120, 30))
|
self.themeSelect.setGeometry(QtCore.QRect(30, 40, 120, 30))
|
||||||
list_of_themes = ['dark']
|
list_of_themes = ['dark']
|
||||||
self.themeSelect.addItems(list_of_themes)
|
self.themeSelect.addItems(list_of_themes)
|
||||||
settings = Settings.get_instance()
|
|
||||||
theme = settings['theme']
|
theme = settings['theme']
|
||||||
if theme in list_of_themes:
|
if theme in list_of_themes:
|
||||||
index = list_of_themes.index(theme)
|
index = list_of_themes.index(theme)
|
||||||
@ -707,25 +625,38 @@ class InterfaceSettings(CenteredWidget):
|
|||||||
self.messages_font_size.setCurrentIndex(settings['message_font_size'] - 10)
|
self.messages_font_size.setCurrentIndex(settings['message_font_size'] - 10)
|
||||||
|
|
||||||
self.unread = QtGui.QPushButton(self)
|
self.unread = QtGui.QPushButton(self)
|
||||||
self.unread.setGeometry(QtCore.QRect(30, 425, 340, 30))
|
self.unread.setGeometry(QtCore.QRect(30, 470, 340, 30))
|
||||||
self.unread.clicked.connect(self.select_color)
|
self.unread.clicked.connect(self.select_color)
|
||||||
|
|
||||||
self.compact_mode = QtGui.QCheckBox(self)
|
self.compact_mode = QtGui.QCheckBox(self)
|
||||||
self.compact_mode.setGeometry(QtCore.QRect(30, 380, 370, 20))
|
self.compact_mode.setGeometry(QtCore.QRect(30, 380, 370, 20))
|
||||||
self.compact_mode.setChecked(settings['compact_mode'])
|
self.compact_mode.setChecked(settings['compact_mode'])
|
||||||
|
|
||||||
|
self.close_to_tray = QtGui.QCheckBox(self)
|
||||||
|
self.close_to_tray.setGeometry(QtCore.QRect(30, 410, 370, 20))
|
||||||
|
self.close_to_tray.setChecked(settings['close_to_tray'])
|
||||||
|
|
||||||
|
self.show_avatars = QtGui.QCheckBox(self)
|
||||||
|
self.show_avatars.setGeometry(QtCore.QRect(30, 440, 370, 20))
|
||||||
|
self.show_avatars.setChecked(settings['show_avatars'])
|
||||||
|
|
||||||
|
self.choose_font = QtGui.QPushButton(self)
|
||||||
|
self.choose_font.setGeometry(QtCore.QRect(30, 510, 340, 30))
|
||||||
|
self.choose_font.clicked.connect(self.new_font)
|
||||||
|
|
||||||
self.import_smileys = QtGui.QPushButton(self)
|
self.import_smileys = QtGui.QPushButton(self)
|
||||||
self.import_smileys.setGeometry(QtCore.QRect(30, 465, 340, 30))
|
self.import_smileys.setGeometry(QtCore.QRect(30, 550, 340, 30))
|
||||||
self.import_smileys.clicked.connect(self.import_sm)
|
self.import_smileys.clicked.connect(self.import_sm)
|
||||||
|
|
||||||
self.import_stickers = QtGui.QPushButton(self)
|
self.import_stickers = QtGui.QPushButton(self)
|
||||||
self.import_stickers.setGeometry(QtCore.QRect(30, 505, 340, 30))
|
self.import_stickers.setGeometry(QtCore.QRect(30, 590, 340, 30))
|
||||||
self.import_stickers.clicked.connect(self.import_st)
|
self.import_stickers.clicked.connect(self.import_st)
|
||||||
|
|
||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
QtCore.QMetaObject.connectSlotsByName(self)
|
QtCore.QMetaObject.connectSlotsByName(self)
|
||||||
|
|
||||||
def retranslateUi(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.setWindowTitle(QtGui.QApplication.translate("interfaceForm", "Interface settings", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label.setText(QtGui.QApplication.translate("interfaceForm", "Theme:", 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))
|
self.lang.setText(QtGui.QApplication.translate("interfaceForm", "Language:", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
@ -737,6 +668,8 @@ class InterfaceSettings(CenteredWidget):
|
|||||||
self.compact_mode.setText(QtGui.QApplication.translate("interfaceForm", "Compact contact list", 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_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))
|
self.import_stickers.setText(QtGui.QApplication.translate("interfaceForm", "Import sticker pack", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.close_to_tray.setText(QtGui.QApplication.translate("interfaceForm", "Close to tray", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.choose_font.setText(QtGui.QApplication.translate("interfaceForm", "Select font", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
def import_st(self):
|
def import_st(self):
|
||||||
directory = QtGui.QFileDialog.getExistingDirectory(self,
|
directory = QtGui.QFileDialog.getExistingDirectory(self,
|
||||||
@ -766,6 +699,20 @@ class InterfaceSettings(CenteredWidget):
|
|||||||
dest = curr_directory() + '/smileys/' + os.path.basename(directory) + '/'
|
dest = curr_directory() + '/smileys/' + os.path.basename(directory) + '/'
|
||||||
copy(src, dest)
|
copy(src, dest)
|
||||||
|
|
||||||
|
def new_font(self):
|
||||||
|
settings = Settings.get_instance()
|
||||||
|
font, ok = QtGui.QFontDialog.getFont(QtGui.QFont(settings['font'], 10), self)
|
||||||
|
if ok:
|
||||||
|
settings['font'] = font.family()
|
||||||
|
settings.save()
|
||||||
|
msgBox = QtGui.QMessageBox()
|
||||||
|
text = QtGui.QApplication.translate("interfaceForm", 'Restart app to apply settings', None,
|
||||||
|
QtGui.QApplication.UnicodeUTF8)
|
||||||
|
msgBox.setWindowTitle(QtGui.QApplication.translate("interfaceForm", 'Restart required', None,
|
||||||
|
QtGui.QApplication.UnicodeUTF8))
|
||||||
|
msgBox.setText(text)
|
||||||
|
msgBox.exec_()
|
||||||
|
|
||||||
def select_color(self):
|
def select_color(self):
|
||||||
col = QtGui.QColorDialog.getColor()
|
col = QtGui.QColorDialog.getColor()
|
||||||
|
|
||||||
@ -786,7 +733,11 @@ class InterfaceSettings(CenteredWidget):
|
|||||||
if settings['compact_mode'] != self.compact_mode.isChecked():
|
if settings['compact_mode'] != self.compact_mode.isChecked():
|
||||||
settings['compact_mode'] = self.compact_mode.isChecked()
|
settings['compact_mode'] = self.compact_mode.isChecked()
|
||||||
restart = True
|
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()
|
settings['smiley_pack'] = self.smiley_pack.currentText()
|
||||||
|
settings['close_to_tray'] = self.close_to_tray.isChecked()
|
||||||
smileys.SmileyLoader.get_instance().load_pack()
|
smileys.SmileyLoader.get_instance().load_pack()
|
||||||
language = self.lang_choose.currentText()
|
language = self.lang_choose.currentText()
|
||||||
if settings['language'] != language:
|
if settings['language'] != language:
|
||||||
@ -830,9 +781,11 @@ class AudioSettings(CenteredWidget):
|
|||||||
self.in_label.setGeometry(QtCore.QRect(25, 5, 350, 20))
|
self.in_label.setGeometry(QtCore.QRect(25, 5, 350, 20))
|
||||||
self.out_label = QtGui.QLabel(self)
|
self.out_label = QtGui.QLabel(self)
|
||||||
self.out_label.setGeometry(QtCore.QRect(25, 65, 350, 20))
|
self.out_label.setGeometry(QtCore.QRect(25, 65, 350, 20))
|
||||||
|
settings = Settings.get_instance()
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(16)
|
font.setPointSize(16)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
|
font.setFamily(settings['font'])
|
||||||
self.in_label.setFont(font)
|
self.in_label.setFont(font)
|
||||||
self.out_label.setFont(font)
|
self.out_label.setFont(font)
|
||||||
self.input = QtGui.QComboBox(self)
|
self.input = QtGui.QComboBox(self)
|
||||||
@ -840,7 +793,6 @@ class AudioSettings(CenteredWidget):
|
|||||||
self.output = QtGui.QComboBox(self)
|
self.output = QtGui.QComboBox(self)
|
||||||
self.output.setGeometry(QtCore.QRect(25, 90, 350, 30))
|
self.output.setGeometry(QtCore.QRect(25, 90, 350, 30))
|
||||||
p = pyaudio.PyAudio()
|
p = pyaudio.PyAudio()
|
||||||
settings = Settings.get_instance()
|
|
||||||
self.in_indexes, self.out_indexes = [], []
|
self.in_indexes, self.out_indexes = [], []
|
||||||
for i in range(p.get_device_count()):
|
for i in range(p.get_device_count()):
|
||||||
device = p.get_device_info_by_index(i)
|
device = p.get_device_info_by_index(i)
|
||||||
|
@ -39,18 +39,6 @@ class TextMessage(Message):
|
|||||||
return self._message, self._owner, self._time, self._type
|
return self._message, self._owner, self._time, self._type
|
||||||
|
|
||||||
|
|
||||||
class GroupChatTextMessage(TextMessage):
|
|
||||||
|
|
||||||
def __init__(self, friend_name, *args):
|
|
||||||
super().__init__(*args)
|
|
||||||
self._name = friend_name
|
|
||||||
|
|
||||||
def get_data(self):
|
|
||||||
data = list(super().get_data())
|
|
||||||
data.append(self._name)
|
|
||||||
return tuple(data)
|
|
||||||
|
|
||||||
|
|
||||||
class TransferMessage(Message):
|
class TransferMessage(Message):
|
||||||
"""
|
"""
|
||||||
Message with info about file transfer
|
Message with info about file transfer
|
||||||
@ -83,7 +71,6 @@ class TransferMessage(Message):
|
|||||||
|
|
||||||
|
|
||||||
class UnsentFile(Message):
|
class UnsentFile(Message):
|
||||||
|
|
||||||
def __init__(self, path, data, time):
|
def __init__(self, path, data, time):
|
||||||
super(UnsentFile, self).__init__(MESSAGE_TYPE['FILE_TRANSFER'], 0, time)
|
super(UnsentFile, self).__init__(MESSAGE_TYPE['FILE_TRANSFER'], 0, time)
|
||||||
self._data, self._path = data, path
|
self._data, self._path = data, path
|
||||||
|
@ -147,6 +147,16 @@ class PluginLoader(util.Singleton):
|
|||||||
continue
|
continue
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def get_message_menu(self, menu, selected_text):
|
||||||
|
result = []
|
||||||
|
for elem in self._plugins.values():
|
||||||
|
if elem[1]:
|
||||||
|
try:
|
||||||
|
result.extend(elem[0].get_message_menu(menu, selected_text))
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
return result
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""
|
"""
|
||||||
App is closing, stop all plugins
|
App is closing, stop all plugins
|
||||||
|
@ -88,6 +88,15 @@ class PluginSuperClass:
|
|||||||
"""
|
"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def get_message_menu(self, menu, text):
|
||||||
|
"""
|
||||||
|
This method creates items for menu which called on right click in message
|
||||||
|
:param menu: menu instance
|
||||||
|
:param text: selected text
|
||||||
|
:return list of QAction's
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
def get_window(self):
|
def get_window(self):
|
||||||
"""
|
"""
|
||||||
This method should return window for plugins with GUI or None
|
This method should return window for plugins with GUI or None
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
from platform import system
|
from platform import system
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import locale
|
from util import Singleton, curr_directory, log, copy
|
||||||
from util import Singleton, curr_directory, log
|
|
||||||
import pyaudio
|
import pyaudio
|
||||||
from toxencryptsave import ToxEncryptSave
|
from toxencryptsave import ToxEncryptSave
|
||||||
import smileys
|
import smileys
|
||||||
@ -34,10 +33,19 @@ class Settings(dict, Singleton):
|
|||||||
super(Settings, self).__init__(Settings.get_default_settings())
|
super(Settings, self).__init__(Settings.get_default_settings())
|
||||||
self.save()
|
self.save()
|
||||||
smileys.SmileyLoader(self)
|
smileys.SmileyLoader(self)
|
||||||
p = pyaudio.PyAudio()
|
|
||||||
self.locked = False
|
self.locked = False
|
||||||
self.audio = {'input': p.get_default_input_device_info()['index'],
|
self.closing = False
|
||||||
'output': p.get_default_output_device_info()['index']}
|
p = pyaudio.PyAudio()
|
||||||
|
input_devices = output_devices = 0
|
||||||
|
for i in range(p.get_device_count()):
|
||||||
|
device = p.get_device_info_by_index(i)
|
||||||
|
if device["maxInputChannels"]:
|
||||||
|
input_devices += 1
|
||||||
|
if device["maxOutputChannels"]:
|
||||||
|
output_devices += 1
|
||||||
|
self.audio = {'input': p.get_default_input_device_info()['index'] if input_devices else -1,
|
||||||
|
'output': p.get_default_output_device_info()['index'] if output_devices else -1,
|
||||||
|
'enabled': input_devices and output_devices}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_auto_profile():
|
def get_auto_profile():
|
||||||
@ -109,7 +117,10 @@ class Settings(dict, Singleton):
|
|||||||
'auto_accept_path': None,
|
'auto_accept_path': None,
|
||||||
'show_online_friends': False,
|
'show_online_friends': False,
|
||||||
'auto_accept_from_friends': [],
|
'auto_accept_from_friends': [],
|
||||||
|
'paused_file_transfers': {},
|
||||||
|
'resend_files': True,
|
||||||
'friends_aliases': [],
|
'friends_aliases': [],
|
||||||
|
'show_avatars': False,
|
||||||
'typing_notifications': False,
|
'typing_notifications': False,
|
||||||
'calls_sound': True,
|
'calls_sound': True,
|
||||||
'blocked': [],
|
'blocked': [],
|
||||||
@ -127,7 +138,8 @@ class Settings(dict, Singleton):
|
|||||||
'save_unsent_only': False,
|
'save_unsent_only': False,
|
||||||
'compact_mode': False,
|
'compact_mode': False,
|
||||||
'show_welcome_screen': True,
|
'show_welcome_screen': True,
|
||||||
'notify_all_gc': False
|
'close_to_tray': False,
|
||||||
|
'font': 'Times New Roman'
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -194,12 +206,17 @@ class Settings(dict, Singleton):
|
|||||||
with open(path + str(self.name) + '.json', 'w') as fl:
|
with open(path + str(self.name) + '.json', 'w') as fl:
|
||||||
fl.write(text)
|
fl.write(text)
|
||||||
|
|
||||||
|
def update_path(self):
|
||||||
|
self.path = ProfileHelper.get_path() + self.name + '.json'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_default_path():
|
def get_default_path():
|
||||||
if system() == 'Linux':
|
if system() == 'Windows':
|
||||||
return os.getenv('HOME') + '/.config/tox/'
|
|
||||||
elif system() == 'Windows':
|
|
||||||
return os.getenv('APPDATA') + '/Tox/'
|
return os.getenv('APPDATA') + '/Tox/'
|
||||||
|
elif system() == 'Darwin':
|
||||||
|
return os.getenv('HOME') + '/Library/Application Support/Tox/'
|
||||||
|
else:
|
||||||
|
return os.getenv('HOME') + '/.config/tox/'
|
||||||
|
|
||||||
|
|
||||||
class ProfileHelper(Singleton):
|
class ProfileHelper(Singleton):
|
||||||
@ -234,13 +251,18 @@ class ProfileHelper(Singleton):
|
|||||||
fl.write(data)
|
fl.write(data)
|
||||||
print('Profile saved successfully')
|
print('Profile saved successfully')
|
||||||
|
|
||||||
def export_profile(self, new_path):
|
def export_profile(self, new_path, use_new_path):
|
||||||
new_path += os.path.basename(self._path)
|
path = new_path + os.path.basename(self._path)
|
||||||
with open(self._path, 'rb') as fin:
|
with open(self._path, 'rb') as fin:
|
||||||
data = fin.read()
|
data = fin.read()
|
||||||
with open(new_path, 'wb') as fout:
|
with open(path, 'wb') as fout:
|
||||||
fout.write(data)
|
fout.write(data)
|
||||||
print('Profile exported successfully')
|
print('Profile exported successfully')
|
||||||
|
copy(self._directory + 'avatars', new_path + 'avatars')
|
||||||
|
if use_new_path:
|
||||||
|
self._path = new_path + os.path.basename(self._path)
|
||||||
|
self._directory = new_path
|
||||||
|
Settings.get_instance().update_path()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def find_profiles():
|
def find_profiles():
|
||||||
|
BIN
toxygen/smileys/ksk/angry.png
Normal file
After Width: | Height: | Size: 883 B |
BIN
toxygen/smileys/ksk/angry2.png
Normal file
After Width: | Height: | Size: 932 B |
BIN
toxygen/smileys/ksk/angry3.png
Normal file
After Width: | Height: | Size: 917 B |
BIN
toxygen/smileys/ksk/blink.png
Normal file
After Width: | Height: | Size: 891 B |
BIN
toxygen/smileys/ksk/bluestar.png
Normal file
After Width: | Height: | Size: 809 B |
BIN
toxygen/smileys/ksk/calm.png
Normal file
After Width: | Height: | Size: 893 B |
1
toxygen/smileys/ksk/config.json
Normal 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"}
|
BIN
toxygen/smileys/ksk/cool.png
Normal file
After Width: | Height: | Size: 914 B |
BIN
toxygen/smileys/ksk/cool2.png
Normal file
After Width: | Height: | Size: 956 B |
BIN
toxygen/smileys/ksk/cry.png
Normal file
After Width: | Height: | Size: 956 B |
BIN
toxygen/smileys/ksk/dead.png
Normal file
After Width: | Height: | Size: 913 B |
BIN
toxygen/smileys/ksk/evil.png
Normal file
After Width: | Height: | Size: 888 B |
BIN
toxygen/smileys/ksk/evil2.png
Normal file
After Width: | Height: | Size: 929 B |
BIN
toxygen/smileys/ksk/flower.png
Normal file
After Width: | Height: | Size: 935 B |
BIN
toxygen/smileys/ksk/getlost.png
Normal file
After Width: | Height: | Size: 921 B |
BIN
toxygen/smileys/ksk/greenstar.png
Normal file
After Width: | Height: | Size: 822 B |
BIN
toxygen/smileys/ksk/grin.png
Normal file
After Width: | Height: | Size: 920 B |
BIN
toxygen/smileys/ksk/heart.png
Normal file
After Width: | Height: | Size: 829 B |
BIN
toxygen/smileys/ksk/kiss.png
Normal file
After Width: | Height: | Size: 996 B |
BIN
toxygen/smileys/ksk/leaf.png
Normal file
After Width: | Height: | Size: 913 B |
BIN
toxygen/smileys/ksk/lol.png
Normal file
After Width: | Height: | Size: 957 B |
BIN
toxygen/smileys/ksk/none.png
Normal file
After Width: | Height: | Size: 882 B |
BIN
toxygen/smileys/ksk/none2.png
Normal file
After Width: | Height: | Size: 890 B |
BIN
toxygen/smileys/ksk/notes.png
Normal file
After Width: | Height: | Size: 751 B |
BIN
toxygen/smileys/ksk/oops.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
toxygen/smileys/ksk/pawn.png
Normal file
After Width: | Height: | Size: 989 B |
BIN
toxygen/smileys/ksk/pleased.png
Normal file
After Width: | Height: | Size: 937 B |
BIN
toxygen/smileys/ksk/redstar.png
Normal file
After Width: | Height: | Size: 782 B |
BIN
toxygen/smileys/ksk/sad.png
Normal file
After Width: | Height: | Size: 914 B |
BIN
toxygen/smileys/ksk/scared.png
Normal file
After Width: | Height: | Size: 897 B |
BIN
toxygen/smileys/ksk/shocked.png
Normal file
After Width: | Height: | Size: 967 B |
BIN
toxygen/smileys/ksk/smile.png
Normal file
After Width: | Height: | Size: 885 B |
BIN
toxygen/smileys/ksk/smile2.png
Normal file
After Width: | Height: | Size: 886 B |
BIN
toxygen/smileys/ksk/tongue.png
Normal file
After Width: | Height: | Size: 918 B |
BIN
toxygen/smileys/ksk/unwell.png
Normal file
After Width: | Height: | Size: 888 B |
BIN
toxygen/smileys/ksk/yellowstar.png
Normal file
After Width: | Height: | Size: 792 B |
BIN
toxygen/smileys/ksk/zzz.png
Normal file
After Width: | Height: | Size: 990 B |
BIN
toxygen/stickers/tox/tox_logo.png
Executable file
After Width: | Height: | Size: 31 KiB |
BIN
toxygen/stickers/tox/tox_logo_1.png
Executable file
After Width: | Height: | Size: 27 KiB |
@ -1245,10 +1245,20 @@ QPushButton:hover
|
|||||||
}
|
}
|
||||||
|
|
||||||
#messages:item:selected
|
#messages:item:selected
|
||||||
|
{
|
||||||
|
background-color: #1E90FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageEdit
|
||||||
{
|
{
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#messages:item:selected QListWidgetItem
|
||||||
|
{
|
||||||
|
background-color: #1E90FF;
|
||||||
|
}
|
||||||
|
|
||||||
#friends_list:item:selected
|
#friends_list:item:selected
|
||||||
{
|
{
|
||||||
background-color: #333333;
|
background-color: #333333;
|
||||||
|
948
toxygen/tox.py
@ -92,22 +92,6 @@ class Tox:
|
|||||||
self.file_recv_chunk_cb = None
|
self.file_recv_chunk_cb = None
|
||||||
self.friend_lossy_packet_cb = None
|
self.friend_lossy_packet_cb = None
|
||||||
self.friend_lossless_packet_cb = None
|
self.friend_lossless_packet_cb = None
|
||||||
self.group_moderation_cb = None
|
|
||||||
self.group_join_fail_cb = None
|
|
||||||
self.group_self_join_cb = None
|
|
||||||
self.group_invite_cb = None
|
|
||||||
self.group_custom_packet_cb = None
|
|
||||||
self.group_private_message_cb = None
|
|
||||||
self.group_private_message_cb = None
|
|
||||||
self.group_message_cb = None
|
|
||||||
self.group_password_cb = None
|
|
||||||
self.group_peer_limit_cb = None
|
|
||||||
self.group_privacy_state_cb = None
|
|
||||||
self.group_topic_cb = None
|
|
||||||
self.group_peer_status_cb = None
|
|
||||||
self.group_peer_name_cb = None
|
|
||||||
self.group_peer_exit_cb = None
|
|
||||||
self.group_peer_join_cb = None
|
|
||||||
|
|
||||||
self.AV = ToxAV(self._tox_pointer)
|
self.AV = ToxAV(self._tox_pointer)
|
||||||
|
|
||||||
@ -1526,935 +1510,3 @@ class Tox:
|
|||||||
return result
|
return result
|
||||||
elif tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']:
|
elif tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']:
|
||||||
raise RuntimeError('The instance was not bound to any port.')
|
raise RuntimeError('The instance was not bound to any port.')
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Group chat instance management
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_new(self, privacy_state, group_name):
|
|
||||||
"""
|
|
||||||
Creates a new group chat.
|
|
||||||
|
|
||||||
This function creates a new group chat object and adds it to the chats array.
|
|
||||||
|
|
||||||
The client should initiate its peer list with self info after calling this function, as
|
|
||||||
the peer_join callback will not be triggered.
|
|
||||||
|
|
||||||
:param privacy_state: The privacy state of the group. If this is set to TOX_GROUP_PRIVACY_STATE_PUBLIC,
|
|
||||||
the group will attempt to announce itself to the DHT and anyone with the Chat ID may join.
|
|
||||||
Otherwise a friend invite will be required to join the group.
|
|
||||||
:param group_name: The name of the group. The name must be non-NULL.
|
|
||||||
|
|
||||||
:return group number on success, UINT32_MAX on failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_new(self._tox_pointer, privacy_state, group_name,
|
|
||||||
len(group_name), byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_join(self, chat_id, password):
|
|
||||||
"""
|
|
||||||
Joins a group chat with specified Chat ID.
|
|
||||||
|
|
||||||
This function creates a new group chat object, adds it to the chats array, and sends
|
|
||||||
a DHT announcement to find peers in the group associated with chat_id. Once a peer has been
|
|
||||||
found a join attempt will be initiated.
|
|
||||||
|
|
||||||
:param chat_id: The Chat ID of the group you wish to join. This must be TOX_GROUP_CHAT_ID_SIZE bytes.
|
|
||||||
:param password: The password required to join the group. Set to NULL if no password is required.
|
|
||||||
|
|
||||||
:return groupnumber on success, UINT32_MAX on failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_join(self._tox_pointer, string_to_bin(chat_id),
|
|
||||||
password,
|
|
||||||
len(password) if password is not None else 0,
|
|
||||||
byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_reconnect(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Reconnects to a group.
|
|
||||||
|
|
||||||
This function disconnects from all peers in the group, then attempts to reconnect with the group.
|
|
||||||
The caller's state is not changed (i.e. name, status, role, chat public key etc.)
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group we wish to reconnect to.
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_reconnect(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_leave(self, groupnumber, message):
|
|
||||||
"""
|
|
||||||
Leaves a group.
|
|
||||||
|
|
||||||
This function sends a parting packet containing a custom (non-obligatory) message to all
|
|
||||||
peers in a group, and deletes the group from the chat array. All group state information is permanently
|
|
||||||
lost, including keys and role credentials.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group we wish to leave.
|
|
||||||
:param message: The parting message to be sent to all the peers. Set to NULL if we do not wish to
|
|
||||||
send a parting message.
|
|
||||||
|
|
||||||
:return True if the group chat instance was successfully deleted.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
f = Tox.libtoxcore.tox_group_leave
|
|
||||||
f.restype = c_bool
|
|
||||||
result = f(self._tox_pointer, groupnumber, message,
|
|
||||||
len(message) if message is not None else 0, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Group user-visible client information (nickname/status/role/public key)
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_self_set_name(self, groupnumber, name):
|
|
||||||
"""
|
|
||||||
Set the client's nickname for the group instance designated by the given group number.
|
|
||||||
|
|
||||||
Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is equal to zero or name is a NULL
|
|
||||||
pointer, the function call will fail.
|
|
||||||
|
|
||||||
:param name: A byte array containing the new nickname.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_self_set_name(self._tox_pointer, groupnumber, name, len(name), byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_self_get_name_size(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Return the length of the client's current nickname for the group instance designated
|
|
||||||
by groupnumber as passed to tox_group_self_set_name.
|
|
||||||
|
|
||||||
If no nickname was set before calling this function, the name is empty,
|
|
||||||
and this function returns 0.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_self_get_name_size(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_self_get_name(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Write the nickname set by tox_group_self_set_name to a byte array.
|
|
||||||
|
|
||||||
If no nickname was set before calling this function, the name is empty,
|
|
||||||
and this function has no effect.
|
|
||||||
|
|
||||||
Call tox_group_self_get_name_size to find out how much memory to allocate for the result.
|
|
||||||
:return nickname
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
size = self.group_self_get_name_size(groupnumber)
|
|
||||||
name = create_string_buffer(size)
|
|
||||||
result = Tox.libtoxcore.tox_group_self_get_name(self._tox_pointer, groupnumber, name, byref(error))
|
|
||||||
return str(name[:size], 'utf-8')
|
|
||||||
|
|
||||||
def group_self_set_status(self, groupnumber, status):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Set the client's status for the group instance. Status must be a TOX_USER_STATUS.
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_self_set_status(self._tox_pointer, groupnumber, status, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_self_get_status(self, groupnumber):
|
|
||||||
"""
|
|
||||||
returns the client's status for the group instance on success.
|
|
||||||
return value is unspecified on failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_self_get_status(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_self_get_role(self, groupnumber):
|
|
||||||
"""
|
|
||||||
returns the client's role for the group instance on success.
|
|
||||||
return value is unspecified on failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_self_get_role(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_self_get_peer_id(self, groupnumber):
|
|
||||||
"""
|
|
||||||
returns the client's peer id for the group instance on success.
|
|
||||||
return value is unspecified on failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_self_get_peer_id(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_self_get_public_key(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Write the client's group public key designated by the given group number to a byte array.
|
|
||||||
|
|
||||||
This key will be permanently tied to the client's identity for this particular group until
|
|
||||||
the client explicitly leaves the group or gets kicked/banned. This key is the only way for
|
|
||||||
other peers to reliably identify the client across client restarts.
|
|
||||||
|
|
||||||
`public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE bytes.
|
|
||||||
|
|
||||||
:return public key
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
key = create_string_buffer(TOX_GROUP_PEER_PUBLIC_KEY_SIZE)
|
|
||||||
result = Tox.libtoxcore.tox_group_self_get_public_key(self._tox_pointer, groupnumber,
|
|
||||||
key, byref(error))
|
|
||||||
return bin_to_string(key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Peer-specific group state queries.
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_peer_get_name_size(self, groupnumber, peer_id):
|
|
||||||
"""
|
|
||||||
Return the length of the peer's name. If the group number or ID is invalid, the
|
|
||||||
return value is unspecified.
|
|
||||||
|
|
||||||
The return value is equal to the `length` argument received by the last
|
|
||||||
`group_peer_name` callback.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_peer_get_name_size(self._tox_pointer, groupnumber, peer_id, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_peer_get_name(self, groupnumber, peer_id):
|
|
||||||
"""
|
|
||||||
Write the name of the peer designated by the given ID to a byte
|
|
||||||
array.
|
|
||||||
|
|
||||||
Call tox_group_peer_get_name_size to determine the allocation size for the `name` parameter.
|
|
||||||
|
|
||||||
The data written to `name` is equal to the data received by the last
|
|
||||||
`group_peer_name` callback.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group we wish to query.
|
|
||||||
:param peer_id: The ID of the peer whose name we want to retrieve.
|
|
||||||
|
|
||||||
:return name.
|
|
||||||
"""
|
|
||||||
error = c_int()
|
|
||||||
size = self.group_peer_get_name_size(groupnumber, peer_id)
|
|
||||||
name = create_string_buffer(size)
|
|
||||||
result = Tox.libtoxcore.tox_group_peer_get_name(self._tox_pointer, groupnumber, peer_id, name, byref(error))
|
|
||||||
return str(name[:], 'utf-8')
|
|
||||||
|
|
||||||
def group_peer_get_status(self, groupnumber, peer_id):
|
|
||||||
"""
|
|
||||||
Return the peer's user status (away/busy/...). If the ID or group number is
|
|
||||||
invalid, the return value is unspecified.
|
|
||||||
|
|
||||||
The status returned is equal to the last status received through the
|
|
||||||
`group_peer_status` callback.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_peer_get_status(self._tox_pointer, groupnumber, peer_id, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_peer_get_role(self, groupnumber, peer_id):
|
|
||||||
"""
|
|
||||||
Return the peer's role (user/moderator/founder...). If the ID or group number is
|
|
||||||
invalid, the return value is unspecified.
|
|
||||||
|
|
||||||
The role returned is equal to the last role received through the
|
|
||||||
`group_moderation` callback.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_peer_get_role(self._tox_pointer, groupnumber, peer_id, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_peer_get_public_key(self, groupnumber, peer_id):
|
|
||||||
"""
|
|
||||||
Write the group public key with the designated peer_id for the designated group number to public_key.
|
|
||||||
|
|
||||||
This key will be parmanently tied to a particular peer until they explicitly leave the group or
|
|
||||||
get kicked/banned, and is the only way to reliably identify the same peer across client restarts.
|
|
||||||
|
|
||||||
`public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE bytes.
|
|
||||||
|
|
||||||
:return public key
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
key = create_string_buffer(TOX_GROUP_PEER_PUBLIC_KEY_SIZE)
|
|
||||||
result = Tox.libtoxcore.tox_group_peer_get_public_key(self._tox_pointer, groupnumber, peer_id,
|
|
||||||
key, byref(error))
|
|
||||||
return bin_to_string(key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE)
|
|
||||||
|
|
||||||
def callback_group_peer_name(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_peer_name` event. Pass NULL to unset.
|
|
||||||
This event is triggered when a peer changes their nickname.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_void_p)
|
|
||||||
self.group_peer_name_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_peer_name(self._tox_pointer, self.group_peer_name_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_peer_status(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_peer_status` event. Pass NULL to unset.
|
|
||||||
This event is triggered when a peer changes their status.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_int, c_void_p)
|
|
||||||
self.group_peer_status_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_peer_status(self._tox_pointer, self.group_peer_status_cb, user_data)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Group chat state queries and events.
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_set_topic(self, groupnumber, topic):
|
|
||||||
"""
|
|
||||||
Set the group topic and broadcast it to the rest of the group.
|
|
||||||
|
|
||||||
topic length cannot be longer than TOX_GROUP_MAX_TOPIC_LENGTH. If length is equal to zero or
|
|
||||||
topic is set to NULL, the topic will be unset.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_set_topic(self._tox_pointer, groupnumber, topic, len(topic), byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_get_topic_size(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Return the length of the group topic. If the group number is invalid, the
|
|
||||||
return value is unspecified.
|
|
||||||
|
|
||||||
The return value is equal to the `length` argument received by the last
|
|
||||||
`group_topic` callback.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_get_topic_size(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_get_topic(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Write the topic designated by the given group number to a byte array.
|
|
||||||
Call tox_group_get_topic_size to determine the allocation size for the `topic` parameter.
|
|
||||||
The data written to `topic` is equal to the data received by the last
|
|
||||||
`group_topic` callback.
|
|
||||||
|
|
||||||
:return topic
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
size = self.group_get_topic_size(groupnumber)
|
|
||||||
topic = create_string_buffer(size)
|
|
||||||
result = Tox.libtoxcore.tox_group_get_topic(self._tox_pointer, groupnumber, topic, byref(error))
|
|
||||||
return str(topic[:size], 'utf-8')
|
|
||||||
|
|
||||||
def group_get_name_size(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Return the length of the group name. If the group number is invalid, the
|
|
||||||
return value is unspecified.
|
|
||||||
"""
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_get_name_size(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_get_name(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Write the name of the group designated by the given group number to a byte array.
|
|
||||||
Call tox_group_get_name_size to determine the allocation size for the `name` parameter.
|
|
||||||
:return true on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
size = self.group_get_name_size(groupnumber)
|
|
||||||
name = create_string_buffer(size)
|
|
||||||
result = Tox.libtoxcore.tox_group_get_name(self._tox_pointer, groupnumber,
|
|
||||||
name, byref(error))
|
|
||||||
return str(name[:size], 'utf-8')
|
|
||||||
|
|
||||||
def group_get_chat_id(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Write the Chat ID designated by the given group number to a byte array.
|
|
||||||
`chat_id` should have room for at least TOX_GROUP_CHAT_ID_SIZE bytes.
|
|
||||||
:return chat id.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
buff = create_string_buffer(TOX_GROUP_CHAT_ID_SIZE)
|
|
||||||
result = Tox.libtoxcore.tox_group_get_chat_id(self._tox_pointer, groupnumber,
|
|
||||||
buff, byref(error))
|
|
||||||
return bin_to_string(buff, TOX_GROUP_CHAT_ID_SIZE)
|
|
||||||
|
|
||||||
def group_get_number_groups(self):
|
|
||||||
"""
|
|
||||||
Return the number of groups in the Tox chats array.
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Tox.libtoxcore.tox_group_get_number_groups(self._tox_pointer)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_get_privacy_state(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Return the privacy state of the group designated by the given group number. If group number
|
|
||||||
is invalid, the return value is unspecified.
|
|
||||||
|
|
||||||
The value returned is equal to the data received by the last
|
|
||||||
`group_privacy_state` callback.
|
|
||||||
|
|
||||||
see the `Group chat founder controls` section for the respective set function.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_get_privacy_state(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_get_peer_limit(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Return the maximum number of peers allowed for the group designated by the given group number.
|
|
||||||
If the group number is invalid, the return value is unspecified.
|
|
||||||
|
|
||||||
The value returned is equal to the data received by the last
|
|
||||||
`group_peer_limit` callback.
|
|
||||||
|
|
||||||
see the `Group chat founder controls` section for the respective set function.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_get_peer_limit(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_get_password_size(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Return the length of the group password. If the group number is invalid, the
|
|
||||||
return value is unspecified.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_get_password_size(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_get_password(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Write the password for the group designated by the given group number to a byte array.
|
|
||||||
|
|
||||||
Call tox_group_get_password_size to determine the allocation size for the `password` parameter.
|
|
||||||
|
|
||||||
The data received is equal to the data received by the last
|
|
||||||
`group_password` callback.
|
|
||||||
|
|
||||||
see the `Group chat founder controls` section for the respective set function.
|
|
||||||
|
|
||||||
:return password
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
size = self.group_get_password_size(groupnumber)
|
|
||||||
password = create_string_buffer(size)
|
|
||||||
result = Tox.libtoxcore.tox_group_get_password(self._tox_pointer, groupnumber,
|
|
||||||
password, byref(error))
|
|
||||||
return str(password[:size], 'utf-8')
|
|
||||||
|
|
||||||
def callback_group_topic(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_topic` event. Pass NULL to unset.
|
|
||||||
This event is triggered when a peer changes the group topic.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_void_p)
|
|
||||||
self.group_topic_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_topic(self._tox_pointer, self.group_topic_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_privacy_state(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_privacy_state` event. Pass NULL to unset.
|
|
||||||
This event is triggered when the group founder changes the privacy state.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_void_p)
|
|
||||||
self.group_privacy_state_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_privacy_state(self._tox_pointer, self.group_privacy_state_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_peer_limit(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_peer_limit` event. Pass NULL to unset.
|
|
||||||
This event is triggered when the group founder changes the maximum peer limit.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p)
|
|
||||||
self.group_peer_limit_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_peer_limit(self._tox_pointer, self.group_peer_limit_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_password(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_password` event. Pass NULL to unset.
|
|
||||||
This event is triggered when the group founder changes the group password.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_char_p, c_size_t, c_void_p)
|
|
||||||
self.group_password_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_password(self._tox_pointer, self.group_password_cb, user_data)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Group message sending
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_send_custom_packet(self, groupnumber, lossless, data):
|
|
||||||
"""
|
|
||||||
Send a custom packet to the group.
|
|
||||||
|
|
||||||
If lossless is true the packet will be lossless. Lossless packet behaviour is comparable
|
|
||||||
to TCP (reliability, arrive in order) but with packets instead of a stream.
|
|
||||||
|
|
||||||
If lossless is false, the packet will be lossy. Lossy packets behave like UDP packets,
|
|
||||||
meaning they might never reach the other side or might arrive more than once (if someone
|
|
||||||
is messing with the connection) or might arrive in the wrong order.
|
|
||||||
|
|
||||||
Unless latency is an issue or message reliability is not important, it is recommended that you use
|
|
||||||
lossless custom packets.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group the message is intended for.
|
|
||||||
:param lossless: True if the packet should be lossless.
|
|
||||||
:param data A byte array containing the packet data.
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_send_custom_packet(self._tox_pointer, groupnumber, lossless, data,
|
|
||||||
len(data), byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_send_private_message(self, groupnumber, peer_id, message):
|
|
||||||
"""
|
|
||||||
Send a text chat message to the specified peer in the specified group.
|
|
||||||
|
|
||||||
This function creates a group private message packet and pushes it into the send
|
|
||||||
queue.
|
|
||||||
|
|
||||||
The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages
|
|
||||||
must be split by the client and sent as separate messages. Other clients can
|
|
||||||
then reassemble the fragments. Messages may not be empty.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group the message is intended for.
|
|
||||||
:param peer_id: The ID of the peer the message is intended for.
|
|
||||||
:param message: A non-NULL pointer to the first element of a byte array containing the message text.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_send_private_message(self._tox_pointer, groupnumber, peer_id, message,
|
|
||||||
len(message), byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_send_message(self, groupnumber, type, message):
|
|
||||||
"""
|
|
||||||
Send a text chat message to the group.
|
|
||||||
|
|
||||||
This function creates a group message packet and pushes it into the send
|
|
||||||
queue.
|
|
||||||
|
|
||||||
The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages
|
|
||||||
must be split by the client and sent as separate messages. Other clients can
|
|
||||||
then reassemble the fragments. Messages may not be empty.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group the message is intended for.
|
|
||||||
:param type: Message type (normal, action, ...).
|
|
||||||
:param message: A non-NULL pointer to the first element of a byte array containing the message text.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_send_message(self._tox_pointer, groupnumber, type, message, len(message),
|
|
||||||
byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Group message receiving
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def callback_group_message(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_message` event. Pass NULL to unset.
|
|
||||||
This event is triggered when the client receives a group message.
|
|
||||||
|
|
||||||
Callback: python function with params:
|
|
||||||
tox Tox* instance
|
|
||||||
groupnumber The group number of the group the message is intended for.
|
|
||||||
peer_id The ID of the peer who sent the message.
|
|
||||||
type The type of message (normal, action, ...).
|
|
||||||
message The message data.
|
|
||||||
length The length of the message.
|
|
||||||
user_data - user data
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_int, c_char_p, c_size_t, c_void_p)
|
|
||||||
self.group_message_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_message(self._tox_pointer, self.group_message_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_private_message(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_private_message` event. Pass NULL to unset.
|
|
||||||
This event is triggered when the client receives a private message.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_void_p)
|
|
||||||
self.group_private_message_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_private_message(self._tox_pointer, self.group_private_message_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_custom_packet(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_custom_packet` event. Pass NULL to unset.
|
|
||||||
|
|
||||||
This event is triggered when the client receives a custom packet.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, POINTER(c_uint8), c_void_p)
|
|
||||||
self.group_custom_packet_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_custom_packet(self._tox_pointer, self.group_custom_packet_cb, user_data)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Group chat inviting and join/part events
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_invite_friend(self, groupnumber, friend_number):
|
|
||||||
"""
|
|
||||||
Invite a friend to a group.
|
|
||||||
|
|
||||||
This function creates an invite request packet and pushes it to the send queue.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group the message is intended for.
|
|
||||||
:param friend_number: The friend number of the friend the invite is intended for.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_invite_friend(self._tox_pointer, groupnumber, friend_number, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_invite_accept(self, invite_data, friend_number, password=None):
|
|
||||||
"""
|
|
||||||
Accept an invite to a group chat that the client previously received from a friend. The invite
|
|
||||||
is only valid while the inviter is present in the group.
|
|
||||||
|
|
||||||
:param invite_data: The invite data received from the `group_invite` event.
|
|
||||||
:param password: The password required to join the group. Set to NULL if no password is required.
|
|
||||||
:return the groupnumber on success, UINT32_MAX on failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
f = Tox.libtoxcore.tox_group_invite_accept
|
|
||||||
f.restype = c_uint32
|
|
||||||
result = f(self._tox_pointer, friend_number, invite_data, len(invite_data), password,
|
|
||||||
len(password) if password is not None else 0, byref(error))
|
|
||||||
print('Invite accept. Result:', result, 'Error:', error.value)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def callback_group_invite(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_invite` event. Pass NULL to unset.
|
|
||||||
|
|
||||||
This event is triggered when the client receives a group invite from a friend. The client must store
|
|
||||||
invite_data which is used to join the group via tox_group_invite_accept.
|
|
||||||
|
|
||||||
Callback: python function with params:
|
|
||||||
tox - Tox*
|
|
||||||
friend_number The friend number of the contact who sent the invite.
|
|
||||||
invite_data The invite data.
|
|
||||||
length The length of invite_data.
|
|
||||||
user_data - user data
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_void_p)
|
|
||||||
self.group_invite_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_invite(self._tox_pointer, self.group_invite_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_peer_join(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_peer_join` event. Pass NULL to unset.
|
|
||||||
|
|
||||||
This event is triggered when a peer other than self joins the group.
|
|
||||||
Callback: python function with params:
|
|
||||||
tox - Tox*
|
|
||||||
group_number - group number
|
|
||||||
peer_id - peer id
|
|
||||||
user_data - user data
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p)
|
|
||||||
self.group_peer_join_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_peer_join(self._tox_pointer, self.group_peer_join_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_peer_exit(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_peer_exit` event. Pass NULL to unset.
|
|
||||||
|
|
||||||
This event is triggered when a peer other than self exits the group.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_void_p)
|
|
||||||
self.group_peer_exit_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_peer_exit(self._tox_pointer, self.group_peer_exit_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_self_join(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_self_join` event. Pass NULL to unset.
|
|
||||||
|
|
||||||
This event is triggered when the client has successfully joined a group. Use this to initialize
|
|
||||||
any group information the client may need.
|
|
||||||
Callback: python fucntion with params:
|
|
||||||
tox - *Tox
|
|
||||||
group_number - group number
|
|
||||||
user_data - user data
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_void_p)
|
|
||||||
self.group_self_join_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_self_join(self._tox_pointer, self.group_self_join_cb, user_data)
|
|
||||||
|
|
||||||
def callback_group_join_fail(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_join_fail` event. Pass NULL to unset.
|
|
||||||
|
|
||||||
This event is triggered when the client fails to join a group.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_void_p)
|
|
||||||
self.group_join_fail_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_join_fail(self._tox_pointer, self.group_join_fail_cb, user_data)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Group chat founder controls (these only work for the group founder)
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_founder_set_password(self, groupnumber, password):
|
|
||||||
"""
|
|
||||||
Set or unset the group password.
|
|
||||||
|
|
||||||
This function sets the groups password, creates a new group shared state including the change,
|
|
||||||
and distributes it to the rest of the group.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group for which we wish to set the password.
|
|
||||||
:param password: The password we want to set. Set password to NULL to unset the password.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_founder_set_password(self._tox_pointer, groupnumber, password,
|
|
||||||
len(password), byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_founder_set_privacy_state(self, groupnumber, privacy_state):
|
|
||||||
"""
|
|
||||||
Set the group privacy state.
|
|
||||||
|
|
||||||
This function sets the group's privacy state, creates a new group shared state
|
|
||||||
including the change, and distributes it to the rest of the group.
|
|
||||||
|
|
||||||
If an attempt is made to set the privacy state to the same state that the group is already
|
|
||||||
in, the function call will be successful and no action will be taken.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group for which we wish to change the privacy state.
|
|
||||||
:param privacy_state: The privacy state we wish to set the group to.
|
|
||||||
|
|
||||||
:return true on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_founder_set_privacy_state(self._tox_pointer, groupnumber, privacy_state,
|
|
||||||
byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_founder_set_peer_limit(self, groupnumber, max_peers):
|
|
||||||
"""
|
|
||||||
Set the group peer limit.
|
|
||||||
|
|
||||||
This function sets a limit for the number of peers who may be in the group, creates a new
|
|
||||||
group shared state including the change, and distributes it to the rest of the group.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group for which we wish to set the peer limit.
|
|
||||||
:param max_peers: The maximum number of peers to allow in the group.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_founder_set_peer_limit(self._tox_pointer, groupnumber,
|
|
||||||
max_peers, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Group chat moderation
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_toggle_ignore(self, groupnumber, peer_id, ignore):
|
|
||||||
"""
|
|
||||||
Ignore or unignore a peer.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group the in which you wish to ignore a peer.
|
|
||||||
:param peer_id: The ID of the peer who shall be ignored or unignored.
|
|
||||||
:param ignore: True to ignore the peer, false to unignore the peer.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_toggle_ignore(self._tox_pointer, groupnumber, peer_id, ignore, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_mod_set_role(self, groupnumber, peer_id, role):
|
|
||||||
"""
|
|
||||||
Set a peer's role.
|
|
||||||
|
|
||||||
This function will first remove the peer's previous role and then assign them a new role.
|
|
||||||
It will also send a packet to the rest of the group, requesting that they perform
|
|
||||||
the role reassignment. Note: peers cannot be set to the founder role.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group the in which you wish set the peer's role.
|
|
||||||
:param peer_id: The ID of the peer whose role you wish to set.
|
|
||||||
:param role: The role you wish to set the peer to.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_mod_set_role(self._tox_pointer, groupnumber, peer_id, role, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_mod_remove_peer(self, groupnumber, peer_id, set_ban):
|
|
||||||
"""
|
|
||||||
Kick/ban a peer.
|
|
||||||
|
|
||||||
This function will remove a peer from the caller's peer list and optionally add their IP address
|
|
||||||
to the ban list. It will also send a packet to all group members requesting them
|
|
||||||
to do the same.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group the ban is intended for.
|
|
||||||
:param peer_id: The ID of the peer who will be kicked and/or added to the ban list.
|
|
||||||
:param set_ban: Set to true if a ban shall be set on the peer's IP address.
|
|
||||||
|
|
||||||
:return True on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_mod_remove_peer(self._tox_pointer, groupnumber, peer_id,
|
|
||||||
set_ban, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_mod_remove_ban(self, groupnumber, ban_id):
|
|
||||||
"""
|
|
||||||
Removes a ban.
|
|
||||||
|
|
||||||
This function removes a ban entry from the ban list, and sends a packet to the rest of
|
|
||||||
the group requesting that they do the same.
|
|
||||||
|
|
||||||
:param groupnumber: The group number of the group in which the ban is to be removed.
|
|
||||||
:param ban_id: The ID of the ban entry that shall be removed.
|
|
||||||
|
|
||||||
:return True on success
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_mod_remove_ban(self._tox_pointer, groupnumber, ban_id, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def callback_group_moderation(self, callback, user_data):
|
|
||||||
"""
|
|
||||||
Set the callback for the `group_moderation` event. Pass NULL to unset.
|
|
||||||
|
|
||||||
This event is triggered when a moderator or founder executes a moderation event.
|
|
||||||
"""
|
|
||||||
|
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_uint32, c_int, c_void_p)
|
|
||||||
self.group_moderation_cb = c_callback(callback)
|
|
||||||
Tox.libtoxcore.tox_callback_group_moderation(self._tox_pointer, self.group_moderation_cb, user_data)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
# Group chat ban list queries
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def group_ban_get_list_size(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Return the number of entries in the ban list for the group designated by
|
|
||||||
the given group number. If the group number is invalid, the return value is unspecified.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_ban_get_list_size(self._tox_pointer, groupnumber, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_ban_get_list(self, groupnumber):
|
|
||||||
"""
|
|
||||||
Copy a list of valid ban list ID's into an array.
|
|
||||||
|
|
||||||
Call tox_group_ban_get_list_size to determine the number of elements to allocate.
|
|
||||||
return true on success.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_ban_get_list(self._tox_pointer, groupnumber, POINTER(c_uint32)(
|
|
||||||
create_string_buffer(sizeof(c_uint32) * self.group_ban_get_list_size(groupnumber)), byref(error)))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_ban_get_name_size(self, groupnumber, ban_id):
|
|
||||||
"""
|
|
||||||
Return the length of the name for the ban list entry designated by ban_id, in the
|
|
||||||
group designated by the given group number. If either groupnumber or ban_id is invalid,
|
|
||||||
the return value is unspecified.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_ban_get_name_size(self._tox_pointer, groupnumber, ban_id, byref(error))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def group_ban_get_name(self, groupnumber, ban_id):
|
|
||||||
"""
|
|
||||||
Write the name of the ban entry designated by ban_id in the group designated by the
|
|
||||||
given group number to a byte array.
|
|
||||||
|
|
||||||
Call tox_group_ban_get_name_size to find out how much memory to allocate for the result.
|
|
||||||
|
|
||||||
:return name
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
size = self.group_ban_get_name_size(groupnumber, ban_id)
|
|
||||||
name = create_string_buffer()
|
|
||||||
|
|
||||||
result = Tox.libtoxcore.tox_group_ban_get_name(self._tox_pointer, groupnumber, ban_id,
|
|
||||||
name, byref(error))
|
|
||||||
return str(name[:size], 'utf-8')
|
|
||||||
|
|
||||||
def group_ban_get_time_set(self, groupnumber, ban_id):
|
|
||||||
"""
|
|
||||||
Return a time stamp indicating the time the ban was set, for the ban list entry
|
|
||||||
designated by ban_id, in the group designated by the given group number.
|
|
||||||
If either groupnumber or ban_id is invalid, the return value is unspecified.
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = c_int()
|
|
||||||
result = Tox.libtoxcore.tox_group_ban_get_time_set(self._tox_pointer, groupnumber, ban_id, byref(error))
|
|
||||||
return result
|
|
||||||
|
@ -12,8 +12,6 @@ class ToxAV:
|
|||||||
peers.
|
peers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
libtoxav = LibToxAV()
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Creation and destruction
|
# Creation and destruction
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
@ -24,9 +22,10 @@ class ToxAV:
|
|||||||
|
|
||||||
:param tox_pointer: pointer to Tox instance
|
:param tox_pointer: pointer to Tox instance
|
||||||
"""
|
"""
|
||||||
|
self.libtoxav = LibToxAV()
|
||||||
toxav_err_new = c_int()
|
toxav_err_new = c_int()
|
||||||
ToxAV.libtoxav.toxav_new.restype = POINTER(c_void_p)
|
self.libtoxav.toxav_new.restype = POINTER(c_void_p)
|
||||||
self._toxav_pointer = ToxAV.libtoxav.toxav_new(tox_pointer, byref(toxav_err_new))
|
self._toxav_pointer = self.libtoxav.toxav_new(tox_pointer, byref(toxav_err_new))
|
||||||
toxav_err_new = toxav_err_new.value
|
toxav_err_new = toxav_err_new.value
|
||||||
if toxav_err_new == TOXAV_ERR_NEW['NULL']:
|
if toxav_err_new == TOXAV_ERR_NEW['NULL']:
|
||||||
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
||||||
@ -48,7 +47,7 @@ class ToxAV:
|
|||||||
If any calls were ongoing, these will be forcibly terminated without notifying peers. After calling this
|
If any calls were ongoing, these will be forcibly terminated without notifying peers. After calling this
|
||||||
function, no other functions may be called and the av pointer becomes invalid.
|
function, no other functions may be called and the av pointer becomes invalid.
|
||||||
"""
|
"""
|
||||||
ToxAV.libtoxav.toxav_kill(self._toxav_pointer)
|
self.libtoxav.toxav_kill(self._toxav_pointer)
|
||||||
|
|
||||||
def get_tox_pointer(self):
|
def get_tox_pointer(self):
|
||||||
"""
|
"""
|
||||||
@ -56,8 +55,8 @@ class ToxAV:
|
|||||||
|
|
||||||
:return: pointer to the Tox instance
|
:return: pointer to the Tox instance
|
||||||
"""
|
"""
|
||||||
ToxAV.libtoxav.toxav_get_tox.restype = POINTER(c_void_p)
|
self.libtoxav.toxav_get_tox.restype = POINTER(c_void_p)
|
||||||
return ToxAV.libtoxav.toxav_get_tox(self._toxav_pointer)
|
return self.libtoxav.toxav_get_tox(self._toxav_pointer)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# A/V event loop
|
# A/V event loop
|
||||||
@ -70,14 +69,14 @@ class ToxAV:
|
|||||||
|
|
||||||
:return: interval in milliseconds
|
:return: interval in milliseconds
|
||||||
"""
|
"""
|
||||||
return ToxAV.libtoxav.toxav_iteration_interval(self._toxav_pointer)
|
return self.libtoxav.toxav_iteration_interval(self._toxav_pointer)
|
||||||
|
|
||||||
def iterate(self):
|
def iterate(self):
|
||||||
"""
|
"""
|
||||||
Main loop for the session. This function needs to be called in intervals of toxav_iteration_interval()
|
Main loop for the session. This function needs to be called in intervals of toxav_iteration_interval()
|
||||||
milliseconds. It is best called in the separate thread from tox_iterate.
|
milliseconds. It is best called in the separate thread from tox_iterate.
|
||||||
"""
|
"""
|
||||||
ToxAV.libtoxav.toxav_iterate(self._toxav_pointer)
|
self.libtoxav.toxav_iterate(self._toxav_pointer)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Call setup
|
# Call setup
|
||||||
@ -97,7 +96,7 @@ class ToxAV:
|
|||||||
:return: True on success.
|
:return: True on success.
|
||||||
"""
|
"""
|
||||||
toxav_err_call = c_int()
|
toxav_err_call = c_int()
|
||||||
result = ToxAV.libtoxav.toxav_call(self._toxav_pointer, c_uint32(friend_number), c_uint32(audio_bit_rate),
|
result = self.libtoxav.toxav_call(self._toxav_pointer, c_uint32(friend_number), c_uint32(audio_bit_rate),
|
||||||
c_uint32(video_bit_rate), byref(toxav_err_call))
|
c_uint32(video_bit_rate), byref(toxav_err_call))
|
||||||
toxav_err_call = toxav_err_call.value
|
toxav_err_call = toxav_err_call.value
|
||||||
if toxav_err_call == TOXAV_ERR_CALL['OK']:
|
if toxav_err_call == TOXAV_ERR_CALL['OK']:
|
||||||
@ -131,7 +130,7 @@ class ToxAV:
|
|||||||
"""
|
"""
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_bool, c_bool, c_void_p)
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_bool, c_bool, c_void_p)
|
||||||
self.call_cb = c_callback(callback)
|
self.call_cb = c_callback(callback)
|
||||||
ToxAV.libtoxav.toxav_callback_call(self._toxav_pointer, self.call_cb, user_data)
|
self.libtoxav.toxav_callback_call(self._toxav_pointer, self.call_cb, user_data)
|
||||||
|
|
||||||
def answer(self, friend_number, audio_bit_rate, video_bit_rate):
|
def answer(self, friend_number, audio_bit_rate, video_bit_rate):
|
||||||
"""
|
"""
|
||||||
@ -146,7 +145,7 @@ class ToxAV:
|
|||||||
:return: True on success.
|
:return: True on success.
|
||||||
"""
|
"""
|
||||||
toxav_err_answer = c_int()
|
toxav_err_answer = c_int()
|
||||||
result = ToxAV.libtoxav.toxav_answer(self._toxav_pointer, c_uint32(friend_number), c_uint32(audio_bit_rate),
|
result = self.libtoxav.toxav_answer(self._toxav_pointer, c_uint32(friend_number), c_uint32(audio_bit_rate),
|
||||||
c_uint32(video_bit_rate), byref(toxav_err_answer))
|
c_uint32(video_bit_rate), byref(toxav_err_answer))
|
||||||
toxav_err_answer = toxav_err_answer.value
|
toxav_err_answer = toxav_err_answer.value
|
||||||
if toxav_err_answer == TOXAV_ERR_ANSWER['OK']:
|
if toxav_err_answer == TOXAV_ERR_ANSWER['OK']:
|
||||||
@ -184,7 +183,7 @@ class ToxAV:
|
|||||||
"""
|
"""
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p)
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p)
|
||||||
self.call_state_cb = c_callback(callback)
|
self.call_state_cb = c_callback(callback)
|
||||||
ToxAV.libtoxav.toxav_callback_call_state(self._toxav_pointer, self.call_state_cb, user_data)
|
self.libtoxav.toxav_callback_call_state(self._toxav_pointer, self.call_state_cb, user_data)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Call control
|
# Call control
|
||||||
@ -199,7 +198,7 @@ class ToxAV:
|
|||||||
:return: True on success.
|
:return: True on success.
|
||||||
"""
|
"""
|
||||||
toxav_err_call_control = c_int()
|
toxav_err_call_control = c_int()
|
||||||
result = ToxAV.libtoxav.toxav_call_control(self._toxav_pointer, c_uint32(friend_number), c_int(control),
|
result = self.libtoxav.toxav_call_control(self._toxav_pointer, c_uint32(friend_number), c_int(control),
|
||||||
byref(toxav_err_call_control))
|
byref(toxav_err_call_control))
|
||||||
toxav_err_call_control = toxav_err_call_control.value
|
toxav_err_call_control = toxav_err_call_control.value
|
||||||
if toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['OK']:
|
if toxav_err_call_control == TOXAV_ERR_CALL_CONTROL['OK']:
|
||||||
@ -241,7 +240,7 @@ class ToxAV:
|
|||||||
24000, or 48000.
|
24000, or 48000.
|
||||||
"""
|
"""
|
||||||
toxav_err_send_frame = c_int()
|
toxav_err_send_frame = c_int()
|
||||||
result = ToxAV.libtoxav.toxav_audio_send_frame(self._toxav_pointer, c_uint32(friend_number),
|
result = self.libtoxav.toxav_audio_send_frame(self._toxav_pointer, c_uint32(friend_number),
|
||||||
cast(pcm, c_void_p),
|
cast(pcm, c_void_p),
|
||||||
c_size_t(sample_count), c_uint8(channels),
|
c_size_t(sample_count), c_uint8(channels),
|
||||||
c_uint32(sampling_rate), byref(toxav_err_send_frame))
|
c_uint32(sampling_rate), byref(toxav_err_send_frame))
|
||||||
@ -281,7 +280,7 @@ class ToxAV:
|
|||||||
:param v: V (Chroma) plane data.
|
:param v: V (Chroma) plane data.
|
||||||
"""
|
"""
|
||||||
toxav_err_send_frame = c_int()
|
toxav_err_send_frame = c_int()
|
||||||
result = ToxAV.libtoxav.toxav_video_send_frame(self._toxav_pointer, c_uint32(friend_number), c_uint16(width),
|
result = self.libtoxav.toxav_video_send_frame(self._toxav_pointer, c_uint32(friend_number), c_uint16(width),
|
||||||
c_uint16(height), c_char_p(y), c_char_p(u), c_char_p(v),
|
c_uint16(height), c_char_p(y), c_char_p(u), c_char_p(v),
|
||||||
byref(toxav_err_send_frame))
|
byref(toxav_err_send_frame))
|
||||||
toxav_err_send_frame = toxav_err_send_frame.value
|
toxav_err_send_frame = toxav_err_send_frame.value
|
||||||
@ -328,7 +327,7 @@ class ToxAV:
|
|||||||
"""
|
"""
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_uint8, c_uint32, c_void_p)
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_uint8, c_uint32, c_void_p)
|
||||||
self.audio_receive_frame_cb = c_callback(callback)
|
self.audio_receive_frame_cb = c_callback(callback)
|
||||||
ToxAV.libtoxav.toxav_callback_audio_receive_frame(self._toxav_pointer, self.audio_receive_frame_cb, user_data)
|
self.libtoxav.toxav_callback_audio_receive_frame(self._toxav_pointer, self.audio_receive_frame_cb, user_data)
|
||||||
|
|
||||||
def callback_video_receive_frame(self, callback, user_data):
|
def callback_video_receive_frame(self, callback, user_data):
|
||||||
"""
|
"""
|
||||||
@ -360,4 +359,4 @@ class ToxAV:
|
|||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint16, c_uint16, POINTER(c_uint8), POINTER(c_uint8),
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint16, c_uint16, POINTER(c_uint8), POINTER(c_uint8),
|
||||||
POINTER(c_uint8), c_int32, c_int32, c_int32, c_void_p)
|
POINTER(c_uint8), c_int32, c_int32, c_int32, c_void_p)
|
||||||
self.video_receive_frame_cb = c_callback(callback)
|
self.video_receive_frame_cb = c_callback(callback)
|
||||||
ToxAV.libtoxav.toxav_callback_video_receive_frame(self._toxav_pointer, self.video_receive_frame_cb, user_data)
|
self.libtoxav.toxav_callback_video_receive_frame(self._toxav_pointer, self.video_receive_frame_cb, user_data)
|
||||||
|
@ -188,729 +188,6 @@ TOX_ERR_GET_PORT = {
|
|||||||
'NOT_BOUND': 1,
|
'NOT_BOUND': 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
TOX_GROUP_PRIVACY_STATE = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group is considered to be public. Anyone may join the group using the Chat ID.
|
|
||||||
#
|
|
||||||
# If the group is in this state, even if the Chat ID is never explicitly shared
|
|
||||||
# with someone outside of the group, information including the Chat ID, IP addresses,
|
|
||||||
# and peer ID's (but not Tox ID's) is visible to anyone with access to a node
|
|
||||||
# storing a DHT entry for the given group.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_PRIVACY_STATE_PUBLIC': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group is considered to be private. The only way to join the group is by having
|
|
||||||
# someone in your contact list send you an invite.
|
|
||||||
#
|
|
||||||
# If the group is in this state, no group information (mentioned above) is present in the DHT;
|
|
||||||
# the DHT is not used for any purpose at all. If a public group is set to private,
|
|
||||||
# all DHT information related to the group will expire shortly.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_PRIVACY_STATE_PRIVATE': 1
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_GROUP_ROLE = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# May kick and ban all other peers as well as set their role to anything (except founder).
|
|
||||||
# Founders may also set the group password, toggle the privacy state, and set the peer limit.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_ROLE_FOUNDER': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# May kick, ban and set the user and observer roles for peers below this role.
|
|
||||||
# May also set the group topic.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_ROLE_MODERATOR': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# May communicate with other peers normally.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_ROLE_USER': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# May observe the group and ignore peers; may not communicate with other peers or with the group.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_ROLE_OBSERVER': 3
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_NEW = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_NEW_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group name exceeded TOX_GROUP_MAX_GROUP_NAME_LENGTH.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_NEW_TOO_LONG': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# group_name is NULL or length is zero.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_NEW_EMPTY': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# TOX_GROUP_PRIVACY_STATE is an invalid type.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_NEW_PRIVACY': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group instance failed to initialize.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_NEW_INIT': 4,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group state failed to initialize. This usually indicates that something went wrong
|
|
||||||
# related to cryptographic signing.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_NEW_STATE': 5,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group failed to announce to the DHT. This indicates a network related error.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_NEW_ANNOUNCE': 6,
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_JOIN = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_JOIN_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group instance failed to initialize.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_JOIN_INIT': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The chat_id pointer is set to NULL or a group with chat_id already exists. This usually
|
|
||||||
# happens if the client attempts to create multiple sessions for the same group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_JOIN_BAD_CHAT_ID': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Password length exceeded TOX_GROUP_MAX_PASSWORD_SIZE.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_JOIN_TOO_LONG': 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_RECONNECT = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_RECONNECT_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_RECONNECT_GROUP_NOT_FOUND': 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_LEAVE = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_LEAVE_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_LEAVE_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Message length exceeded 'TOX_GROUP_MAX_PART_LENGTH.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_LEAVE_TOO_LONG': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The parting packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_LEAVE_FAIL_SEND': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group chat instance failed to be deleted. This may occur due to memory related errors.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_LEAVE_DELETE_FAIL': 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_SELF_QUERY = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_QUERY_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND': 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_SELF_NAME_SET = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_NAME_SET_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_NAME_SET_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Name length exceeded 'TOX_MAX_NAME_LENGTH.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_NAME_SET_TOO_LONG': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The length given to the set function is zero or name is a NULL pointer.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_NAME_SET_INVALID': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The name is already taken by another peer in the group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_NAME_SET_TAKEN': 4,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_NAME_SET_FAIL_SEND': 5
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_SELF_STATUS_SET = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_STATUS_SET_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_STATUS_SET_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# An invalid type was passed to the set function.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_STATUS_SET_INVALID': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SELF_STATUS_SET_FAIL_SEND': 3
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_PEER_QUERY = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_PEER_QUERY_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The ID passed did not designate a valid peer.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND': 2
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_STATE_QUERIES = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_STATE_QUERIES_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND': 1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_TOPIC_SET = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_TOPIC_SET_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_TOPIC_SET_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Topic length exceeded 'TOX_GROUP_MAX_TOPIC_LENGTH.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_TOPIC_SET_TOO_LONG': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions to set the topic.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The packet could not be created. This error is usually related to cryptographic signing.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE': 4,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_TOPIC_SET_FAIL_SEND': 5
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_SEND_MESSAGE = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_MESSAGE_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_MESSAGE_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Message length exceeded 'TOX_MAX_MESSAGE_LENGTH.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The message pointer is null or length is zero.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_MESSAGE_EMPTY': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The message type is invalid.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_MESSAGE_BAD_TYPE': 4,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions to send group messages.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS': 5,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_MESSAGE_FAIL_SEND': 6
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The ID passed did not designate a valid peer.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Message length exceeded 'TOX_MAX_MESSAGE_LENGTH.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The message pointer is null or length is zero.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY': 4,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions to send group messages.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS': 5,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND': 6
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_SEND_CUSTOM_PACKET = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Message length exceeded 'TOX_MAX_MESSAGE_LENGTH.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The message pointer is null or length is zero.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions to send group messages.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS': 4
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_INVITE_FRIEND = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_INVITE_FRIEND_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_INVITE_FRIEND_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The friend number passed did not designate a valid friend.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Creation of the invite packet failed. This indicates a network related error.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_INVITE_FRIEND_FAIL_SEND': 4
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_INVITE_ACCEPT = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_INVITE_ACCEPT_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The invite data is not in the expected format.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_INVITE_ACCEPT_BAD_INVITE': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group instance failed to initialize.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_INVITE_ACCEPT_INIT_FAILED': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Password length exceeded 'TOX_GROUP_MAX_PASSWORD_SIZE.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG': 3
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_GROUP_JOIN_FAIL = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# You are using the same nickname as someone who is already in the group.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_JOIN_FAIL_NAME_TAKEN': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group peer limit has been reached.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_JOIN_FAIL_PEER_LIMIT': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# You have supplied an invalid password.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The join attempt failed due to an unspecified error. This often occurs when the group is
|
|
||||||
# not found in the DHT.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_JOIN_FAIL_UNKNOWN': 3
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_FOUNDER_SET_PASSWORD = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions to set the password.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# Password length exceeded 'TOX_GROUP_MAX_PASSWORD_SIZE.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND': 4
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# 'TOX_GROUP_PRIVACY_STATE is an invalid type.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_INVALID': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions to set the privacy state.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The privacy state could not be set. This may occur due to an error related to
|
|
||||||
# cryptographic signing of the new shared state.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET': 4,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND': 5
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions to set the peer limit.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The peer limit could not be set. This may occur due to an error related to
|
|
||||||
# cryptographic signing of the new shared state.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND': 4
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_TOGGLE_IGNORE = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_TOGGLE_IGNORE_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_TOGGLE_IGNORE_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The ID passed did not designate a valid peer.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_TOGGLE_IGNORE_PEER_NOT_FOUND': 2
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_MOD_SET_ROLE = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_SET_ROLE_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The ID passed did not designate a valid peer. Note: you cannot set your own role.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions for this action.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The role assignment is invalid. This will occur if you try to set a peer's role to
|
|
||||||
# the role they already have.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT': 4,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The role was not successfully set. This may occur if something goes wrong with role setting': ,
|
|
||||||
# or if the packet fails to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION': 5
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_MOD_REMOVE_PEER = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_PEER_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_PEER_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The ID passed did not designate a valid peer.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_PEER_PEER_NOT_FOUND': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions for this action.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_PEER_PERMISSIONS': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The peer could not be removed from the group.
|
|
||||||
#
|
|
||||||
# If a ban was set': , this error indicates that the ban entry could not be created.
|
|
||||||
# This is usually due to the peer's IP address already occurring in the ban list. It may also
|
|
||||||
# be due to the entry containing invalid peer information': , or a failure to cryptographically
|
|
||||||
# authenticate the entry.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_PEER_FAIL_ACTION': 4,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_PEER_FAIL_SEND': 5
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_MOD_REMOVE_BAN = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_BAN_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_BAN_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The caller does not have the required permissions for this action.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_BAN_PERMISSIONS': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The ban entry could not be removed. This may occur if ban_id does not designate
|
|
||||||
# a valid ban entry.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_ACTION': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The packet failed to send.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_SEND': 4
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_GROUP_MOD_EVENT = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# A peer has been kicked from the group.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_MOD_EVENT_KICK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# A peer has been banned from the group.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_MOD_EVENT_BAN': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# A peer as been given the observer role.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_MOD_EVENT_OBSERVER': 2,
|
|
||||||
|
|
||||||
#
|
|
||||||
# A peer has been given the user role.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_MOD_EVENT_USER': 3,
|
|
||||||
|
|
||||||
#
|
|
||||||
# A peer has been given the moderator role.
|
|
||||||
#
|
|
||||||
'TOX_GROUP_MOD_EVENT_MODERATOR': 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_ERR_GROUP_BAN_QUERY = {
|
|
||||||
|
|
||||||
#
|
|
||||||
# The function returned successfully.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_BAN_QUERY_OK': 0,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The group number passed did not designate a valid group.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_BAN_QUERY_GROUP_NOT_FOUND': 1,
|
|
||||||
|
|
||||||
#
|
|
||||||
# The ban_id does not designate a valid ban list entry.
|
|
||||||
#
|
|
||||||
'TOX_ERR_GROUP_BAN_QUERY_BAD_ID': 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
TOX_PUBLIC_KEY_SIZE = 32
|
TOX_PUBLIC_KEY_SIZE = 32
|
||||||
|
|
||||||
TOX_ADDRESS_SIZE = TOX_PUBLIC_KEY_SIZE + 6
|
TOX_ADDRESS_SIZE = TOX_PUBLIC_KEY_SIZE + 6
|
||||||
@ -919,18 +196,6 @@ TOX_MAX_FRIEND_REQUEST_LENGTH = 1016
|
|||||||
|
|
||||||
TOX_MAX_MESSAGE_LENGTH = 1372
|
TOX_MAX_MESSAGE_LENGTH = 1372
|
||||||
|
|
||||||
TOX_GROUP_MAX_TOPIC_LENGTH = 512
|
|
||||||
|
|
||||||
TOX_GROUP_MAX_PART_LENGTH = 128
|
|
||||||
|
|
||||||
TOX_GROUP_MAX_GROUP_NAME_LENGTH = 48
|
|
||||||
|
|
||||||
TOX_GROUP_MAX_PASSWORD_SIZE = 32
|
|
||||||
|
|
||||||
TOX_GROUP_CHAT_ID_SIZE = 32
|
|
||||||
|
|
||||||
TOX_GROUP_PEER_PUBLIC_KEY_SIZE = 32
|
|
||||||
|
|
||||||
TOX_MAX_NAME_LENGTH = 128
|
TOX_MAX_NAME_LENGTH = 128
|
||||||
|
|
||||||
TOX_MAX_STATUS_MESSAGE_LENGTH = 1007
|
TOX_MAX_STATUS_MESSAGE_LENGTH = 1007
|
||||||
|
@ -36,10 +36,9 @@ TOX_PASS_ENCRYPTION_EXTRA_LENGTH = 80
|
|||||||
|
|
||||||
class ToxEncryptSave(util.Singleton):
|
class ToxEncryptSave(util.Singleton):
|
||||||
|
|
||||||
libtoxencryptsave = libtox.LibToxEncryptSave()
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
self.libtoxencryptsave = libtox.LibToxEncryptSave()
|
||||||
self._passphrase = None
|
self._passphrase = None
|
||||||
|
|
||||||
def set_password(self, passphrase):
|
def set_password(self, passphrase):
|
||||||
|
@ -3,22 +3,22 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>AddContact</name>
|
<name>AddContact</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="70"/>
|
<location filename="menu.py" line="75"/>
|
||||||
<source>Add contact</source>
|
<source>Add contact</source>
|
||||||
<translation>Add contact</translation>
|
<translation>Add contact</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="72"/>
|
<location filename="menu.py" line="77"/>
|
||||||
<source>TOX ID:</source>
|
<source>TOX ID:</source>
|
||||||
<translation>TOX ID:</translation>
|
<translation>TOX ID:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="73"/>
|
<location filename="menu.py" line="78"/>
|
||||||
<source>Message:</source>
|
<source>Message:</source>
|
||||||
<translation>Message:</translation>
|
<translation>Message:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="74"/>
|
<location filename="menu.py" line="79"/>
|
||||||
<source>TOX ID or public key of contact</source>
|
<source>TOX ID or public key of contact</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -34,32 +34,32 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>Form</name>
|
<name>Form</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="71"/>
|
<location filename="menu.py" line="76"/>
|
||||||
<source>Send request</source>
|
<source>Send request</source>
|
||||||
<translation>Send request</translation>
|
<translation>Send request</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="334"/>
|
<location filename="menu.py" line="339"/>
|
||||||
<source>IPv6</source>
|
<source>IPv6</source>
|
||||||
<translation>IPv6</translation>
|
<translation>IPv6</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="335"/>
|
<location filename="menu.py" line="340"/>
|
||||||
<source>UDP</source>
|
<source>UDP</source>
|
||||||
<translation>UDP</translation>
|
<translation>UDP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="336"/>
|
<location filename="menu.py" line="341"/>
|
||||||
<source>Proxy</source>
|
<source>Proxy</source>
|
||||||
<translation>Proxy</translation>
|
<translation>Proxy</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="337"/>
|
<location filename="menu.py" line="342"/>
|
||||||
<source>IP:</source>
|
<source>IP:</source>
|
||||||
<translation>IP:</translation>
|
<translation>IP:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="338"/>
|
<location filename="menu.py" line="343"/>
|
||||||
<source>Port:</source>
|
<source>Port:</source>
|
||||||
<translation>Port:</translation>
|
<translation>Port:</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -69,12 +69,12 @@
|
|||||||
<translation type="obsolete">Online contacts</translation>
|
<translation type="obsolete">Online contacts</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="340"/>
|
<location filename="menu.py" line="345"/>
|
||||||
<source>HTTP</source>
|
<source>HTTP</source>
|
||||||
<translation>HTTP</translation>
|
<translation>HTTP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="342"/>
|
<location filename="menu.py" line="347"/>
|
||||||
<source>WARNING:
|
<source>WARNING:
|
||||||
using proxy with enabled UDP
|
using proxy with enabled UDP
|
||||||
can produce IP leak</source>
|
can produce IP leak</source>
|
||||||
@ -84,98 +84,98 @@ can produce IP leak</source>
|
|||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="101"/>
|
<location filename="mainscreen.py" line="104"/>
|
||||||
<source>Profile</source>
|
<source>Profile</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="107"/>
|
<location filename="mainscreen.py" line="110"/>
|
||||||
<source>Settings</source>
|
<source>Settings</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="359"/>
|
<location filename="mainscreen.py" line="364"/>
|
||||||
<source>About</source>
|
<source>About</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="100"/>
|
<location filename="mainscreen.py" line="103"/>
|
||||||
<source>Add contact</source>
|
<source>Add contact</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="102"/>
|
<location filename="mainscreen.py" line="105"/>
|
||||||
<source>Privacy</source>
|
<source>Privacy</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="103"/>
|
<location filename="mainscreen.py" line="106"/>
|
||||||
<source>Interface</source>
|
<source>Interface</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="104"/>
|
<location filename="mainscreen.py" line="107"/>
|
||||||
<source>Notifications</source>
|
<source>Notifications</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="105"/>
|
<location filename="mainscreen.py" line="108"/>
|
||||||
<source>Network</source>
|
<source>Network</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="106"/>
|
<location filename="mainscreen.py" line="109"/>
|
||||||
<source>About program</source>
|
<source>About program</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<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>User {} wants to add you to contact list. Message:
|
||||||
{}</source>
|
{}</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="755"/>
|
<location filename="profile.py" line="763"/>
|
||||||
<source>Friend request</source>
|
<source>Friend request</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="430"/>
|
<location filename="mainscreen.py" line="455"/>
|
||||||
<source>Choose file</source>
|
<source>Choose file</source>
|
||||||
<translation>Choose file</translation>
|
<translation>Choose file</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="493"/>
|
<location filename="mainscreen.py" line="518"/>
|
||||||
<source>Disallow auto accept</source>
|
<source>Disallow auto accept</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="494"/>
|
<location filename="mainscreen.py" line="519"/>
|
||||||
<source>Allow auto accept</source>
|
<source>Allow auto accept</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="496"/>
|
<location filename="mainscreen.py" line="521"/>
|
||||||
<source>Set alias</source>
|
<source>Set alias</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="497"/>
|
<location filename="mainscreen.py" line="522"/>
|
||||||
<source>Clear history</source>
|
<source>Clear history</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="504"/>
|
<location filename="mainscreen.py" line="529"/>
|
||||||
<source>Remove friend</source>
|
<source>Remove friend</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<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's name:</source>
|
<source>Enter new alias for friend {} or leave empty to use friend's name:</source>
|
||||||
<translation>Enter new alias for friend {} or leave empty to use friend's name:</translation>
|
<translation>Enter new alias for friend {} or leave empty to use friend's name:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="108"/>
|
<location filename="mainscreen.py" line="111"/>
|
||||||
<source>Audio</source>
|
<source>Audio</source>
|
||||||
<translation>Audio</translation>
|
<translation>Audio</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -185,24 +185,24 @@ can produce IP leak</source>
|
|||||||
<translation type="obsolete">Find contact</translation>
|
<translation type="obsolete">Find contact</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="725"/>
|
<location filename="profile.py" line="733"/>
|
||||||
<source>Friend added</source>
|
<source>Friend added</source>
|
||||||
<translation>Friend added</translation>
|
<translation>Friend added</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="360"/>
|
<location filename="mainscreen.py" line="365"/>
|
||||||
<source>Toxygen is Tox client written on Python.
|
<source>Toxygen is Tox client written on Python.
|
||||||
Version: </source>
|
Version: </source>
|
||||||
<translation>Toxygen is Tox client written on Python.
|
<translation>Toxygen is Tox client written on Python.
|
||||||
Version:</translation>
|
Version:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="726"/>
|
<location filename="profile.py" line="734"/>
|
||||||
<source>Friend added without sending friend request</source>
|
<source>Friend added without sending friend request</source>
|
||||||
<translation>Friend added without sending friend request</translation>
|
<translation>Friend added without sending friend request</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="list_items.py" line="486"/>
|
<location filename="list_items.py" line="495"/>
|
||||||
<source>Choose folder</source>
|
<source>Choose folder</source>
|
||||||
<translation>Choose folder</translation>
|
<translation>Choose folder</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -217,47 +217,47 @@ Version:</translation>
|
|||||||
<translation type="obsolete">Send file</translation>
|
<translation type="obsolete">Send file</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="110"/>
|
<location filename="mainscreen.py" line="113"/>
|
||||||
<source>Send message</source>
|
<source>Send message</source>
|
||||||
<translation>Send message</translation>
|
<translation>Send message</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="111"/>
|
<location filename="mainscreen.py" line="114"/>
|
||||||
<source>Start audio call with friend</source>
|
<source>Start audio call with friend</source>
|
||||||
<translation>Start audio call with friend</translation>
|
<translation>Start audio call with friend</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="509"/>
|
<location filename="mainscreen.py" line="534"/>
|
||||||
<source>Plugins</source>
|
<source>Plugins</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="96"/>
|
<location filename="mainscreen.py" line="99"/>
|
||||||
<source>List of plugins</source>
|
<source>List of plugins</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="109"/>
|
<location filename="mainscreen.py" line="112"/>
|
||||||
<source>Search</source>
|
<source>Search</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="113"/>
|
<location filename="mainscreen.py" line="116"/>
|
||||||
<source>All</source>
|
<source>All</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="114"/>
|
<location filename="mainscreen.py" line="117"/>
|
||||||
<source>Online</source>
|
<source>Online</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="505"/>
|
<location filename="mainscreen.py" line="530"/>
|
||||||
<source>Notes</source>
|
<source>Notes</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="527"/>
|
<location filename="mainscreen.py" line="552"/>
|
||||||
<source>Notes about user</source>
|
<source>Notes about user</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -307,7 +307,7 @@ Version:</translation>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="259"/>
|
<location filename="profile.py" line="261"/>
|
||||||
<source>User {} is now known as {}</source>
|
<source>User {} is now known as {}</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -317,35 +317,75 @@ Version:</translation>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="94"/>
|
<location filename="mainscreen.py" line="97"/>
|
||||||
<source>Lock</source>
|
<source>Lock</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="403"/>
|
<location filename="mainscreen.py" line="428"/>
|
||||||
<source>Cannot lock app</source>
|
<source>Cannot lock app</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="406"/>
|
<location filename="mainscreen.py" line="431"/>
|
||||||
<source>Error. Profile password is not set.</source>
|
<source>Error. Profile password is not set.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="499"/>
|
<location filename="mainscreen.py" line="524"/>
|
||||||
<source>Name</source>
|
<source>Name</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="500"/>
|
<location filename="mainscreen.py" line="525"/>
|
||||||
<source>Status message</source>
|
<source>Status message</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="501"/>
|
<location filename="mainscreen.py" line="526"/>
|
||||||
<source>Public key</source>
|
<source>Public key</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</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>
|
||||||
<context>
|
<context>
|
||||||
<name>MenuWindow</name>
|
<name>MenuWindow</name>
|
||||||
@ -398,12 +438,12 @@ Version:</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>NetworkSettings</name>
|
<name>NetworkSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="333"/>
|
<location filename="menu.py" line="338"/>
|
||||||
<source>Network settings</source>
|
<source>Network settings</source>
|
||||||
<translation>Network settings</translation>
|
<translation>Network settings</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="339"/>
|
<location filename="menu.py" line="344"/>
|
||||||
<source>Restart TOX core</source>
|
<source>Restart TOX core</source>
|
||||||
<translation>Restart Tox core</translation>
|
<translation>Restart Tox core</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -411,12 +451,12 @@ Version:</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>PluginWindow</name>
|
<name>PluginWindow</name>
|
||||||
<message>
|
<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>
|
<source>List of commands for plugin {}</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>No commands available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -424,42 +464,42 @@ Version:</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>PluginsForm</name>
|
<name>PluginsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="761"/>
|
<location filename="menu.py" line="812"/>
|
||||||
<source>Plugins</source>
|
<source>Plugins</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="762"/>
|
<location filename="menu.py" line="813"/>
|
||||||
<source>Open selected plugin</source>
|
<source>Open selected plugin</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="775"/>
|
<location filename="menu.py" line="826"/>
|
||||||
<source>No GUI found for this plugin</source>
|
<source>No GUI found for this plugin</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="791"/>
|
<location filename="menu.py" line="842"/>
|
||||||
<source>No description available</source>
|
<source>No description available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="807"/>
|
<location filename="menu.py" line="858"/>
|
||||||
<source>Disable plugin</source>
|
<source>Disable plugin</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="809"/>
|
<location filename="menu.py" line="860"/>
|
||||||
<source>Enable plugin</source>
|
<source>Enable plugin</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="799"/>
|
<location filename="menu.py" line="850"/>
|
||||||
<source>No plugins found</source>
|
<source>No plugins found</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="776"/>
|
<location filename="menu.py" line="827"/>
|
||||||
<source>Error</source>
|
<source>Error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -467,122 +507,122 @@ Version:</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>ProfileSettingsForm</name>
|
<name>ProfileSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="169"/>
|
<location filename="menu.py" line="174"/>
|
||||||
<source>Export profile</source>
|
<source>Export profile</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="170"/>
|
<location filename="menu.py" line="175"/>
|
||||||
<source>Profile settings</source>
|
<source>Profile settings</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="171"/>
|
<location filename="menu.py" line="176"/>
|
||||||
<source>Name:</source>
|
<source>Name:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="172"/>
|
<location filename="menu.py" line="177"/>
|
||||||
<source>Status:</source>
|
<source>Status:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="173"/>
|
<location filename="menu.py" line="178"/>
|
||||||
<source>TOX ID:</source>
|
<source>TOX ID:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="174"/>
|
<location filename="menu.py" line="179"/>
|
||||||
<source>Copy TOX ID</source>
|
<source>Copy TOX ID</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="175"/>
|
<location filename="menu.py" line="180"/>
|
||||||
<source>New avatar</source>
|
<source>New avatar</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="176"/>
|
<location filename="menu.py" line="181"/>
|
||||||
<source>Reset avatar</source>
|
<source>Reset avatar</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="177"/>
|
<location filename="menu.py" line="182"/>
|
||||||
<source>New NoSpam</source>
|
<source>New NoSpam</source>
|
||||||
<translation>New NoSpam</translation>
|
<translation>New NoSpam</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="178"/>
|
<location filename="menu.py" line="183"/>
|
||||||
<source>Profile password</source>
|
<source>Profile password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="179"/>
|
<location filename="menu.py" line="184"/>
|
||||||
<source>Password (at least 8 symbols)</source>
|
<source>Password (at least 8 symbols)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="180"/>
|
<location filename="menu.py" line="185"/>
|
||||||
<source>Confirm password</source>
|
<source>Confirm password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="181"/>
|
<location filename="menu.py" line="186"/>
|
||||||
<source>Set password</source>
|
<source>Set password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="221"/>
|
<location filename="menu.py" line="226"/>
|
||||||
<source>Passwords do not match</source>
|
<source>Passwords do not match</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="183"/>
|
<location filename="menu.py" line="188"/>
|
||||||
<source>Leaving blank will reset current password</source>
|
<source>Leaving blank will reset current password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="184"/>
|
<location filename="menu.py" line="189"/>
|
||||||
<source>There is no way to recover lost passwords</source>
|
<source>There is no way to recover lost passwords</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="217"/>
|
<location filename="menu.py" line="222"/>
|
||||||
<source>Password must be at least 8 symbols</source>
|
<source>Password must be at least 8 symbols</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="250"/>
|
<location filename="menu.py" line="255"/>
|
||||||
<source>Choose avatar</source>
|
<source>Choose avatar</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="185"/>
|
<location filename="menu.py" line="190"/>
|
||||||
<source>Online</source>
|
<source>Online</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="186"/>
|
<location filename="menu.py" line="191"/>
|
||||||
<source>Away</source>
|
<source>Away</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="187"/>
|
<location filename="menu.py" line="192"/>
|
||||||
<source>Busy</source>
|
<source>Busy</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="202"/>
|
<location filename="menu.py" line="207"/>
|
||||||
<source>Mark as not default profile</source>
|
<source>Mark as not default profile</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="206"/>
|
<location filename="menu.py" line="211"/>
|
||||||
<source>Mark as default profile</source>
|
<source>Mark as default profile</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="188"/>
|
<location filename="menu.py" line="193"/>
|
||||||
<source>Copy public key</source>
|
<source>Copy public key</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -619,11 +659,6 @@ Version:</translation>
|
|||||||
<source>Since v0.1.3 Toxygen supports plugins. <a href="https://github.com/xveduk/toxygen/blob/master/docs/plugins.md">Read more</a></source>
|
<source>Since v0.1.3 Toxygen supports plugins. <a href="https://github.com/xveduk/toxygen/blob/master/docs/plugins.md">Read more</a></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="mainscreen_widgets.py" line="361"/>
|
|
||||||
<source>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</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen_widgets.py" line="341"/>
|
<location filename="mainscreen_widgets.py" line="341"/>
|
||||||
<source>Right click on screenshot button hides app to tray during screenshot.</source>
|
<source>Right click on screenshot button hides app to tray during screenshot.</source>
|
||||||
@ -640,25 +675,40 @@ Version:</translation>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<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 -> Settings -> Set new NoSpam.</source>
|
<source>Set new NoSpam to avoid spam friend requests: Profile -> Settings -> Set new NoSpam.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen_widgets.py" line="361"/>
|
||||||
|
<source>New in Toxygen v0.2.3:<br>TCS compliance<br>Plugins, smileys and stickers import<br>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 "Delete" 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>
|
||||||
<context>
|
<context>
|
||||||
<name>audioSettingsForm</name>
|
<name>audioSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="718"/>
|
<location filename="menu.py" line="769"/>
|
||||||
<source>Audio settings</source>
|
<source>Audio settings</source>
|
||||||
<translation>Audio settings</translation>
|
<translation>Audio settings</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="719"/>
|
<location filename="menu.py" line="770"/>
|
||||||
<source>Input device:</source>
|
<source>Input device:</source>
|
||||||
<translation>Input device:</translation>
|
<translation>Input device:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="720"/>
|
<location filename="menu.py" line="771"/>
|
||||||
<source>Output device:</source>
|
<source>Output device:</source>
|
||||||
<translation>Output device:</translation>
|
<translation>Output device:</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -666,32 +716,32 @@ Version:</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>incoming_call</name>
|
<name>incoming_call</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1132"/>
|
<location filename="profile.py" line="1141"/>
|
||||||
<source>Incoming video call</source>
|
<source>Incoming video call</source>
|
||||||
<translation>Incoming video call</translation>
|
<translation>Incoming video call</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1135"/>
|
<location filename="profile.py" line="1144"/>
|
||||||
<source>Incoming audio call</source>
|
<source>Incoming audio call</source>
|
||||||
<translation>Incoming audio call</translation>
|
<translation>Incoming audio call</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1115"/>
|
<location filename="profile.py" line="1124"/>
|
||||||
<source>Outgoing video call</source>
|
<source>Outgoing video call</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1118"/>
|
<location filename="profile.py" line="1127"/>
|
||||||
<source>Outgoing audio call</source>
|
<source>Outgoing audio call</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1164"/>
|
<location filename="profile.py" line="1173"/>
|
||||||
<source>Call declined</source>
|
<source>Call declined</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1166"/>
|
<location filename="profile.py" line="1175"/>
|
||||||
<source>Call finished</source>
|
<source>Call finished</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -699,60 +749,75 @@ Version:</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>interfaceForm</name>
|
<name>interfaceForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="619"/>
|
<location filename="menu.py" line="637"/>
|
||||||
<source>Interface settings</source>
|
<source>Interface settings</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="620"/>
|
<location filename="menu.py" line="638"/>
|
||||||
<source>Theme:</source>
|
<source>Theme:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="621"/>
|
<location filename="menu.py" line="639"/>
|
||||||
<source>Language:</source>
|
<source>Language:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="622"/>
|
<location filename="menu.py" line="640"/>
|
||||||
<source>Smileys</source>
|
<source>Smileys</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="623"/>
|
<location filename="menu.py" line="641"/>
|
||||||
<source>Smiley pack:</source>
|
<source>Smiley pack:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="624"/>
|
<location filename="menu.py" line="642"/>
|
||||||
<source>Mirror mode</source>
|
<source>Mirror mode</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="625"/>
|
<location filename="menu.py" line="643"/>
|
||||||
<source>Messages font size:</source>
|
<source>Messages font size:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="667"/>
|
<location filename="menu.py" line="718"/>
|
||||||
<source>Restart app to apply settings</source>
|
<source>Restart app to apply settings</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="668"/>
|
<location filename="menu.py" line="719"/>
|
||||||
<source>Restart required</source>
|
<source>Restart required</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="626"/>
|
<location filename="menu.py" line="644"/>
|
||||||
<source>Select unread messages notification color</source>
|
<source>Select unread messages notification color</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="627"/>
|
<location filename="menu.py" line="645"/>
|
||||||
<source>Compact contact list</source>
|
<source>Compact contact list</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</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>
|
||||||
<context>
|
<context>
|
||||||
<name>login</name>
|
<name>login</name>
|
||||||
@ -802,30 +867,35 @@ Version:</translation>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>Other instance of Toxygen uses this profile or profile was not properly closed. Continue?</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="main.py" line="120"/>
|
||||||
|
<source>Do you want to set profile password?</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>notificationsForm</name>
|
<name>notificationsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="530"/>
|
<location filename="menu.py" line="535"/>
|
||||||
<source>Notification settings</source>
|
<source>Notification settings</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="531"/>
|
<location filename="menu.py" line="536"/>
|
||||||
<source>Enable notifications</source>
|
<source>Enable notifications</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="532"/>
|
<location filename="menu.py" line="537"/>
|
||||||
<source>Enable call's sound</source>
|
<source>Enable call's sound</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="533"/>
|
<location filename="menu.py" line="538"/>
|
||||||
<source>Enable sound notifications</source>
|
<source>Enable sound notifications</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -833,72 +903,72 @@ Version:</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>privacySettings</name>
|
<name>privacySettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="426"/>
|
<location filename="menu.py" line="431"/>
|
||||||
<source>Privacy settings</source>
|
<source>Privacy settings</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="427"/>
|
<location filename="menu.py" line="432"/>
|
||||||
<source>Save chat history</source>
|
<source>Save chat history</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="428"/>
|
<location filename="menu.py" line="433"/>
|
||||||
<source>Allow file auto accept</source>
|
<source>Allow file auto accept</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="429"/>
|
<location filename="menu.py" line="434"/>
|
||||||
<source>Send typing notifications</source>
|
<source>Send typing notifications</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="430"/>
|
<location filename="menu.py" line="435"/>
|
||||||
<source>Auto accept default path:</source>
|
<source>Auto accept default path:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="431"/>
|
<location filename="menu.py" line="436"/>
|
||||||
<source>Change</source>
|
<source>Change</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="432"/>
|
<location filename="menu.py" line="437"/>
|
||||||
<source>Allow inlines</source>
|
<source>Allow inlines</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="477"/>
|
<location filename="menu.py" line="482"/>
|
||||||
<source>Chat history</source>
|
<source>Chat history</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="480"/>
|
<location filename="menu.py" line="485"/>
|
||||||
<source>History will be cleaned! Continue?</source>
|
<source>History will be cleaned! Continue?</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="434"/>
|
<location filename="menu.py" line="439"/>
|
||||||
<source>Blocked users:</source>
|
<source>Blocked users:</source>
|
||||||
<translation>Blocked users:</translation>
|
<translation>Blocked users:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="435"/>
|
<location filename="menu.py" line="440"/>
|
||||||
<source>Unblock</source>
|
<source>Unblock</source>
|
||||||
<translation>Unblock</translation>
|
<translation>Unblock</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="436"/>
|
<location filename="menu.py" line="441"/>
|
||||||
<source>Block user</source>
|
<source>Block user</source>
|
||||||
<translation>Block user</translation>
|
<translation>Block user</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="448"/>
|
<location filename="menu.py" line="453"/>
|
||||||
<source>Add to friend list</source>
|
<source>Add to friend list</source>
|
||||||
<translation>Add to friend list</translation>
|
<translation>Add to friend list</translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>Do you want to add this user to friend list?</source>
|
||||||
<translation>Do you want to add this user to friend list?</translation>
|
<translation>Do you want to add this user to friend list?</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -908,12 +978,12 @@ Version:</translation>
|
|||||||
<translation type="obsolete">Block by TOX ID:</translation>
|
<translation type="obsolete">Block by TOX ID:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="433"/>
|
<location filename="menu.py" line="438"/>
|
||||||
<source>Block by public key:</source>
|
<source>Block by public key:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="437"/>
|
<location filename="menu.py" line="442"/>
|
||||||
<source>Save unsent messages only</source>
|
<source>Save unsent messages only</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -921,32 +991,32 @@ Version:</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>tray</name>
|
<name>tray</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="176"/>
|
<location filename="main.py" line="203"/>
|
||||||
<source>Open Toxygen</source>
|
<source>Open Toxygen</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="185"/>
|
<location filename="main.py" line="212"/>
|
||||||
<source>Exit</source>
|
<source>Exit</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="177"/>
|
<location filename="main.py" line="204"/>
|
||||||
<source>Set status</source>
|
<source>Set status</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="178"/>
|
<location filename="main.py" line="205"/>
|
||||||
<source>Online</source>
|
<source>Online</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="179"/>
|
<location filename="main.py" line="206"/>
|
||||||
<source>Away</source>
|
<source>Away</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="180"/>
|
<location filename="main.py" line="207"/>
|
||||||
<source>Busy</source>
|
<source>Busy</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -3,22 +3,22 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>AddContact</name>
|
<name>AddContact</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="70"/>
|
<location filename="menu.py" line="75"/>
|
||||||
<source>Add contact</source>
|
<source>Add contact</source>
|
||||||
<translation>Rajouter un contact</translation>
|
<translation>Rajouter un contact</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="72"/>
|
<location filename="menu.py" line="77"/>
|
||||||
<source>TOX ID:</source>
|
<source>TOX ID:</source>
|
||||||
<translation>ID TOX :</translation>
|
<translation>ID TOX :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="73"/>
|
<location filename="menu.py" line="78"/>
|
||||||
<source>Message:</source>
|
<source>Message:</source>
|
||||||
<translation>Message :</translation>
|
<translation>Message :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="74"/>
|
<location filename="menu.py" line="79"/>
|
||||||
<source>TOX ID or public key of contact</source>
|
<source>TOX ID or public key of contact</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -34,32 +34,32 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>Form</name>
|
<name>Form</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="71"/>
|
<location filename="menu.py" line="76"/>
|
||||||
<source>Send request</source>
|
<source>Send request</source>
|
||||||
<translation>Envoyer une demande</translation>
|
<translation>Envoyer une demande</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="334"/>
|
<location filename="menu.py" line="339"/>
|
||||||
<source>IPv6</source>
|
<source>IPv6</source>
|
||||||
<translation>IPv6</translation>
|
<translation>IPv6</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="335"/>
|
<location filename="menu.py" line="340"/>
|
||||||
<source>UDP</source>
|
<source>UDP</source>
|
||||||
<translation>UDP</translation>
|
<translation>UDP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="336"/>
|
<location filename="menu.py" line="341"/>
|
||||||
<source>Proxy</source>
|
<source>Proxy</source>
|
||||||
<translation>Proxy</translation>
|
<translation>Proxy</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="337"/>
|
<location filename="menu.py" line="342"/>
|
||||||
<source>IP:</source>
|
<source>IP:</source>
|
||||||
<translation>IP :</translation>
|
<translation>IP :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="338"/>
|
<location filename="menu.py" line="343"/>
|
||||||
<source>Port:</source>
|
<source>Port:</source>
|
||||||
<translation>Port :</translation>
|
<translation>Port :</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -69,12 +69,12 @@
|
|||||||
<translation type="obsolete">Contacts connectés</translation>
|
<translation type="obsolete">Contacts connectés</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="340"/>
|
<location filename="menu.py" line="345"/>
|
||||||
<source>HTTP</source>
|
<source>HTTP</source>
|
||||||
<translation>HTTP</translation>
|
<translation>HTTP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="342"/>
|
<location filename="menu.py" line="347"/>
|
||||||
<source>WARNING:
|
<source>WARNING:
|
||||||
using proxy with enabled UDP
|
using proxy with enabled UDP
|
||||||
can produce IP leak</source>
|
can produce IP leak</source>
|
||||||
@ -84,58 +84,58 @@ can produce IP leak</source>
|
|||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="101"/>
|
<location filename="mainscreen.py" line="104"/>
|
||||||
<source>Profile</source>
|
<source>Profile</source>
|
||||||
<translation>Profile</translation>
|
<translation>Profile</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="107"/>
|
<location filename="mainscreen.py" line="110"/>
|
||||||
<source>Settings</source>
|
<source>Settings</source>
|
||||||
<translation>Paramêtres</translation>
|
<translation>Paramêtres</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="359"/>
|
<location filename="mainscreen.py" line="364"/>
|
||||||
<source>About</source>
|
<source>About</source>
|
||||||
<translation>À Propos</translation>
|
<translation>À Propos</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="100"/>
|
<location filename="mainscreen.py" line="103"/>
|
||||||
<source>Add contact</source>
|
<source>Add contact</source>
|
||||||
<translation>Rajouter un contact</translation>
|
<translation>Rajouter un contact</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="102"/>
|
<location filename="mainscreen.py" line="105"/>
|
||||||
<source>Privacy</source>
|
<source>Privacy</source>
|
||||||
<translation>Confidentialité</translation>
|
<translation>Confidentialité</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="103"/>
|
<location filename="mainscreen.py" line="106"/>
|
||||||
<source>Interface</source>
|
<source>Interface</source>
|
||||||
<translation>Interface</translation>
|
<translation>Interface</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="104"/>
|
<location filename="mainscreen.py" line="107"/>
|
||||||
<source>Notifications</source>
|
<source>Notifications</source>
|
||||||
<translation>Notifications</translation>
|
<translation>Notifications</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="105"/>
|
<location filename="mainscreen.py" line="108"/>
|
||||||
<source>Network</source>
|
<source>Network</source>
|
||||||
<translation>Réseau</translation>
|
<translation>Réseau</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="106"/>
|
<location filename="mainscreen.py" line="109"/>
|
||||||
<source>About program</source>
|
<source>About program</source>
|
||||||
<translation>À propos du programme</translation>
|
<translation>À propos du programme</translation>
|
||||||
</message>
|
</message>
|
||||||
<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>User {} wants to add you to contact list. Message:
|
||||||
{}</source>
|
{}</source>
|
||||||
<translation>L'Utilisateur {} veut vout rajouter à sa liste de contacts. Message : {}</translation>
|
<translation>L'Utilisateur {} veut vout rajouter à sa liste de contacts. Message : {}</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="755"/>
|
<location filename="profile.py" line="763"/>
|
||||||
<source>Friend request</source>
|
<source>Friend request</source>
|
||||||
<translation>Demande d'amis</translation>
|
<translation>Demande d'amis</translation>
|
||||||
</message>
|
</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>
|
<translation type="obsolete">Toxygen est un client Tox écris en Python 2.7. Version : </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="430"/>
|
<location filename="mainscreen.py" line="455"/>
|
||||||
<source>Choose file</source>
|
<source>Choose file</source>
|
||||||
<translation>Choisir un fichier</translation>
|
<translation>Choisir un fichier</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="493"/>
|
<location filename="mainscreen.py" line="518"/>
|
||||||
<source>Disallow auto accept</source>
|
<source>Disallow auto accept</source>
|
||||||
<translation>Désactiver l'auto-réception</translation>
|
<translation>Désactiver l'auto-réception</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="494"/>
|
<location filename="mainscreen.py" line="519"/>
|
||||||
<source>Allow auto accept</source>
|
<source>Allow auto accept</source>
|
||||||
<translation>Activer l'auto-réception</translation>
|
<translation>Activer l'auto-réception</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="496"/>
|
<location filename="mainscreen.py" line="521"/>
|
||||||
<source>Set alias</source>
|
<source>Set alias</source>
|
||||||
<translation>Définir un alias</translation>
|
<translation>Définir un alias</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="497"/>
|
<location filename="mainscreen.py" line="522"/>
|
||||||
<source>Clear history</source>
|
<source>Clear history</source>
|
||||||
<translation>Vider l'historique</translation>
|
<translation>Vider l'historique</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -175,17 +175,17 @@ can produce IP leak</source>
|
|||||||
<translation type="obsolete">Copier la clé publique</translation>
|
<translation type="obsolete">Copier la clé publique</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="504"/>
|
<location filename="mainscreen.py" line="529"/>
|
||||||
<source>Remove friend</source>
|
<source>Remove friend</source>
|
||||||
<translation>Retirer un ami</translation>
|
<translation>Retirer un ami</translation>
|
||||||
</message>
|
</message>
|
||||||
<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's name:</source>
|
<source>Enter new alias for friend {} or leave empty to use friend's name:</source>
|
||||||
<translation>Entrez un nouvel alias pour l'ami {} ou laissez vide pour garder son nom de base :</translation>
|
<translation>Entrez un nouvel alias pour l'ami {} ou laissez vide pour garder son nom de base :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="108"/>
|
<location filename="mainscreen.py" line="111"/>
|
||||||
<source>Audio</source>
|
<source>Audio</source>
|
||||||
<translation>Audio</translation>
|
<translation>Audio</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -195,24 +195,24 @@ can produce IP leak</source>
|
|||||||
<translation type="obsolete">Trouver le contact</translation>
|
<translation type="obsolete">Trouver le contact</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="725"/>
|
<location filename="profile.py" line="733"/>
|
||||||
<source>Friend added</source>
|
<source>Friend added</source>
|
||||||
<translation>Ami rajouté</translation>
|
<translation>Ami rajouté</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="360"/>
|
<location filename="mainscreen.py" line="365"/>
|
||||||
<source>Toxygen is Tox client written on Python.
|
<source>Toxygen is Tox client written on Python.
|
||||||
Version: </source>
|
Version: </source>
|
||||||
<translation>Toxygen est un client Tox écrit en Python.
|
<translation>Toxygen est un client Tox écrit en Python.
|
||||||
Version :</translation>
|
Version :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="726"/>
|
<location filename="profile.py" line="734"/>
|
||||||
<source>Friend added without sending friend request</source>
|
<source>Friend added without sending friend request</source>
|
||||||
<translation>Ami rajouté sans avoir envoyé de demande</translation>
|
<translation>Ami rajouté sans avoir envoyé de demande</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="list_items.py" line="486"/>
|
<location filename="list_items.py" line="495"/>
|
||||||
<source>Choose folder</source>
|
<source>Choose folder</source>
|
||||||
<translation>Choisir le dossier</translation>
|
<translation>Choisir le dossier</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -227,47 +227,47 @@ Version :</translation>
|
|||||||
<translation type="obsolete">Envoyer le fichier</translation>
|
<translation type="obsolete">Envoyer le fichier</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="110"/>
|
<location filename="mainscreen.py" line="113"/>
|
||||||
<source>Send message</source>
|
<source>Send message</source>
|
||||||
<translation>Envoyer le message</translation>
|
<translation>Envoyer le message</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="111"/>
|
<location filename="mainscreen.py" line="114"/>
|
||||||
<source>Start audio call with friend</source>
|
<source>Start audio call with friend</source>
|
||||||
<translation>Lancer un appel audio avec un ami</translation>
|
<translation>Lancer un appel audio avec un ami</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="509"/>
|
<location filename="mainscreen.py" line="534"/>
|
||||||
<source>Plugins</source>
|
<source>Plugins</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="96"/>
|
<location filename="mainscreen.py" line="99"/>
|
||||||
<source>List of plugins</source>
|
<source>List of plugins</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="109"/>
|
<location filename="mainscreen.py" line="112"/>
|
||||||
<source>Search</source>
|
<source>Search</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="113"/>
|
<location filename="mainscreen.py" line="116"/>
|
||||||
<source>All</source>
|
<source>All</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="114"/>
|
<location filename="mainscreen.py" line="117"/>
|
||||||
<source>Online</source>
|
<source>Online</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="505"/>
|
<location filename="mainscreen.py" line="530"/>
|
||||||
<source>Notes</source>
|
<source>Notes</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="527"/>
|
<location filename="mainscreen.py" line="552"/>
|
||||||
<source>Notes about user</source>
|
<source>Notes about user</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -317,7 +317,7 @@ Version :</translation>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="259"/>
|
<location filename="profile.py" line="261"/>
|
||||||
<source>User {} is now known as {}</source>
|
<source>User {} is now known as {}</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -327,35 +327,75 @@ Version :</translation>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="94"/>
|
<location filename="mainscreen.py" line="97"/>
|
||||||
<source>Lock</source>
|
<source>Lock</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="403"/>
|
<location filename="mainscreen.py" line="428"/>
|
||||||
<source>Cannot lock app</source>
|
<source>Cannot lock app</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="406"/>
|
<location filename="mainscreen.py" line="431"/>
|
||||||
<source>Error. Profile password is not set.</source>
|
<source>Error. Profile password is not set.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="499"/>
|
<location filename="mainscreen.py" line="524"/>
|
||||||
<source>Name</source>
|
<source>Name</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="500"/>
|
<location filename="mainscreen.py" line="525"/>
|
||||||
<source>Status message</source>
|
<source>Status message</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="501"/>
|
<location filename="mainscreen.py" line="526"/>
|
||||||
<source>Public key</source>
|
<source>Public key</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</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>
|
||||||
<context>
|
<context>
|
||||||
<name>MenuWindow</name>
|
<name>MenuWindow</name>
|
||||||
@ -408,12 +448,12 @@ Version :</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>NetworkSettings</name>
|
<name>NetworkSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="333"/>
|
<location filename="menu.py" line="338"/>
|
||||||
<source>Network settings</source>
|
<source>Network settings</source>
|
||||||
<translation>Paramètres réseaux</translation>
|
<translation>Paramètres réseaux</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="339"/>
|
<location filename="menu.py" line="344"/>
|
||||||
<source>Restart TOX core</source>
|
<source>Restart TOX core</source>
|
||||||
<translation>Relancer le noyau TOX</translation>
|
<translation>Relancer le noyau TOX</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -421,12 +461,12 @@ Version :</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>PluginWindow</name>
|
<name>PluginWindow</name>
|
||||||
<message>
|
<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>
|
<source>List of commands for plugin {}</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>No commands available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -434,42 +474,42 @@ Version :</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>PluginsForm</name>
|
<name>PluginsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="761"/>
|
<location filename="menu.py" line="812"/>
|
||||||
<source>Plugins</source>
|
<source>Plugins</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="762"/>
|
<location filename="menu.py" line="813"/>
|
||||||
<source>Open selected plugin</source>
|
<source>Open selected plugin</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="775"/>
|
<location filename="menu.py" line="826"/>
|
||||||
<source>No GUI found for this plugin</source>
|
<source>No GUI found for this plugin</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="791"/>
|
<location filename="menu.py" line="842"/>
|
||||||
<source>No description available</source>
|
<source>No description available</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="807"/>
|
<location filename="menu.py" line="858"/>
|
||||||
<source>Disable plugin</source>
|
<source>Disable plugin</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="809"/>
|
<location filename="menu.py" line="860"/>
|
||||||
<source>Enable plugin</source>
|
<source>Enable plugin</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="799"/>
|
<location filename="menu.py" line="850"/>
|
||||||
<source>No plugins found</source>
|
<source>No plugins found</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="776"/>
|
<location filename="menu.py" line="827"/>
|
||||||
<source>Error</source>
|
<source>Error</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -477,122 +517,122 @@ Version :</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>ProfileSettingsForm</name>
|
<name>ProfileSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="169"/>
|
<location filename="menu.py" line="174"/>
|
||||||
<source>Export profile</source>
|
<source>Export profile</source>
|
||||||
<translation>Exporter le profile</translation>
|
<translation>Exporter le profile</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="170"/>
|
<location filename="menu.py" line="175"/>
|
||||||
<source>Profile settings</source>
|
<source>Profile settings</source>
|
||||||
<translation>Paramêtres du profil</translation>
|
<translation>Paramêtres du profil</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="171"/>
|
<location filename="menu.py" line="176"/>
|
||||||
<source>Name:</source>
|
<source>Name:</source>
|
||||||
<translation>Nom :</translation>
|
<translation>Nom :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="172"/>
|
<location filename="menu.py" line="177"/>
|
||||||
<source>Status:</source>
|
<source>Status:</source>
|
||||||
<translation>Status :</translation>
|
<translation>Status :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="173"/>
|
<location filename="menu.py" line="178"/>
|
||||||
<source>TOX ID:</source>
|
<source>TOX ID:</source>
|
||||||
<translation>ID TOX :</translation>
|
<translation>ID TOX :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="174"/>
|
<location filename="menu.py" line="179"/>
|
||||||
<source>Copy TOX ID</source>
|
<source>Copy TOX ID</source>
|
||||||
<translation>Copier l'ID TOX</translation>
|
<translation>Copier l'ID TOX</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="175"/>
|
<location filename="menu.py" line="180"/>
|
||||||
<source>New avatar</source>
|
<source>New avatar</source>
|
||||||
<translation>Nouvel avatar</translation>
|
<translation>Nouvel avatar</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="176"/>
|
<location filename="menu.py" line="181"/>
|
||||||
<source>Reset avatar</source>
|
<source>Reset avatar</source>
|
||||||
<translation>Réinitialiser l'avatar</translation>
|
<translation>Réinitialiser l'avatar</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="177"/>
|
<location filename="menu.py" line="182"/>
|
||||||
<source>New NoSpam</source>
|
<source>New NoSpam</source>
|
||||||
<translation>Nouveau NoSpam</translation>
|
<translation>Nouveau NoSpam</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="178"/>
|
<location filename="menu.py" line="183"/>
|
||||||
<source>Profile password</source>
|
<source>Profile password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="179"/>
|
<location filename="menu.py" line="184"/>
|
||||||
<source>Password (at least 8 symbols)</source>
|
<source>Password (at least 8 symbols)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="180"/>
|
<location filename="menu.py" line="185"/>
|
||||||
<source>Confirm password</source>
|
<source>Confirm password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="181"/>
|
<location filename="menu.py" line="186"/>
|
||||||
<source>Set password</source>
|
<source>Set password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="221"/>
|
<location filename="menu.py" line="226"/>
|
||||||
<source>Passwords do not match</source>
|
<source>Passwords do not match</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="183"/>
|
<location filename="menu.py" line="188"/>
|
||||||
<source>Leaving blank will reset current password</source>
|
<source>Leaving blank will reset current password</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="184"/>
|
<location filename="menu.py" line="189"/>
|
||||||
<source>There is no way to recover lost passwords</source>
|
<source>There is no way to recover lost passwords</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="217"/>
|
<location filename="menu.py" line="222"/>
|
||||||
<source>Password must be at least 8 symbols</source>
|
<source>Password must be at least 8 symbols</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="250"/>
|
<location filename="menu.py" line="255"/>
|
||||||
<source>Choose avatar</source>
|
<source>Choose avatar</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="185"/>
|
<location filename="menu.py" line="190"/>
|
||||||
<source>Online</source>
|
<source>Online</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="186"/>
|
<location filename="menu.py" line="191"/>
|
||||||
<source>Away</source>
|
<source>Away</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="187"/>
|
<location filename="menu.py" line="192"/>
|
||||||
<source>Busy</source>
|
<source>Busy</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="202"/>
|
<location filename="menu.py" line="207"/>
|
||||||
<source>Mark as not default profile</source>
|
<source>Mark as not default profile</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="206"/>
|
<location filename="menu.py" line="211"/>
|
||||||
<source>Mark as default profile</source>
|
<source>Mark as default profile</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="188"/>
|
<location filename="menu.py" line="193"/>
|
||||||
<source>Copy public key</source>
|
<source>Copy public key</source>
|
||||||
<translation type="unfinished">Copier la clé publique</translation>
|
<translation type="unfinished">Copier la clé publique</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -629,11 +669,6 @@ Version :</translation>
|
|||||||
<source>Since v0.1.3 Toxygen supports plugins. <a href="https://github.com/xveduk/toxygen/blob/master/docs/plugins.md">Read more</a></source>
|
<source>Since v0.1.3 Toxygen supports plugins. <a href="https://github.com/xveduk/toxygen/blob/master/docs/plugins.md">Read more</a></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="mainscreen_widgets.py" line="361"/>
|
|
||||||
<source>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</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen_widgets.py" line="341"/>
|
<location filename="mainscreen_widgets.py" line="341"/>
|
||||||
<source>Right click on screenshot button hides app to tray during screenshot.</source>
|
<source>Right click on screenshot button hides app to tray during screenshot.</source>
|
||||||
@ -650,25 +685,40 @@ Version :</translation>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<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 -> Settings -> Set new NoSpam.</source>
|
<source>Set new NoSpam to avoid spam friend requests: Profile -> Settings -> Set new NoSpam.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen_widgets.py" line="361"/>
|
||||||
|
<source>New in Toxygen v0.2.3:<br>TCS compliance<br>Plugins, smileys and stickers import<br>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 "Delete" 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>
|
||||||
<context>
|
<context>
|
||||||
<name>audioSettingsForm</name>
|
<name>audioSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="718"/>
|
<location filename="menu.py" line="769"/>
|
||||||
<source>Audio settings</source>
|
<source>Audio settings</source>
|
||||||
<translation>Paramètres audio</translation>
|
<translation>Paramètres audio</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="719"/>
|
<location filename="menu.py" line="770"/>
|
||||||
<source>Input device:</source>
|
<source>Input device:</source>
|
||||||
<translation>Péripherique d'entrée :</translation>
|
<translation>Péripherique d'entrée :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="720"/>
|
<location filename="menu.py" line="771"/>
|
||||||
<source>Output device:</source>
|
<source>Output device:</source>
|
||||||
<translation>Péripherique de sortie :</translation>
|
<translation>Péripherique de sortie :</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -676,32 +726,32 @@ Version :</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>incoming_call</name>
|
<name>incoming_call</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1132"/>
|
<location filename="profile.py" line="1141"/>
|
||||||
<source>Incoming video call</source>
|
<source>Incoming video call</source>
|
||||||
<translation>Appel vidéo entrant</translation>
|
<translation>Appel vidéo entrant</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1135"/>
|
<location filename="profile.py" line="1144"/>
|
||||||
<source>Incoming audio call</source>
|
<source>Incoming audio call</source>
|
||||||
<translation>Appel audio entrant</translation>
|
<translation>Appel audio entrant</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1115"/>
|
<location filename="profile.py" line="1124"/>
|
||||||
<source>Outgoing video call</source>
|
<source>Outgoing video call</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1118"/>
|
<location filename="profile.py" line="1127"/>
|
||||||
<source>Outgoing audio call</source>
|
<source>Outgoing audio call</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1164"/>
|
<location filename="profile.py" line="1173"/>
|
||||||
<source>Call declined</source>
|
<source>Call declined</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1166"/>
|
<location filename="profile.py" line="1175"/>
|
||||||
<source>Call finished</source>
|
<source>Call finished</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -709,60 +759,75 @@ Version :</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>interfaceForm</name>
|
<name>interfaceForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="619"/>
|
<location filename="menu.py" line="637"/>
|
||||||
<source>Interface settings</source>
|
<source>Interface settings</source>
|
||||||
<translation>Paramêtres de l'interface</translation>
|
<translation>Paramêtres de l'interface</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="620"/>
|
<location filename="menu.py" line="638"/>
|
||||||
<source>Theme:</source>
|
<source>Theme:</source>
|
||||||
<translation>Thème :</translation>
|
<translation>Thème :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="621"/>
|
<location filename="menu.py" line="639"/>
|
||||||
<source>Language:</source>
|
<source>Language:</source>
|
||||||
<translation>Langue :</translation>
|
<translation>Langue :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="622"/>
|
<location filename="menu.py" line="640"/>
|
||||||
<source>Smileys</source>
|
<source>Smileys</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="623"/>
|
<location filename="menu.py" line="641"/>
|
||||||
<source>Smiley pack:</source>
|
<source>Smiley pack:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="624"/>
|
<location filename="menu.py" line="642"/>
|
||||||
<source>Mirror mode</source>
|
<source>Mirror mode</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="625"/>
|
<location filename="menu.py" line="643"/>
|
||||||
<source>Messages font size:</source>
|
<source>Messages font size:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="667"/>
|
<location filename="menu.py" line="718"/>
|
||||||
<source>Restart app to apply settings</source>
|
<source>Restart app to apply settings</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="668"/>
|
<location filename="menu.py" line="719"/>
|
||||||
<source>Restart required</source>
|
<source>Restart required</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="626"/>
|
<location filename="menu.py" line="644"/>
|
||||||
<source>Select unread messages notification color</source>
|
<source>Select unread messages notification color</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="627"/>
|
<location filename="menu.py" line="645"/>
|
||||||
<source>Compact contact list</source>
|
<source>Compact contact list</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</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>
|
||||||
<context>
|
<context>
|
||||||
<name>login</name>
|
<name>login</name>
|
||||||
@ -817,30 +882,35 @@ Version :</translation>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>Other instance of Toxygen uses this profile or profile was not properly closed. Continue?</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="main.py" line="120"/>
|
||||||
|
<source>Do you want to set profile password?</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>notificationsForm</name>
|
<name>notificationsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="530"/>
|
<location filename="menu.py" line="535"/>
|
||||||
<source>Notification settings</source>
|
<source>Notification settings</source>
|
||||||
<translation>Paramêtres de notification</translation>
|
<translation>Paramêtres de notification</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="531"/>
|
<location filename="menu.py" line="536"/>
|
||||||
<source>Enable notifications</source>
|
<source>Enable notifications</source>
|
||||||
<translation>Activer les notifications</translation>
|
<translation>Activer les notifications</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="532"/>
|
<location filename="menu.py" line="537"/>
|
||||||
<source>Enable call's sound</source>
|
<source>Enable call's sound</source>
|
||||||
<translation>Activer les sons d'appel</translation>
|
<translation>Activer les sons d'appel</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="533"/>
|
<location filename="menu.py" line="538"/>
|
||||||
<source>Enable sound notifications</source>
|
<source>Enable sound notifications</source>
|
||||||
<translation>Activer les sons de notifications</translation>
|
<translation>Activer les sons de notifications</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -848,72 +918,72 @@ Version :</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>privacySettings</name>
|
<name>privacySettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="426"/>
|
<location filename="menu.py" line="431"/>
|
||||||
<source>Privacy settings</source>
|
<source>Privacy settings</source>
|
||||||
<translation>Paramêtres de confidentialité</translation>
|
<translation>Paramêtres de confidentialité</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="427"/>
|
<location filename="menu.py" line="432"/>
|
||||||
<source>Save chat history</source>
|
<source>Save chat history</source>
|
||||||
<translation>Sauvegarder l'historique de chat</translation>
|
<translation>Sauvegarder l'historique de chat</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="428"/>
|
<location filename="menu.py" line="433"/>
|
||||||
<source>Allow file auto accept</source>
|
<source>Allow file auto accept</source>
|
||||||
<translation>Autoriser les fichier automatiquement</translation>
|
<translation>Autoriser les fichier automatiquement</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="429"/>
|
<location filename="menu.py" line="434"/>
|
||||||
<source>Send typing notifications</source>
|
<source>Send typing notifications</source>
|
||||||
<translation>Notifier la frappe</translation>
|
<translation>Notifier la frappe</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="430"/>
|
<location filename="menu.py" line="435"/>
|
||||||
<source>Auto accept default path:</source>
|
<source>Auto accept default path:</source>
|
||||||
<translation>Chemin d'accès des fichiers acceptés automatiquement :</translation>
|
<translation>Chemin d'accès des fichiers acceptés automatiquement :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="431"/>
|
<location filename="menu.py" line="436"/>
|
||||||
<source>Change</source>
|
<source>Change</source>
|
||||||
<translation>Modifier</translation>
|
<translation>Modifier</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="432"/>
|
<location filename="menu.py" line="437"/>
|
||||||
<source>Allow inlines</source>
|
<source>Allow inlines</source>
|
||||||
<translation>Activer l'auto-réception</translation>
|
<translation>Activer l'auto-réception</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="477"/>
|
<location filename="menu.py" line="482"/>
|
||||||
<source>Chat history</source>
|
<source>Chat history</source>
|
||||||
<translation>Historique de chat</translation>
|
<translation>Historique de chat</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="480"/>
|
<location filename="menu.py" line="485"/>
|
||||||
<source>History will be cleaned! Continue?</source>
|
<source>History will be cleaned! Continue?</source>
|
||||||
<translation>L'Historique va être nettoyé ! Confirmer ?</translation>
|
<translation>L'Historique va être nettoyé ! Confirmer ?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="434"/>
|
<location filename="menu.py" line="439"/>
|
||||||
<source>Blocked users:</source>
|
<source>Blocked users:</source>
|
||||||
<translation>Utilisateurs bloqués :</translation>
|
<translation>Utilisateurs bloqués :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="435"/>
|
<location filename="menu.py" line="440"/>
|
||||||
<source>Unblock</source>
|
<source>Unblock</source>
|
||||||
<translation>Débloquer</translation>
|
<translation>Débloquer</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="436"/>
|
<location filename="menu.py" line="441"/>
|
||||||
<source>Block user</source>
|
<source>Block user</source>
|
||||||
<translation>Bloquer l'utilisateur</translation>
|
<translation>Bloquer l'utilisateur</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="448"/>
|
<location filename="menu.py" line="453"/>
|
||||||
<source>Add to friend list</source>
|
<source>Add to friend list</source>
|
||||||
<translation>Ajouter à la liste des amis</translation>
|
<translation>Ajouter à la liste des amis</translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>Do you want to add this user to friend list?</source>
|
||||||
<translation>Voulez vous rajouter cet utilisateur à votre liste d'amis ?</translation>
|
<translation>Voulez vous rajouter cet utilisateur à votre liste d'amis ?</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -923,12 +993,12 @@ Version :</translation>
|
|||||||
<translation type="obsolete">Bloquer l'ID TOX :</translation>
|
<translation type="obsolete">Bloquer l'ID TOX :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="433"/>
|
<location filename="menu.py" line="438"/>
|
||||||
<source>Block by public key:</source>
|
<source>Block by public key:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="437"/>
|
<location filename="menu.py" line="442"/>
|
||||||
<source>Save unsent messages only</source>
|
<source>Save unsent messages only</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -936,32 +1006,32 @@ Version :</translation>
|
|||||||
<context>
|
<context>
|
||||||
<name>tray</name>
|
<name>tray</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="176"/>
|
<location filename="main.py" line="203"/>
|
||||||
<source>Open Toxygen</source>
|
<source>Open Toxygen</source>
|
||||||
<translation>Ouvrir Toxygen</translation>
|
<translation>Ouvrir Toxygen</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="185"/>
|
<location filename="main.py" line="212"/>
|
||||||
<source>Exit</source>
|
<source>Exit</source>
|
||||||
<translation>Quitter</translation>
|
<translation>Quitter</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="177"/>
|
<location filename="main.py" line="204"/>
|
||||||
<source>Set status</source>
|
<source>Set status</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="178"/>
|
<location filename="main.py" line="205"/>
|
||||||
<source>Online</source>
|
<source>Online</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="179"/>
|
<location filename="main.py" line="206"/>
|
||||||
<source>Away</source>
|
<source>Away</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="180"/>
|
<location filename="main.py" line="207"/>
|
||||||
<source>Busy</source>
|
<source>Busy</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -1,25 +1,24 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!DOCTYPE TS>
|
<!DOCTYPE TS><TS version="1.1" language="ru_RU">
|
||||||
<TS version="2.0" language="ru_RU">
|
|
||||||
<context>
|
<context>
|
||||||
<name>AddContact</name>
|
<name>AddContact</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="70"/>
|
<location filename="menu.py" line="75"/>
|
||||||
<source>Add contact</source>
|
<source>Add contact</source>
|
||||||
<translation>Добавить контакт</translation>
|
<translation>Добавить контакт</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="72"/>
|
<location filename="menu.py" line="77"/>
|
||||||
<source>TOX ID:</source>
|
<source>TOX ID:</source>
|
||||||
<translation>TOX ID:</translation>
|
<translation>TOX ID:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="73"/>
|
<location filename="menu.py" line="78"/>
|
||||||
<source>Message:</source>
|
<source>Message:</source>
|
||||||
<translation>Сообщение:</translation>
|
<translation>Сообщение:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="74"/>
|
<location filename="menu.py" line="79"/>
|
||||||
<source>TOX ID or public key of contact</source>
|
<source>TOX ID or public key of contact</source>
|
||||||
<translation>TOX ID или публичный ключ контакта</translation>
|
<translation>TOX ID или публичный ключ контакта</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -35,32 +34,32 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>Form</name>
|
<name>Form</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="71"/>
|
<location filename="menu.py" line="76"/>
|
||||||
<source>Send request</source>
|
<source>Send request</source>
|
||||||
<translation>Отправить запрос</translation>
|
<translation>Отправить запрос</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="334"/>
|
<location filename="menu.py" line="339"/>
|
||||||
<source>IPv6</source>
|
<source>IPv6</source>
|
||||||
<translation>IPv6</translation>
|
<translation>IPv6</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="335"/>
|
<location filename="menu.py" line="340"/>
|
||||||
<source>UDP</source>
|
<source>UDP</source>
|
||||||
<translation>UDP</translation>
|
<translation>UDP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="336"/>
|
<location filename="menu.py" line="341"/>
|
||||||
<source>Proxy</source>
|
<source>Proxy</source>
|
||||||
<translation>Прокси</translation>
|
<translation>Прокси</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="337"/>
|
<location filename="menu.py" line="342"/>
|
||||||
<source>IP:</source>
|
<source>IP:</source>
|
||||||
<translation>IP:</translation>
|
<translation>IP:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="338"/>
|
<location filename="menu.py" line="343"/>
|
||||||
<source>Port:</source>
|
<source>Port:</source>
|
||||||
<translation>Порт:</translation>
|
<translation>Порт:</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -70,12 +69,12 @@
|
|||||||
<translation type="obsolete">Контакты в сети</translation>
|
<translation type="obsolete">Контакты в сети</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="340"/>
|
<location filename="menu.py" line="345"/>
|
||||||
<source>HTTP</source>
|
<source>HTTP</source>
|
||||||
<translation>HTTP</translation>
|
<translation>HTTP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="342"/>
|
<location filename="menu.py" line="347"/>
|
||||||
<source>WARNING:
|
<source>WARNING:
|
||||||
using proxy with enabled UDP
|
using proxy with enabled UDP
|
||||||
can produce IP leak</source>
|
can produce IP leak</source>
|
||||||
@ -87,84 +86,84 @@ can produce IP leak</source>
|
|||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="101"/>
|
<location filename="mainscreen.py" line="104"/>
|
||||||
<source>Profile</source>
|
<source>Profile</source>
|
||||||
<translation>Профиль</translation>
|
<translation>Профиль</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="107"/>
|
<location filename="mainscreen.py" line="110"/>
|
||||||
<source>Settings</source>
|
<source>Settings</source>
|
||||||
<translation>Настройки</translation>
|
<translation>Настройки</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="359"/>
|
<location filename="mainscreen.py" line="364"/>
|
||||||
<source>About</source>
|
<source>About</source>
|
||||||
<translation>О программе</translation>
|
<translation>О программе</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="100"/>
|
<location filename="mainscreen.py" line="103"/>
|
||||||
<source>Add contact</source>
|
<source>Add contact</source>
|
||||||
<translation>Добавить контакт</translation>
|
<translation>Добавить контакт</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="102"/>
|
<location filename="mainscreen.py" line="105"/>
|
||||||
<source>Privacy</source>
|
<source>Privacy</source>
|
||||||
<translation>Приватность</translation>
|
<translation>Приватность</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="103"/>
|
<location filename="mainscreen.py" line="106"/>
|
||||||
<source>Interface</source>
|
<source>Interface</source>
|
||||||
<translation>Интерфейс</translation>
|
<translation>Интерфейс</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="104"/>
|
<location filename="mainscreen.py" line="107"/>
|
||||||
<source>Notifications</source>
|
<source>Notifications</source>
|
||||||
<translation>Уведомления</translation>
|
<translation>Уведомления</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="105"/>
|
<location filename="mainscreen.py" line="108"/>
|
||||||
<source>Network</source>
|
<source>Network</source>
|
||||||
<translation>Сеть</translation>
|
<translation>Сеть</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="106"/>
|
<location filename="mainscreen.py" line="109"/>
|
||||||
<source>About program</source>
|
<source>About program</source>
|
||||||
<translation>О программе</translation>
|
<translation>О программе</translation>
|
||||||
</message>
|
</message>
|
||||||
<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>User {} wants to add you to contact list. Message:
|
||||||
{}</source>
|
{}</source>
|
||||||
<translation>Пользователь {} хочет добавить Вас в список контактов. Сообщение:
|
<translation>Пользователь {} хочет добавить Вас в список контактов. Сообщение:
|
||||||
{}</translation>
|
{}</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="755"/>
|
<location filename="profile.py" line="763"/>
|
||||||
<source>Friend request</source>
|
<source>Friend request</source>
|
||||||
<translation>Запрос на добавление в друзья</translation>
|
<translation>Запрос на добавление в друзья</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="430"/>
|
<location filename="mainscreen.py" line="455"/>
|
||||||
<source>Choose file</source>
|
<source>Choose file</source>
|
||||||
<translation>Выберите файл</translation>
|
<translation>Выберите файл</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="493"/>
|
<location filename="mainscreen.py" line="518"/>
|
||||||
<source>Disallow auto accept</source>
|
<source>Disallow auto accept</source>
|
||||||
<translation>Запретить автоматическое получение файлов</translation>
|
<translation>Запретить автоматическое получение файлов</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="494"/>
|
<location filename="mainscreen.py" line="519"/>
|
||||||
<source>Allow auto accept</source>
|
<source>Allow auto accept</source>
|
||||||
<translation>Разрешить автоматическое получение файлов</translation>
|
<translation>Разрешить автоматическое получение файлов</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="496"/>
|
<location filename="mainscreen.py" line="521"/>
|
||||||
<source>Set alias</source>
|
<source>Set alias</source>
|
||||||
<translation>Изменить псевдоним</translation>
|
<translation>Изменить псевдоним</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="497"/>
|
<location filename="mainscreen.py" line="522"/>
|
||||||
<source>Clear history</source>
|
<source>Clear history</source>
|
||||||
<translation>Очистить историю</translation>
|
<translation>Очистить историю</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -174,17 +173,17 @@ can produce IP leak</source>
|
|||||||
<translation type="obsolete">Копировать публичный ключ</translation>
|
<translation type="obsolete">Копировать публичный ключ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="504"/>
|
<location filename="mainscreen.py" line="529"/>
|
||||||
<source>Remove friend</source>
|
<source>Remove friend</source>
|
||||||
<translation>Удалить друга</translation>
|
<translation>Удалить друга</translation>
|
||||||
</message>
|
</message>
|
||||||
<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's name:</source>
|
<source>Enter new alias for friend {} or leave empty to use friend's name:</source>
|
||||||
<translation>Введите новый псевдоним для друга {} или оставьте пустым для использования его имени:</translation>
|
<translation>Введите новый псевдоним для друга {} или оставьте пустым для использования его имени:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="108"/>
|
<location filename="mainscreen.py" line="111"/>
|
||||||
<source>Audio</source>
|
<source>Audio</source>
|
||||||
<translation>Аудио</translation>
|
<translation>Аудио</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -194,23 +193,23 @@ can produce IP leak</source>
|
|||||||
<translation type="obsolete">Найти контакт</translation>
|
<translation type="obsolete">Найти контакт</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="725"/>
|
<location filename="profile.py" line="733"/>
|
||||||
<source>Friend added</source>
|
<source>Friend added</source>
|
||||||
<translation>Друг добавлен</translation>
|
<translation>Друг добавлен</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="360"/>
|
<location filename="mainscreen.py" line="365"/>
|
||||||
<source>Toxygen is Tox client written on Python.
|
<source>Toxygen is Tox client written on Python.
|
||||||
Version: </source>
|
Version: </source>
|
||||||
<translation>Toxygen - клиент для мессенджера Tox, написанный на Python. Версия: </translation>
|
<translation>Toxygen - клиент для мессенджера Tox, написанный на Python. Версия: </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="726"/>
|
<location filename="profile.py" line="734"/>
|
||||||
<source>Friend added without sending friend request</source>
|
<source>Friend added without sending friend request</source>
|
||||||
<translation>Друг добавлен без отправки запроса на добавление в друзья</translation>
|
<translation>Друг добавлен без отправки запроса на добавление в друзья</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="list_items.py" line="486"/>
|
<location filename="list_items.py" line="495"/>
|
||||||
<source>Choose folder</source>
|
<source>Choose folder</source>
|
||||||
<translation>Выбрать папку</translation>
|
<translation>Выбрать папку</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -225,47 +224,47 @@ Version: </source>
|
|||||||
<translation type="obsolete">Отправить файл</translation>
|
<translation type="obsolete">Отправить файл</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="110"/>
|
<location filename="mainscreen.py" line="113"/>
|
||||||
<source>Send message</source>
|
<source>Send message</source>
|
||||||
<translation>Отправить сообщение</translation>
|
<translation>Отправить сообщение</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="111"/>
|
<location filename="mainscreen.py" line="114"/>
|
||||||
<source>Start audio call with friend</source>
|
<source>Start audio call with friend</source>
|
||||||
<translation>Начать аудиозвонок с другом</translation>
|
<translation>Начать аудиозвонок с другом</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="509"/>
|
<location filename="mainscreen.py" line="534"/>
|
||||||
<source>Plugins</source>
|
<source>Plugins</source>
|
||||||
<translation>Плагины</translation>
|
<translation>Плагины</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="96"/>
|
<location filename="mainscreen.py" line="99"/>
|
||||||
<source>List of plugins</source>
|
<source>List of plugins</source>
|
||||||
<translation>Список плагинов</translation>
|
<translation>Список плагинов</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="109"/>
|
<location filename="mainscreen.py" line="112"/>
|
||||||
<source>Search</source>
|
<source>Search</source>
|
||||||
<translation>Поиск</translation>
|
<translation>Поиск</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="113"/>
|
<location filename="mainscreen.py" line="116"/>
|
||||||
<source>All</source>
|
<source>All</source>
|
||||||
<translation>Все</translation>
|
<translation>Все</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="114"/>
|
<location filename="mainscreen.py" line="117"/>
|
||||||
<source>Online</source>
|
<source>Online</source>
|
||||||
<translation>Онлайн</translation>
|
<translation>Онлайн</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="505"/>
|
<location filename="mainscreen.py" line="530"/>
|
||||||
<source>Notes</source>
|
<source>Notes</source>
|
||||||
<translation>Заметки</translation>
|
<translation>Заметки</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="527"/>
|
<location filename="mainscreen.py" line="552"/>
|
||||||
<source>Notes about user</source>
|
<source>Notes about user</source>
|
||||||
<translation>Заметки о пользователе</translation>
|
<translation>Заметки о пользователе</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -315,7 +314,7 @@ Version: </source>
|
|||||||
<translation>Сохранить</translation>
|
<translation>Сохранить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="259"/>
|
<location filename="profile.py" line="261"/>
|
||||||
<source>User {} is now known as {}</source>
|
<source>User {} is now known as {}</source>
|
||||||
<translation>Пользователь {} сейчас известен как {}</translation>
|
<translation>Пользователь {} сейчас известен как {}</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -325,35 +324,75 @@ Version: </source>
|
|||||||
<translation>Удалить сообщение</translation>
|
<translation>Удалить сообщение</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="94"/>
|
<location filename="mainscreen.py" line="97"/>
|
||||||
<source>Lock</source>
|
<source>Lock</source>
|
||||||
<translation>Заблокировать</translation>
|
<translation>Заблокировать</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="403"/>
|
<location filename="mainscreen.py" line="428"/>
|
||||||
<source>Cannot lock app</source>
|
<source>Cannot lock app</source>
|
||||||
<translation>Невозможно заблокировать приложение</translation>
|
<translation>Невозможно заблокировать приложение</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="406"/>
|
<location filename="mainscreen.py" line="431"/>
|
||||||
<source>Error. Profile password is not set.</source>
|
<source>Error. Profile password is not set.</source>
|
||||||
<translation>Ошибка. Пароль профиля не установлен.</translation>
|
<translation>Ошибка. Пароль профиля не установлен.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="499"/>
|
<location filename="mainscreen.py" line="524"/>
|
||||||
<source>Name</source>
|
<source>Name</source>
|
||||||
<translation>Имя</translation>
|
<translation>Имя</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="500"/>
|
<location filename="mainscreen.py" line="525"/>
|
||||||
<source>Status message</source>
|
<source>Status message</source>
|
||||||
<translation>Статус</translation>
|
<translation>Статус</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="501"/>
|
<location filename="mainscreen.py" line="526"/>
|
||||||
<source>Public key</source>
|
<source>Public key</source>
|
||||||
<translation>Публичный ключ</translation>
|
<translation>Публичный ключ</translation>
|
||||||
</message>
|
</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>
|
||||||
<context>
|
<context>
|
||||||
<name>MenuWindow</name>
|
<name>MenuWindow</name>
|
||||||
@ -406,12 +445,12 @@ Version: </source>
|
|||||||
<context>
|
<context>
|
||||||
<name>NetworkSettings</name>
|
<name>NetworkSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="333"/>
|
<location filename="menu.py" line="338"/>
|
||||||
<source>Network settings</source>
|
<source>Network settings</source>
|
||||||
<translation>Настройки сети</translation>
|
<translation>Настройки сети</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="339"/>
|
<location filename="menu.py" line="344"/>
|
||||||
<source>Restart TOX core</source>
|
<source>Restart TOX core</source>
|
||||||
<translation>Перезапустить ядро TOX</translation>
|
<translation>Перезапустить ядро TOX</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -419,12 +458,12 @@ Version: </source>
|
|||||||
<context>
|
<context>
|
||||||
<name>PluginWindow</name>
|
<name>PluginWindow</name>
|
||||||
<message>
|
<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>
|
<source>List of commands for plugin {}</source>
|
||||||
<translation>Список команд для плагина {}</translation>
|
<translation>Список команд для плагина {}</translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>No commands available</source>
|
||||||
<translation>Команды не найдены</translation>
|
<translation>Команды не найдены</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -432,42 +471,42 @@ Version: </source>
|
|||||||
<context>
|
<context>
|
||||||
<name>PluginsForm</name>
|
<name>PluginsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="761"/>
|
<location filename="menu.py" line="812"/>
|
||||||
<source>Plugins</source>
|
<source>Plugins</source>
|
||||||
<translation>Плагины</translation>
|
<translation>Плагины</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="762"/>
|
<location filename="menu.py" line="813"/>
|
||||||
<source>Open selected plugin</source>
|
<source>Open selected plugin</source>
|
||||||
<translation>Открыть выбранный плагин</translation>
|
<translation>Открыть выбранный плагин</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="775"/>
|
<location filename="menu.py" line="826"/>
|
||||||
<source>No GUI found for this plugin</source>
|
<source>No GUI found for this plugin</source>
|
||||||
<translation>GUI для данного плагина не найден</translation>
|
<translation>GUI для данного плагина не найден</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="791"/>
|
<location filename="menu.py" line="842"/>
|
||||||
<source>No description available</source>
|
<source>No description available</source>
|
||||||
<translation>Описание недоступно</translation>
|
<translation>Описание недоступно</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="807"/>
|
<location filename="menu.py" line="858"/>
|
||||||
<source>Disable plugin</source>
|
<source>Disable plugin</source>
|
||||||
<translation>Отключить плагин</translation>
|
<translation>Отключить плагин</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="809"/>
|
<location filename="menu.py" line="860"/>
|
||||||
<source>Enable plugin</source>
|
<source>Enable plugin</source>
|
||||||
<translation>Включить плагин</translation>
|
<translation>Включить плагин</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="799"/>
|
<location filename="menu.py" line="850"/>
|
||||||
<source>No plugins found</source>
|
<source>No plugins found</source>
|
||||||
<translation>Плагины не найдены</translation>
|
<translation>Плагины не найдены</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="776"/>
|
<location filename="menu.py" line="827"/>
|
||||||
<source>Error</source>
|
<source>Error</source>
|
||||||
<translation>Ошибка</translation>
|
<translation>Ошибка</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -475,32 +514,32 @@ Version: </source>
|
|||||||
<context>
|
<context>
|
||||||
<name>ProfileSettingsForm</name>
|
<name>ProfileSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="169"/>
|
<location filename="menu.py" line="174"/>
|
||||||
<source>Export profile</source>
|
<source>Export profile</source>
|
||||||
<translation>Экспорт профиля</translation>
|
<translation>Экспорт профиля</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="170"/>
|
<location filename="menu.py" line="175"/>
|
||||||
<source>Profile settings</source>
|
<source>Profile settings</source>
|
||||||
<translation>Настройки профиля</translation>
|
<translation>Настройки профиля</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="171"/>
|
<location filename="menu.py" line="176"/>
|
||||||
<source>Name:</source>
|
<source>Name:</source>
|
||||||
<translation>Имя:</translation>
|
<translation>Имя:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="172"/>
|
<location filename="menu.py" line="177"/>
|
||||||
<source>Status:</source>
|
<source>Status:</source>
|
||||||
<translation>Статус:</translation>
|
<translation>Статус:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="173"/>
|
<location filename="menu.py" line="178"/>
|
||||||
<source>TOX ID:</source>
|
<source>TOX ID:</source>
|
||||||
<translation>TOX ID:</translation>
|
<translation>TOX ID:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="174"/>
|
<location filename="menu.py" line="179"/>
|
||||||
<source>Copy TOX ID</source>
|
<source>Copy TOX ID</source>
|
||||||
<translation>Копировать TOX ID</translation>
|
<translation>Копировать TOX ID</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -510,92 +549,92 @@ Version: </source>
|
|||||||
<translation type="obsolete">Язык:</translation>
|
<translation type="obsolete">Язык:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="175"/>
|
<location filename="menu.py" line="180"/>
|
||||||
<source>New avatar</source>
|
<source>New avatar</source>
|
||||||
<translation>Новый аватар</translation>
|
<translation>Новый аватар</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="176"/>
|
<location filename="menu.py" line="181"/>
|
||||||
<source>Reset avatar</source>
|
<source>Reset avatar</source>
|
||||||
<translation>Сбросить аватар</translation>
|
<translation>Сбросить аватар</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="177"/>
|
<location filename="menu.py" line="182"/>
|
||||||
<source>New NoSpam</source>
|
<source>New NoSpam</source>
|
||||||
<translation>Новый NoSpam</translation>
|
<translation>Новый NoSpam</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="178"/>
|
<location filename="menu.py" line="183"/>
|
||||||
<source>Profile password</source>
|
<source>Profile password</source>
|
||||||
<translation>Пароль профиля</translation>
|
<translation>Пароль профиля</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="179"/>
|
<location filename="menu.py" line="184"/>
|
||||||
<source>Password (at least 8 symbols)</source>
|
<source>Password (at least 8 symbols)</source>
|
||||||
<translation>Пароль (минимум 8 символов)</translation>
|
<translation>Пароль (минимум 8 символов)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="180"/>
|
<location filename="menu.py" line="185"/>
|
||||||
<source>Confirm password</source>
|
<source>Confirm password</source>
|
||||||
<translation>Подтверждение пароля</translation>
|
<translation>Подтверждение пароля</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="181"/>
|
<location filename="menu.py" line="186"/>
|
||||||
<source>Set password</source>
|
<source>Set password</source>
|
||||||
<translation>Изменить пароль</translation>
|
<translation>Изменить пароль</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="221"/>
|
<location filename="menu.py" line="226"/>
|
||||||
<source>Passwords do not match</source>
|
<source>Passwords do not match</source>
|
||||||
<translation>Пароли не совпадают</translation>
|
<translation>Пароли не совпадают</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="183"/>
|
<location filename="menu.py" line="188"/>
|
||||||
<source>Leaving blank will reset current password</source>
|
<source>Leaving blank will reset current password</source>
|
||||||
<translation>Пустое поле сбросит текущий пароль</translation>
|
<translation>Пустое поле сбросит текущий пароль</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="184"/>
|
<location filename="menu.py" line="189"/>
|
||||||
<source>There is no way to recover lost passwords</source>
|
<source>There is no way to recover lost passwords</source>
|
||||||
<translation>Восстановление забытых паролей не поддерживается</translation>
|
<translation>Восстановление забытых паролей не поддерживается</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="217"/>
|
<location filename="menu.py" line="222"/>
|
||||||
<source>Password must be at least 8 symbols</source>
|
<source>Password must be at least 8 symbols</source>
|
||||||
<translation>Пароль должен быть длиной не менее 8 символов</translation>
|
<translation>Пароль должен быть длиной не менее 8 символов</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="250"/>
|
<location filename="menu.py" line="255"/>
|
||||||
<source>Choose avatar</source>
|
<source>Choose avatar</source>
|
||||||
<translation>Выбрать аватар</translation>
|
<translation>Выбрать аватар</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="185"/>
|
<location filename="menu.py" line="190"/>
|
||||||
<source>Online</source>
|
<source>Online</source>
|
||||||
<translation>Онлайн</translation>
|
<translation>Онлайн</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="186"/>
|
<location filename="menu.py" line="191"/>
|
||||||
<source>Away</source>
|
<source>Away</source>
|
||||||
<translation>Нет на месте</translation>
|
<translation>Нет на месте</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="187"/>
|
<location filename="menu.py" line="192"/>
|
||||||
<source>Busy</source>
|
<source>Busy</source>
|
||||||
<translation>Занят</translation>
|
<translation>Занят</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="202"/>
|
<location filename="menu.py" line="207"/>
|
||||||
<source>Mark as not default profile</source>
|
<source>Mark as not default profile</source>
|
||||||
<translation>Отключить автозагрузку профиля</translation>
|
<translation>Отключить автозагрузку профиля</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="206"/>
|
<location filename="menu.py" line="211"/>
|
||||||
<source>Mark as default profile</source>
|
<source>Mark as default profile</source>
|
||||||
<translation>Сделать профилем по умолчанию</translation>
|
<translation>Сделать профилем по умолчанию</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="188"/>
|
<location filename="menu.py" line="193"/>
|
||||||
<source>Copy public key</source>
|
<source>Copy public key</source>
|
||||||
<translation>Копировать публичный ключ</translation>
|
<translation>Копировать публичный ключ</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -645,7 +684,7 @@ Version: </source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen_widgets.py" line="361"/>
|
<location filename="mainscreen_widgets.py" line="361"/>
|
||||||
<source>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</source>
|
<source>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</source>
|
||||||
<translation>С версии 0.1.3 Toxygen поддерживает плагины. <a href="https://github.com/xveduk/toxygen/blob/master/docs/plugins.md">Узнать больше.</a></translation>
|
<translation type="obsolete">С версии 0.1.3 Toxygen поддерживает плагины. <a href="https://github.com/xveduk/toxygen/blob/master/docs/plugins.md">Узнать больше.</a></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen_widgets.py" line="367"/>
|
<location filename="mainscreen_widgets.py" line="367"/>
|
||||||
@ -673,25 +712,40 @@ Version: </source>
|
|||||||
<translation>Toxygen поддерживает псевдооффлайн сообщения и файл трансферы.</translation>
|
<translation>Toxygen поддерживает псевдооффлайн сообщения и файл трансферы.</translation>
|
||||||
</message>
|
</message>
|
||||||
<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 -> Settings -> Set new NoSpam.</source>
|
<source>Set new NoSpam to avoid spam friend requests: Profile -> Settings -> Set new NoSpam.</source>
|
||||||
<translation>Установите новый NoSpam, чтобы избежать спам запросов в друзья: Профиль->Настройки->Новый NoSpam.</translation>
|
<translation>Установите новый NoSpam, чтобы избежать спам запросов в друзья: Профиль->Настройки->Новый NoSpam.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen_widgets.py" line="361"/>
|
||||||
|
<source>New in Toxygen v0.2.3:<br>TCS compliance<br>Plugins, smileys and stickers import<br>Bug fixes</source>
|
||||||
|
<translation>Новое в Toxygen 0.2.3:<br>Соответствие TCS<br>Импорт плагинов, смайлов и стикеров<br>Исправления ошибок</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 "Delete" in menu</source>
|
||||||
|
<translation>Чтобы удалить отдельное сообщение в чате сделайте правый клик на спиннер или время сообщения и выберите "Удалить" в меню</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>
|
||||||
<context>
|
<context>
|
||||||
<name>audioSettingsForm</name>
|
<name>audioSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="718"/>
|
<location filename="menu.py" line="769"/>
|
||||||
<source>Audio settings</source>
|
<source>Audio settings</source>
|
||||||
<translation>Настройки аудио</translation>
|
<translation>Настройки аудио</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="719"/>
|
<location filename="menu.py" line="770"/>
|
||||||
<source>Input device:</source>
|
<source>Input device:</source>
|
||||||
<translation>Устройство ввода:</translation>
|
<translation>Устройство ввода:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="720"/>
|
<location filename="menu.py" line="771"/>
|
||||||
<source>Output device:</source>
|
<source>Output device:</source>
|
||||||
<translation>Устройство вывода:</translation>
|
<translation>Устройство вывода:</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -699,32 +753,32 @@ Version: </source>
|
|||||||
<context>
|
<context>
|
||||||
<name>incoming_call</name>
|
<name>incoming_call</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1132"/>
|
<location filename="profile.py" line="1141"/>
|
||||||
<source>Incoming video call</source>
|
<source>Incoming video call</source>
|
||||||
<translation>Входящий видеозвонок</translation>
|
<translation>Входящий видеозвонок</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1135"/>
|
<location filename="profile.py" line="1144"/>
|
||||||
<source>Incoming audio call</source>
|
<source>Incoming audio call</source>
|
||||||
<translation>Входящий аудиозвонок</translation>
|
<translation>Входящий аудиозвонок</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1115"/>
|
<location filename="profile.py" line="1124"/>
|
||||||
<source>Outgoing video call</source>
|
<source>Outgoing video call</source>
|
||||||
<translation>Исходящий видеозвонок</translation>
|
<translation>Исходящий видеозвонок</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1118"/>
|
<location filename="profile.py" line="1127"/>
|
||||||
<source>Outgoing audio call</source>
|
<source>Outgoing audio call</source>
|
||||||
<translation>Исходящий аудиозвонок</translation>
|
<translation>Исходящий аудиозвонок</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1164"/>
|
<location filename="profile.py" line="1173"/>
|
||||||
<source>Call declined</source>
|
<source>Call declined</source>
|
||||||
<translation>Звонок отменен</translation>
|
<translation>Звонок отменен</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1166"/>
|
<location filename="profile.py" line="1175"/>
|
||||||
<source>Call finished</source>
|
<source>Call finished</source>
|
||||||
<translation>Звонок завершен</translation>
|
<translation>Звонок завершен</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -732,60 +786,75 @@ Version: </source>
|
|||||||
<context>
|
<context>
|
||||||
<name>interfaceForm</name>
|
<name>interfaceForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="619"/>
|
<location filename="menu.py" line="637"/>
|
||||||
<source>Interface settings</source>
|
<source>Interface settings</source>
|
||||||
<translation>Настройки интерфейса</translation>
|
<translation>Настройки интерфейса</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="620"/>
|
<location filename="menu.py" line="638"/>
|
||||||
<source>Theme:</source>
|
<source>Theme:</source>
|
||||||
<translation>Тема:</translation>
|
<translation>Тема:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="621"/>
|
<location filename="menu.py" line="639"/>
|
||||||
<source>Language:</source>
|
<source>Language:</source>
|
||||||
<translation>Язык:</translation>
|
<translation>Язык:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="622"/>
|
<location filename="menu.py" line="640"/>
|
||||||
<source>Smileys</source>
|
<source>Smileys</source>
|
||||||
<translation>Смайлики</translation>
|
<translation>Смайлики</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="623"/>
|
<location filename="menu.py" line="641"/>
|
||||||
<source>Smiley pack:</source>
|
<source>Smiley pack:</source>
|
||||||
<translation>Набор смайликов:</translation>
|
<translation>Набор смайликов:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="624"/>
|
<location filename="menu.py" line="642"/>
|
||||||
<source>Mirror mode</source>
|
<source>Mirror mode</source>
|
||||||
<translation>Зеркальный режим</translation>
|
<translation>Зеркальный режим</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="625"/>
|
<location filename="menu.py" line="643"/>
|
||||||
<source>Messages font size:</source>
|
<source>Messages font size:</source>
|
||||||
<translation>Размер шрифта сообщений:</translation>
|
<translation>Размер шрифта сообщений:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="667"/>
|
<location filename="menu.py" line="718"/>
|
||||||
<source>Restart app to apply settings</source>
|
<source>Restart app to apply settings</source>
|
||||||
<translation>Для применения настроек необходимо перезапустить приложение</translation>
|
<translation>Для применения настроек необходимо перезапустить приложение</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="668"/>
|
<location filename="menu.py" line="719"/>
|
||||||
<source>Restart required</source>
|
<source>Restart required</source>
|
||||||
<translation>Требуется перезапуск</translation>
|
<translation>Требуется перезапуск</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="626"/>
|
<location filename="menu.py" line="644"/>
|
||||||
<source>Select unread messages notification color</source>
|
<source>Select unread messages notification color</source>
|
||||||
<translation>Цвет уведомления о сообщении</translation>
|
<translation>Цвет уведомления о сообщении</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="627"/>
|
<location filename="menu.py" line="645"/>
|
||||||
<source>Compact contact list</source>
|
<source>Compact contact list</source>
|
||||||
<translation>Компактный список контактов</translation>
|
<translation>Компактный список контактов</translation>
|
||||||
</message>
|
</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>
|
||||||
<context>
|
<context>
|
||||||
<name>login</name>
|
<name>login</name>
|
||||||
@ -840,30 +909,35 @@ Version: </source>
|
|||||||
<translation>Имя профиля</translation>
|
<translation>Имя профиля</translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>Other instance of Toxygen uses this profile or profile was not properly closed. Continue?</source>
|
||||||
<translation>Этот профиль используется другим экземпляром Toxygen или не был правильно закрыт. Продолжить?</translation>
|
<translation>Этот профиль используется другим экземпляром Toxygen или не был правильно закрыт. Продолжить?</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="main.py" line="120"/>
|
||||||
|
<source>Do you want to set profile password?</source>
|
||||||
|
<translation>Хотите ли вы установить пароль профиля?</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>notificationsForm</name>
|
<name>notificationsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="530"/>
|
<location filename="menu.py" line="535"/>
|
||||||
<source>Notification settings</source>
|
<source>Notification settings</source>
|
||||||
<translation>Настройки уведомлений</translation>
|
<translation>Настройки уведомлений</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="531"/>
|
<location filename="menu.py" line="536"/>
|
||||||
<source>Enable notifications</source>
|
<source>Enable notifications</source>
|
||||||
<translation>Включить уведомления</translation>
|
<translation>Включить уведомления</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="532"/>
|
<location filename="menu.py" line="537"/>
|
||||||
<source>Enable call's sound</source>
|
<source>Enable call's sound</source>
|
||||||
<translation>Включить звук звонка</translation>
|
<translation>Включить звук звонка</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="533"/>
|
<location filename="menu.py" line="538"/>
|
||||||
<source>Enable sound notifications</source>
|
<source>Enable sound notifications</source>
|
||||||
<translation>Включить звуковые уведомления
|
<translation>Включить звуковые уведомления
|
||||||
</translation>
|
</translation>
|
||||||
@ -872,72 +946,72 @@ Version: </source>
|
|||||||
<context>
|
<context>
|
||||||
<name>privacySettings</name>
|
<name>privacySettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="426"/>
|
<location filename="menu.py" line="431"/>
|
||||||
<source>Privacy settings</source>
|
<source>Privacy settings</source>
|
||||||
<translation>Настройки приватности</translation>
|
<translation>Настройки приватности</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="427"/>
|
<location filename="menu.py" line="432"/>
|
||||||
<source>Save chat history</source>
|
<source>Save chat history</source>
|
||||||
<translation>Сохранять историю переписки</translation>
|
<translation>Сохранять историю переписки</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="428"/>
|
<location filename="menu.py" line="433"/>
|
||||||
<source>Allow file auto accept</source>
|
<source>Allow file auto accept</source>
|
||||||
<translation>Разрешить автополучение файлов</translation>
|
<translation>Разрешить автополучение файлов</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="429"/>
|
<location filename="menu.py" line="434"/>
|
||||||
<source>Send typing notifications</source>
|
<source>Send typing notifications</source>
|
||||||
<translation>Посылать уведомления о наборе текста</translation>
|
<translation>Посылать уведомления о наборе текста</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="430"/>
|
<location filename="menu.py" line="435"/>
|
||||||
<source>Auto accept default path:</source>
|
<source>Auto accept default path:</source>
|
||||||
<translation>Путь автоприема файлов:</translation>
|
<translation>Путь автоприема файлов:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="431"/>
|
<location filename="menu.py" line="436"/>
|
||||||
<source>Change</source>
|
<source>Change</source>
|
||||||
<translation>Изменить</translation>
|
<translation>Изменить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="432"/>
|
<location filename="menu.py" line="437"/>
|
||||||
<source>Allow inlines</source>
|
<source>Allow inlines</source>
|
||||||
<translation>Разрешать инлайны</translation>
|
<translation>Разрешать инлайны</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="477"/>
|
<location filename="menu.py" line="482"/>
|
||||||
<source>Chat history</source>
|
<source>Chat history</source>
|
||||||
<translation>История чата</translation>
|
<translation>История чата</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="480"/>
|
<location filename="menu.py" line="485"/>
|
||||||
<source>History will be cleaned! Continue?</source>
|
<source>History will be cleaned! Continue?</source>
|
||||||
<translation>История переписки будет очищена! Продолжить?</translation>
|
<translation>История переписки будет очищена! Продолжить?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="434"/>
|
<location filename="menu.py" line="439"/>
|
||||||
<source>Blocked users:</source>
|
<source>Blocked users:</source>
|
||||||
<translation>Заблокированные пользователи:</translation>
|
<translation>Заблокированные пользователи:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="435"/>
|
<location filename="menu.py" line="440"/>
|
||||||
<source>Unblock</source>
|
<source>Unblock</source>
|
||||||
<translation>Разблокировать</translation>
|
<translation>Разблокировать</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="436"/>
|
<location filename="menu.py" line="441"/>
|
||||||
<source>Block user</source>
|
<source>Block user</source>
|
||||||
<translation>Заблокировать пользователя</translation>
|
<translation>Заблокировать пользователя</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="448"/>
|
<location filename="menu.py" line="453"/>
|
||||||
<source>Add to friend list</source>
|
<source>Add to friend list</source>
|
||||||
<translation>Добавить в список друзей</translation>
|
<translation>Добавить в список друзей</translation>
|
||||||
</message>
|
</message>
|
||||||
<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>
|
<source>Do you want to add this user to friend list?</source>
|
||||||
<translation>Добавить этого пользователя в список друзей?</translation>
|
<translation>Добавить этого пользователя в список друзей?</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -947,12 +1021,12 @@ Version: </source>
|
|||||||
<translation type="obsolete">Блокировать по TOX ID:</translation>
|
<translation type="obsolete">Блокировать по TOX ID:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="433"/>
|
<location filename="menu.py" line="438"/>
|
||||||
<source>Block by public key:</source>
|
<source>Block by public key:</source>
|
||||||
<translation>Блокировать по публичному ключу:</translation>
|
<translation>Блокировать по публичному ключу:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="437"/>
|
<location filename="menu.py" line="442"/>
|
||||||
<source>Save unsent messages only</source>
|
<source>Save unsent messages only</source>
|
||||||
<translation>Сохранять только неотправленные сообщения</translation>
|
<translation>Сохранять только неотправленные сообщения</translation>
|
||||||
</message>
|
</message>
|
||||||
@ -960,32 +1034,32 @@ Version: </source>
|
|||||||
<context>
|
<context>
|
||||||
<name>tray</name>
|
<name>tray</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="176"/>
|
<location filename="main.py" line="203"/>
|
||||||
<source>Open Toxygen</source>
|
<source>Open Toxygen</source>
|
||||||
<translation>Открыть Toxygen</translation>
|
<translation>Открыть Toxygen</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="185"/>
|
<location filename="main.py" line="212"/>
|
||||||
<source>Exit</source>
|
<source>Exit</source>
|
||||||
<translation>Выход</translation>
|
<translation>Выход</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="177"/>
|
<location filename="main.py" line="204"/>
|
||||||
<source>Set status</source>
|
<source>Set status</source>
|
||||||
<translation>Изменить статус</translation>
|
<translation>Изменить статус</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="178"/>
|
<location filename="main.py" line="205"/>
|
||||||
<source>Online</source>
|
<source>Online</source>
|
||||||
<translation>Онлайн</translation>
|
<translation>Онлайн</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="179"/>
|
<location filename="main.py" line="206"/>
|
||||||
<source>Away</source>
|
<source>Away</source>
|
||||||
<translation>Нет на месте</translation>
|
<translation>Нет на месте</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="180"/>
|
<location filename="main.py" line="207"/>
|
||||||
<source>Busy</source>
|
<source>Busy</source>
|
||||||
<translation>Занят</translation>
|
<translation>Занят</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -2,7 +2,7 @@ import os
|
|||||||
import time
|
import time
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
program_version = '0.2.2'
|
program_version = '0.2.3'
|
||||||
|
|
||||||
|
|
||||||
def log(data):
|
def log(data):
|
||||||
|
@ -9,7 +9,7 @@ class DataLabel(QtGui.QLabel):
|
|||||||
Label with elided text
|
Label with elided text
|
||||||
"""
|
"""
|
||||||
def setText(self, text):
|
def setText(self, text):
|
||||||
text = ''.join(c if c <= '\u10FFFF' else '\u25AF' for c in text)
|
text = ''.join(c if c <= '\U0010FFFF' else '\u25AF' for c in text)
|
||||||
metrics = QtGui.QFontMetrics(self.font())
|
metrics = QtGui.QFontMetrics(self.font())
|
||||||
text = metrics.elidedText(text, QtCore.Qt.ElideRight, self.width())
|
text = metrics.elidedText(text, QtCore.Qt.ElideRight, self.width())
|
||||||
super().setText(text)
|
super().setText(text)
|
||||||
|