Search code examples
pythonwxpython

wxPython FileDialog prevent some files from being picked


I am designing some kind of pdf converter. It can merge images and other pdf files into one pdf file. I am using wxPython as GUI framework.

There are two buttons: one to set input files and the second to set the output file. Here are two of my event handlers.

def pick_files(self, event):
    with wx.FileDialog(self, "Pick files", wildcard=self.load_options,
                       style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE) as fileDialog:
        if fileDialog.ShowModal() != wx.ID_CANCEL:
            self.files_list = fileDialog.GetPaths()
            self.convert_and_merge_button.Enable()

def convert_and_merge(self, event):
    with wx.FileDialog(self, "Convert and merge", wildcard=self.save_options,
                       style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog:
        if fileDialog.ShowModal() != wx.ID_CANCEL:
            # pass parameters to Converter class
            self.converter.convert(self.files_list, fileDialog.GetPath())

The problem is that if I pick one of input files as my output file, the program crashes. How can I prevent some files from being picked in a FileDialog?

I am wondering if it's possible to have some kind of MessageBox, like "This file is set as input file. You can't overwrite it." and to get back to FileDialog.


Solution

  • Just check the file name chosen for the output against the input file list, prior to the merge routine.

    import wx
    
    class MyFrame(wx.Frame):
        def __init__(self, *args, **kwargs):
            wx.Frame.__init__(self, *args, **kwargs)
            panel = wx.Panel(self)
            sizer = wx.BoxSizer(wx.HORIZONTAL)
            self.select_button = wx.Button(panel, label="Select files")
            self.convert_and_merge_button = wx.Button(panel, label="Merge files")
            sizer.Add(self.select_button, 0, 0, 0)
            sizer.Add(self.convert_and_merge_button, 0, 0, 0)
            self.select_button.Bind(wx.EVT_BUTTON, self.pick_files)
            self.convert_and_merge_button.Bind(wx.EVT_BUTTON, self.convert_and_merge)
            self.load_options = "Pdf and Image Files |*.pdf;*.gif;*.bmp;*.tif;*.png;"
            self.save_options = "Pdf Files |*.pdf;"
            self.convert_and_merge_button.Enable(False)
            panel.SetSizer(sizer)
    
        def pick_files(self, event):
            with wx.FileDialog(self, "Pick files", wildcard=self.load_options,
                               style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE) as fileDialog:
                if fileDialog.ShowModal() != wx.ID_CANCEL:
                    self.files_list = fileDialog.GetPaths()
                    self.convert_and_merge_button.Enable()
    
        def convert_and_merge(self, event):
            with wx.FileDialog(self, "Convert and merge", wildcard=self.save_options,
                               style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog:
                if fileDialog.ShowModal() != wx.ID_CANCEL:
                    # pass parameters to Converter class
                    merge_file = fileDialog.GetPath()
                    #Test that the output file is not in the input list
                    if merge_file in self.files_list:
                        wx.MessageBox('The chosen output file is in the input files\n Choose another file', 'Error', wx.OK | wx.ICON_INFORMATION)
                        return
                    self.converter(self.files_list, merge_file)
    
        def converter(self, files_list, merge_file):
            print ("Merging:\n"+str(files_list)+"\n into\n"+str(merge_file))
    
    class MyApp(wx.App):
        def OnInit(self):
            frame = MyFrame(None, -1, 'A test dialog')
            frame.Show()
            return True
    
    if __name__ == "__main__":
        app = MyApp()
        app.MainLoop()