Daniel Brötzmann pushed to branch master at gajim / gajim
Commits: 293127fa by wurstsalat at 2023-04-16T15:10:03+02:00 cfix: OMEMO: Remove obsolete qr code message
- - - - - b7235b5a by wurstsalat at 2023-04-16T15:10:03+02:00 cq: Satisfly linter for generated ui types
- - - - - 047f5138 by wurstsalat at 2023-04-16T15:10:03+02:00 refactor: Move QR code generation to helpers
- - - - - 45219590 by wurstsalat at 2023-04-16T15:10:03+02:00 imprv: ChatBanner: Add QR code for sharing JIDs
Fixes #11429
- - - - -
7 changed files:
- gajim/common/helpers.py - gajim/data/gui/chat_banner.ui - gajim/data/gui/omemo_trust_manager.ui - gajim/gtk/builder.pyi - gajim/gtk/chat_banner.py - gajim/gtk/omemo_trust_manager.py - scripts/generate_ui_types.py
Changes:
===================================== gajim/common/helpers.py ===================================== @@ -48,6 +48,7 @@ import socket import string import sys +import tempfile import unicodedata import weakref import webbrowser @@ -61,8 +62,10 @@ from urllib.parse import urlparse
import precis_i18n.codec # noqa: F401 +import qrcode from cryptography import x509 from cryptography.hazmat.backends import default_backend +from gi.repository import GdkPixbuf from gi.repository import Gio from gi.repository import GLib from gi.repository import GObject @@ -366,6 +369,22 @@ def get_contact_dict_for_account(account: str) -> dict[str, types.BareContact]: return contacts_dict
+def generate_qr_code(content: str) -> GdkPixbuf.Pixbuf | None: + image_path = os.path.join( + tempfile.gettempdir(), + f'{get_random_string()}.png') + qr = qrcode.QRCode(version=None, + error_correction=qrcode.constants.ERROR_CORRECT_L, + box_size=6, + border=4) + qr.add_data(content) + qr.make(fit=True) + + img = qr.make_image(fill_color='black', back_color='white') + img.save(image_path) + return GdkPixbuf.Pixbuf.new_from_file(image_path) + + def play_sound(sound_event: str, account: Optional[str] = None, force: bool = False,
===================================== gajim/data/gui/chat_banner.ui ===================================== @@ -9,7 +9,24 @@ <property name="visible">True</property> <property name="can-focus">False</property> <property name="orientation">vertical</property> - <property name="spacing">6</property> + <property name="spacing">12</property> + <child> + <object class="GtkImage" id="qr_code_image"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">center</property> + <property name="icon_size">6</property> + <style> + <class name="border"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack-type">end</property> + <property name="position">0</property> + </packing> + </child> <child> <object class="GtkBox"> <property name="visible">True</property> @@ -226,6 +243,7 @@ <property name="tooltip-text" translatable="yes">Share Contact…</property> <property name="valign">center</property> <property name="popover">share_popover</property> + <signal name="clicked" handler="_on_share_clicked" swapped="no"/> <child> <object class="GtkImage"> <property name="visible">True</property>
===================================== gajim/data/gui/omemo_trust_manager.ui ===================================== @@ -91,25 +91,6 @@ <property name="position">3</property> </packing> </child> - <child> - <object class="GtkLabel" id="qr_dependency_missing"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="label" translatable="yes">For verification via QR-Code you have to install <tt>python-qrcode</tt>.</property> - <property name="use-markup">True</property> - <property name="wrap">True</property> - <property name="max-width-chars">42</property> - <property name="xalign">0</property> - <style> - <class name="dim-label"/> - </style> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">4</property> - </packing> - </child> <style> <class name="padding-18"/> </style>
===================================== gajim/gtk/builder.pyi ===================================== @@ -187,6 +187,7 @@ class CertificateBuilder(Builder):
class ChatBannerBuilder(Builder): share_popover: Gtk.Popover + qr_code_image: Gtk.Image jid_label: Gtk.Label banner_box: Gtk.Box avatar_image: Gtk.Image @@ -602,7 +603,6 @@ class OmemoTrustManagerBuilder(Builder): comparing_instructions: Gtk.Label our_fingerprint_2: Gtk.Label qr_code_image: Gtk.Image - qr_dependency_missing: Gtk.Label stack: Gtk.Stack our_fingerprint_1: Gtk.Label qr_menu_button: Gtk.MenuButton @@ -1050,9 +1050,9 @@ def get_builder(file_name: Literal['manage_sounds.ui'], widgets: list[str] = ... @overload def get_builder(file_name: Literal['message_actions_box.ui'], widgets: list[str] = ...) -> MessageActionsBoxBuilder: ... # noqa @overload -def get_builder(file_name: Literal['password_dialog.ui'], widgets: list[str] = ...) -> PasswordDialogBuilder: ... # noqa +def get_builder(file_name: Literal['omemo_trust_manager.ui'], widgets: list[str] = ...) -> OmemoTrustManagerBuilder: ... # noqa @overload -def get_builder(file_name: Literal['omemo_trust_manager.ui'], widgets: list[str] = ...) -> OmemoTrustManagerBuilder: ... #noqa +def get_builder(file_name: Literal['password_dialog.ui'], widgets: list[str] = ...) -> PasswordDialogBuilder: ... # noqa @overload def get_builder(file_name: Literal['pep_config.ui'], widgets: list[str] = ...) -> PepConfigBuilder: ... # noqa @overload
===================================== gajim/gtk/chat_banner.py ===================================== @@ -32,6 +32,7 @@ from gajim.common.events import MessageReceived from gajim.common.events import MucDiscoUpdate from gajim.common.ged import EventHelper +from gajim.common.helpers import generate_qr_code from gajim.common.i18n import _ from gajim.common.modules.contacts import BareContact from gajim.common.modules.contacts import GroupchatContact @@ -330,6 +331,14 @@ def _update_share_box(self) -> None: self._ui.share_menu_button.set_sensitive(True) self._ui.jid_label.set_text(str(self._contact.jid))
+ def _on_share_clicked(self, _button: Gtk.Button) -> None: + # Generate QR code on demand (i.e. not when switching chats) + assert self._contact is not None + text = f'xmpp:{self._contact.jid}' + if self._contact.is_groupchat: + text = f'{text}?join' + self._ui.qr_code_image.set_from_pixbuf(generate_qr_code(text)) + def _on_copy_jid_clicked(self, _button: Gtk.Button) -> None: assert self._contact is not None text = f'xmpp:{self._contact.jid}'
===================================== gajim/gtk/omemo_trust_manager.py ===================================== @@ -23,8 +23,6 @@
import locale import logging -import os -import tempfile import time
from gi.repository import GdkPixbuf @@ -38,6 +36,7 @@ from gajim.common.events import AccountConnected from gajim.common.events import AccountDisconnected from gajim.common.ged import EventHelper +from gajim.common.helpers import generate_qr_code from gajim.common.i18n import _ from gajim.common.modules.contacts import BareContact from gajim.common.omemo.util import get_fingerprint @@ -235,41 +234,22 @@ def _load_fingerprints(self, contact: types.ChatContactT) -> None: self._ui.list.add(row)
@staticmethod - def _get_qrcode(jid: str, sid: int, identity_key: IdentityKeyPair) -> str: - fingerprint = get_fingerprint(identity_key) - path = os.path.join(tempfile.gettempdir(), - 'omemo_{}.png'.format(jid)) + def _get_qrcode(jid: str, + sid: int, + identity_key: IdentityKeyPair + ) -> GdkPixbuf.Pixbuf | None:
+ fingerprint = get_fingerprint(identity_key) ver_string = 'xmpp:{}?omemo-sid-{}={}'.format(jid, sid, fingerprint) log.debug('Verification String: %s', ver_string) - - import qrcode - qr = qrcode.QRCode(version=None, - error_correction=qrcode.constants.ERROR_CORRECT_L, - box_size=6, - border=4) - qr.add_data(ver_string) - qr.make(fit=True) - - img = qr.make_image(fill_color='black', back_color='white') - img.save(path) - return path + return generate_qr_code(ver_string)
def _load_qrcode(self) -> None: - try: - client = app.get_client(self._account) - path = self._get_qrcode(client.get_own_jid().bare, - self._omemo.backend.own_device, - self._identity_key) - except ImportError: - log.exception('Failed to generate QR code') - self._ui.qr_code_image.hide() - self._ui.qr_dependency_missing.show() - else: - pixbuf = GdkPixbuf.Pixbuf.new_from_file(path) - self._ui.qr_code_image.set_from_pixbuf(pixbuf) - self._ui.qr_code_image.show() - self._ui.qr_dependency_missing.hide() + client = app.get_client(self._account) + pixbuf = self._get_qrcode(client.get_own_jid().bare, + self._omemo.backend.own_device, + self._identity_key) + self._ui.qr_code_image.set_from_pixbuf(pixbuf)
def _on_show_inactive(self, switch: Gtk.Switch, _param: Any) -> None: self._ui.list.invalidate_filter()
===================================== scripts/generate_ui_types.py ===================================== @@ -32,7 +32,6 @@ from gi.repository import Gtk from gi.repository import GtkSource
- class Builder(Gtk.Builder): ...
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/e7da059c9392945a14e8e93340a2714f...