Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2# This file is part of Xpra. 

3# Copyright (C) 2020 Antoine Martin <antoine@xpra.org> 

4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any 

5# later version. See the file COPYING for details. 

6 

7import gi 

8gi.require_version("Gtk", "3.0") 

9from gi.repository import Gtk, GLib, GdkPixbuf 

10 

11from xpra.gtk_common.gtk_util import add_close_accel 

12from xpra.util import first_time 

13from xpra.log import Logger 

14 

15log = Logger("menu") 

16 

17 

18_qrencode_fn = None 

19def get_qrencode_fn(): 

20 global _qrencode_fn 

21 if _qrencode_fn is None: 

22 _qrencode_fn = _get_qrencode_fn() or False 

23 log("get_qrencode_fn()=%s", _qrencode_fn) 

24 return _qrencode_fn 

25 

26def _get_qrencode_fn(): 

27 try: 

28 from PIL import Image 

29 from qrencode import encode 

30 def qrencode_fn(s): 

31 return encode(s)[2] 

32 return qrencode_fn 

33 except ImportError: 

34 try: 

35 from PIL import Image 

36 from ctypes import ( 

37 Structure, POINTER, 

38 cdll, create_string_buffer, c_int, c_char_p, 

39 ) 

40 from ctypes.util import find_library 

41 class QRCode(Structure): 

42 _fields_ = ( 

43 ("version", c_int), 

44 ("width", c_int), 

45 ("data", c_char_p), 

46 ) 

47 PQRCode = POINTER(QRCode) 

48 lib_file = None 

49 for lib_name in ("libqrencode", "qrencode"): 

50 lib_file = find_library(lib_name) 

51 if lib_file: 

52 break 

53 if not lib_file: 

54 if first_time("libqrencode"): 

55 log.warn("Warning: libqrencode not found") 

56 return None 

57 libqrencode = cdll.LoadLibrary(lib_file) 

58 encodeString8bit = libqrencode.QRcode_encodeString8bit 

59 encodeString8bit.argtypes = (c_char_p, c_int, c_int) 

60 encodeString8bit.restype = PQRCode 

61 QRcode_free = libqrencode.QRcode_free 

62 QRcode_free.argtypes = (PQRCode,) 

63 def qrencode_ctypes_fn(s): 

64 data = create_string_buffer(s.encode("latin1")) 

65 qrcode = encodeString8bit(data, 0, 0).contents 

66 try: 

67 size = qrcode.width 

68 pixels = bytearray(size*size) 

69 pdata = qrcode.data 

70 for i in range(size*size): 

71 pixels[i] = 0 if (pdata[i] & 0x1) else 255 

72 return Image.frombytes('L', (size, size), bytes(pixels)) 

73 finally: 

74 QRcode_free(qrcode) 

75 return qrencode_ctypes_fn 

76 except Exception: 

77 log.error("failed to load qrencode via ctypes", exc_info=True) 

78 return None 

79 

80 

81def qrencode(s): 

82 fn = get_qrencode_fn() 

83 if fn: 

84 return fn(s) 

85 return None 

86 

87def show_qr(uri, width=640, height=640): 

88 #support old-style URIs, ie: tcp:host:port 

89 if uri.find(":")!=uri.find("://"): 

90 uri = uri.replace(":", "://", 1) 

91 parts = uri.split(":", 1) 

92 if parts[0] in ("tcp", "ws"): 

93 uri = "http:"+parts[1] 

94 else: 

95 uri = "https:"+parts[1] 

96 pixbuf = qr_pixbuf(uri, width, height) 

97 if not pixbuf: 

98 return 

99 image = Gtk.Image().new_from_pixbuf(pixbuf) 

100 window = Gtk.Window(modal=True, title="QR Code") 

101 window.set_position(Gtk.WindowPosition.CENTER) 

102 window.add(image) 

103 window.set_size_request(width, height) 

104 window.set_resizable(False) 

105 def close(*_args): 

106 window.destroy() 

107 add_close_accel(window, close) 

108 window.show_all() 

109 

110def qr_pixbuf(uri, width=640, height=640): 

111 img = qrencode(uri) 

112 if not img: 

113 return None 

114 from PIL import Image 

115 img = img.convert("RGB") 

116 img = img.resize((width, height), Image.NEAREST) 

117 data = img.tobytes() 

118 w, h = img.size 

119 data = GLib.Bytes.new(data) 

120 pixbuf = GdkPixbuf.Pixbuf.new_from_bytes(data, GdkPixbuf.Colorspace.RGB, 

121 False, 8, w, h, w * 3) 

122 return pixbuf 

123 

124 

125def main(): 

126 if "-v" in sys.argv or "--verbose" in sys.argv: 

127 log.enable_debug() 

128 fn = get_qrencode_fn() 

129 log.info("qrencode_fn=%s" % (fn,)) 

130 

131 

132if __name__ == "__main__": 

133 import sys 

134 main() 

135 sys.exit(0)