Loading src/nova/trame/model/data_selector.py +31 −32 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ import os from pathlib import Path from typing import Any, List, Optional from typing import Any, Dict, List, Optional from warnings import warn from natsort import natsorted Loading Loading @@ -140,7 +140,7 @@ class DataSelectorModel: return natsorted(experiments) def sort_directories(self, directories: List[Any]) -> List[Any]: def sort_directories(self, directories: List[Dict[str, Any]]) -> List[Dict[str, Any]]: # Sort the current level of dictionaries sorted_dirs = natsorted(directories, key=lambda x: x["title"]) Loading @@ -164,9 +164,11 @@ class DataSelectorModel: return Path(self.state.custom_directory) def get_directories(self) -> List[str]: def get_directories(self, base_path: Optional[Path] = None) -> List[Dict[str, Any]]: using_custom_directory = self.state.facility == CUSTOM_DIRECTORIES_LABEL if using_custom_directory: if base_path: pass elif using_custom_directory: base_path = self.get_custom_directory_path() else: base_path = self.get_experiment_directory_path() Loading @@ -176,16 +178,13 @@ class DataSelectorModel: directories = [] try: if using_custom_directory: for entry in os.listdir(base_path): path = base_path / entry if os.path.isdir(path): directories.append({"path": str(path), "title": entry}) else: for dirpath, _, _ in os.walk(base_path): for dirpath, dirs, _ in os.walk(base_path): # Get the relative path from the start path path_parts = os.path.relpath(dirpath, base_path).split(os.sep) if len(path_parts) > 1: dirs.clear() # Only create a new entry for top-level directories if len(path_parts) == 1 and path_parts[0] != ".": # This indicates a top-level directory current_dir = {"path": dirpath, "title": path_parts[0]} Loading src/nova/trame/view/components/data_selector.py +2 −0 Original line number Diff line number Diff line Loading @@ -133,8 +133,10 @@ class DataSelector(datagrid.VGrid): activatable=True, active_strategy="single-independent", classes="flex-1-0 h-0 overflow-y-auto", fluid=True, item_value="path", items=(self._directories_name,), click_open=(self._vm.expand_directory, "[$event.path]"), update_activated=(self._vm.set_directory, "$event"), ) vuetify.VListItem("No directories found", classes="flex-0-1 text-center", v_else=True) Loading src/nova/trame/view/theme/assets/core_style.scss +8 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,14 @@ html { white-space: pre-wrap; } .nova-data-selector { .v-list-group { .v-treeview-item { --indent-padding: 1em !important; } } } .nova-data-selector revo-grid { font-family: 'Roboto', sans-serif; font-size: 0.75rem !important; Loading src/nova/trame/view_model/data_selector.py +24 −1 Original line number Diff line number Diff line """View model implementation for the DataSelector widget.""" import os from pathlib import Path from typing import Any, Dict, List, Optional from nova.mvvm.interface import BindingInterface Loading @@ -14,6 +15,8 @@ class DataSelectorViewModel: self.model = model self.datafiles: List[Dict[str, Any]] = [] self.directories: List[Dict[str, Any]] = [] self.expanded: List[str] = [] self.state_bind = binding.new_bind(self.model.state, callback_after_update=self.on_state_updated) self.facilities_bind = binding.new_bind() Loading @@ -23,6 +26,25 @@ class DataSelectorViewModel: self.datafiles_bind = binding.new_bind() self.reset_bind = binding.new_bind() def expand_directory(self, paths: List[str]) -> None: if paths[-1] in self.expanded: return # TODO: refactor/clean this up as it's confusing new_directories = self.model.get_directories(Path(paths[-1])) current_level: Any = self.directories for current_path in paths: if isinstance(current_level, Dict): current_level = current_level["children"] for entry in current_level: if current_path == entry["path"]: current_level = entry break current_level["children"] = new_directories self.expanded.append(paths[-1]) self.directories_bind.update_in_view(self.directories) def set_directory(self, directory_path: str = "") -> None: self.model.set_directory(directory_path) self.update_view() Loading @@ -33,6 +55,7 @@ class DataSelectorViewModel: def reset(self) -> None: self.model.set_directory("") self.directories = self.model.get_directories() self.reset_bind.update_in_view(None) def on_state_updated(self, results: Dict[str, Any]) -> None: Loading @@ -55,7 +78,7 @@ class DataSelectorViewModel: self.facilities_bind.update_in_view(self.model.get_facilities()) self.instruments_bind.update_in_view(self.model.get_instruments()) self.experiments_bind.update_in_view(self.model.get_experiments()) self.directories_bind.update_in_view(self.model.get_directories()) self.directories_bind.update_in_view(self.directories) self.datafiles = [ {"path": datafile, "title": os.path.basename(datafile)} for datafile in self.model.get_datafiles() Loading Loading
src/nova/trame/model/data_selector.py +31 −32 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ import os from pathlib import Path from typing import Any, List, Optional from typing import Any, Dict, List, Optional from warnings import warn from natsort import natsorted Loading Loading @@ -140,7 +140,7 @@ class DataSelectorModel: return natsorted(experiments) def sort_directories(self, directories: List[Any]) -> List[Any]: def sort_directories(self, directories: List[Dict[str, Any]]) -> List[Dict[str, Any]]: # Sort the current level of dictionaries sorted_dirs = natsorted(directories, key=lambda x: x["title"]) Loading @@ -164,9 +164,11 @@ class DataSelectorModel: return Path(self.state.custom_directory) def get_directories(self) -> List[str]: def get_directories(self, base_path: Optional[Path] = None) -> List[Dict[str, Any]]: using_custom_directory = self.state.facility == CUSTOM_DIRECTORIES_LABEL if using_custom_directory: if base_path: pass elif using_custom_directory: base_path = self.get_custom_directory_path() else: base_path = self.get_experiment_directory_path() Loading @@ -176,16 +178,13 @@ class DataSelectorModel: directories = [] try: if using_custom_directory: for entry in os.listdir(base_path): path = base_path / entry if os.path.isdir(path): directories.append({"path": str(path), "title": entry}) else: for dirpath, _, _ in os.walk(base_path): for dirpath, dirs, _ in os.walk(base_path): # Get the relative path from the start path path_parts = os.path.relpath(dirpath, base_path).split(os.sep) if len(path_parts) > 1: dirs.clear() # Only create a new entry for top-level directories if len(path_parts) == 1 and path_parts[0] != ".": # This indicates a top-level directory current_dir = {"path": dirpath, "title": path_parts[0]} Loading
src/nova/trame/view/components/data_selector.py +2 −0 Original line number Diff line number Diff line Loading @@ -133,8 +133,10 @@ class DataSelector(datagrid.VGrid): activatable=True, active_strategy="single-independent", classes="flex-1-0 h-0 overflow-y-auto", fluid=True, item_value="path", items=(self._directories_name,), click_open=(self._vm.expand_directory, "[$event.path]"), update_activated=(self._vm.set_directory, "$event"), ) vuetify.VListItem("No directories found", classes="flex-0-1 text-center", v_else=True) Loading
src/nova/trame/view/theme/assets/core_style.scss +8 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,14 @@ html { white-space: pre-wrap; } .nova-data-selector { .v-list-group { .v-treeview-item { --indent-padding: 1em !important; } } } .nova-data-selector revo-grid { font-family: 'Roboto', sans-serif; font-size: 0.75rem !important; Loading
src/nova/trame/view_model/data_selector.py +24 −1 Original line number Diff line number Diff line """View model implementation for the DataSelector widget.""" import os from pathlib import Path from typing import Any, Dict, List, Optional from nova.mvvm.interface import BindingInterface Loading @@ -14,6 +15,8 @@ class DataSelectorViewModel: self.model = model self.datafiles: List[Dict[str, Any]] = [] self.directories: List[Dict[str, Any]] = [] self.expanded: List[str] = [] self.state_bind = binding.new_bind(self.model.state, callback_after_update=self.on_state_updated) self.facilities_bind = binding.new_bind() Loading @@ -23,6 +26,25 @@ class DataSelectorViewModel: self.datafiles_bind = binding.new_bind() self.reset_bind = binding.new_bind() def expand_directory(self, paths: List[str]) -> None: if paths[-1] in self.expanded: return # TODO: refactor/clean this up as it's confusing new_directories = self.model.get_directories(Path(paths[-1])) current_level: Any = self.directories for current_path in paths: if isinstance(current_level, Dict): current_level = current_level["children"] for entry in current_level: if current_path == entry["path"]: current_level = entry break current_level["children"] = new_directories self.expanded.append(paths[-1]) self.directories_bind.update_in_view(self.directories) def set_directory(self, directory_path: str = "") -> None: self.model.set_directory(directory_path) self.update_view() Loading @@ -33,6 +55,7 @@ class DataSelectorViewModel: def reset(self) -> None: self.model.set_directory("") self.directories = self.model.get_directories() self.reset_bind.update_in_view(None) def on_state_updated(self, results: Dict[str, Any]) -> None: Loading @@ -55,7 +78,7 @@ class DataSelectorViewModel: self.facilities_bind.update_in_view(self.model.get_facilities()) self.instruments_bind.update_in_view(self.model.get_instruments()) self.experiments_bind.update_in_view(self.model.get_experiments()) self.directories_bind.update_in_view(self.model.get_directories()) self.directories_bind.update_in_view(self.directories) self.datafiles = [ {"path": datafile, "title": os.path.basename(datafile)} for datafile in self.model.get_datafiles() Loading