11 Commits

Author SHA1 Message Date
337601f2a1 reconnection timeout++ and fix 2016-09-15 00:21:06 +03:00
42e0ec005b db timeout 2016-09-08 00:10:32 +03:00
fb1caa244a fix #25 2016-09-03 14:10:36 +03:00
0fd75c5517 fix #23 2016-08-30 20:23:55 +03:00
d81e3e781b fix #20 2016-08-28 16:11:40 +03:00
43d9a41dae bug fixes 2016-08-28 15:32:02 +03:00
1caf7cd63c readme update 2016-08-19 20:12:51 +03:00
14816588f1 some updates 2016-08-18 19:08:12 +03:00
47b710acdd bug fixes and docs update 2016-08-08 22:11:43 +03:00
3668088f3e some fixes 2016-08-08 14:07:18 +03:00
9f702afcb8 short update 2016-08-05 22:44:01 +03:00
17 changed files with 226 additions and 39 deletions

4
.gitignore vendored
View File

@ -15,9 +15,11 @@ toxygen/libs
toxygen/build toxygen/build
toxygen/dist toxygen/dist
*.spec *.spec
dist/ dist
toxygen/avatars toxygen/avatars
toxygen/__pycache__ toxygen/__pycache__
/*.egg-info /*.egg-info
/*.egg /*.egg
html
Toxygen.egg-info

View File

@ -1,21 +1,20 @@
# Toxygen # Toxygen
Toxygen is cross-platform [Tox](https://tox.chat/) client written in pure Python3 Toxygen is powerful cross-platform [Tox](https://tox.chat/) client written in pure Python3.
[![Release](https://img.shields.io/github/release/xveduk/toxygen.svg?style=flat)](https://github.com/toxygen-project/toxygen/releases/latest) [![Release](https://img.shields.io/github/release/xveduk/toxygen.svg?style=flat)](https://github.com/toxygen-project/toxygen/releases/latest)
[![Stars](https://img.shields.io/github/stars/xveduk/toxygen.svg?style=flat)](https://github.com/toxygen-project/toxygen/stargazers) [![Stars](https://img.shields.io/github/stars/xveduk/toxygen.svg?style=flat)](https://github.com/toxygen-project/toxygen/stargazers)
[![Open issues](https://img.shields.io/github/issues/xveduk/toxygen.svg?style=flat)](https://github.com/toxygen-project/toxygen/issues) [![Open issues](https://img.shields.io/github/issues/xveduk/toxygen.svg?style=flat)](https://github.com/toxygen-project/toxygen/issues)
[![License](https://img.shields.io/badge/license-GPLv3-blue.svg?style=flat)](https://raw.githubusercontent.com/toxygen-project/toxygen/master/LICENSE.md) [![License](https://img.shields.io/badge/license-GPLv3-blue.svg?style=flat)](https://raw.githubusercontent.com/toxygen-project/toxygen/master/LICENSE.md)
[![Build Status](https://travis-ci.org/toxygen-project/toxygen.svg?branch=master)](https://travis-ci.org/toxygen-project/toxygen)
### [Install](/docs/install.md) - [Contribute](/docs/contributing.md) - [Plugins](/docs/plugins.md) - [Compile](/docs/compile.md) - [Contact](/docs/contact.md) ### [Install](/docs/install.md) - [Contribute](/docs/contributing.md) - [Plugins](/docs/plugins.md) - [Compile](/docs/compile.md) - [Contact](/docs/contact.md)
### Supported OS: ### Supported OS:
- Windows ![Linux, Windows and OS X](/docs/os.png)
- Linux
- OS X
### Features ### Features:
- [x] 1v1 messages - [x] 1v1 messages
- [x] File transfers - [x] File transfers
@ -61,3 +60,7 @@ Toxygen is cross-platform [Tox](https://tox.chat/) client written in pure Python
### Docs ### Docs
[Check /docs/ for more info](/docs/) [Check /docs/ for more info](/docs/)
Also visit [pythonhosted.org/Toxygen/](http://pythonhosted.org/Toxygen/)
[Wiki](https://wiki.tox.chat/clients/toxygen)

View File

@ -27,12 +27,14 @@ Run app using ``toxygen`` command.
2. Install PortAudio: 2. Install PortAudio:
``brew install portaudio`` ``brew install portaudio``
3. Install toxygen: 3. Install toxygen:
``pip3 install toxygen`` ``pip3.4 install toxygen``
4. Run toxygen using ``toxygen`` command. 4. Run toxygen using ``toxygen`` command.
## Packages ## Packages
Coming soon. Arch Linux: [AUR](https://aur.archlinux.org/packages/toxygen-git/)
Debian/Ubuntu: [tox.chat](https://tox.chat/download.html#gnulinux)
## From source code (recommended for developers) ## From source code (recommended for developers)

BIN
docs/os.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -340,3 +340,8 @@ class ReceiveAvatar(ReceiveTransfer):
chdir(dirname(avatar_path)) chdir(dirname(avatar_path))
remove(avatar_path) remove(avatar_path)
rename(self._path, avatar_path) rename(self._path, avatar_path)
self.finished(True)
def finished(self, emit=False):
if emit:
super().finished()

View File

@ -1,4 +1,3 @@
# coding=utf-8
from sqlite3 import connect from sqlite3 import connect
import settings import settings
from os import chdir from os import chdir
@ -8,6 +7,8 @@ from toxencryptsave import ToxEncryptSave
PAGE_SIZE = 42 PAGE_SIZE = 42
TIMEOUT = 11
MESSAGE_OWNER = { MESSAGE_OWNER = {
'ME': 0, 'ME': 0,
'FRIEND': 1, 'FRIEND': 1,
@ -32,7 +33,7 @@ class History:
fout.write(data) fout.write(data)
except: except:
os.remove(path) os.remove(path)
db = connect(name + '.hstr') db = connect(name + '.hstr', timeout=TIMEOUT)
cursor = db.cursor() cursor = db.cursor()
cursor.execute('CREATE TABLE IF NOT EXISTS friends(' cursor.execute('CREATE TABLE IF NOT EXISTS friends('
' tox_id TEXT PRIMARY KEY' ' tox_id TEXT PRIMARY KEY'
@ -62,7 +63,7 @@ class History:
def add_friend_to_db(self, tox_id): def add_friend_to_db(self, tox_id):
chdir(settings.ProfileHelper.get_path()) chdir(settings.ProfileHelper.get_path())
db = connect(self._name + '.hstr') db = connect(self._name + '.hstr', timeout=TIMEOUT)
try: try:
cursor = db.cursor() cursor = db.cursor()
cursor.execute('INSERT INTO friends VALUES (?);', (tox_id, )) cursor.execute('INSERT INTO friends VALUES (?);', (tox_id, ))
@ -82,7 +83,7 @@ class History:
def delete_friend_from_db(self, tox_id): def delete_friend_from_db(self, tox_id):
chdir(settings.ProfileHelper.get_path()) chdir(settings.ProfileHelper.get_path())
db = connect(self._name + '.hstr') db = connect(self._name + '.hstr', timeout=TIMEOUT)
try: try:
cursor = db.cursor() cursor = db.cursor()
cursor.execute('DELETE FROM friends WHERE tox_id=?;', (tox_id, )) cursor.execute('DELETE FROM friends WHERE tox_id=?;', (tox_id, ))
@ -96,7 +97,7 @@ class History:
def friend_exists_in_db(self, tox_id): def friend_exists_in_db(self, tox_id):
chdir(settings.ProfileHelper.get_path()) chdir(settings.ProfileHelper.get_path())
db = connect(self._name + '.hstr') db = connect(self._name + '.hstr', timeout=TIMEOUT)
cursor = db.cursor() cursor = db.cursor()
cursor.execute('SELECT 0 FROM friends WHERE tox_id=?', (tox_id, )) cursor.execute('SELECT 0 FROM friends WHERE tox_id=?', (tox_id, ))
result = cursor.fetchone() result = cursor.fetchone()
@ -105,7 +106,7 @@ class History:
def save_messages_to_db(self, tox_id, messages_iter): def save_messages_to_db(self, tox_id, messages_iter):
chdir(settings.ProfileHelper.get_path()) chdir(settings.ProfileHelper.get_path())
db = connect(self._name + '.hstr') db = connect(self._name + '.hstr', timeout=TIMEOUT)
try: try:
cursor = db.cursor() cursor = db.cursor()
cursor.executemany('INSERT INTO id' + tox_id + '(message, owner, unix_time, message_type) ' cursor.executemany('INSERT INTO id' + tox_id + '(message, owner, unix_time, message_type) '
@ -119,7 +120,7 @@ class History:
def update_messages(self, tox_id, unsent_time): def update_messages(self, tox_id, unsent_time):
chdir(settings.ProfileHelper.get_path()) chdir(settings.ProfileHelper.get_path())
db = connect(self._name + '.hstr') db = connect(self._name + '.hstr', timeout=TIMEOUT)
try: try:
cursor = db.cursor() cursor = db.cursor()
cursor.execute('UPDATE id' + tox_id + ' SET owner = 0 ' cursor.execute('UPDATE id' + tox_id + ' SET owner = 0 '
@ -134,7 +135,7 @@ class History:
def delete_message(self, tox_id, time): def delete_message(self, tox_id, time):
chdir(settings.ProfileHelper.get_path()) chdir(settings.ProfileHelper.get_path())
db = connect(self._name + '.hstr') db = connect(self._name + '.hstr', timeout=TIMEOUT)
try: try:
cursor = db.cursor() cursor = db.cursor()
cursor.execute('DELETE FROM id' + tox_id + ' WHERE unix_time = ' + str(time) + ';') cursor.execute('DELETE FROM id' + tox_id + ' WHERE unix_time = ' + str(time) + ';')
@ -147,7 +148,7 @@ class History:
def delete_messages(self, tox_id): def delete_messages(self, tox_id):
chdir(settings.ProfileHelper.get_path()) chdir(settings.ProfileHelper.get_path())
db = connect(self._name + '.hstr') db = connect(self._name + '.hstr', timeout=TIMEOUT)
try: try:
cursor = db.cursor() cursor = db.cursor()
cursor.execute('DELETE FROM id' + tox_id + ';') cursor.execute('DELETE FROM id' + tox_id + ';')
@ -162,9 +163,10 @@ class History:
return History.MessageGetter(self._name, tox_id) return History.MessageGetter(self._name, tox_id)
class MessageGetter: class MessageGetter:
def __init__(self, name, tox_id): def __init__(self, name, tox_id):
chdir(settings.ProfileHelper.get_path()) chdir(settings.ProfileHelper.get_path())
self._db = connect(name + '.hstr') self._db = connect(name + '.hstr', timeout=TIMEOUT)
self._cursor = self._db.cursor() self._cursor = self._db.cursor()
self._cursor.execute('SELECT message, owner, unix_time, message_type FROM id' + tox_id + self._cursor.execute('SELECT message, owner, unix_time, message_type FROM id' + tox_id +
' ORDER BY unix_time DESC;') ' ORDER BY unix_time DESC;')

View File

@ -25,7 +25,9 @@ class MessageEdit(QtGui.QTextBrowser):
self.setOpenExternalLinks(True) self.setOpenExternalLinks(True)
self.setAcceptRichText(True) self.setAcceptRichText(True)
self.setOpenLinks(False) self.setOpenLinks(False)
self.setSearchPaths([smileys.SmileyLoader.get_instance().get_smileys_path()]) path = smileys.SmileyLoader.get_instance().get_smileys_path()
if path is not None:
self.setSearchPaths([path])
self.document().setDefaultStyleSheet('a { color: #306EFF; }') self.document().setDefaultStyleSheet('a { color: #306EFF; }')
text = self.decoratedText(text) text = self.decoratedText(text)
if message_type != TOX_MESSAGE_TYPE['NORMAL']: if message_type != TOX_MESSAGE_TYPE['NORMAL']:
@ -127,7 +129,7 @@ class MessageItem(QtGui.QWidget):
def __init__(self, text, time, user='', sent=True, message_type=TOX_MESSAGE_TYPE['NORMAL'], parent=None): def __init__(self, text, time, user='', sent=True, message_type=TOX_MESSAGE_TYPE['NORMAL'], parent=None):
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
self.name = DataLabel(self) self.name = DataLabel(self)
self.name.setGeometry(QtCore.QRect(2, 2, 95, 20)) self.name.setGeometry(QtCore.QRect(2, 2, 95, 23))
self.name.setTextFormat(QtCore.Qt.PlainText) self.name.setTextFormat(QtCore.Qt.PlainText)
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily(settings.Settings.get_instance()['font']) font.setFamily(settings.Settings.get_instance()['font'])
@ -137,7 +139,7 @@ class MessageItem(QtGui.QWidget):
self.name.setText(user) self.name.setText(user)
self.time = QtGui.QLabel(self) self.time = QtGui.QLabel(self)
self.time.setGeometry(QtCore.QRect(parent.width() - 50, 0, 50, 20)) self.time.setGeometry(QtCore.QRect(parent.width() - 60, 0, 50, 25))
font.setPointSize(10) font.setPointSize(10)
font.setBold(False) font.setBold(False)
self.time.setFont(font) self.time.setFont(font)
@ -151,12 +153,12 @@ class MessageItem(QtGui.QWidget):
self.time.setText(convert_time(time)) self.time.setText(convert_time(time))
self.t = False self.t = False
self.message = MessageEdit(text, parent.width() - 150, message_type, self) self.message = MessageEdit(text, parent.width() - 160, message_type, self)
if message_type != TOX_MESSAGE_TYPE['NORMAL']: if message_type != TOX_MESSAGE_TYPE['NORMAL']:
self.name.setStyleSheet("QLabel { color: #5CB3FF; }") self.name.setStyleSheet("QLabel { color: #5CB3FF; }")
self.message.setAlignment(QtCore.Qt.AlignCenter) self.message.setAlignment(QtCore.Qt.AlignCenter)
self.time.setStyleSheet("QLabel { color: #5CB3FF; }") self.time.setStyleSheet("QLabel { color: #5CB3FF; }")
self.message.setGeometry(QtCore.QRect(100, 0, parent.width() - 150, self.message.height())) self.message.setGeometry(QtCore.QRect(100, 0, parent.width() - 160, self.message.height()))
self.setFixedHeight(self.message.height()) self.setFixedHeight(self.message.height())
def mouseReleaseEvent(self, event): def mouseReleaseEvent(self, event):
@ -295,7 +297,7 @@ class FileTransferItem(QtGui.QListWidget):
self.state = state self.state = state
self.name = DataLabel(self) self.name = DataLabel(self)
self.name.setGeometry(QtCore.QRect(3, 7, 95, 20)) self.name.setGeometry(QtCore.QRect(3, 7, 95, 25))
self.name.setTextFormat(QtCore.Qt.PlainText) self.name.setTextFormat(QtCore.Qt.PlainText)
font = QtGui.QFont() font = QtGui.QFont()
font.setFamily(settings.Settings.get_instance()['font']) font.setFamily(settings.Settings.get_instance()['font'])
@ -305,14 +307,14 @@ class FileTransferItem(QtGui.QListWidget):
self.name.setText(user) self.name.setText(user)
self.time = QtGui.QLabel(self) self.time = QtGui.QLabel(self)
self.time.setGeometry(QtCore.QRect(width - 53, 7, 50, 20)) self.time.setGeometry(QtCore.QRect(width - 60, 7, 50, 25))
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.cancel = QtGui.QPushButton(self) self.cancel = QtGui.QPushButton(self)
self.cancel.setGeometry(QtCore.QRect(width - 120, 2, 30, 30)) self.cancel.setGeometry(QtCore.QRect(width - 125, 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)
@ -360,7 +362,7 @@ class FileTransferItem(QtGui.QListWidget):
self.file_name.setToolTip(file_name) self.file_name.setToolTip(file_name)
self.saved_name = file_name self.saved_name = file_name
self.time_left = QtGui.QLabel(self) self.time_left = QtGui.QLabel(self)
self.time_left.setGeometry(QtCore.QRect(width - 87, 7, 30, 20)) self.time_left.setGeometry(QtCore.QRect(width - 92, 7, 30, 20))
font.setPointSize(10) font.setPointSize(10)
self.time_left.setFont(font) self.time_left.setFont(font)
self.time_left.setVisible(state == TOX_FILE_TRANSFER_STATE['RUNNING']) self.time_left.setVisible(state == TOX_FILE_TRANSFER_STATE['RUNNING'])

View File

@ -127,7 +127,7 @@ class MainWindow(QtGui.QMainWindow, Singleton):
self.messageEdit.setGeometry(QtCore.QRect(0, 3, 450, 55)) self.messageEdit.setGeometry(QtCore.QRect(0, 3, 450, 55))
self.messageEdit.setObjectName("messageEdit") self.messageEdit.setObjectName("messageEdit")
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(10) font.setPointSize(11)
font.setFamily(settings.Settings.get_instance()['font']) font.setFamily(settings.Settings.get_instance()['font'])
self.messageEdit.setFont(font) self.messageEdit.setFont(font)
@ -260,7 +260,7 @@ class MainWindow(QtGui.QMainWindow, Singleton):
self.messages.setSpacing(1) self.messages.setSpacing(1)
self.messages.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.messages.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.messages.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.messages.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
# self.messages.setFocusPolicy(QtCore.Qt.NoFocus) self.messages.focusOutEvent = lambda event: self.messages.clearSelection()
def load(pos): def load(pos):
if not pos: if not pos:

View File

@ -714,10 +714,10 @@ class InterfaceSettings(CenteredWidget):
msgBox.exec_() msgBox.exec_()
def select_color(self): def select_color(self):
col = QtGui.QColorDialog.getColor() settings = Settings.get_instance()
col = QtGui.QColorDialog.getColor(settings['unread_color'])
if col.isValid(): if col.isValid():
settings = Settings.get_instance()
name = col.name() name = col.name()
settings['unread_color'] = name settings['unread_color'] = name
settings.save() settings.save()

View File

@ -237,7 +237,7 @@ class Profile(contact.Contact, Singleton):
self.update_filtration() self.update_filtration()
except Exception as ex: # no friend found. ignore except Exception as ex: # no friend found. ignore
log('Friend value: ' + str(value)) log('Friend value: ' + str(value))
log('Error: ' + str(ex)) log('Error in set active: ' + str(ex))
raise raise
active_friend = property(get_active, set_active) active_friend = property(get_active, set_active)
@ -313,7 +313,7 @@ class Profile(contact.Contact, Singleton):
ft = self._file_transfers[(friend_num, file_num)] ft = self._file_transfers[(friend_num, file_num)]
if type(ft) is SendTransfer: if type(ft) is SendTransfer:
self._paused_file_transfers[ft.get_id()] = [ft.get_path(), friend_num, False, -1] self._paused_file_transfers[ft.get_id()] = [ft.get_path(), friend_num, False, -1]
elif type(ft) is ReceiveTransfer: elif type(ft) is ReceiveTransfer and ft.state != TOX_FILE_TRANSFER_STATE['INCOMING_NOT_STARTED']:
self._paused_file_transfers[ft.get_id()] = [ft.get_path(), friend_num, True, ft.total_size()] self._paused_file_transfers[ft.get_id()] = [ft.get_path(), friend_num, True, ft.total_size()]
self.cancel_transfer(friend_num, file_num, True) self.cancel_transfer(friend_num, file_num, True)
@ -838,7 +838,7 @@ class Profile(contact.Contact, Singleton):
def reconnect(self): def reconnect(self):
if self.status is None or all(list(map(lambda x: x.status is None, self._friends))): if self.status is None or all(list(map(lambda x: x.status is None, self._friends))):
self.reset(self._screen.reset) self.reset(self._screen.reset)
QtCore.QTimer.singleShot(30000, self.reconnect) QtCore.QTimer.singleShot(45000, self.reconnect)
def close(self): def close(self):
for friend in self._friends: for friend in self._friends:
@ -1100,7 +1100,8 @@ class Profile(contact.Contact, Singleton):
t = type(transfer) t = type(transfer)
if t is ReceiveAvatar: if t is ReceiveAvatar:
self.get_friend_by_number(friend_number).load_avatar() self.get_friend_by_number(friend_number).load_avatar()
self.set_active(None) if friend_number == self.get_active_number():
self.set_active(None)
elif t is ReceiveToBuffer or (t is SendFromBuffer and Settings.get_instance()['allow_inline']): # inline image elif t is ReceiveToBuffer or (t is SendFromBuffer and Settings.get_instance()['allow_inline']): # inline image
print('inline') print('inline')
inline = InlineImage(transfer.get_data()) inline = InlineImage(transfer.get_data())
@ -1115,6 +1116,7 @@ class Profile(contact.Contact, Singleton):
elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height())) elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height()))
self._messages.insertItem(count + i + 1, elem) self._messages.insertItem(count + i + 1, elem)
self._messages.setItemWidget(elem, item) self._messages.setItemWidget(elem, item)
self._messages.scrollToBottom()
elif t is not SendAvatar: elif t is not SendAvatar:
self.get_friend_by_number(friend_number).update_transfer_data(file_number, self.get_friend_by_number(friend_number).update_transfer_data(file_number,
TOX_FILE_TRANSFER_STATE['FINISHED']) TOX_FILE_TRANSFER_STATE['FINISHED'])

View File

@ -48,7 +48,7 @@ class SmileyLoader(util.Singleton):
print('Smiley pack {} was not loaded. Error: {}'.format(pack_name, ex)) print('Smiley pack {} was not loaded. Error: {}'.format(pack_name, ex))
def get_smileys_path(self): def get_smileys_path(self):
return util.curr_directory() + '/smileys/' + self._curr_pack + '/' return util.curr_directory() + '/smileys/' + self._curr_pack + '/' if self._curr_pack is not None else None
def get_packs_list(self): def get_packs_list(self):
d = util.curr_directory() + '/smileys/' d = util.curr_directory() + '/smileys/'

View File

@ -1,2 +1,2 @@
SOURCES = main.py profile.py menu.py list_items.py loginscreen.py mainscreen.py plugins/plugin_super_class.py callbacks.py widgets.py avwidgets.py mainscreen_widgets.py SOURCES = main.py profile.py menu.py list_items.py loginscreen.py mainscreen.py plugins/plugin_super_class.py callbacks.py widgets.py avwidgets.py mainscreen_widgets.py passwordscreen.py
TRANSLATIONS = translations/en_GB.ts translations/ru_RU.ts translations/fr_FR.ts TRANSLATIONS = translations/en_GB.ts translations/ru_RU.ts translations/fr_FR.ts

View File

@ -468,6 +468,44 @@ Version:</translation>
<translation>Restart Tox core</translation> <translation>Restart Tox core</translation>
</message> </message>
</context> </context>
<context>
<name>PasswordScreen</name>
<message>
<location filename="passwordscreen.py" line="136"/>
<source>Profile password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="139"/>
<source>Password (at least 8 symbols)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="142"/>
<source>Confirm password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="144"/>
<source>Set password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="163"/>
<source>Passwords do not match</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="149"/>
<source>There is no way to recover lost passwords</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="159"/>
<source>Password must be at least 8 symbols</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>PluginWindow</name> <name>PluginWindow</name>
<message> <message>
@ -945,6 +983,24 @@ Version:</translation>
<translation></translation> <translation></translation>
</message> </message>
</context> </context>
<context>
<name>pass</name>
<message>
<location filename="passwordscreen.py" line="64"/>
<source>Enter password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="65"/>
<source>Password:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="66"/>
<source>Incorrect password</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>privacySettings</name> <name>privacySettings</name>
<message> <message>

View File

@ -478,6 +478,44 @@ Version :</translation>
<translation>Relancer le noyau TOX</translation> <translation>Relancer le noyau TOX</translation>
</message> </message>
</context> </context>
<context>
<name>PasswordScreen</name>
<message>
<location filename="passwordscreen.py" line="136"/>
<source>Profile password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="139"/>
<source>Password (at least 8 symbols)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="142"/>
<source>Confirm password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="144"/>
<source>Set password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="163"/>
<source>Passwords do not match</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="149"/>
<source>There is no way to recover lost passwords</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="159"/>
<source>Password must be at least 8 symbols</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>PluginWindow</name> <name>PluginWindow</name>
<message> <message>
@ -960,6 +998,24 @@ Version :</translation>
<translation>Activer les sons de notifications</translation> <translation>Activer les sons de notifications</translation>
</message> </message>
</context> </context>
<context>
<name>pass</name>
<message>
<location filename="passwordscreen.py" line="64"/>
<source>Enter password</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="65"/>
<source>Password:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="passwordscreen.py" line="66"/>
<source>Incorrect password</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>privacySettings</name> <name>privacySettings</name>
<message> <message>

Binary file not shown.

View File

@ -476,6 +476,44 @@ Version: </source>
<translation>Перезапустить ядро TOX</translation> <translation>Перезапустить ядро TOX</translation>
</message> </message>
</context> </context>
<context>
<name>PasswordScreen</name>
<message>
<location filename="passwordscreen.py" line="136"/>
<source>Profile password</source>
<translation>Пароль профиля</translation>
</message>
<message>
<location filename="passwordscreen.py" line="139"/>
<source>Password (at least 8 symbols)</source>
<translation>Пароль (минимум 8 символов)</translation>
</message>
<message>
<location filename="passwordscreen.py" line="142"/>
<source>Confirm password</source>
<translation>Подтверждение пароля</translation>
</message>
<message>
<location filename="passwordscreen.py" line="144"/>
<source>Set password</source>
<translation>Изменить пароль</translation>
</message>
<message>
<location filename="passwordscreen.py" line="163"/>
<source>Passwords do not match</source>
<translation>Пароли не совпадают</translation>
</message>
<message>
<location filename="passwordscreen.py" line="149"/>
<source>There is no way to recover lost passwords</source>
<translation>Восстановление забытых паролей не поддерживается</translation>
</message>
<message>
<location filename="passwordscreen.py" line="159"/>
<source>Password must be at least 8 symbols</source>
<translation>Пароль должен быть длиной не менее 8 символов</translation>
</message>
</context>
<context> <context>
<name>PluginWindow</name> <name>PluginWindow</name>
<message> <message>
@ -994,6 +1032,24 @@ Version: </source>
</translation> </translation>
</message> </message>
</context> </context>
<context>
<name>pass</name>
<message>
<location filename="passwordscreen.py" line="64"/>
<source>Enter password</source>
<translation>Введите пароль</translation>
</message>
<message>
<location filename="passwordscreen.py" line="65"/>
<source>Password:</source>
<translation>Пароль</translation>
</message>
<message>
<location filename="passwordscreen.py" line="66"/>
<source>Incorrect password</source>
<translation>Неверный пароль</translation>
</message>
</context>
<context> <context>
<name>privacySettings</name> <name>privacySettings</name>
<message> <message>

View File

@ -2,7 +2,7 @@ import os
import time import time
import shutil import shutil
program_version = '0.2.4' program_version = '0.2.5'
def log(data): def log(data):
@ -31,7 +31,8 @@ def copy(src, dest):
def convert_time(t): def convert_time(t):
sec = int(t) - time.timezone offset = time.timezone - time.daylight * 3600
sec = int(t) - offset
m, s = divmod(sec, 60) m, s = divmod(sec, 60)
h, m = divmod(m, 60) h, m = divmod(m, 60)
d, h = divmod(h, 24) d, h = divmod(h, 24)