12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- import platform
- from pathlib import Path
- from typing import Optional
- from nicegui import events, ui
- class local_file_picker(ui.dialog):
- def __init__(self, directory: str, *,
- upper_limit: Optional[str] = ..., multiple: bool = False, show_hidden_files: bool = False) -> None:
- """Local File Picker
- This is a simple file picker that allows you to select a file from the local filesystem where NiceGUI is running.
- :param directory: The directory to start in.
- :param upper_limit: The directory to stop at (None: no limit, default: same as the starting directory).
- :param multiple: Whether to allow multiple files to be selected.
- :param show_hidden_files: Whether to show hidden files.
- """
- super().__init__()
- self.path = Path(directory).expanduser()
- if upper_limit is None:
- self.upper_limit = None
- else:
- self.upper_limit = Path(directory if upper_limit == ... else upper_limit).expanduser()
- self.show_hidden_files = show_hidden_files
- with self, ui.card():
- self.add_drives_toggle()
- self.grid = ui.aggrid({
- 'columnDefs': [{'field': 'name', 'headerName': 'File'}],
- 'rowSelection': 'multiple' if multiple else 'single',
- }, html_columns=[0]).classes('w-96').on('cellDoubleClicked', self.handle_double_click)
- with ui.row().classes('w-full justify-end'):
- ui.button('Cancel', on_click=self.close).props('outline')
- ui.button('Ok', on_click=self._handle_ok)
- self.update_grid()
- def add_drives_toggle(self):
- if platform.system() == 'Windows':
- import win32api
- drives = win32api.GetLogicalDriveStrings().split('\000')[:-1]
- self.drives_toggle = ui.toggle(drives, value=drives[0], on_change=self.update_drive)
- def update_drive(self):
- self.path = Path(self.drives_toggle.value).expanduser()
- self.update_grid()
- def update_grid(self) -> None:
- paths = list(self.path.glob('*'))
- if not self.show_hidden_files:
- paths = [p for p in paths if not p.name.startswith('.')]
- paths.sort(key=lambda p: p.name.lower())
- paths.sort(key=lambda p: not p.is_dir())
- self.grid.options['rowData'] = [
- {
- 'name': f'📁 <strong>{p.name}</strong>' if p.is_dir() else p.name,
- 'path': str(p),
- }
- for p in paths
- ]
- if (self.upper_limit is None and self.path != self.path.parent) or \
- (self.upper_limit is not None and self.path != self.upper_limit):
- self.grid.options['rowData'].insert(0, {
- 'name': '📁 <strong>..</strong>',
- 'path': str(self.path.parent),
- })
- self.grid.update()
- def handle_double_click(self, e: events.GenericEventArguments) -> None:
- self.path = Path(e.args['data']['path'])
- if self.path.is_dir():
- self.update_grid()
- else:
- self.submit([str(self.path)])
- async def _handle_ok(self):
- rows = await self.grid.get_selected_rows()
- self.submit([r['path'] for r in rows])
|