diff --git a/toxygen/contacts/contact_menu.py b/toxygen/contacts/contact_menu.py
index e10f07d..63d0d36 100644
--- a/toxygen/contacts/contact_menu.py
+++ b/toxygen/contacts/contact_menu.py
@@ -181,9 +181,12 @@ class GroupMenuGenerator(BaseContactMenuGenerator):
menu = (builder
.with_action(util_ui.tr('Set alias'), lambda: main_screen.set_alias(number))
.with_submenu(copy_menu_builder)
+ .with_optional_action(util_ui.tr('Manage group'),
+ lambda: groups_service.show_group_management_screen(self._contact),
+ self._contact.is_self_founder())
.with_optional_action(util_ui.tr('Set topic'),
lambda: groups_service.set_group_topic(self._contact),
- self._contact.is_moderator_or_founder())
+ self._contact.is_self_moderator_or_founder())
.with_action(util_ui.tr('Reconnect to group'),
lambda: groups_service.reconnect_to_group(self._contact.number))
.with_optional_action(util_ui.tr('Disconnect from group'),
diff --git a/toxygen/contacts/group_chat.py b/toxygen/contacts/group_chat.py
index 38ab686..b38e538 100644
--- a/toxygen/contacts/group_chat.py
+++ b/toxygen/contacts/group_chat.py
@@ -12,6 +12,8 @@ class GroupChat(contact.Contact, ToxSave):
super().__init__(profile_manager, message_getter, number, name, status_message, widget, tox_id)
ToxSave.__init__(self, tox)
self._is_private = is_private
+ self._password = None
+ self._peers_limit = 512
self._peers = []
self._add_self_to_gc()
@@ -32,7 +34,26 @@ class GroupChat(contact.Contact, ToxSave):
def get_is_private(self):
return self._is_private
- is_private = property(get_is_private)
+ def set_is_private(self, is_private):
+ self._is_private = is_private
+
+ is_private = property(get_is_private, set_is_private)
+
+ def get_password(self):
+ return self._password
+
+ def set_password(self, password):
+ self._password = password
+
+ password = property(get_password, set_password)
+
+ def get_peers_limit(self):
+ return self._peers_limit
+
+ def set_peers_limit(self, peers_limit):
+ self._peers_limit = peers_limit
+
+ peers_limit = property(get_peers_limit, set_peers_limit)
# -----------------------------------------------------------------------------------------------------------------
# Peers methods
@@ -47,9 +68,12 @@ class GroupChat(contact.Contact, ToxSave):
def get_self_role(self):
return self._peers[0].role
- def is_moderator_or_founder(self):
+ def is_self_moderator_or_founder(self):
return self.get_self_role() <= constants.TOX_GROUP_ROLE['MODERATOR']
+ def is_self_founder(self):
+ return self.get_self_role() == constants.TOX_GROUP_ROLE['FOUNDER']
+
def add_peer(self, peer_id, is_current_user=False):
peer = GroupChatPeer(peer_id,
self._tox.group_peer_get_name(self._number, peer_id),
diff --git a/toxygen/groups/groups_service.py b/toxygen/groups/groups_service.py
index 1016bd7..4cf1368 100644
--- a/toxygen/groups/groups_service.py
+++ b/toxygen/groups/groups_service.py
@@ -15,7 +15,7 @@ class GroupsService(tox_save.ToxSave):
self._peers_list_widget = main_screen.peers_list
self._widgets_factory_provider = widgets_factory_provider
self._group_invites = []
- self._peer_screen = None
+ self._peer_screen = self._management_screen = None
def set_tox(self, tox):
super().set_tox(tox)
@@ -70,14 +70,14 @@ class GroupsService(tox_save.ToxSave):
friend = self._get_friend_by_number(friend_number)
invite = GroupInvite(friend.tox_id, group_name, invite_data)
self._group_invites.append(invite)
- self._main_screen.update_gc_invites_button_state()
+ self._update_invites_button_state()
def accept_group_invite(self, invite, name, status, password):
pk = invite.friend_public_key
friend = self._get_friend_by_public_key(pk)
self._join_gc_via_invite(invite.invite_data, friend.number, name, status, password)
self._delete_group_invite(invite)
- self._main_screen.update_gc_invites_button_state()
+ self._update_invites_button_state()
def decline_group_invite(self, invite):
self._delete_group_invite(invite)
@@ -102,7 +102,7 @@ class GroupsService(tox_save.ToxSave):
group.status_message = self._tox.group_get_topic(group.number)
def set_group_topic(self, group):
- if not group.is_moderator_or_founder():
+ if not group.is_self_moderator_or_founder():
return
text = util_ui.tr('New topic for group "{}":'.format(group.name))
title = util_ui.tr('Set group topic')
@@ -112,6 +112,30 @@ class GroupsService(tox_save.ToxSave):
self._tox.group_set_topic(group.number, topic)
group.status_message = topic
+ def show_group_management_screen(self, group):
+ widgets_factory = self._get_widgets_factory()
+ self._management_screen = widgets_factory.create_group_management_screen(group)
+ self._management_screen.show()
+
+ def set_group_password(self, group, password):
+ if group.password == password:
+ return
+ self._tox.group_founder_set_password(group.number, password)
+ group.password = password
+
+ def set_group_peers_limit(self, group, peers_limit):
+ if group.peers_limit == peers_limit:
+ return
+ self._tox.group_founder_set_peer_limit(group.number, peers_limit)
+ group.peers_limit = peers_limit
+
+ def set_group_privacy_state(self, group, privacy_state):
+ is_private = privacy_state == constants.TOX_GROUP_PRIVACY_STATE['PRIVATE']
+ if group.is_private == is_private:
+ return
+ self._tox.group_founder_set_privacy_state(group.number, privacy_state)
+ group.is_private = is_private
+
# -----------------------------------------------------------------------------------------------------------------
# Peers list
# -----------------------------------------------------------------------------------------------------------------
@@ -123,7 +147,7 @@ class GroupsService(tox_save.ToxSave):
PeersListGenerator().generate(group.peers, self, self._peers_list_widget, group.tox_id)
def peer_selected(self, chat_id, peer_id):
- widgets_factory = self._widgets_factory_provider.get_item()
+ widgets_factory = self._get_widgets_factory()
group = self._get_group_by_public_key(chat_id)
self_peer = group.get_self_peer()
if self_peer.id != peer_id:
@@ -186,3 +210,9 @@ class GroupsService(tox_save.ToxSave):
def _join_gc_via_invite(self, invite_data, friend_number, nick, status, password):
group_number = self._tox.group_invite_accept(invite_data, friend_number, nick, status, password)
self._add_new_group_by_number(group_number)
+
+ def _update_invites_button_state(self):
+ self._main_screen.update_gc_invites_button_state()
+
+ def _get_widgets_factory(self):
+ return self._widgets_factory_provider.get_item()
diff --git a/toxygen/middleware/callbacks.py b/toxygen/middleware/callbacks.py
index 36bb960..77a029d 100644
--- a/toxygen/middleware/callbacks.py
+++ b/toxygen/middleware/callbacks.py
@@ -506,6 +506,34 @@ def group_moderation(groups_service, contacts_provider, contacts_manager, messen
return wrapped
+
+def group_password(contacts_provider):
+
+ def wrapped(tox_link, group_number, password, length, user_data):
+ password = str(password[:length], 'utf-8')
+ group = contacts_provider.get_group_by_number(group_number)
+ group.password = password
+
+ return wrapped
+
+
+def group_peer_limit(contacts_provider):
+
+ def wrapped(tox_link, group_number, peer_limit, user_data):
+ group = contacts_provider.get_group_by_number(group_number)
+ group.peer_limit = peer_limit
+
+ return wrapped
+
+
+def group_privacy_state(contacts_provider):
+
+ def wrapped(tox_link, group_number, privacy_state, user_data):
+ group = contacts_provider.get_group_by_number(group_number)
+ group.is_private = privacy_state == TOX_GROUP_PRIVACY_STATE['PRIVATE']
+
+ return wrapped
+
# -----------------------------------------------------------------------------------------------------------------
# Callbacks - initialization
# -----------------------------------------------------------------------------------------------------------------
@@ -573,3 +601,6 @@ def init_callbacks(tox, profile, settings, plugin_loader, contacts_manager,
tox.callback_group_peer_status(group_peer_status(contacts_provider, groups_service), 0)
tox.callback_group_topic(group_topic(contacts_provider), 0)
tox.callback_group_moderation(group_moderation(groups_service, contacts_provider, contacts_manager, messenger), 0)
+ tox.callback_group_password(group_password(contacts_provider), 0)
+ tox.callback_group_peer_limit(group_peer_limit(contacts_provider), 0)
+ tox.callback_group_privacy_state(group_privacy_state(contacts_provider), 0)
diff --git a/toxygen/ui/group_management_screen.py b/toxygen/ui/group_management_screen.py
new file mode 100644
index 0000000..bbc2629
--- /dev/null
+++ b/toxygen/ui/group_management_screen.py
@@ -0,0 +1,46 @@
+from ui.widgets import CenteredWidget
+from PyQt5 import uic
+import utils.util as util
+import utils.ui as util_ui
+
+
+class GroupManagementScreen(CenteredWidget):
+
+ def __init__(self, groups_service, group):
+ super().__init__()
+ self._groups_service = groups_service
+ self._group = group
+
+ uic.loadUi(util.get_views_path('group_management_screen'), self)
+ self._update_ui()
+
+ def _update_ui(self):
+ self._retranslate_ui()
+
+ self.passwordLineEdit.setText(self._group.password)
+ self.privacyStateComboBox.setCurrentIndex(1 if self._group.is_private else 0)
+ self.peersLimitSpinBox.setValue(self._group.peers_limit)
+
+ self.savePushButton.clicked.connect(self._save)
+
+ def _retranslate_ui(self):
+ self.setWindowTitle(util_ui.tr('Group "{}"').format(self._group.name))
+ self.passwordLabel.setText(util_ui.tr('Password'))
+ self.peerLimitLabel.setText(util_ui.tr('Peer limit:'))
+ self.privacyStateLabel.setText(util_ui.tr('Privacy state'))
+ self.savePushButton.setText(util_ui.tr('Save'))
+
+ self.privacyStateComboBox.clear()
+ self.privacyStateComboBox.addItem(util_ui.tr('Public'))
+ self.privacyStateComboBox.addItem(util_ui.tr('Private'))
+
+ def _save(self):
+ password = self.passwordLineEdit.text()
+ privacy_state = self.privacyStateComboBox.currentIndex()
+ peers_limit = self.peersLimitSpinBox.value()
+
+ self._groups_service.set_group_password(self._group, password)
+ self._groups_service.set_group_privacy_state(self._group, privacy_state)
+ self._groups_service.set_group_peers_limit(self._group, peers_limit)
+
+ self.close()
diff --git a/toxygen/ui/views/group_management_screen.ui b/toxygen/ui/views/group_management_screen.ui
new file mode 100644
index 0000000..859754b
--- /dev/null
+++ b/toxygen/ui/views/group_management_screen.ui
@@ -0,0 +1,110 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 658
+ 238
+
+
+
+ Form
+
+
+
+
+ 180
+ 20
+ 450
+ 41
+
+
+
+
+
+
+ 20
+ 30
+ 145
+ 20
+
+
+
+ TextLabel
+
+
+
+
+
+ 20
+ 80
+ 145
+ 20
+
+
+
+ TextLabel
+
+
+
+
+
+ 180
+ 70
+ 450
+ 40
+
+
+
+ 2
+
+
+ 9999
+
+
+ 512
+
+
+
+
+
+ 20
+ 130
+ 145
+ 20
+
+
+
+ TextLabel
+
+
+
+
+
+ 180
+ 120
+ 450
+ 40
+
+
+
+
+
+
+ 20
+ 180
+ 611
+ 41
+
+
+
+ PushButton
+
+
+
+
+
+
diff --git a/toxygen/ui/views/interface_settings_screen.ui b/toxygen/ui/views/interface_settings_screen.ui
new file mode 100644
index 0000000..fb0bcf1
--- /dev/null
+++ b/toxygen/ui/views/interface_settings_screen.ui
@@ -0,0 +1,253 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 552
+ 847
+
+
+
+ Form
+
+
+ -
+
+
+ Qt::ScrollBarAsNeeded
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 532
+ 827
+
+
+
+
+
+ 30
+ 140
+ 67
+ 17
+
+
+
+ TextLabel
+
+
+
+
+
+ 20
+ 180
+ 471
+ 31
+
+
+
+
+
+
+ 20
+ 60
+ 471
+ 31
+
+
+
+
+
+
+ 30
+ 20
+ 67
+ 17
+
+
+
+ TextLabel
+
+
+
+
+
+ 30
+ 220
+ 461
+ 23
+
+
+
+ CheckBox
+
+
+
+
+
+ 30
+ 280
+ 461
+ 221
+
+
+
+ GroupBox
+
+
+
+
+ 30
+ 40
+ 92
+ 23
+
+
+
+ CheckBox
+
+
+
+
+
+ 30
+ 80
+ 411
+ 17
+
+
+
+ TextLabel
+
+
+
+
+
+ 30
+ 120
+ 411
+ 31
+
+
+
+
+
+
+
+ 30
+ 250
+ 461
+ 23
+
+
+
+ CheckBox
+
+
+
+
+
+ 30
+ 750
+ 471
+ 40
+
+
+
+ PushButton
+
+
+
+
+
+ 30
+ 690
+ 471
+ 40
+
+
+
+ PushButton
+
+
+
+
+
+ 30
+ 520
+ 461
+ 23
+
+
+
+ CheckBox
+
+
+
+
+
+ 30
+ 550
+ 471
+ 131
+
+
+
+ GroupBox
+
+
+
+
+ 30
+ 30
+ 421
+ 23
+
+
+
+ RadioButton
+
+
+
+
+
+ 30
+ 60
+ 431
+ 23
+
+
+
+ RadioButton
+
+
+
+
+
+ 30
+ 90
+ 421
+ 23
+
+
+
+ RadioButton
+
+
+
+
+
+
+
+
+
+
+
diff --git a/toxygen/ui/widgets_factory.py b/toxygen/ui/widgets_factory.py
index 75b83b4..e394684 100644
--- a/toxygen/ui/widgets_factory.py
+++ b/toxygen/ui/widgets_factory.py
@@ -4,6 +4,7 @@ from ui.groups_widgets import *
from ui.peer_screen import *
from ui.self_peer_screen import *
from ui.group_invites_widgets import *
+from ui.group_management_screen import *
class WidgetsFactory:
@@ -82,3 +83,6 @@ class WidgetsFactory:
def create_group_invites_window(self):
return GroupInvitesScreen(self._groups_service, self._profile, self._contacts_provider)
+
+ def create_group_management_screen(self, group):
+ return GroupManagementScreen(self._groups_service, group)