Metadata-Version: 2.4
Name: fry-qt6-io-widget
Version: 0.1.0
Summary: A reusable PyQt6 widget for selecting input/output paths, with four file/folder I/O modes, drag-and-drop, validation and auto-sync.
Author: FanRenYi
License: MIT
Project-URL: Homepage, https://gitlab.com/fanrenyi33/fry_python_lib_d130_fry_qt6_io_widget
Project-URL: Repository, https://gitlab.com/fanrenyi33/fry_python_lib_d130_fry_qt6_io_widget
Project-URL: Issues, https://gitlab.com/fanrenyi33/fry_python_lib_d130_fry_qt6_io_widget/-/issues
Keywords: pyqt6,qt6,widget,io,file-dialog,drag-and-drop
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: User Interfaces
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PyQt6>=6.2.0
Requires-Dist: QtAwesome>=1.2.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-qt>=4.2; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# fry-qt6-io-widget

[![Python](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org)
[![PyQt6](https://img.shields.io/badge/PyQt6-6.2%2B-green.svg)](https://pypi.org/project/PyQt6/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

A reusable **PyQt6** widget for picking input and output paths.

Four I/O modes out of the box:

| Mode | Input | Output | Example use case |
|------|-------|--------|------------------|
| **A** | Folder | Folder | Batch image processing |
| **B** | Folder | File   | Aggregate a directory into one report |
| **C** | File   | Folder | Extract / decompose an archive |
| **D** | File   | File   | One-shot conversion (md → html) |

Built-in features:

- Drag-and-drop a file or folder onto the input box
- Live path validity check (✓ exists / ○ will be created / ✗ invalid)
- Auto-sync: output path is generated from input path (postfix + optional timestamp)
- Opens the input/output location in the OS file manager
- `get_params_dict()` / `load_params_dict()` for trivial persistence
- Ships as a **`QWidget`** — wrap it in a `QDockWidget` yourself if you need that (see [examples/example_dock_wrapper.py](examples/example_dock_wrapper.py))

---

## Install

```bash
pip install fry-qt6-io-widget
```

Requires Python 3.8+, PyQt6 ≥ 6.2, and QtAwesome ≥ 1.2.

## Quick start

```python
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow
from fry_qt6_io_widget import FryIOWidget, IOMode

app = QApplication(sys.argv)
win = QMainWindow()

widget = FryIOWidget(mode=IOMode.FOLDER_TO_FOLDER)
win.setCentralWidget(widget)

widget.input_path_changed.connect(lambda p: print("in:", p))
widget.output_path_changed.connect(lambda p: print("out:", p))

win.show()
sys.exit(app.exec())
```

### Pick a mode

```python
FryIOWidget(mode=IOMode.FOLDER_TO_FOLDER)   # A
FryIOWidget(mode=IOMode.FOLDER_TO_FILE)     # B
FryIOWidget(mode=IOMode.FILE_TO_FOLDER)     # C
FryIOWidget(mode=IOMode.FILE_TO_FILE)       # D
```

Or switch at runtime:

```python
widget.set_mode(IOMode.FILE_TO_FILE)
```

### Use it as a dock

The package intentionally ships only a `QWidget`. Wrapping it in a dock
is three lines:

```python
from PyQt6.QtWidgets import QDockWidget
from PyQt6.QtCore import Qt

dock = QDockWidget("输入输出", main_window)
dock.setWidget(FryIOWidget(mode=IOMode.FOLDER_TO_FOLDER))
main_window.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, dock)
```

A complete runnable example is in
[examples/example_dock_wrapper.py](examples/example_dock_wrapper.py).

### Useful options

```python
FryIOWidget(
    mode=IOMode.FOLDER_TO_FILE,
    output_path_postfix="_report",          # appended to the auto-generated output
    output_use_timestamp=True,              # also append HH:MM:SS.mmm
    input_file_filter="Images (*.png *.jpg);;All (*)",
    output_file_filter="CSV (*.csv)",
    default_output_extension=".csv",        # used in modes B and D
)
```

### Helpful methods

```python
widget.get_input_path()                     # -> str
widget.get_output_path()                    # -> str
widget.set_input_path("/some/path")
widget.set_output_path("/elsewhere")

widget.get_params_dict()                    # serialise current state
widget.load_params_dict(params)             # restore it

widget.create_output_folder_if_needed()     # mkdir -p for the output directory
widget.compute_auto_output_path("/foo")     # preview what auto-sync would generate
```

### Signals

| Signal | Payload | When |
|--------|---------|------|
| `input_path_changed`  | `str` | input text changes |
| `output_path_changed` | `str` | output text changes |

---

## Examples

Five runnable examples are in [`examples/`](examples/):

- `example_a_folder_to_folder.py` — mode A
- `example_b_folder_to_file.py`   — mode B
- `example_c_file_to_folder.py`   — mode C
- `example_d_file_to_file.py`     — mode D
- `example_mode_switcher.py`      — switch modes via combobox
- `example_dock_wrapper.py`       — wrap into a `QDockWidget`

Run any of them:

```bash
python examples/example_a_folder_to_folder.py
```

---

## Core concepts

For internals (auto-sync rules, path-validity states, how each mode
re-uses the same UI), see [docs/CORE_CONCEPTS.md](docs/CORE_CONCEPTS.md).

---

## Development

```bash
git clone https://gitlab.com/fanrenyi33/fry_python_lib_d130_fry_qt6_io_widget.git
cd fry_python_lib_d130_fry_qt6_io_widget
pip install -e ".[dev]"
pytest
```

To build distributions:

```bash
python -m build
# dist/fry_qt6_io_widget-0.1.0-py3-none-any.whl
# dist/fry_qt6_io_widget-0.1.0.tar.gz
```

## License

MIT — see [LICENSE](LICENSE).
