local_file_picker.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. from pathlib import Path
  2. from typing import Optional
  3. from nicegui import ui
  4. class local_file_picker(ui.dialog):
  5. def __init__(self, directory: str, *,
  6. upper_limit: Optional[str] = None, multiple: bool = False, show_hidden_files: bool = False) -> None:
  7. """Local File Picker
  8. This is a simple file picker that allows you to select a file from the local filesystem where NiceGUI is running.
  9. :param directory: The directory to start in.
  10. :param upper_limit: The directory to stop at. If not specified, the upper limit is the same as the starting directory.
  11. :param multiple: Whether to allow multiple files to be selected.
  12. :param show_hidden_files: Whether to show hidden files.
  13. """
  14. super().__init__()
  15. self.path = Path(directory).expanduser()
  16. self.upper_limit = Path(upper_limit if upper_limit else directory).expanduser()
  17. self.show_hidden_files = show_hidden_files
  18. with self, ui.card():
  19. self.table = ui.table({
  20. 'columnDefs': [{'field': 'name', 'headerName': 'File'}],
  21. 'rowSelection': 'multiple' if multiple else 'single',
  22. }, html_columns=[0]).classes('w-96').on('cellDoubleClicked', self.handle_double_click)
  23. with ui.row().classes('w-full justify-end'):
  24. ui.button('Cancel', on_click=self.close).props('outline')
  25. ui.button('Ok', on_click=self._handle_ok)
  26. self.update_table()
  27. def update_table(self) -> None:
  28. paths = list(self.path.glob('*'))
  29. if not self.show_hidden_files:
  30. paths = [p for p in paths if not p.name.startswith('.')]
  31. paths.sort(key=lambda p: p.name.lower())
  32. paths.sort(key=lambda p: not p.is_dir())
  33. self.table.options['rowData'] = [
  34. {
  35. 'name': f'📁 <strong>{p.name}</strong>' if p.is_dir() else p.name,
  36. 'path': str(p),
  37. } for p in paths
  38. ]
  39. if self.path != self.upper_limit:
  40. self.table.options['rowData'].insert(0, {
  41. 'name': '📁 <strong>..</strong>',
  42. 'path': str(self.path.parent),
  43. })
  44. self.table.update()
  45. async def handle_double_click(self, msg: dict) -> None:
  46. self.path = Path(msg['args']['data']['path'])
  47. if self.path.is_dir():
  48. self.update_table()
  49. else:
  50. self.submit([str(self.path)])
  51. async def _handle_ok(self):
  52. rows = await ui.run_javascript(f'getElement({self.table.id}).gridOptions.api.getSelectedRows()')
  53. self.submit([r['path'] for r in rows])