Philipp Hörist pushed to branch server_info at gajim / gajim
Commits: 1e5e17b4 by wurstsalat at 2022-09-24T21:03:36+02:00 imprv: Emojis: Extract codepoints for all emoji variants
- - - - - ed35915f by wurstsalat at 2022-09-24T21:03:43+02:00 imprv: Avatars: Use PangoCairo for generate_avatar
Fixes #10960
- - - - - 938d79fb by wurstsalat at 2022-09-24T21:44:10+02:00 chore: Remove unused method from emoji_data
- - - - - a782329f by wurstsalat at 2022-09-25T00:08:03+02:00 fix: CreateGroupchatWindow: Fix Create button state when switching MUC type
Fixes #11162
- - - - - e3bba1d5 by wurstsalat at 2022-09-25T12:39:23+02:00 imprv: Emojis: Improve shortcode usability
- - - - - 117a4b92 by wurstsalat at 2022-09-25T12:57:50+02:00 fix: AccountPage: Disable Ad-Hoc Commands button when offline
Fixes #11167
- - - - - ac898ebb by wurstsalat at 2022-09-25T12:58:09+02:00 chore: Fix typo in AccountDisconnected event
- - - - - 678579ad by wurstsalat at 2022-09-25T13:11:15+02:00 fix: When removing a chat, clear view only if it's currently loaded
Fixes #11164
- - - - - 3722623b by mesonium at 2022-09-25T16:25:00+00:00 chore: Update package link for Fedora
- - - - - 7d01e618 by Philipp Hörist at 2022-09-25T22:00:03+02:00 refactor: Main: Move action definition to const module
- - - - - 05457d58 by Philipp Hörist at 2022-09-25T22:01:00+02:00 feat: ServerInfo: Add TLS version and cipher suite
- - - - -
23 changed files:
- README.md - gajim/common/application.py - gajim/common/client.py - gajim/common/const.py - gajim/common/events.py - gajim/data/gui/account_page.ui - gajim/data/gui/server_info.ui - gajim/gajim.py - gajim/gtk/account_page.py - gajim/gtk/accounts.py - gajim/gtk/avatar.py - gajim/gtk/builder.pyi - gajim/gtk/chat_page.py - gajim/gtk/const.py - gajim/gtk/emoji_data.py - gajim/gtk/emoji_data.pyi - gajim/gtk/emoji_data_gtk.py - gajim/gtk/groupchat_creation.py - gajim/gtk/main.py - gajim/gtk/remove_account.py - gajim/gtk/server_info.py - gajim/gtk/status_icon.py - gajim/gtk/workspace_dialog.py
Changes:
===================================== README.md ===================================== @@ -55,7 +55,7 @@ #### Packages
- [Arch Linux](https://www.archlinux.org/packages/community/any/gajim/) - [Debian](https://packages.debian.org/stable/gajim) -- [Fedora](https://apps.fedoraproject.org/packages/gajim) +- [Fedora](https://packages.fedoraproject.org/pkgs/gajim/) - [Ubuntu](https://packages.ubuntu.com/gajim) - [FreeBSD](https://www.freshports.org/net-im/gajim/)
===================================== gajim/common/application.py ===================================== @@ -39,7 +39,7 @@ from gajim.common import passwords from gajim.common.commands import ChatCommands from gajim.common.dbus import logind -from gajim.common.events import AccountDisonnected +from gajim.common.events import AccountDisconnected from gajim.common.events import AllowGajimUpdateCheck from gajim.common.events import GajimUpdateAvailable from gajim.common.client import Client @@ -167,7 +167,7 @@ def start_shutdown(self, *args: Any, **kwargs: Any) -> None: self._quit_app() return
- def _on_disconnect(event: AccountDisonnected) -> None: + def _on_disconnect(event: AccountDisconnected) -> None: accounts_to_disconnect.pop(event.account) if not accounts_to_disconnect: self._quit_app()
===================================== gajim/common/client.py ===================================== @@ -36,7 +36,7 @@ from gajim.common import passwords from gajim.common.events import AccountConnected from gajim.common.events import MessageSent -from gajim.common.events import AccountDisonnected +from gajim.common.events import AccountDisconnected from gajim.common.events import PasswordRequired from gajim.common.events import PlainConnection from gajim.common.events import SignedIn @@ -316,7 +316,7 @@ def _after_disconnect(self) -> None: self._destroy_client = False self._create_client()
- app.ged.raise_event(AccountDisonnected(account=self._account)) + app.ged.raise_event(AccountDisconnected(account=self._account))
def _on_connection_failed(self, _client: NBXMPPClient,
===================================== gajim/common/const.py ===================================== @@ -1184,3 +1184,12 @@ def __lt__(self, other: Union[PresenceShowExt, PresenceShow]) -> bool: if not isinstance(other, PresenceShow): # pyright: ignore return NotImplemented return True + + +# Replace keys with Gio.TlsProtocolVersion enum once +# we require GLib >= 2.69 +TLS_VERSION_STRINGS = { + 3: '1.1', + 4: '1.2', + 5: '1.3', +}
===================================== gajim/common/events.py ===================================== @@ -89,7 +89,7 @@ class AccountConnected(ApplicationEvent):
@dataclass -class AccountDisonnected(ApplicationEvent): +class AccountDisconnected(ApplicationEvent): name: str = field(init=False, default='account-disconnected') account: str
===================================== gajim/data/gui/account_page.ui ===================================== @@ -229,7 +229,7 @@ </packing> </child> <child> - <object class="GtkButton"> + <object class="GtkButton" id="adhoc_commands_button"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="receives-default">True</property>
===================================== gajim/data/gui/server_info.ui ===================================== @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.38.2 --> +<!-- Generated with glade 3.40.0 --> <interface> <requires lib="gtk+" version="3.22"/> <object class="GtkNotebook" id="server_info_notebook"> @@ -151,7 +151,7 @@ </packing> </child> <child> - <!-- n-columns=2 n-rows=7 --> + <!-- n-columns=2 n-rows=9 --> <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -183,7 +183,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">5</property> + <property name="top-attach">7</property> </packing> </child> <child> @@ -196,7 +196,7 @@ </object> <packing> <property name="left-attach">1</property> - <property name="top-attach">5</property> + <property name="top-attach">7</property> </packing> </child> <child> @@ -211,7 +211,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">6</property> + <property name="top-attach">8</property> </packing> </child> <child> @@ -224,7 +224,7 @@ </object> <packing> <property name="left-attach">1</property> - <property name="top-attach">6</property> + <property name="top-attach">8</property> </packing> </child> <child> @@ -351,6 +351,58 @@ <property name="top-attach">3</property> </packing> </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">end</property> + <property name="label" translatable="yes">TLS Version</property> + <style> + <class name="dim-label"/> + </style> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">5</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">end</property> + <property name="label" translatable="yes">Cipher Suite</property> + <style> + <class name="dim-label"/> + </style> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">6</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="tls_version"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">start</property> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">5</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="cipher_suite"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">start</property> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">6</property> + </packing> + </child> <style> <class name="margin-18"/> </style>
===================================== gajim/gajim.py ===================================== @@ -66,6 +66,7 @@ def _check_required_deps() -> None: 'GtkSource': '4', 'GObject': '2.0', 'Pango': '1.0', + 'PangoCairo': '1.0', 'Soup': '2.4'}) except ValueError as error: sys.exit('Missing dependency: %s' % error)
===================================== gajim/gtk/account_page.py ===================================== @@ -14,6 +14,8 @@
from __future__ import annotations
+from typing import Union + from gi.repository import Gdk from gi.repository import Gio from gi.repository import Gtk @@ -23,6 +25,8 @@ from gajim.common import app from gajim.common import ged from gajim.common.const import AvatarSize +from gajim.common.events import AccountConnected +from gajim.common.events import AccountDisconnected from gajim.common.events import SubscribePresenceReceived from gajim.common.events import UnsubscribedPresenceReceived from gajim.common.events import MucInvitation @@ -88,6 +92,8 @@ def __init__(self, account: str) -> None: ged.GUI1, self._unsubscribed_received), ('muc-invitation', ged.GUI1, self._muc_invitation_received), ('muc-decline', ged.GUI1, self._muc_invitation_declined), + ('account-connected', ged.GUI2, self._on_account_state), + ('account-disconnected', ged.GUI2, self._on_account_state), ]) # pylint: enable=line-too-long
@@ -109,6 +115,16 @@ def _on_adhoc_commands(self, _button: Gtk.Button) -> None: server_jid = JID.from_string(self._jid).domain open_window('AdHocCommands', account=self._account, jid=server_jid)
+ def _on_account_state(self, + event: Union[AccountConnected, AccountDisconnected] + ) -> None: + + if event.account != self._account: + return + + self._ui.adhoc_commands_button.set_sensitive( + app.account_is_connected(event.account)) + def _on_search_changed(self, widget: Gtk.SearchEntry) -> None: text = widget.get_text().lower() self._roster.set_search_string(text)
===================================== gajim/gtk/accounts.py ===================================== @@ -30,7 +30,7 @@ from gajim.common import app from gajim.common import ged from gajim.common import passwords -from gajim.common.events import AccountDisonnected +from gajim.common.events import AccountDisconnected from gajim.common.i18n import _ from gajim.common.i18n import Q_ from gajim.common.settings import AllSettingsT @@ -541,7 +541,7 @@ def _on_enable_switch(self, state: bool, account: str ) -> int: - def _on_disconnect(event: AccountDisonnected) -> None: + def _on_disconnect(event: AccountDisconnected) -> None: if event.account != account: return app.ged.remove_event_handler('account-disconnected',
===================================== gajim/gtk/avatar.py ===================================== @@ -26,6 +26,8 @@
from gi.repository import Gdk from gi.repository import GdkPixbuf +from gi.repository import Pango +from gi.repository import PangoCairo import cairo from nbxmpp.protocol import JID
@@ -38,8 +40,7 @@ from gajim.common.const import StyleAttr
from .const import DEFAULT_WORKSPACE_COLOR -from .emoji_data import is_emoji -from .emoji_data import get_emoji_font +from .emoji_data_gtk import get_emoji_data from .util import load_icon_surface from .util import load_pixbuf from .util import text_to_color @@ -56,6 +57,23 @@ cairo.ImageSurface]]
+def generate_avatar_letter(text: str) -> str: + if not text: + return '' + + if text[0].isalpha(): + return text[0].upper() + + emoji_data = get_emoji_data() + + # Max (arbitrary) length for emoji ZJW sequences: 11 + for length in range(11, 0, -1): + if text[:length] in emoji_data.values(): + return text[:length] + + return text[0].upper() + + def generate_avatar(letters: str, color: tuple[float, float, float], size: int, @@ -70,7 +88,7 @@ def generate_avatar(letters: str,
width = size height = size - font_size = size * 0.5 + font_size = size * 0.4
# Set up surface surface = cairo.ImageSurface(cairo.Format.ARGB32, width, height) @@ -81,26 +99,25 @@ def generate_avatar(letters: str, context.fill()
# Draw letters - if is_emoji(letters): - font_face = get_emoji_font() - else: - font_face = 'sans-serif' - context.select_font_face(font_face, - cairo.FontSlant.NORMAL, - cairo.FontWeight.NORMAL) - context.set_font_size(font_size) - extends = context.text_extents(letters) - x_bearing = extends.x_bearing - y_bearing = extends.y_bearing - ex_width = extends.width - ex_height = extends.height - - x_pos = width / 2 - (ex_width / 2 + x_bearing) - y_pos = height / 2 - (ex_height / 2 + y_bearing) + layout = PangoCairo.create_layout(context) + layout.set_text(generate_avatar_letter(letters)) + + description = Pango.FontDescription() + description.set_family('Sans') + description.set_size(int(font_size * Pango.SCALE)) + + layout.set_font_description(description) + + _ink_rect, logical_rect = layout.get_extents() + layout_width = logical_rect.width / Pango.SCALE + layout_height = logical_rect.height / Pango.SCALE + x_pos = (width - layout_width) / 2 + y_pos = (height - layout_height) / 2 + context.move_to(x_pos, y_pos) context.set_source_rgb(0.95, 0.95, 0.95) context.set_operator(cairo.Operator.OVER) - context.show_text(letters) + PangoCairo.show_layout(context, layout)
return context.get_target() # pyright: ignore
@@ -399,7 +416,7 @@ def get_surface(self, name = contact.name color_string = str(contact.jid)
- letter = self._generate_letter(name) + letter = generate_avatar_letter(name) surface = generate_default_avatar( letter, color_string, size, scale, style=style) if show is not None: @@ -441,7 +458,7 @@ def get_muc_surface(self,
con = app.connections[account] name = get_groupchat_name(con, jid) - letter = self._generate_letter(name) + letter = generate_avatar_letter(name) surface = generate_default_avatar(letter, str(jid), size, scale, style) self._cache[jid][(size, scale, None)] = surface return surface @@ -469,9 +486,8 @@ def get_workspace_surface(self, app.settings.set_workspace_setting(workspace_id, 'avatar_sha', '')
rgba = make_rgba(color or DEFAULT_WORKSPACE_COLOR) - letter = name[:1].upper() surface = make_workspace_avatar( - letter, rgba_to_float(rgba), size, scale) + name, rgba_to_float(rgba), size, scale) self._cache[workspace_id][(size, scale, None)] = surface return surface
@@ -571,10 +587,3 @@ def _get_avatar_from_storage(self, if surface is None: return None return clip(surface, style) - - @staticmethod - def _generate_letter(name: str) -> str: - for letter in name: - if letter.isalpha(): - return letter.capitalize() - return name[0].capitalize()
===================================== gajim/gtk/builder.pyi ===================================== @@ -18,6 +18,7 @@ class AccountPageBuilder(Builder): avatar_image: Gtk.Image account_label: Gtk.Label account_action_box: Gtk.Box + adhoc_commands_button: Gtk.Button status_message_box: Gtk.Box
===================================== gajim/gtk/chat_page.py ===================================== @@ -283,10 +283,16 @@ def remove_chat(self, account: str, jid: JID) -> None: self._chat_list_stack.remove_chat(workspace_id, account, jid) return
- def _on_chat_removed(self, _chat_list: ChatList, account: str, jid: JID, - type_: str) -> None: + def _on_chat_removed(self, + _chat_list: ChatList, + account: str, + jid: JID, + type_: str + ) -> None: + + if self._chat_control.is_loaded(account, jid): + self._chat_control.clear()
- self._chat_control.clear() if type_ == 'groupchat': client = app.get_client(account) client.get_module('MUC').leave(jid)
===================================== gajim/gtk/const.py ===================================== @@ -216,6 +216,40 @@ def __str__(self): ('muc-request-voice', None, False), ('scroll-view-up', None, True), ('scroll-view-down', None, True), + ('change-nickname', None, True), + ('change-subject', None, True), + ('escape', None, True), + ('close-tab', None, True), + ('switch-next-tab', None, True), + ('switch-prev-tab', None, True), + ('switch-next-unread-tab', None, True), + ('switch-prev-unread-tab', None, True), + ('switch-tab-1', None, True), + ('switch-tab-2', None, True), + ('switch-tab-3', None, True), + ('switch-tab-4', None, True), + ('switch-tab-5', None, True), + ('switch-tab-6', None, True), + ('switch-tab-7', None, True), + ('switch-tab-8', None, True), + ('switch-tab-9', None, True), + ('switch-workspace-1', None, True), + ('switch-workspace-2', None, True), + ('switch-workspace-3', None, True), + ('switch-workspace-4', None, True), + ('switch-workspace-5', None, True), + ('switch-workspace-6', None, True), + ('switch-workspace-7', None, True), + ('switch-workspace-8', None, True), + ('switch-workspace-9', None, True), + ('toggle-chat-list', None, True), + ('add-workspace', 's', True), + ('edit-workspace', 's', True), + ('remove-workspace', 's', True), + ('activate-workspace', 's', True), + ('add-chat', 'a{sv}', True), + ('add-group-chat', 'as', True), + ('add-to-roster', 'a{sv}', True), ]
===================================== gajim/gtk/emoji_data.py ===================================== @@ -17,7 +17,6 @@ from typing import Optional
import re -import sys import weakref from enum import IntEnum from collections import OrderedDict @@ -62,12 +61,6 @@ def get_emoji_pixbuf(codepoints: str) -> Optional[GdkPixbuf.Pixbuf]: return pixbuf
-def get_emoji_font() -> str: - if sys.platform == 'win32': - return 'Segoe UI Emoji' - return 'Noto Color Emoji' - - class EmojiData(OrderedDict): def __getitem__(self, key): try:
===================================== gajim/gtk/emoji_data.pyi ===================================== @@ -22,7 +22,6 @@ class Emoji(IntEnum): ...
def is_emoji(codepoints: str) -> bool: ... -def get_emoji_font() -> str: ... def get_emoji_pixbuf(codepoints: str) -> GdkPixbuf.Pixbuf: ...
class EmojiData(OrderedDict):
===================================== gajim/gtk/emoji_data_gtk.py ===================================== @@ -26,6 +26,40 @@
log = logging.getLogger('gajim.gui.emoji_data_gtk')
+SKIN_TONE_MODIFIERS = { + 127995: 'light skin tone', + 127996: 'medium-light skin tone', + 127997: 'medium skin tone', + 127998: 'medium-dark skin tone', + 127999: 'dark skin tone' +} + + +def generate_unicode_sequence(c_sequence: list[int]) -> str: + ''' + Generates a unicode sequence from a list of codepoints + ''' + u_sequence = '' + for codepoint in c_sequence: + u_sequence += chr(codepoint) + return u_sequence + + +def replace_skin_tone_placeholder(c_sequence: list[int], + modifier: int + ) -> list[int]: + + ''' + Replaces GTKs placeholder '0' for skin tone modifiers + with a given modifier + ''' + c_mod_sequence: list[int] = [] + for codepoint in c_sequence: + if codepoint == 0: + codepoint = modifier + c_mod_sequence.append(codepoint) + return c_mod_sequence +
def get_emoji_data() -> dict[str, str]: return emoji_data @@ -46,33 +80,62 @@ def load_emoji_data() -> dict[str, str]: # We have to store bytes_data in a variable to make sure Python # keeps it until it is processed. bytes_data = bytes_.get_data() - - def _pass(_user_data: Any) -> None: - pass - - variant = GLib.Variant.new_from_data( - GLib.VariantType('a(auss)'), - bytes_data, - True, - _pass) - - emoji_data_dict: dict[str, str] = {} - index = 0 - for _item in variant: - emoji = variant.get_child_value(index) - points = emoji.get_child_value(0) - codepoint = points.get_child_value(0).get_uint32() - shortcode = emoji.get_child_value(1).get_string() - emoji_data_dict[shortcode] = chr(codepoint) - index += 1 - - # Add commonly used shortcodes - emoji_data_dict['+1'] = '\U0001F44D' - emoji_data_dict['-1'] = '\U0001F44E' - return emoji_data_dict - - except GLib.Error: + except GLib.Error as error: + log.warning('Loading emoji resources failed: %s', error) return {}
- -emoji_data = load_emoji_data() + def _pass(_user_data: Any) -> None: + pass + + variant = GLib.Variant.new_from_data( + GLib.VariantType('a(auss)'), + bytes_data, + True, + _pass) + + emoji_data_dict: dict[str, str] = {} + for c_sequence, shortcode, _ in variant: + # Example item: + # ([128105, 0, 8205, 10084, 65039, 8205, 128104, 0], + # 'couple with heart: woman, man', + # 'couple'), + # GTK sets '0' as a placeholder for skin tone modifiers, see: + # https://gitlab.gnome.org/GNOME/gtk/-/blob/main/gtk/emoji/ + # convert-emoji.c + + # Replace colon by comma to improve emoji shortcode usability + shortcode = shortcode.replace(':', ',') + + if 0 not in c_sequence: + # No skin tone modifiers present + u_sequence = generate_unicode_sequence(c_sequence) + emoji_data_dict[shortcode] = u_sequence + continue + + # Filter out 0 in order to generate basic (yellow) variation + c_basic_sequence = [c for c in c_sequence if c != 0] + u_sequence = generate_unicode_sequence(c_basic_sequence) + emoji_data_dict[shortcode] = u_sequence + + # Add variations with skin tone modifiers + for modifier, mod_shortcode in SKIN_TONE_MODIFIERS.items(): + new_shortcode = f'{shortcode}, {mod_shortcode}' + c_mod_sequence = replace_skin_tone_placeholder( + c_sequence, modifier) + u_mod_sequence = generate_unicode_sequence(c_mod_sequence) + emoji_data_dict[new_shortcode] = u_mod_sequence + + # Add commonly used shortcodes + emoji_data_dict['+1'] = '\U0001F44D' + emoji_data_dict['-1'] = '\U0001F44E' + + emoji_data_dict = dict(sorted(emoji_data_dict.items())) + + return emoji_data_dict + + +try: + emoji_data = load_emoji_data() +except Exception as err: + log.warning('Unable to load emoji data: %s', err) + emoji_data = {}
===================================== gajim/gtk/groupchat_creation.py ===================================== @@ -29,7 +29,7 @@ from gajim.common.const import MUC_CREATION_EXAMPLES from gajim.common.const import MUC_DISCO_ERRORS from gajim.common.events import AccountConnected -from gajim.common.events import AccountDisonnected +from gajim.common.events import AccountDisconnected from gajim.common.ged import EventHelper from gajim.common.helpers import get_random_muc_localpart from gajim.common.helpers import validate_jid @@ -85,7 +85,7 @@ def __init__(self, account: Optional[str]) -> None: self.set_focus(self._ui.address_entry)
def _on_account_state(self, - _event: Union[AccountConnected, AccountDisonnected] + _event: Union[AccountConnected, AccountDisconnected] ) -> None: any_account_connected = app.get_number_of_connected_accounts() > 0 if any_account_connected: @@ -231,6 +231,10 @@ def _update_entry_completion(self, entry: Gtk.Entry, text: str) -> None:
def _on_public_private_toggled(self, _radiobutton: Gtk.RadioButton) -> None: is_public = self._ui.public_radio.get_active() + if is_public: + self._validate_jid(self._ui.address_entry.get_text()) + else: + self._ui.create_button.set_sensitive(True) self._ui.address_label.set_visible(is_public) self._ui.address_entry.set_visible(is_public)
===================================== gajim/gtk/main.py ===================================== @@ -53,7 +53,6 @@ from .dialogs import ConfirmationCheckDialog from .builder import get_builder from .util import get_app_window -from .util import get_key_theme from .util import resize_window from .util import restore_main_window_position from .util import save_main_window_position @@ -81,8 +80,8 @@ def __init__(self) -> None: app.window = self
self._add_actions() - self._add_actions2() self._add_stateful_actions() + self._connect_actions()
self._startup_finished: bool = False
@@ -303,22 +302,11 @@ def _on_muc_added(self, event: events.MucAdded) -> None: self.add_group_chat(event.account, event.jid)
def _add_actions(self) -> None: - actions = [ - ('add-workspace', 's', self._add_workspace), - ('edit-workspace', 's', self._edit_workspace), - ('remove-workspace', 's', self._remove_workspace), - ('activate-workspace', 's', self._activate_workspace), - ('add-chat', 'a{sv}', self._add_chat), - ('add-group-chat', 'as', self._add_group_chat), - ('add-to-roster', 'a{sv}', self._add_to_roster), - ] - - for action in actions: - action_name, variant, func = action - if variant is not None: - variant = GLib.VariantType.new(variant) - act = Gio.SimpleAction.new(action_name, variant) - act.connect('activate', func) + for action, variant_type, enabled in MAIN_WIN_ACTIONS: + if variant_type is not None: + variant_type = GLib.VariantType(variant_type) + act = Gio.SimpleAction.new(action, variant_type) + act.set_enabled(enabled) self.add_action(act)
def _add_stateful_actions(self) -> None: @@ -347,56 +335,47 @@ def _add_stateful_actions(self) -> None:
self.add_action(action)
- def _add_actions2(self) -> None: - for action, variant_type, enabled in MAIN_WIN_ACTIONS: - if variant_type is not None: - variant_type = GLib.VariantType(variant_type) - act = Gio.SimpleAction.new(action, variant_type) - act.set_enabled(enabled) - self.add_action(act) - + def _connect_actions(self) -> None: actions = [ - 'change-nickname', - 'change-subject', - 'escape', - 'close-tab', - 'switch-next-tab', - 'switch-prev-tab', - 'switch-next-unread-tab', - 'switch-prev-unread-tab', - 'switch-tab-1', - 'switch-tab-2', - 'switch-tab-3', - 'switch-tab-4', - 'switch-tab-5', - 'switch-tab-6', - 'switch-tab-7', - 'switch-tab-8', - 'switch-tab-9', - 'switch-workspace-1', - 'switch-workspace-2', - 'switch-workspace-3', - 'switch-workspace-4', - 'switch-workspace-5', - 'switch-workspace-6', - 'switch-workspace-7', - 'switch-workspace-8', - 'switch-workspace-9', - 'toggle-chat-list', + ('change-nickname', self._on_action), + ('change-subject', self._on_action), + ('escape', self._on_action), + ('close-tab', self._on_action), + ('switch-next-tab', self._on_action), + ('switch-prev-tab', self._on_action), + ('switch-next-unread-tab', self._on_action), + ('switch-prev-unread-tab', self._on_action), + ('switch-tab-1', self._on_action), + ('switch-tab-2', self._on_action), + ('switch-tab-3', self._on_action), + ('switch-tab-4', self._on_action), + ('switch-tab-5', self._on_action), + ('switch-tab-6', self._on_action), + ('switch-tab-7', self._on_action), + ('switch-tab-8', self._on_action), + ('switch-tab-9', self._on_action), + ('switch-workspace-1', self._on_action), + ('switch-workspace-2', self._on_action), + ('switch-workspace-3', self._on_action), + ('switch-workspace-4', self._on_action), + ('switch-workspace-5', self._on_action), + ('switch-workspace-6', self._on_action), + ('switch-workspace-7', self._on_action), + ('switch-workspace-8', self._on_action), + ('switch-workspace-9', self._on_action), + ('toggle-chat-list', self._on_action), + ('add-workspace', self._add_workspace), + ('edit-workspace', self._edit_workspace), + ('remove-workspace', self._remove_workspace), + ('activate-workspace', self._activate_workspace), + ('add-chat', self._add_chat), + ('add-group-chat', self._add_group_chat), + ('add-to-roster', self._add_to_roster), ]
- disabled_for_emacs = ( - 'close-tab' - ) - - key_theme = get_key_theme() - - for action in actions: - if key_theme == 'Emacs' and action in disabled_for_emacs: - continue - act = Gio.SimpleAction.new(action, None) - act.connect('activate', self._on_action) - self.add_action(act) + for action, func in actions: + act = self.get_action(action) + act.connect('activate', func)
def _on_action(self, action: Gio.SimpleAction,
===================================== gajim/gtk/remove_account.py ===================================== @@ -25,7 +25,7 @@ from gajim.common import app from gajim.common import ged from gajim.common.events import AccountConnected -from gajim.common.events import AccountDisonnected +from gajim.common.events import AccountDisconnected from gajim.common.i18n import _ from gajim.common.helpers import to_user_string from gajim.common.helpers import event_filter @@ -83,7 +83,7 @@ def _on_account_connected(self, _event: AccountConnected) -> None: self._set_remove_from_server_checkbox()
@event_filter(['account']) - def _on_account_disconnected(self, _event: AccountDisonnected) -> None: + def _on_account_disconnected(self, _event: AccountDisconnected) -> None: self._set_remove_from_server_checkbox()
if self._account_removed:
===================================== gajim/gtk/server_info.py ===================================== @@ -35,6 +35,7 @@
from gajim.common import app from gajim.common import ged +from gajim.common.const import TLS_VERSION_STRINGS from gajim.common.events import ServerDiscoReceived from gajim.common.helpers import open_uri from gajim.common.i18n import _ @@ -148,6 +149,13 @@ def _add_connection_info(self) -> None: self._ui.websocket.set_visible(visible) self._ui.websocket.set_text(address.uri or '')
+ tls_version = TLS_VERSION_STRINGS.get(nbxmpp_client.tls_version) + self._ui.tls_version.set_text(tls_version or _('Not available')) + + visible = nbxmpp_client.ciphersuite is not None + self._ui.cipher_suite.set_text(nbxmpp_client.ciphersuite or + _('Not available')) + def _add_contact_addresses(self, dataforms: list[SimpleDataForm]) -> None: fields = { 'admin-addresses': _('Admin'),
===================================== gajim/gtk/status_icon.py ===================================== @@ -172,7 +172,7 @@ def _on_our_show(self, _event: events.ShowChanged) -> None:
def _on_account_state(self, _event: Union[events.AccountConnected, - events.AccountDisonnected] + events.AccountDisconnected] ) -> None: account_connected = bool(app.get_number_of_connected_accounts() > 0) self._ui.start_chat_menuitem.set_sensitive(account_connected)
===================================== gajim/gtk/workspace_dialog.py ===================================== @@ -131,7 +131,7 @@ def _update_avatar(self) -> None: scale) else: surface = make_workspace_avatar( - name[:1].upper(), + name, rgba_to_float(rgba), AvatarSize.WORKSPACE_EDIT, scale)
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/2d26eb11c1248c53bccb16e417d54fd7...