Daniel Brötzmann pushed to branch mainwindow at gajim / gajim
Commits: bc98008e by Daniel Brötzmann at 2021-03-03T11:14:17+01:00 Improve AccountPage and Roster
- - - - - be18925d by Daniel Brötzmann at 2021-03-03T11:19:18+01:00 ChatList: Improve popover menu
- - - - -
8 changed files:
- + gajim/data/gui/account_page.ui - gajim/data/gui/main.ui - gajim/data/gui/roster.ui - gajim/data/style/gajim.css - gajim/gtk/account_page.py - gajim/gtk/chat_list.py - gajim/gtk/roster.py - gajim/gui_menu_builder.py
Changes:
===================================== gajim/data/gui/account_page.ui ===================================== @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.38.2 --> +<interface> + <requires lib="gtk+" version="3.24"/> + <object class="GtkPaned" id="paned"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkBox" id="roster_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">3</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="spacing">12</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes">Contact List</property> + <style> + <class name="bold16"/> + </style> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkMenuButton" id="roster_menu_button"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="focus-on-click">False</property> + <property name="receives-default">True</property> + <property name="halign">end</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="icon-name">open-menu-symbolic</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack-type">end</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkSearchEntry" id="roster_search_entry"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="primary-icon-name">edit-find-symbolic</property> + <property name="primary-icon-activatable">False</property> + <property name="primary-icon-sensitive">False</property> + <property name="placeholder-text" translatable="yes">Search…</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="margin-start">6</property> + <property name="margin-end">6</property> + <property name="margin-top">12</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <style> + <class name="account-page-roster"/> + </style> + </object> + <packing> + <property name="resize">False</property> + <property name="shrink">False</property> + </packing> + </child> + <child> + <object class="GtkBox" id="account_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">center</property> + <property name="hexpand">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="spacing">12</property> + <child> + <object class="GtkLabel" id="account_label"> + <property name="visible">True</property> + <property name="can-focus">False</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="GtkButton" id="account_settings"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes">Account Settings…</property> + <signal name="clicked" handler="_on_account_settings" swapped="no"/> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="icon-name">preferences-other-symbolic</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</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">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <style> + <class name="account-page-box"/> + </style> + </object> + <packing> + <property name="resize">True</property> + <property name="shrink">True</property> + </packing> + </child> + </object> +</interface>
===================================== gajim/data/gui/main.ui ===================================== @@ -165,7 +165,7 @@ <property name="label">Workspace Label</property> <property name="ellipsize">end</property> <style> - <class name="large-header"/> + <class name="bold16"/> </style> </object> <packing>
===================================== gajim/data/gui/roster.ui ===================================== @@ -30,7 +30,6 @@ <child> <object class="GtkTreeViewColumn" id="contact_column"> <property name="sizing">fixed</property> - <property name="fixed-width">210</property> <property name="title">avatar</property> <property name="expand">True</property> <child>
===================================== gajim/data/style/gajim.css ===================================== @@ -132,9 +132,20 @@ background-color: darker(@theme_bg_color); margin: 0px 12px 0px 12px; } + /* Account Page */ .account-page { - background: @theme_bg_color; + background: transparent; +} +.account-page-roster { + padding: 12px; +} +.account-page-box { + padding: 18px; +} +/* Roster */ +.roster treeview { + padding: 0 3px; }
/*Middle Grid*/ @@ -416,9 +427,6 @@ infobar.error > revealer > box { .start-chat-row:not(.activatable) label { color: @insensitive_fg_color; } .start-chat-row:focus { outline: none; }
-/* Roster */ -.roster treeview { padding-left: 4px; } - /* GroupChatRoster */ .groupchat-roster { border-left: 1px solid; border-color: @borders; }
===================================== gajim/gtk/account_page.py ===================================== @@ -15,55 +15,41 @@ from gi.repository import Gtk
from gajim.common import app -from gajim.common.i18n import _
from .roster import Roster from .status_selector import StatusSelector +from .util import get_builder from .util import open_window
class AccountPage(Gtk.Box): def __init__(self, account): Gtk.Box.__init__(self) - self.get_style_context().add_class('account-page') - self._account = account
- self._account_label = Gtk.Label() - self._account_label.get_style_context().add_class('large-header') + self._ui = get_builder('account_page.ui') + self.add(self._ui.paned)
self._status_selector = StatusSelector() self._status_selector.set_halign(Gtk.Align.CENTER) - - settings_button = Gtk.Button(label=_('Settings')) - settings_button.set_halign(Gtk.Align.CENTER) - settings_button.connect('clicked', self._on_settings) - - box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=18) - box.set_halign(Gtk.Align.CENTER) - box.set_valign(Gtk.Align.CENTER) - box.set_hexpand(True) - box.add(self._account_label) - box.add(settings_button) - box.add(self._status_selector) + self._ui.account_box.add(self._status_selector)
self._roster = Roster(account) - hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12) - hbox.add(self._roster) - hbox.add(box) + self._ui.roster_box.add(self._roster)
- self.add(hbox) + self._ui.connect_signals(self) self.show_all() + self.update()
- def _on_settings(self, _button): + def _on_account_settings(self, _button): window = open_window('AccountsWindow') window.select_account(self._account)
def update(self): account_label = app.settings.get_account_setting( self._account, 'account_label') - self._account_label.set_text(account_label) + self._ui.account_label.set_text(account_label) self._status_selector.update()
def process_event(self, event):
===================================== gajim/gtk/chat_list.py ===================================== @@ -1,5 +1,6 @@ import logging
+from gi.repository import Gdk from gi.repository import GLib from gi.repository import Gtk
@@ -14,7 +15,6 @@
from gajim.gui_menu_builder import get_chat_list_row_menu
-from .tooltips import RosterTooltip from .util import get_builder
log = logging.getLogger('gajim.gui.chatlist') @@ -32,7 +32,6 @@ def __init__(self, workspace_id): self.set_filter_func(self._filter_func) self.set_header_func(self._header_func) self.set_sort_func(self._sort_func) - self.set_has_tooltip(True) self._set_placeholder()
self.connect('destroy', self._on_destroy) @@ -340,13 +339,21 @@ def is_pinned(self):
def _on_button_press(self, _widget, event): if event.button == 3: # right click - self._popup_menu() + self._popup_menu(event)
- def _popup_menu(self): + def _popup_menu(self, event): menu = get_chat_list_row_menu( self.workspace_id, self.account, self.jid, self._pinned) + + rectangle = Gdk.Rectangle() + rectangle.x = event.x + rectangle.y = event.y + rectangle.width = rectangle.height = 1 + popover = Gtk.Popover.new_from_model(self, menu) - popover.set_position(Gtk.PositionType.BOTTOM) + popover.set_relative_to(self) + popover.set_position(Gtk.PositionType.RIGHT) + popover.set_pointing_to(rectangle) popover.popup()
def toggle_pinned(self):
===================================== gajim/gtk/roster.py ===================================== @@ -3,6 +3,7 @@ from typing import Optional from enum import IntEnum
+from gi.repository import Gdk from gi.repository import GLib from gi.repository import Gtk from gi.repository import GObject @@ -13,6 +14,8 @@ from gajim.common.const import StyleAttr from gajim.common.i18n import _
+from gajim.gui_menu_builder import get_roster_menu + from .util import EventHelper from .util import get_builder
@@ -43,7 +46,8 @@ class Roster(Gtk.ScrolledWindow, EventHelper): def __init__(self, account): Gtk.ScrolledWindow.__init__(self) EventHelper.__init__(self) - self.set_size_request(300, -1) + self.set_size_request(200, -1) + self.set_vexpand(True) self.get_style_context().add_class('roster')
self._account = account @@ -80,8 +84,8 @@ def _on_roster_row_activated(self, _treeview, path, _column): # This is a group row return
- nick = self._store[iter_][Column.JID_OR_GROUP] - self.emit('row-activated', nick) + jid = self._store[iter_][Column.JID_OR_GROUP] + self.emit('row-activated', jid)
def _on_roster_button_press_event(self, treeview, event): if event.button not in (2, 3): @@ -97,13 +101,13 @@ def _on_roster_button_press_event(self, treeview, event): # Group row return
- nick = self._store[iter_][Column.JID_OR_GROUP] + jid = self._store[iter_][Column.JID_OR_GROUP]
if event.button == 3: # right click - self._show_contact_menu(nick) + self._show_contact_menu(jid, treeview, event)
if event.button == 2: # middle click - self.emit('row-activated', nick) + self.emit('row-activated', jid)
@staticmethod def _on_focus_out(treeview, _param): @@ -112,15 +116,26 @@ def _on_focus_out(treeview, _param): def _on_theme_update(self, _event): self.redraw()
- def _show_contact_menu(self, nick): - pass + def _show_contact_menu(self, jid, treeview, event): + menu = get_roster_menu(self._account, jid) + + rectangle = Gdk.Rectangle() + rectangle.x = event.x + rectangle.y = event.y + rectangle.width = rectangle.height = 1 + + popover = Gtk.Popover.new_from_model(self, menu) + popover.set_relative_to(treeview) + popover.set_position(Gtk.PositionType.RIGHT) + popover.set_pointing_to(rectangle) + popover.popup()
def _on_destroy(self, _roster): self._contact_refs = {} self._group_refs = {} self._roster.set_model(None) self._roster = None - # Store keeps a ref on the object if we dont unset the sort func + # Store keeps a ref on the object if we don’t unset the sort func self._store.set_sort_func(Column.TEXT, print) self._store.clear() self._store = None @@ -188,13 +203,15 @@ def _add_contact(self, contact): # Avatar surface = contact.get_avatar(AvatarSize.CHAT, self.get_scale_factor())
+ jid = str(contact.jid) + # TODO: Multiple groups per contact ? iter_ = self._store.append( - group_iter, (surface, contact.name, True, str(contact.jid))) - self._contact_refs[contact.jid] = Gtk.TreeRowReference( + group_iter, (surface, contact.name, True, jid)) + self._contact_refs[jid] = Gtk.TreeRowReference( self._store, self._store.get_path(iter_))
self.draw_groups() - self.draw_contact(contact.jid) + self.draw_contact(jid)
if (group_path is not None and self._roster.get_model() is not None): @@ -224,14 +241,13 @@ def draw_contact(self, jid): if not iter_: return
- client = app.get_client(self._account) - contact = client.get_module('Contacts').get_contact(jid) + contact = self._client.get_module('Contacts').get_contact(jid)
self.draw_avatar(contact) self._store[iter_][Column.TEXT] = GLib.markup_escape_text(contact.name)
def draw_avatar(self, contact): - iter_ = self._get_contact_iter(contact.jid) + iter_ = self._get_contact_iter(str(contact.jid)) if iter_ is None: return
===================================== gajim/gui_menu_builder.py ===================================== @@ -796,8 +796,25 @@ def get_conv_context_menu(account, uri): return menu
+def get_roster_menu(account, jid): + menu_items = [ + ('show-contact-info', _('Contact Info')), + ] + menu = Gio.Menu() + for item in menu_items: + action, label = item + action = f'win.{action}' + menuitem = Gio.MenuItem.new(label, action) + variant_list = GLib.Variant( + 'as', [account, str(jid)]) + menuitem.set_action_and_target_value(action, variant_list) + menu.append_item(menuitem) + + return menu + + def get_chat_list_row_menu(workspace_id, account, jid, pinned): - toggle_label = _('Unpin Conversation') if pinned else _('Pin Conversation') + toggle_label = _('Unpin Chat') if pinned else _('Pin Chat') menu_items = [ ('toggle-chat-pinned', toggle_label), (_('Move Chat'), []),
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/06f2b6288c9ce8bf9dc4d521ed4fcc0c...