Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f445a79e11 | ||
|
|
29617c2168 | ||
|
|
e441b8ffd2 | ||
|
|
b588e19789 | ||
|
|
168d259ebd | ||
|
|
0db5195689 | ||
|
|
91b558775a | ||
|
|
4d1addfa63 | ||
|
|
0239b4f8ef | ||
|
|
60df9f7b1d | ||
|
|
2ed4e00d3e | ||
|
|
e6a0988c6d | ||
|
|
57b4e2af67 | ||
|
|
6192688e0c | ||
|
|
177e180e37 | ||
|
|
8d3db9f897 | ||
|
|
2903ed1877 | ||
|
|
a1fbd87719 | ||
|
|
be6acff18d | ||
|
|
81660a9ad4 | ||
|
|
0e103749a2 | ||
|
|
160e9dc72f | ||
|
|
c503cf4a72 | ||
|
|
575d626e03 | ||
|
|
c6d832ae92 | ||
|
|
78c376a0b0 | ||
|
|
8df2e3ebce | ||
|
|
845af6d37e | ||
|
|
5e1dfe6d36 | ||
|
|
2b8da1deb4 | ||
|
|
89be47dc72 | ||
|
|
f5782c2dcb | ||
|
|
7a5b1fc05e | ||
|
|
61b124dad4 | ||
|
|
ac1800703f | ||
|
|
89c4b2cdf6 | ||
|
|
ce40acc4a0 | ||
|
|
7a02ae3ef4 |
17
README.md
@@ -1,10 +1,13 @@
|
|||||||
# Toxygen
|
# Toxygen
|
||||||
Toxygen is simple [Tox](https://tox.chat/) client written on pure Python
|
Toxygen is cross-platform [Tox](https://tox.chat/) client written on Python
|
||||||
### [How to install](/docs/install.md)
|
|
||||||
|
|
||||||
### [Contributing](/docs/contributing.md)
|
[](https://github.com/xveduk/toxygen/releases/latest)
|
||||||
|
[](https://github.com/xveduk/toxygen/issues)
|
||||||
|
[](https://raw.githubusercontent.com/xveduk/toxygen/master/LICENSE.md)
|
||||||
|
|
||||||
# Supported OS:
|
### [Install](/docs/install.md) - [Contribute](/docs/contributing.md)
|
||||||
|
|
||||||
|
### Supported OS:
|
||||||
- Windows
|
- Windows
|
||||||
- Linux
|
- Linux
|
||||||
|
|
||||||
@@ -25,10 +28,10 @@ Toxygen is simple [Tox](https://tox.chat/) client written on pure Python
|
|||||||
- [x] Contact aliases
|
- [x] Contact aliases
|
||||||
- [x] Contact blocking
|
- [x] Contact blocking
|
||||||
- [x] Typing notifications
|
- [x] Typing notifications
|
||||||
|
- [x] Changing nospam
|
||||||
|
- [x] File resuming
|
||||||
- [ ] Video
|
- [ ] Video
|
||||||
- [ ] Save file encryption
|
- [ ] Save file encryption
|
||||||
- [ ] File resuming
|
|
||||||
- [ ] Changing nospam
|
|
||||||
- [ ] Plugins support
|
- [ ] Plugins support
|
||||||
- [ ] Group chats
|
- [ ] Group chats
|
||||||
- [ ] Read receipts
|
- [ ] Read receipts
|
||||||
@@ -43,7 +46,7 @@ Toxygen is simple [Tox](https://tox.chat/) client written on pure Python
|
|||||||
[Releases](https://github.com/xveduk/toxygen/releases)
|
[Releases](https://github.com/xveduk/toxygen/releases)
|
||||||
|
|
||||||
###Screenshots
|
###Screenshots
|
||||||
*Toxygen running on Ubuntu and Windows*
|
*Toxygen on Ubuntu and Windows*
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
|
#Compile Toxygen
|
||||||
|
|
||||||
You can compile Toxygen using [PyInstaller](http://www.pyinstaller.org/)
|
You can compile Toxygen using [PyInstaller](http://www.pyinstaller.org/)
|
||||||
|
|
||||||
Install PyInstaller:
|
Install PyInstaller:
|
||||||
``pip install pyinstaller``
|
``pip install pyinstaller``
|
||||||
|
|
||||||
|
|||||||
BIN
docs/ubuntu.png
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 94 KiB |
BIN
docs/windows.png
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 317 KiB |
@@ -76,7 +76,7 @@ def friend_connection_status(tox, friend_num, new_status, user_data):
|
|||||||
profile = Profile.get_instance()
|
profile = Profile.get_instance()
|
||||||
friend = profile.get_friend_by_number(friend_num)
|
friend = profile.get_friend_by_number(friend_num)
|
||||||
if new_status == TOX_CONNECTION['NONE']:
|
if new_status == TOX_CONNECTION['NONE']:
|
||||||
invoke_in_main_thread(friend.set_status, None)
|
invoke_in_main_thread(profile.friend_exit, friend_num)
|
||||||
invoke_in_main_thread(profile.update_filtration)
|
invoke_in_main_thread(profile.update_filtration)
|
||||||
if Settings.get_instance()['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']:
|
if 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'])
|
||||||
@@ -183,11 +183,14 @@ def file_recv_chunk(tox, friend_number, file_number, position, chunk, length, us
|
|||||||
"""
|
"""
|
||||||
Incoming chunk
|
Incoming chunk
|
||||||
"""
|
"""
|
||||||
invoke_in_main_thread(Profile.get_instance().incoming_chunk,
|
if not length:
|
||||||
friend_number,
|
invoke_in_main_thread(Profile.get_instance().incoming_chunk,
|
||||||
file_number,
|
friend_number,
|
||||||
position,
|
file_number,
|
||||||
chunk[:length] if length else None)
|
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):
|
||||||
@@ -210,6 +213,10 @@ def file_recv_control(tox, friend_number, file_number, file_control, user_data):
|
|||||||
"""
|
"""
|
||||||
if file_control == TOX_FILE_CONTROL['CANCEL']:
|
if file_control == TOX_FILE_CONTROL['CANCEL']:
|
||||||
Profile.get_instance().cancel_transfer(friend_number, file_number, True)
|
Profile.get_instance().cancel_transfer(friend_number, file_number, True)
|
||||||
|
elif file_control == TOX_FILE_CONTROL['PAUSE']:
|
||||||
|
Profile.get_instance().pause_transfer(friend_number, file_number, True)
|
||||||
|
elif file_control == TOX_FILE_CONTROL['RESUME']:
|
||||||
|
Profile.get_instance().resume_transfer(friend_number, file_number, True)
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ TOX_FILE_TRANSFER_STATE = {
|
|||||||
'PAUSED': 1,
|
'PAUSED': 1,
|
||||||
'CANCELED': 2,
|
'CANCELED': 2,
|
||||||
'FINISHED': 3,
|
'FINISHED': 3,
|
||||||
|
'PAUSED_BY_FRIEND': 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class StateSignal(QtCore.QObject):
|
class StateSignal(QtCore.QObject):
|
||||||
signal = QtCore.Signal(int, float)
|
signal = QtCore.Signal(int, float) # state and progress
|
||||||
|
|
||||||
|
|
||||||
class FileTransfer(QtCore.QObject):
|
class FileTransfer(QtCore.QObject):
|
||||||
@@ -42,6 +43,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 signal(self):
|
||||||
|
self._state_changed.signal.emit(self.state, self._done / self._size if self._size else 0)
|
||||||
|
|
||||||
def get_file_number(self):
|
def get_file_number(self):
|
||||||
return self._file_number
|
return self._file_number
|
||||||
|
|
||||||
@@ -58,12 +62,20 @@ class FileTransfer(QtCore.QObject):
|
|||||||
if hasattr(self, '_file'):
|
if hasattr(self, '_file'):
|
||||||
sleep(0.1)
|
sleep(0.1)
|
||||||
self._file.close()
|
self._file.close()
|
||||||
self._state_changed.signal.emit(TOX_FILE_CONTROL['CANCEL'], 1)
|
self.state = TOX_FILE_TRANSFER_STATE['CANCELED']
|
||||||
|
self._state_changed.signal.emit(self.state, 1)
|
||||||
|
|
||||||
|
def pause(self, by_friend):
|
||||||
|
if not by_friend:
|
||||||
|
self.send_control(TOX_FILE_CONTROL['PAUSE'])
|
||||||
|
else:
|
||||||
|
self.state = TOX_FILE_TRANSFER_STATE['PAUSED_BY_FRIEND']
|
||||||
|
self.signal()
|
||||||
|
|
||||||
def send_control(self, control):
|
def send_control(self, control):
|
||||||
if self._tox.file_control(self._friend_number, self._file_number, control):
|
if self._tox.file_control(self._friend_number, self._file_number, control):
|
||||||
self.state = control
|
self.state = control
|
||||||
self._state_changed.signal.emit(self.state, self._done / self._size if self._size else 0)
|
self.signal()
|
||||||
|
|
||||||
def get_file_id(self):
|
def get_file_id(self):
|
||||||
return self._tox.file_get_file_id(self._friend_number, self._file_number)
|
return self._tox.file_get_file_id(self._friend_number, self._file_number)
|
||||||
@@ -96,9 +108,10 @@ 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._state_changed.signal.emit(self.state, self._done / self._size)
|
self.signal()
|
||||||
else:
|
else:
|
||||||
self._file.close()
|
if hasattr(self, '_file'):
|
||||||
|
self._file.close()
|
||||||
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
self.state = TOX_FILE_TRANSFER_STATE['FINISHED']
|
||||||
self._state_changed.signal.emit(self.state, 1)
|
self._state_changed.signal.emit(self.state, 1)
|
||||||
|
|
||||||
@@ -208,7 +221,7 @@ class ReceiveToBuffer(FileTransfer):
|
|||||||
if position + l > self._data_size:
|
if position + l > self._data_size:
|
||||||
self._data_size = position + l
|
self._data_size = position + l
|
||||||
self._done += l
|
self._done += l
|
||||||
self._state_changed.signal.emit(self.state, self._done / self._size)
|
self.signal()
|
||||||
|
|
||||||
|
|
||||||
class ReceiveAvatar(ReceiveTransfer):
|
class ReceiveAvatar(ReceiveTransfer):
|
||||||
@@ -226,7 +239,6 @@ class ReceiveAvatar(ReceiveTransfer):
|
|||||||
elif exists(path):
|
elif exists(path):
|
||||||
if not size:
|
if not size:
|
||||||
self.send_control(TOX_FILE_CONTROL['CANCEL'])
|
self.send_control(TOX_FILE_CONTROL['CANCEL'])
|
||||||
self.state = TOX_FILE_TRANSFER_STATE['CANCELED']
|
|
||||||
self._file.close()
|
self._file.close()
|
||||||
remove(path)
|
remove(path)
|
||||||
remove(path + '.tmp')
|
remove(path + '.tmp')
|
||||||
@@ -237,7 +249,6 @@ class ReceiveAvatar(ReceiveTransfer):
|
|||||||
existing_hash = Tox.hash(data)
|
existing_hash = Tox.hash(data)
|
||||||
if hash == existing_hash:
|
if hash == existing_hash:
|
||||||
self.send_control(TOX_FILE_CONTROL['CANCEL'])
|
self.send_control(TOX_FILE_CONTROL['CANCEL'])
|
||||||
self.state = TOX_FILE_TRANSFER_STATE['CANCELED']
|
|
||||||
remove(path + '.tmp')
|
remove(path + '.tmp')
|
||||||
else:
|
else:
|
||||||
self.send_control(TOX_FILE_CONTROL['RESUME'])
|
self.send_control(TOX_FILE_CONTROL['RESUME'])
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
src/images/pause.png
Executable file
|
After Width: | Height: | Size: 306 B |
BIN
src/images/resume.png
Executable file
|
After Width: | Height: | Size: 2.6 KiB |
@@ -136,17 +136,21 @@ class StatusCircle(QtGui.QWidget):
|
|||||||
|
|
||||||
class FileTransferItem(QtGui.QListWidget):
|
class FileTransferItem(QtGui.QListWidget):
|
||||||
|
|
||||||
def __init__(self, file_name, size, time, user, friend_number, file_number, state, parent=None):
|
def __init__(self, file_name, size, time, user, friend_number, file_number, state, width, parent=None):
|
||||||
|
|
||||||
QtGui.QListWidget.__init__(self, parent)
|
QtGui.QListWidget.__init__(self, parent)
|
||||||
self.resize(QtCore.QSize(620, 50))
|
self.resize(QtCore.QSize(width, 34))
|
||||||
if state != FILE_TRANSFER_MESSAGE_STATUS['CANCELLED']:
|
if state == FILE_TRANSFER_MESSAGE_STATUS['CANCELLED']:
|
||||||
self.setStyleSheet('QWidget { background-color: green; }')
|
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
||||||
|
elif state in (FILE_TRANSFER_MESSAGE_STATUS['INCOMING_NOT_STARTED'], FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_FRIEND']):
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }')
|
||||||
else:
|
else:
|
||||||
self.setStyleSheet('QWidget { background-color: #B40404; }')
|
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
||||||
|
|
||||||
|
self.state = state
|
||||||
|
|
||||||
self.name = DataLabel(self)
|
self.name = DataLabel(self)
|
||||||
self.name.setGeometry(QtCore.QRect(1, 15, 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("Times New Roman")
|
||||||
@@ -154,45 +158,50 @@ class FileTransferItem(QtGui.QListWidget):
|
|||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.name.setFont(font)
|
self.name.setFont(font)
|
||||||
self.name.setText(user)
|
self.name.setText(user)
|
||||||
self.name.setStyleSheet('QLabel { color: black; }')
|
|
||||||
|
|
||||||
self.time = QtGui.QLabel(self)
|
self.time = QtGui.QLabel(self)
|
||||||
self.time.setGeometry(QtCore.QRect(570, 2, 50, 46))
|
self.time.setGeometry(QtCore.QRect(width - 53, 7, 50, 20))
|
||||||
font.setPointSize(10)
|
font.setPointSize(10)
|
||||||
font.setBold(False)
|
font.setBold(False)
|
||||||
self.time.setFont(font)
|
self.time.setFont(font)
|
||||||
self.time.setText(convert_time(time))
|
self.time.setText(convert_time(time))
|
||||||
self.time.setStyleSheet('QLabel { color: black; }')
|
|
||||||
|
|
||||||
self.cancel = QtGui.QPushButton(self)
|
self.cancel = QtGui.QPushButton(self)
|
||||||
self.cancel.setGeometry(QtCore.QRect(500, 2, 46, 46))
|
self.cancel.setGeometry(QtCore.QRect(width - 120, 2, 30, 30))
|
||||||
pixmap = QtGui.QPixmap(curr_directory() + '/images/decline.png')
|
pixmap = QtGui.QPixmap(curr_directory() + '/images/decline.png')
|
||||||
icon = QtGui.QIcon(pixmap)
|
icon = QtGui.QIcon(pixmap)
|
||||||
self.cancel.setIcon(icon)
|
self.cancel.setIcon(icon)
|
||||||
self.cancel.setIconSize(QtCore.QSize(30, 30))
|
self.cancel.setIconSize(QtCore.QSize(30, 30))
|
||||||
self.cancel.setVisible(state > 1)
|
self.cancel.setVisible(state > 1)
|
||||||
self.cancel.clicked.connect(lambda: self.cancel_transfer(friend_number, file_number))
|
self.cancel.clicked.connect(lambda: self.cancel_transfer(friend_number, file_number))
|
||||||
self.cancel.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; }')
|
self.cancel.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; background-color: none;}')
|
||||||
|
|
||||||
self.accept = QtGui.QPushButton(self)
|
self.accept_or_pause = QtGui.QPushButton(self)
|
||||||
self.accept.setGeometry(QtCore.QRect(450, 2, 46, 46))
|
self.accept_or_pause.setGeometry(QtCore.QRect(width - 170, 2, 30, 30))
|
||||||
pixmap = QtGui.QPixmap(curr_directory() + '/images/accept.png')
|
if state == FILE_TRANSFER_MESSAGE_STATUS['INCOMING_NOT_STARTED']:
|
||||||
icon = QtGui.QIcon(pixmap)
|
self.accept_or_pause.setVisible(True)
|
||||||
self.accept.setIcon(icon)
|
self.button_update('accept')
|
||||||
self.accept.setIconSize(QtCore.QSize(30, 30))
|
elif state in (0, 1, 5):
|
||||||
self.accept.clicked.connect(lambda: self.accept_transfer(friend_number, file_number, size))
|
self.accept_or_pause.setVisible(False)
|
||||||
self.accept.setVisible(state == FILE_TRANSFER_MESSAGE_STATUS['INCOMING_NOT_STARTED'])
|
elif state == FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_USER']: # setup for continue
|
||||||
self.accept.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; }')
|
self.accept_or_pause.setVisible(True)
|
||||||
|
self.button_update('resume')
|
||||||
|
else: # pause
|
||||||
|
self.accept_or_pause.setVisible(True)
|
||||||
|
self.button_update('pause')
|
||||||
|
self.accept_or_pause.clicked.connect(lambda: self.accept_or_pause_transfer(friend_number, file_number, size))
|
||||||
|
|
||||||
|
self.accept_or_pause.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; background-color: none}')
|
||||||
|
|
||||||
self.pb = QtGui.QProgressBar(self)
|
self.pb = QtGui.QProgressBar(self)
|
||||||
self.pb.setGeometry(QtCore.QRect(100, 15, 100, 20))
|
self.pb.setGeometry(QtCore.QRect(100, 7, 100, 20))
|
||||||
self.pb.setValue(0)
|
self.pb.setValue(0)
|
||||||
self.pb.setStyleSheet('QProgressBar { background-color: #302F2F; }')
|
self.pb.setStyleSheet('QProgressBar { background-color: #302F2F; }')
|
||||||
if state < 2:
|
if state < 2:
|
||||||
self.pb.setVisible(False)
|
self.pb.setVisible(False)
|
||||||
|
|
||||||
self.file_name = DataLabel(self)
|
self.file_name = DataLabel(self)
|
||||||
self.file_name.setGeometry(QtCore.QRect(210, 2, 230, 46))
|
self.file_name.setGeometry(QtCore.QRect(210, 7, width - 400, 20))
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
self.file_name.setFont(font)
|
self.file_name.setFont(font)
|
||||||
file_size = size / 1024
|
file_size = size / 1024
|
||||||
@@ -204,56 +213,103 @@ class FileTransferItem(QtGui.QListWidget):
|
|||||||
file_size = '{}KB'.format(file_size)
|
file_size = '{}KB'.format(file_size)
|
||||||
file_data = u'{} {}'.format(file_size, file_name)
|
file_data = u'{} {}'.format(file_size, file_name)
|
||||||
self.file_name.setText(file_data)
|
self.file_name.setText(file_data)
|
||||||
self.file_name.setStyleSheet('QLabel { color: black; }')
|
|
||||||
self.saved_name = file_name
|
self.saved_name = file_name
|
||||||
|
self.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.paused = False
|
||||||
|
|
||||||
def cancel_transfer(self, friend_number, file_number):
|
def cancel_transfer(self, friend_number, file_number):
|
||||||
pr = profile.Profile.get_instance()
|
pr = profile.Profile.get_instance()
|
||||||
pr.cancel_transfer(friend_number, file_number)
|
pr.cancel_transfer(friend_number, file_number)
|
||||||
self.setStyleSheet('QListWidget { background-color: #B40404; }')
|
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
||||||
self.cancel.setVisible(False)
|
self.cancel.setVisible(False)
|
||||||
self.accept.setVisible(False)
|
self.accept_or_pause.setVisible(False)
|
||||||
self.pb.setVisible(False)
|
self.pb.setVisible(False)
|
||||||
|
|
||||||
def accept_transfer(self, friend_number, file_number, size):
|
def accept_or_pause_transfer(self, friend_number, file_number, size):
|
||||||
directory = QtGui.QFileDialog.getExistingDirectory()
|
if self.state == FILE_TRANSFER_MESSAGE_STATUS['INCOMING_NOT_STARTED']:
|
||||||
if directory:
|
directory = QtGui.QFileDialog.getExistingDirectory(self,
|
||||||
pr = profile.Profile.get_instance()
|
QtGui.QApplication.translate("MainWindow", 'Choose folder', None, QtGui.QApplication.UnicodeUTF8),
|
||||||
pr.accept_transfer(self, directory + '/' + self.saved_name, friend_number, file_number, size)
|
curr_directory(),
|
||||||
self.accept.setVisible(False)
|
QtGui.QFileDialog.ShowDirsOnly)
|
||||||
|
if directory:
|
||||||
|
pr = profile.Profile.get_instance()
|
||||||
|
pr.accept_transfer(self, directory + '/' + self.saved_name, friend_number, file_number, size)
|
||||||
|
self.button_update('pause')
|
||||||
|
elif self.state == FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_USER']: # resume
|
||||||
|
self.paused = False
|
||||||
|
profile.Profile.get_instance().resume_transfer(friend_number, file_number)
|
||||||
|
self.button_update('pause')
|
||||||
|
self.state = FILE_TRANSFER_MESSAGE_STATUS['OUTGOING']
|
||||||
|
else: # pause
|
||||||
|
self.paused = True
|
||||||
|
self.state = FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_USER']
|
||||||
|
profile.Profile.get_instance().pause_transfer(friend_number, file_number)
|
||||||
|
self.button_update('resume')
|
||||||
|
self.accept_or_pause.clearFocus()
|
||||||
|
|
||||||
|
def button_update(self, path):
|
||||||
|
pixmap = QtGui.QPixmap(curr_directory() + '/images/{}.png'.format(path))
|
||||||
|
icon = QtGui.QIcon(pixmap)
|
||||||
|
self.accept_or_pause.setIcon(icon)
|
||||||
|
self.accept_or_pause.setIconSize(QtCore.QSize(30, 30))
|
||||||
|
|
||||||
|
def convert(self, state):
|
||||||
|
# convert TOX_FILE_TRANSFER_STATE to FILE_TRANSFER_MESSAGE_STATUS
|
||||||
|
d = {0: 2, 1: 6, 2: 1, 3: 0, 4: 5}
|
||||||
|
return d[state]
|
||||||
|
|
||||||
@QtCore.Slot(int, float)
|
@QtCore.Slot(int, float)
|
||||||
def update(self, state, progress):
|
def update(self, state, progress):
|
||||||
self.pb.setValue(int(progress * 100))
|
self.pb.setValue(int(progress * 100))
|
||||||
if state == TOX_FILE_TRANSFER_STATE['CANCELED']:
|
state = self.convert(state)
|
||||||
self.setStyleSheet('QListWidget { background-color: #B40404; }')
|
if self.state != state:
|
||||||
self.cancel.setVisible(False)
|
if state == FILE_TRANSFER_MESSAGE_STATUS['CANCELLED']:
|
||||||
self.accept.setVisible(False)
|
self.setStyleSheet('QListWidget { border: 1px solid #B40404; }')
|
||||||
self.pb.setVisible(False)
|
self.cancel.setVisible(False)
|
||||||
elif state == TOX_FILE_TRANSFER_STATE['FINISHED']:
|
self.accept_or_pause.setVisible(False)
|
||||||
self.pb.setVisible(False)
|
self.pb.setVisible(False)
|
||||||
self.cancel.setVisible(False)
|
self.state = state
|
||||||
|
elif state == FILE_TRANSFER_MESSAGE_STATUS['FINISHED']:
|
||||||
|
self.accept_or_pause.setVisible(False)
|
||||||
|
self.pb.setVisible(False)
|
||||||
|
self.cancel.setVisible(False)
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
||||||
|
self.state = state
|
||||||
|
elif state == FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_FRIEND']:
|
||||||
|
self.accept_or_pause.setVisible(False)
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }')
|
||||||
|
self.state = state
|
||||||
|
elif state == FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_USER']:
|
||||||
|
self.button_update('resume') # setup button continue
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
||||||
|
self.state = state
|
||||||
|
elif not self.paused: # active
|
||||||
|
self.accept_or_pause.setVisible(True) # setup to pause
|
||||||
|
self.button_update('pause')
|
||||||
|
self.setStyleSheet('QListWidget { border: 1px solid green; }')
|
||||||
|
self.state = state
|
||||||
|
|
||||||
|
|
||||||
class InlineImageItem(QtGui.QWidget):
|
class InlineImageItem(QtGui.QWidget):
|
||||||
|
|
||||||
def __init__(self, data, parent=None):
|
def __init__(self, data, width, parent=None):
|
||||||
|
|
||||||
QtGui.QWidget.__init__(self, parent)
|
QtGui.QWidget.__init__(self, parent)
|
||||||
self.resize(QtCore.QSize(620, 500))
|
self.resize(QtCore.QSize(width, 500))
|
||||||
self._image_label = QtGui.QLabel(self)
|
self._image_label = QtGui.QLabel(self)
|
||||||
self._image_label.raise_()
|
self._image_label.raise_()
|
||||||
self._image_label.setAutoFillBackground(True)
|
self._image_label.setAutoFillBackground(True)
|
||||||
self._image_label.setScaledContents(False)
|
self._image_label.setScaledContents(False)
|
||||||
self.pixmap = QtGui.QPixmap()
|
self.pixmap = QtGui.QPixmap()
|
||||||
self.pixmap.loadFromData(QtCore.QByteArray(data), "PNG")
|
self.pixmap.loadFromData(QtCore.QByteArray(data), "PNG")
|
||||||
if self.pixmap.width() <= 600:
|
max_size = width - 40
|
||||||
|
if self.pixmap.width() <= max_size:
|
||||||
self._image_label.setPixmap(self.pixmap)
|
self._image_label.setPixmap(self.pixmap)
|
||||||
self.resize(QtCore.QSize(600, self.pixmap.height()))
|
self.resize(QtCore.QSize(max_size, self.pixmap.height()))
|
||||||
else:
|
else:
|
||||||
pixmap = self.pixmap.scaled(600, 600, QtCore.Qt.KeepAspectRatio)
|
pixmap = self.pixmap.scaled(max_size, max_size, QtCore.Qt.KeepAspectRatio)
|
||||||
self._image_label.setPixmap(pixmap)
|
self._image_label.setPixmap(pixmap)
|
||||||
self.resize(QtCore.QSize(600, pixmap.height()))
|
self.resize(QtCore.QSize(max_size, pixmap.height()))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
101
src/main.py
@@ -13,9 +13,10 @@ import locale
|
|||||||
|
|
||||||
class Toxygen(object):
|
class Toxygen(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, path=None):
|
||||||
super(Toxygen, self).__init__()
|
super(Toxygen, self).__init__()
|
||||||
self.tox = self.ms = self.init = self.mainloop = self.avloop = None
|
self.tox = self.ms = self.init = self.mainloop = self.avloop = None
|
||||||
|
self.path = path
|
||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
"""
|
"""
|
||||||
@@ -28,51 +29,57 @@ class Toxygen(object):
|
|||||||
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()
|
||||||
app.setStyleSheet(dark_style)
|
app.setStyleSheet(dark_style)
|
||||||
|
if self.path is not None:
|
||||||
auto_profile = Settings.get_auto_profile()
|
path = os.path.dirname(self.path.encode(locale.getpreferredencoding())) + '/'
|
||||||
if not auto_profile:
|
name = os.path.basename(self.path.encode(locale.getpreferredencoding()))[:-4]
|
||||||
# show login screen if default profile not found
|
|
||||||
current_locale = QtCore.QLocale()
|
|
||||||
curr_lang = current_locale.languageToString(current_locale.language())
|
|
||||||
langs = Settings.supported_languages()
|
|
||||||
if curr_lang in map(lambda x: x[0], langs):
|
|
||||||
lang_path = filter(lambda x: x[0] == curr_lang, langs)[0][1]
|
|
||||||
translator = QtCore.QTranslator()
|
|
||||||
translator.load(curr_directory() + '/translations/' + lang_path)
|
|
||||||
app.installTranslator(translator)
|
|
||||||
app.translator = translator
|
|
||||||
ls = LoginScreen()
|
|
||||||
ls.setWindowIconText("Toxygen")
|
|
||||||
profiles = ProfileHelper.find_profiles()
|
|
||||||
ls.update_select(map(lambda x: x[1], profiles))
|
|
||||||
_login = self.Login(profiles)
|
|
||||||
ls.update_on_close(_login.login_screen_close)
|
|
||||||
ls.show()
|
|
||||||
app.connect(app, QtCore.SIGNAL("lastWindowClosed()"), app, QtCore.SLOT("quit()"))
|
|
||||||
app.exec_()
|
|
||||||
if not _login.t:
|
|
||||||
return
|
|
||||||
elif _login.t == 1: # create new profile
|
|
||||||
name = _login.name if _login.name else 'toxygen_user'
|
|
||||||
self.tox = tox_factory()
|
|
||||||
self.tox.self_set_name(_login.name if _login.name else 'Toxygen User')
|
|
||||||
self.tox.self_set_status_message('Toxing on Toxygen')
|
|
||||||
ProfileHelper.save_profile(self.tox.get_savedata(), name)
|
|
||||||
path = Settings.get_default_path()
|
|
||||||
settings = Settings(name)
|
|
||||||
else: # load existing profile
|
|
||||||
path, name = _login.get_data()
|
|
||||||
if _login.default:
|
|
||||||
Settings.set_auto_profile(path, name)
|
|
||||||
data = ProfileHelper.open_profile(path, name)
|
|
||||||
settings = Settings(name)
|
|
||||||
self.tox = tox_factory(data, settings)
|
|
||||||
else:
|
|
||||||
path, name = auto_profile
|
|
||||||
path = path.encode(locale.getpreferredencoding())
|
|
||||||
data = ProfileHelper.open_profile(path, name)
|
data = ProfileHelper.open_profile(path, name)
|
||||||
settings = Settings(name)
|
settings = Settings(name)
|
||||||
self.tox = tox_factory(data, settings)
|
self.tox = tox_factory(data, settings)
|
||||||
|
else:
|
||||||
|
auto_profile = Settings.get_auto_profile()
|
||||||
|
if not auto_profile:
|
||||||
|
# show login screen if default profile not found
|
||||||
|
current_locale = QtCore.QLocale()
|
||||||
|
curr_lang = current_locale.languageToString(current_locale.language())
|
||||||
|
langs = Settings.supported_languages()
|
||||||
|
if curr_lang in map(lambda x: x[0], langs):
|
||||||
|
lang_path = filter(lambda x: x[0] == curr_lang, langs)[0][1]
|
||||||
|
translator = QtCore.QTranslator()
|
||||||
|
translator.load(curr_directory() + '/translations/' + lang_path)
|
||||||
|
app.installTranslator(translator)
|
||||||
|
app.translator = translator
|
||||||
|
ls = LoginScreen()
|
||||||
|
ls.setWindowIconText("Toxygen")
|
||||||
|
profiles = ProfileHelper.find_profiles()
|
||||||
|
ls.update_select(map(lambda x: x[1], profiles))
|
||||||
|
_login = self.Login(profiles)
|
||||||
|
ls.update_on_close(_login.login_screen_close)
|
||||||
|
ls.show()
|
||||||
|
app.connect(app, QtCore.SIGNAL("lastWindowClosed()"), app, QtCore.SLOT("quit()"))
|
||||||
|
app.exec_()
|
||||||
|
if not _login.t:
|
||||||
|
return
|
||||||
|
elif _login.t == 1: # create new profile
|
||||||
|
name = _login.name if _login.name else 'toxygen_user'
|
||||||
|
self.tox = tox_factory()
|
||||||
|
self.tox.self_set_name(_login.name if _login.name else 'Toxygen User')
|
||||||
|
self.tox.self_set_status_message('Toxing on Toxygen')
|
||||||
|
ProfileHelper.save_profile(self.tox.get_savedata(), name)
|
||||||
|
path = Settings.get_default_path()
|
||||||
|
settings = Settings(name)
|
||||||
|
else: # load existing profile
|
||||||
|
path, name = _login.get_data()
|
||||||
|
if _login.default:
|
||||||
|
Settings.set_auto_profile(path, name)
|
||||||
|
data = ProfileHelper.open_profile(path, name)
|
||||||
|
settings = Settings(name)
|
||||||
|
self.tox = tox_factory(data, settings)
|
||||||
|
else:
|
||||||
|
path, name = auto_profile
|
||||||
|
path = path.encode(locale.getpreferredencoding())
|
||||||
|
data = ProfileHelper.open_profile(path, name)
|
||||||
|
settings = Settings(name)
|
||||||
|
self.tox = tox_factory(data, settings)
|
||||||
|
|
||||||
if ProfileHelper.is_active_profile(path, name): # profile is in use
|
if ProfileHelper.is_active_profile(path, name): # profile is in use
|
||||||
reply = QtGui.QMessageBox.question(None,
|
reply = QtGui.QMessageBox.question(None,
|
||||||
@@ -110,6 +117,8 @@ class Toxygen(object):
|
|||||||
if not self.ms.isActiveWindow():
|
if not self.ms.isActiveWindow():
|
||||||
self.ms.setWindowState(self.ms.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
|
self.ms.setWindowState(self.ms.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
|
||||||
self.ms.activateWindow()
|
self.ms.activateWindow()
|
||||||
|
if self.ms.isHidden():
|
||||||
|
self.ms.show()
|
||||||
|
|
||||||
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()"), lambda: app.exit())
|
||||||
@@ -252,6 +261,8 @@ class Toxygen(object):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# TODO: add command line options
|
if len(sys.argv) == 1:
|
||||||
toxygen = Toxygen()
|
toxygen = Toxygen()
|
||||||
|
else: # path to profile
|
||||||
|
toxygen = Toxygen(sys.argv[1])
|
||||||
toxygen.main()
|
toxygen.main()
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ class MessageArea(QtGui.QPlainTextEdit):
|
|||||||
if modifiers & QtCore.Qt.ControlModifier or modifiers & QtCore.Qt.ShiftModifier:
|
if modifiers & QtCore.Qt.ControlModifier or modifiers & QtCore.Qt.ShiftModifier:
|
||||||
self.appendPlainText('')
|
self.appendPlainText('')
|
||||||
else:
|
else:
|
||||||
self.parent.send_message()
|
|
||||||
if self.timer.isActive():
|
if self.timer.isActive():
|
||||||
self.timer.stop()
|
self.timer.stop()
|
||||||
self.parent.profile.send_typing(False)
|
self.parent.profile.send_typing(False)
|
||||||
|
self.parent.send_message()
|
||||||
elif event.key() == QtCore.Qt.Key_Up and not self.toPlainText():
|
elif event.key() == QtCore.Qt.Key_Up and not self.toPlainText():
|
||||||
self.appendPlainText(Profile.get_instance().get_last_message())
|
self.appendPlainText(Profile.get_instance().get_last_message())
|
||||||
else:
|
else:
|
||||||
@@ -109,50 +109,70 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.actionAbout_program.setText(QtGui.QApplication.translate("MainWindow", "About program", None, QtGui.QApplication.UnicodeUTF8))
|
self.actionAbout_program.setText(QtGui.QApplication.translate("MainWindow", "About program", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.actionSettings.setText(QtGui.QApplication.translate("MainWindow", "Settings", None, QtGui.QApplication.UnicodeUTF8))
|
self.actionSettings.setText(QtGui.QApplication.translate("MainWindow", "Settings", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.audioSettings.setText(QtGui.QApplication.translate("MainWindow", "Audio", None, QtGui.QApplication.UnicodeUTF8))
|
self.audioSettings.setText(QtGui.QApplication.translate("MainWindow", "Audio", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.contact_name.setPlaceholderText(QtGui.QApplication.translate("MainWindow", "Find contact", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.screenshotButton.setToolTip(QtGui.QApplication.translate("MainWindow", "Send screenshot", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.fileTransferButton.setToolTip(QtGui.QApplication.translate("MainWindow", "Send file", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.sendMessageButton.setToolTip(QtGui.QApplication.translate("MainWindow", "Send message", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.callButton.setToolTip(QtGui.QApplication.translate("MainWindow", "Start audio call with friend", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
def setup_right_bottom(self, Form):
|
def setup_right_bottom(self, Form):
|
||||||
Form.setObjectName("right_bottom")
|
Form.setObjectName("right_bottom")
|
||||||
Form.resize(650, 100)
|
Form.resize(650, 75)
|
||||||
self.messageEdit = MessageArea(Form, self)
|
self.messageEdit = MessageArea(Form, self)
|
||||||
self.messageEdit.setGeometry(QtCore.QRect(0, 10, 450, 110))
|
self.messageEdit.setGeometry(QtCore.QRect(0, 5, 450, 70))
|
||||||
self.messageEdit.setObjectName("messageEdit")
|
self.messageEdit.setObjectName("messageEdit")
|
||||||
self.screenshotButton = QtGui.QPushButton(Form)
|
|
||||||
self.screenshotButton.setGeometry(QtCore.QRect(460, 10, 90, 55))
|
class QRightClickButton(QtGui.QPushButton):
|
||||||
|
def __init__(self, parent):
|
||||||
|
super(QRightClickButton, self).__init__(parent)
|
||||||
|
|
||||||
|
def mousePressEvent(self, event):
|
||||||
|
if event.button() == QtCore.Qt.RightButton:
|
||||||
|
self.emit(QtCore.SIGNAL("rightClicked()"))
|
||||||
|
else:
|
||||||
|
super(QRightClickButton, self).mousePressEvent(event)
|
||||||
|
|
||||||
|
self.screenshotButton = QRightClickButton(Form)
|
||||||
|
self.screenshotButton.setGeometry(QtCore.QRect(455, 5, 55, 70))
|
||||||
self.screenshotButton.setObjectName("screenshotButton")
|
self.screenshotButton.setObjectName("screenshotButton")
|
||||||
|
|
||||||
self.fileTransferButton = QtGui.QPushButton(Form)
|
self.fileTransferButton = QtGui.QPushButton(Form)
|
||||||
self.fileTransferButton.setGeometry(QtCore.QRect(460, 65, 90, 55))
|
self.fileTransferButton.setGeometry(QtCore.QRect(510, 5, 55, 70))
|
||||||
self.fileTransferButton.setObjectName("fileTransferButton")
|
self.fileTransferButton.setObjectName("fileTransferButton")
|
||||||
|
|
||||||
self.sendMessageButton = QtGui.QPushButton(Form)
|
self.sendMessageButton = QtGui.QPushButton(Form)
|
||||||
self.sendMessageButton.setGeometry(QtCore.QRect(550, 10, 70, 110))
|
self.sendMessageButton.setGeometry(QtCore.QRect(565, 5, 55, 70))
|
||||||
self.sendMessageButton.setObjectName("sendMessageButton")
|
self.sendMessageButton.setObjectName("sendMessageButton")
|
||||||
self.sendMessageButton.clicked.connect(self.send_message)
|
|
||||||
|
|
||||||
pixmap = QtGui.QPixmap(curr_directory() + '/images/send.png')
|
pixmap = QtGui.QPixmap(curr_directory() + '/images/send.png')
|
||||||
icon = QtGui.QIcon(pixmap)
|
icon = QtGui.QIcon(pixmap)
|
||||||
self.sendMessageButton.setIcon(icon)
|
self.sendMessageButton.setIcon(icon)
|
||||||
self.sendMessageButton.setIconSize(QtCore.QSize(50, 100))
|
self.sendMessageButton.setIconSize(QtCore.QSize(45, 60))
|
||||||
pixmap = QtGui.QPixmap(curr_directory() + '/images/file.png')
|
pixmap = QtGui.QPixmap(curr_directory() + '/images/file.png')
|
||||||
icon = QtGui.QIcon(pixmap)
|
icon = QtGui.QIcon(pixmap)
|
||||||
self.fileTransferButton.setIcon(icon)
|
self.fileTransferButton.setIcon(icon)
|
||||||
self.fileTransferButton.setIconSize(QtCore.QSize(90, 40))
|
self.fileTransferButton.setIconSize(QtCore.QSize(30, 45))
|
||||||
pixmap = QtGui.QPixmap(curr_directory() + '/images/screenshot.png')
|
pixmap = QtGui.QPixmap(curr_directory() + '/images/screenshot.png')
|
||||||
icon = QtGui.QIcon(pixmap)
|
icon = QtGui.QIcon(pixmap)
|
||||||
self.screenshotButton.setIcon(icon)
|
self.screenshotButton.setIcon(icon)
|
||||||
self.screenshotButton.setIconSize(QtCore.QSize(90, 40))
|
self.screenshotButton.setIconSize(QtCore.QSize(40, 60))
|
||||||
|
|
||||||
self.fileTransferButton.clicked.connect(self.send_file)
|
self.fileTransferButton.clicked.connect(self.send_file)
|
||||||
self.screenshotButton.clicked.connect(self.send_screenshot)
|
self.screenshotButton.clicked.connect(self.send_screenshot)
|
||||||
|
self.sendMessageButton.clicked.connect(self.send_message)
|
||||||
|
self.connect(self.screenshotButton, QtCore.SIGNAL("rightClicked()"), lambda: self.send_screenshot(True))
|
||||||
|
|
||||||
QtCore.QMetaObject.connectSlotsByName(Form)
|
QtCore.QMetaObject.connectSlotsByName(Form)
|
||||||
|
|
||||||
def setup_left_bottom(self, Form):
|
def setup_left_bottom(self, Form):
|
||||||
Form.setObjectName("left_bottom")
|
Form.setObjectName("left_bottom")
|
||||||
Form.resize(500, 60)
|
Form.resize(270, 80)
|
||||||
self.online_contacts = QtGui.QCheckBox(Form)
|
self.online_contacts = QtGui.QCheckBox(Form)
|
||||||
self.online_contacts.setGeometry(QtCore.QRect(0, 0, 250, 20))
|
self.online_contacts.setGeometry(QtCore.QRect(0, 0, 250, 20))
|
||||||
self.online_contacts.setObjectName("online_contacts")
|
self.online_contacts.setObjectName("online_contacts")
|
||||||
self.online_contacts.clicked.connect(self.filtering)
|
self.online_contacts.clicked.connect(self.filtering)
|
||||||
self.contact_name = QtGui.QLineEdit(Form)
|
self.contact_name = QtGui.QLineEdit(Form)
|
||||||
self.contact_name.setGeometry(QtCore.QRect(0, 27, 270, 30))
|
self.contact_name.setGeometry(QtCore.QRect(0, 23, 270, 26))
|
||||||
self.contact_name.setObjectName("contact_name")
|
self.contact_name.setObjectName("contact_name")
|
||||||
self.contact_name.textChanged.connect(self.filtering)
|
self.contact_name.textChanged.connect(self.filtering)
|
||||||
QtCore.QMetaObject.connectSlotsByName(Form)
|
QtCore.QMetaObject.connectSlotsByName(Form)
|
||||||
@@ -240,10 +260,11 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
def setup_right_center(self, widget):
|
def setup_right_center(self, widget):
|
||||||
self.messages = QtGui.QListWidget(widget)
|
self.messages = QtGui.QListWidget(widget)
|
||||||
self.messages.setGeometry(0, 0, 620, 250)
|
self.messages.setGeometry(0, 0, 620, 310)
|
||||||
self.messages.setObjectName("messages")
|
self.messages.setObjectName("messages")
|
||||||
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)
|
||||||
|
|
||||||
def load(pos):
|
def load(pos):
|
||||||
if not pos:
|
if not pos:
|
||||||
@@ -254,9 +275,9 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
def initUI(self, tox):
|
def initUI(self, tox):
|
||||||
self.setMinimumSize(920, 500)
|
self.setMinimumSize(920, 500)
|
||||||
self.setMaximumSize(920, 500)
|
|
||||||
self.setGeometry(400, 400, 920, 500)
|
self.setGeometry(400, 400, 920, 500)
|
||||||
self.setWindowTitle('Toxygen')
|
self.setWindowTitle('Toxygen')
|
||||||
|
os.chdir(curr_directory() + '/images/')
|
||||||
main = QtGui.QWidget()
|
main = QtGui.QWidget()
|
||||||
grid = QtGui.QGridLayout()
|
grid = QtGui.QGridLayout()
|
||||||
search = QtGui.QWidget()
|
search = QtGui.QWidget()
|
||||||
@@ -279,8 +300,11 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
grid.addWidget(main_list, 1, 0, 2, 1)
|
grid.addWidget(main_list, 1, 0, 2, 1)
|
||||||
grid.setColumnMinimumWidth(1, 500)
|
grid.setColumnMinimumWidth(1, 500)
|
||||||
grid.setColumnMinimumWidth(0, 270)
|
grid.setColumnMinimumWidth(0, 270)
|
||||||
grid.setRowMinimumHeight(1, 250)
|
grid.setRowMinimumHeight(1, 400)
|
||||||
|
grid.setRowMinimumHeight(2, 20)
|
||||||
grid.setRowMinimumHeight(3, 50)
|
grid.setRowMinimumHeight(3, 50)
|
||||||
|
grid.setColumnStretch(1, 1)
|
||||||
|
grid.setRowStretch(1, 1)
|
||||||
main.setLayout(grid)
|
main.setLayout(grid)
|
||||||
self.setCentralWidget(main)
|
self.setCentralWidget(main)
|
||||||
self.setup_menu(self)
|
self.setup_menu(self)
|
||||||
@@ -294,6 +318,25 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
self.profile.close()
|
self.profile.close()
|
||||||
QtGui.QApplication.closeAllWindows()
|
QtGui.QApplication.closeAllWindows()
|
||||||
|
|
||||||
|
def resizeEvent(self, *args, **kwargs):
|
||||||
|
self.messages.setGeometry(0, 0, self.width() - 300, self.height() - 205)
|
||||||
|
self.friends_list.setGeometry(0, 0, 270, self.height() - 180)
|
||||||
|
self.callButton.setGeometry(QtCore.QRect(self.width() - 370, 30, 50, 50))
|
||||||
|
self.typing.setGeometry(QtCore.QRect(self.width() - 420, 40, 50, 30))
|
||||||
|
self.messageEdit.setGeometry(QtCore.QRect(0, 5, self.width() - 470, 70))
|
||||||
|
self.screenshotButton.setGeometry(QtCore.QRect(self.width() - 465, 5, 55, 70))
|
||||||
|
self.fileTransferButton.setGeometry(QtCore.QRect(self.width() - 410, 5, 55, 70))
|
||||||
|
self.sendMessageButton.setGeometry(QtCore.QRect(self.width() - 355, 5, 55, 70))
|
||||||
|
self.account_name.setGeometry(QtCore.QRect(100, 30, self.width() - 520, 25))
|
||||||
|
self.account_status.setGeometry(QtCore.QRect(100, 50, self.width() - 520, 25))
|
||||||
|
self.profile.update()
|
||||||
|
|
||||||
|
def keyPressEvent(self, event):
|
||||||
|
if event.key() == QtCore.Qt.Key_Escape:
|
||||||
|
self.hide()
|
||||||
|
else:
|
||||||
|
super(MainWindow, self).keyPressEvent(event)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Functions which called when user click in menu
|
# Functions which called when user click in menu
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
@@ -302,7 +345,8 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
import util
|
import util
|
||||||
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))
|
||||||
msgBox.setText(QtGui.QApplication.translate("MainWindow", 'Toxygen is Tox client written on Python 2.7. Version: ', None, QtGui.QApplication.UnicodeUTF8) + util.program_version)
|
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.exec_()
|
msgBox.exec_()
|
||||||
|
|
||||||
def network_settings(self):
|
def network_settings(self):
|
||||||
@@ -343,15 +387,18 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
def send_file(self):
|
def send_file(self):
|
||||||
if self.profile.is_active_online(): # active friend exists and online
|
if self.profile.is_active_online(): # active friend exists and online
|
||||||
choose = QtGui.QApplication.translate("MainWindow", "Choose file", None, QtGui.QApplication.UnicodeUTF8)
|
choose_file = 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)
|
name = QtGui.QFileDialog.getOpenFileName(self, choose)
|
||||||
if name[0]:
|
if name[0]:
|
||||||
self.profile.send_file(name[0])
|
self.profile.send_file(name[0])
|
||||||
|
|
||||||
def send_screenshot(self):
|
def send_screenshot(self, hide=False):
|
||||||
if self.profile.is_active_online(): # active friend exists and online
|
if self.profile.is_active_online(): # active friend exists and online
|
||||||
self.sw = ScreenShotWindow()
|
self.sw = ScreenShotWindow(self)
|
||||||
self.sw.show()
|
self.sw.show()
|
||||||
|
if hide:
|
||||||
|
self.hide()
|
||||||
|
|
||||||
def call(self):
|
def call(self):
|
||||||
if self.profile.is_active_online(): # active friend exists and online
|
if self.profile.is_active_online(): # active friend exists and online
|
||||||
@@ -419,8 +466,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
if value:
|
if value:
|
||||||
settings['auto_accept_from_friends'].append(tox_id)
|
settings['auto_accept_from_friends'].append(tox_id)
|
||||||
else:
|
else:
|
||||||
index = settings['auto_accept_from_friends'].index(tox_id)
|
settings['auto_accept_from_friends'].remove(tox_id)
|
||||||
del settings['auto_accept_from_friends'][index]
|
|
||||||
settings.save()
|
settings.save()
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
@@ -445,14 +491,19 @@ class MainWindow(QtGui.QMainWindow):
|
|||||||
|
|
||||||
class ScreenShotWindow(QtGui.QWidget):
|
class ScreenShotWindow(QtGui.QWidget):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, parent):
|
||||||
super(ScreenShotWindow, self).__init__()
|
super(ScreenShotWindow, self).__init__()
|
||||||
|
self.parent = parent
|
||||||
self.setMouseTracking(True)
|
self.setMouseTracking(True)
|
||||||
self.setWindowFlags(self.windowFlags() | QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
|
self.setWindowFlags(self.windowFlags() | QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
|
||||||
self.showFullScreen()
|
self.showFullScreen()
|
||||||
self.setWindowOpacity(0.5)
|
self.setWindowOpacity(0.5)
|
||||||
self.rubberband = QtGui.QRubberBand(QtGui.QRubberBand.Rectangle, None)
|
self.rubberband = QtGui.QRubberBand(QtGui.QRubberBand.Rectangle, None)
|
||||||
|
|
||||||
|
def closeEvent(self, *args):
|
||||||
|
if self.parent.isHidden():
|
||||||
|
self.parent.show()
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
self.origin = event.pos()
|
self.origin = event.pos()
|
||||||
self.rubberband.setGeometry(QtCore.QRect(self.origin, QtCore.QSize()))
|
self.rubberband.setGeometry(QtCore.QRect(self.origin, QtCore.QSize()))
|
||||||
@@ -473,16 +524,17 @@ class ScreenShotWindow(QtGui.QWidget):
|
|||||||
self.rubberband.hide()
|
self.rubberband.hide()
|
||||||
rect = self.rubberband.geometry()
|
rect = self.rubberband.geometry()
|
||||||
print rect
|
print rect
|
||||||
p = QtGui.QPixmap.grabWindow(QtGui.QApplication.desktop().winId(),
|
if rect.width() and rect.height():
|
||||||
rect.x() + 4,
|
p = QtGui.QPixmap.grabWindow(QtGui.QApplication.desktop().winId(),
|
||||||
rect.y() + 4,
|
rect.x() + 4,
|
||||||
rect.width() - 8,
|
rect.y() + 4,
|
||||||
rect.height() - 8)
|
rect.width() - 8,
|
||||||
byte_array = QtCore.QByteArray()
|
rect.height() - 8)
|
||||||
buffer = QtCore.QBuffer(byte_array)
|
byte_array = QtCore.QByteArray()
|
||||||
buffer.open(QtCore.QIODevice.WriteOnly)
|
buffer = QtCore.QBuffer(byte_array)
|
||||||
p.save(buffer, 'PNG')
|
buffer.open(QtCore.QIODevice.WriteOnly)
|
||||||
Profile.get_instance().send_screenshot(str(byte_array.data()))
|
p.save(buffer, 'PNG')
|
||||||
|
Profile.get_instance().send_screenshot(str(byte_array.data()))
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
|
|||||||
106
src/menu.py
@@ -2,7 +2,7 @@ from PySide import QtCore, QtGui
|
|||||||
from settings import *
|
from settings import *
|
||||||
from profile import Profile
|
from profile import Profile
|
||||||
from util import get_style, curr_directory
|
from util import get_style, curr_directory
|
||||||
from widgets import CenteredWidget
|
from widgets import CenteredWidget, DataLabel
|
||||||
import pyaudio
|
import pyaudio
|
||||||
|
|
||||||
|
|
||||||
@@ -26,28 +26,29 @@ class AddContact(CenteredWidget):
|
|||||||
self.tox_id.setGeometry(QtCore.QRect(50, 40, 471, 27))
|
self.tox_id.setGeometry(QtCore.QRect(50, 40, 471, 27))
|
||||||
self.tox_id.setObjectName("lineEdit")
|
self.tox_id.setObjectName("lineEdit")
|
||||||
self.label = QtGui.QLabel(self)
|
self.label = QtGui.QLabel(self)
|
||||||
self.label.setGeometry(QtCore.QRect(30, 10, 80, 20))
|
self.label.setGeometry(QtCore.QRect(60, 10, 80, 20))
|
||||||
self.error_label = QtGui.QLabel(self)
|
self.error_label = DataLabel(self)
|
||||||
self.error_label.setGeometry(QtCore.QRect(120, 10, 400, 20))
|
self.error_label.setGeometry(QtCore.QRect(120, 10, 420, 20))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(16)
|
font.setPointSize(10)
|
||||||
font.setWeight(75)
|
font.setWeight(30)
|
||||||
font.setBold(True)
|
|
||||||
self.label.setFont(font)
|
|
||||||
font.setPointSize(12)
|
|
||||||
font.setBold(False)
|
|
||||||
font.setWeight(40)
|
|
||||||
self.error_label.setFont(font)
|
self.error_label.setFont(font)
|
||||||
self.error_label.setStyleSheet("QLabel { color: red; }")
|
self.error_label.setStyleSheet("QLabel { color: red; }")
|
||||||
self.label.setObjectName("label")
|
self.label.setObjectName("label")
|
||||||
self.message_edit = QtGui.QTextEdit(self)
|
self.message_edit = QtGui.QTextEdit(self)
|
||||||
self.message_edit.setGeometry(QtCore.QRect(50, 110, 471, 151))
|
self.message_edit.setGeometry(QtCore.QRect(50, 110, 471, 151))
|
||||||
self.message_edit.setObjectName("textEdit")
|
self.message_edit.setObjectName("textEdit")
|
||||||
self.label_2 = QtGui.QLabel(self)
|
self.message = QtGui.QLabel(self)
|
||||||
self.label_2.setGeometry(QtCore.QRect(60, 70, 101, 31))
|
self.message.setGeometry(QtCore.QRect(60, 70, 101, 31))
|
||||||
self.label_2.setFont(font)
|
self.message.setFont(font)
|
||||||
self.label_2.setObjectName("label_2")
|
self.message.setObjectName("label_2")
|
||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
|
self.message_edit.setText('Hello! Add me to your contact list please')
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(12)
|
||||||
|
font.setBold(True)
|
||||||
|
self.label.setFont(font)
|
||||||
|
self.message.setFont(font)
|
||||||
QtCore.QMetaObject.connectSlotsByName(self)
|
QtCore.QMetaObject.connectSlotsByName(self)
|
||||||
|
|
||||||
def add_friend(self):
|
def add_friend(self):
|
||||||
@@ -57,15 +58,13 @@ class AddContact(CenteredWidget):
|
|||||||
# request was successful
|
# request was successful
|
||||||
self.close()
|
self.close()
|
||||||
else: # print error data
|
else: # print error data
|
||||||
if len(send) > 40:
|
|
||||||
send = send[:40] + '...'
|
|
||||||
self.error_label.setText(send)
|
self.error_label.setText(send)
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslateUi(self):
|
||||||
self.setWindowTitle(QtGui.QApplication.translate('AddContact', "Add contact", None, QtGui.QApplication.UnicodeUTF8))
|
self.setWindowTitle(QtGui.QApplication.translate('AddContact', "Add contact", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.sendRequestButton.setText(QtGui.QApplication.translate("Form", "Send request", None, QtGui.QApplication.UnicodeUTF8))
|
self.sendRequestButton.setText(QtGui.QApplication.translate("Form", "Send request", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label.setText(QtGui.QApplication.translate('AddContact', "TOX ID:", None, QtGui.QApplication.UnicodeUTF8))
|
self.label.setText(QtGui.QApplication.translate('AddContact', "TOX ID:", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label_2.setText(QtGui.QApplication.translate('AddContact', "Message:", None, QtGui.QApplication.UnicodeUTF8))
|
self.message.setText(QtGui.QApplication.translate('AddContact', "Message:", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
|
|
||||||
class ProfileSettings(CenteredWidget):
|
class ProfileSettings(CenteredWidget):
|
||||||
@@ -76,8 +75,8 @@ class ProfileSettings(CenteredWidget):
|
|||||||
|
|
||||||
def initUI(self):
|
def initUI(self):
|
||||||
self.setObjectName("ProfileSettingsForm")
|
self.setObjectName("ProfileSettingsForm")
|
||||||
self.setMinimumSize(QtCore.QSize(650, 370))
|
self.setMinimumSize(QtCore.QSize(650, 320))
|
||||||
self.setMaximumSize(QtCore.QSize(650, 370))
|
self.setMaximumSize(QtCore.QSize(650, 320))
|
||||||
self.nick = QtGui.QLineEdit(self)
|
self.nick = QtGui.QLineEdit(self)
|
||||||
self.nick.setGeometry(QtCore.QRect(30, 60, 350, 27))
|
self.nick.setGeometry(QtCore.QRect(30, 60, 350, 27))
|
||||||
self.nick.setObjectName("nick")
|
self.nick.setObjectName("nick")
|
||||||
@@ -88,7 +87,7 @@ class ProfileSettings(CenteredWidget):
|
|||||||
self.status.setObjectName("status")
|
self.status.setObjectName("status")
|
||||||
self.status.setText(profile.status_message)
|
self.status.setText(profile.status_message)
|
||||||
self.label = QtGui.QLabel(self)
|
self.label = QtGui.QLabel(self)
|
||||||
self.label.setGeometry(QtCore.QRect(50, 30, 91, 21))
|
self.label.setGeometry(QtCore.QRect(40, 30, 91, 25))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(18)
|
font.setPointSize(18)
|
||||||
font.setWeight(75)
|
font.setWeight(75)
|
||||||
@@ -96,11 +95,11 @@ class ProfileSettings(CenteredWidget):
|
|||||||
self.label.setFont(font)
|
self.label.setFont(font)
|
||||||
self.label.setObjectName("label")
|
self.label.setObjectName("label")
|
||||||
self.label_2 = QtGui.QLabel(self)
|
self.label_2 = QtGui.QLabel(self)
|
||||||
self.label_2.setGeometry(QtCore.QRect(40, 100, 100, 21))
|
self.label_2.setGeometry(QtCore.QRect(40, 100, 100, 25))
|
||||||
self.label_2.setFont(font)
|
self.label_2.setFont(font)
|
||||||
self.label_2.setObjectName("label_2")
|
self.label_2.setObjectName("label_2")
|
||||||
self.label_3 = QtGui.QLabel(self)
|
self.label_3 = QtGui.QLabel(self)
|
||||||
self.label_3.setGeometry(QtCore.QRect(40, 170, 100, 21))
|
self.label_3.setGeometry(QtCore.QRect(40, 180, 100, 25))
|
||||||
self.label_3.setFont(font)
|
self.label_3.setFont(font)
|
||||||
self.label_3.setObjectName("label_3")
|
self.label_3.setObjectName("label_3")
|
||||||
self.tox_id = QtGui.QLabel(self)
|
self.tox_id = QtGui.QLabel(self)
|
||||||
@@ -111,13 +110,16 @@ class ProfileSettings(CenteredWidget):
|
|||||||
s = profile.tox_id
|
s = profile.tox_id
|
||||||
self.tox_id.setText(s)
|
self.tox_id.setText(s)
|
||||||
self.copyId = QtGui.QPushButton(self)
|
self.copyId = QtGui.QPushButton(self)
|
||||||
self.copyId.setGeometry(QtCore.QRect(40, 250, 150, 30))
|
self.copyId.setGeometry(QtCore.QRect(40, 250, 160, 30))
|
||||||
self.copyId.setObjectName("copyId")
|
self.copyId.setObjectName("copyId")
|
||||||
self.copyId.clicked.connect(self.copy)
|
self.copyId.clicked.connect(self.copy)
|
||||||
self.export = QtGui.QPushButton(self)
|
self.export = QtGui.QPushButton(self)
|
||||||
self.export.setGeometry(QtCore.QRect(200, 250, 150, 30))
|
self.export.setGeometry(QtCore.QRect(210, 250, 160, 30))
|
||||||
self.export.setObjectName("export")
|
self.export.setObjectName("export")
|
||||||
self.export.clicked.connect(self.export_profile)
|
self.export.clicked.connect(self.export_profile)
|
||||||
|
self.new_nospam = QtGui.QPushButton(self)
|
||||||
|
self.new_nospam.setGeometry(QtCore.QRect(380, 250, 160, 30))
|
||||||
|
self.new_nospam.clicked.connect(self.new_no_spam)
|
||||||
self.new_avatar = QtGui.QPushButton(self)
|
self.new_avatar = QtGui.QPushButton(self)
|
||||||
self.new_avatar.setGeometry(QtCore.QRect(400, 50, 200, 50))
|
self.new_avatar.setGeometry(QtCore.QRect(400, 50, 200, 50))
|
||||||
self.delete_avatar = QtGui.QPushButton(self)
|
self.delete_avatar = QtGui.QPushButton(self)
|
||||||
@@ -136,18 +138,25 @@ class ProfileSettings(CenteredWidget):
|
|||||||
self.copyId.setText(QtGui.QApplication.translate("ProfileSettingsForm", "Copy TOX ID", None, QtGui.QApplication.UnicodeUTF8))
|
self.copyId.setText(QtGui.QApplication.translate("ProfileSettingsForm", "Copy TOX ID", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.new_avatar.setText(QtGui.QApplication.translate("ProfileSettingsForm", "New avatar", None, QtGui.QApplication.UnicodeUTF8))
|
self.new_avatar.setText(QtGui.QApplication.translate("ProfileSettingsForm", "New avatar", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.delete_avatar.setText(QtGui.QApplication.translate("ProfileSettingsForm", "Reset avatar", None, QtGui.QApplication.UnicodeUTF8))
|
self.delete_avatar.setText(QtGui.QApplication.translate("ProfileSettingsForm", "Reset avatar", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.new_nospam.setText(QtGui.QApplication.translate("ProfileSettingsForm", "New NoSpam", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
clipboard = QtGui.QApplication.clipboard()
|
clipboard = QtGui.QApplication.clipboard()
|
||||||
profile = Profile.get_instance()
|
profile = Profile.get_instance()
|
||||||
clipboard.setText(profile.tox_id)
|
clipboard.setText(profile.tox_id)
|
||||||
|
pixmap = QtGui.QPixmap(curr_directory() + '/images/accept.png')
|
||||||
|
icon = QtGui.QIcon(pixmap)
|
||||||
|
self.copyId.setIcon(icon)
|
||||||
|
self.copyId.setIconSize(QtCore.QSize(10, 10))
|
||||||
|
|
||||||
|
def new_no_spam(self):
|
||||||
|
self.tox_id.setText(Profile.get_instance().new_nospam())
|
||||||
|
|
||||||
def reset_avatar(self):
|
def reset_avatar(self):
|
||||||
Profile.get_instance().reset_avatar()
|
Profile.get_instance().reset_avatar()
|
||||||
|
|
||||||
def set_avatar(self):
|
def set_avatar(self):
|
||||||
name = QtGui.QFileDialog.getOpenFileName(self, 'Open file', None, 'Image Files (*.png)')
|
name = QtGui.QFileDialog.getOpenFileName(self, 'Open file', None, 'Image Files (*.png)')
|
||||||
print name
|
|
||||||
if name[0]:
|
if name[0]:
|
||||||
with open(name[0], 'rb') as f:
|
with open(name[0], 'rb') as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
@@ -173,7 +182,6 @@ class NetworkSettings(CenteredWidget):
|
|||||||
def __init__(self, reset):
|
def __init__(self, reset):
|
||||||
super(NetworkSettings, self).__init__()
|
super(NetworkSettings, self).__init__()
|
||||||
self.reset = reset
|
self.reset = reset
|
||||||
self.reconn = False
|
|
||||||
self.initUI()
|
self.initUI()
|
||||||
|
|
||||||
def initUI(self):
|
def initUI(self):
|
||||||
@@ -204,14 +212,15 @@ class NetworkSettings(CenteredWidget):
|
|||||||
self.label_2 = QtGui.QLabel(self)
|
self.label_2 = QtGui.QLabel(self)
|
||||||
self.label_2.setGeometry(QtCore.QRect(40, 165, 66, 17))
|
self.label_2.setGeometry(QtCore.QRect(40, 165, 66, 17))
|
||||||
self.reconnect = QtGui.QPushButton(self)
|
self.reconnect = QtGui.QPushButton(self)
|
||||||
self.reconnect.setGeometry(QtCore.QRect(40, 230, 200, 30))
|
self.reconnect.setGeometry(QtCore.QRect(40, 230, 231, 30))
|
||||||
self.reconnect.clicked.connect(self.restart_core)
|
self.reconnect.clicked.connect(self.restart_core)
|
||||||
settings = Settings.get_instance()
|
settings = Settings.get_instance()
|
||||||
self.ipv.setChecked(settings['ipv6_enabled'])
|
self.ipv.setChecked(settings['ipv6_enabled'])
|
||||||
self.udp.setChecked(settings['udp_enabled'])
|
self.udp.setChecked(settings['udp_enabled'])
|
||||||
self.proxy.setChecked(settings['proxy_type'] != 0)
|
self.proxy.setChecked(settings['proxy_type'])
|
||||||
self.proxyip.setText(settings['proxy_host'])
|
self.proxyip.setText(settings['proxy_host'])
|
||||||
self.proxyport.setText(unicode(settings['proxy_port']))
|
self.proxyport.setText(unicode(settings['proxy_port']))
|
||||||
|
self.http.setChecked(settings['proxy_type'] == 1)
|
||||||
self.retranslateUi()
|
self.retranslateUi()
|
||||||
self.proxy.stateChanged.connect(lambda x: self.activate())
|
self.proxy.stateChanged.connect(lambda x: self.activate())
|
||||||
self.activate()
|
self.activate()
|
||||||
@@ -233,27 +242,20 @@ class NetworkSettings(CenteredWidget):
|
|||||||
self.http.setEnabled(bl)
|
self.http.setEnabled(bl)
|
||||||
self.proxyport.setEnabled(bl)
|
self.proxyport.setEnabled(bl)
|
||||||
|
|
||||||
def closeEvent(self, *args, **kwargs):
|
def restart_core(self):
|
||||||
settings = Settings.get_instance()
|
try:
|
||||||
old_data = str(settings['ipv6_enabled']) + str(settings['udp_enabled']) + str(bool(settings['proxy_type']))
|
settings = Settings.get_instance()
|
||||||
new_data = str(self.ipv.isChecked()) + str(self.udp.isChecked()) + str(self.proxy.isChecked())
|
|
||||||
changed = old_data != new_data
|
|
||||||
if self.proxy.isChecked() and (self.proxyip.text() != settings['proxy_host'] or self.proxyport.text() != unicode(settings['proxy_port'])):
|
|
||||||
changed = True
|
|
||||||
if changed:
|
|
||||||
settings['ipv6_enabled'] = self.ipv.isChecked()
|
settings['ipv6_enabled'] = self.ipv.isChecked()
|
||||||
settings['udp_enabled'] = self.udp.isChecked()
|
settings['udp_enabled'] = self.udp.isChecked()
|
||||||
settings['proxy_type'] = 2 - int(self.http.isChecked())
|
settings['proxy_type'] = 2 - int(self.http.isChecked()) if self.proxy.isChecked() else 0
|
||||||
settings['proxy_host'] = self.proxyip.text()
|
settings['proxy_host'] = str(self.proxyip.text())
|
||||||
settings['proxy_port'] = int(self.proxyport.text())
|
settings['proxy_port'] = int(self.proxyport.text())
|
||||||
settings.save()
|
settings.save()
|
||||||
if changed or self.reconnect:
|
|
||||||
# recreate tox instance
|
# recreate tox instance
|
||||||
Profile.get_instance().reset(self.reset)
|
Profile.get_instance().reset(self.reset)
|
||||||
|
self.close()
|
||||||
def restart_core(self):
|
except:
|
||||||
self.reconn = True
|
pass
|
||||||
self.close()
|
|
||||||
|
|
||||||
|
|
||||||
class PrivacySettings(CenteredWidget):
|
class PrivacySettings(CenteredWidget):
|
||||||
@@ -269,21 +271,21 @@ class PrivacySettings(CenteredWidget):
|
|||||||
self.setMinimumSize(QtCore.QSize(350, 550))
|
self.setMinimumSize(QtCore.QSize(350, 550))
|
||||||
self.setMaximumSize(QtCore.QSize(350, 550))
|
self.setMaximumSize(QtCore.QSize(350, 550))
|
||||||
self.saveHistory = QtGui.QCheckBox(self)
|
self.saveHistory = QtGui.QCheckBox(self)
|
||||||
self.saveHistory.setGeometry(QtCore.QRect(40, 20, 291, 22))
|
self.saveHistory.setGeometry(QtCore.QRect(10, 20, 291, 22))
|
||||||
self.saveHistory.setObjectName("saveHistory")
|
self.saveHistory.setObjectName("saveHistory")
|
||||||
self.fileautoaccept = QtGui.QCheckBox(self)
|
self.fileautoaccept = QtGui.QCheckBox(self)
|
||||||
self.fileautoaccept.setGeometry(QtCore.QRect(40, 60, 271, 22))
|
self.fileautoaccept.setGeometry(QtCore.QRect(10, 60, 271, 22))
|
||||||
self.fileautoaccept.setObjectName("fileautoaccept")
|
self.fileautoaccept.setObjectName("fileautoaccept")
|
||||||
self.typingNotifications = QtGui.QCheckBox(self)
|
self.typingNotifications = QtGui.QCheckBox(self)
|
||||||
self.typingNotifications.setGeometry(QtCore.QRect(40, 100, 350, 30))
|
self.typingNotifications.setGeometry(QtCore.QRect(10, 100, 350, 30))
|
||||||
self.typingNotifications.setObjectName("typingNotifications")
|
self.typingNotifications.setObjectName("typingNotifications")
|
||||||
self.inlines = QtGui.QCheckBox(self)
|
self.inlines = QtGui.QCheckBox(self)
|
||||||
self.inlines.setGeometry(QtCore.QRect(40, 140, 350, 30))
|
self.inlines.setGeometry(QtCore.QRect(10, 140, 350, 30))
|
||||||
self.inlines.setObjectName("inlines")
|
self.inlines.setObjectName("inlines")
|
||||||
|
|
||||||
|
|
||||||
self.auto_path = QtGui.QLabel(self)
|
self.auto_path = QtGui.QLabel(self)
|
||||||
self.auto_path.setGeometry(QtCore.QRect(40, 190, 350, 30))
|
self.auto_path.setGeometry(QtCore.QRect(10, 190, 350, 30))
|
||||||
self.path = QtGui.QPlainTextEdit(self)
|
self.path = QtGui.QPlainTextEdit(self)
|
||||||
self.path.setGeometry(QtCore.QRect(10, 225, 330, 45))
|
self.path.setGeometry(QtCore.QRect(10, 225, 330, 45))
|
||||||
self.change_path = QtGui.QPushButton(self)
|
self.change_path = QtGui.QPushButton(self)
|
||||||
@@ -382,6 +384,12 @@ class NotificationsSettings(CenteredWidget):
|
|||||||
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))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(12)
|
||||||
|
font.setBold(True)
|
||||||
|
self.callsSound.setFont(font)
|
||||||
|
self.soundNotifications.setFont(font)
|
||||||
|
self.enableNotifications.setFont(font)
|
||||||
s = Settings.get_instance()
|
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'])
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ FILE_TRANSFER_MESSAGE_STATUS = {
|
|||||||
'CANCELLED': 1,
|
'CANCELLED': 1,
|
||||||
'OUTGOING': 2,
|
'OUTGOING': 2,
|
||||||
'INCOMING_NOT_STARTED': 3,
|
'INCOMING_NOT_STARTED': 3,
|
||||||
'INCOMING_STARTED': 4
|
'INCOMING_STARTED': 4,
|
||||||
|
'PAUSED_BY_FRIEND': 5,
|
||||||
|
'PAUSED_BY_USER': 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
140
src/profile.py
@@ -207,7 +207,7 @@ class Friend(Contact):
|
|||||||
"""
|
"""
|
||||||
if hasattr(self, '_message_getter'):
|
if hasattr(self, '_message_getter'):
|
||||||
del self._message_getter
|
del self._message_getter
|
||||||
self._corr = filter(lambda x: x.get_type() == 2 and x.get_status() in (2, 4), self._corr)
|
self._corr = filter(lambda x: x.get_type() == 2 and x.get_status() >= 2, self._corr)
|
||||||
self._unsaved_messages = 0
|
self._unsaved_messages = 0
|
||||||
|
|
||||||
def update_transfer_data(self, file_number, status, inline=None):
|
def update_transfer_data(self, file_number, status, inline=None):
|
||||||
@@ -341,6 +341,12 @@ class Profile(Contact, Singleton):
|
|||||||
super(self.__class__, self).set_status_message(value)
|
super(self.__class__, self).set_status_message(value)
|
||||||
self._tox.self_set_status_message(self._status_message.encode('utf-8'))
|
self._tox.self_set_status_message(self._status_message.encode('utf-8'))
|
||||||
|
|
||||||
|
def new_nospam(self):
|
||||||
|
import random
|
||||||
|
self._tox.self_set_nospam(random.randint(0, 4294967295)) # no spam - uint32
|
||||||
|
self._tox_id = self._tox.self_get_address()
|
||||||
|
return self._tox_id
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Filtration
|
# Filtration
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
@@ -381,6 +387,7 @@ class Profile(Contact, Singleton):
|
|||||||
|
|
||||||
def set_active(self, value=None):
|
def set_active(self, value=None):
|
||||||
"""
|
"""
|
||||||
|
Change current active friend or update info
|
||||||
:param value: number of new active friend in friend's list or None to update active user's data
|
:param value: number of new active friend in friend's list or None to update active user's data
|
||||||
"""
|
"""
|
||||||
if value is None and self._active_friend == -1: # nothing to update
|
if value is None and self._active_friend == -1: # nothing to update
|
||||||
@@ -413,9 +420,13 @@ class Profile(Contact, Singleton):
|
|||||||
data[3])
|
data[3])
|
||||||
elif message.get_type() == 2:
|
elif message.get_type() == 2:
|
||||||
item = self.create_file_transfer_item(message)
|
item = self.create_file_transfer_item(message)
|
||||||
if message.get_status() in (2, 4): # active file transfer
|
if message.get_status() >= 2: # active file transfer
|
||||||
ft = self._file_transfers[(message.get_friend_number(), message.get_file_number())]
|
try:
|
||||||
ft.set_state_changed_handler(item.update)
|
ft = self._file_transfers[(message.get_friend_number(), message.get_file_number())]
|
||||||
|
ft.set_state_changed_handler(item.update)
|
||||||
|
ft.signal()
|
||||||
|
except:
|
||||||
|
print 'Incoming not started transfer - no info found'
|
||||||
else: # inline
|
else: # inline
|
||||||
self.create_inline_item(message.get_data())
|
self.create_inline_item(message.get_data())
|
||||||
self._messages.scrollToBottom()
|
self._messages.scrollToBottom()
|
||||||
@@ -433,6 +444,7 @@ class Profile(Contact, Singleton):
|
|||||||
avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(friend.tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
|
avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(friend.tox_id[:TOX_PUBLIC_KEY_SIZE * 2])
|
||||||
if not os.path.isfile(avatar_path): # load default image
|
if not os.path.isfile(avatar_path): # load default image
|
||||||
avatar_path = curr_directory() + '/images/avatar.png'
|
avatar_path = curr_directory() + '/images/avatar.png'
|
||||||
|
os.chdir(os.path.dirname(avatar_path))
|
||||||
pixmap = QtGui.QPixmap(QtCore.QSize(64, 64))
|
pixmap = QtGui.QPixmap(QtCore.QSize(64, 64))
|
||||||
pixmap.load(avatar_path)
|
pixmap.load(avatar_path)
|
||||||
self._screen.account_avatar.setScaledContents(False)
|
self._screen.account_avatar.setScaledContents(False)
|
||||||
@@ -456,17 +468,36 @@ class Profile(Contact, Singleton):
|
|||||||
def is_active_online(self):
|
def is_active_online(self):
|
||||||
return self._active_friend + 1 and self._friends[self._active_friend].status is not None
|
return self._active_friend + 1 and self._friends[self._active_friend].status is not None
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
if self._active_friend + 1:
|
||||||
|
self.set_active(self._active_friend)
|
||||||
|
|
||||||
|
def friend_exit(self, friend_number):
|
||||||
|
self.get_friend_by_number(friend_number).status = None
|
||||||
|
self.friend_typing(friend_number, False)
|
||||||
|
if friend_number in self._call:
|
||||||
|
self._call.finish_call(friend_number, True)
|
||||||
|
for key in filter(lambda x: x[0] == friend_number, self._file_transfers.keys()):
|
||||||
|
self._file_transfers[key].cancelled()
|
||||||
|
del self._file_transfers[key]
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Typing notifications
|
# Typing notifications
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
def send_typing(self, typing):
|
def send_typing(self, typing):
|
||||||
|
"""
|
||||||
|
Send typing notification to a friend
|
||||||
|
"""
|
||||||
if Settings.get_instance()['typing_notifications']:
|
if Settings.get_instance()['typing_notifications']:
|
||||||
friend = self._friends[self._active_friend]
|
friend = self._friends[self._active_friend]
|
||||||
if friend.status is not None:
|
if friend.status is not None:
|
||||||
self._tox.self_set_typing(friend.number, typing)
|
self._tox.self_set_typing(friend.number, typing)
|
||||||
|
|
||||||
def friend_typing(self, friend_number, typing):
|
def friend_typing(self, friend_number, typing):
|
||||||
|
"""
|
||||||
|
Display incoming typing notification
|
||||||
|
"""
|
||||||
if friend_number == self.get_active_number():
|
if friend_number == self.get_active_number():
|
||||||
self._screen.typing.setVisible(typing)
|
self._screen.typing.setVisible(typing)
|
||||||
|
|
||||||
@@ -491,7 +522,7 @@ class Profile(Contact, Singleton):
|
|||||||
elif '.' in last_part:
|
elif '.' in last_part:
|
||||||
index = last_part.index('.')
|
index = last_part.index('.')
|
||||||
else:
|
else:
|
||||||
index = TOX_MAX_MESSAGE_LENGTH - size
|
index = TOX_MAX_MESSAGE_LENGTH - size - 1
|
||||||
index += size + 1
|
index += size + 1
|
||||||
self._tox.friend_send_message(number, message_type, message[:index])
|
self._tox.friend_send_message(number, message_type, message[:index])
|
||||||
message = message[index:]
|
message = message[index:]
|
||||||
@@ -586,7 +617,7 @@ class Profile(Contact, Singleton):
|
|||||||
False)
|
False)
|
||||||
elif message.get_type() == 2:
|
elif message.get_type() == 2:
|
||||||
item = self.create_file_transfer_item(message, False)
|
item = self.create_file_transfer_item(message, False)
|
||||||
if message.get_status() in (2, 4):
|
if message.get_status() >= 2:
|
||||||
ft = self._file_transfers[(message.get_friend_number(), message.get_file_number())]
|
ft = self._file_transfers[(message.get_friend_number(), message.get_file_number())]
|
||||||
ft.set_state_changed_handler(item.update)
|
ft.set_state_changed_handler(item.update)
|
||||||
|
|
||||||
@@ -622,9 +653,10 @@ class Profile(Contact, Singleton):
|
|||||||
def create_file_transfer_item(self, tm, append=True):
|
def create_file_transfer_item(self, tm, append=True):
|
||||||
data = list(tm.get_data())
|
data = list(tm.get_data())
|
||||||
data[3] = self.get_friend_by_number(data[4]).name if data[3] else self._name
|
data[3] = self.get_friend_by_number(data[4]).name if data[3] else self._name
|
||||||
|
data.append(self._messages.width())
|
||||||
item = FileTransferItem(*data)
|
item = FileTransferItem(*data)
|
||||||
elem = QtGui.QListWidgetItem()
|
elem = QtGui.QListWidgetItem()
|
||||||
elem.setSizeHint(QtCore.QSize(600, 50))
|
elem.setSizeHint(QtCore.QSize(self._messages.width() - 30, 34))
|
||||||
if append:
|
if append:
|
||||||
self._messages.addItem(elem)
|
self._messages.addItem(elem)
|
||||||
else:
|
else:
|
||||||
@@ -633,9 +665,9 @@ class Profile(Contact, Singleton):
|
|||||||
return item
|
return item
|
||||||
|
|
||||||
def create_inline_item(self, data, append=True):
|
def create_inline_item(self, data, append=True):
|
||||||
item = InlineImageItem(data)
|
item = InlineImageItem(data, self._messages.width())
|
||||||
elem = QtGui.QListWidgetItem()
|
elem = QtGui.QListWidgetItem()
|
||||||
elem.setSizeHint(QtCore.QSize(600, item.height()))
|
elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height()))
|
||||||
if append:
|
if append:
|
||||||
self._messages.addItem(elem)
|
self._messages.addItem(elem)
|
||||||
else:
|
else:
|
||||||
@@ -691,6 +723,13 @@ class Profile(Contact, Singleton):
|
|||||||
:param num: number of friend in list
|
:param num: number of friend in list
|
||||||
"""
|
"""
|
||||||
friend = self._friends[num]
|
friend = self._friends[num]
|
||||||
|
try:
|
||||||
|
settings = Settings.get_instance()
|
||||||
|
index = map(lambda x: x[0], settings['friends_aliases']).index(friend.tox_id)
|
||||||
|
del settings['friends_aliases'][index]
|
||||||
|
settings.save()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
self.clear_history(num)
|
self.clear_history(num)
|
||||||
if self._history.friend_exists_in_db(friend.tox_id):
|
if self._history.friend_exists_in_db(friend.tox_id):
|
||||||
self._history.delete_friend_from_db(friend.tox_id)
|
self._history.delete_friend_from_db(friend.tox_id)
|
||||||
@@ -702,6 +741,8 @@ class Profile(Contact, Singleton):
|
|||||||
self.set_active(-1)
|
self.set_active(-1)
|
||||||
else:
|
else:
|
||||||
self.set_active(0)
|
self.set_active(0)
|
||||||
|
data = self._tox.get_savedata()
|
||||||
|
ProfileHelper.save_profile(data)
|
||||||
|
|
||||||
def add_friend(self, tox_id):
|
def add_friend(self, tox_id):
|
||||||
num = self._tox.friend_add_norequest(tox_id) # num - friend number
|
num = self._tox.friend_add_norequest(tox_id) # num - friend number
|
||||||
@@ -717,6 +758,9 @@ class Profile(Contact, Singleton):
|
|||||||
self._friends.append(friend)
|
self._friends.append(friend)
|
||||||
|
|
||||||
def block_user(self, tox_id):
|
def block_user(self, tox_id):
|
||||||
|
"""
|
||||||
|
Block user with specified tox id (or public key) - delete from friends list and ignore friend requests
|
||||||
|
"""
|
||||||
tox_id = tox_id[:TOX_PUBLIC_KEY_SIZE * 2]
|
tox_id = tox_id[:TOX_PUBLIC_KEY_SIZE * 2]
|
||||||
if tox_id == self.tox_id[:TOX_PUBLIC_KEY_SIZE * 2]:
|
if tox_id == self.tox_id[:TOX_PUBLIC_KEY_SIZE * 2]:
|
||||||
return
|
return
|
||||||
@@ -727,15 +771,24 @@ class Profile(Contact, Singleton):
|
|||||||
try:
|
try:
|
||||||
num = self._tox.friend_by_public_key(tox_id)
|
num = self._tox.friend_by_public_key(tox_id)
|
||||||
self.delete_friend(num)
|
self.delete_friend(num)
|
||||||
|
data = self._tox.get_savedata()
|
||||||
|
ProfileHelper.save_profile(data)
|
||||||
except: # not in friend list
|
except: # not in friend list
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def unblock_user(self, tox_id, add_to_friend_list):
|
def unblock_user(self, tox_id, add_to_friend_list):
|
||||||
|
"""
|
||||||
|
Unblock user
|
||||||
|
:param tox_id: tox id of contact
|
||||||
|
:param add_to_friend_list: add this contact to friend list or not
|
||||||
|
"""
|
||||||
s = Settings.get_instance()
|
s = Settings.get_instance()
|
||||||
s['blocked'].remove(tox_id)
|
s['blocked'].remove(tox_id)
|
||||||
s.save()
|
s.save()
|
||||||
if add_to_friend_list:
|
if add_to_friend_list:
|
||||||
self.add_friend(tox_id)
|
self.add_friend(tox_id)
|
||||||
|
data = self._tox.get_savedata()
|
||||||
|
ProfileHelper.save_profile(data)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Friend requests
|
# Friend requests
|
||||||
@@ -749,19 +802,29 @@ class Profile(Contact, Singleton):
|
|||||||
:return: True on success else error string
|
:return: True on success else error string
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
message = message or 'Add me to your contact list'
|
message = message or 'Hello! Add me to your contact list please'
|
||||||
if '@' in tox_id: # value like groupbot@toxme.io
|
if '@' in tox_id: # value like groupbot@toxme.io
|
||||||
tox_id = tox_dns(tox_id)
|
tox_id = tox_dns(tox_id)
|
||||||
if tox_id is None:
|
if tox_id is None:
|
||||||
raise Exception('TOX DNS lookup failed')
|
raise Exception('TOX DNS lookup failed')
|
||||||
result = self._tox.friend_add(tox_id, message.encode('utf-8'))
|
if len(tox_id) == TOX_PUBLIC_KEY_SIZE * 2: # public key
|
||||||
tox_id = tox_id[:TOX_PUBLIC_KEY_SIZE * 2]
|
self.add_friend(tox_id)
|
||||||
item = self.create_friend_item()
|
msgBox = QtGui.QMessageBox()
|
||||||
if not self._history.friend_exists_in_db(tox_id):
|
msgBox.setWindowTitle(QtGui.QApplication.translate("MainWindow", "Friend added", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self._history.add_friend_to_db(tox_id)
|
text = (QtGui.QApplication.translate("MainWindow", 'Friend added without sending friend request', None, QtGui.QApplication.UnicodeUTF8))
|
||||||
message_getter = self._history.messages_getter(tox_id)
|
msgBox.setText(text)
|
||||||
friend = Friend(message_getter, result, tox_id, '', item, tox_id)
|
msgBox.exec_()
|
||||||
self._friends.append(friend)
|
else:
|
||||||
|
result = self._tox.friend_add(tox_id, message.encode('utf-8'))
|
||||||
|
tox_id = tox_id[:TOX_PUBLIC_KEY_SIZE * 2]
|
||||||
|
item = self.create_friend_item()
|
||||||
|
if not self._history.friend_exists_in_db(tox_id):
|
||||||
|
self._history.add_friend_to_db(tox_id)
|
||||||
|
message_getter = self._history.messages_getter(tox_id)
|
||||||
|
friend = Friend(message_getter, result, tox_id, '', item, tox_id)
|
||||||
|
self._friends.append(friend)
|
||||||
|
data = self._tox.get_savedata()
|
||||||
|
ProfileHelper.save_profile(data)
|
||||||
return True
|
return True
|
||||||
except Exception as ex: # wrong data
|
except Exception as ex: # wrong data
|
||||||
log('Friend request failed with ' + str(ex))
|
log('Friend request failed with ' + str(ex))
|
||||||
@@ -780,6 +843,8 @@ class Profile(Contact, Singleton):
|
|||||||
reply = QtGui.QMessageBox.question(None, fr_req, info, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
reply = QtGui.QMessageBox.question(None, fr_req, info, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
||||||
if reply == QtGui.QMessageBox.Yes: # accepted
|
if reply == QtGui.QMessageBox.Yes: # accepted
|
||||||
self.add_friend(tox_id)
|
self.add_friend(tox_id)
|
||||||
|
data = self._tox.get_savedata()
|
||||||
|
ProfileHelper.save_profile(data)
|
||||||
except Exception as ex: # something is wrong
|
except Exception as ex: # something is wrong
|
||||||
log('Accept friend request failed! ' + str(ex))
|
log('Accept friend request failed! ' + str(ex))
|
||||||
|
|
||||||
@@ -795,6 +860,7 @@ class Profile(Contact, Singleton):
|
|||||||
for key in self._file_transfers.keys():
|
for key in self._file_transfers.keys():
|
||||||
self._file_transfers[key].cancel()
|
self._file_transfers[key].cancel()
|
||||||
del self._file_transfers[key]
|
del self._file_transfers[key]
|
||||||
|
self._call.stop()
|
||||||
del self._tox
|
del self._tox
|
||||||
self._tox = restart()
|
self._tox = restart()
|
||||||
self.status = None
|
self.status = None
|
||||||
@@ -884,10 +950,34 @@ class Profile(Contact, Singleton):
|
|||||||
tr.cancel()
|
tr.cancel()
|
||||||
else:
|
else:
|
||||||
tr.cancelled()
|
tr.cancelled()
|
||||||
del self._file_transfers[(friend_number, file_number)]
|
if (friend_number, file_number) in self._file_transfers:
|
||||||
|
del tr
|
||||||
|
del self._file_transfers[(friend_number, file_number)]
|
||||||
else:
|
else:
|
||||||
self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['CANCEL'])
|
self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['CANCEL'])
|
||||||
|
|
||||||
|
def pause_transfer(self, friend_number, file_number, by_friend=False):
|
||||||
|
"""
|
||||||
|
Pause transfer with specified data
|
||||||
|
"""
|
||||||
|
tr = self._file_transfers[(friend_number, file_number)]
|
||||||
|
tr.pause(by_friend)
|
||||||
|
t = FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_FRIEND'] if by_friend else FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_USER']
|
||||||
|
self.get_friend_by_number(friend_number).update_transfer_data(file_number, t)
|
||||||
|
|
||||||
|
def resume_transfer(self, friend_number, file_number, by_friend=False):
|
||||||
|
"""
|
||||||
|
Resume transfer with specified data
|
||||||
|
"""
|
||||||
|
self.get_friend_by_number(friend_number).update_transfer_data(file_number,
|
||||||
|
FILE_TRANSFER_MESSAGE_STATUS['OUTGOING'])
|
||||||
|
tr = self._file_transfers[(friend_number, file_number)]
|
||||||
|
if by_friend:
|
||||||
|
tr.state = TOX_FILE_TRANSFER_STATE['RUNNING']
|
||||||
|
tr.signal()
|
||||||
|
else: # send seek control?
|
||||||
|
tr.send_control(TOX_FILE_CONTROL['RESUME'])
|
||||||
|
|
||||||
def accept_transfer(self, item, path, friend_number, file_number, size, inline=False):
|
def accept_transfer(self, item, path, friend_number, file_number, size, inline=False):
|
||||||
"""
|
"""
|
||||||
:param item: transfer item.
|
:param item: transfer item.
|
||||||
@@ -918,7 +1008,7 @@ class Profile(Contact, Singleton):
|
|||||||
self._file_transfers[(friend.number, st.get_file_number())] = st
|
self._file_transfers[(friend.number, st.get_file_number())] = st
|
||||||
tm = TransferMessage(MESSAGE_OWNER['ME'],
|
tm = TransferMessage(MESSAGE_OWNER['ME'],
|
||||||
time.time(),
|
time.time(),
|
||||||
FILE_TRANSFER_MESSAGE_STATUS['OUTGOING'],
|
FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_FRIEND'], # OUTGOING NOT STARTED
|
||||||
len(data),
|
len(data),
|
||||||
'toxygen_inline.png',
|
'toxygen_inline.png',
|
||||||
friend.number,
|
friend.number,
|
||||||
@@ -938,7 +1028,7 @@ class Profile(Contact, Singleton):
|
|||||||
self._file_transfers[(friend_number, st.get_file_number())] = st
|
self._file_transfers[(friend_number, st.get_file_number())] = st
|
||||||
tm = TransferMessage(MESSAGE_OWNER['ME'],
|
tm = TransferMessage(MESSAGE_OWNER['ME'],
|
||||||
time.time(),
|
time.time(),
|
||||||
FILE_TRANSFER_MESSAGE_STATUS['OUTGOING'],
|
FILE_TRANSFER_MESSAGE_STATUS['PAUSED_BY_FRIEND'], # OUTGOING NOT STARTED
|
||||||
os.path.getsize(path),
|
os.path.getsize(path),
|
||||||
os.path.basename(path),
|
os.path.basename(path),
|
||||||
friend_number,
|
friend_number,
|
||||||
@@ -952,7 +1042,7 @@ class Profile(Contact, Singleton):
|
|||||||
if (friend_number, file_number) in self._file_transfers:
|
if (friend_number, file_number) in self._file_transfers:
|
||||||
transfer = self._file_transfers[(friend_number, file_number)]
|
transfer = self._file_transfers[(friend_number, file_number)]
|
||||||
transfer.write_chunk(position, data)
|
transfer.write_chunk(position, data)
|
||||||
if transfer.state:
|
if transfer.state in (2, 3): # finished or cancelled
|
||||||
if type(transfer) is ReceiveAvatar:
|
if type(transfer) is ReceiveAvatar:
|
||||||
self.get_friend_by_number(friend_number).load_avatar()
|
self.get_friend_by_number(friend_number).load_avatar()
|
||||||
self.set_active(None)
|
self.set_active(None)
|
||||||
@@ -963,7 +1053,7 @@ class Profile(Contact, Singleton):
|
|||||||
inline)
|
inline)
|
||||||
if friend_number == self.get_active_number():
|
if friend_number == self.get_active_number():
|
||||||
count = self._messages.count()
|
count = self._messages.count()
|
||||||
item = InlineImageItem(transfer.get_data())
|
item = InlineImageItem(transfer.get_data(), self._messages.width())
|
||||||
elem = QtGui.QListWidgetItem()
|
elem = QtGui.QListWidgetItem()
|
||||||
elem.setSizeHint(QtCore.QSize(600, item.height()))
|
elem.setSizeHint(QtCore.QSize(600, item.height()))
|
||||||
self._messages.insertItem(count + i + 1, elem)
|
self._messages.insertItem(count + i + 1, elem)
|
||||||
@@ -977,7 +1067,7 @@ class Profile(Contact, Singleton):
|
|||||||
if (friend_number, file_number) in self._file_transfers:
|
if (friend_number, file_number) in self._file_transfers:
|
||||||
transfer = self._file_transfers[(friend_number, file_number)]
|
transfer = self._file_transfers[(friend_number, file_number)]
|
||||||
transfer.send_chunk(position, size)
|
transfer.send_chunk(position, size)
|
||||||
if transfer.state:
|
if transfer.state in (2, 3): # finished or cancelled
|
||||||
del self._file_transfers[(friend_number, file_number)]
|
del self._file_transfers[(friend_number, file_number)]
|
||||||
if type(transfer) is not SendAvatar:
|
if type(transfer) is not SendAvatar:
|
||||||
if type(transfer) is SendFromBuffer and Settings.get_instance()['allow_inline']: # inline
|
if type(transfer) is SendFromBuffer and Settings.get_instance()['allow_inline']: # inline
|
||||||
@@ -985,7 +1075,7 @@ class Profile(Contact, Singleton):
|
|||||||
self.get_friend_by_number(friend_number).update_transfer_data(file_number,
|
self.get_friend_by_number(friend_number).update_transfer_data(file_number,
|
||||||
FILE_TRANSFER_MESSAGE_STATUS['FINISHED'],
|
FILE_TRANSFER_MESSAGE_STATUS['FINISHED'],
|
||||||
inline)
|
inline)
|
||||||
self.set_active(self._active_friend)
|
self.update()
|
||||||
else:
|
else:
|
||||||
self.get_friend_by_number(friend_number).update_transfer_data(file_number,
|
self.get_friend_by_number(friend_number).update_transfer_data(file_number,
|
||||||
FILE_TRANSFER_MESSAGE_STATUS['FINISHED'])
|
FILE_TRANSFER_MESSAGE_STATUS['FINISHED'])
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from platform import system
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import locale
|
import locale
|
||||||
from util import Singleton, curr_directory
|
from util import Singleton, curr_directory, log
|
||||||
import pyaudio
|
import pyaudio
|
||||||
|
|
||||||
|
|
||||||
@@ -14,7 +14,12 @@ class Settings(Singleton, dict):
|
|||||||
if os.path.isfile(self.path):
|
if os.path.isfile(self.path):
|
||||||
with open(self.path) as fl:
|
with open(self.path) as fl:
|
||||||
data = fl.read()
|
data = fl.read()
|
||||||
super(self.__class__, self).__init__(json.loads(data))
|
try:
|
||||||
|
info = json.loads(data)
|
||||||
|
except Exception as ex:
|
||||||
|
info = Settings.get_default_settings()
|
||||||
|
log('Parsing settings error: ' + str(ex))
|
||||||
|
super(self.__class__, self).__init__(info)
|
||||||
self.upgrade()
|
self.upgrade()
|
||||||
else:
|
else:
|
||||||
super(self.__class__, self).__init__(Settings.get_default_settings())
|
super(self.__class__, self).__init__(Settings.get_default_settings())
|
||||||
@@ -57,7 +62,7 @@ class Settings(Singleton, dict):
|
|||||||
'language': 'English',
|
'language': 'English',
|
||||||
'save_history': False,
|
'save_history': False,
|
||||||
'allow_inline': True,
|
'allow_inline': True,
|
||||||
'allow_auto_accept': False,
|
'allow_auto_accept': True,
|
||||||
'auto_accept_path': None,
|
'auto_accept_path': None,
|
||||||
'show_online_friends': False,
|
'show_online_friends': False,
|
||||||
'auto_accept_from_friends': [],
|
'auto_accept_from_friends': [],
|
||||||
|
|||||||
0
src/styles/rc/Hmovetoolbar.png
Normal file → Executable file
|
Before Width: | Height: | Size: 220 B After Width: | Height: | Size: 220 B |
0
src/styles/rc/Hsepartoolbar.png
Normal file → Executable file
|
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 172 B |
0
src/styles/rc/Vmovetoolbar.png
Normal file → Executable file
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 228 B |
0
src/styles/rc/Vsepartoolbar.png
Normal file → Executable file
|
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
0
src/styles/rc/branch_closed-on.png
Normal file → Executable file
|
Before Width: | Height: | Size: 147 B After Width: | Height: | Size: 147 B |
0
src/styles/rc/branch_closed.png
Normal file → Executable file
|
Before Width: | Height: | Size: 160 B After Width: | Height: | Size: 160 B |
0
src/styles/rc/branch_open-on.png
Normal file → Executable file
|
Before Width: | Height: | Size: 150 B After Width: | Height: | Size: 150 B |
0
src/styles/rc/branch_open.png
Normal file → Executable file
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
BIN
src/styles/rc/checkbox_checked.png
Normal file → Executable file
|
Before Width: | Height: | Size: 492 B After Width: | Height: | Size: 4.4 KiB |
BIN
src/styles/rc/checkbox_checked_disabled.png
Normal file → Executable file
|
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 4.4 KiB |
BIN
src/styles/rc/checkbox_checked_focus.png
Normal file → Executable file
|
Before Width: | Height: | Size: 512 B After Width: | Height: | Size: 4.4 KiB |
0
src/styles/rc/checkbox_indeterminate.png
Normal file → Executable file
|
Before Width: | Height: | Size: 493 B After Width: | Height: | Size: 493 B |
0
src/styles/rc/checkbox_indeterminate_disabled.png
Normal file → Executable file
|
Before Width: | Height: | Size: 492 B After Width: | Height: | Size: 492 B |
0
src/styles/rc/checkbox_indeterminate_focus.png
Normal file → Executable file
|
Before Width: | Height: | Size: 514 B After Width: | Height: | Size: 514 B |
BIN
src/styles/rc/checkbox_unchecked.png
Normal file → Executable file
|
Before Width: | Height: | Size: 464 B After Width: | Height: | Size: 2.8 KiB |
BIN
src/styles/rc/checkbox_unchecked_disabled.png
Normal file → Executable file
|
Before Width: | Height: | Size: 464 B After Width: | Height: | Size: 2.8 KiB |
BIN
src/styles/rc/checkbox_unchecked_focus.png
Normal file → Executable file
|
Before Width: | Height: | Size: 483 B After Width: | Height: | Size: 2.8 KiB |
0
src/styles/rc/close-hover.png
Normal file → Executable file
|
Before Width: | Height: | Size: 598 B After Width: | Height: | Size: 598 B |
0
src/styles/rc/close-pressed.png
Normal file → Executable file
|
Before Width: | Height: | Size: 598 B After Width: | Height: | Size: 598 B |
0
src/styles/rc/close.png
Normal file → Executable file
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 586 B |
0
src/styles/rc/down_arrow.png
Normal file → Executable file
|
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
0
src/styles/rc/down_arrow_disabled.png
Normal file → Executable file
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
0
src/styles/rc/left_arrow.png
Normal file → Executable file
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
0
src/styles/rc/left_arrow_disabled.png
Normal file → Executable file
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
0
src/styles/rc/radio_checked.png
Normal file → Executable file
|
Before Width: | Height: | Size: 940 B After Width: | Height: | Size: 940 B |
0
src/styles/rc/radio_checked_disabled.png
Normal file → Executable file
|
Before Width: | Height: | Size: 972 B After Width: | Height: | Size: 972 B |
0
src/styles/rc/radio_checked_focus.png
Normal file → Executable file
|
Before Width: | Height: | Size: 933 B After Width: | Height: | Size: 933 B |
0
src/styles/rc/radio_unchecked.png
Normal file → Executable file
|
Before Width: | Height: | Size: 728 B After Width: | Height: | Size: 728 B |
0
src/styles/rc/radio_unchecked_disabled.png
Normal file → Executable file
|
Before Width: | Height: | Size: 760 B After Width: | Height: | Size: 760 B |
0
src/styles/rc/radio_unchecked_focus.png
Normal file → Executable file
|
Before Width: | Height: | Size: 724 B After Width: | Height: | Size: 724 B |
0
src/styles/rc/right_arrow.png
Normal file → Executable file
|
Before Width: | Height: | Size: 160 B After Width: | Height: | Size: 160 B |
0
src/styles/rc/right_arrow_disabled.png
Normal file → Executable file
|
Before Width: | Height: | Size: 160 B After Width: | Height: | Size: 160 B |
0
src/styles/rc/sizegrip.png
Normal file → Executable file
|
Before Width: | Height: | Size: 129 B After Width: | Height: | Size: 129 B |
0
src/styles/rc/stylesheet-branch-end.png
Normal file → Executable file
|
Before Width: | Height: | Size: 224 B After Width: | Height: | Size: 224 B |
0
src/styles/rc/stylesheet-branch-more.png
Normal file → Executable file
|
Before Width: | Height: | Size: 182 B After Width: | Height: | Size: 182 B |
0
src/styles/rc/stylesheet-vline.png
Normal file → Executable file
|
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |
0
src/styles/rc/transparent.png
Normal file → Executable file
|
Before Width: | Height: | Size: 195 B After Width: | Height: | Size: 195 B |
0
src/styles/rc/undock.png
Normal file → Executable file
|
Before Width: | Height: | Size: 578 B After Width: | Height: | Size: 578 B |
0
src/styles/rc/up_arrow.png
Normal file → Executable file
|
Before Width: | Height: | Size: 158 B After Width: | Height: | Size: 158 B |
0
src/styles/rc/up_arrow_disabled.png
Normal file → Executable file
|
Before Width: | Height: | Size: 159 B After Width: | Height: | Size: 159 B |
@@ -668,7 +668,7 @@ QComboBox QAbstractItemView
|
|||||||
background-color: #201F1F;
|
background-color: #201F1F;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
border: 1px solid #444;
|
border: 1px solid #444;
|
||||||
selection-background-color: #3d8ec9;
|
selection-background-color: #A9A9A9;
|
||||||
}
|
}
|
||||||
|
|
||||||
QComboBox::drop-down
|
QComboBox::drop-down
|
||||||
@@ -1268,4 +1268,9 @@ QCheckBox
|
|||||||
color: #bbb;
|
color: #bbb;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QListWidget > QLabel
|
||||||
|
{
|
||||||
|
color: #A9A9A9;
|
||||||
}
|
}
|
||||||
144
src/tox.py
@@ -32,6 +32,7 @@ def bin_to_string(raw_id, length):
|
|||||||
|
|
||||||
|
|
||||||
class Tox(object):
|
class Tox(object):
|
||||||
|
|
||||||
libtoxcore = LibToxCore()
|
libtoxcore = LibToxCore()
|
||||||
|
|
||||||
def __init__(self, tox_options=None, tox_pointer=None):
|
def __init__(self, tox_options=None, tox_pointer=None):
|
||||||
@@ -57,9 +58,9 @@ class Tox(object):
|
|||||||
raise MemoryError('The function was unable to allocate enough '
|
raise MemoryError('The function was unable to allocate enough '
|
||||||
'memory to store the internal structures for the Tox object.')
|
'memory to store the internal structures for the Tox object.')
|
||||||
elif tox_err_new == TOX_ERR_NEW['PORT_ALLOC']:
|
elif tox_err_new == TOX_ERR_NEW['PORT_ALLOC']:
|
||||||
raise MemoryError('The function was unable to bind to a port. This may mean that all ports have already'
|
raise RuntimeError('The function was unable to bind to a port. This may mean that all ports have '
|
||||||
' been bound, e.g. by other Tox instances, or it may mean a permission error. You may'
|
'already been bound, e.g. by other Tox instances, or it may mean a permission error.'
|
||||||
' be able to gather more information from errno.')
|
' You may be able to gather more information from errno.')
|
||||||
elif tox_err_new == TOX_ERR_NEW['PROXY_BAD_TYPE']:
|
elif tox_err_new == TOX_ERR_NEW['PROXY_BAD_TYPE']:
|
||||||
raise ArgumentError('proxy_type was invalid.')
|
raise ArgumentError('proxy_type was invalid.')
|
||||||
elif tox_err_new == TOX_ERR_NEW['PROXY_BAD_HOST']:
|
elif tox_err_new == TOX_ERR_NEW['PROXY_BAD_HOST']:
|
||||||
@@ -89,6 +90,8 @@ class Tox(object):
|
|||||||
self.file_chunk_request_cb = None
|
self.file_chunk_request_cb = None
|
||||||
self.file_recv_cb = None
|
self.file_recv_cb = None
|
||||||
self.file_recv_chunk_cb = None
|
self.file_recv_chunk_cb = None
|
||||||
|
self.friend_lossy_packet_cb = None
|
||||||
|
self.friend_lossless_packet_cb = None
|
||||||
|
|
||||||
self.AV = ToxAV(self._tox_pointer)
|
self.AV = ToxAV(self._tox_pointer)
|
||||||
|
|
||||||
@@ -218,7 +221,7 @@ class Tox(object):
|
|||||||
"""
|
"""
|
||||||
tox_err_bootstrap = c_int()
|
tox_err_bootstrap = c_int()
|
||||||
result = Tox.libtoxcore.tox_add_tcp_relay(self._tox_pointer, c_char_p(address), c_uint16(port),
|
result = Tox.libtoxcore.tox_add_tcp_relay(self._tox_pointer, c_char_p(address), c_uint16(port),
|
||||||
c_char_p(public_key), byref(tox_err_bootstrap))
|
string_to_bin(public_key), byref(tox_err_bootstrap))
|
||||||
tox_err_bootstrap = tox_err_bootstrap.value
|
tox_err_bootstrap = tox_err_bootstrap.value
|
||||||
if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']:
|
if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']:
|
||||||
return bool(result)
|
return bool(result)
|
||||||
@@ -674,6 +677,7 @@ class Tox(object):
|
|||||||
|
|
||||||
The data written to `name` is equal to the data received by the last `friend_name` callback.
|
The data written to `name` is equal to the data received by the last `friend_name` callback.
|
||||||
|
|
||||||
|
:param friend_number: number of friend
|
||||||
:param name: pointer (c_char_p) to a valid memory region large enough to store the friend's name.
|
:param name: pointer (c_char_p) to a valid memory region large enough to store the friend's name.
|
||||||
:return: name of the friend
|
:return: name of the friend
|
||||||
"""
|
"""
|
||||||
@@ -949,7 +953,7 @@ class Tox(object):
|
|||||||
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['FRIEND_NOT_CONNECTED']:
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['FRIEND_NOT_CONNECTED']:
|
||||||
raise ArgumentError('This client is currently not connected to the friend.')
|
raise ArgumentError('This client is currently not connected to the friend.')
|
||||||
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['SENDQ']:
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['SENDQ']:
|
||||||
raise ArgumentError('An allocation error occurred while increasing the send queue size.')
|
raise MemoryError('An allocation error occurred while increasing the send queue size.')
|
||||||
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['TOO_LONG']:
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['TOO_LONG']:
|
||||||
raise ArgumentError('Message length exceeded TOX_MAX_MESSAGE_LENGTH.')
|
raise ArgumentError('Message length exceeded TOX_MAX_MESSAGE_LENGTH.')
|
||||||
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['EMPTY']:
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['EMPTY']:
|
||||||
@@ -1055,16 +1059,16 @@ class Tox(object):
|
|||||||
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['FRIEND_NOT_FOUND']:
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['FRIEND_NOT_FOUND']:
|
||||||
raise ArgumentError('The friend_number passed did not designate a valid friend.')
|
raise ArgumentError('The friend_number passed did not designate a valid friend.')
|
||||||
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['FRIEND_NOT_CONNECTED']:
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['FRIEND_NOT_CONNECTED']:
|
||||||
raise RuntimeError('This client is currently not connected to the friend.')
|
raise ArgumentError('This client is currently not connected to the friend.')
|
||||||
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_FOUND']:
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_FOUND']:
|
||||||
raise ArgumentError('No file transfer with the given file number was found for the given friend.')
|
raise ArgumentError('No file transfer with the given file number was found for the given friend.')
|
||||||
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_PAUSED']:
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_PAUSED']:
|
||||||
raise ArgumentError('A RESUME control was sent, but the file transfer is running normally.')
|
raise RuntimeError('A RESUME control was sent, but the file transfer is running normally.')
|
||||||
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['DENIED']:
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['DENIED']:
|
||||||
raise ArgumentError('A RESUME control was sent, but the file transfer was paused by the other party. Only '
|
raise RuntimeError('A RESUME control was sent, but the file transfer was paused by the other party. Only '
|
||||||
'the party that paused the transfer can resume it.')
|
'the party that paused the transfer can resume it.')
|
||||||
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['ALREADY_PAUSED']:
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['ALREADY_PAUSED']:
|
||||||
raise ArgumentError('A PAUSE control was sent, but the file transfer was already paused.')
|
raise RuntimeError('A PAUSE control was sent, but the file transfer was already paused.')
|
||||||
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['SENDQ']:
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['SENDQ']:
|
||||||
raise RuntimeError('Packet queue is full.')
|
raise RuntimeError('Packet queue is full.')
|
||||||
|
|
||||||
@@ -1110,15 +1114,15 @@ class Tox(object):
|
|||||||
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['FRIEND_NOT_FOUND']:
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['FRIEND_NOT_FOUND']:
|
||||||
raise ArgumentError('The friend_number passed did not designate a valid friend.')
|
raise ArgumentError('The friend_number passed did not designate a valid friend.')
|
||||||
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['FRIEND_NOT_CONNECTED']:
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['FRIEND_NOT_CONNECTED']:
|
||||||
raise RuntimeError('This client is currently not connected to the friend.')
|
raise ArgumentError('This client is currently not connected to the friend.')
|
||||||
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['NOT_FOUND']:
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['NOT_FOUND']:
|
||||||
raise ArgumentError('No file transfer with the given file number was found for the given friend.')
|
raise ArgumentError('No file transfer with the given file number was found for the given friend.')
|
||||||
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['SEEK_DENIED']:
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['SEEK_DENIED']:
|
||||||
raise ArgumentError('File was not in a state where it could be seeked.')
|
raise IOError('File was not in a state where it could be seeked.')
|
||||||
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['INVALID_POSITION']:
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['INVALID_POSITION']:
|
||||||
raise ArgumentError('Seek position was invalid')
|
raise ArgumentError('Seek position was invalid')
|
||||||
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['SENDQ']:
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['SENDQ']:
|
||||||
raise ArgumentError('Packet queue is full.')
|
raise RuntimeError('Packet queue is full.')
|
||||||
|
|
||||||
def file_get_file_id(self, friend_number, file_number, file_id=None):
|
def file_get_file_id(self, friend_number, file_number, file_id=None):
|
||||||
"""
|
"""
|
||||||
@@ -1206,7 +1210,7 @@ class Tox(object):
|
|||||||
elif tox_err_file_send == TOX_ERR_FILE_SEND['FRIEND_NOT_FOUND']:
|
elif tox_err_file_send == TOX_ERR_FILE_SEND['FRIEND_NOT_FOUND']:
|
||||||
raise ArgumentError('The friend_number passed did not designate a valid friend.')
|
raise ArgumentError('The friend_number passed did not designate a valid friend.')
|
||||||
elif tox_err_file_send == TOX_ERR_FILE_SEND['FRIEND_NOT_CONNECTED']:
|
elif tox_err_file_send == TOX_ERR_FILE_SEND['FRIEND_NOT_CONNECTED']:
|
||||||
raise RuntimeError('This client is currently not connected to the friend.')
|
raise ArgumentError('This client is currently not connected to the friend.')
|
||||||
elif tox_err_file_send == TOX_ERR_FILE_SEND['NAME_TOO_LONG']:
|
elif tox_err_file_send == TOX_ERR_FILE_SEND['NAME_TOO_LONG']:
|
||||||
raise ArgumentError('Filename length exceeded TOX_MAX_FILENAME_LENGTH bytes.')
|
raise ArgumentError('Filename length exceeded TOX_MAX_FILENAME_LENGTH bytes.')
|
||||||
elif tox_err_file_send == TOX_ERR_FILE_SEND['TOO_MANY']:
|
elif tox_err_file_send == TOX_ERR_FILE_SEND['TOO_MANY']:
|
||||||
@@ -1252,7 +1256,7 @@ class Tox(object):
|
|||||||
'adjusted according to maximum transmission unit and the expected end of the file. '
|
'adjusted according to maximum transmission unit and the expected end of the file. '
|
||||||
'Trying to send less or more than requested will return this error.')
|
'Trying to send less or more than requested will return this error.')
|
||||||
elif tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['SENDQ']:
|
elif tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['SENDQ']:
|
||||||
raise ArgumentError('Packet queue is full.')
|
raise RuntimeError('Packet queue is full.')
|
||||||
elif tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['WRONG_POSITION']:
|
elif tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['WRONG_POSITION']:
|
||||||
raise ArgumentError('Position parameter was wrong.')
|
raise ArgumentError('Position parameter was wrong.')
|
||||||
|
|
||||||
@@ -1346,9 +1350,117 @@ class Tox(object):
|
|||||||
self.libtoxcore.tox_callback_file_recv_chunk(self._tox_pointer, self.file_recv_chunk_cb, user_data)
|
self.libtoxcore.tox_callback_file_recv_chunk(self._tox_pointer, self.file_recv_chunk_cb, user_data)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# TODO Low-level custom packet sending and receiving
|
# Low-level custom packet sending and receiving
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def friend_send_lossy_packet(self, friend_number, data):
|
||||||
|
"""
|
||||||
|
Send a custom lossy packet to a friend.
|
||||||
|
The first byte of data must be in the range 200-254. Maximum length of a
|
||||||
|
custom packet is TOX_MAX_CUSTOM_PACKET_SIZE.
|
||||||
|
|
||||||
|
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, it is recommended that you use lossless custom packets instead.
|
||||||
|
|
||||||
|
:param friend_number: The friend number of the friend this lossy packet
|
||||||
|
:param data: python string containing the packet data
|
||||||
|
:return: True on success.
|
||||||
|
"""
|
||||||
|
tox_err_friend_custom_packet = c_int()
|
||||||
|
result = self.libtoxcore.tox_friend_send_lossy_packet(self._tox_pointer, c_uint32(friend_number),
|
||||||
|
c_char_p(data), c_size_t(len(data)),
|
||||||
|
byref(tox_err_friend_custom_packet))
|
||||||
|
tox_err_friend_custom_packet = tox_err_friend_custom_packet.value
|
||||||
|
if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['OK']:
|
||||||
|
return bool(result)
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['NULL']:
|
||||||
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['FRIEND_NOT_FOUND']:
|
||||||
|
raise ArgumentError('The friend number did not designate a valid friend.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['FRIEND_NOT_CONNECTED']:
|
||||||
|
raise ArgumentError('This client is currently not connected to the friend.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['INVALID']:
|
||||||
|
raise ArgumentError('The first byte of data was not in the specified range for the packet type.'
|
||||||
|
'This range is 200-254 for lossy, and 160-191 for lossless packets.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['EMPTY']:
|
||||||
|
raise ArgumentError('Attempted to send an empty packet.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['TOO_LONG']:
|
||||||
|
raise ArgumentError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['SENDQ']:
|
||||||
|
raise RuntimeError('Packet queue is full.')
|
||||||
|
|
||||||
|
def friend_send_lossless_packet(self, friend_number, data):
|
||||||
|
"""
|
||||||
|
Send a custom lossless packet to a friend.
|
||||||
|
The first byte of data must be in the range 160-191. Maximum length of a
|
||||||
|
custom packet is TOX_MAX_CUSTOM_PACKET_SIZE.
|
||||||
|
|
||||||
|
Lossless packet behaviour is comparable to TCP (reliability, arrive in order)
|
||||||
|
but with packets instead of a stream.
|
||||||
|
|
||||||
|
:param friend_number: The friend number of the friend this lossless packet
|
||||||
|
:param data: python string containing the packet data
|
||||||
|
:return: True on success.
|
||||||
|
"""
|
||||||
|
tox_err_friend_custom_packet = c_int()
|
||||||
|
result = self.libtoxcore.tox_friend_send_lossless_packet(self._tox_pointer, c_uint32(friend_number),
|
||||||
|
c_char_p(data), c_size_t(len(data)),
|
||||||
|
byref(tox_err_friend_custom_packet))
|
||||||
|
tox_err_friend_custom_packet = tox_err_friend_custom_packet.value
|
||||||
|
if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['OK']:
|
||||||
|
return bool(result)
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['NULL']:
|
||||||
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['FRIEND_NOT_FOUND']:
|
||||||
|
raise ArgumentError('The friend number did not designate a valid friend.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['FRIEND_NOT_CONNECTED']:
|
||||||
|
raise ArgumentError('This client is currently not connected to the friend.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['INVALID']:
|
||||||
|
raise ArgumentError('The first byte of data was not in the specified range for the packet type.'
|
||||||
|
'This range is 200-254 for lossy, and 160-191 for lossless packets.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['EMPTY']:
|
||||||
|
raise ArgumentError('Attempted to send an empty packet.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['TOO_LONG']:
|
||||||
|
raise ArgumentError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.')
|
||||||
|
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['SENDQ']:
|
||||||
|
raise RuntimeError('Packet queue is full.')
|
||||||
|
|
||||||
|
def callback_friend_lossy_packet(self, callback, user_data):
|
||||||
|
"""
|
||||||
|
Set the callback for the `friend_lossy_packet` event. Pass NULL to unset.
|
||||||
|
|
||||||
|
:param callback: Python function.
|
||||||
|
Should take pointer (c_void_p) to Tox object,
|
||||||
|
friend_number (c_uint32) - The friend number of the friend who sent a lossy packet,
|
||||||
|
A byte array (c_uint8 array) containing the received packet data,
|
||||||
|
length (c_size_t) - The length of the packet data byte array,
|
||||||
|
pointer (c_void_p) to user_data
|
||||||
|
:param user_data: pointer (c_void_p) to user data
|
||||||
|
"""
|
||||||
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_void_p)
|
||||||
|
self.friend_lossy_packet_cb = c_callback(callback)
|
||||||
|
self.libtoxcore.tox_callback_friend_lossy_packet(self._tox_pointer, self.friend_lossy_packet_cb, user_data)
|
||||||
|
|
||||||
|
def callback_friend_lossless_packet(self, callback, user_data):
|
||||||
|
"""
|
||||||
|
Set the callback for the `friend_lossless_packet` event. Pass NULL to unset.
|
||||||
|
|
||||||
|
:param callback: Python function.
|
||||||
|
Should take pointer (c_void_p) to Tox object,
|
||||||
|
friend_number (c_uint32) - The friend number of the friend who sent a lossless packet,
|
||||||
|
A byte array (c_uint8 array) containing the received packet data,
|
||||||
|
length (c_size_t) - The length of the packet data byte array,
|
||||||
|
pointer (c_void_p) to user_data
|
||||||
|
:param user_data: pointer (c_void_p) to user data
|
||||||
|
"""
|
||||||
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_void_p)
|
||||||
|
self.friend_lossless_packet_cb = c_callback(callback)
|
||||||
|
self.libtoxcore.tox_callback_friend_lossless_packet(self._tox_pointer, self.friend_lossless_packet_cb,
|
||||||
|
user_data)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
# Low-level network information
|
# Low-level network information
|
||||||
# -----------------------------------------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ class ToxAV(object):
|
|||||||
height Height (c_uint16) of the frame in pixels.
|
height Height (c_uint16) of the frame in pixels.
|
||||||
y
|
y
|
||||||
u
|
u
|
||||||
v Plane data (c_char_p).
|
v Plane data (POINTER(c_uint8)).
|
||||||
The size of plane data is derived from width and height where
|
The size of plane data is derived from width and height where
|
||||||
Y = MAX(width, abs(ystride)) * height,
|
Y = MAX(width, abs(ystride)) * height,
|
||||||
U = MAX(width/2, abs(ustride)) * (height/2) and
|
U = MAX(width/2, abs(ustride)) * (height/2) and
|
||||||
@@ -357,7 +357,7 @@ class ToxAV(object):
|
|||||||
user_data pointer (c_void_p) to user_data
|
user_data pointer (c_void_p) to user_data
|
||||||
:param user_data: pointer (c_void_p) to user data
|
:param user_data: pointer (c_void_p) to user data
|
||||||
"""
|
"""
|
||||||
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint16, c_uint16, c_char_p, c_char_p, c_char_p, c_int32,
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint16, c_uint16, POINTER(c_uint8), POINTER(c_uint8),
|
||||||
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)
|
ToxAV.libtoxav.toxav_callback_video_receive_frame(self._toxav_pointer, self.video_receive_frame_cb, user_data)
|
||||||
|
|||||||
@@ -4,17 +4,17 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>AddContact</name>
|
<name>AddContact</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="65"/>
|
<location filename="menu.py" line="64"/>
|
||||||
<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="67"/>
|
<location filename="menu.py" line="66"/>
|
||||||
<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="68"/>
|
<location filename="menu.py" line="67"/>
|
||||||
<source>Message:</source>
|
<source>Message:</source>
|
||||||
<translation>Message:</translation>
|
<translation>Message:</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -22,159 +22,206 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>Form</name>
|
<name>Form</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="66"/>
|
<location filename="menu.py" line="65"/>
|
||||||
<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="220"/>
|
<location filename="menu.py" line="231"/>
|
||||||
<source>IPv6</source>
|
<source>IPv6</source>
|
||||||
<translation>IPv6</translation>
|
<translation>IPv6</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="221"/>
|
<location filename="menu.py" line="232"/>
|
||||||
<source>UDP</source>
|
<source>UDP</source>
|
||||||
<translation>UDP</translation>
|
<translation>UDP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="222"/>
|
<location filename="menu.py" line="233"/>
|
||||||
<source>Proxy</source>
|
<source>Proxy</source>
|
||||||
<translation>Proxy</translation>
|
<translation>Proxy</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="223"/>
|
<location filename="menu.py" line="234"/>
|
||||||
<source>IP:</source>
|
<source>IP:</source>
|
||||||
<translation>IP:</translation>
|
<translation>IP:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="224"/>
|
<location filename="menu.py" line="235"/>
|
||||||
<source>Port:</source>
|
<source>Port:</source>
|
||||||
<translation>Port:</translation>
|
<translation>Port:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="90"/>
|
<location filename="mainscreen.py" line="99"/>
|
||||||
<source>Online contacts</source>
|
<source>Online contacts</source>
|
||||||
<translation>Online contacts</translation>
|
<translation>Online contacts</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="237"/>
|
||||||
|
<source>HTTP</source>
|
||||||
|
<translation>HTTP</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="95"/>
|
<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="101"/>
|
<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="286"/>
|
<location filename="mainscreen.py" line="346"/>
|
||||||
<source>About</source>
|
<source>About</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="94"/>
|
<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="96"/>
|
<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="97"/>
|
<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="98"/>
|
<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="99"/>
|
<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="100"/>
|
<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="762"/>
|
<location filename="profile.py" line="840"/>
|
||||||
<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="764"/>
|
<location filename="profile.py" line="842"/>
|
||||||
<source>Friend request</source>
|
<source>Friend request</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="287"/>
|
<location filename="mainscreen.py" line="390"/>
|
||||||
<source>Toxygen is Tox client written on Python 2.7. Version: </source>
|
|
||||||
<translation></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="mainscreen.py" line="329"/>
|
|
||||||
<source>Choose file</source>
|
<source>Choose file</source>
|
||||||
<translation></translation>
|
<translation>Choose file</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="367"/>
|
<location filename="mainscreen.py" line="431"/>
|
||||||
<source>Disallow auto accept</source>
|
<source>Disallow auto accept</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="368"/>
|
<location filename="mainscreen.py" line="432"/>
|
||||||
<source>Allow auto accept</source>
|
<source>Allow auto accept</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="370"/>
|
<location filename="mainscreen.py" line="434"/>
|
||||||
<source>Set alias</source>
|
<source>Set alias</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="371"/>
|
<location filename="mainscreen.py" line="435"/>
|
||||||
<source>Clear history</source>
|
<source>Clear history</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="372"/>
|
<location filename="mainscreen.py" line="436"/>
|
||||||
<source>Copy public key</source>
|
<source>Copy public key</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="374"/>
|
<location filename="mainscreen.py" line="438"/>
|
||||||
<source>Remove friend</source>
|
<source>Remove friend</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="639"/>
|
<location filename="profile.py" line="686"/>
|
||||||
<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="102"/>
|
<location filename="mainscreen.py" line="111"/>
|
||||||
<source>Audio</source>
|
<source>Audio</source>
|
||||||
<translation>Audio</translation>
|
<translation>Audio</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="112"/>
|
||||||
|
<source>Find contact</source>
|
||||||
|
<translation>Find contact</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="profile.py" line="812"/>
|
||||||
|
<source>Friend added</source>
|
||||||
|
<translation>Friend added</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="347"/>
|
||||||
|
<source>Toxygen is Tox client written on Python.
|
||||||
|
Version: </source>
|
||||||
|
<translation>Toxygen is Tox client written on Python.
|
||||||
|
Version:</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="profile.py" line="813"/>
|
||||||
|
<source>Friend added without sending friend request</source>
|
||||||
|
<translation>Friend added without sending friend request</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="list_items.py" line="231"/>
|
||||||
|
<source>Choose folder</source>
|
||||||
|
<translation>Choose folder</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="113"/>
|
||||||
|
<source>Send screenshot</source>
|
||||||
|
<translation>Send screenshot</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="114"/>
|
||||||
|
<source>Send file</source>
|
||||||
|
<translation>Send file</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="115"/>
|
||||||
|
<source>Send message</source>
|
||||||
|
<translation>Send message</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="116"/>
|
||||||
|
<source>Start audio call with friend</source>
|
||||||
|
<translation>Start audio call with friend</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>NetworkSettings</name>
|
<name>NetworkSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="219"/>
|
<location filename="menu.py" line="230"/>
|
||||||
<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="225"/>
|
<location filename="menu.py" line="236"/>
|
||||||
<source>Restart TOX core</source>
|
<source>Restart TOX core</source>
|
||||||
<translation>Restart Tox core</translation>
|
<translation>Restart Tox core</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -182,60 +229,65 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ProfileSettingsForm</name>
|
<name>ProfileSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="131"/>
|
<location filename="menu.py" line="133"/>
|
||||||
<source>Export profile</source>
|
<source>Export profile</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="132"/>
|
<location filename="menu.py" line="134"/>
|
||||||
<source>Profile settings</source>
|
<source>Profile settings</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="133"/>
|
<location filename="menu.py" line="135"/>
|
||||||
<source>Name:</source>
|
<source>Name:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="134"/>
|
<location filename="menu.py" line="136"/>
|
||||||
<source>Status:</source>
|
<source>Status:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="135"/>
|
<location filename="menu.py" line="137"/>
|
||||||
<source>TOX ID:</source>
|
<source>TOX ID:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="136"/>
|
<location filename="menu.py" line="138"/>
|
||||||
<source>Copy TOX ID</source>
|
<source>Copy TOX ID</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="137"/>
|
<location filename="menu.py" line="139"/>
|
||||||
<source>New avatar</source>
|
<source>New avatar</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="138"/>
|
<location filename="menu.py" line="140"/>
|
||||||
<source>Reset avatar</source>
|
<source>Reset avatar</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="141"/>
|
||||||
|
<source>New NoSpam</source>
|
||||||
|
<translation>New NoSpam</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>audioSettingsForm</name>
|
<name>audioSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="504"/>
|
<location filename="menu.py" line="522"/>
|
||||||
<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="505"/>
|
<location filename="menu.py" line="523"/>
|
||||||
<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="506"/>
|
<location filename="menu.py" line="524"/>
|
||||||
<source>Output device:</source>
|
<source>Output device:</source>
|
||||||
<translation>Output device:</translation>
|
<translation>Output device:</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -243,12 +295,12 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>incoming_call</name>
|
<name>incoming_call</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1041"/>
|
<location filename="profile.py" line="1151"/>
|
||||||
<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="1043"/>
|
<location filename="profile.py" line="1153"/>
|
||||||
<source>Incoming audio call</source>
|
<source>Incoming audio call</source>
|
||||||
<translation>Incoming audio call</translation>
|
<translation>Incoming audio call</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -256,17 +308,17 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>interfaceForm</name>
|
<name>interfaceForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="442"/>
|
<location filename="menu.py" line="460"/>
|
||||||
<source>Interface settings</source>
|
<source>Interface settings</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="443"/>
|
<location filename="menu.py" line="461"/>
|
||||||
<source>Theme:</source>
|
<source>Theme:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="444"/>
|
<location filename="menu.py" line="462"/>
|
||||||
<source>Language:</source>
|
<source>Language:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -274,47 +326,47 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>login</name>
|
<name>login</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="57"/>
|
<location filename="loginscreen.py" line="70"/>
|
||||||
<source>Log in</source>
|
<source>Log in</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="58"/>
|
<location filename="loginscreen.py" line="71"/>
|
||||||
<source>Create</source>
|
<source>Create</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="59"/>
|
<location filename="loginscreen.py" line="72"/>
|
||||||
<source>Profile name:</source>
|
<source>Profile name:</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="60"/>
|
<location filename="loginscreen.py" line="73"/>
|
||||||
<source>Load profile</source>
|
<source>Load profile</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="61"/>
|
<location filename="loginscreen.py" line="74"/>
|
||||||
<source>Use as default</source>
|
<source>Use as default</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="62"/>
|
<location filename="loginscreen.py" line="75"/>
|
||||||
<source>Load existing profile</source>
|
<source>Load existing profile</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="63"/>
|
<location filename="loginscreen.py" line="76"/>
|
||||||
<source>Create new profile</source>
|
<source>Create new profile</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="64"/>
|
<location filename="loginscreen.py" line="77"/>
|
||||||
<source>toxygen</source>
|
<source>toxygen</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="80"/>
|
<location filename="main.py" line="87"/>
|
||||||
<source>Looks like other instance of Toxygen uses this profile! Continue?</source>
|
<source>Looks like other instance of Toxygen uses this profile! Continue?</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -322,22 +374,22 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>notificationsForm</name>
|
<name>notificationsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="383"/>
|
<location filename="menu.py" line="401"/>
|
||||||
<source>Notification settings</source>
|
<source>Notification settings</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="384"/>
|
<location filename="menu.py" line="402"/>
|
||||||
<source>Enable notifications</source>
|
<source>Enable notifications</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="385"/>
|
<location filename="menu.py" line="403"/>
|
||||||
<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="386"/>
|
<location filename="menu.py" line="404"/>
|
||||||
<source>Enable sound notifications</source>
|
<source>Enable sound notifications</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -345,77 +397,77 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>privacySettings</name>
|
<name>privacySettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="307"/>
|
<location filename="menu.py" line="319"/>
|
||||||
<source>Privacy settings</source>
|
<source>Privacy settings</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="308"/>
|
<location filename="menu.py" line="320"/>
|
||||||
<source>Save chat history</source>
|
<source>Save chat history</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="309"/>
|
<location filename="menu.py" line="321"/>
|
||||||
<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="310"/>
|
<location filename="menu.py" line="322"/>
|
||||||
<source>Send typing notifications</source>
|
<source>Send typing notifications</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="311"/>
|
<location filename="menu.py" line="323"/>
|
||||||
<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="312"/>
|
<location filename="menu.py" line="324"/>
|
||||||
<source>Change</source>
|
<source>Change</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="313"/>
|
<location filename="menu.py" line="325"/>
|
||||||
<source>Allow inlines</source>
|
<source>Allow inlines</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="336"/>
|
<location filename="menu.py" line="348"/>
|
||||||
<source>Chat history</source>
|
<source>Chat history</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="339"/>
|
<location filename="menu.py" line="351"/>
|
||||||
<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="315"/>
|
<location filename="menu.py" line="327"/>
|
||||||
<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="316"/>
|
<location filename="menu.py" line="328"/>
|
||||||
<source>Unblock</source>
|
<source>Unblock</source>
|
||||||
<translation>Unblock</translation>
|
<translation>Unblock</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="317"/>
|
<location filename="menu.py" line="329"/>
|
||||||
<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="323"/>
|
<location filename="menu.py" line="335"/>
|
||||||
<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="324"/>
|
<location filename="menu.py" line="336"/>
|
||||||
<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>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="314"/>
|
<location filename="menu.py" line="326"/>
|
||||||
<source>Block by TOX ID:</source>
|
<source>Block by TOX ID:</source>
|
||||||
<translation>Block by TOX ID:</translation>
|
<translation>Block by TOX ID:</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -423,12 +475,12 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>tray</name>
|
<name>tray</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="106"/>
|
<location filename="main.py" line="113"/>
|
||||||
<source>Open Toxygen</source>
|
<source>Open Toxygen</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="107"/>
|
<location filename="main.py" line="114"/>
|
||||||
<source>Exit</source>
|
<source>Exit</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!DOCTYPE TS><TS version="1.1" language="fr">
|
<!DOCTYPE TS>
|
||||||
|
<TS version="2.1" language="fr">
|
||||||
<context>
|
<context>
|
||||||
<name>AddContact</name>
|
<name>AddContact</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="65"/>
|
<location filename="menu.py" line="64"/>
|
||||||
<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="67"/>
|
<location filename="menu.py" line="66"/>
|
||||||
<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="68"/>
|
<location filename="menu.py" line="67"/>
|
||||||
<source>Message:</source>
|
<source>Message:</source>
|
||||||
<translation>Message :</translation>
|
<translation>Message :</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -21,251 +22,308 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>Form</name>
|
<name>Form</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="66"/>
|
<location filename="menu.py" line="65"/>
|
||||||
<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="220"/>
|
<location filename="menu.py" line="231"/>
|
||||||
<source>IPv6</source>
|
<source>IPv6</source>
|
||||||
<translation>IPv6</translation>
|
<translation>IPv6</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="221"/>
|
<location filename="menu.py" line="232"/>
|
||||||
<source>UDP</source>
|
<source>UDP</source>
|
||||||
<translation>UDP</translation>
|
<translation>UDP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="222"/>
|
<location filename="menu.py" line="233"/>
|
||||||
<source>Proxy</source>
|
<source>Proxy</source>
|
||||||
<translation>Proxy</translation>
|
<translation>Proxy</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="223"/>
|
<location filename="menu.py" line="234"/>
|
||||||
<source>IP:</source>
|
<source>IP:</source>
|
||||||
<translation>IP :</translation>
|
<translation>IP :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="224"/>
|
<location filename="menu.py" line="235"/>
|
||||||
<source>Port:</source>
|
<source>Port:</source>
|
||||||
<translation>Port :</translation>
|
<translation>Port :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="90"/>
|
<location filename="mainscreen.py" line="99"/>
|
||||||
<source>Online contacts</source>
|
<source>Online contacts</source>
|
||||||
<translation>Contacts connectés</translation>
|
<translation>Contacts connectés</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="237"/>
|
||||||
|
<source>HTTP</source>
|
||||||
|
<translation>HTTP</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="95"/>
|
<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="101"/>
|
<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="286"/>
|
<location filename="mainscreen.py" line="346"/>
|
||||||
<source>About</source>
|
<source>About</source>
|
||||||
<translation>À Propos</translation>
|
<translation>À Propos</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="94"/>
|
<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="96"/>
|
<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="97"/>
|
<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="98"/>
|
<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="99"/>
|
<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="100"/>
|
<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="762"/>
|
<location filename="profile.py" line="840"/>
|
||||||
<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="764"/>
|
<location filename="profile.py" line="842"/>
|
||||||
<source>Friend request</source>
|
<source>Friend request</source>
|
||||||
<translation>Demande d'amis</translation>
|
<translation>Demande d'amis</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="287"/>
|
<location filename="mainscreen.py" line="319"/>
|
||||||
<source>Toxygen is Tox client written on Python 2.7. Version: </source>
|
<source>Toxygen is Tox client written on Python 2.7. Version: </source>
|
||||||
<translation>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="329"/>
|
<location filename="mainscreen.py" line="390"/>
|
||||||
<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="367"/>
|
<location filename="mainscreen.py" line="431"/>
|
||||||
<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="368"/>
|
<location filename="mainscreen.py" line="432"/>
|
||||||
<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="370"/>
|
<location filename="mainscreen.py" line="434"/>
|
||||||
<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="371"/>
|
<location filename="mainscreen.py" line="435"/>
|
||||||
<source>Clear history</source>
|
<source>Clear history</source>
|
||||||
<translation>Vider l'historique</translation>
|
<translation>Vider l'historique</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="372"/>
|
<location filename="mainscreen.py" line="436"/>
|
||||||
<source>Copy public key</source>
|
<source>Copy public key</source>
|
||||||
<translation>Copier la clé publique</translation>
|
<translation>Copier la clé publique</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="374"/>
|
<location filename="mainscreen.py" line="438"/>
|
||||||
<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="639"/>
|
<location filename="profile.py" line="686"/>
|
||||||
<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 type="unfinished"></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="102"/>
|
<location filename="mainscreen.py" line="111"/>
|
||||||
<source>Audio</source>
|
<source>Audio</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Audio</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="112"/>
|
||||||
|
<source>Find contact</source>
|
||||||
|
<translation>Trouver le contact</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="profile.py" line="812"/>
|
||||||
|
<source>Friend added</source>
|
||||||
|
<translation>Ami rajouté</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="347"/>
|
||||||
|
<source>Toxygen is Tox client written on Python.
|
||||||
|
Version: </source>
|
||||||
|
<translation>Toxygen est un client Tox écrit en Python.
|
||||||
|
Version :</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="profile.py" line="813"/>
|
||||||
|
<source>Friend added without sending friend request</source>
|
||||||
|
<translation>Ami rajouté sans avoir envoyé de demande</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="list_items.py" line="231"/>
|
||||||
|
<source>Choose folder</source>
|
||||||
|
<translation>Choisir le dossier</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="113"/>
|
||||||
|
<source>Send screenshot</source>
|
||||||
|
<translation>Envoyer une capture d'écran</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="114"/>
|
||||||
|
<source>Send file</source>
|
||||||
|
<translation>Envoyer le fichier</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="115"/>
|
||||||
|
<source>Send message</source>
|
||||||
|
<translation>Envoyer le message</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="116"/>
|
||||||
|
<source>Start audio call with friend</source>
|
||||||
|
<translation>Lancer un appel audio avec un ami</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>NetworkSettings</name>
|
<name>NetworkSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="219"/>
|
<location filename="menu.py" line="230"/>
|
||||||
<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="225"/>
|
<location filename="menu.py" line="236"/>
|
||||||
<source>Restart TOX core</source>
|
<source>Restart TOX core</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Relancer le noyau TOX</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ProfileSettingsForm</name>
|
<name>ProfileSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="131"/>
|
<location filename="menu.py" line="133"/>
|
||||||
<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="132"/>
|
<location filename="menu.py" line="134"/>
|
||||||
<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="133"/>
|
<location filename="menu.py" line="135"/>
|
||||||
<source>Name:</source>
|
<source>Name:</source>
|
||||||
<translation>Nom :</translation>
|
<translation>Nom :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="134"/>
|
<location filename="menu.py" line="136"/>
|
||||||
<source>Status:</source>
|
<source>Status:</source>
|
||||||
<translation>Status :</translation>
|
<translation>Status :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="135"/>
|
<location filename="menu.py" line="137"/>
|
||||||
<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="136"/>
|
<location filename="menu.py" line="138"/>
|
||||||
<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="137"/>
|
<location filename="menu.py" line="139"/>
|
||||||
<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="138"/>
|
<location filename="menu.py" line="140"/>
|
||||||
<source>Reset avatar</source>
|
<source>Reset avatar</source>
|
||||||
<translation>Réinitialiser l'avatar</translation>
|
<translation>Réinitialiser l'avatar</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="141"/>
|
||||||
|
<source>New NoSpam</source>
|
||||||
|
<translation>Nouveau NoSpam</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>audioSettingsForm</name>
|
<name>audioSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="504"/>
|
<location filename="menu.py" line="522"/>
|
||||||
<source>Audio settings</source>
|
<source>Audio settings</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Paramètres audio</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="505"/>
|
<location filename="menu.py" line="523"/>
|
||||||
<source>Input device:</source>
|
<source>Input device:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Péripherique d'entrée :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="506"/>
|
<location filename="menu.py" line="524"/>
|
||||||
<source>Output device:</source>
|
<source>Output device:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Péripherique de sortie :</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>incoming_call</name>
|
<name>incoming_call</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1041"/>
|
<location filename="profile.py" line="1151"/>
|
||||||
<source>Incoming video call</source>
|
<source>Incoming video call</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Appel vidéo entrant</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1043"/>
|
<location filename="profile.py" line="1153"/>
|
||||||
<source>Incoming audio call</source>
|
<source>Incoming audio call</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Appel audio entrant</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>interfaceForm</name>
|
<name>interfaceForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="442"/>
|
<location filename="menu.py" line="460"/>
|
||||||
<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="443"/>
|
<location filename="menu.py" line="461"/>
|
||||||
<source>Theme:</source>
|
<source>Theme:</source>
|
||||||
<translation>Thème :</translation>
|
<translation>Thème :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="444"/>
|
<location filename="menu.py" line="462"/>
|
||||||
<source>Language:</source>
|
<source>Language:</source>
|
||||||
<translation>Langue :</translation>
|
<translation>Langue :</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -273,47 +331,47 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>login</name>
|
<name>login</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="57"/>
|
<location filename="loginscreen.py" line="70"/>
|
||||||
<source>Log in</source>
|
<source>Log in</source>
|
||||||
<translation>Se connecter</translation>
|
<translation>Se connecter</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="58"/>
|
<location filename="loginscreen.py" line="71"/>
|
||||||
<source>Create</source>
|
<source>Create</source>
|
||||||
<translation>Créer</translation>
|
<translation>Créer</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="59"/>
|
<location filename="loginscreen.py" line="72"/>
|
||||||
<source>Profile name:</source>
|
<source>Profile name:</source>
|
||||||
<translation>Nom du profil :</translation>
|
<translation>Nom du profil :</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="60"/>
|
<location filename="loginscreen.py" line="73"/>
|
||||||
<source>Load profile</source>
|
<source>Load profile</source>
|
||||||
<translation>Charger le profil</translation>
|
<translation>Charger le profil</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="61"/>
|
<location filename="loginscreen.py" line="74"/>
|
||||||
<source>Use as default</source>
|
<source>Use as default</source>
|
||||||
<translation>Utiliser par défaut</translation>
|
<translation>Utiliser par défaut</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="62"/>
|
<location filename="loginscreen.py" line="75"/>
|
||||||
<source>Load existing profile</source>
|
<source>Load existing profile</source>
|
||||||
<translation>Charger un profil existant</translation>
|
<translation>Charger un profil existant</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="63"/>
|
<location filename="loginscreen.py" line="76"/>
|
||||||
<source>Create new profile</source>
|
<source>Create new profile</source>
|
||||||
<translation>Créer un nouveau profil</translation>
|
<translation>Créer un nouveau profil</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="64"/>
|
<location filename="loginscreen.py" line="77"/>
|
||||||
<source>toxygen</source>
|
<source>toxygen</source>
|
||||||
<translation>toxygen</translation>
|
<translation>toxygen</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="80"/>
|
<location filename="main.py" line="87"/>
|
||||||
<source>Looks like other instance of Toxygen uses this profile! Continue?</source>
|
<source>Looks like other instance of Toxygen uses this profile! Continue?</source>
|
||||||
<translation>Il semble qu'une autre instance de Toxygen utilise ce profil ! Continuer ?</translation>
|
<translation>Il semble qu'une autre instance de Toxygen utilise ce profil ! Continuer ?</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -321,22 +379,22 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>notificationsForm</name>
|
<name>notificationsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="383"/>
|
<location filename="menu.py" line="401"/>
|
||||||
<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="384"/>
|
<location filename="menu.py" line="402"/>
|
||||||
<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="385"/>
|
<location filename="menu.py" line="403"/>
|
||||||
<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="386"/>
|
<location filename="menu.py" line="404"/>
|
||||||
<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>
|
||||||
@@ -344,90 +402,90 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>privacySettings</name>
|
<name>privacySettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="307"/>
|
<location filename="menu.py" line="319"/>
|
||||||
<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="308"/>
|
<location filename="menu.py" line="320"/>
|
||||||
<source>Save chat history</source>
|
<source>Save chat history</source>
|
||||||
<translation>Sauvegarder l'historique du chat</translation>
|
<translation>Sauvegarder l'historique de chat</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="309"/>
|
<location filename="menu.py" line="321"/>
|
||||||
<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="310"/>
|
<location filename="menu.py" line="322"/>
|
||||||
<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="311"/>
|
<location filename="menu.py" line="323"/>
|
||||||
<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="312"/>
|
<location filename="menu.py" line="324"/>
|
||||||
<source>Change</source>
|
<source>Change</source>
|
||||||
<translation>Modifier</translation>
|
<translation>Modifier</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="313"/>
|
<location filename="menu.py" line="325"/>
|
||||||
<source>Allow inlines</source>
|
<source>Allow inlines</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Activer l'auto-réception</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="348"/>
|
||||||
|
<source>Chat history</source>
|
||||||
|
<translation>Historique de chat</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="351"/>
|
||||||
|
<source>History will be cleaned! Continue?</source>
|
||||||
|
<translation>L'Historique va être nettoyé ! Confirmer ?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="327"/>
|
||||||
|
<source>Blocked users:</source>
|
||||||
|
<translation>Utilisateurs bloqués :</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="328"/>
|
||||||
|
<source>Unblock</source>
|
||||||
|
<translation>Débloquer</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="329"/>
|
||||||
|
<source>Block user</source>
|
||||||
|
<translation>Bloquer l'utilisateur</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="335"/>
|
||||||
|
<source>Add to friend list</source>
|
||||||
|
<translation>Ajouter à la liste des amis</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="336"/>
|
<location filename="menu.py" line="336"/>
|
||||||
<source>Chat history</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="menu.py" line="339"/>
|
|
||||||
<source>History will be cleaned! Continue?</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="menu.py" line="315"/>
|
|
||||||
<source>Blocked users:</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="menu.py" line="316"/>
|
|
||||||
<source>Unblock</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="menu.py" line="317"/>
|
|
||||||
<source>Block user</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="menu.py" line="323"/>
|
|
||||||
<source>Add to friend list</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="menu.py" line="324"/>
|
|
||||||
<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 type="unfinished"></translation>
|
<translation>Voulez vous rajouter cet utilisateur à votre liste d'amis ?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="314"/>
|
<location filename="menu.py" line="326"/>
|
||||||
<source>Block by TOX ID:</source>
|
<source>Block by TOX ID:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Bloquer l'ID TOX :</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>tray</name>
|
<name>tray</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="106"/>
|
<location filename="main.py" line="113"/>
|
||||||
<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="107"/>
|
<location filename="main.py" line="114"/>
|
||||||
<source>Exit</source>
|
<source>Exit</source>
|
||||||
<translation>Quitter</translation>
|
<translation>Quitter</translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
@@ -4,17 +4,17 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>AddContact</name>
|
<name>AddContact</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="65"/>
|
<location filename="menu.py" line="64"/>
|
||||||
<source>Add contact</source>
|
<source>Add contact</source>
|
||||||
<translation>Добавить контакт</translation>
|
<translation>Добавить контакт</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="67"/>
|
<location filename="menu.py" line="66"/>
|
||||||
<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="68"/>
|
<location filename="menu.py" line="67"/>
|
||||||
<source>Message:</source>
|
<source>Message:</source>
|
||||||
<translation>Сообщение:</translation>
|
<translation>Сообщение:</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -22,160 +22,206 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>Form</name>
|
<name>Form</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="66"/>
|
<location filename="menu.py" line="65"/>
|
||||||
<source>Send request</source>
|
<source>Send request</source>
|
||||||
<translation>Отправить запрос</translation>
|
<translation>Отправить запрос</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="220"/>
|
<location filename="menu.py" line="231"/>
|
||||||
<source>IPv6</source>
|
<source>IPv6</source>
|
||||||
<translation>IPv6</translation>
|
<translation>IPv6</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="221"/>
|
<location filename="menu.py" line="232"/>
|
||||||
<source>UDP</source>
|
<source>UDP</source>
|
||||||
<translation>UDP</translation>
|
<translation>UDP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="222"/>
|
<location filename="menu.py" line="233"/>
|
||||||
<source>Proxy</source>
|
<source>Proxy</source>
|
||||||
<translation>Прокси</translation>
|
<translation>Прокси</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="223"/>
|
<location filename="menu.py" line="234"/>
|
||||||
<source>IP:</source>
|
<source>IP:</source>
|
||||||
<translation>IP:</translation>
|
<translation>IP:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="224"/>
|
<location filename="menu.py" line="235"/>
|
||||||
<source>Port:</source>
|
<source>Port:</source>
|
||||||
<translation>Порт:</translation>
|
<translation>Порт:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="90"/>
|
<location filename="mainscreen.py" line="99"/>
|
||||||
<source>Online contacts</source>
|
<source>Online contacts</source>
|
||||||
<translation>Контакты в сети</translation>
|
<translation>Контакты в сети</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="237"/>
|
||||||
|
<source>HTTP</source>
|
||||||
|
<translation>HTTP</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="95"/>
|
<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="101"/>
|
<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="286"/>
|
<location filename="mainscreen.py" line="346"/>
|
||||||
<source>About</source>
|
<source>About</source>
|
||||||
<translation>О программе</translation>
|
<translation>О программе</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="94"/>
|
<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="96"/>
|
<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="97"/>
|
<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="98"/>
|
<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="99"/>
|
<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="100"/>
|
<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="762"/>
|
<location filename="profile.py" line="840"/>
|
||||||
<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="764"/>
|
<location filename="profile.py" line="842"/>
|
||||||
<source>Friend request</source>
|
<source>Friend request</source>
|
||||||
<translation>Запрос на добавление в друзья</translation>
|
<translation>Запрос на добавление в друзья</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="287"/>
|
<location filename="mainscreen.py" line="390"/>
|
||||||
<source>Toxygen is Tox client written on Python 2.7. Version: </source>
|
|
||||||
<translation>Toxygen - клиент для мессенджера Tox, написанный на Python 2.7. Версия: </translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="mainscreen.py" line="329"/>
|
|
||||||
<source>Choose file</source>
|
<source>Choose file</source>
|
||||||
<translation>Выберите файл</translation>
|
<translation>Выберите файл</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="367"/>
|
<location filename="mainscreen.py" line="431"/>
|
||||||
<source>Disallow auto accept</source>
|
<source>Disallow auto accept</source>
|
||||||
<translation>Запретить автоматическое получение файлов</translation>
|
<translation>Запретить автоматическое получение файлов</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="368"/>
|
<location filename="mainscreen.py" line="432"/>
|
||||||
<source>Allow auto accept</source>
|
<source>Allow auto accept</source>
|
||||||
<translation>Разрешить автоматическое получение файлов</translation>
|
<translation>Разрешить автоматическое получение файлов</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="370"/>
|
<location filename="mainscreen.py" line="434"/>
|
||||||
<source>Set alias</source>
|
<source>Set alias</source>
|
||||||
<translation>Изменить псевдоним</translation>
|
<translation>Изменить псевдоним</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="371"/>
|
<location filename="mainscreen.py" line="435"/>
|
||||||
<source>Clear history</source>
|
<source>Clear history</source>
|
||||||
<translation>Очистить историю</translation>
|
<translation>Очистить историю</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="372"/>
|
<location filename="mainscreen.py" line="436"/>
|
||||||
<source>Copy public key</source>
|
<source>Copy public key</source>
|
||||||
<translation>Копировать публичный ключ</translation>
|
<translation>Копировать публичный ключ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="mainscreen.py" line="374"/>
|
<location filename="mainscreen.py" line="438"/>
|
||||||
<source>Remove friend</source>
|
<source>Remove friend</source>
|
||||||
<translation>Удалить друга</translation>
|
<translation>Удалить друга</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="639"/>
|
<location filename="profile.py" line="686"/>
|
||||||
<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="102"/>
|
<location filename="mainscreen.py" line="111"/>
|
||||||
<source>Audio</source>
|
<source>Audio</source>
|
||||||
<translation>Аудио</translation>
|
<translation>Аудио</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="112"/>
|
||||||
|
<source>Find contact</source>
|
||||||
|
<translation>Найти контакт</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="profile.py" line="812"/>
|
||||||
|
<source>Friend added</source>
|
||||||
|
<translation>Друг добавлен</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="347"/>
|
||||||
|
<source>Toxygen is Tox client written on Python.
|
||||||
|
Version: </source>
|
||||||
|
<translation>Toxygen - клиент для мессенджера Tox, написанный на Python. Версия: </translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="profile.py" line="813"/>
|
||||||
|
<source>Friend added without sending friend request</source>
|
||||||
|
<translation>Друг добавлен без отправки запроса на добавление в друзья</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="list_items.py" line="231"/>
|
||||||
|
<source>Choose folder</source>
|
||||||
|
<translation>Выбрать папку</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="113"/>
|
||||||
|
<source>Send screenshot</source>
|
||||||
|
<translation>Отправить снимок экрана</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="114"/>
|
||||||
|
<source>Send file</source>
|
||||||
|
<translation>Отправить файл</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="115"/>
|
||||||
|
<source>Send message</source>
|
||||||
|
<translation>Отправить сообщение</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="mainscreen.py" line="116"/>
|
||||||
|
<source>Start audio call with friend</source>
|
||||||
|
<translation>Начать аудиозвонок с другом</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>NetworkSettings</name>
|
<name>NetworkSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="219"/>
|
<location filename="menu.py" line="230"/>
|
||||||
<source>Network settings</source>
|
<source>Network settings</source>
|
||||||
<translation>Настройки сети</translation>
|
<translation>Настройки сети</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="225"/>
|
<location filename="menu.py" line="236"/>
|
||||||
<source>Restart TOX core</source>
|
<source>Restart TOX core</source>
|
||||||
<translation>Перезапустить ядро TOX</translation>
|
<translation>Перезапустить ядро TOX</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -183,32 +229,32 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ProfileSettingsForm</name>
|
<name>ProfileSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="131"/>
|
<location filename="menu.py" line="133"/>
|
||||||
<source>Export profile</source>
|
<source>Export profile</source>
|
||||||
<translation>Экспорт профиля</translation>
|
<translation>Экспорт профиля</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="132"/>
|
<location filename="menu.py" line="134"/>
|
||||||
<source>Profile settings</source>
|
<source>Profile settings</source>
|
||||||
<translation>Настройки профиля</translation>
|
<translation>Настройки профиля</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="133"/>
|
<location filename="menu.py" line="135"/>
|
||||||
<source>Name:</source>
|
<source>Name:</source>
|
||||||
<translation>Имя:</translation>
|
<translation>Имя:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="134"/>
|
<location filename="menu.py" line="136"/>
|
||||||
<source>Status:</source>
|
<source>Status:</source>
|
||||||
<translation>Статус:</translation>
|
<translation>Статус:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="135"/>
|
<location filename="menu.py" line="137"/>
|
||||||
<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="136"/>
|
<location filename="menu.py" line="138"/>
|
||||||
<source>Copy TOX ID</source>
|
<source>Copy TOX ID</source>
|
||||||
<translation>Копировать TOX ID</translation>
|
<translation>Копировать TOX ID</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -218,30 +264,35 @@
|
|||||||
<translation type="obsolete">Язык:</translation>
|
<translation type="obsolete">Язык:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="137"/>
|
<location filename="menu.py" line="139"/>
|
||||||
<source>New avatar</source>
|
<source>New avatar</source>
|
||||||
<translation>Новый аватар</translation>
|
<translation>Новый аватар</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="138"/>
|
<location filename="menu.py" line="140"/>
|
||||||
<source>Reset avatar</source>
|
<source>Reset avatar</source>
|
||||||
<translation>Сбросить аватар</translation>
|
<translation>Сбросить аватар</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="menu.py" line="141"/>
|
||||||
|
<source>New NoSpam</source>
|
||||||
|
<translation>Новый NoSpam</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>audioSettingsForm</name>
|
<name>audioSettingsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="504"/>
|
<location filename="menu.py" line="522"/>
|
||||||
<source>Audio settings</source>
|
<source>Audio settings</source>
|
||||||
<translation>Настройки аудио</translation>
|
<translation>Настройки аудио</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="505"/>
|
<location filename="menu.py" line="523"/>
|
||||||
<source>Input device:</source>
|
<source>Input device:</source>
|
||||||
<translation>Устройство ввода:</translation>
|
<translation>Устройство ввода:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="506"/>
|
<location filename="menu.py" line="524"/>
|
||||||
<source>Output device:</source>
|
<source>Output device:</source>
|
||||||
<translation>Устройство вывода:</translation>
|
<translation>Устройство вывода:</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -249,12 +300,12 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>incoming_call</name>
|
<name>incoming_call</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1041"/>
|
<location filename="profile.py" line="1151"/>
|
||||||
<source>Incoming video call</source>
|
<source>Incoming video call</source>
|
||||||
<translation>Входящий видеозвонок</translation>
|
<translation>Входящий видеозвонок</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="profile.py" line="1043"/>
|
<location filename="profile.py" line="1153"/>
|
||||||
<source>Incoming audio call</source>
|
<source>Incoming audio call</source>
|
||||||
<translation>Входящий аудиозвонок</translation>
|
<translation>Входящий аудиозвонок</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -262,17 +313,17 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>interfaceForm</name>
|
<name>interfaceForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="442"/>
|
<location filename="menu.py" line="460"/>
|
||||||
<source>Interface settings</source>
|
<source>Interface settings</source>
|
||||||
<translation>Настройки интерфейса</translation>
|
<translation>Настройки интерфейса</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="443"/>
|
<location filename="menu.py" line="461"/>
|
||||||
<source>Theme:</source>
|
<source>Theme:</source>
|
||||||
<translation>Тема:</translation>
|
<translation>Тема:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="444"/>
|
<location filename="menu.py" line="462"/>
|
||||||
<source>Language:</source>
|
<source>Language:</source>
|
||||||
<translation>Язык:</translation>
|
<translation>Язык:</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -280,47 +331,47 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>login</name>
|
<name>login</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="57"/>
|
<location filename="loginscreen.py" line="70"/>
|
||||||
<source>Log in</source>
|
<source>Log in</source>
|
||||||
<translation>Вход</translation>
|
<translation>Вход</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="58"/>
|
<location filename="loginscreen.py" line="71"/>
|
||||||
<source>Create</source>
|
<source>Create</source>
|
||||||
<translation>Создать</translation>
|
<translation>Создать</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="59"/>
|
<location filename="loginscreen.py" line="72"/>
|
||||||
<source>Profile name:</source>
|
<source>Profile name:</source>
|
||||||
<translation>Имя профиля:</translation>
|
<translation>Имя профиля:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="60"/>
|
<location filename="loginscreen.py" line="73"/>
|
||||||
<source>Load profile</source>
|
<source>Load profile</source>
|
||||||
<translation>Загрузить профиль</translation>
|
<translation>Загрузить профиль</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="61"/>
|
<location filename="loginscreen.py" line="74"/>
|
||||||
<source>Use as default</source>
|
<source>Use as default</source>
|
||||||
<translation>По умолчанию</translation>
|
<translation>По умолчанию</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="62"/>
|
<location filename="loginscreen.py" line="75"/>
|
||||||
<source>Load existing profile</source>
|
<source>Load existing profile</source>
|
||||||
<translation>Загрузить профиль</translation>
|
<translation>Загрузить профиль</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="63"/>
|
<location filename="loginscreen.py" line="76"/>
|
||||||
<source>Create new profile</source>
|
<source>Create new profile</source>
|
||||||
<translation>Создать новый профиль</translation>
|
<translation>Создать новый профиль</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="loginscreen.py" line="64"/>
|
<location filename="loginscreen.py" line="77"/>
|
||||||
<source>toxygen</source>
|
<source>toxygen</source>
|
||||||
<translation>toxygen</translation>
|
<translation>toxygen</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="80"/>
|
<location filename="main.py" line="87"/>
|
||||||
<source>Looks like other instance of Toxygen uses this profile! Continue?</source>
|
<source>Looks like other instance of Toxygen uses this profile! Continue?</source>
|
||||||
<translation>Похоже, что этот профиль используется другим экземпляром Toxygen! Продолжить?</translation>
|
<translation>Похоже, что этот профиль используется другим экземпляром Toxygen! Продолжить?</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -328,22 +379,22 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>notificationsForm</name>
|
<name>notificationsForm</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="383"/>
|
<location filename="menu.py" line="401"/>
|
||||||
<source>Notification settings</source>
|
<source>Notification settings</source>
|
||||||
<translation>Настройки уведомлений</translation>
|
<translation>Настройки уведомлений</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="384"/>
|
<location filename="menu.py" line="402"/>
|
||||||
<source>Enable notifications</source>
|
<source>Enable notifications</source>
|
||||||
<translation>Включить уведомления</translation>
|
<translation>Включить уведомления</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="385"/>
|
<location filename="menu.py" line="403"/>
|
||||||
<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="386"/>
|
<location filename="menu.py" line="404"/>
|
||||||
<source>Enable sound notifications</source>
|
<source>Enable sound notifications</source>
|
||||||
<translation>Включить звуковые уведомления
|
<translation>Включить звуковые уведомления
|
||||||
</translation>
|
</translation>
|
||||||
@@ -352,77 +403,77 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>privacySettings</name>
|
<name>privacySettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="307"/>
|
<location filename="menu.py" line="319"/>
|
||||||
<source>Privacy settings</source>
|
<source>Privacy settings</source>
|
||||||
<translation>Настройки приватности</translation>
|
<translation>Настройки приватности</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="308"/>
|
<location filename="menu.py" line="320"/>
|
||||||
<source>Save chat history</source>
|
<source>Save chat history</source>
|
||||||
<translation>Сохранять историю переписки</translation>
|
<translation>Сохранять историю переписки</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="309"/>
|
<location filename="menu.py" line="321"/>
|
||||||
<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="310"/>
|
<location filename="menu.py" line="322"/>
|
||||||
<source>Send typing notifications</source>
|
<source>Send typing notifications</source>
|
||||||
<translation>Посылать уведомления о наборе текста</translation>
|
<translation>Посылать уведомления о наборе текста</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="311"/>
|
<location filename="menu.py" line="323"/>
|
||||||
<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="312"/>
|
<location filename="menu.py" line="324"/>
|
||||||
<source>Change</source>
|
<source>Change</source>
|
||||||
<translation>Изменить</translation>
|
<translation>Изменить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="313"/>
|
<location filename="menu.py" line="325"/>
|
||||||
<source>Allow inlines</source>
|
<source>Allow inlines</source>
|
||||||
<translation>Разрешать инлайны</translation>
|
<translation>Разрешать инлайны</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="336"/>
|
<location filename="menu.py" line="348"/>
|
||||||
<source>Chat history</source>
|
<source>Chat history</source>
|
||||||
<translation>История чата</translation>
|
<translation>История чата</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="339"/>
|
<location filename="menu.py" line="351"/>
|
||||||
<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="315"/>
|
<location filename="menu.py" line="327"/>
|
||||||
<source>Blocked users:</source>
|
<source>Blocked users:</source>
|
||||||
<translation>Заблокированные пользователи:</translation>
|
<translation>Заблокированные пользователи:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="316"/>
|
<location filename="menu.py" line="328"/>
|
||||||
<source>Unblock</source>
|
<source>Unblock</source>
|
||||||
<translation>Разблокировать</translation>
|
<translation>Разблокировать</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="317"/>
|
<location filename="menu.py" line="329"/>
|
||||||
<source>Block user</source>
|
<source>Block user</source>
|
||||||
<translation>Заблокировать пользователя</translation>
|
<translation>Заблокировать пользователя</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="323"/>
|
<location filename="menu.py" line="335"/>
|
||||||
<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="324"/>
|
<location filename="menu.py" line="336"/>
|
||||||
<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>
|
||||||
<message>
|
<message>
|
||||||
<location filename="menu.py" line="314"/>
|
<location filename="menu.py" line="326"/>
|
||||||
<source>Block by TOX ID:</source>
|
<source>Block by TOX ID:</source>
|
||||||
<translation>Блокировать по TOX ID:</translation>
|
<translation>Блокировать по TOX ID:</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -430,12 +481,12 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>tray</name>
|
<name>tray</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="106"/>
|
<location filename="main.py" line="113"/>
|
||||||
<source>Open Toxygen</source>
|
<source>Open Toxygen</source>
|
||||||
<translation>Открыть Toxygen</translation>
|
<translation>Открыть Toxygen</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="main.py" line="107"/>
|
<location filename="main.py" line="114"/>
|
||||||
<source>Exit</source>
|
<source>Exit</source>
|
||||||
<translation>Выход</translation>
|
<translation>Выход</translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import time
|
|||||||
from platform import system
|
from platform import system
|
||||||
|
|
||||||
|
|
||||||
program_version = '0.1.1'
|
program_version = '0.1.2'
|
||||||
|
|
||||||
|
|
||||||
def log(data):
|
def log(data):
|
||||||
@@ -27,14 +27,15 @@ def convert_time(t):
|
|||||||
return '%02d:%02d' % (h, m)
|
return '%02d:%02d' % (h, m)
|
||||||
|
|
||||||
|
|
||||||
|
# obsolete
|
||||||
def get_style(style):
|
def get_style(style):
|
||||||
if style != 'default':
|
if style != 'default':
|
||||||
return style
|
return style
|
||||||
else:
|
else:
|
||||||
if system() == 'Linux':
|
if system() == 'Windows':
|
||||||
return 'gtk'
|
|
||||||
elif system() == 'Windows':
|
|
||||||
return 'windows'
|
return 'windows'
|
||||||
|
else:
|
||||||
|
return 'gtk'
|
||||||
|
|
||||||
|
|
||||||
class Singleton(object):
|
class Singleton(object):
|
||||||
|
|||||||