~huluti/coulr/master

« back to all changes in this revision

Viewing changes to src/window.py

  • Committer: Hugo Posnic
  • Date: 2020-03-19 21:10:36 UTC
  • Revision ID: git-v1:38a38c9742a2bf294ea2011ada83fe7a8b9fcf51
Adopt meson and use flatpak over snap

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import os
 
2
import sys
 
3
import json
 
4
import gi
 
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
 
9
 
 
10
 
 
11
SETTINGS_SCHEMA = 'com.github.huluti.Coulr'
 
12
 
 
13
 
 
14
class CoulrWindow(Gtk.ApplicationWindow):
 
15
    __gtype_name__ = 'CoulrWindow'
 
16
 
 
17
    _settings = Gio.Settings.new(SETTINGS_SCHEMA)
 
18
 
 
19
    def __init__(self, **kwargs):
 
20
        super().__init__(**kwargs)
 
21
        self.app = kwargs['application']
 
22
 
 
23
        """Initialize app"""
 
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)
 
29
 
 
30
        self.connect('delete-event', self.quit_app)
 
31
 
 
32
        # Enable notifications
 
33
        Notify.init(self.app_name)
 
34
 
 
35
        # Main vars
 
36
        self.rgb_color = None
 
37
        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
 
38
 
 
39
        # Header bar
 
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)
 
45
 
 
46
        # About button
 
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)
 
54
 
 
55
        # Copy button
 
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)
 
63
 
 
64
        # Random button
 
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)
 
72
 
 
73
        # Main wrappers
 
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)
 
77
        main_box.add(layout1)
 
78
        main_box.add(layout2)
 
79
        self.add(main_box)
 
80
 
 
81
        # RGB
 
82
 
 
83
        # Red label
 
84
        label = Gtk.Label(_("R"))
 
85
        layout1.attach(label, 0, 1, 1, 1)
 
86
 
 
87
        # Red spinner
 
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)
 
92
 
 
93
        # Red slider
 
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)
 
99
 
 
100
        # Green label
 
101
        label = Gtk.Label(_("G"))
 
102
        layout1.attach(label, 0, 2, 1, 1)
 
103
 
 
104
        # Green spinner
 
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)
 
109
 
 
110
        # Green slider
 
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)
 
116
 
 
117
        # Blue label
 
118
        label = Gtk.Label(_("B"))
 
119
        layout1.attach(label, 0, 3, 1, 1)
 
120
 
 
121
        # Blue spinner
 
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)
 
126
 
 
127
        # Blue slider
 
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)
 
133
 
 
134
        # Layout 2
 
135
        # Output mode
 
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)
 
141
 
 
142
        # Output entry
 
143
        self.output = Gtk.Entry()
 
144
        self.output_id = self.output.connect("changed", self.output_entry_changed)
 
145
 
 
146
        # Preview color with square
 
147
        self.square = Gtk.Frame()
 
148
        self.square.set_size_request(150, 150)
 
149
 
 
150
        layout2.add(self.square)
 
151
        layout2.add(self.combo_output)
 
152
        layout2.add(self.output)
 
153
 
 
154
        if self._settings.get_string("last-color"):
 
155
            color = hex_to_rgb(self._settings.get_string("last-color").lstrip("#"))
 
156
        else:
 
157
            color = random_rgb()
 
158
        self.change_color(color)
 
159
        self.show_all()
 
160
 
 
161
    def change_color(self, rgb):
 
162
        """Refresh preview and set values of all fields.
 
163
        :param rgb: rgb color values
 
164
        :type rgb: tuple
 
165
        """
 
166
 
 
167
        rgba = Gdk.RGBA()
 
168
        rgba.parse("rgb({},{},{})".format(*rgb))
 
169
        self.square.override_background_color(Gtk.StateType.NORMAL, rgba)
 
170
 
 
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)
 
177
 
 
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)
 
184
 
 
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)
 
191
 
 
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)
 
195
 
 
196
        self.rgb_color = rgb
 
197
        self.change_output()
 
198
 
 
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)
 
206
 
 
207
        self.output.set_text(output)
 
208
 
 
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()
 
214
 
 
215
        self.change_color((spin_red, spin_green, spin_blue))
 
216
 
 
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())
 
222
 
 
223
        self.change_color((slider_red, slider_green, slider_blue))
 
224
 
 
225
    def output_entry_changed(self, event):
 
226
        """Hex entry value changed"""
 
227
        value = self.output.get_text().lstrip("#")
 
228
 
 
229
        if len(value) == 6:
 
230
            rgb = hex_to_rgb(value)
 
231
            self.change_color(rgb)
 
232
 
 
233
    def random_button_clicked(self, event):
 
234
        """Random button clicked"""
 
235
        self.change_color(random_rgb())
 
236
 
 
237
    def copy_output(self, event):
 
238
        """Copy output to clipboard"""
 
239
        color = self.output.get_text()
 
240
        self.clipboard.set_text(color, -1)
 
241
 
 
242
        notification = Notify.Notification.new(_("Color copied"), color)
 
243
        notification.show()
 
244
 
 
245
    def about_dialog(self, event):
 
246
        """About dialog"""
 
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)
 
259
        about_dialog.run()
 
260
        about_dialog.destroy()
 
261
 
 
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))
 
265
        self.app.quit()
 
266
 
 
267
 
 
268
def rgb_to_hex(rgb):
 
269
    """Convert RGB color to hex color."
 
270
    :param rgb: RGB color
 
271
    :type rgb: tuple
 
272
    :return: Hex color
 
273
    :rtype: str
 
274
    """
 
275
    return "#{0:02x}{1:02x}{2:02x}".format(*rgb)
 
276
 
 
277
 
 
278
def hex_to_rgb(hexa):
 
279
    """Convert hex color to RGB color.
 
280
    :param hexa: Hex color
 
281
    :type hexa: str
 
282
    :return: RGB color
 
283
    :rtype: tuple
 
284
    """
 
285
    return tuple(int(hexa[i:i+2], 16) for i in (0, 2, 4))
 
286
 
 
287
 
 
288
def random_rgb():
 
289
    """Random rgb values.
 
290
    :return: Random RGB color
 
291
    :rtype: tuple
 
292
    """
 
293
    return (randint(0, 255), randint(0, 255), randint(0, 255))