An open dialog.

    :param parent: window or None
    :param patterns: file match patterns
    :param folder: initial folder
    :param filter: file filter

    Use of filter and patterns at the same time is invalid.

def open_filechooser(title, parent=None, patterns=None,
                     folder=None, filter=None, multiple=False,
                     _before_run=None, action=None):
    """An open dialog.

    :param parent: window or None
    :param patterns: file match patterns
    :param folder: initial folder
    :param filter: file filter

    Use of filter and patterns at the same time is invalid.
    """

    assert not (patterns and filter)
    if multiple:
        if action is not None and action != gtk.FILE_CHOOSER_ACTION_OPEN:
            raise ValueError('`multiple` is only valid for the action '
                             '`gtk.FILE_CHOOSER_ACTION_OPEN`.')
        action = gtk.FILE_CHOOSER_ACTION_OPEN
    else:
        assert action is not None
    filechooser = gtk.FileChooserDialog(title,
                                        parent,
                                        action,
                                        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                         gtk.STOCK_OPEN, gtk.RESPONSE_OK))
    if multiple:
        filechooser.set_select_multiple(True)

    if patterns or filter:
        if not filter:
            filter = gtk.FileFilter()
            for pattern in patterns:
                filter.add_pattern(pattern)
        filechooser.set_filter(filter)
    filechooser.set_default_response(gtk.RESPONSE_OK)

    if folder:
        filechooser.set_current_folder(folder)

    try:
        if _before_run is not None:
            _before_run(filechooser)
        response = filechooser.run()
        if response not in (gtk.RESPONSE_OK, gtk.RESPONSE_NONE):
            return

        if multiple:
            return filechooser.get_filenames()
        else:
            return filechooser.get_filename()
    finally:
        _destroy(filechooser)