File: ribar.py

package info (click to toggle)
syncthing-gtk 0.9.4.4%2Bds%2Bgit20201209%2Bc46fbd8-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 3,260 kB
  • sloc: python: 7,592; sh: 259; xml: 115; makefile: 2
file content (154 lines) | stat: -rw-r--r-- 4,351 bytes parent folder | download
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
#!/usr/bin/env python3
"""
Syncthing-GTK - RIBar

Infobar wrapped in Revealer, for greater justice
"""

from gi.repository import Gtk, GLib, GObject
RevealerClass = None
if hasattr(Gtk, "Revealer"):
	RevealerClass = Gtk.Revealer
else:
	from syncthing_gtk.fakerevealer import FakeRevealer
	RevealerClass = FakeRevealer


class RIBar(RevealerClass):
	"""
	Infobar wrapped in Revealer
	
	Signals:
		Everything from Gtk.Revealer, plus:
		close()
			emitted when the user dismisses the info bar
		response(response_id)
			Emitted when an action widget (button) is clicked
	"""
	__gsignals__ = {
		"response"	: (GObject.SIGNAL_RUN_FIRST, None, (int,)),
		"close"		: (GObject.SIGNAL_RUN_FIRST, None, ()),
	}

	### Initialization
	def __init__(self, label, message_type=Gtk.MessageType.INFO, *buttons):
		"""
		... where label can be Gtk.Widget or str and buttons are tuples
		of (Gtk.Button, response_id)
		"""
		# Init
		RevealerClass.__init__(self)
		self._infobar = Gtk.InfoBar()
		self._values = {}
		self._label = None
		# Icon
		icon_name = "dialog-information"
		if message_type == Gtk.MessageType.ERROR:
			icon_name = "dialog-error"
		elif message_type == Gtk.MessageType.WARNING:
			icon_name = "dialog-warning"
		icon = Gtk.Image()
		icon.set_from_icon_name(icon_name, Gtk.IconSize.DIALOG)
		self._infobar.get_content_area().pack_start(icon, False, False, 1)
		# Label
		if isinstance(label, Gtk.Widget):
			self._infobar.get_content_area().pack_start(label, True, True, 0)
			self._label = label
		else:
			self._label = Gtk.Label()
			self._label.set_size_request(300, -1)
			self._label.set_markup(label)
			self._label.set_alignment(0, 0.5)
			self._label.set_line_wrap(True)
			self._infobar.get_content_area().add(self._label)
		# Buttons
		for button, response_id in buttons:
			self.add_button(button, response_id)
		# Signals
		self._infobar.connect("close", self._cb_close)
		self._infobar.connect("response", self._cb_response)
		# Settings
		self._infobar.set_message_type(message_type)
		if hasattr(self._infobar, "set_show_close_button"):
			# GTK >3.8
			self._infobar.set_show_close_button(True)
		else:
			self.add_button(Gtk.Button("X"), 0)
		self.set_reveal_child(False)
		# Packing
		self.add(self._infobar)
		self.show_all()
	
	def _cb_close(self, ib):
		self.emit("close")
	
	def _cb_response(self, ib, response_id):
		self.emit("response", response_id)
	
	def disable_close_button(self):
		if hasattr(self._infobar, "set_show_close_button"):
			self._infobar.set_show_close_button(False)
	
	def add_widget(self, widget, expand=False, fill=True):
		self._infobar.get_content_area().pack_start(widget, expand, fill, 1)
		widget.show()
	
	def add_button(self, button, response_id):
		self._infobar.add_action_widget(button, response_id)
		self._infobar.show_all()
	
	def get_label(self):
		""" Returns label widget """
		return self._label
	
	def close_on_close(self):
		"""
		Setups revealer so it will be automaticaly closed, removed and
		destroyed when user clicks to any button, including 'X'
		"""
		self.connect("close", self.close)
		self.connect("response", self.close)
	
	def close(self, *a):
		"""
		Closes revealer (with animation), removes it from parent and
		calls destroy()
		"""
		self.set_reveal_child(False)
		GLib.timeout_add(self.get_transition_duration() + 50, self._cb_destroy)
	
	def _cb_destroy(self, *a):
		""" Callback used by _cb_close method """
		if not self.get_parent() is None:
			self.get_parent().remove(self)
		self.destroy()
	
	def set_value(self, key, value):
		""" Stores some metadata """
		self._values[key] = value
	
	def get_value(self, key):
		""" Retrieves some metadata """
		return self._values[key]
	
	def __getitem__(self, key):
		""" Shortcut to get_value """
		return self._values[key]
	
	def __setitem__(self, key, value):
		""" Shortcut to set_value """
		self.set_value(key, value)
	
	@staticmethod
	def build_button(label, icon_name=None, icon_widget=None, use_stock=False):
		""" Builds button situable for action area """
		b = Gtk.Button.new_from_stock(label) if use_stock \
			else Gtk.Button.new_with_label(label)
		b.set_use_underline(True)
		if not icon_name is None:
			icon_widget = Gtk.Image()
			icon_widget.set_from_icon_name(icon_name, Gtk.IconSize.BUTTON)
		if not icon_widget is None:
			b.set_image(icon_widget)
			b.set_always_show_image(True)
		return b