Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
N
nbUI
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
DISCO Beamline
nbUI
Commits
46f92f78
Commit
46f92f78
authored
Feb 1, 2021
by
hugo chauvet
Browse files
Options
Downloads
Patches
Plain Diff
Add selectfiles ui
parent
1e6f750c
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
nbUI/selectfiles.py
+253
-0
253 additions, 0 deletions
nbUI/selectfiles.py
with
253 additions
and
0 deletions
nbUI/selectfiles.py
0 → 100644
+
253
−
0
View file @
46f92f78
#!/usr/bin/env python3
"""
Simple files selector build on top of IpyWidgets
Author: H.Chauvet
"""
import
logging
import
os
import
ipywidgets
as
widgets
def
list_files
(
path
:
str
,
search
:
[
str
,
None
]
=
None
,
hidden
:
bool
=
False
,
fileexts
:
[
list
,
None
]
=
None
)
->
list
:
"""
Get the list of files from the given path.
List of files could be filtered by search term
or with file extension list.
Parameters
----------
path: string,
The path to scann for folders
search: string or None,
The search term to filter the folder list
hiiden: boolean,
Do we return hidden file
fileexts: list of string, or None,
Extension that must end the filename. format should be lowercase
and start with a dot such as [
'
.jpeg
'
,
'
.png
'
]
Return a list of folder names
"""
if
path
.
startswith
(
'
~
'
):
path
=
os
.
path
.
expanduser
(
path
)
abspath
=
os
.
path
.
abspath
(
os
.
path
.
dirname
(
path
))
listf
=
os
.
listdir
(
abspath
)
# Create a fullpath to those listed paths
listall
=
tuple
(
os
.
path
.
join
(
abspath
,
p
)
for
p
in
listf
)
# Keep only basename
listf
=
(
os
.
path
.
basename
(
p
)
for
p
in
listall
if
not
os
.
path
.
isdir
(
p
))
listdir
=
(
os
.
path
.
basename
(
p
)
for
p
in
listall
if
os
.
path
.
isdir
(
p
))
# filter extensions
if
isinstance
(
fileexts
,
(
list
,
tuple
))
and
len
(
fileexts
)
>
0
:
listf
=
(
p
for
p
in
listf
if
os
.
path
.
splitext
(
p
)[
1
]
in
fileexts
)
listall
=
tuple
(
listdir
)
+
tuple
(
listf
)
if
not
hidden
:
listall
=
(
p
for
p
in
listall
if
not
p
.
strip
().
startswith
(
'
.
'
))
if
search
is
not
None
and
len
(
search
)
>
0
:
listall
=
(
p
for
p
in
listall
if
search
in
p
)
return
tuple
(
listall
)
class
SelectFiles
():
"""
A simple folder selector build on top of ipywidgets.
"""
def
__init__
(
self
,
init_path
=
'
./
'
,
fileext
=
None
,
autoclose
=
False
,
show_hidden
=
False
,
load_callback
=
None
,
layout
=
widgets
.
Layout
()):
"""
autoclose: boolean,
Do we need to autoclose the widget when select button is clicked. The default is True
fileext: List of extension or None,
File extension, to filter files in the file list
to end with the given list of extension end (such as tif,
jpeg)
show_hidden: boolean,
If True show hidden files in file list. Default is False.
load_callback: function or None,
Function called when the select button is clicked. Default action is None
layout: None or ipywidgets.Layout object,
Layout to pass to the VBox model
"""
self
.
callback
=
load_callback
self
.
selected_files
=
[]
self
.
autoclose
=
autoclose
self
.
hidden
=
show_hidden
self
.
fileext
=
fileext
self
.
init_path
=
init_path
self
.
wpath
=
widgets
.
Text
(
value
=
init_path
,
placeholder
=
'
Enter the path (../ to go back, / start at disk root, ~/ start at your Home)
'
,
description
=
''
,
disabled
=
False
,
layout
=
widgets
.
Layout
(
width
=
'
auto
'
)
)
self
.
wpathlist
=
widgets
.
SelectMultiple
(
value
=
[],
options
=
list_files
(
init_path
,
hidden
=
self
.
hidden
,
fileexts
=
self
.
fileext
),
layout
=
widgets
.
Layout
(
min_height
=
'
110px
'
,
width
=
'
auto
'
)
)
self
.
wselectbtn
=
widgets
.
Button
(
description
=
'
Select File(s)
'
,
disabled
=
True
,
button_style
=
'
info
'
,
# 'success', 'info', 'warning', 'danger' or ''
tooltip
=
'
Search or select a file in the list above
'
,
icon
=
'
caret-square-o-up
'
,
layout
=
widgets
.
Layout
(
width
=
'
auto
'
)
)
# Connect to callback
self
.
wpath
.
observe
(
self
.
autocomplete
,
names
=
'
value
'
)
self
.
wpathlist
.
observe
(
self
.
on_list_select
,
'
value
'
)
self
.
wselectbtn
.
on_click
(
self
.
on_click
)
# Build the layout
self
.
box
=
widgets
.
AppLayout
(
header
=
self
.
wpath
,
left_sidebar
=
None
,
center
=
self
.
wpathlist
,
right_sidebar
=
None
,
footer
=
self
.
wselectbtn
,
layout
=
layout
)
def
autocomplete
(
self
,
val
):
"""
Perform the autocompletion of the directory that match with the input
path in val parameter
"""
nval
=
val
[
'
new
'
]
# Do we add str to path or we are deleting the path
forward
=
bool
(
len
(
val
[
'
new
'
])
>
len
(
val
[
'
old
'
]))
search_in_path
=
os
.
path
.
basename
(
nval
).
strip
()
if
nval
.
strip
()
==
''
:
nval
=
'
./
'
try
:
good_paths
=
list_files
(
nval
,
search_in_path
,
hidden
=
self
.
hidden
,
fileexts
=
self
.
fileext
)
except
Exception
as
err
:
logging
.
error
(
err
)
good_paths
=
None
if
good_paths
is
None
:
self
.
wpathlist
.
options
=
[
'
Not a valid Path
'
]
self
.
wselectbtn
.
disabled
=
True
self
.
wselectbtn
.
button_style
=
'
danger
'
self
.
wselectbtn
.
description
=
'
Not a valid file or path!
'
self
.
wselectbtn
.
icon
=
'
times-circle-o
'
self
.
wpathlist
.
value
=
[]
else
:
# Update list of paths
self
.
wpathlist
.
options
=
good_paths
# Update the select button style
if
len
(
good_paths
)
==
0
:
# Something wrong no file found
self
.
wselectbtn
.
disabled
=
True
self
.
wselectbtn
.
button_style
=
'
danger
'
self
.
wselectbtn
.
description
=
'
Not a valid file!
'
self
.
wselectbtn
.
icon
=
'
times-circle-o
'
self
.
wpathlist
.
value
=
[]
else
:
if
len
(
self
.
wpathlist
.
value
)
==
0
:
self
.
wselectbtn
.
disabled
=
True
self
.
wselectbtn
.
button_style
=
'
info
'
self
.
wselectbtn
.
description
=
'
Select file(s) [0/%i]
'
%
(
len
(
self
.
wpathlist
.
options
))
self
.
wselectbtn
.
icon
=
'
caret-square-o-up
'
if
forward
:
# Auto fill files name if only one name remains
if
len
(
search_in_path
)
>
0
:
fstarts
=
tuple
(
p
for
p
in
good_paths
if
p
.
startswith
(
search_in_path
))
if
len
(
fstarts
)
==
1
:
tmp
=
self
.
wpath
.
value
base
=
os
.
path
.
dirname
(
tmp
)
lastdir
=
os
.
path
.
basename
(
tmp
)
lastdir
=
lastdir
.
replace
(
lastdir
,
fstarts
[
0
])
self
.
wpath
.
value
=
os
.
path
.
join
(
base
,
lastdir
)
# If only one good path found, enter to the folder if the name is completed
if
len
(
good_paths
)
==
1
:
# Auto enter in the folder if it's a folder or select the file if it's a file
if
good_paths
[
0
]
==
search_in_path
and
os
.
path
.
isdir
(
os
.
path
.
expanduser
(
self
.
wpath
.
value
)):
self
.
wpath
.
value
=
self
.
wpath
.
value
+
'
/
'
# If it's a valid file autoselect it
if
good_paths
[
0
]
==
search_in_path
and
not
os
.
path
.
isdir
(
os
.
path
.
expanduser
(
self
.
wpath
.
value
)):
self
.
wselectbtn
.
disabled
=
False
self
.
wselectbtn
.
button_style
=
'
success
'
self
.
wselectbtn
.
description
=
'
Load %s file
'
%
os
.
path
.
basename
(
self
.
wpath
.
value
)
# remove the last / in path str
self
.
wselectbtn
.
icon
=
'
check
'
def
on_list_select
(
self
,
val
):
"""
Callback when selected folder in list are changed
"""
nselected
=
val
[
'
new
'
]
if
len
(
nselected
)
>
0
:
self
.
wselectbtn
.
disabled
=
False
self
.
wselectbtn
.
button_style
=
'
success
'
self
.
wselectbtn
.
description
=
'
Load (%i) file
'
%
len
(
nselected
)
self
.
wselectbtn
.
icon
=
'
check
'
else
:
self
.
wselectbtn
.
disabled
=
True
self
.
wselectbtn
.
button_style
=
'
info
'
self
.
wselectbtn
.
description
=
'
Select files(s) [0/%i]
'
%
(
len
(
self
.
wpathlist
.
options
))
self
.
wselectbtn
.
icon
=
'
caret-square-o-up
'
def
on_click
(
self
,
val
):
"""
Call back when the load button is clicked
"""
if
'
~
'
in
self
.
wpath
.
value
:
rpath
=
os
.
path
.
expanduser
(
self
.
wpath
.
value
)
else
:
rpath
=
self
.
wpath
.
value
if
len
(
self
.
wpathlist
.
value
)
>
0
:
self
.
selected_files
=
[
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
rpath
),
p
))
for
p
in
self
.
wpathlist
.
value
]
else
:
self
.
selected_files
=
[
os
.
path
.
abspath
(
rpath
)]
if
self
.
autoclose
:
self
.
box
.
close
()
if
self
.
callback
is
not
None
:
try
:
self
.
callback
(
self
.
selected_files
)
except
Exception
as
err
:
logging
.
error
(
err
)
def
__call__
(
self
):
return
self
.
box
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment