Daniel Brötzmann pushed to branch mainwindow at gajim / gajim
Commits: 2f77f7f8 by wurstsalat at 2021-09-16T23:43:36+02:00 AdhocMUC: Rework
- - - - -
4 changed files:
- gajim/data/gui/adhoc_muc.ui - gajim/gtk/adhoc_muc.py - gajim/gtk/const.py - gajim/gtk/controls/chat.py
Changes:
===================================== gajim/data/gui/adhoc_muc.ui ===================================== @@ -12,184 +12,180 @@ <column type="gchararray"/> </columns> </object> - <object class="GtkWindow" id="adhoc_muc_window"> + <object class="GtkListStore" id="server_store"> + <columns> + <!-- column-name server --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkBox" id="adhoc_box"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="border-width">5</property> - <property name="title" translatable="yes">Invite Friends!</property> - <property name="type-hint">dialog</property> - <signal name="destroy" handler="on_chat_to_muc_window_destroy" swapped="no"/> - <signal name="key-press-event" handler="on_chat_to_muc_window_key_press_event" swapped="no"/> + <property name="border-width">18</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> <child> - <object class="GtkBox"> + <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">You are now entering a group chat. -Select the contacts you want to invite</property> - <property name="justify">center</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="padding">4</property> - <property name="position">0</property> - </packing> - </child> + <property name="label" translatable="yes">Group Chat Invitation</property> + <style> + <class name="large-header"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="description_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="justify">center</property> + <property name="wrap">True</property> + <property name="max-width-chars">40</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> <child> - <object class="GtkScrolledWindow" id="guests_scrolledwindow"> + <object class="GtkTreeView" id="guests_treeview"> + <property name="height-request">300</property> <property name="visible">True</property> <property name="can-focus">True</property> - <property name="shadow-type">in</property> + <property name="model">guests_store</property> + <property name="headers-visible">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> + </child> <child> - <object class="GtkTreeView" id="guests_treeview"> - <property name="height-request">300</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="model">guests_store</property> - <property name="headers-visible">False</property> - <child internal-child="selection"> - <object class="GtkTreeSelection"/> - </child> + <object class="GtkTreeViewColumn"> + <property name="title" translatable="yes">column</property> <child> - <object class="GtkTreeViewColumn"> - <property name="title" translatable="yes">column</property> - <child> - <object class="GtkCellRendererPixbuf"/> - <attributes> - <attribute name="icon-name">0</attribute> - </attributes> - </child> - </object> - </child> - <child> - <object class="GtkTreeViewColumn"> - <property name="title" translatable="yes">column</property> - <child> - <object class="GtkCellRendererText"/> - <attributes> - <attribute name="text">1</attribute> - </attributes> - </child> - </object> + <object class="GtkCellRendererPixbuf"/> + <attributes> + <attribute name="icon-name">0</attribute> + </attributes> </child> </object> </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="padding">4</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkExpander"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> - <object class="GtkBox"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkLabel" id="server_select_label"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="label" translatable="yes">Please select a group chat server.</property> - <property name="justify">center</property> - <property name="wrap">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="padding">4</property> - <property name="position">0</property> - </packing> - </child> + <object class="GtkTreeViewColumn"> + <property name="title" translatable="yes">column</property> <child> - <object class="GtkComboBox" id="server_list_comboboxentry"> - <property name="visible">True</property> - <property name="can-focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> + <object class="GtkCellRendererText"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> </child> </object> </child> - <child type="label"> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Group chat server</property> - </object> - </child> </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="padding">4</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkExpander"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> - <object class="GtkButtonBox"> + <object class="GtkBox"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="spacing">6</property> - <property name="layout-style">end</property> + <property name="margin-top">6</property> + <property name="spacing">12</property> <child> - <object class="GtkButton" id="cancel_button"> - <property name="label">_Cancel</property> + <object class="GtkLabel"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="use-underline">True</property> - <signal name="clicked" handler="on_cancel_button_clicked" swapped="no"/> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Server</property> + <style> + <class name="dim-label"/> + </style> </object> <packing> <property name="expand">False</property> - <property name="fill">False</property> - <property name="padding">3</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <object class="GtkButton" id="invite_button"> - <property name="label" translatable="yes">Invite</property> + <object class="GtkComboBox" id="server_combobox"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="use-underline">True</property> - <signal name="clicked" handler="on_invite_button_clicked" swapped="no"/> + <property name="can-focus">False</property> + <property name="model">server_store</property> + <property name="active">0</property> + <property name="has-entry">True</property> + <property name="entry-text-column">0</property> + <child internal-child="entry"> + <object class="GtkEntry" id="server_entry"> + <property name="can-focus">True</property> + <signal name="changed" handler="_on_server_combobox_entry_changed" swapped="no"/> + </object> + </child> </object> <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="padding">3</property> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> </child> + <child type="label"> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Advanced</property> + <style> + <class name="dim-label"/> + </style> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkButton" id="invite_button"> + <property name="label" translatable="yes">_Invite</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="halign">end</property> + <property name="use-underline">True</property> + <signal name="clicked" handler="_on_invite_clicked" swapped="no"/> + <style> + <class name="suggested-action"/> + </style> </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">3</property> + <property name="position">4</property> + </packing> </child> </object> </interface>
===================================== gajim/gtk/adhoc_muc.py ===================================== @@ -12,10 +12,6 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
-from typing import Dict # pylint: disable=unused-import -from typing import List # pylint: disable=unused-import -from typing import Tuple # pylint: disable=unused-import - import uuid import logging
@@ -31,104 +27,114 @@ log = logging.getLogger('gajim.gui.adhoc_muc')
-class AdhocMUC: - - # Keep a reference on windows so garbage collector don't restroy them - instances = [] # type: List[AdhocMUC] - - def __init__(self, account, jids, preselected=None): +class AdhocMUC(Gtk.ApplicationWindow): + def __init__(self, account, contact, preselected=None): """ This window is used to transform a one-to-one chat to a MUC. We do 2 things: first select the server and then make a guests list """ + Gtk.ApplicationWindow.__init__(self) + self.set_application(app.app) + self.set_position(Gtk.WindowPosition.CENTER) + self.set_type_hint(Gdk.WindowTypeHint.DIALOG) + self.set_show_menubar(False) + self.set_title(_('Adhoc Group Chat')) + self.set_default_size(500, 400) + self.set_resizable(True)
- self.instances.append(self) self.account = account - self.auto_jids = jids - self.preselected_jids = preselected - - self.xml = get_builder('adhoc_muc.ui') - self.window = self.xml.get_object('adhoc_muc_window') - - server_list = [] - self.servers = Gtk.ListStore(str) - self.xml.server_list_comboboxentry.set_model(self.servers) - cell = Gtk.CellRendererText() - self.xml.server_list_comboboxentry.pack_start(cell, True) - self.xml.server_list_comboboxentry.add_attribute(cell, 'text', 0) - - # get the muc server of our server + self.jid = contact.jid + self._preselected_jids = preselected self._client = app.get_client(account) - service_jid = self._client.get_module('MUC').service_jid - if service_jid is not None: - server_list.append(str(service_jid))
- # add servers or recently joined groupchats - recent_groupchats = app.settings.get_account_setting( - account, 'recent_groupchats').split() - for group_chat in recent_groupchats: - server = app.get_server_from_jid(group_chat) - if server not in server_list and not server.startswith('irc'): - server_list.append(server) - # add a default server - if not server_list: - server_list.append('conference.jabber.org') + self._ui = get_builder('adhoc_muc.ui') + self.add(self._ui.adhoc_box)
- for serv in server_list: - self.servers.append([serv]) + self._ui.description_label.set_text( + _('Invite someone to your chat with %s') % contact.name)
- self.xml.server_list_comboboxentry.set_active(0) + # Setup treeview: name, jid + self._ui.guests_store.set_sort_column_id(1, Gtk.SortType.ASCENDING) + self._ui.guests_treeview.get_selection().set_mode( + Gtk.SelectionMode.MULTIPLE)
- # set treeview - # name, jid + self._add_possible_invitees() + self._fill_server_list()
- self.xml.guests_store.set_sort_column_id(1, Gtk.SortType.ASCENDING) - self.xml.guests_treeview.get_selection().set_mode( - Gtk.SelectionMode.MULTIPLE) + self.connect('key-press-event', self._on_key_press) + self._ui.connect_signals(self) + self.show_all()
+ def _on_key_press(self, _widget, event): + if event.keyval == Gdk.KEY_Escape: + self.destroy() + + def _add_possible_invitees(self): for acc in app.settings.get_active_accounts(): client = app.get_client(acc) if client.is_zeroconf: continue for contact in client.get_module('Roster').iter_contacts(): jid = str(contact.jid) - if (jid not in self.auto_jids and - jid != str(self._client.get_own_jid().bare)): + # Add contact if it can be invited + if self._is_invitable(contact): icon = get_icon_name(contact.show.value) - iter_ = self.xml.guests_store.append( + iter_ = self._ui.guests_store.append( [icon, contact.name, jid]) # preselect treeview rows - if self.preselected_jids and jid in self.preselected_jids: - path = self.xml.guests_store.get_path(iter_) - self.xml.guests_treeview.get_selection().select_path( + if (self._preselected_jids and + jid in self._preselected_jids): + path = self._ui.guests_store.get_path(iter_) + self._ui.guests_treeview.get_selection().select_path( path)
- # show all - self.window.show_all() + def _is_invitable(self, contact): + # All contacts BUT the following can be invited: + # ourself, gateway contacts, zeroconf contacts + return (str(contact.jid) != str(self.jid) and + contact.jid != str(self._client.get_own_jid().bare) and + str(contact.jid) != app.get_jid_from_account(self.account) and + contact.show.value != 'error' and + not contact.is_gateway)
- self.xml.connect_signals(self) + def _fill_server_list(self): + servers = []
- def on_chat_to_muc_window_destroy(self, _widget): - self.instances.remove(self) + # Add own server to combobox + service_jid = self._client.get_module('MUC').service_jid + if service_jid is not None: + servers.append(str(service_jid))
- def on_chat_to_muc_window_key_press_event(self, _widget, event): - if event.keyval == Gdk.KEY_Escape: - self.window.destroy() + # Add servers or recently joined groupchats + recent_groupchats = app.get_recent_groupchats(self.account) + for groupchat in recent_groupchats: + if (groupchat.server not in servers and + not groupchat.server.startswith('irc')): + servers.append(groupchat.server)
- def on_invite_button_clicked(self, _widget): - row = self.xml.server_list_comboboxentry.get_child().get_displayed_row() - model = self.xml.server_list_comboboxentry.get_model() - server = model[row][0].strip() - if server == '': - return + # Add a default server (necessary?) + if not servers: + servers.append('conference.jabber.org')
+ for server in servers: + self._ui.server_store.append([server]) + + self._ui.server_combobox.set_active(0) + + def _on_server_combobox_entry_changed(self, _widget): + server = self._ui.server_entry.get_text() + self._ui.invite_button.set_sensitive(server != '') + + def _on_invite_clicked(self, _widget): + server = self._ui.server_entry.get_text() guest_list = [] - guests = self.xml.guests_treeview.get_selection().get_selected_rows() + guests = self._ui.guests_treeview.get_selection().get_selected_rows() for guest in guests[1]: - iter_ = self.xml.guests_store.get_iter(guest) - guest_list.append(self.xml.guests_store[iter_][2]) - for guest in self.auto_jids: - guest_list.append(guest) + iter_ = self._ui.guests_store.get_iter(guest) + guest_list.append(self._ui.guests_store[iter_][2]) + guest_list.append(self.jid) + + # Build group chat JID room_jid = f'{uuid.uuid4()}@{server}' app.automatic_rooms[self.account][room_jid] = {} app.automatic_rooms[self.account][room_jid]['invities'] = guest_list @@ -149,7 +155,4 @@ def on_invite_button_clicked(self, _widget):
app.interface.create_groupchat(self.account, room_jid, config) app.window.select_chat(self.account, room_jid) - self.window.destroy() - - def on_cancel_button_clicked(self, _widget): - self.window.destroy() + self.destroy()
===================================== gajim/gtk/const.py ===================================== @@ -139,5 +139,6 @@ def __str__(self): 'WorkspaceDialog': 'gajim.gui.workspace_dialog', 'RosterItemExchange': 'gajim.gui.roster_item_exchange', 'ServiceRegistration': 'gajim.gui.service_registration', - 'SynchronizeAccounts': 'gajim.gui.synchronize_accounts' + 'SynchronizeAccounts': 'gajim.gui.synchronize_accounts', + 'AdhocMUC': 'gajim.gui.adhoc_muc', }
===================================== gajim/gtk/controls/chat.py ===================================== @@ -52,7 +52,6 @@
from gajim import gui_menu_builder
-from gajim.gui.adhoc_muc import AdhocMUC from gajim.gui.call_widget import CallWidget from gajim.gui.const import TARGET_TYPE_URI_LIST from gajim.gui.const import ControlType @@ -319,7 +318,7 @@ def _on_information(self, _action, _param): app.window.contact_info(self.account, self.contact.jid)
def _on_invite_contacts(self, _action, _param): - AdhocMUC(self.account, [self.contact.jid]) + open_window('AdhocMUC', account=self.account, contact=self.contact)
def _on_send_chatstate(self, action, param): action.set_state(param)
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/commit/2f77f7f8164862c45eebad82b924fd757...