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
|