This commit is contained in:
emdee 2022-10-08 02:46:23 +00:00
parent 9e037f13c0
commit be6eb0e2a9
18 changed files with 135 additions and 71 deletions

25
ToDo.md
View file

@ -16,24 +16,29 @@ The code is in there but it's not working.
I may have broken it trying to wire up the ability to I may have broken it trying to wire up the ability to
set the audio device from the command line. set the audio device from the command line.
## Group peer_id ## Groups
There has been a change of API on a field named group.peer_id 1. peer_id There has been a change of API on a field named
The code is broken in places because I have not seen the path ```group.peer_id``` The code is broken in places because I have not
to change from the old API ro the new one. seen the path to change from the old API ro the new one.
2. There is no way to delete a group in the UI
3. Distinguish between Frieds, Groups and Whispers in the UI.
## Plugin system ## Plugin system
Needs better documentation and checking. 1. Needs better documentation and checking.
There's something broken in the way some of them plug into Qt menus.
Should the plugins be in toxygen or a separate repo? 2. There's something broken in the way some of them plug into Qt menus.
3. Should the plugins be in toxygen or a separate repo?
## check toxygen_wrapper ## check toxygen_wrapper
I've broken out toxygen_wrapper to be standalone, 1. I've broken out toxygen_wrapper to be standalone,
https://git.plastiras.org/emdee/toxygen_wrapper https://git.plastiras.org/emdee/toxygen_wrapper but the tox.py
but the tox.py needs each call double checking. needs each call double checking.

View file

@ -162,6 +162,7 @@ class App:
LOG.info("Starting toxygen version " +version) LOG.info("Starting toxygen version " +version)
self._version = version self._version = version
self._tox = None
self._app = self._settings = self._profile_manager = None self._app = self._settings = self._profile_manager = None
self._plugin_loader = self._messenger = None self._plugin_loader = self._messenger = None
self._tox = self._ms = self._init = self._main_loop = self._av_loop = None self._tox = self._ms = self._init = self._main_loop = self._av_loop = None
@ -777,6 +778,7 @@ class App:
retval = tox_factory(data=data, settings=settings_, retval = tox_factory(data=data, settings=settings_,
args=self._args, app=self) args=self._args, app=self)
LOG.debug("_create_tox succeeded") LOG.debug("_create_tox succeeded")
self._tox = retval
return retval return retval
def _force_exit(self, retval=0): def _force_exit(self, retval=0):

View file

@ -254,10 +254,14 @@ class ContactsManager(ToxSave):
group = self.get_group_by_number(group_number) group = self.get_group_by_number(group_number)
peer = group.get_peer_by_id(peer_id) peer = group.get_peer_by_id(peer_id)
if peer: # broken if peer: # broken
if hasattr(peer, 'public_key'):
LOG.error(f'no peer public_key ' + repr(dir(peer)))
else:
if not self.check_if_contact_exists(peer.public_key): if not self.check_if_contact_exists(peer.public_key):
self.add_group_peer(group, peer) self.add_group_peer(group, peer)
return self.get_contact_by_tox_id(peer.public_key) return self.get_contact_by_tox_id(peer.public_key)
else:
LOG.warn(f'no peer group_number={group_number}')
def check_if_contact_exists(self, tox_id): def check_if_contact_exists(self, tox_id):
return any(filter(lambda c: c.tox_id == tox_id, self._contacts)) return any(filter(lambda c: c.tox_id == tox_id, self._contacts))

View file

@ -7,6 +7,9 @@ from groups.group_invite import GroupInvite
import wrapper.toxcore_enums_and_consts as constants import wrapper.toxcore_enums_and_consts as constants
from wrapper.toxcore_enums_and_consts import * from wrapper.toxcore_enums_and_consts import *
global LOG
import logging
LOG = logging.getLogger('app.'+'gs')
class GroupsService(tox_save.ToxSave): class GroupsService(tox_save.ToxSave):
@ -19,6 +22,8 @@ class GroupsService(tox_save.ToxSave):
self._widgets_factory_provider = widgets_factory_provider self._widgets_factory_provider = widgets_factory_provider
self._group_invites = [] self._group_invites = []
self._screen = None self._screen = None
# maybe just use self
self._tox = tox
def set_tox(self, tox): def set_tox(self, tox):
super().set_tox(tox) super().set_tox(tox)
@ -30,7 +35,11 @@ class GroupsService(tox_save.ToxSave):
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
def create_new_gc(self, name, privacy_state, nick, status): def create_new_gc(self, name, privacy_state, nick, status):
try:
group_number = self._tox.group_new(privacy_state, name, nick, status) group_number = self._tox.group_new(privacy_state, name, nick, status)
except Exception as e:
LOG.error(f"create_new_gc {e}")
return
if group_number == -1: if group_number == -1:
return return
@ -48,6 +57,7 @@ class GroupsService(tox_save.ToxSave):
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
def leave_group(self, group_number): def leave_group(self, group_number):
if type(group_number) == int:
self._tox.group_leave(group_number) self._tox.group_leave(group_number)
self._contacts_manager.delete_group(group_number) self._contacts_manager.delete_group(group_number)
@ -246,7 +256,13 @@ class GroupsService(tox_save.ToxSave):
self._group_invites.remove(invite) self._group_invites.remove(invite)
def _join_gc_via_invite(self, invite_data, friend_number, nick, status, password): def _join_gc_via_invite(self, invite_data, friend_number, nick, status, password):
if nick is None: nick = ''
if invite_data is None: invite_data = ''
try:
group_number = self._tox.group_invite_accept(invite_data, friend_number, nick, status, password) group_number = self._tox.group_invite_accept(invite_data, friend_number, nick, status, password)
except Exception as e:
LOG.error(f"_join_gc_via_invite {e}")
else:
self._add_new_group_by_number(group_number) self._add_new_group_by_number(group_number)
def _update_invites_button_state(self): def _update_invites_button_state(self):

View file

@ -387,6 +387,7 @@ def main(lArgs):
toxygen = app.App(__version__, oArgs) toxygen = app.App(__version__, oArgs)
global oAPP global oAPP
oAPP = toxygen oAPP = toxygen
__builtins__['app'] = toxygen
i = toxygen.iMain() i = toxygen.iMain()
return i return i

View file

@ -27,6 +27,7 @@ class GroupInvitesScreen(CenteredWidget):
self._groups_service = groups_service self._groups_service = groups_service
self._profile = profile self._profile = profile
self._contacts_provider = contacts_provider self._contacts_provider = contacts_provider
self._tox = self._groups_service._tox
uic.loadUi(util.get_views_path('group_invites_screen'), self) uic.loadUi(util.get_views_path('group_invites_screen'), self)
@ -68,6 +69,8 @@ class GroupInvitesScreen(CenteredWidget):
password = self.passwordLineEdit.text() password = self.passwordLineEdit.text()
status = self.statusComboBox.currentIndex() status = self.statusComboBox.currentIndex()
if not nick:
nick = self._tox.self_get_name()
selected_invites = self._get_selected_invites() selected_invites = self._get_selected_invites()
for invite in selected_invites: for invite in selected_invites:
self._groups_service.accept_group_invite(invite, nick, status, password) self._groups_service.accept_group_invite(invite, nick, status, password)
@ -90,7 +93,7 @@ class GroupInvitesScreen(CenteredWidget):
for index in range(items_count): for index in range(items_count):
list_item = self.invitesListWidget.item(index) list_item = self.invitesListWidget.item(index)
item_widget = self.invitesListWidget.itemWidget(list_item) item_widget = self.invitesListWidget.itemWidget(list_item)
if item_widget.is_selected(): if item_widget and item_widget.is_selected():
selected.append(all_invites[index]) selected.append(all_invites[index])
return selected return selected

View file

@ -3,7 +3,6 @@ from PyQt5 import uic
import utils.util as util import utils.util as util
import utils.ui as util_ui import utils.ui as util_ui
class GroupManagementScreen(CenteredWidget): class GroupManagementScreen(CenteredWidget):
def __init__(self, groups_service, group): def __init__(self, groups_service, group):
@ -21,6 +20,7 @@ class GroupManagementScreen(CenteredWidget):
self.privacyStateComboBox.setCurrentIndex(1 if self._group.is_private else 0) self.privacyStateComboBox.setCurrentIndex(1 if self._group.is_private else 0)
self.peersLimitSpinBox.setValue(self._group.peers_limit) self.peersLimitSpinBox.setValue(self._group.peers_limit)
self.deletePushButton.clicked.connect(self._delete)
self.savePushButton.clicked.connect(self._save) self.savePushButton.clicked.connect(self._save)
def _retranslate_ui(self): def _retranslate_ui(self):
@ -28,12 +28,21 @@ class GroupManagementScreen(CenteredWidget):
self.passwordLabel.setText(util_ui.tr('Password:')) self.passwordLabel.setText(util_ui.tr('Password:'))
self.peerLimitLabel.setText(util_ui.tr('Peer limit:')) self.peerLimitLabel.setText(util_ui.tr('Peer limit:'))
self.privacyStateLabel.setText(util_ui.tr('Privacy state:')) self.privacyStateLabel.setText(util_ui.tr('Privacy state:'))
self.deletePushButton.setText(util_ui.tr('Delete'))
self.savePushButton.setText(util_ui.tr('Save')) self.savePushButton.setText(util_ui.tr('Save'))
self.privacyStateComboBox.clear() self.privacyStateComboBox.clear()
self.privacyStateComboBox.addItem(util_ui.tr('Public')) self.privacyStateComboBox.addItem(util_ui.tr('Public'))
self.privacyStateComboBox.addItem(util_ui.tr('Private')) self.privacyStateComboBox.addItem(util_ui.tr('Private'))
def _delete(self):
self._groups_service.leave_group(self._group.number)
self.close()
def _disconnect(self):
self._groups_service.disconnect_from_group(self._group.number)
self.close()
def _save(self): def _save(self):
password = self.passwordLineEdit.text() password = self.passwordLineEdit.text()
privacy_state = self.privacyStateComboBox.currentIndex() privacy_state = self.privacyStateComboBox.currentIndex()

View file

@ -76,13 +76,16 @@ class MainWindow(QtWidgets.QMainWindow):
self._contacts_manager = None self._contacts_manager = None
self._tray = tray self._tray = tray
self._app = app self._app = app
self._tox = app._tox
self._widget_factory = None self._widget_factory = None
self._modal_window = None self._modal_window = None
self._plugins_loader = None self._plugins_loader = None
self.setAcceptDrops(True) self.setAcceptDrops(True)
self._saved = False self._saved = False
self._smiley_window = None self._smiley_window = None
self._profile = self._toxes = self._messenger = None self._profile = None
self._toxes = None
self._messenger = None
self._file_transfer_handler = self._history_loader = self._groups_service = self._calls_manager = None self._file_transfer_handler = self._history_loader = self._groups_service = self._calls_manager = None
self._should_show_group_peers_list = False self._should_show_group_peers_list = False
self.initUI() self.initUI()
@ -91,6 +94,7 @@ class MainWindow(QtWidgets.QMainWindow):
# take a rough guess of 2/3 the default width at the default font # take a rough guess of 2/3 the default width at the default font
iMAX = settings['width'] * 2/3 / settings['message_font_size'] iMAX = settings['width'] * 2/3 / settings['message_font_size']
self._me = LogDialog(self, app) self._me = LogDialog(self, app)
self._pe = None
def set_dependencies(self, widget_factory, tray, contacts_manager, messenger, profile, plugins_loader, def set_dependencies(self, widget_factory, tray, contacts_manager, messenger, profile, plugins_loader,
file_transfer_handler, history_loader, calls_manager, groups_service, toxes, app): file_transfer_handler, history_loader, calls_manager, groups_service, toxes, app):
@ -159,6 +163,8 @@ class MainWindow(QtWidgets.QMainWindow):
self.actionLog_console = QtWidgets.QAction(window) self.actionLog_console = QtWidgets.QAction(window)
self.actionLog_console.setObjectName("actionLog_console") self.actionLog_console.setObjectName("actionLog_console")
self.actionPython_console = QtWidgets.QAction(window)
self.actionPython_console.setObjectName("actionLog_console")
self.updateSettings = QtWidgets.QAction(window) self.updateSettings = QtWidgets.QAction(window)
self.actionSettings = QtWidgets.QAction(window) self.actionSettings = QtWidgets.QAction(window)
self.actionSettings.setObjectName("actionSettings") self.actionSettings.setObjectName("actionSettings")
@ -196,6 +202,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.menuPlugins.addAction(self.reloadPlugins) self.menuPlugins.addAction(self.reloadPlugins)
self.menuPlugins.addAction(self.reloadToxchat) self.menuPlugins.addAction(self.reloadToxchat)
self.menuPlugins.addAction(self.actionLog_console) self.menuPlugins.addAction(self.actionLog_console)
self.menuPlugins.addAction(self.actionPython_console)
self.menuAbout.addAction(self.actionAbout_program) self.menuAbout.addAction(self.actionAbout_program)
@ -211,6 +218,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.actionQuit_program.triggered.connect(self.quit_program) self.actionQuit_program.triggered.connect(self.quit_program)
self.actionAbout_program.triggered.connect(self.about_program) self.actionAbout_program.triggered.connect(self.about_program)
self.actionLog_console.triggered.connect(self.log_console) self.actionLog_console.triggered.connect(self.log_console)
self.actionPython_console.triggered.connect(self.python_console)
self.actionNetwork.triggered.connect(self.network_settings) self.actionNetwork.triggered.connect(self.network_settings)
self.actionAdd_friend.triggered.connect(self.add_contact_triggered) self.actionAdd_friend.triggered.connect(self.add_contact_triggered)
self.createGC.triggered.connect(self.create_gc) self.createGC.triggered.connect(self.create_gc)
@ -264,6 +272,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.actionNetwork.setText(util_ui.tr("Network")) self.actionNetwork.setText(util_ui.tr("Network"))
self.actionAbout_program.setText(util_ui.tr("About program")) self.actionAbout_program.setText(util_ui.tr("About program"))
self.actionLog_console.setText(util_ui.tr("Console Log")) self.actionLog_console.setText(util_ui.tr("Console Log"))
self.actionPython_console.setText(util_ui.tr("Python Console"))
self.actionTest_tox.setText(util_ui.tr("Bootstrap")) self.actionTest_tox.setText(util_ui.tr("Bootstrap"))
self.actionTest_socks.setText(util_ui.tr("Test program")) self.actionTest_socks.setText(util_ui.tr("Test program"))
self.actionQuit_program.setText(util_ui.tr("Quit program")) self.actionQuit_program.setText(util_ui.tr("Quit program"))
@ -554,6 +563,18 @@ class MainWindow(QtWidgets.QMainWindow):
def log_console(self): def log_console(self):
self._me.show() self._me.show()
def python_console(self):
try:
if not self._pe:
from pyqtconsole.console import PythonConsole
self._pe = PythonConsole(sFont="Courier New", bBold=True)
self._pe.show()
self._pe.eval_queued()
# self._pe.eval_in_thread()
except Exception as e:
LOG.debug(e)
self._me.show()
def about_program(self): def about_program(self):
# TODO: replace with window # TODO: replace with window
text = util_ui.tr('Toxygen is Tox client written in Python.\nVersion: ') text = util_ui.tr('Toxygen is Tox client written in Python.\nVersion: ')

View file

@ -40,11 +40,11 @@ class LibToxCore:
class LibToxAV: class LibToxAV:
def __init__(self): def __init__(self):
platform = util.get_platform() platform = sys.platform
if platform == 'Windows': if platform == 'win32':
# on Windows av api is in libtox.dll # on Windows av api is in libtox.dll
self._libtoxav = CDLL(os.path.join(sLIBS_DIR, 'libtox.dll')) self._libtoxav = CDLL(os.path.join(sLIBS_DIR, 'libtox.dll'))
elif platform == 'Darwin': elif platform == 'darwin':
self._libtoxav = CDLL('libtoxcore.dylib') self._libtoxav = CDLL('libtoxcore.dylib')
else: else:
libFile = os.path.join(sLIBS_DIR, 'libtoxav.so') libFile = os.path.join(sLIBS_DIR, 'libtoxav.so')

View file

@ -776,7 +776,7 @@ class Tox:
if friend_list is None: if friend_list is None:
friend_list = create_string_buffer(sizeof(c_uint32) * friend_list_size) friend_list = create_string_buffer(sizeof(c_uint32) * friend_list_size)
friend_list = POINTER(c_uint32)(friend_list) friend_list = POINTER(c_uint32)(friend_list)
LOG_DEBUG(f"tox_self_get_friend_list") LOG_TRACE(f"tox_self_get_friend_list")
Tox.libtoxcore.tox_self_get_friend_list(self._tox_pointer, friend_list) Tox.libtoxcore.tox_self_get_friend_list(self._tox_pointer, friend_list)
return friend_list[0:friend_list_size] return friend_list[0:friend_list_size]
@ -2387,7 +2387,6 @@ class Tox:
error = c_int() error = c_int()
buff = create_string_buffer(TOX_GROUP_CHAT_ID_SIZE) buff = create_string_buffer(TOX_GROUP_CHAT_ID_SIZE)
LOG_DEBUG(f"tox_group_get_chat_id")
result = Tox.libtoxcore.tox_group_get_chat_id(self._tox_pointer, result = Tox.libtoxcore.tox_group_get_chat_id(self._tox_pointer,
group_number, group_number,
buff, byref(error)) buff, byref(error))
@ -2575,23 +2574,27 @@ class Tox:
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
def group_send_custom_packet(self, group_number, lossless, data): def group_send_custom_packet(self, group_number, lossless, data):
""" """Send a custom packet to the group.
Send a custom packet to the group.
If lossless is true the packet will be lossless. Lossless packet behaviour is comparable If lossless is true the packet will be lossless. Lossless
to TCP (reliability, arrive in order) but with packets instead of a stream. packet behaviour is comparable to TCP (reliability, arrive in
order) but with packets instead of a stream.
If lossless is false, the packet will be lossy. Lossy packets behave like UDP packets, If lossless is false, the packet will be lossy. Lossy packets
meaning they might never reach the other side or might arrive more than once (if someone behave like UDP packets, meaning they might never reach the
is messing with the connection) or might arrive in the wrong order. other side or might arrive more than once (if someone is
messing with the connection) or might arrive in the wrong
order.
Unless latency is an issue or message reliability is not important, it is recommended that you use Unless latency is an issue or message reliability is not
lossless custom packets. important, it is recommended that you use lossless custom
packets.
:param group_number: The group number of the group the message is intended for. :param group_number: The group number of the group the message is intended for.
:param lossless: True if the packet should be lossless. :param lossless: True if the packet should be lossless.
:param data A byte array containing the packet data. :param data A byte array containing the packet data.
:return True on success. :return True on success.
""" """
error = c_int() error = c_int()