trying to fix group addition

This commit is contained in:
emdee 2022-10-08 17:59:45 +00:00
parent fb520357e9
commit 633b8f9561
14 changed files with 271 additions and 135 deletions

1
.gitignore vendored
View file

@ -26,4 +26,3 @@ Toxygen.egg-info
.cache .cache
*.db *.db
.pylint.sh

View file

@ -9,11 +9,9 @@ from time import sleep
from gevent import monkey; monkey.patch_all(); del monkey # noqa from gevent import monkey; monkey.patch_all(); del monkey # noqa
import gevent import gevent
import wrapper_tests.support_testing as ts from PyQt5 import QtWidgets, QtGui, QtCore
from wrapper_tests.tests_wrapper import bootstrap_iNodeInfo from qtpy.QtCore import QTimer
from user_data import settings from qtpy.QtWidgets import QApplication
IDLE_PERIOD = 0.10
try: try:
import coloredlogs import coloredlogs
@ -23,9 +21,66 @@ try:
except ImportError as e: except ImportError as e:
coloredlogs = False coloredlogs = False
try:
# https://github.com/pyqtconsole/pyqtconsole
from pyqtconsole.console import PythonConsole
except Exception as e:
PythonConsole = None
try:
import qdarkstylexxx
except ImportError:
qdarkstyle = None
from middleware import threads
import middleware.callbacks as callbacks
import updater.updater as updater
from middleware.tox_factory import tox_factory
import wrapper.toxencryptsave as tox_encrypt_save
import user_data.toxes
from user_data import settings
from user_data.settings import get_user_config_path, merge_args_into_settings
from user_data.settings import Settings
from user_data.profile_manager import ProfileManager
from plugin_support.plugin_support import PluginLoader
import ui.password_screen as password_screen
from ui.login_screen import LoginScreen
from ui.main_screen import MainWindow
from ui import tray
import utils.ui as util_ui
import utils.util as util
from av.calls_manager import CallsManager
from common.provider import Provider
from contacts.contact_provider import ContactProvider
from contacts.contacts_manager import ContactsManager
from contacts.friend_factory import FriendFactory
from contacts.group_factory import GroupFactory
from contacts.group_peer_factory import GroupPeerFactory
from contacts.profile import Profile
from file_transfers.file_transfers_handler import FileTransfersHandler
from file_transfers.file_transfers_messages_service import FileTransfersMessagesService
from groups.groups_service import GroupsService
from history.database import Database
from history.history import History
from messenger.messenger import Messenger
from network.tox_dns import ToxDns
from smileys.smileys import SmileyLoader
from ui.create_profile_screen import CreateProfileScreen
from ui.items_factories import MessagesItemsFactory, ContactItemsFactory
from ui.widgets_factory import WidgetsFactory
from user_data.backup_service import BackupService
import styles.style # TODO: dynamic loading
import wrapper_tests.support_testing as ts
from wrapper_tests.tests_wrapper import bootstrap_iNodeInfo
global LOG global LOG
import logging import logging
LOG = logging.getLogger('app') LOG = logging.getLogger('app')
IDLE_PERIOD = 0.10
def setup_logging(oArgs): def setup_logging(oArgs):
global LOG global LOG
@ -68,57 +123,6 @@ logging.getLogger('PyQt5.uic').setLevel(logging.ERROR)
logging.getLogger('PyQt5.uic.uiparser').setLevel(logging.ERROR) logging.getLogger('PyQt5.uic.uiparser').setLevel(logging.ERROR)
logging.getLogger('PyQt5.uic.properties').setLevel(logging.ERROR) logging.getLogger('PyQt5.uic.properties').setLevel(logging.ERROR)
from PyQt5 import QtWidgets, QtGui, QtCore
from qtpy.QtCore import QTimer
from qtpy.QtWidgets import QApplication
try:
import qdarkstylexxx
except ImportError:
qdarkstyle = None
from middleware import threads
import middleware.callbacks as callbacks
import ui.password_screen as password_screen
import updater.updater as updater
from middleware.tox_factory import tox_factory
import wrapper.toxencryptsave as tox_encrypt_save
import user_data.toxes
from user_data import settings
from user_data.settings import get_user_config_path, merge_args_into_settings
from user_data.settings import Settings
from ui.login_screen import LoginScreen
from user_data.profile_manager import ProfileManager
from plugin_support.plugin_support import PluginLoader
from ui.main_screen import MainWindow
from ui import tray
import utils.ui as util_ui
import utils.util as util
from contacts.profile import Profile
from file_transfers.file_transfers_handler import FileTransfersHandler
from contacts.contact_provider import ContactProvider
from contacts.friend_factory import FriendFactory
from contacts.group_factory import GroupFactory
from contacts.contacts_manager import ContactsManager
from av.calls_manager import CallsManager
from history.database import Database
from ui.widgets_factory import WidgetsFactory
from smileys.smileys import SmileyLoader
from ui.items_factories import MessagesItemsFactory, ContactItemsFactory
from messenger.messenger import Messenger
from network.tox_dns import ToxDns
from history.history import History
from file_transfers.file_transfers_messages_service import FileTransfersMessagesService
from groups.groups_service import GroupsService
from ui.create_profile_screen import CreateProfileScreen
from common.provider import Provider
from contacts.group_peer_factory import GroupPeerFactory
from user_data.backup_service import BackupService
import styles.style # TODO: dynamic loading
from wrapper_tests.support_testing import lLOCAL, lGOOD, lNEW, lRELAYS
from wrapper_tests.tests_wrapper import main as oTOX_OPTIONS, iMain, ToxOptions, iNodeInfo
global iI global iI
iI = 0 iI = 0
@ -147,18 +151,19 @@ sSTYLE = """
from copy import deepcopy from copy import deepcopy
class App: class App:
def __init__(self, version, args): def __init__(self, version, oArgs):
global LOG global LOG
self._args = args self._args = oArgs
self._path = path_to_profile = args.profile self.oArgs = oArgs
uri = args.uri self._path = path_to_profile = oArgs.profile
logfile = args.logfile uri = oArgs.uri
loglevel = args.loglevel logfile = oArgs.logfile
loglevel = oArgs.loglevel
setup_logging(args) setup_logging(oArgs)
# sys.stderr.write( 'Command line args: ' +repr(oArgs) +'\n') # sys.stderr.write( 'Command line args: ' +repr(oArgs) +'\n')
LOG.info("Command line: " +' '.join(sys.argv[1:])) LOG.info("Command line: " +' '.join(sys.argv[1:]))
LOG.debug(f'oArgs = {args!r}') LOG.debug(f'oArgs = {oArgs!r}')
LOG.info("Starting toxygen version " +version) LOG.info("Starting toxygen version " +version)
self._version = version self._version = version

View file

@ -1,5 +1,11 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
import common.tox_save as tox_save import common.tox_save as tox_save
global LOG
import logging
LOG = logging.getLogger(__name__)
class ContactProvider(tox_save.ToxSave): class ContactProvider(tox_save.ToxSave):
@ -54,11 +60,21 @@ class ContactProvider(tox_save.ToxSave):
def get_group_by_number(self, group_number): def get_group_by_number(self, group_number):
try: try:
public_key = self._tox.group_get_chat_id(group_number) if True:
# original code
public_key = self._tox.group_get_chat_id(group_number)
LOG.info(f"group_get_chat_id {group_number} {public_key}")
return self.get_group_by_public_key(public_key)
else:
# guessing
chat_id = self._tox.group_get_chat_id(group_number)
LOG.info(f"group_get_chat_id {group_number} {chat_id}")
group = self.get_contact_by_tox_id(chat_id)
return group
except Exception as e: except Exception as e:
LOG.warn(f"group_get_chat_id {group_number} {e}")
return None return None
return self.get_group_by_public_key(public_key)
def get_group_by_public_key(self, public_key): def get_group_by_public_key(self, public_key):
group = self._get_contact_from_cache(public_key) group = self._get_contact_from_cache(public_key)

View file

@ -201,6 +201,12 @@ class ContactsManager(ToxSave):
part2 = sorted(part2, key=key_lambda) part2 = sorted(part2, key=key_lambda)
self._contacts = part1 + part2 self._contacts = part1 + part2
elif sorting == 0: elif sorting == 0:
# AttributeError: 'NoneType' object has no attribute 'number'
for (i, contact) in enumerate(self._contacts):
if contact is None or not hasattr(contact, 'number'):
LOG.error("Contact {i} is None or not hasattr 'number'")
del self._contacts[i]
continue
contacts = sorted(self._contacts, key=lambda c: c.number) contacts = sorted(self._contacts, key=lambda c: c.number)
friends = filter(lambda c: type(c) is Friend, contacts) friends = filter(lambda c: type(c) is Friend, contacts)
groups = filter(lambda c: type(c) is GroupChat, contacts) groups = filter(lambda c: type(c) is GroupChat, contacts)
@ -370,13 +376,19 @@ class ContactsManager(ToxSave):
return list(filter(lambda c: type(c) is GroupChat, self._contacts)) return list(filter(lambda c: type(c) is GroupChat, self._contacts))
def add_group(self, group_number): def add_group(self, group_number):
group = self._contact_provider.get_group_by_number(group_number)
index = len(self._contacts) index = len(self._contacts)
self._contacts.append(group) group = self._contact_provider.get_group_by_number(group_number)
group.reset_avatar(self._settings['identicons']) if not group:
self._save_profile() LOG.warn(f"CM.add_group: NO group {group_number}")
self.set_active(index) else:
self.update_filtration() LOG.info(f"CM.add_group: Adding group {group._name}")
self._contacts.append(group)
LOG.info(f"contacts_manager.add_group: saving profile")
self._save_profile()
group.reset_avatar(self._settings['identicons'])
LOG.info(f"contacts_manager.add_group: setting active")
self.set_active(index)
self.update_filtration()
def delete_group(self, group_number): def delete_group(self, group_number):
group = self.get_group_by_number(group_number) group = self.get_group_by_number(group_number)
@ -503,6 +515,7 @@ class ContactsManager(ToxSave):
def update_groups_numbers(self): def update_groups_numbers(self):
groups = self._contact_provider.get_all_groups() groups = self._contact_provider.get_all_groups()
LOG.info("update_groups_numbers len(groups)={len(groups)}")
for i in range(len(groups)): for i in range(len(groups)):
chat_id = self._tox.group_get_chat_id(i) chat_id = self._tox.group_get_chat_id(i)
group = self.get_contact_by_tox_id(chat_id) group = self.get_contact_by_tox_id(chat_id)
@ -523,7 +536,13 @@ class ContactsManager(ToxSave):
self._load_groups() self._load_groups()
if len(self._contacts): if len(self._contacts):
self.set_active(0) self.set_active(0)
for contact in filter(lambda c: not c.has_avatar(), self._contacts): # filter(lambda c: not c.has_avatar(), self._contacts)
for (i, contact) in enumerate(self._contacts):
if not contact:
LOG.warn("_load_contacts NULL contact {i}")
del self._contacts[i]
continue
if contact.has_avatar(): continue
contact.reset_avatar(self._settings['identicons']) contact.reset_avatar(self._settings['identicons'])
self.update_filtration() self.update_filtration()

View file

@ -87,6 +87,7 @@ class GroupChat(contact.Contact, ToxSave):
LOG_WARN(f"add_peer id={peer_id} > {self._peers_limit}") LOG_WARN(f"add_peer id={peer_id} > {self._peers_limit}")
return return
LOG_INFO(f"add_peer id={peer_id}")
peer = GroupChatPeer(peer_id, peer = GroupChatPeer(peer_id,
self._tox.group_peer_get_name(self._number, peer_id), self._tox.group_peer_get_name(self._number, peer_id),
self._tox.group_peer_get_status(self._number, peer_id), self._tox.group_peer_get_status(self._number, peer_id),

View file

@ -1,7 +1,12 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
from contacts.group_chat import GroupChat from contacts.group_chat import GroupChat
from common.tox_save import ToxSave from common.tox_save import ToxSave
import wrapper.toxcore_enums_and_consts as constants import wrapper.toxcore_enums_and_consts as constants
global LOG
import logging
LOG = logging.getLogger(__name__)
class GroupFactory(ToxSave): class GroupFactory(ToxSave):
@ -18,6 +23,7 @@ class GroupFactory(ToxSave):
return self.create_group_by_number(group_number) return self.create_group_by_number(group_number)
def create_group_by_number(self, group_number): def create_group_by_number(self, group_number):
LOG.info(f"create_group_by_number {group_number}")
aliases = self._settings['friends_aliases'] aliases = self._settings['friends_aliases']
tox_id = self._tox.group_get_chat_id(group_number) tox_id = self._tox.group_get_chat_id(group_number)
try: try:

View file

@ -50,7 +50,10 @@ class GroupsService(tox_save.ToxSave):
def join_gc_by_id(self, chat_id, password, nick, status): def join_gc_by_id(self, chat_id, password, nick, status):
group_number = self._tox.group_join(chat_id, password, nick, status) group_number = self._tox.group_join(chat_id, password, nick, status)
LOG.debug(f"_join_gc_via_id {group_number}")
self._add_new_group_by_number(group_number) self._add_new_group_by_number(group_number)
group = self._get_group_by_number(group_number)
group.status = constants.TOX_USER_STATUS['NONE']
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
# Groups reconnect and leaving # Groups reconnect and leaving
@ -92,6 +95,8 @@ class GroupsService(tox_save.ToxSave):
def process_group_invite(self, friend_number, group_name, invite_data): def process_group_invite(self, friend_number, group_name, invite_data):
friend = self._get_friend_by_number(friend_number) friend = self._get_friend_by_number(friend_number)
# binary {invite_data}
LOG.debug(f"process_group_invite {friend_number} {group_name}")
invite = GroupInvite(friend.tox_id, group_name, invite_data) invite = GroupInvite(friend.tox_id, group_name, invite_data)
self._group_invites.append(invite) self._group_invites.append(invite)
self._update_invites_button_state() self._update_invites_button_state()
@ -99,6 +104,7 @@ class GroupsService(tox_save.ToxSave):
def accept_group_invite(self, invite, name, status, password): def accept_group_invite(self, invite, name, status, password):
pk = invite.friend_public_key pk = invite.friend_public_key
friend = self._get_friend_by_public_key(pk) friend = self._get_friend_by_public_key(pk)
LOG.debug(f"accept_group_invite {name}")
self._join_gc_via_invite(invite.invite_data, friend.number, name, status, password) self._join_gc_via_invite(invite.invite_data, friend.number, name, status, password)
self._delete_group_invite(invite) self._delete_group_invite(invite)
self._update_invites_button_state() self._update_invites_button_state()
@ -230,6 +236,7 @@ class GroupsService(tox_save.ToxSave):
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
def _add_new_group_by_number(self, group_number): def _add_new_group_by_number(self, group_number):
LOG.debug(f"_add_new_group_by_number {group_number}")
self._contacts_manager.add_group(group_number) self._contacts_manager.add_group(group_number)
def _get_group_by_number(self, group_number): def _get_group_by_number(self, group_number):
@ -256,14 +263,21 @@ 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 = '' LOG.debug(f"_join_gc_via_invite friend_number={friend_number} nick={nick} datalen={len(invite_data)}")
if invite_data is None: invite_data = '' if nick is None:
nick = ''
if invite_data is None:
invite_data = b''
try: 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: except Exception as e:
LOG.error(f"_join_gc_via_invite {e}") LOG.error(f"_join_gc_via_invite ERROR {e}")
else: return
try:
self._add_new_group_by_number(group_number) self._add_new_group_by_number(group_number)
except Exception as e:
LOG.error(f"_join_gc_via_invite group_number={group_number} {e}")
return
def _update_invites_button_state(self): def _update_invites_button_state(self):
self._main_screen.update_gc_invites_button_state() self._main_screen.update_gc_invites_button_state()

View file

@ -333,8 +333,6 @@ lKEEP_SETTINGS = ['uri',
class A(): pass class A(): pass
global oAPP
oAPP = None
def main(lArgs): def main(lArgs):
global oPYA global oPYA
from argparse import Namespace from argparse import Namespace
@ -385,9 +383,8 @@ def main(lArgs):
oArgs = aArgs oArgs = aArgs
toxygen = app.App(__version__, oArgs) toxygen = app.App(__version__, oArgs)
global oAPP # for pyqtconsole
oAPP = toxygen __builtins__.app = toxygen
__builtins__['app'] = toxygen
i = toxygen.iMain() i = toxygen.iMain()
return i return i

View file

@ -148,9 +148,12 @@ class Messenger(tox_save.ToxSave):
""" """
t = util.get_unix_time() t = util.get_unix_time()
group = self._get_group_by_number(group_number) group = self._get_group_by_number(group_number)
if not group:
LOG.error(f"FixMe new_group_message _get_group_by_number({group_number})")
return
peer = group.get_peer_by_id(peer_id) peer = group.get_peer_by_id(peer_id)
if not peer: if not peer:
LOG.warn('FixMe new_group_message group.get_peer_by_id ' + str(peer_id)) LOG.error('FixMe new_group_message group.get_peer_by_id ' + str(peer_id))
return return
text_message = TextMessage(message, MessageAuthor(peer.name, MESSAGE_AUTHOR['GC_PEER']), t, message_type) text_message = TextMessage(message, MessageAuthor(peer.name, MESSAGE_AUTHOR['GC_PEER']), t, message_type)
self._add_message(text_message, group) self._add_message(text_message, group)

View file

@ -14,11 +14,18 @@ from notifications.sound import *
from datetime import datetime from datetime import datetime
iMAX_INT32 = 4294967295 iMAX_INT32 = 4294967295
# callbacks can be called in any thread so were being careful
def LOG_ERROR(l): print('EROR< '+l) def LOG_ERROR(l): print('EROR< '+l)
def LOG_WARN(l): print('WARN< '+l) def LOG_WARN(l): print('WARN< '+l)
def LOG_INFO(l): print('INFO< '+l) def LOG_INFO(l):
def LOG_DEBUG(l): print('DBUG< '+l) bIsVerbose = hasattr(__builtins__, 'app') and app.oArgs.loglevel <= 20-1
def LOG_TRACE(l): pass # print('TRACE+ '+l) if bIsVerbose: print('INFO< '+l)
def LOG_DEBUG(l):
bIsVerbose = hasattr(__builtins__, 'app') and app.oArgs.loglevel <= 10-1
if bIsVerbose: print('DBUG< '+l)
def LOG_TRACE(l):
bIsVerbose = hasattr(__builtins__, 'app') and app.oArgs.loglevel < 10-1
pass # print('TRACE+ '+l)
global aTIMES global aTIMES
aTIMES=dict() aTIMES=dict()
@ -185,7 +192,9 @@ def friend_message(messenger, contacts_manager, profile, settings, window, tray)
invoke_in_main_thread(messenger.new_message, friend_number, message_type, message) invoke_in_main_thread(messenger.new_message, friend_number, message_type, message)
if not window.isActiveWindow(): if not window.isActiveWindow():
friend = contacts_manager.get_friend_by_number(friend_number) friend = contacts_manager.get_friend_by_number(friend_number)
if settings['notifications'] and profile.status != TOX_USER_STATUS['BUSY'] and not settings.locked: if settings['notifications'] \
and profile.status != TOX_USER_STATUS['BUSY'] \
and not settings.locked:
invoke_in_main_thread(tray_notification, friend.name, message, tray, window) invoke_in_main_thread(tray_notification, friend.name, message, tray, window)
if settings['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']: if settings['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']:
sound_notification(SOUND_NOTIFICATION['MESSAGE']) sound_notification(SOUND_NOTIFICATION['MESSAGE'])
@ -249,7 +258,9 @@ def tox_file_recv(window, tray, profile, file_transfer_handler, contacts_manager
file_name) file_name)
if not window.isActiveWindow(): if not window.isActiveWindow():
friend = contacts_manager.get_friend_by_number(friend_number) friend = contacts_manager.get_friend_by_number(friend_number)
if settings['notifications'] and profile.status != TOX_USER_STATUS['BUSY'] and not settings.locked: if settings['notifications'] \
and profile.status != TOX_USER_STATUS['BUSY'] \
and not settings.locked:
file_from = util_ui.tr("File from") file_from = util_ui.tr("File from")
invoke_in_main_thread(tray_notification, file_from + ' ' + friend.name, file_name, tray, window) invoke_in_main_thread(tray_notification, file_from + ' ' + friend.name, file_name, tray, window)
if settings['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']: if settings['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']:
@ -452,13 +463,14 @@ def group_message(window, tray, tox, messenger, settings, profile):
if settings['sound_notifications'] and bl and \ if settings['sound_notifications'] and bl and \
profile.status != TOX_USER_STATUS['BUSY']: profile.status != TOX_USER_STATUS['BUSY']:
sound_notification(SOUND_NOTIFICATION['MESSAGE']) sound_notification(SOUND_NOTIFICATION['MESSAGE'])
if False and settings['tray_icon']: if False and settings['tray_icon'] and tray:
if settings['notifications'] and \ if settings['notifications'] and \
profile.status != TOX_USER_STATUS['BUSY'] and \ profile.status != TOX_USER_STATUS['BUSY'] and \
(not settings.locked) and bl: (not settings.locked) and bl:
invoke_in_main_thread(tray_notification, name, message, tray, window) invoke_in_main_thread(tray_notification, name, message, tray, window)
icon = util.join_path(util.get_images_directory(), 'icon_new_messages.png') if tray:
invoke_in_main_thread(tray.setIcon, QtGui.QIcon(icon)) icon = util.join_path(util.get_images_directory(), 'icon_new_messages.png')
invoke_in_main_thread(tray.setIcon, QtGui.QIcon(icon))
return wrapped return wrapped
@ -475,7 +487,9 @@ def group_private_message(window, tray, tox, messenger, settings, profile):
return return
bl = settings['notify_all_gc'] or profile.name in message bl = settings['notify_all_gc'] or profile.name in message
name = tox.group_peer_get_name(group_number, peer_id) name = tox.group_peer_get_name(group_number, peer_id)
if settings['notifications'] and profile.status != TOX_USER_STATUS['BUSY'] and (not settings.locked) and bl: if settings['notifications'] and settings['tray_icon'] \
and profile.status != TOX_USER_STATUS['BUSY'] \
and (not settings.locked) and bl:
invoke_in_main_thread(tray_notification, name, message, tray, window) invoke_in_main_thread(tray_notification, name, message, tray, window)
if settings['sound_notifications'] and bl and profile.status != TOX_USER_STATUS['BUSY']: if settings['sound_notifications'] and bl and profile.status != TOX_USER_STATUS['BUSY']:
sound_notification(SOUND_NOTIFICATION['MESSAGE']) sound_notification(SOUND_NOTIFICATION['MESSAGE'])
@ -485,7 +499,7 @@ def group_private_message(window, tray, tox, messenger, settings, profile):
return wrapped return wrapped
# Exception ignored on calling ctypes callback function: <function group_invite.<locals>.wrapped at 0x7ffede910700>
def group_invite(window, settings, tray, profile, groups_service, contacts_provider): def group_invite(window, settings, tray, profile, groups_service, contacts_provider):
def wrapped(tox, friend_number, invite_data, length, group_name, group_name_length, user_data): def wrapped(tox, friend_number, invite_data, length, group_name, group_name_length, user_data):
LOG_DEBUG(f"group_invite friend_number={friend_number}") LOG_DEBUG(f"group_invite friend_number={friend_number}")
@ -495,14 +509,18 @@ def group_invite(window, settings, tray, profile, groups_service, contacts_provi
bytes(invite_data[:length])) bytes(invite_data[:length]))
if window.isActiveWindow(): if window.isActiveWindow():
return return
if settings['notifications'] and \ bHasTray = tray and settings['tray_icon']
profile.status != TOX_USER_STATUS['BUSY'] and not settings.locked: if settings['notifications'] \
and bHasTray \
and profile.status != TOX_USER_STATUS['BUSY'] \
and not settings.locked:
friend = contacts_provider.get_friend_by_number(friend_number) friend = contacts_provider.get_friend_by_number(friend_number)
title = util_ui.tr('New invite to group chat') title = util_ui.tr('New invite to group chat')
text = util_ui.tr('{} invites you to group "{}"').format(friend.name, group_name) text = util_ui.tr('{} invites you to group "{}"').format(friend.name, group_name)
invoke_in_main_thread(tray_notification, title, text, tray, window) invoke_in_main_thread(tray_notification, title, text, tray, window)
icon = util.join_path(util.get_images_directory(), 'icon_new_messages.png') if tray:
invoke_in_main_thread(tray.setIcon, QtGui.QIcon(icon)) icon = util.join_path(util.get_images_directory(), 'icon_new_messages.png')
invoke_in_main_thread(tray.setIcon, QtGui.QIcon(icon))
return wrapped return wrapped

View file

@ -10,7 +10,7 @@ def tray_notification(title, text, tray, window):
:param tray: ref to tray icon :param tray: ref to tray icon
:param window: main window :param window: main window
""" """
if QtWidgets.QSystemTrayIcon.isSystemTrayAvailable(): if tray and QtWidgets.QSystemTrayIcon.isSystemTrayAvailable():
if len(text) > 30: if len(text) > 30:
text = text[:27] + '...' text = text[:27] + '...'
tray.showMessage(title, text, QtWidgets.QSystemTrayIcon.NoIcon, 3000) tray.showMessage(title, text, QtWidgets.QSystemTrayIcon.NoIcon, 3000)

View file

@ -1,19 +0,0 @@
.QWidget {font-family Helvetica;}
.QCheckBox { font-family Helvetica;}
.QComboBox { font-family Helvetica;}
.QGroupBox { font-family Helvetica;}
.QLabel {font-family Helvetica;}
.QLineEdit { font-family Helvetica;}
.QListWidget { font-family Helvetica;}
.QListWidgetItem { font-family Helvetica;}
.QMainWindow {font-family Helvetica;}
.QMenu {font-family Helvetica;}
.QMenuBar {font-family Helvetica;}
.QPlainText {font-family Courier; weight: 75;}
.QPlainTextEdit {font-family Courier;}
.QPushButton {font-family Helvetica;}
.QRadioButton { font-family Helvetica; }
.QText {font-family Courier; weight: 75; }
.QTextBrowser {font-family Courier; weight: 75; }
.QTextSingleLine {font-family Courier; weight: 75; }
.QToolBar { font-weight: bold; }

View file

@ -2,6 +2,9 @@ from PyQt5 import uic, QtWidgets
import utils.util as util import utils.util as util
from ui.widgets import * from ui.widgets import *
global LOG
import logging
LOG = logging.getLogger('app')
class GroupInviteItem(QtWidgets.QWidget): class GroupInviteItem(QtWidgets.QWidget):
@ -73,6 +76,7 @@ class GroupInvitesScreen(CenteredWidget):
nick = self._tox.self_get_name() 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:
LOG.debug(f"_accept_invites {nick}")
self._groups_service.accept_group_invite(invite, nick, status, password) self._groups_service.accept_group_invite(invite, nick, status, password)
self._refresh_invites_list() self._refresh_invites_list()
@ -81,6 +85,7 @@ class GroupInvitesScreen(CenteredWidget):
def _decline_invites(self): def _decline_invites(self):
selected_invites = self._get_selected_invites() selected_invites = self._get_selected_invites()
for invite in selected_invites: for invite in selected_invites:
LOG.debug(f"_groups_service.decline_group_invite")
self._groups_service.decline_group_invite(invite) self._groups_service.decline_group_invite(invite)
self._refresh_invites_list() self._refresh_invites_list()

View file

@ -1,19 +1,65 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- # -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
import os import os
import logging import logging
from PyQt5 import uic
from PyQt5 import QtWidgets, QtGui
from qtpy.QtGui import (QColor, QTextCharFormat, QFont, QSyntaxHighlighter)
from ui.contact_items import * from ui.contact_items import *
from ui.widgets import MultilineEdit from ui.widgets import MultilineEdit
from ui.main_screen_widgets import * from ui.main_screen_widgets import *
import utils.util as util import utils.util as util
import utils.ui as util_ui import utils.ui as util_ui
from PyQt5 import uic
from PyQt5 import QtWidgets, QtGui
from user_data.settings import Settings from user_data.settings import Settings
iMAX = 70
global LOG global LOG
LOG = logging.getLogger('app.'+'mains') LOG = logging.getLogger('app.'+'mains')
iMAX = 70
try:
# https://github.com/pyqtconsole/pyqtconsole
from pyqtconsole.console import PythonConsole
import pyqtconsole.highlighter as hl
except Exception as e:
LOG.warn(e)
PythonConsole = None
else:
def hl_format(color, style=''):
"""Return a QTextCharFormat with the given attributes.
unused
"""
_color = QColor()
_color.setNamedColor(color)
_format = QTextCharFormat()
_format.setBackground(_color)
if 'bold' in style:
_format.setFontWeight(QFont.Bold)
if 'italic' in style:
_format.setFontItalic(True)
_fgcolor = QColor()
_fgcolor.setNamedColor('white')
_format.setForeground(_fgcolor)
return _format
aFORMATS = {
'keyword': hl.format('blue', 'bold'),
'operator': hl.format('red'),
'brace': hl.format('darkGray'),
'defclass': hl.format('black', 'bold'),
'string': hl.format('magenta'),
'string2': hl.format('darkMagenta'),
'comment': hl.format('darkGreen', 'italic'),
'self': hl.format('black', 'italic'),
'numbers': hl.format('brown'),
'inprompt': hl.format('darkBlue', 'bold'),
'outprompt': hl.format('darkRed', 'bold'),
}
class QTextEditLogger(logging.Handler): class QTextEditLogger(logging.Handler):
def __init__(self, parent, app): def __init__(self, parent, app):
super().__init__() super().__init__()
@ -564,21 +610,45 @@ class MainWindow(QtWidgets.QMainWindow):
self._me.show() self._me.show()
def python_console(self): def python_console(self):
try: if PythonConsole:
if not self._pe: app = self._app
from pyqtconsole.console import PythonConsole if app and app._settings:
self._pe = PythonConsole(sFont="Courier New", bBold=True) size = app._settings['message_font_size']
self._pe.show() font_name = app._settings['font']
self._pe.eval_queued() else:
# self._pe.eval_in_thread() size = 12
except Exception as e: font_name = "Courier New"
LOG.debug(e)
self._me.show() size = font_width = 10
font_name = "DejaVu Sans Mono"
try:
if not self._pe:
self._pe = PythonConsole(sFont=font_name,
formats=aFORMATS,
bBold=True,
font_width=size)
self._pe.setWindowTitle('variable: app is the application')
# self._pe.edit.setStyleSheet('foreground: white; background-color: black;}')
# Fix the pyconsole geometry
geometry = self._pe.geometry()
geometry.setWidth(font_width*80+20)
geometry.setHeight(font_width*40)
self._pe.setGeometry(geometry)
self._pe.resize(font_width*80+20, font_width*40)
self._pe.show()
self._pe.eval_queued()
# or self._pe.eval_in_thread()
return
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: ')
text += '' + '\nGitHub: https://github.com/toxygen-project/toxygen/' text += '' + '\nGitHub: https://git.plastiras.org/emdee/toxygen'
title = util_ui.tr('About') title = util_ui.tr('About')
util_ui.message_box(text, title) util_ui.message_box(text, title)
@ -861,8 +931,10 @@ class MainWindow(QtWidgets.QMainWindow):
def update_gc_invites_button_state(self): def update_gc_invites_button_state(self):
invites_count = self._groups_service.group_invites_count invites_count = self._groups_service.group_invites_count
LOG.debug(f"invites_count={invites_count}") LOG.debug(f"update_gc_invites_button_state invites_count={invites_count}")
# Fixme
self.groupInvitesPushButton.setVisible(True) # invites_count > 0 self.groupInvitesPushButton.setVisible(True) # invites_count > 0
text = util_ui.tr('{} new invites to group chats').format(invites_count) text = util_ui.tr(f'{invites_count} new invites to group chats')
self.groupInvitesPushButton.setText(text) self.groupInvitesPushButton.setText(text)
self.resizeEvent() self.resizeEvent()