File: keylistwidget.py

package info (click to toggle)
gnome-keysign 1.3.0-5.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,460 kB
  • sloc: python: 5,143; xml: 126; makefile: 33; sh: 16
file content (217 lines) | stat: -rwxr-xr-x 7,919 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#!/usr/bin/env python
from __future__ import unicode_literals
import logging
import os

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GObject  # for __gsignals__
from gi.repository import GLib  # for markup_escape_text

if  __name__ == "__main__" and __package__ is None:
    logging.getLogger().error("You seem to be trying to execute " +
                              "this script directly which is discouraged. " +
                              "Try python -m instead.")
    parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    os.sys.path.insert(0, parent_dir)
    os.sys.path.insert(0, os.path.join(parent_dir, 'monkeysign'))
    import keysign
    #mod = __import__('keysign')
    #sys.modules["keysign"] = mod
    __package__ = str('keysign')

from .gpgmeh import get_usable_keys
from .i18n import _
from .util import fix_infobar

log = logging.getLogger(__name__)

class ListBoxRowWithKey(Gtk.ListBoxRow):
    "A simple extension of a Gtk.ListBoxRow to also hold a key object"

    def __init__(self, key):
        super(ListBoxRowWithKey, self).__init__()
        self.key = key

        s = self.format(key)
        label = Gtk.Label(label=s, use_markup=True, xalign=0)
        self.add(label)

    @staticmethod
    def glib_markup_escape_text_to_text(s):
        """A helper function to return the text type
        markup_escape_text returns a "str" which is
        a binary type in python2.
        This function tries to decode the returned
        str object.  It will fail in Python3.
        """
        m = GLib.markup_escape_text(s)
        try:
            ret = m.decode('utf-8')
        except AttributeError:
            # We are in Python3 land. All is fine.
            ret = m
        return ret
        

    @classmethod
    def format_uid(cls, uid):
        "Returns a pango string for a gpgmeh.UID"
        fmt = "{name}\t<i>{email}</i>\t<small>{expiry}</small>"

        items = ('name', 'email', 'expiry')
        format_dict = {k: ""+(uid._asdict()[k] or "")
                          for k in items}
        log.info("format dicT: %r", format_dict)
        d = {k: (log.debug("handling kv: %r %r", k, v),
                  cls.glib_markup_escape_text_to_text(
                    "{}".format(v)))[1]
             for k, v in format_dict.items()}
        log.info("Formatting UID %r", d)
        s = fmt.format(**d)
        log.info("Formatted UID: %r", s)
        return s


    @classmethod
    def format(cls, key):
        "Returns a pango string for a gpgmeh.Key"
        fmt  = "{created} "
        fmt  = "<b>{fingerprint}</b>\n"
        fmt += "\n".join((cls.format_uid(uid) for uid in key.uidslist))
        fmt += "\n<small>" + _("Expires: ") + " {expiry}</small>"

        d = {k: GLib.markup_escape_text("{}".format(v))
             for k,v in key._asdict().items()}
        log.info("Formatting key %r", d)
        s = fmt.format(**d)
        log.info("Formatted key: %r", s)
        return s


class KeyListWidget(Gtk.HBox):
    """A Gtk Widget representing a list of OpenPGP Keys
    
    It shows the keys you provide in a ListBox and emits a
    `key-activated` or `key-selected` signal when the user
    "activated" or "selected" a key. "Activating" is Gtk speak for
    double-clicking (or pressing space, enter, ...) on an entry.
    It is also possible that the widget emits that signal on a single
    click if so configured.  "Selected" means that the user switched
    to an entry, e.g. by clicking it or pressing up or down.

    If you don't provide any keys, the widget will not behave nicely
    and potentially display a user facing warning. Or not.
    """
    __gsignals__ = {
        str('key-activated'): (GObject.SignalFlags.RUN_LAST, None,
                               # (ListBoxRowWithKey.__gtype__,)
                               (object,)),
                               # The activated key
        str('key-selected'): (GObject.SignalFlags.RUN_LAST, None,
                               # (ListBoxRowWithKey.__gtype__,)
                               (object,)),
                               # The selected key
    }

    def __init__(self, keys, builder=None):
        "Sets the widget up with the given keys"
        super(KeyListWidget, self).__init__()
        self.log = logging.getLogger(__name__)
        self.log.debug("KLW with keys: %r", keys)

        thisdir = os.path.dirname(os.path.abspath(__file__))
        widget_name = 'keylistbox'
        if not builder:
            builder = Gtk.Builder()
            builder.add_objects_from_file(
                os.path.join(thisdir, 'send.ui'),
                [widget_name])
        widget = builder.get_object(widget_name)
        old_parent = widget.get_parent()
        if old_parent:
            old_parent.remove(widget)
        self.add(widget)

        self.listbox = builder.get_object("keys_listbox")
        self.code_spinner = builder.get_object("code_spinner")
        self.ib_internet = builder.get_object('infobar_internet')
        fix_infobar(self.ib_internet)
        self.label_ib_internet = builder.get_object('label_internet')

        self.ib_import_okay = builder.get_object('infobar_import_okay')
        self.ib_import_error = builder.get_object('infobar_import_error')
        assert self.ib_import_okay
        assert self.ib_import_error
        fix_infobar(self.ib_import_okay)
        fix_infobar(self.ib_import_error)
        self.label_ib_import_okay = builder.get_object('label_import_okay')
        self.image_ib_import_okay = builder.get_object('image_import_okay')
        self.label_ib_import_error = builder.get_object('label_import_error')
        self.image_ib_import_error = builder.get_object('image_import_error')
        self.button_ib_import_error = builder.get_object('import_error_details_button')
        self.button_ib_import_okay = builder.get_object('return_signature')

        if len(list(keys)) <= 0:
            infobar = builder.get_object("infobar")
            infobar.show()
            l = Gtk.Label("You don't have any OpenPGP keys")
            self.listbox.add(l)
        else:
            for key in keys:
                self.log.debug("Adding key: %r", key)
                lbr = ListBoxRowWithKey(key)
                lbr.props.margin_bottom = 5
                self.listbox.add(lbr)
            self.listbox.connect('row-activated', self.on_row_activated)
            self.listbox.connect('row-selected', self.on_row_selected)


    def on_row_activated(self, keylistwidget, row):
        if row:
            self.emit('key-activated', row.key)

    def on_row_selected(self, keylistwidget, row):
        if row:
            self.emit('key-selected', row.key)


class App(Gtk.Application):
    def __init__(self, *args, **kwargs):
        super(App, self).__init__(*args, **kwargs)
        self.connect('activate', self.on_activate)
        self.kpw = None

    def on_activate(self, app):
        window = Gtk.ApplicationWindow()
        window.set_title("Key List")

        if not self.kpw:
            self.kpw = KeyListWidget(get_usable_keys())
        self.kpw.connect('key-activated', self.on_key_activated)
        self.kpw.connect('key-selected', self.on_key_selected)
        window.add(self.kpw)

        window.show_all()
        self.add_window(window)

    def on_key_activated(self, keylistwidget, row):
        self.get_windows()[0].get_window().beep()
        print ("Row activated! %r" % (row,))

    def on_key_selected(self, keylistwidget, row):
        print ("Row selected! %r" % (row,))

    def run(self, args):
        if not args:
            args = [""]
        keys = list(get_usable_keys(pattern=args[0]))
        self.kpw = KeyListWidget(keys)
        super(App, self).run()

if __name__ == "__main__":
    import sys
    logging.basicConfig(level=logging.DEBUG)
    app = App()
    app.run(sys.argv[1:])