Excluding files from FileDialog

I would like to show only “editable” files in a FileDailog. A natural way of doing this seems to me to exclude certain extensions, e.g. .EXE and .JPG.
I know the wildcard parameter allows you to specify extensions to *include", but not a far as I know to exclude.
If the user always kept the FileDIalog in the same directory, I could do this my checking what files are there an constructing a wildcard filter to only include the ones I want. But this won’t work if they change the directory. If I had a way of detecting when they change directory, changing the filter when that happened might work, but I can’t find a way of doing this (there doesn’t seem to be anything like a OnDirChange event).
Rob Cliffe

It’s possible to specify a wildcard that matches multiple file extensions. See https://www.blog.pythonlibrary.org/2011/02/10/wxpython-showing-2-filetypes-in-wx-filedialog/

I took that example and modified it to work with latest wxPython. I then added a list of wanted file extensions. It seems to work OK using wxPython 4.2.3 gtk3 (phoenix) wxWidgets 3.2.7 + Python 3.12.3 + Linux Mint 22.1.

import wx

wanted_extns = "*.py;*.c;*.txt"

# Doesn't match files with no extension
wildcard = f"Editable Files|{wanted_extns}"

class MyForm(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY,
                          "Multi-file type wx.FileDialog Tutorial")
        panel = wx.Panel(self, wx.ID_ANY)
        btn = wx.Button(panel, label="Open File Dialog")
        btn.Bind(wx.EVT_BUTTON, self.onOpenFile)

    def onOpenFile(self, event):
        """
        Create and show the Open FileDialog
        """
        dlg = wx.FileDialog(
            self, message="Choose a file",
            defaultFile="",
            wildcard=wildcard,
            style=wx.FD_OPEN | wx.FD_MULTIPLE | wx.FD_CHANGE_DIR
        )
        if dlg.ShowModal() == wx.ID_OK:
            paths = dlg.GetPaths()
            print()
            "You chose the following file(s):"
            for path in paths:
                print(path)
        dlg.Destroy()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()

EDIT: alternatively, perhaps you could create your own dialog containing a wx.FileCtrl object, which supports EVT_FILECTRL_FOLDERCHANGED events.

Thanks, but I already knew that (sorry if that wasn’t clear from my original post). My requirement was to include any and all extensions (not known in advance) that occur in the files in a directory, except for excluding a list of certain ones. Rob Cliffe

Yes, I had noticed that “*.” does not match files with no extension. That seems like a bug. Or is it something to do with the underlying wxWidgets framework? Best, Rob Cliffe

I found that (on linux at least) a single asterisk ‘*’ does match a file with no extension. However, it also matches all files which is not what you require.

I had a brief look in the wxPython and wxWidgets code for FileDialog but couldn’t find any evidence that the wildcard pattern matching is actually performed in either, so I assume it is done in the platform specific toolkits (gtk/msw).

I did notice in the wxWidgets source code for the generic version of the FileCtrl class (wxWidgets/src/generic/filectrlg.cpp at 26c988ee8a4576a981a2c1b5b7334017f41f1825 · wxWidgets/wxWidgets · GitHub) there is an UpdateFiles() method (line 484) which looks like it does apply the wildcard pattern matching itself. However, that method does not appear to be exposed in wxPython. In any case, I would not be able to experiment with it as the generic version is not used on linux.

The only solution I can think of to meet your requirements would be to create your own bespoke file dialog.

OK. Thanks for looking into this, Robin.
Do you know of anywhere where I can find some example code of someone creating their own bespoke file dialog?
That would almost certainly save me some time.
Thanks again,
Rob

I haven’t managed to find any example code.

I think for most applications the valid file types can be specified by a limited number of file extensions. In the case where there is an ‘All files’ pattern in the wildcards and the user chooses a file the application can’t handle, the usual behaviour is to display an error message. I can see that you want to avoid that situation for your application, but it seems that most developers just use the existing dialog despite its limitations.

If you seriously, desperately need this specific feature and absolutely need a custom control, I believe there should be a way to convert the generic implementation of wx.FileDialog from C++ to pure wxPython.

This 400-line file:

https://github.com/wxWidgets/wxWidgets/blob/ea2beaaf5b5e0846cc15e9c58e047d282c03d7bc/src/generic/filedlgg.cp

Plus some stuff from:

May get you there. Not simple and not quick, but definitely doable. We have done much worse in the past :blush:.

Andrea.

Many thanks.
Rob Cliffe