Skip to content

[ENH] Added dropdown to select drives and to select files from the tree view while selecting location of new project #475

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4304f32
Added dropdown to select drives in new project
sumana-2705 Mar 7, 2025
c49869e
Merge branch 'neuroinformatics-unit:main' into mount_external_drives
sumana-2705 Mar 13, 2025
aa38d36
updated UI of the Tree for clean view
sumana-2705 Mar 13, 2025
11140ca
Merge branch 'mount_external_drives' of https://github.com/sumana-270…
sumana-2705 Mar 13, 2025
42f41cd
made changes as per suggestions
sumana-2705 Mar 14, 2025
f5facb7
Merge branch 'neuroinformatics-unit:main' into mount_external_drives
sumana-2705 Mar 14, 2025
4db86db
Resolved merge conflicts
sumana-2705 Mar 23, 2025
8f00f79
used psutil replacing win32api
sumana-2705 Mar 23, 2025
4b08cbb
checked functionality in Mac and adjusted code
sumana-2705 Mar 23, 2025
9447c18
wrote code for linux and mac combinely
sumana-2705 Mar 23, 2025
a7b14fe
Merge branch 'neuroinformatics-unit:main' into mount_external_drives
sumana-2705 Jun 2, 2025
6064b31
included suggested changes
sumana-2705 Jun 2, 2025
b62f967
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 2, 2025
357ac51
Added tests for SelectDirectoryTree Modal screen
sumana-2705 Jun 10, 2025
ef40da9
Merge branch 'neuroinformatics-unit:main' into mount_external_drives
sumana-2705 Jun 10, 2025
c268f76
Merge branch 'mount_external_drives' of https://github.com/sumana-270…
sumana-2705 Jun 10, 2025
d1bc05f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 10, 2025
44a09f9
corrected tests
sumana-2705 Jun 15, 2025
6577f49
updated tests for SelectDirectoryTreeScreen
sumana-2705 Jun 15, 2025
7db7b69
corrected tests for SelectDirectoryTreeScreen
sumana-2705 Jun 15, 2025
7045467
Resolved merge conflicts in test_tui_selectdirectorytree_modalscreen.py
sumana-2705 Jun 15, 2025
9b1befa
Merge branch 'neuroinformatics-unit:main' into mount_external_drives
sumana-2705 Jun 18, 2025
ca78172
Added dropdown to select drives in new project
sumana-2705 Mar 7, 2025
429301c
checked functionality in Mac and adjusted code
sumana-2705 Mar 23, 2025
cd5026b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 10, 2025
0861abc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 18, 2025
1e1868a
corrected id in the modal_dialogs.py file
sumana-2705 Jun 18, 2025
92cccfa
Add `psutil` to `pyproject.toml`
JoeZiminski Jun 19, 2025
1b1802c
Merge branch 'main' into mount_external_drives
JoeZiminski Jun 19, 2025
b18a321
Refactor get_selected_drive and update test to use monkeypatching
sumana-2705 Jun 20, 2025
c52de58
Merge branch 'mount_external_drives' of https://github.com/sumana-270…
sumana-2705 Jun 20, 2025
262d001
Merge remote-tracking branch 'upstream/main' into mount_external_drives
JoeZiminski Jun 21, 2025
37a5826
Fix tests.
JoeZiminski Jun 21, 2025
41eaf07
Use base dir on macos.
JoeZiminski Jun 21, 2025
f2076d9
Small changes.
JoeZiminski Jun 21, 2025
1fc26d2
Use psutil disk_partitions(all=True)
JoeZiminski Jun 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion datashuttle/tui/screens/modal_dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@
from datashuttle.tui.app import TuiApp
from datashuttle.utils.custom_types import InterfaceOutput, Prefix

import platform
from pathlib import Path

import psutil
from textual.containers import Container, Horizontal
from textual.screen import ModalScreen
from textual.widgets import Button, Input, Label, LoadingIndicator, Static
from textual.widgets import (
Button,
Input,
Label,
LoadingIndicator,
Select,
Static,
)

from datashuttle.tui.custom_widgets import CustomDirectoryTree
from datashuttle.tui.utils.tui_decorators import (
Expand Down Expand Up @@ -201,6 +210,12 @@ def compose(self) -> ComposeResult:

yield Container(
Static(label_message, id="select_directory_tree_screen_label"),
Select(
[(drive, drive) for drive in self.get_drives()],
value=self.get_selected_drive(),
allow_blank=False,
id="select_directory_tree_drive_select",
),
CustomDirectoryTree(
self.mainwindow,
self.path_,
Expand All @@ -210,6 +225,48 @@ def compose(self) -> ComposeResult:
id="select_directory_tree_container",
)

@staticmethod
def get_drives():
"""
Get drives available on the machine to switch between.
For Windows, use `psutil` to get the list of drives.
Otherwise, assume root is "/" and take all folders from that level.
"""
operating_system = platform.system()

assert operating_system in [
"Windows",
"Darwin",
"Linux",
], f"Unexpected operating system: {operating_system} encountered."

if platform.system() == "Windows":
return [disk.device for disk in psutil.disk_partitions(all=True)]

else:
return ["/"] + [
f"/{dir.name}" for dir in Path("/").iterdir() if dir.is_dir()
]

def get_selected_drive(self):
"""
Get the default drive which the select starts on. For windows,
use the .drive attribute but for macOS and Linux this is blank.
On these Os use the first folder (e.g. /Users) as the default drive.
"""
if platform.system() == "Windows":
selected_drive = f"{self.path_.drive}\\"
else:
selected_drive = f"/{self.path_.parts[1]}"
return selected_drive

def on_select_changed(self, event: Select.Changed) -> None:
"""Updates the directory tree when the drive is changed."""
self.path_ = Path(event.value)
self.query_one("#select_directory_tree_directory_tree").path = (
self.path_
)

@require_double_click
def on_directory_tree_directory_selected(
self, event: DirectoryTree.DirectorySelected
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ dependencies = [
"textual==3.4.0",
"show-in-file-manager",
"gitpython",
"typeguard"
"typeguard",
"psutil"
]

classifiers = [
Expand Down
58 changes: 58 additions & 0 deletions tests/tests_tui/test_tui_selectdirectorytree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import pytest
from tui_base import TuiBase

from datashuttle.tui.app import TuiApp
from datashuttle.tui.screens.modal_dialogs import (
SelectDirectoryTreeScreen,
)


class TestSelectTree(TuiBase):
@pytest.mark.asyncio
async def test_select_directory_tree(self, monkeypatch):
"""
Test that changing the drive in SelectDirectoryTreeScreen
updates the DirectoryTree path as expected.
"""

# Set the Select drives to be these test cases
monkeypatch.setattr(
SelectDirectoryTreeScreen,
"get_selected_drive",
staticmethod(lambda: "Drive1"),
)

monkeypatch.setattr(
SelectDirectoryTreeScreen,
"get_drives",
staticmethod(lambda: ["Drive1", "Drive2"]),
)

app = TuiApp()
async with app.run_test() as pilot:

# Open the select directory tree screen
await self.scroll_to_click_pause(
pilot, "#mainwindow_new_project_button"
)

await self.scroll_to_click_pause(
pilot, "#configs_local_path_select_button"
)
assert isinstance(pilot.app.screen, SelectDirectoryTreeScreen)

# Switch the select, and ensure the directory tree is updated as expected
tree = pilot.app.screen.query_one(
"#select_directory_tree_directory_tree"
)
select = pilot.app.screen.query_one(
"#select_directory_tree_drive_select"
)

select.value = "Drive1"
await pilot.pause()
assert str(tree.path) == "Drive1"

select.value = "Drive2"
await pilot.pause()
assert str(tree.path) == "Drive2"
Loading