Mercurial > system76-keyboard-colors
changeset 0:11a9d346aa7a
Sort of working model
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Wed, 27 Jan 2021 21:02:30 -0500 |
parents | |
children | b6d0a1e6ba3a |
files | .hgignore keyboard_colors/__init__.py keyboard_colors/color_profile.py keyboard_colors/custom/__init__.py keyboard_colors/custom/custom.glade keyboard_colors/custom/custom.py main.py ui/MainWindow.glade ui/__init__.py ui/main_window.py |
diffstat | 7 files changed, 474 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Wed Jan 27 21:02:30 2021 -0500 @@ -0,0 +1,5 @@ +syntax:glob + +*.pyc +.vscode +*~
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyboard_colors/color_profile.py Wed Jan 27 21:02:30 2021 -0500 @@ -0,0 +1,65 @@ +import gi +import importlib +import json +import os +import pathlib +import sys +import uuid +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk +from gi.repository import GLib + +class ColorProfileBase: + + type_name = '(no name)' + + def __init__(self): + self.name = '' + self.id = uuid.uuid4().hex + + def build_settings_ui(self): + glade_file = sys.modules[self.__module__].__file__.replace('.py', '.glade') + builder = Gtk.Builder() + builder.add_from_file(glade_file) + return builder.get_object('edit_profile_container') + +class ProfileManager: + + def __init__(self): + self.profiles = self.load_profiles() + self.save_profiles() + + def get_types(self): + types = [] + profile_directory = os.path.dirname(os.path.realpath(__file__)) + (_, dirnames, _) = next(os.walk(profile_directory)) + for dirname in dirnames: + module_file = os.path.join(profile_directory, dirname, dirname + '.py') + if os.path.isfile(module_file): + profile_module = importlib.import_module('keyboard_colors.' + dirname + '.' + dirname) + profile_class = getattr(profile_module, 'ColorProfile') + types.append(profile_class) + return types + + def config_path(self): + dir = GLib.get_user_config_dir() + if not os.path.isdir(dir): + os.mkdir(dir) + return os.path.join(dir, 'keyboard-color-profiles.conf') + + def load_profiles(self): + if os.path.isfile(self.config_path()): + data = pathlib.Path(self.config_path()).read_text('utf-8') + try: + return json.loads(data, object_hook=lambda d: SimpleNamespace(**d)) + except json.decoder.JSONDecodeError: + return [] + else: + return [] + + def save_profiles(self): + data = json.dumps(self.profiles, default=lambda o: o.__dict__) + pathlib.Path(self.config_path()).write_text(data, 'utf-8') + + def get_profiles(self): + return self.profiles \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyboard_colors/custom/custom.glade Wed Jan 27 21:02:30 2021 -0500 @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.2 --> +<interface> + <requires lib="gtk+" version="3.20"/> + <object class="GtkBox" id="edit_profile_container"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">label</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> +</interface>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyboard_colors/custom/custom.py Wed Jan 27 21:02:30 2021 -0500 @@ -0,0 +1,8 @@ +from keyboard_colors.color_profile import ColorProfileBase + +class ColorProfile(ColorProfileBase): + + type_name = 'Custom colors' + + def __init__(self): + super().__init__() \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.py Wed Jan 27 21:02:30 2021 -0500 @@ -0,0 +1,7 @@ +from ui.main_window import MainWindow + +def main(): + MainWindow().init() + +if __name__ == "__main__": + main()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/MainWindow.glade Wed Jan 27 21:02:30 2021 -0500 @@ -0,0 +1,270 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.2 --> +<interface> + <requires lib="gtk+" version="3.0"/> + <object class="GtkBox" id="add_profile_button_contents"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">7</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="stock">gtk-add</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes">Add color profile</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">1</property> + </packing> + </child> + </object> + <object class="GtkListStore" id="color_profile_list_store"> + <columns> + <!-- column-name id --> + <column type="gchararray"/> + <!-- column-name name --> + <column type="gchararray"/> + </columns> + <data> + <row> + <col id="0" translatable="yes">1-2-3</col> + <col id="1" translatable="yes">test name</col> + </row> + </data> + </object> + <object class="GtkApplicationWindow" id="main_window"> + <property name="width_request">600</property> + <property name="height_request">400</property> + <property name="can_focus">False</property> + <property name="has_resize_grip">True</property> + <child type="titlebar"> + <placeholder/> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkBox" id="keyboard_section"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">5</property> + <property name="homogeneous">True</property> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkPaned"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <child> + <object class="GtkBox" id="profile_pane"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkTreeView" id="profile_tree_view"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">False</property> + <property name="vexpand">False</property> + <property name="model">color_profile_list_store</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> + </child> + <child> + <object class="GtkTreeViewColumn"> + <property name="title" translatable="yes">Color profile</property> + <child> + <object class="GtkCellRendererText" id="name"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="resize">False</property> + <property name="shrink">True</property> + </packing> + </child> + <child> + <object class="GtkFrame"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label_xalign">0</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkBox" id="edit_profile_box"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="margin_left">10</property> + <property name="margin_right">10</property> + <property name="margin_top">10</property> + <property name="margin_bottom">10</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="column_spacing">9</property> + <property name="row_homogeneous">True</property> + <property name="column_homogeneous">True</property> + <child> + <object class="GtkLabel" id="edit_profile_type_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="margin_right">1</property> + <property name="label" translatable="yes">Type</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="edit_profile_name_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="label" translatable="yes">Name</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="edit_profile_type_name_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="edit_profile_name_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <signal name="changed" handler="edit_profile_name_changed" swapped="no"/> + <signal name="focus-out-event" handler="edit_profile_name_entry_focus_out" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="edit_profile_details_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButtonBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="homogeneous">True</property> + <property name="layout_style">start</property> + <child> + <object class="GtkButton" id="delete_profile_button"> + <property name="label">gtk-delete</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + <style> + <class name="destructive-action"/> + </style> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + <child type="label_item"> + <placeholder/> + </child> + </object> + <packing> + <property name="resize">True</property> + <property name="shrink">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> +</interface>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/main_window.py Wed Jan 27 21:02:30 2021 -0500 @@ -0,0 +1,91 @@ +import gi +import os +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk +from keyboard_colors.color_profile import ProfileManager +# from ui.keyboard_section import KeyboardSection + +class MainWindow: + + def init(self): + self.profile_manager = ProfileManager() + + self.builder = Gtk.Builder() + dirname = os.path.dirname(os.path.realpath(__file__)) + self.builder.add_from_file(os.path.join(dirname, 'MainWindow.glade')) + self.builder.connect_signals(self) + window = self.builder.get_object('main_window') + + color_profile_list_store = self.builder.get_object('color_profile_list_store') + # color_profile_list_store.append(["1", "test"]) + + keyboard_section = self.builder.get_object('keyboard_section') + keyboard_section.pack_start(KeyboardSection(color_profile_list_store), False, False, 0) + keyboard_section.pack_start(KeyboardSection(color_profile_list_store), False, False, 0) + keyboard_section.pack_start(KeyboardSection(color_profile_list_store), False, False, 0) + + # for profile_id, profile_type in self.profile_manager.get_types().items(): + + menu = Gtk.Menu() + menu.set_halign(Gtk.Align.CENTER) + for profile_type in self.profile_manager.get_types(): + item = Gtk.MenuItem.new_with_label(profile_type.type_name) + item.connect('activate', self.create_profile, profile_type) + item.show() + menu.append(item) + add_button = Gtk.MenuButton() + add_button.set_popup(menu) + add_profile_button_contents = self.builder.get_object('add_profile_button_contents') + add_button.add(add_profile_button_contents) + + profile_pane = self.builder.get_object('profile_pane') + profile_pane.add(add_button) + + window.show_all() + Gtk.main() + + def create_profile(self, widget, profile_type): + profile = profile_type() + color_profile_list_store = self.builder.get_object('color_profile_list_store') + color_profile_list_store.append([profile.id, 'New ' + profile.type_name]) + self.builder.get_object('profile_tree_view').set_cursor(len(color_profile_list_store) - 1) + self.edit_profile(profile) + self.builder.get_object('edit_profile_name_entry').grab_focus() + + def edit_profile(self, profile): + self.builder.get_object('edit_profile_box').show() + + self.builder.get_object('edit_profile_type_name_label').set_text(profile.type_name) + self.builder.get_object('edit_profile_name_entry').set_text(profile.name) + + edit_profile_details_box = self.builder.get_object('edit_profile_details_box') + for child in edit_profile_details_box.get_children(): + edit_profile_details_box.remove(child) + edit_profile_details_box.add(profile.build_settings_ui()) + + def edit_profile_name_changed(self, entry): + profile_name = entry.get_text() + color_profile_list_store = self.builder.get_object('color_profile_list_store') + selection = self.builder.get_object('profile_tree_view').get_selection() + (model, tree_iter) = selection.get_selected() + model.set_value(tree_iter, 1, profile_name) + + def edit_profile_name_entry_focus_out(self, entry, event): + pass + +class KeyboardSection(Gtk.Grid): + + def __init__(self, model): + super().__init__() + + profile_label = Gtk.Label('Color profile') + # profile_combo_box = Gtk.ComboBox(model) + profile_combo_box = Gtk.ComboBox.new_with_model(model) + # profile_combo_box.set_entry_text_column(1) + # profile_combo_box.append_text('asdf') + renderer_text = Gtk.CellRendererText() + profile_combo_box.pack_start(renderer_text, True) + profile_combo_box.add_attribute(renderer_text, 'text', 1) + + self.add(profile_label) + self.add(profile_combo_box)