Is this possible? Couldn’t find it in the docu.
unfortunately not. At least not in a sane way. Can you add a feature request to: http://bugreport.glyphsapp.com
Still the same answer here?
not sure if there’s a better way, but I do it like this:
filterContent = {"Count" : 1,
"ShallHaveCount" : 1,
"icon" : "CustomFilterListTemplate",
"isLeaf" : 1,
"list" : ["A"],
"name" : "myNewFilter"
}
filterController = Font.fontView.glyphsGroupViewController()
filters = filterController.glyphGroups()[2]["subGroup"]
filters.append(filterContent)
filterController.update()
That looks very good.
Any updates on this? It doesn’t seem to work anymore with Glyphs 3.
from Foundation import NSMutableDictionary
font = Glyphs.font
filterController = font.fontView.glyphsGroupViewController()
glyphGroups = filterController.glyphGroups()
filters = glyphGroups[3]
print(filters)
flt = NSMutableDictionary.dictionaryWithObjectsAndKeys_(
True, "isLeaf",
"MyListFilter", "name",
["A", "B"], "list",
"CustomFilterListTemplate", "icon",
None
)
# Neither of those two options work:
# filters.insertObject_inSubItemsAtIndex_(flt, 0)
# filters.insertSubItems_atIndex_([flt], 0)
filterController.update()
Alternatively, is there a way to filter the font view from within a script temporarily without adding a filter to the sidebar?
Alternatively, is there a way to filter the font view from within a script temporarily without adding a filter to the sidebar?
I have thought the same thing a few years ago:
class SearchState(object):
ALL = 0
NAME = 1
UNICODE = 2
NOTE = 3
@staticmethod
def make_key(key, searchField):
if Glyphs.versionNumber < 3.0:
return 'GlyphList{0}'.format(key)
return searchField.key_(key)
@classmethod
def set_state_in_font(cls, font, state, search=False):
controller = font.fontView
searchField = controller.glyphSearchField()
searchField.setStringValue_(state.pattern)
Glyphs.defaults[cls.make_key('SearchState', searchField)] = state.mode
Glyphs.defaults[cls.make_key('SearchStateMatchCase', searchField)] = state.match_case
Glyphs.defaults[cls.make_key('SearchStateRegex', searchField)] = state.regex
if search:
controller.filterGlyphs_(searchField)
@classmethod
def from_font(cls, font):
controller = font.fontView
searchField = controller.glyphSearchField()
return cls(
searchField.stringValue(),
Glyphs.defaults[cls.make_key('SearchState', searchField)],
bool(Glyphs.defaults[cls.make_key('SearchStateMatchCase', searchField)]),
bool(Glyphs.defaults[cls.make_key('SearchStateRegex', searchField)])
)
def __init__(self, pattern, mode=0, match_case=False, regex=False):
self.pattern = pattern
self.mode = mode if not regex else self.NAME
self.match_case = match_case
self.regex = regex
def perform_temporal_search(self, font):
prev = self.from_font(font)
try:
self.set_state_in_font(font, self, search=True)
finally:
self.set_state_in_font(font, prev, search=False)
@classmethod
def reset(cls, font):
cls.set_state_in_font(font, cls.from_font(font), search=True)
if __name__ == '__main__':
SearchState('A|B|C', mode=SearchState.NAME, match_case=True, regex=True).perform_temporal_search(Glyphs.font)
I came up with the code above. My idea at that time was to perform a regex search, and then restore only the UI state as if nothing happened.
To add a new filter:
GSSidebarItem = objc.lookUpClass("GSSidebarItem")
font = Glyphs.font
filterController = font.fontView.glyphsGroupViewController()
glyphGroups = filterController.glyphGroups()
filters = glyphGroups[3]
print(filters)
newItem = GSSidebarItem.new()
newItem.setName_("MyListFilter1")
newItem.setCoverage_(["A", "B"])
newItem.setIconName_("CustomFilterListTemplate")
newItem.setItemType_(3)
filters.insertObject_inSubItemsAtIndex_(newItem, len(filters.subItems()))
filterController.didChangeSidebarItem_(filters)
And to temporarily change the sorting in Font view:
from AppKit import NSSortDescriptor
font = Glyphs.font
glyphsArrayController = font.fontView.glyphsArrayController()
glyphsArrayController.setSortDescriptors_([NSSortDescriptor.alloc().initWithKey_ascending_("layer0.LSB", True)])
And when you like to use a predefined list of names:
GSSortDescriptorNameList = objc.lookUpClass("GSSortDescriptorNameList")
font = Glyphs.font
glyphsArrayController = font.fontView.glyphsArrayController()
sortDescriptor = GSSortDescriptorNameList.alloc().initWithKey_ascending_("name", True)
sortDescriptor.setReferenceList_(["z", "y", "x"])
glyphsArrayController.setSortDescriptors_([sortDescriptor])
Whoa. I can even set up a filter smarter than a smart filter:
newItem = GSSidebarItem.new()
newItem.setName_("MySmartFilter1")
newItem.setPredicate_(NSPredicate.predicateWithFormat_("""\
NOT (name MATCHES '[A-Z].+')
AND ((name CONTAINS 'acute') OR (name CONTAINS 'grave'))
AND (export == 1)
AND ((layer0.countOfPaths > 0) OR (layer0.countOfComponents > 0))
"""))
newItem.setIconName_('CustomFilterPredicateTemplate')
newItem.setItemType_(3)
This will be definitely a time saver for me. Thanks for the snippets!
I am trying to use this code to implement a temporarily change to the sorting in the Font view using a pre-defined list of names. I’m able to see the Font View change successfully, but after a second or two, it updates again and restores back to the standard view. This didn’t happen when I was running the plugin on Glyphs2, so that leads me to think this is something new in Glyphs3. Is there some way to prevent the fontview from updating again or to preserve the predefined sort for longer?
Following up on this @GeorgSeifert. Any idea why this is happening?
I used the script and the sorting is still there even after I worked on the font for some time.
But any selection in the sidebar and adding/removing glyphs will most likely reset it.
Ah, thanks! It seems one of the instances of Glyphs.font.fontView.glyphsGroupViewController().update() in my script was being re-run for some reason, clearing the view.
I’m working on a Python-based filter using the technique described in this thread. I’d like the order of the subset of glyphs to be as it would be in unfiltered view. Is there a simple way to achieve this?
What exactly are you doing. A NSPredicate based filter should not alter the sorting. For list filters, you control the order yourself.
I am working on a filter that shows all glyphs not found (by name) in the other opened font (only works with exactly 2 fonts open).
This is what I have got so far:
#MenuTitle: Glyphset Diff
# encoding: utf-8
__doc__='''
Shows the glyphs that are not present in the other font.
'''
from GlyphsApp import *
if (len(Glyphs.documents) == 2):
thisFont = Glyphs.currentDocument.font
otherDocument = [doc for doc in Glyphs.documents if doc is not Glyphs.currentDocument][0]
otherFont = otherDocument.font
thisGlyphnames = set([glyph.name for glyph in thisFont.glyphs])
otherGlyphnames = set([glyph.name for glyph in otherFont.glyphs])
diff = list(thisGlyphnames - otherGlyphnames)
# https://forum.glyphsapp.com/t/create-list-filter-via-script/2134/7
GSSortDescriptorNameList = objc.lookUpClass("GSSortDescriptorNameList")
glyphsArrayController = thisFont.fontView.glyphsArrayController()
sortDescriptor = GSSortDescriptorNameList.alloc().initWithKey_ascending_("name", True)
sortDescriptor.setReferenceList_(diff)
glyphsArrayController.setSortDescriptors_([sortDescriptor])
else:
Message('Please make sure that\nexactly two fonts are open', '')
This works but the order is somewhat random. I’d like the order of the glyphs to be as it would be in unfiltered view.
You might not need that GSSortDescriptorNameList part.
And have you checked it diff is in the order you expect?
Oh, now I understand. It was the use of sets that jumbled the order!
I can simply use:
diff = [glyph.name for glyph in thisFont.glyphs if not glyph.name in otherGlyphnames]
Just tried this and it gives me the desired order.
Seems like GSfont.glyphs always returns a nicely sorted list, or was I just lucky?
How would it work without a GSSortDescriptorNameList? Can it be simplified?
If you only set the filter, the underlying order should be preserved.
You were looking at the wrong sample code. It was about sorting, not filtering.
# MenuTitle: Glyphset Diff
# encoding: utf-8
__doc__ = '''
Shows the glyphs that are not present in the other font.
'''
from GlyphsApp import *
if len(Glyphs.documents) == 2:
thisFont = Glyphs.documents[0].font
otherFont = Glyphs.documents[1].font
otherGlyphnames = set(otherFont.glyphNames())
diff = [glyph for glyph in thisFont.glyphs if glyph.name not in otherGlyphnames]
fontView = thisFont.fontView
glyphsArrayController = fontView.glyphsArrayController()
predicate = fontView.predicateForNameList_negative_(diff, False)
glyphsArrayController.setFilterPredicate_(predicate)
else:
Message('Please make sure that\nexactly two fonts are open', '')
Ah this is the original reason why I asked about this API ![]()