How to reset FileFilter and how FileFilter.add_pattern works?

I have a DirectoryList and I want to filter files in it by pattern.
image

My first question is whether it is possible to clear the filled patterns(or all filters of FilterListModel) so that the user enters new values in the Entry to change a single filter, and not add new ones every time.

Now on entry buffer changed callback Im doing this:

# ff here is custom data of the signal
proc entryChanged(self: EntryBuffer, position: int, chars: string, nChars: int, ff: FileFilter) = 
  ff.addPattern(self.text)

It looks like it works only for first entered symbol.
I’m looking for a way to do something like this:

proc entryChanged(self: EntryBuffer, position: int, chars: string, nChars: int, ff: FileFilter) = 
  ff.clear()
  ff.addPattern(self.text)

The second question is why the code below does not work, more precisely, it only works while there is "*" in addPattern.
Putting anything else I get an empty list

I found this example gtk/filefilter.c at 143770f16d43245f2821d1cdddd6ec1c4d92175f · val-verde/gtk · GitHub
And did exactly the same ff.addPattern("D*.st[xy]") and created Dro.sty file, you can see it on screenshot. But I still get an empty list. Any pattern other than * gives an empty list.

import gintro/[gtk4, gobject, gio]
import std/with

# Factory signals
proc getFileName(info: gio.FileInfo): string =
  return info.getName()  

proc setup_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  listitem.setChild(newLabel(""))
  
proc bind_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  let 
    lb = listitem.getChild().Label
    strobj = cast[FileInfo](listitem.getItem())

  lb.text = strobj.getFileName()

proc unbind_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  echo "unbind"

proc teardown_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  listitem.setChild (nil)



# Callbacks
proc entryChanged(self: EntryBuffer, position: int, chars: string, nChars: int, ff: FileFilter) = 
  ff.addPattern(self.text)
  echo self.text

proc activate(app: gtk4.Application) =
  let
    window = newApplicationWindow(app)
    scr = newScrolledWindow()
    file = gio.newGFileForPath(".")
    dl = gtk4.newDirectoryList("standard::name", file)
    ls = listModel(dl)
    ff = newFileFilter()
    fm = newFilterListModel(ls, ff)
    ns = gtk4.newNoSelection(listModel(fm))
    factory = gtk4.newSignalListItemFactory()
    lv = newListView(ns, factory)

    mainBox = newBox(Orientation.vertical, 5)
    patternEntry = newEntry()


  patternEntry.placeholderText = "Enter pattern"
  patternEntry.buffer.connect("inserted_text", entryChanged, ff)

  with mainBox:
    append patternEntry
    append scr

  # ff.addPattern("D*.st[xy]")

  with scr: 
    vexpand = true
    setChild lv

  dl.setMonitored true

  with factory:
    connect("setup", setup_cb)
    connect("bind", bind_cb)
    connect("unbind", unbind_cb)
    connect("teardown", teardown_cb)

  with window:
    defaultSize = (600, 400)
    title = "Nim ListView"
    setChild mainBox
    show

proc main =
  let app = newApplication("org.gtk.example")
  app.connect("activate", activate)
  discard run(app)

main()

GTK version 4.2.1

@matthiasc in IRC told me that the filters are one-time, and you need to create new ones instead of a reset, so I rewrote the callback function, now it takes a FilterListModel and creates a new filter for each character entered.

proc entryChanged(self: EntryBuffer, position: int, chars: string, nChars: int, fm: FilterListModel) = 
  let ff = newFileFilter()
  ff.addPattern(self.text)
  fm.setFilter(ff)
  echo self.text
...
patternEntry.buffer.connect("inserted_text", entryChanged, fm)

But I still have a problem that all patterns except * show an empty list.

I just noticed that even n * in a row, for example **, already show emptiness, thats strange.

The problem was that when initializing DirectoryList, I used “standard:: name” instead of " standard::*". Apparently, a different attribute is used to implement addPattern in FileFilter, maybe displayName
Here the rigth code:

import gintro/[gtk4, gobject, gio]
import std/with

# Factory signals
proc getFileName(info: gio.FileInfo): string =
  return info.getName()  

proc setup_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  listitem.setChild(newLabel(""))
  
proc bind_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  let 
    lb = listitem.getChild().Label
    strobj = cast[FileInfo](listitem.getItem())

  lb.text = strobj.getFileName()

proc unbind_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  echo "unbind"

proc teardown_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  listitem.setChild (nil)



# Callbacks
proc entryChanged(self: EntryBuffer, position: int, chars: string, nChars: int, fm: FilterListModel) = 
  let ff = newFileFilter()
  ff.addPattern(self.text)
  fm.setFilter(ff)
  echo self.text

proc activate(app: gtk4.Application) =
  let
    window = newApplicationWindow(app)
    scr = newScrolledWindow()
    file = gio.newGFileForPath(".")
    dl = gtk4.newDirectoryList("standard::name", file)
    ls = listModel(dl)
    ff = newFileFilter()
    fm = newFilterListModel(ls, ff)
    ns = gtk4.newNoSelection(listModel(fm))
    factory = gtk4.newSignalListItemFactory()
    lv = newListView(ns, factory)

    mainBox = newBox(Orientation.vertical, 5)
    patternEntry = newEntry()

  ff.addPattern("*")

  patternEntry.placeholderText = "Enter pattern"
  patternEntry.buffer.connect("inserted_text", entryChanged, fm)

  with mainBox:
    append patternEntry
    append scr


  with scr: 
    vexpand = true
    setChild lv

  dl.setMonitored true

  with factory:
    connect("setup", setup_cb)
    connect("bind", bind_cb)
    connect("unbind", unbind_cb)
    connect("teardown", teardown_cb)

  with window:
    defaultSize = (600, 400)
    title = "Nim ListView"
    setChild mainBox
    show

proc main =
  let app = newApplication("org.gtk.example")
  app.connect("activate", activate)
  discard run(app)

main()

1 Like