Metadata-Version: 2.1
Name: whines_crossfiledialog
Version: 1.0.0
Summary: 
Author: whinee
Requires-Python: >=3.12,<3.13
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Requires-Dist: pyqt5 (>=5.15.11,<6.0.0) ; sys_platform == "linux"
Requires-Dist: pyqt6 (>=6.8.0,<7.0.0) ; sys_platform == "linux"
Requires-Dist: pywin32 (>=308,<309) ; sys_platform == "win32"
Requires-Dist: vext-gi (>=0.7.4,<0.8.0) ; sys_platform == "linux"
Description-Content-Type: text/markdown

<h1 align="center" style="font-weight: bold">
    CrossFileDialog
</h1>

<p align="center">
    <a href="https://github.com/whinee/crossfiledialog/issues">
        <img src="https://img.shields.io/github/issues/whinee/crossfiledialog.svg?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAACVUlEQVR4nO3doW5UQRTG8XPaEHwLBgQhCGoQJLwAiiYY3qCG10DgCc/QJ0AgMCTUIkCCqiAhkCBQpNAW0g+xS5pguLv3DPeb3f/P35OZ+XJm7+yIGwEAAAAAALAQSW813pup5zHExtQDGOi0oMZJQY3megmkYjEJpBCBmCEQMwRihkDMVCzmcUGN5tYpEDqkEOcQM3SIGQIxQyBmCMQMgZghEDMVr70cDAvRIWYIxAyBmCEQMwRihkDMEIgZLqjMcB9ihi3LDIGYIRAzYxfzLDN/loyksS4CyczTiNCIEhUvBf9FF4HMjVnULl55I/oKZMy21cXvRwSB2OkpkDFbFoE0QIeYIRAzBGKGQMyMWVTOIQ3QIWYIxAyBmOFgaIYOMUMgZgjEDIGY4WBohg4xw2uvGTrEzFoEklMPYChJ1yPizpKPv87Mj5XjAQAAAACgiW5O6n+bn9zvRsStiNiK2Vy+RsT7iDjIzMMJh7c+JN2W9ELS2T++F/JS0rJ/tWAISXuSjhf4iMuJpIdTj3slSdqV9Gvh7+rMnrk/9fhXiqQLkg6XCOOPD5IuTj2PIXq5D3kQETdGPH9tXsNeL4HsFtS4V1CjuV4C2SmocbOgRnO9BLJVUONSQY3megnkqKDGt4IazfUSyCeTGs31EsirghoHBTUQESHpiqTvI84hPyRdnXoeQ3TRIZn5OSKejCjxNDO72LK6IWlT0rMluuO5pM2px7+SJG1IeiTpaOA29bi3MLq8D5F0OSL24vw+ZDvO70PexewHfD8zv0w2SAAAAAAAsAJ+A9PfbN9hclgfAAAAAElFTkSuQmCC">
    </a>
    <a href="https://github.com/whinee/crossfiledialog/network/members">
        <img src="https://img.shields.io/github/forks/whinee/crossfiledialog.svg?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAABlVBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////gR4oeAAAAhnRSTlMAAQIDBAUGBwgJCwwPERMUFRYXGBseIyQlJiktMzQ5Oz9BREVHSUxNTk9QUVJTVFVWWFlaW1xdXmBiZGVoaWpsbm9xdHp8f4eIiYqLjI2Oj5CSl5qio6Slpqeoqauws7S2usHDxMbHycrR1NbX2Nna29zd3t/g4ebn7/Hy8/T1+Pn6+/z9/sSRs40AAAKSSURBVGje7dn7W9JQHAbwF3RUVmY3I7OyuwEZdiGzm5WVYKVpIkZ2LyshxcwsmReC9+/uBxXZ5qNsnu+eep69P2982A7nZTsH8OLF3QSiqayuZ1PRgJwRmeJKcmEhwp9gReJ+EaSXhvSI3CuaEhIY85wZmVI/+lFa0qYcGbEiSeXIhBXJKkfyViSvHNGdIHYbYsqKTCpviGErMqS8IdqtSHTjMxLGo+NVINoPs/G9Vn1DtJpPikg0RJ/xnCciDeHrNxi+jY9OOW2IyHR5PDa9wd8cN4R2OU2S6UvapofOWZG5qmc+SYo1hF0k56AhbCMp2w3hALHfEA4QbcYyGWuVI9aGOAv1CPqNRi8kEN+zCqKU8IkgQLQ8LrlzgBCCQGyUZGH4Yi3kEOAQyRzsxiZyguQ7aaST5AtpZJBktzSSIXlSGDlCcmmXMNJH8g1kkb3zJK8JI8MkZ3fIIjGSvAdR5PQiya/bRZHORZJLzRBE9r8kyVIMcsiBuE6SxS5IIQ0dowWS5PwFiCD1Zx6+/7PyT/XxMFQj/sbwg3TFO/JMRw1UIrtb7gyOGZ9LP8e2AcqQppvJadOzT/HD/UZsKQbk2ONJE7Dwqa99H7aaNWTn7S+Gz599+/T6UTWLOqtIzY2fa19/bOBWSz3UZQVpWr0K/XVXswbFWUauLC+1LIycElnyJEncXX49626ATEjyapEkXx0EBJECST0CiCIk9eMQR0ohyCMDkEd+7XEBicMFJOgCMi5sIFhXF5S+EC824u1pVR9vT8tGvD0tW3FlT2sd5LdyZJ0F/oxyZJ09ref/509Ym3RhMiJsMkqtEuVl2tJ7JGHAH6+8jh6ZqgdC5XGZOA+xaG3JTD4/PtSmwYuXfzt/AfC5xL1x+uRQAAAAAElFTkSuQmCC">
    </a>
    <a href="https://github.com/whinee/crossfiledialog/stargazers">
        <img src="https://img.shields.io/github/stars/whinee/crossfiledialog.svg?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAB3VBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+9lhkRAAAAnnRSTlMAAQIDBAUGBwgJCgsMDQ8QERMUFRYYGhscICEiIyUmJygpKissLzEzNDU2ODk7PD0/QEFCRUZHSEpNTk9QUVZYWl1eX2JlZmdoa25vcXd4eYCBhIaHiImLjI2RkpWWl5mdnqKjqaqrrK6ws7S1t7u8vb7ExcrLzM3Q0dPU1dbY2dvc3t/h4uPk5ufo6uzt7u/x8vP09fb3+Pn6+/z9/myHqc8AAALNSURBVBgZ7cGJV0xxGAbgd0yjtCgVJUsYZc8SZSxDIctYhmQZhbJlMGRfJqUwoSxJm+77t3I6c5iZe2/d787vOsc58zzIyMj4P3n2t7bu88BRpU/42+MSOKmT027BQdWMWwvntDPuKhxT/INxY6Vwykn+cQIOcffxj7duOGMvE+yBMx4wwX04YqXGRKvhhDYmaYUDCr4yyfB8qBdgimNQzvWaKXrnQLV66tRBtTvUCUOxpVPU0ZZDrYs0cAFK5Q7RwJc8qHSYhpqg0gsaeuWCOltpYgvUuUkTN6DMogmamCxHmrLLqusbjre0h3toqifc3nK8ob66LBsCRd4aX1Mw1BGJDkxRYnTgabgjdKLRV7PEA1OlpyPRTxoV0D5FI8ESGKgeolKDVdBx91KxHjdS1VK5bUh1iModRKqdVK4OqebGqNg7D3Q2jlCpkQ0wsP4jFRrcBEMV3VSmdxlMFHVRkYfFMDW3g0pcz8EMXEGN6Qu5MLMD40zTZBNmVfuFaflWDwtW9TMNsSpYsvAxbXteDovybtOmewWwzB2iLVeyIBH4STEtCKHdIxQa9UOsKkaRD+tgQ9lzCkQXw5bCl7TsZSFs6qZlUdi0QKNlWjHs2UUBH+w5R4EW2POIAg9hS/YYBcZyYMdmitTAjlMUOQk77lAkDBtcQxT5PAdyqynkhdwRCh2G3DUKdUCun0J9EFtEsXJI+Wmis5Mm/JC6RENvdgK13TQUgtQzGvgRzMFvnsAwDTyFUP4k9cIViCu/Qb2fBZDZQZ33jUjg66POdsicZoqJUD6SzAuOMkUQMveZ7MFK6Cy9y2QRiGQNM1GsEYZ8/Uz0PQsSK5hgvDkPJvKax5mgEhLr+VekEjOojPCvNZDIHWNczI9Z+GOMG50HkbOcNnE+H7PKPz/BaWcg476skezywhJvF8mpNjekvEcDa2DZ2sDRVcjIyMj4R34BGVzQ+tbGsbEAAAAASUVORK5CYII=">
    </a>
    <a href="https://github.com/whinee/crossfiledialog/graphs/contributors">
        <img src="https://img.shields.io/github/contributors/whinee/crossfiledialog.svg?style=for-the-badge&logo=data:image/png;base64,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">
    </a>
    
</p>

A Python wrapper for opening files and folders with the native file dialog.

Makes it easy to prompt the user with a native filepicker on all supported platforms.

Currently supports:

- GTK (via PyGObject, Zenity)
- KDE (via KDialog)
- Qt5/6 (via pyqt5/pyqt6)
- Windows 2000 and newer (via PyWin32)

## Note

Guys, I really don't know why, but why does QT and Kdialog have the same UI in my computer? Can someone who knows open an issue and explain it to me? Thank you!

Edit: The explanation has been provided in [this issue comment](https://github.com/maikelwever/crossfiledialog/issues/8#issuecomment-2640213041).

If you know how to add the file picker for MacOS, please consider doing so and make a pull request for it.

## Basic API usage

```python
from crossfiledialog import file_dialog

CrossFileDialog = file_dialog(["zenity"])

filename = CrossFileDialog.open_file()
multiple_filenames = CrossFileDialog.open_multiple()
save_filename = CrossFileDialog.save_file()
foldername = CrossFileDialog.choose_folder()
```

## Documentation

```python
file_dialog(picker_preference: Optional[list[str]] = None) -> BaseFileDialog
```

From a list of (optional) file picker preferences, return the first available implementation. 

Args:
- picker_preference (`Optional[list[str]]`, optional): Order of precedence for picking the file picker implementations. Defaults to `None`.

Raises:
- `NoImplementationFoundException`: Raise when no implementation is found from the list of preferences
- `NoImplementationFoundException`: Raise when no implementation is found for the current platform

Returns:
`BaseFileDialog`: File picker class.

---

```python
CrossFileDialog.open_file(title, start_dir, filter) -> str
```

Open a file selection dialog for selecting a file.

Args:
- title (`str`, optional): The title of the file selection dialog.
    Default is 'Choose a file'
- start_dir (`str`, optional): The starting directory for the dialog.
- filter (`str | list[str | list[str] | dict[str, str]] | dict[str, str | list[str]]`, optional):
    The filter for file types to display. For an example, head to documentation the
    of `crossfiledialog.utils.filter_processor`.

Returns:
`Optional[str]`: The selected file's path.

Example:
result = open_file(title="Select a file", start_dir="/path/to/starting/directory", filter="*.txt")

---

```python
CrossFileDialog.open_multiple(title, start_dir, filter) -> list[str]
```

Open a file selection dialog for selecting multiple files.

Parameters:
 - title (str, optional) — The title of the file selection dialog. Default is 'Choose one or more files'
 - start_dir (str, optional) — The starting directory for the dialog.
 - filter (str, list, dict, optional) — The filter for file types to display. It can be either:
   - a single wildcard (e.g.: `"*.py"`, all files are displayed ending .py)
   - a list of wildcards (e.g.: `["*.py" "*.md"]`, all files are displayed ending either .py or .md)
   - a list of list optional one or more wildcards (e.g.: `[["*.py", "*.md"], ["*.txt"]]`, 
 user can switch between (.py, .md) and (.txt))
   - a dictionary mapping descriptions to wildcards (e.g.: `{"PDF-Files": "*.pdf", "Python Project": ["\*.py", "*.md"]}`)

Returns:
 - list[str]: A list of selected file paths.

---

```python
CrossFileDialog.save_file(title, start_dir) -> str
```
Open a save file dialog.

Parameters:
 - title (str, optional) — The title of the file selection dialog. Default is 'Enter the name of the file to save to'
 - start_dir (str, optional) — The starting directory for the dialog.

Returns:
 - str: The selected file's path for saving.

---

```python
CrossFileDialog.save_file(title, start_dir) -> str
```

Open a folder selection dialog.

Parameters:
 - title (str, optional) — The title of the file selection dialog. Default is 'Choose a folder'
 - start_dir (str, optional) — The starting directory for the dialog.

Returns:
 - str: The selected folder's path.

## Getting Started

Install the following dependencies

- Python 3.12
- [just](https://just.systems/)

In Linux, run the following command:

```sh
just bootstrap
```

or:

```sh
python3.12 -m venv --system-site-packages .venv
source .venv/bin/activate
rm -rf poetry.lock
poetry install --no-root --with dev
```

## Linting

In any platform, run the following command:

```sh
just lint
```

or:

```sh
python -m no_implicit_optional crossfiledialog
python -m black -q school
python -m ruff check crossfiledialog --fix
```

## Attribution

Thank you so much to [Maikel Wever](https://github.com/maikelwever) and [3ricsonn](https://github.com/3ricsonn) for allowing [their Github repository](https://github.com/maikelwever/crossfiledialog) to be relicensed to LGPL 3.0 so that I can use this library in my own proprietary projects.

My deepest gratitude also goes to [Benjamin Auquite](https://github.com/th3w1zard1) for letting me use snippets of their code [from a pull request](https://github.com/beeware/toga/pull/2786) they made to the [Toga](https://github.com/beeware/toga) repository, and to [Russell Keith-Magee](https://github.com/freakboy3742) (the owner of said repository) and [Malcolm Smith](https://github.com/mhsmith) for the advice regarding using BSD 3-Clause licensed code to an LGPL licensed codebase.

Thank you so much!

## License

This software is licensed under the GNU LGPL 3.0.

Copyright (c) 2020-2025 [Maikel Wever](https://github.com/maikelwever)  
Copyright (c) 2024-2025 [whinee](https://github.com/whinee)  

Portions of this codebase, specifically [`crossfiledialog/file_pickers/win32.py`](crossfiledialog/file_pickers/win32.py), are derived from [Toga](https://github.com/beeware/toga), which is licensed under the BSD 3-Clause License.

Copyright (c) 2014 Russell Keith-Magee.  

See [LICENSE.md](docs/LICENSE.md) for full details.


