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)