Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
337601f2a1 | |||
42e0ec005b | |||
fb1caa244a | |||
0fd75c5517 | |||
d81e3e781b | |||
43d9a41dae | |||
1caf7cd63c | |||
14816588f1 | |||
47b710acdd | |||
3668088f3e | |||
9f702afcb8 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -15,9 +15,11 @@ toxygen/libs
|
||||
toxygen/build
|
||||
toxygen/dist
|
||||
*.spec
|
||||
dist/
|
||||
dist
|
||||
toxygen/avatars
|
||||
toxygen/__pycache__
|
||||
/*.egg-info
|
||||
/*.egg
|
||||
html
|
||||
Toxygen.egg-info
|
||||
|
||||
|
13
README.md
13
README.md
@ -1,21 +1,20 @@
|
||||
# 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.
|
||||
|
||||
[](https://github.com/toxygen-project/toxygen/releases/latest)
|
||||
[](https://github.com/toxygen-project/toxygen/stargazers)
|
||||
[](https://github.com/toxygen-project/toxygen/issues)
|
||||
[](https://raw.githubusercontent.com/toxygen-project/toxygen/master/LICENSE.md)
|
||||
[](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)
|
||||
|
||||
### Supported OS:
|
||||
|
||||
- Windows
|
||||
- Linux
|
||||
- OS X
|
||||

|
||||
|
||||
### Features
|
||||
### Features:
|
||||
|
||||
- [x] 1v1 messages
|
||||
- [x] File transfers
|
||||
@ -61,3 +60,7 @@ Toxygen is cross-platform [Tox](https://tox.chat/) client written in pure Python
|
||||
|
||||
### Docs
|
||||
[Check /docs/ for more info](/docs/)
|
||||
|
||||
Also visit [pythonhosted.org/Toxygen/](http://pythonhosted.org/Toxygen/)
|
||||
|
||||
[Wiki](https://wiki.tox.chat/clients/toxygen)
|
||||
|
@ -27,12 +27,14 @@ Run app using ``toxygen`` command.
|
||||
2. Install PortAudio:
|
||||
``brew install portaudio``
|
||||
3. Install toxygen:
|
||||
``pip3 install toxygen``
|
||||
``pip3.4 install toxygen``
|
||||
4. Run toxygen using ``toxygen`` command.
|
||||
|
||||
## 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)
|
||||
|
||||
|
BIN
docs/os.png
Executable file
BIN
docs/os.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@ -340,3 +340,8 @@ class ReceiveAvatar(ReceiveTransfer):
|
||||
chdir(dirname(avatar_path))
|
||||
remove(avatar_path)
|
||||
rename(self._path, avatar_path)
|
||||
self.finished(True)
|
||||
|
||||
def finished(self, emit=False):
|
||||
if emit:
|
||||
super().finished()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# coding=utf-8
|
||||
from sqlite3 import connect
|
||||
import settings
|
||||
from os import chdir
|
||||
@ -8,6 +7,8 @@ from toxencryptsave import ToxEncryptSave
|
||||
|
||||
PAGE_SIZE = 42
|
||||
|
||||
TIMEOUT = 11
|
||||
|
||||
MESSAGE_OWNER = {
|
||||
'ME': 0,
|
||||
'FRIEND': 1,
|
||||
@ -32,7 +33,7 @@ class History:
|
||||
fout.write(data)
|
||||
except:
|
||||
os.remove(path)
|
||||
db = connect(name + '.hstr')
|
||||
db = connect(name + '.hstr', timeout=TIMEOUT)
|
||||
cursor = db.cursor()
|
||||
cursor.execute('CREATE TABLE IF NOT EXISTS friends('
|
||||
' tox_id TEXT PRIMARY KEY'
|
||||
@ -62,7 +63,7 @@ class History:
|
||||
|
||||
def add_friend_to_db(self, tox_id):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
db = connect(self._name + '.hstr')
|
||||
db = connect(self._name + '.hstr', timeout=TIMEOUT)
|
||||
try:
|
||||
cursor = db.cursor()
|
||||
cursor.execute('INSERT INTO friends VALUES (?);', (tox_id, ))
|
||||
@ -82,7 +83,7 @@ class History:
|
||||
|
||||
def delete_friend_from_db(self, tox_id):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
db = connect(self._name + '.hstr')
|
||||
db = connect(self._name + '.hstr', timeout=TIMEOUT)
|
||||
try:
|
||||
cursor = db.cursor()
|
||||
cursor.execute('DELETE FROM friends WHERE tox_id=?;', (tox_id, ))
|
||||
@ -96,7 +97,7 @@ class History:
|
||||
|
||||
def friend_exists_in_db(self, tox_id):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
db = connect(self._name + '.hstr')
|
||||
db = connect(self._name + '.hstr', timeout=TIMEOUT)
|
||||
cursor = db.cursor()
|
||||
cursor.execute('SELECT 0 FROM friends WHERE tox_id=?', (tox_id, ))
|
||||
result = cursor.fetchone()
|
||||
@ -105,7 +106,7 @@ class History:
|
||||
|
||||
def save_messages_to_db(self, tox_id, messages_iter):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
db = connect(self._name + '.hstr')
|
||||
db = connect(self._name + '.hstr', timeout=TIMEOUT)
|
||||
try:
|
||||
cursor = db.cursor()
|
||||
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):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
db = connect(self._name + '.hstr')
|
||||
db = connect(self._name + '.hstr', timeout=TIMEOUT)
|
||||
try:
|
||||
cursor = db.cursor()
|
||||
cursor.execute('UPDATE id' + tox_id + ' SET owner = 0 '
|
||||
@ -134,7 +135,7 @@ class History:
|
||||
|
||||
def delete_message(self, tox_id, time):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
db = connect(self._name + '.hstr')
|
||||
db = connect(self._name + '.hstr', timeout=TIMEOUT)
|
||||
try:
|
||||
cursor = db.cursor()
|
||||
cursor.execute('DELETE FROM id' + tox_id + ' WHERE unix_time = ' + str(time) + ';')
|
||||
@ -147,7 +148,7 @@ class History:
|
||||
|
||||
def delete_messages(self, tox_id):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
db = connect(self._name + '.hstr')
|
||||
db = connect(self._name + '.hstr', timeout=TIMEOUT)
|
||||
try:
|
||||
cursor = db.cursor()
|
||||
cursor.execute('DELETE FROM id' + tox_id + ';')
|
||||
@ -162,9 +163,10 @@ class History:
|
||||
return History.MessageGetter(self._name, tox_id)
|
||||
|
||||
class MessageGetter:
|
||||
|
||||
def __init__(self, name, tox_id):
|
||||
chdir(settings.ProfileHelper.get_path())
|
||||
self._db = connect(name + '.hstr')
|
||||
self._db = connect(name + '.hstr', timeout=TIMEOUT)
|
||||
self._cursor = self._db.cursor()
|
||||
self._cursor.execute('SELECT message, owner, unix_time, message_type FROM id' + tox_id +
|
||||
' ORDER BY unix_time DESC;')
|
||||
|
@ -25,7 +25,9 @@ class MessageEdit(QtGui.QTextBrowser):
|
||||
self.setOpenExternalLinks(True)
|
||||
self.setAcceptRichText(True)
|
||||
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; }')
|
||||
text = self.decoratedText(text)
|
||||
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):
|
||||
QtGui.QWidget.__init__(self, parent)
|
||||
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)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(settings.Settings.get_instance()['font'])
|
||||
@ -137,7 +139,7 @@ class MessageItem(QtGui.QWidget):
|
||||
self.name.setText(user)
|
||||
|
||||
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.setBold(False)
|
||||
self.time.setFont(font)
|
||||
@ -151,12 +153,12 @@ class MessageItem(QtGui.QWidget):
|
||||
self.time.setText(convert_time(time))
|
||||
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']:
|
||||
self.name.setStyleSheet("QLabel { color: #5CB3FF; }")
|
||||
self.message.setAlignment(QtCore.Qt.AlignCenter)
|
||||
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())
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
@ -295,7 +297,7 @@ class FileTransferItem(QtGui.QListWidget):
|
||||
self.state = state
|
||||
|
||||
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)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily(settings.Settings.get_instance()['font'])
|
||||
@ -305,14 +307,14 @@ class FileTransferItem(QtGui.QListWidget):
|
||||
self.name.setText(user)
|
||||
|
||||
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.setBold(False)
|
||||
self.time.setFont(font)
|
||||
self.time.setText(convert_time(time))
|
||||
|
||||
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')
|
||||
icon = QtGui.QIcon(pixmap)
|
||||
self.cancel.setIcon(icon)
|
||||
@ -360,7 +362,7 @@ class FileTransferItem(QtGui.QListWidget):
|
||||
self.file_name.setToolTip(file_name)
|
||||
self.saved_name = file_name
|
||||
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)
|
||||
self.time_left.setFont(font)
|
||||
self.time_left.setVisible(state == TOX_FILE_TRANSFER_STATE['RUNNING'])
|
||||
|
@ -127,7 +127,7 @@ class MainWindow(QtGui.QMainWindow, Singleton):
|
||||
self.messageEdit.setGeometry(QtCore.QRect(0, 3, 450, 55))
|
||||
self.messageEdit.setObjectName("messageEdit")
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setPointSize(11)
|
||||
font.setFamily(settings.Settings.get_instance()['font'])
|
||||
self.messageEdit.setFont(font)
|
||||
|
||||
@ -260,7 +260,7 @@ class MainWindow(QtGui.QMainWindow, Singleton):
|
||||
self.messages.setSpacing(1)
|
||||
self.messages.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
|
||||
self.messages.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||
# self.messages.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
self.messages.focusOutEvent = lambda event: self.messages.clearSelection()
|
||||
|
||||
def load(pos):
|
||||
if not pos:
|
||||
|
@ -714,10 +714,10 @@ class InterfaceSettings(CenteredWidget):
|
||||
msgBox.exec_()
|
||||
|
||||
def select_color(self):
|
||||
col = QtGui.QColorDialog.getColor()
|
||||
settings = Settings.get_instance()
|
||||
col = QtGui.QColorDialog.getColor(settings['unread_color'])
|
||||
|
||||
if col.isValid():
|
||||
settings = Settings.get_instance()
|
||||
name = col.name()
|
||||
settings['unread_color'] = name
|
||||
settings.save()
|
||||
|
@ -237,7 +237,7 @@ class Profile(contact.Contact, Singleton):
|
||||
self.update_filtration()
|
||||
except Exception as ex: # no friend found. ignore
|
||||
log('Friend value: ' + str(value))
|
||||
log('Error: ' + str(ex))
|
||||
log('Error in set active: ' + str(ex))
|
||||
raise
|
||||
|
||||
active_friend = property(get_active, set_active)
|
||||
@ -313,7 +313,7 @@ class Profile(contact.Contact, Singleton):
|
||||
ft = self._file_transfers[(friend_num, file_num)]
|
||||
if type(ft) is SendTransfer:
|
||||
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.cancel_transfer(friend_num, file_num, True)
|
||||
|
||||
@ -838,7 +838,7 @@ class Profile(contact.Contact, Singleton):
|
||||
def reconnect(self):
|
||||
if self.status is None or all(list(map(lambda x: x.status is None, self._friends))):
|
||||
self.reset(self._screen.reset)
|
||||
QtCore.QTimer.singleShot(30000, self.reconnect)
|
||||
QtCore.QTimer.singleShot(45000, self.reconnect)
|
||||
|
||||
def close(self):
|
||||
for friend in self._friends:
|
||||
@ -1100,7 +1100,8 @@ class Profile(contact.Contact, Singleton):
|
||||
t = type(transfer)
|
||||
if t is ReceiveAvatar:
|
||||
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
|
||||
print('inline')
|
||||
inline = InlineImage(transfer.get_data())
|
||||
@ -1115,6 +1116,7 @@ class Profile(contact.Contact, Singleton):
|
||||
elem.setSizeHint(QtCore.QSize(self._messages.width(), item.height()))
|
||||
self._messages.insertItem(count + i + 1, elem)
|
||||
self._messages.setItemWidget(elem, item)
|
||||
self._messages.scrollToBottom()
|
||||
elif t is not SendAvatar:
|
||||
self.get_friend_by_number(friend_number).update_transfer_data(file_number,
|
||||
TOX_FILE_TRANSFER_STATE['FINISHED'])
|
||||
|
@ -48,7 +48,7 @@ class SmileyLoader(util.Singleton):
|
||||
print('Smiley pack {} was not loaded. Error: {}'.format(pack_name, ex))
|
||||
|
||||
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):
|
||||
d = util.curr_directory() + '/smileys/'
|
||||
|
@ -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
|
||||
|
@ -468,6 +468,44 @@ Version:</translation>
|
||||
<translation>Restart Tox core</translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>PluginWindow</name>
|
||||
<message>
|
||||
@ -945,6 +983,24 @@ Version:</translation>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>privacySettings</name>
|
||||
<message>
|
||||
|
@ -478,6 +478,44 @@ Version :</translation>
|
||||
<translation>Relancer le noyau TOX</translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>PluginWindow</name>
|
||||
<message>
|
||||
@ -960,6 +998,24 @@ Version :</translation>
|
||||
<translation>Activer les sons de notifications</translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>privacySettings</name>
|
||||
<message>
|
||||
|
Binary file not shown.
@ -476,6 +476,44 @@ Version: </source>
|
||||
<translation>Перезапустить ядро TOX</translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>PluginWindow</name>
|
||||
<message>
|
||||
@ -994,6 +1032,24 @@ Version: </source>
|
||||
</translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>privacySettings</name>
|
||||
<message>
|
||||
|
@ -2,7 +2,7 @@ import os
|
||||
import time
|
||||
import shutil
|
||||
|
||||
program_version = '0.2.4'
|
||||
program_version = '0.2.5'
|
||||
|
||||
|
||||
def log(data):
|
||||
@ -31,7 +31,8 @@ def copy(src, dest):
|
||||
|
||||
|
||||
def convert_time(t):
|
||||
sec = int(t) - time.timezone
|
||||
offset = time.timezone - time.daylight * 3600
|
||||
sec = int(t) - offset
|
||||
m, s = divmod(sec, 60)
|
||||
h, m = divmod(m, 60)
|
||||
d, h = divmod(h, 24)
|
||||
|
Reference in New Issue
Block a user