fennil 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fennil-1.3.0/.gitignore +6 -0
- fennil-1.3.0/LICENSE +21 -0
- fennil-1.3.0/PKG-INFO +114 -0
- fennil-1.3.0/README.md +79 -0
- fennil-1.3.0/pyproject.toml +113 -0
- fennil-1.3.0/src/fennil/__init__.py +1 -0
- fennil-1.3.0/src/fennil/app/__init__.py +5 -0
- fennil-1.3.0/src/fennil/app/components/__init__.py +4 -0
- fennil-1.3.0/src/fennil/app/components/file_browser.py +202 -0
- fennil-1.3.0/src/fennil/app/components/scale.py +65 -0
- fennil-1.3.0/src/fennil/app/core.py +330 -0
- fennil-1.3.0/src/fennil/app/deck/__init__.py +7 -0
- fennil-1.3.0/src/fennil/app/deck/builder.py +18 -0
- fennil-1.3.0/src/fennil/app/deck/faults.py +117 -0
- fennil-1.3.0/src/fennil/app/deck/mapbox.py +32 -0
- fennil-1.3.0/src/fennil/app/deck/primitives.py +130 -0
- fennil-1.3.0/src/fennil/app/deck/stations.py +25 -0
- fennil-1.3.0/src/fennil/app/deck/styles.py +43 -0
- fennil-1.3.0/src/fennil/app/deck/tde.py +38 -0
- fennil-1.3.0/src/fennil/app/deck/tooltips.py +21 -0
- fennil-1.3.0/src/fennil/app/deck/vectors.py +45 -0
- fennil-1.3.0/src/fennil/app/geo_projs.py +128 -0
- fennil-1.3.0/src/fennil/app/io.py +309 -0
- fennil-1.3.0/src/fennil/app/main.py +10 -0
- fennil-1.3.0/src/fennil/app/registry.py +91 -0
- fennil-1.3.0/src/fennil/app/state.py +53 -0
- fennil-1.3.0/src/fennil/app/viz/__init__.py +29 -0
- fennil-1.3.0/src/fennil/app/viz/fault_proj.py +49 -0
- fennil-1.3.0/src/fennil/app/viz/locs.py +38 -0
- fennil-1.3.0/src/fennil/app/viz/mod.py +45 -0
- fennil-1.3.0/src/fennil/app/viz/mog.py +38 -0
- fennil-1.3.0/src/fennil/app/viz/obs.py +45 -0
- fennil-1.3.0/src/fennil/app/viz/res.py +45 -0
- fennil-1.3.0/src/fennil/app/viz/res_compare.py +27 -0
- fennil-1.3.0/src/fennil/app/viz/rot.py +45 -0
- fennil-1.3.0/src/fennil/app/viz/seg.py +45 -0
- fennil-1.3.0/src/fennil/app/viz/slip.py +62 -0
- fennil-1.3.0/src/fennil/app/viz/str.py +38 -0
- fennil-1.3.0/src/fennil/app/viz/tde.py +41 -0
- fennil-1.3.0/src/fennil/app/viz/tri.py +45 -0
fennil-1.3.0/.gitignore
ADDED
fennil-1.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Brendan Meade
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
fennil-1.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fennil
|
|
3
|
+
Version: 1.3.0
|
|
4
|
+
Summary: Viewer for kinematic earthquake simulations
|
|
5
|
+
Author: Kitware, Inc.
|
|
6
|
+
Author-email: Brendan Meade <brendanjmeade@gmail.com>
|
|
7
|
+
License: MIT License
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: Application,Framework,Interactive,Python,Web
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Web Environment
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: numpy
|
|
20
|
+
Requires-Dist: pandas<3
|
|
21
|
+
Requires-Dist: pydeck
|
|
22
|
+
Requires-Dist: trame-dataclass
|
|
23
|
+
Requires-Dist: trame-deckgl>=2.0.4
|
|
24
|
+
Requires-Dist: trame-vuetify
|
|
25
|
+
Requires-Dist: trame>=3.12
|
|
26
|
+
Provides-Extra: app
|
|
27
|
+
Requires-Dist: pywebview; extra == 'app'
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: nox; extra == 'dev'
|
|
30
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-cov>=3; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=6; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
## fennil
|
|
37
|
+
|
|
38
|
+
Attempt at a much faster rebuild of
|
|
39
|
+
[`result_manager`](https://github.com/brendanjmeade/result_manager) for larger
|
|
40
|
+
[`celeri`](https://github.com/brendanjmeade/celeri) models.
|
|
41
|
+
|
|
42
|
+
Viewer for kinematic earthquake simulations
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
This library is OpenSource and follows the MIT License
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
Install the application/library
|
|
51
|
+
|
|
52
|
+
```console
|
|
53
|
+
pip install fennil
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Run the application
|
|
57
|
+
|
|
58
|
+
```console
|
|
59
|
+
fennil
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Mapbox token
|
|
63
|
+
|
|
64
|
+
Set a Mapbox access token so base maps render with Mapbox styles. Either export
|
|
65
|
+
it in your shell or place it in a local `.env` (already gitignored):
|
|
66
|
+
|
|
67
|
+
```console
|
|
68
|
+
export FENNIL_MAP_BOX_TOKEN="YOUR_TOKEN_HERE"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Or create a `.env` file in the project root containing:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
FENNIL_MAP_BOX_TOKEN=YOUR_TOKEN_HERE
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Development setup
|
|
78
|
+
|
|
79
|
+
We recommend using uv for setting up and managing a virtual environment for your
|
|
80
|
+
development.
|
|
81
|
+
|
|
82
|
+
```console
|
|
83
|
+
# Create venv and install all dependencies
|
|
84
|
+
uv sync --all-extras --dev
|
|
85
|
+
|
|
86
|
+
# Activate environment
|
|
87
|
+
source .venv/bin/activate
|
|
88
|
+
|
|
89
|
+
# Install commit analysis
|
|
90
|
+
pre-commit install
|
|
91
|
+
pre-commit install --hook-type commit-msg
|
|
92
|
+
|
|
93
|
+
# Allow live code edit
|
|
94
|
+
uv pip install -e .
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For running tests and checks, you can run `nox`.
|
|
98
|
+
|
|
99
|
+
```console
|
|
100
|
+
# run all
|
|
101
|
+
nox
|
|
102
|
+
|
|
103
|
+
# lint
|
|
104
|
+
nox -s lint
|
|
105
|
+
|
|
106
|
+
# tests
|
|
107
|
+
nox -s tests
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Commit message convention
|
|
111
|
+
|
|
112
|
+
Semantic release rely on
|
|
113
|
+
[conventional commits](https://www.conventionalcommits.org/) to generate new
|
|
114
|
+
releases and changelog.
|
fennil-1.3.0/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
## fennil
|
|
2
|
+
|
|
3
|
+
Attempt at a much faster rebuild of
|
|
4
|
+
[`result_manager`](https://github.com/brendanjmeade/result_manager) for larger
|
|
5
|
+
[`celeri`](https://github.com/brendanjmeade/celeri) models.
|
|
6
|
+
|
|
7
|
+
Viewer for kinematic earthquake simulations
|
|
8
|
+
|
|
9
|
+
## License
|
|
10
|
+
|
|
11
|
+
This library is OpenSource and follows the MIT License
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Install the application/library
|
|
16
|
+
|
|
17
|
+
```console
|
|
18
|
+
pip install fennil
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Run the application
|
|
22
|
+
|
|
23
|
+
```console
|
|
24
|
+
fennil
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Mapbox token
|
|
28
|
+
|
|
29
|
+
Set a Mapbox access token so base maps render with Mapbox styles. Either export
|
|
30
|
+
it in your shell or place it in a local `.env` (already gitignored):
|
|
31
|
+
|
|
32
|
+
```console
|
|
33
|
+
export FENNIL_MAP_BOX_TOKEN="YOUR_TOKEN_HERE"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or create a `.env` file in the project root containing:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
FENNIL_MAP_BOX_TOKEN=YOUR_TOKEN_HERE
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Development setup
|
|
43
|
+
|
|
44
|
+
We recommend using uv for setting up and managing a virtual environment for your
|
|
45
|
+
development.
|
|
46
|
+
|
|
47
|
+
```console
|
|
48
|
+
# Create venv and install all dependencies
|
|
49
|
+
uv sync --all-extras --dev
|
|
50
|
+
|
|
51
|
+
# Activate environment
|
|
52
|
+
source .venv/bin/activate
|
|
53
|
+
|
|
54
|
+
# Install commit analysis
|
|
55
|
+
pre-commit install
|
|
56
|
+
pre-commit install --hook-type commit-msg
|
|
57
|
+
|
|
58
|
+
# Allow live code edit
|
|
59
|
+
uv pip install -e .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
For running tests and checks, you can run `nox`.
|
|
63
|
+
|
|
64
|
+
```console
|
|
65
|
+
# run all
|
|
66
|
+
nox
|
|
67
|
+
|
|
68
|
+
# lint
|
|
69
|
+
nox -s lint
|
|
70
|
+
|
|
71
|
+
# tests
|
|
72
|
+
nox -s tests
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Commit message convention
|
|
76
|
+
|
|
77
|
+
Semantic release rely on
|
|
78
|
+
[conventional commits](https://www.conventionalcommits.org/) to generate new
|
|
79
|
+
releases and changelog.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "fennil"
|
|
3
|
+
version = "1.3.0"
|
|
4
|
+
description = "Viewer for kinematic earthquake simulations"
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "Brendan Meade", email = "brendanjmeade@gmail.com"},
|
|
7
|
+
{name = "Kitware, Inc."},
|
|
8
|
+
]
|
|
9
|
+
dependencies = [
|
|
10
|
+
"trame>=3.12",
|
|
11
|
+
"trame-vuetify",
|
|
12
|
+
"trame-deckgl>=2.0.4",
|
|
13
|
+
"trame-dataclass",
|
|
14
|
+
"pydeck",
|
|
15
|
+
"numpy",
|
|
16
|
+
"pandas<3",
|
|
17
|
+
]
|
|
18
|
+
requires-python = ">=3.10"
|
|
19
|
+
readme = "README.md"
|
|
20
|
+
license = {text = "MIT License"}
|
|
21
|
+
keywords = ["Python", "Interactive", "Web", "Application", "Framework"]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Environment :: Web Environment",
|
|
25
|
+
"License :: OSI Approved :: MIT License",
|
|
26
|
+
"Natural Language :: English",
|
|
27
|
+
"Operating System :: OS Independent",
|
|
28
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
29
|
+
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
30
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
app = [
|
|
35
|
+
"pywebview",
|
|
36
|
+
]
|
|
37
|
+
dev = [
|
|
38
|
+
"pre-commit",
|
|
39
|
+
"ruff",
|
|
40
|
+
"pytest >=6",
|
|
41
|
+
"pytest-cov >=3",
|
|
42
|
+
"nox",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[project.scripts]
|
|
46
|
+
fennil = "fennil.app:main"
|
|
47
|
+
|
|
48
|
+
[build-system]
|
|
49
|
+
requires = ["hatchling"]
|
|
50
|
+
build-backend = "hatchling.build"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
[tool.hatch.build]
|
|
54
|
+
include = [
|
|
55
|
+
"/src/fennil/**/*.py",
|
|
56
|
+
"/src/fennil/**/*.js",
|
|
57
|
+
"/src/fennil/**/*.css",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.hatch.build.targets.wheel]
|
|
61
|
+
packages = [
|
|
62
|
+
"src/fennil",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[tool.ruff]
|
|
66
|
+
|
|
67
|
+
[tool.ruff.lint]
|
|
68
|
+
extend-select = [
|
|
69
|
+
"ARG", # flake8-unused-arguments
|
|
70
|
+
"B", # flake8-bugbear
|
|
71
|
+
"C4", # flake8-comprehensions
|
|
72
|
+
"EM", # flake8-errmsg
|
|
73
|
+
"EXE", # flake8-executable
|
|
74
|
+
"G", # flake8-logging-format
|
|
75
|
+
"I", # isort
|
|
76
|
+
"ICN", # flake8-import-conventions
|
|
77
|
+
"NPY", # NumPy specific rules
|
|
78
|
+
"PD", # pandas-vet
|
|
79
|
+
"PGH", # pygrep-hooks
|
|
80
|
+
"PIE", # flake8-pie
|
|
81
|
+
"PL", # pylint
|
|
82
|
+
"PT", # flake8-pytest-style
|
|
83
|
+
"PTH", # flake8-use-pathlib
|
|
84
|
+
"RET", # flake8-return
|
|
85
|
+
"RUF", # Ruff-specific
|
|
86
|
+
"SIM", # flake8-simplify
|
|
87
|
+
"T20", # flake8-print
|
|
88
|
+
"UP", # pyupgrade
|
|
89
|
+
"YTT", # flake8-2020
|
|
90
|
+
]
|
|
91
|
+
ignore = [
|
|
92
|
+
"PLR09", # Too many <...>
|
|
93
|
+
"PLR2004", # Magic value used in comparison
|
|
94
|
+
"ISC001", # Conflicts with formatter
|
|
95
|
+
]
|
|
96
|
+
isort.required-imports = []
|
|
97
|
+
|
|
98
|
+
[tool.ruff.lint.per-file-ignores]
|
|
99
|
+
"tests/**" = ["T20"]
|
|
100
|
+
"noxfile.py" = ["T20"]
|
|
101
|
+
"src/**" = ["SIM117"]
|
|
102
|
+
|
|
103
|
+
[tool.semantic_release]
|
|
104
|
+
version_toml = [
|
|
105
|
+
"pyproject.toml:project.version",
|
|
106
|
+
]
|
|
107
|
+
version_variables = [
|
|
108
|
+
"src/fennil/__init__.py:__version__",
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
[tool.semantic_release.publish]
|
|
112
|
+
dist_glob_patterns = ["dist/*"]
|
|
113
|
+
upload_to_vcs_release = true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.3.0"
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from trame.widgets import dataclass, html
|
|
4
|
+
from trame.widgets import vuetify3 as v3
|
|
5
|
+
from trame_dataclass.core import StateDataModel
|
|
6
|
+
|
|
7
|
+
from fennil.app.io import is_valid_data_folder
|
|
8
|
+
|
|
9
|
+
FILE_BROWSER_HEADERS = [
|
|
10
|
+
{"title": "Name", "align": "start", "key": "name", "sortable": False},
|
|
11
|
+
{"title": "Type", "align": "start", "key": "type", "sortable": False},
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FileBrowserState(StateDataModel):
|
|
16
|
+
show: bool = False
|
|
17
|
+
current: str = "/"
|
|
18
|
+
listing: list
|
|
19
|
+
active: int = -1
|
|
20
|
+
error: str | None
|
|
21
|
+
headers: list = FILE_BROWSER_HEADERS
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class FileBrowser(dataclass.Provider):
|
|
25
|
+
def __init__(self, current_directory=None, on_open=None, **kwargs):
|
|
26
|
+
if current_directory is None:
|
|
27
|
+
current_directory = Path.cwd()
|
|
28
|
+
self._on_open = on_open
|
|
29
|
+
self._state = None
|
|
30
|
+
super().__init__(name="browser", **kwargs)
|
|
31
|
+
self._state = FileBrowserState(self.server, current=str(current_directory))
|
|
32
|
+
self.instance = self._state._id
|
|
33
|
+
self.update_listing()
|
|
34
|
+
|
|
35
|
+
with (
|
|
36
|
+
self,
|
|
37
|
+
v3.VDialog(
|
|
38
|
+
v_model="browser.show",
|
|
39
|
+
max_width="900",
|
|
40
|
+
persistent=True,
|
|
41
|
+
),
|
|
42
|
+
):
|
|
43
|
+
with v3.VCard(title="Select data folder", rounded="lg"):
|
|
44
|
+
with v3.VCardText():
|
|
45
|
+
with v3.VRow(dense=True, classes="pb-1 align-center"):
|
|
46
|
+
v3.VBtn(
|
|
47
|
+
icon="mdi-home",
|
|
48
|
+
variant="text",
|
|
49
|
+
size="small",
|
|
50
|
+
click=self.go_home,
|
|
51
|
+
)
|
|
52
|
+
v3.VBtn(
|
|
53
|
+
icon="mdi-folder-upload-outline",
|
|
54
|
+
variant="text",
|
|
55
|
+
size="small",
|
|
56
|
+
click=self.go_parent,
|
|
57
|
+
)
|
|
58
|
+
v3.VTextField(
|
|
59
|
+
v_model="browser.current",
|
|
60
|
+
hide_details=True,
|
|
61
|
+
density="compact",
|
|
62
|
+
variant="outlined",
|
|
63
|
+
readonly=True,
|
|
64
|
+
classes="ml-2 flex-grow-1",
|
|
65
|
+
)
|
|
66
|
+
with v3.VDataTable(
|
|
67
|
+
density="compact",
|
|
68
|
+
fixed_header=True,
|
|
69
|
+
headers=["browser.header"],
|
|
70
|
+
items=["browser.listing"],
|
|
71
|
+
height="50vh",
|
|
72
|
+
style="user-select: none; cursor: pointer;",
|
|
73
|
+
items_per_page=-1,
|
|
74
|
+
):
|
|
75
|
+
v3.Template(v_slot_bottom=True)
|
|
76
|
+
with v3.Template(v_slot_item="{ item }"):
|
|
77
|
+
with v3.VDataTableRow(
|
|
78
|
+
item=["item"],
|
|
79
|
+
click=(self.select_entry, "[item]"),
|
|
80
|
+
dblclick=(self.open_entry, "[item]"),
|
|
81
|
+
classes=[
|
|
82
|
+
"{ 'bg-grey-lighten-3': item.index === browser.active }"
|
|
83
|
+
],
|
|
84
|
+
):
|
|
85
|
+
with v3.Template(raw_attrs=["v-slot:item.name"]):
|
|
86
|
+
with html.Div(classes="d-flex align-center"):
|
|
87
|
+
v3.VIcon(
|
|
88
|
+
"{{ item.icon }}",
|
|
89
|
+
size="small",
|
|
90
|
+
classes="mr-2",
|
|
91
|
+
)
|
|
92
|
+
html.Div("{{ item.name }}")
|
|
93
|
+
with v3.Template(raw_attrs=["v-slot:item.type"]):
|
|
94
|
+
html.Div("{{ item.type }}")
|
|
95
|
+
|
|
96
|
+
with v3.VCardActions(classes="pa-3"):
|
|
97
|
+
html.Div(
|
|
98
|
+
"{{ browser.error }}",
|
|
99
|
+
v_if="browser.error",
|
|
100
|
+
classes="text-error text-caption",
|
|
101
|
+
)
|
|
102
|
+
v3.VSpacer()
|
|
103
|
+
v3.VBtn(
|
|
104
|
+
text="Cancel",
|
|
105
|
+
variant="flat",
|
|
106
|
+
click="browser.show = false",
|
|
107
|
+
)
|
|
108
|
+
v3.VBtn(
|
|
109
|
+
text="Select folder",
|
|
110
|
+
color="primary",
|
|
111
|
+
variant="flat",
|
|
112
|
+
click=self.select_folder,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
def update_listing(self):
|
|
116
|
+
current = Path(self._state.current)
|
|
117
|
+
if not current.exists():
|
|
118
|
+
current = Path.home()
|
|
119
|
+
self._state.current = str(current.resolve())
|
|
120
|
+
|
|
121
|
+
entries = []
|
|
122
|
+
for entry in current.iterdir():
|
|
123
|
+
name = entry.name
|
|
124
|
+
if name.startswith("."):
|
|
125
|
+
continue
|
|
126
|
+
if entry.is_dir():
|
|
127
|
+
entries.append(
|
|
128
|
+
{
|
|
129
|
+
"name": name,
|
|
130
|
+
"type": "directory",
|
|
131
|
+
"icon": "mdi-folder",
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
elif entry.is_file():
|
|
135
|
+
entries.append(
|
|
136
|
+
{
|
|
137
|
+
"name": name,
|
|
138
|
+
"type": "file",
|
|
139
|
+
"icon": "mdi-file-document-outline",
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
entries.sort(key=lambda item: (item["type"] != "directory", item["name"]))
|
|
143
|
+
listing = [{**item, "index": idx} for idx, item in enumerate(entries)]
|
|
144
|
+
self._state.listing = listing
|
|
145
|
+
self._state.active = -1
|
|
146
|
+
|
|
147
|
+
def select_entry(self, entry):
|
|
148
|
+
self._state.active = entry.get("index", -1) if entry else -1
|
|
149
|
+
|
|
150
|
+
def open_entry(self, entry):
|
|
151
|
+
if not entry or entry.get("type") != "directory":
|
|
152
|
+
return
|
|
153
|
+
current = Path(self._state.current)
|
|
154
|
+
next_path = (current / entry.get("name")).resolve()
|
|
155
|
+
|
|
156
|
+
if is_valid_data_folder(next_path):
|
|
157
|
+
self._state.error = None
|
|
158
|
+
self._state.show = False
|
|
159
|
+
if self._on_open:
|
|
160
|
+
self._on_open(next_path)
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
self._state.current = str(next_path)
|
|
164
|
+
self.update_listing()
|
|
165
|
+
|
|
166
|
+
def go_home(self):
|
|
167
|
+
self._state.current = str(Path.home().resolve())
|
|
168
|
+
self.update_listing()
|
|
169
|
+
|
|
170
|
+
def go_parent(self):
|
|
171
|
+
current = Path(self._state.current)
|
|
172
|
+
parent = current.parent if current.parent != current else current
|
|
173
|
+
self._state.current = str(parent.resolve())
|
|
174
|
+
self.update_listing()
|
|
175
|
+
|
|
176
|
+
def open(self, existing_path=None):
|
|
177
|
+
if existing_path:
|
|
178
|
+
self._state.current = str(Path(existing_path).resolve())
|
|
179
|
+
|
|
180
|
+
self._state.show = True
|
|
181
|
+
self._state.error = None
|
|
182
|
+
self.update_listing()
|
|
183
|
+
|
|
184
|
+
def select_folder(self):
|
|
185
|
+
current = Path(self._state.current)
|
|
186
|
+
folder_path = current
|
|
187
|
+
active_idx = self._state.active
|
|
188
|
+
listing = self._state.listing
|
|
189
|
+
if active_idx is not None and active_idx >= 0:
|
|
190
|
+
if active_idx >= len(listing):
|
|
191
|
+
active_idx = -1
|
|
192
|
+
else:
|
|
193
|
+
entry = listing[active_idx]
|
|
194
|
+
if entry.get("type") == "directory":
|
|
195
|
+
folder_path = (current / entry.get("name")).resolve()
|
|
196
|
+
if not is_valid_data_folder(folder_path):
|
|
197
|
+
self._state.error = "Selected folder is missing required model_*.csv files."
|
|
198
|
+
return
|
|
199
|
+
self._state.error = None
|
|
200
|
+
self._state.show = False
|
|
201
|
+
if self._on_open:
|
|
202
|
+
self._on_open(folder_path)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from trame.widgets import vuetify3 as v3
|
|
2
|
+
|
|
3
|
+
v3.enable_lab()
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Scale(v3.VCol):
|
|
7
|
+
def __init__(self, name="scale", **kwargs):
|
|
8
|
+
self._name = name
|
|
9
|
+
super().__init__(**kwargs)
|
|
10
|
+
|
|
11
|
+
with self:
|
|
12
|
+
with v3.VRow(dense=True, no_gutter=True):
|
|
13
|
+
with v3.VCol():
|
|
14
|
+
v3.VBtn(
|
|
15
|
+
"50%",
|
|
16
|
+
click=(self.scale, "[0.5]"),
|
|
17
|
+
size="small",
|
|
18
|
+
variant="outlined",
|
|
19
|
+
block=True,
|
|
20
|
+
)
|
|
21
|
+
with v3.VCol():
|
|
22
|
+
v3.VBtn(
|
|
23
|
+
"90%",
|
|
24
|
+
click=(self.scale, "[0.9]"),
|
|
25
|
+
size="small",
|
|
26
|
+
variant="outlined",
|
|
27
|
+
block=True,
|
|
28
|
+
)
|
|
29
|
+
with v3.VCol():
|
|
30
|
+
v3.VBtn(
|
|
31
|
+
"110%",
|
|
32
|
+
click=(self.scale, "[1.1]"),
|
|
33
|
+
size="small",
|
|
34
|
+
variant="outlined",
|
|
35
|
+
block=True,
|
|
36
|
+
)
|
|
37
|
+
with v3.VCol():
|
|
38
|
+
v3.VBtn(
|
|
39
|
+
"200%",
|
|
40
|
+
click=(self.scale, "[2]"),
|
|
41
|
+
size="small",
|
|
42
|
+
variant="outlined",
|
|
43
|
+
block=True,
|
|
44
|
+
)
|
|
45
|
+
with v3.VRow():
|
|
46
|
+
with v3.VCol(classes="pt-0"):
|
|
47
|
+
v3.VNumberInput(
|
|
48
|
+
click_prepend=self.reset,
|
|
49
|
+
prepend_icon="mdi-vector-line",
|
|
50
|
+
v_model=(name, 1),
|
|
51
|
+
precision=6,
|
|
52
|
+
min=[0.0001],
|
|
53
|
+
max=[10000],
|
|
54
|
+
step=[0.01],
|
|
55
|
+
density="compact",
|
|
56
|
+
hide_details=True,
|
|
57
|
+
variant="outlined",
|
|
58
|
+
control_variant="split",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def scale(self, value):
|
|
62
|
+
self.state[self._name] *= value
|
|
63
|
+
|
|
64
|
+
def reset(self):
|
|
65
|
+
self.state[self._name] = 1
|