# Copyright (C) 2019 Philipp Hörist # # This file is part of the OpenPGP Gajim Plugin. # # OpenPGP Gajim Plugin is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; version 3 only. # # OpenPGP Gajim Plugin is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with OpenPGP Gajim Plugin. If not, see . from __future__ import annotations from typing import cast import logging import threading from enum import IntEnum from gi.repository import GLib from gi.repository import Gtk from gajim.common import app from gajim.common.client import Client from gajim.gtk.control import ChatControl from gajim.plugins.plugins_i18n import _ from ..pgpplugin import OpenPGPPlugin log = logging.getLogger("gajim.p.openpgp.wizard") class Page(IntEnum): WELCOME = 0 NEWKEY = 1 SUCCESS = 2 ERROR = 3 class KeyWizard(Gtk.Assistant): def __init__( self, plugin: OpenPGPPlugin, account: str, chat_control: ChatControl ) -> None: Gtk.Assistant.__init__(self) self._client = app.get_client(account) self._plugin = plugin self._account = account self._data_form_widget = None self._is_form = None self._chat_control = chat_control self.set_application(app.app) self.set_transient_for(app.window) self.set_resizable(True) self.set_default_size(600, 400) self.get_style_context().add_class("dialog-margin") self._add_page(WelcomePage()) # self._add_page(BackupKeyPage()) self._add_page(NewKeyPage(self, self._client)) # self._add_page(SaveBackupCodePage()) self._add_page(SuccessfulPage()) self._add_page(ErrorPage()) self.connect("prepare", self._on_page_change) self.connect("cancel", self._on_cancel) self.connect("close", self._on_cancel) self._remove_sidebar() self.show() def _add_page(self, page: PagesT) -> None: self.append_page(page) self.set_page_type(page, page.type_) self.set_page_title(page, page.title) self.set_page_complete(page, page.complete) def _remove_sidebar(self) -> None: main_box = cast(Gtk.Box, self.get_child()) sidebar = main_box.get_first_child() assert sidebar is not None main_box.remove(sidebar) def _activate_encryption(self): action = app.window.lookup_action("set-encryption") assert action is not None action.activate(GLib.Variant("s", self._plugin.encryption_name)) def _on_page_change(self, assistant: Gtk.Assistant, page: PagesT) -> None: if self.get_current_page() == Page.NEWKEY: page = cast(NewKeyPage, page) if self._client.get_module("OpenPGP").secret_key_available: # pyright: ignore self.set_current_page(Page.SUCCESS) else: page.generate() elif self.get_current_page() == Page.SUCCESS: self._activate_encryption() def _on_cancel(self, widget: Gtk.Assistant): self.destroy() class WelcomePage(Gtk.Box): type_ = Gtk.AssistantPageType.INTRO title = _("Welcome") complete = True def __init__(self): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(18) title_label = Gtk.Label(label=_("Setup OpenPGP")) text_label = Gtk.Label(label=_("Gajim will now try to setup OpenPGP for you")) self.append(title_label) self.append(text_label) class RequestPage(Gtk.Box): type_ = Gtk.AssistantPageType.INTRO title = _("Request OpenPGP Key") complete = False def __init__(self): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(18) spinner = Gtk.Spinner() self.append(spinner) spinner.start() # class BackupKeyPage(Gtk.Box): # type_ = Gtk.AssistantPageType.INTRO # title = _('Supply Backup Code') # complete = True # def __init__(self): # super().__init__(orientation=Gtk.Orientation.VERTICAL) # self.set_spacing(18) # title_label = Gtk.Label(label=_('Backup Code')) # text_label = Gtk.Label( # label=_('We found a backup Code, please supply your password')) # self.add(title_label) # self.add(text_label) # entry = Gtk.Entry() # self.add(entry) class NewKeyPage(RequestPage): type_ = Gtk.AssistantPageType.PROGRESS title = _("Generating new Key") complete = False def __init__(self, assistant: Gtk.Assistant, client: Client) -> None: super().__init__() self._assistant = assistant self._client = client def generate(self): log.info("Creating Key") thread = threading.Thread(target=self.worker) thread.start() def worker(self): text = None try: self._client.get_module("OpenPGP").generate_key() # pyright: ignore except Exception as error: text = str(error) GLib.idle_add(self.finished, text) def finished(self, error: str | None) -> None: if error is None: self._client.get_module("OpenPGP").get_own_key_details() # pyright: ignore self._client.get_module("OpenPGP").set_public_key() # pyright: ignore self._client.get_module("OpenPGP").request_keylist() # pyright: ignore self._assistant.set_current_page(Page.SUCCESS) else: error_page = cast(ErrorPage, self._assistant.get_nth_page(Page.ERROR)) error_page.set_text(error) self._assistant.set_current_page(Page.ERROR) # class SaveBackupCodePage(RequestPage): # type_ = Gtk.AssistantPageType.PROGRESS # title = _('Save this code') # complete = False # def __init__(self): # super().__init__(orientation=Gtk.Orientation.VERTICAL) # self.set_spacing(18) # title_label = Gtk.Label(label=_('Backup Code')) # text_label = Gtk.Label( # label=_('This is your backup code, you need it if you reinstall Gajim')) # self.add(title_label) # self.add(text_label) class SuccessfulPage(Gtk.Box): type_ = Gtk.AssistantPageType.SUMMARY title = _("Setup successful") complete = True def __init__(self): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(12) self.set_homogeneous(True) icon = Gtk.Image.new_from_icon_name("object-select-symbolic") icon.add_css_class("success-color") icon.set_valign(Gtk.Align.END) label = Gtk.Label(label=_("Setup successful")) label.add_css_class("bold16") label.set_valign(Gtk.Align.START) self.append(icon) self.append(label) class ErrorPage(Gtk.Box): type_ = Gtk.AssistantPageType.SUMMARY title = _("Setup failed") complete = True def __init__(self): super().__init__(orientation=Gtk.Orientation.VERTICAL) self.set_spacing(12) self.set_homogeneous(True) icon = Gtk.Image.new_from_icon_name("dialog-error-symbolic") icon.get_style_context().add_class("error-color") icon.set_valign(Gtk.Align.END) self._label = Gtk.Label() self._label.get_style_context().add_class("bold16") self._label.set_valign(Gtk.Align.START) self.append(icon) self.append(self._label) def set_text(self, text: str) -> None: self._label.set_text(text) PagesT = WelcomePage | RequestPage | NewKeyPage | SuccessfulPage | ErrorPage