Skip to content

Commit 75a53a8

Browse files
committed
cs_keyboard: Add an entry to allow type-to-search shortcut names.
To allow this, merge all keybinding entries into a single model, and use a GtkTreeModelFilter to display only those matching either the current category when one is selected, or matching keybinding labels against the search string.
1 parent 74c26ab commit 75a53a8

File tree

1 file changed

+86
-34
lines changed

1 file changed

+86
-34
lines changed

Diff for: files/usr/share/cinnamon/cinnamon-settings/modules/cs_keyboard.py

+86-34
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ def on_module_selected(self):
267267
vbox.set_border_width(6)
268268
vbox.set_spacing(6)
269269
self.sidePage.stack.add_titled(vbox, "shortcuts", _("Shortcuts"))
270+
self.sidePage.stack.connect("notify::visible-child-name", self.stack_page_changed)
270271

271272
headingbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 2)
272273
mainbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 2)
@@ -281,10 +282,17 @@ def on_module_selected(self):
281282

282283
paned.add1(left_vbox)
283284

285+
right_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
286+
paned.add2(right_box)
287+
288+
self.kb_search_entry = Gtk.Entry(placeholder_text=_("Type to search"))
289+
right_box.pack_start(self.kb_search_entry, False, False, 2)
290+
self.kb_search_handler_id = self.kb_search_entry.connect("changed", self.on_kb_search_changed)
291+
284292
right_scroller = Gtk.ScrolledWindow.new(None, None)
285293
right_scroller.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.NEVER)
286294
right_scroller.add(right_vbox)
287-
paned.add2(right_scroller)
295+
right_box.pack_start(right_scroller, True, True, 2)
288296

289297
category_scroller = Gtk.ScrolledWindow.new(None, None)
290298
category_scroller.set_shadow_type(Gtk.ShadowType.IN)
@@ -298,9 +306,9 @@ def on_module_selected(self):
298306
right_vbox.pack_start(kb_name_scroller, True, True, 2)
299307
right_vbox.pack_start(entry_scroller, True, True, 2)
300308
kb_name_scroller.set_property('min-content-height', 150)
301-
self.cat_tree = Gtk.TreeView.new()
302-
self.kb_tree = Gtk.TreeView.new()
303-
self.entry_tree = Gtk.TreeView.new()
309+
self.cat_tree = Gtk.TreeView(enable_search=False, search_column=-1)
310+
self.kb_tree = Gtk.TreeView(enable_search=False, search_column=-1)
311+
self.entry_tree = Gtk.TreeView(enable_search=False, search_column=-1)
304312

305313
self.kb_tree.connect('row-activated', self.onCustomKeyBindingEdited)
306314
self.kb_tree.connect('button-press-event', self.onContextMenuPopup)
@@ -331,9 +339,11 @@ def on_module_selected(self):
331339
self.cat_store = Gtk.TreeStore(str, # Icon name or None
332340
str, # The category name
333341
object) # The category object
342+
self.kb_root_store = Gtk.ListStore( str, # Keybinding name
343+
object)# The keybinding object
334344

335-
self.kb_store = Gtk.ListStore( str, # Keybinding name
336-
object)# The keybinding object
345+
self.kb_store = Gtk.TreeModelFilter(child_model=self.kb_root_store)
346+
self.kb_store.set_visible_func(self.kb_store_visible_func)
337347

338348
self.entry_store = Gtk.ListStore(str) # Accel string
339349

@@ -350,7 +360,6 @@ def on_module_selected(self):
350360
cat_column.set_property('min-width', 200)
351361

352362
self.cat_tree.append_column(cat_column)
353-
self.cat_tree.set_search_column(1)
354363
self.cat_tree.connect("cursor-changed", self.onCategoryChanged)
355364

356365
kb_name_cell = Gtk.CellRendererText()
@@ -371,7 +380,7 @@ def on_module_selected(self):
371380
self.entry_tree.append_column(entry_column)
372381

373382
self.entry_tree.set_tooltip_text(CellRendererKeybinding.TOOLTIP_TEXT)
374-
383+
self.current_category = None
375384
self.main_store = []
376385

377386
for cat in CATEGORIES:
@@ -402,11 +411,12 @@ def on_module_selected(self):
402411

403412
paned.set_position(max(w, 200))
404413

405-
self.loadCustoms()
406414
self.cat_tree.set_model(self.cat_store)
407415
self.kb_tree.set_model(self.kb_store)
408416
self.entry_tree.set_model(self.entry_store)
409417

418+
self.populate_kb_tree()
419+
410420
vbox.pack_start(headingbox, True, True, 0)
411421

412422
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
@@ -425,27 +435,75 @@ def on_module_selected(self):
425435
widget.show()
426436
vbox.pack_start(cheat_box, True, True, 0)
427437

438+
self.kb_search_entry.grab_focus()
439+
440+
def stack_page_changed(self, stack, pspec, data=None):
441+
if stack.get_visible_child_name() == "shortcuts":
442+
self.kb_search_entry.grab_focus()
443+
428444
def addNotebookTab(self, tab):
429445
self.notebook.append_page(tab.tab, Gtk.Label.new(tab.name))
430446
self.tabs.append(tab)
431447

432448
def onCategoryChanged(self, tree):
433-
self.kb_store.clear()
449+
self.kb_search_entry.handler_block(self.kb_search_handler_id)
450+
self.kb_search_entry.set_text("")
451+
self.kb_search_entry.handler_unblock(self.kb_search_handler_id)
452+
434453
if tree.get_selection() is not None:
435454
categories, iter = tree.get_selection().get_selected()
436455
if iter:
437456
category = categories[iter][2]
438-
if category.int_name != "custom":
439-
for keybinding in category.keybindings:
440-
self.kb_store.append((keybinding.label, keybinding))
441-
else:
442-
self.loadCustoms()
457+
self.current_category = category
458+
self.kb_store.refilter()
459+
443460
self.remove_custom_button.set_property('sensitive', False)
444461

445-
def loadCustoms(self):
462+
def on_kb_search_changed(self, entry, data=None):
463+
self.cat_tree.get_selection().unselect_all()
464+
self.current_category = None
465+
self.kb_store.refilter()
466+
467+
def populate_kb_tree(self):
468+
self.kb_root_store.clear()
469+
self.current_category = None
470+
self.kb_search_entry.handler_block(self.kb_search_handler_id)
471+
self.kb_search_entry.set_text("")
472+
self.kb_search_entry.handler_unblock(self.kb_search_handler_id)
473+
446474
for category in self.main_store:
447-
if category.int_name == "custom":
448-
category.clear()
475+
for keybinding in category.keybindings:
476+
self.kb_root_store.append((keybinding.label, keybinding))
477+
self.loadCustoms()
478+
479+
def kb_store_visible_func(self, model, iter, data=None):
480+
if self.current_category is None and self.kb_search_entry.get_text == "":
481+
print("empty")
482+
return False
483+
484+
keybinding = self.kb_root_store.get_value(iter, 1)
485+
486+
search = self.kb_search_entry.get_text().lower().strip()
487+
if search != "":
488+
return search in keybinding.label.lower().strip()
489+
490+
if self.current_category is not None:
491+
return keybinding.category == self.current_category.int_name
492+
493+
def loadCustoms(self):
494+
iter = self.kb_root_store.get_iter_first()
495+
496+
while iter:
497+
# Removing a row moves the iter to the next row, which may also be
498+
# custom, so we don't want to call iter_next() until we hit a row
499+
# that isn't, otherwise we may skip one.
500+
keybinding = self.kb_root_store.get_value(iter, 1)
501+
if keybinding.category == "custom":
502+
if not self.kb_root_store.remove(iter):
503+
break
504+
continue
505+
506+
iter = self.kb_root_store.iter_next(iter)
449507

450508
parent = Gio.Settings.new(CUSTOM_KEYS_PARENT_SCHEMA)
451509
custom_list = parent.get_strv("custom-list")
@@ -460,10 +518,7 @@ def loadCustoms(self):
460518
schema.get_string("name"),
461519
schema.get_string("command"),
462520
schema.get_strv("binding"))
463-
self.kb_store.append((custom_kb.label, custom_kb))
464-
for category in self.main_store:
465-
if category.int_name == "custom":
466-
category.add(custom_kb)
521+
self.kb_root_store.append((custom_kb.label, custom_kb))
467522

468523
def onKeyBindingChanged(self, tree):
469524
self.entry_store.clear()
@@ -477,7 +532,6 @@ def onKeyBindingChanged(self, tree):
477532
self.remove_custom_button.set_property('sensitive', isinstance(keybinding, CustomKeyBinding))
478533

479534
def onEntryChanged(self, cell, path, accel_string, accel_label, entry_store):
480-
iter = entry_store.get_iter(path)
481535
keybindings, kb_iter = self.kb_tree.get_selection().get_selected()
482536
if kb_iter:
483537
current_keybinding = keybindings[kb_iter][1]
@@ -513,7 +567,6 @@ def onEntryChanged(self, cell, path, accel_string, accel_label, entry_store):
513567
self.entry_tree.get_selection().select_path(path)
514568

515569
def onEntryCleared(self, cell, path, entry_store):
516-
iter = entry_store.get_iter(path)
517570
keybindings, kb_iter = self.kb_tree.get_selection().get_selected()
518571
if kb_iter:
519572
current_keybinding = keybindings[kb_iter][1]
@@ -557,6 +610,10 @@ def onAddCustomButtonClicked(self, button):
557610
new_schema.set_string("name", dialog.name_entry.get_text())
558611
new_schema.set_string("command", dialog.command_entry.get_text().replace("%20", "\ "))
559612
new_schema.set_strv("binding", ())
613+
614+
self.loadCustoms()
615+
self.kb_store.refilter()
616+
560617
i = 0
561618
for cat in self.cat_store:
562619
if cat[2].int_name == "custom":
@@ -596,13 +653,11 @@ def onRemoveCustomButtonClicked(self, button):
596653
ensureCustomListIsValid(array)
597654
parent_settings.set_strv("custom-list", array)
598655

599-
i = 0
600-
for cat in self.cat_store:
601-
if cat[2].int_name == "custom":
602-
self.cat_tree.set_cursor(str(i), self.cat_tree.get_column(0), False)
603-
i += 1
656+
self.loadCustoms()
657+
self.kb_store.refilter()
604658

605659
def onCustomKeyBindingEdited(self, kb_treeview, column, kb_column):
660+
print("what")
606661
keybindings, iter = kb_treeview.get_selection().get_selected()
607662
if iter:
608663
keybinding = keybindings[iter][1]
@@ -622,11 +677,6 @@ def onCustomKeyBindingEdited(self, kb_treeview, column, kb_column):
622677
keybinding.action = dialog.command_entry.get_text().replace("%20", "\ ")
623678
keybinding.writeSettings()
624679

625-
i = 0
626-
for cat in self.cat_store:
627-
if cat[2].int_name == "custom":
628-
self.cat_tree.set_cursor(str(i), self.cat_tree.get_column(0), False)
629-
i += 1
630680
i = 0
631681
for keybinding in self.kb_store:
632682
if keybinding[0] == dialog.name_entry.get_text():
@@ -685,6 +735,7 @@ def clear(self):
685735
class KeyBinding():
686736
def __init__(self, label, schema, key, category):
687737
self.key = key
738+
self.category = category
688739
self.label = label
689740
self.entries = [ ]
690741
self.settings = Gio.Settings.new(schema)
@@ -724,6 +775,7 @@ def resetDefaults(self):
724775

725776
class CustomKeyBinding():
726777
def __init__(self, path, label, action, binding):
778+
self.category = "custom"
727779
self.path = path
728780
self.label = label
729781
self.action = action

0 commit comments

Comments
 (0)