Skip to content

Commit e7cef34

Browse files
committed
Add "Open from directory" action to the "File" menu
1 parent d304506 commit e7cef34

File tree

11 files changed

+176
-5
lines changed

11 files changed

+176
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ See DataLab [roadmap page](https://datalab-platform.com/en/contributing/roadmap.
66

77
💥 New features and enhancements:
88

9+
* Add "Open from directory" action to the "File" menu for both Signal and Image panels
910
* Add `1/x` operation to the "Operations" menu for both Signal and Image panels:
1011
* This feature relies on the `numpy.reciprocal` function, and handles the case where the denominator is zero by catching warnings and replacing the `np.inf` values with `np.nan` values
1112
* Add `compute_inverse` method for image and signal processors

cdl/core/baseproxy.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,14 @@ def load_from_files(self, filenames: list[str]) -> None:
211211
filenames: list of file names
212212
"""
213213

214+
@abc.abstractmethod
215+
def load_from_directory(self, path: str) -> None:
216+
"""Open objects from directory in current panel (signals/images).
217+
218+
Args:
219+
path: directory path
220+
"""
221+
214222
@abc.abstractmethod
215223
def add_signal(
216224
self,
@@ -623,6 +631,14 @@ def load_from_files(self, filenames: list[str]) -> None:
623631
"""
624632
self._cdl.load_from_files(filenames)
625633

634+
def load_from_directory(self, path: str) -> None:
635+
"""Open objects from directory in current panel (signals/images).
636+
637+
Args:
638+
path: directory path
639+
"""
640+
self._cdl.load_from_directory(path)
641+
626642
def get_sel_object_uuids(self, include_groups: bool = False) -> list[str]:
627643
"""Return selected objects uuids.
628644

cdl/core/gui/actionhandler.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,14 @@ def create_first_actions(self):
415415
select_condition=SelectCond.always,
416416
toolbar_pos=-1,
417417
)
418+
self.new_action(
419+
_("Open from directory..."),
420+
icon_name="fileopen_directory.svg",
421+
tip=_("Open %s objects from directory") % self.OBJECT_STR,
422+
triggered=self.panel.load_from_directory,
423+
select_condition=SelectCond.always,
424+
toolbar_pos=-1,
425+
)
418426
self.new_action(
419427
_("Save %s...") % self.OBJECT_STR,
420428
# icon: filesave_signal.svg or filesave_image.svg

cdl/core/gui/main.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,16 @@ def load_from_files(self, filenames: list[str]) -> None:
14931493
panel = self.__get_current_basedatapanel()
14941494
panel.load_from_files(filenames)
14951495

1496+
@remote_controlled
1497+
def load_from_directory(self, path: str) -> None:
1498+
"""Open objects from directory in current panel (signals/images).
1499+
1500+
Args:
1501+
path: directory path
1502+
"""
1503+
panel = self.__get_current_basedatapanel()
1504+
panel.load_from_directory(path)
1505+
14961506
# ------Other methods related to AbstractCDLControl interface
14971507
def get_version(self) -> str:
14981508
"""Return DataLab public version.

cdl/core/gui/panel/base.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import abc
1212
import dataclasses
13+
import glob
1314
import os.path as osp
1415
import re
1516
import warnings
@@ -28,7 +29,12 @@
2829
from plotpy.tools import ActionTool
2930
from qtpy import QtCore as QC
3031
from qtpy import QtWidgets as QW
31-
from qtpy.compat import getopenfilename, getopenfilenames, getsavefilename
32+
from qtpy.compat import (
33+
getexistingdirectory,
34+
getopenfilename,
35+
getopenfilenames,
36+
getsavefilename,
37+
)
3238

3339
from cdl.config import APP_NAME, Conf, _
3440
from cdl.core.gui import actionhandler, objectmodel, objectview
@@ -859,11 +865,38 @@ def __save_to_file(self, obj: TypeObj, filename: str) -> None:
859865
"""
860866
self.IO_REGISTRY.write(filename, obj)
861867

862-
def load_from_files(self, filenames: list[str] | None = None) -> list[TypeObj]:
868+
def load_from_directory(self, directory: str | None = None) -> list[TypeObj]:
869+
"""Open objects from directory (signals or images, depending on the panel),
870+
add them to DataLab and return them.
871+
If the directory is not specified, ask the user to select a directory.
872+
873+
Args:
874+
directory: directory name
875+
876+
Returns:
877+
list of new objects
878+
"""
879+
if not self.mainwindow.confirm_memory_state():
880+
return []
881+
if directory is None: # pragma: no cover
882+
basedir = Conf.main.base_dir.get()
883+
with save_restore_stds():
884+
directory = getexistingdirectory(self, _("Open"), basedir)
885+
if not directory:
886+
return []
887+
# Get all files in the directory:
888+
relfnames = sorted(glob.glob("**/*.*", root_dir=directory, recursive=True))
889+
filenames = [osp.join(directory, fname) for fname in relfnames]
890+
return self.load_from_files(filenames, ignore_unknown=True)
891+
892+
def load_from_files(
893+
self, filenames: list[str] | None = None, ignore_unknown: bool = False
894+
) -> list[TypeObj]:
863895
"""Open objects from file (signals/images), add them to DataLab and return them.
864896
865897
Args:
866898
filenames: File names
899+
ignore_unknown: if True, ignore unknown file types (default: False)
867900
868901
Returns:
869902
list of new objects
@@ -879,7 +912,14 @@ def load_from_files(self, filenames: list[str] | None = None) -> list[TypeObj]:
879912
for filename in filenames:
880913
with qt_try_loadsave_file(self.parent(), filename, "load"):
881914
Conf.main.base_dir.set(filename)
882-
objs += self.__load_from_file(filename)
915+
try:
916+
objs += self.__load_from_file(filename)
917+
except NotImplementedError as exc:
918+
if ignore_unknown:
919+
# Ignore unknown file types
920+
pass
921+
else:
922+
raise exc
883923
return objs
884924

885925
def save_to_files(self, filenames: list[str] | str | None = None) -> None:

cdl/core/remote.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ class RemoteServer(QC.QThread):
145145
SIG_ADD_OBJECT = QC.Signal(object)
146146
SIG_ADD_GROUP = QC.Signal(str, str, bool)
147147
SIG_LOAD_FROM_FILES = QC.Signal(list)
148+
SIG_LOAD_FROM_DIRECTORY = QC.Signal(str)
148149
SIG_SELECT_OBJECTS = QC.Signal(list, str)
149150
SIG_SELECT_GROUPS = QC.Signal(list, str)
150151
SIG_SELECT_ALL_GROUPS = QC.Signal(str)
@@ -174,6 +175,7 @@ def __init__(self, win: CDLMainWindow) -> None:
174175
self.SIG_ADD_OBJECT.connect(win.add_object)
175176
self.SIG_ADD_GROUP.connect(win.add_group)
176177
self.SIG_LOAD_FROM_FILES.connect(win.load_from_files)
178+
self.SIG_LOAD_FROM_DIRECTORY.connect(win.load_from_directory)
177179
self.SIG_SELECT_OBJECTS.connect(win.select_objects)
178180
self.SIG_SELECT_GROUPS.connect(win.select_groups)
179181
self.SIG_SELECT_ALL_GROUPS.connect(lambda panel: win.select_groups(None, panel))
@@ -348,6 +350,15 @@ def load_from_files(self, filenames: list[str]) -> None:
348350
"""
349351
self.SIG_LOAD_FROM_FILES.emit(filenames)
350352

353+
@remote_call
354+
def load_from_directory(self, path: str) -> None:
355+
"""Open objects from directory in current panel (signals/images).
356+
357+
Args:
358+
path: directory path
359+
"""
360+
self.SIG_LOAD_FROM_DIRECTORY.emit(path)
361+
351362
@remote_call
352363
def add_signal(
353364
self,
Lines changed: 60 additions & 0 deletions
Loading
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
1850.0 -0.443
2+
1851.0 -0.288
3+
1852.0 -0.289
4+
1853.0 -0.333
5+
1854.0 -0.304
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
1850.0 -0.443
2+
1851.0 -0.288
3+
1852.0 -0.289
4+
1853.0 -0.333
5+
1854.0 -0.304

cdl/locale/fr/LC_MESSAGES/cdl.po

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
msgid ""
55
msgstr ""
66
"Project-Id-Version: PACKAGE VERSION\n"
7-
"POT-Creation-Date: 2025-03-23 14:48+0100\n"
7+
"POT-Creation-Date: 2025-03-30 15:59+0200\n"
88
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
99
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1010
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -824,6 +824,12 @@ msgstr "Ouvrir un objet %s..."
824824
msgid "Open %s"
825825
msgstr "Ouvrir un objet %s"
826826

827+
msgid "Open from directory..."
828+
msgstr "Ouvrir depuis le répertoire..."
829+
830+
msgid "Open %s objects from directory"
831+
msgstr "Ouvrir des objets %s depuis le répertoire"
832+
827833
msgid "Save %s..."
828834
msgstr "Enregistrer un objet %s..."
829835

@@ -1813,7 +1819,10 @@ msgid ""
18131819
"Do you want to clear current workspace (signals and images) before importing "
18141820
"data from HDF5 files?<br><br>Choosing to ignore this message will prevent it "
18151821
"from being displayed again, and will use the current setting (%s)."
1816-
msgstr "Souhaitez-vous effacer l'espace de travail actuel (signaux et images) avant d'importer des données depuis des fichiers HDF5 ?<br><br>Ignorer ce message empêchera son affichage ultérieur, et utilisera le réglage actuel (%s)."
1822+
msgstr ""
1823+
"Souhaitez-vous effacer l'espace de travail actuel (signaux et images) avant "
1824+
"d'importer des données depuis des fichiers HDF5 ?<br><br>Ignorer ce message "
1825+
"empêchera son affichage ultérieur, et utilisera le réglage actuel (%s)."
18171826

18181827
msgid "No"
18191828
msgstr "Non"

0 commit comments

Comments
 (0)