5
gi.require_version("Gtk", "3.0")
6
gi.require_version("Notify", "0.7")
7
from gi.repository import Gtk, Gdk, Gio, GObject, GdkPixbuf, Notify
8
from random import randint
11
SETTINGS_SCHEMA = 'com.github.huluti.Coulr'
14
class CoulrWindow(Gtk.ApplicationWindow):
15
__gtype_name__ = 'CoulrWindow'
17
_settings = Gio.Settings.new(SETTINGS_SCHEMA)
19
def __init__(self, **kwargs):
20
super().__init__(**kwargs)
21
self.app = kwargs['application']
24
self.app_name = "Coulr"
25
self.set_border_width(15)
26
self.set_size_request(600, -1)
27
self.set_resizable(False)
28
self.set_position(Gtk.WindowPosition.CENTER)
30
self.connect('delete-event', self.quit_app)
32
# Enable notifications
33
Notify.init(self.app_name)
37
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
40
header_bar = Gtk.HeaderBar()
41
header_bar.set_show_close_button(True)
42
header_bar.props.title = self.app_name
43
header_bar.set_subtitle(_("Enjoy colors and feel happy!"))
44
self.set_titlebar(header_bar)
47
button_about = Gtk.Button()
48
button_about.set_tooltip_text(_("About"))
49
icon_about = Gio.ThemedIcon(name="help-about-symbolic")
50
image_about = Gtk.Image.new_from_gicon(icon_about, Gtk.IconSize.BUTTON)
51
button_about.add(image_about)
52
button_about.connect("clicked", self.about_dialog)
53
header_bar.pack_end(button_about)
56
button_copy = Gtk.Button()
57
button_copy.set_tooltip_text(_("Copy color"))
58
icon_copy = Gio.ThemedIcon(name="edit-copy-symbolic")
59
image_copy = Gtk.Image.new_from_gicon(icon_copy, Gtk.IconSize.BUTTON)
60
button_copy.add(image_copy)
61
button_copy.connect("clicked", self.copy_output)
62
header_bar.pack_end(button_copy)
65
self.button_random = Gtk.Button()
66
self.button_random.set_tooltip_text(_("Generate random color"))
67
icon_random = Gio.ThemedIcon(name="media-playlist-shuffle-symbolic")
68
image_random = Gtk.Image.new_from_gicon(icon_random, Gtk.IconSize.BUTTON)
69
self.button_random.add(image_random)
70
self.button_random.connect("clicked", self.random_button_clicked)
71
header_bar.pack_end(self.button_random)
74
main_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
75
layout1 = Gtk.Grid(row_spacing=30, column_spacing=10, valign=Gtk.Align.CENTER)
76
layout2 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5, valign=Gtk.Align.CENTER)
84
label = Gtk.Label(_("R"))
85
layout1.attach(label, 0, 1, 1, 1)
88
adj = Gtk.Adjustment(0, 0, 255, 1, 10, 0)
89
self.spinbutton_r = Gtk.SpinButton(adjustment=adj)
90
self.red_sb_id = self.spinbutton_r.connect("value-changed", self.rgb_spin_changed)
91
layout1.attach(self.spinbutton_r, 1, 1, 1, 1)
94
adj = Gtk.Adjustment(0, 0, 255, 2, 10, 0)
95
self.slider_r = Gtk.Scale(adjustment=adj, draw_value=False)
96
self.slider_r.set_hexpand(True)
97
self.red_s_id = self.slider_r.connect("value-changed", self.rgb_slider_moved)
98
layout1.attach(self.slider_r, 2, 1, 2, 1)
101
label = Gtk.Label(_("G"))
102
layout1.attach(label, 0, 2, 1, 1)
105
adj = Gtk.Adjustment(0, 0, 255, 1, 10, 0)
106
self.spinbutton_g = Gtk.SpinButton(adjustment=adj)
107
self.green_sb_id = self.spinbutton_g.connect("value-changed", self.rgb_spin_changed)
108
layout1.attach(self.spinbutton_g, 1, 2, 1, 1)
111
adj = Gtk.Adjustment(0, 0, 255, 2, 10, 0)
112
self.slider_g = Gtk.Scale(adjustment=adj, draw_value=False)
113
self.slider_g.set_hexpand(True)
114
self.green_s_id = self.slider_g.connect("value-changed", self.rgb_slider_moved)
115
layout1.attach(self.slider_g, 2, 2, 2, 1)
118
label = Gtk.Label(_("B"))
119
layout1.attach(label, 0, 3, 1, 1)
122
adj = Gtk.Adjustment(0, 0, 255, 1, 10, 0)
123
self.spinbutton_b = Gtk.SpinButton(adjustment=adj)
124
self.blue_sb_id = self.spinbutton_b.connect("value-changed", self.rgb_spin_changed)
125
layout1.attach(self.spinbutton_b, 1, 3, 1, 1)
128
adj = Gtk.Adjustment(0, 0, 255, 2, 10, 0)
129
self.slider_b = Gtk.Scale(adjustment=adj, draw_value=False)
130
self.slider_b.set_hexpand(True)
131
self.blue_s_id = self.slider_b.connect("value-changed", self.rgb_slider_moved)
132
layout1.attach(self.slider_b, 2, 3, 2, 1)
136
self.combo_output = Gtk.ComboBoxText()
137
self.combo_output.append("hex", _("Hexadecimal"))
138
self.combo_output.append("rgb", _("RGB"))
139
self.combo_output.set_active(0)
140
self.combo_output.connect("changed", self.change_output)
143
self.output = Gtk.Entry()
144
self.output_id = self.output.connect("changed", self.output_entry_changed)
146
# Preview color with square
147
self.square = Gtk.Frame()
148
self.square.set_size_request(150, 150)
150
layout2.add(self.square)
151
layout2.add(self.combo_output)
152
layout2.add(self.output)
154
if self._settings.get_string("last-color"):
155
color = hex_to_rgb(self._settings.get_string("last-color").lstrip("#"))
158
self.change_color(color)
161
def change_color(self, rgb):
162
"""Refresh preview and set values of all fields.
163
:param rgb: rgb color values
168
rgba.parse("rgb({},{},{})".format(*rgb))
169
self.square.override_background_color(Gtk.StateType.NORMAL, rgba)
171
GObject.signal_handler_block(self.spinbutton_r, self.red_sb_id)
172
self.spinbutton_r.set_value(rgb[0])
173
GObject.signal_handler_unblock(self.spinbutton_r, self.red_sb_id)
174
GObject.signal_handler_block(self.slider_r, self.red_s_id)
175
self.slider_r.set_value(rgb[0])
176
GObject.signal_handler_unblock(self.slider_r, self.red_s_id)
178
GObject.signal_handler_block(self.spinbutton_g, self.green_sb_id)
179
self.spinbutton_g.set_value(rgb[1])
180
GObject.signal_handler_unblock(self.spinbutton_g, self.green_sb_id)
181
GObject.signal_handler_block(self.slider_g, self.green_s_id)
182
self.slider_g.set_value(rgb[1])
183
GObject.signal_handler_unblock(self.slider_g, self.green_s_id)
185
GObject.signal_handler_block(self.spinbutton_b, self.blue_sb_id)
186
self.spinbutton_b.set_value(rgb[2])
187
GObject.signal_handler_unblock(self.spinbutton_b, self.blue_sb_id)
188
GObject.signal_handler_block(self.slider_b, self.blue_s_id)
189
self.slider_b.set_value(rgb[2])
190
GObject.signal_handler_unblock(self.slider_b, self.blue_s_id)
192
GObject.signal_handler_block(self.output, self.output_id)
193
self.output.set_text(rgb_to_hex(rgb))
194
GObject.signal_handler_unblock(self.output, self.output_id)
199
def change_output(self, event=None):
200
"""Set output field"""
201
combo_id = self.combo_output.get_active_id()
202
if combo_id == "hex":
203
output = rgb_to_hex(self.rgb_color)
204
elif combo_id == "rgb":
205
output = "rgb({},{},{})".format(*self.rgb_color)
207
self.output.set_text(output)
209
def rgb_spin_changed(self, event):
210
"""RGB spinners values changed"""
211
spin_red = self.spinbutton_r.get_value_as_int()
212
spin_green = self.spinbutton_g.get_value_as_int()
213
spin_blue = self.spinbutton_b.get_value_as_int()
215
self.change_color((spin_red, spin_green, spin_blue))
217
def rgb_slider_moved(self, event):
218
"""RGB sliders values changed"""
219
slider_red = int(self.slider_r.get_value())
220
slider_green = int(self.slider_g.get_value())
221
slider_blue = int(self.slider_b.get_value())
223
self.change_color((slider_red, slider_green, slider_blue))
225
def output_entry_changed(self, event):
226
"""Hex entry value changed"""
227
value = self.output.get_text().lstrip("#")
230
rgb = hex_to_rgb(value)
231
self.change_color(rgb)
233
def random_button_clicked(self, event):
234
"""Random button clicked"""
235
self.change_color(random_rgb())
237
def copy_output(self, event):
238
"""Copy output to clipboard"""
239
color = self.output.get_text()
240
self.clipboard.set_text(color, -1)
242
notification = Notify.Notification.new(_("Color copied"), color)
245
def about_dialog(self, event):
247
about_dialog = Gtk.AboutDialog(self)
248
about_dialog.set_program_name(self.app_name)
249
about_dialog.set_version("1.8")
250
about_dialog.set_copyright("Hugo Posnic")
251
about_dialog.set_comments(_("Enjoy colors and feel happy!"))
252
about_dialog.set_website("https://github.com/Huluti/{}"
253
.format(self.app_name))
254
about_dialog.set_website_label("GitHub")
255
about_dialog.set_authors(["Hugo Posnic"])
256
about_dialog.set_logo_icon_name('com.github.huluti.Coulr')
257
about_dialog.set_license(self.app_name + " " + _("is under MIT Licence."))
258
about_dialog.set_transient_for(self)
260
about_dialog.destroy()
262
def quit_app(self, *args):
263
"""Quit app and save current color"""
264
self._settings.set_string("last-color", rgb_to_hex(self.rgb_color))
269
"""Convert RGB color to hex color."
270
:param rgb: RGB color
275
return "#{0:02x}{1:02x}{2:02x}".format(*rgb)
278
def hex_to_rgb(hexa):
279
"""Convert hex color to RGB color.
280
:param hexa: Hex color
285
return tuple(int(hexa[i:i+2], 16) for i in (0, 2, 4))
289
"""Random rgb values.
290
:return: Random RGB color
293
return (randint(0, 255), randint(0, 255), randint(0, 255))