Skip to content

Commit

Permalink
ENH: Enable unloading data and loading dicom directories (#36)
Browse files Browse the repository at this point in the history
Selected data can be unloaded from memory or removed from settings.

All data in settings can cleared.

FileDialog updated to enable directory selection - the first series
of DICOM data in that directory is then loaded.
  • Loading branch information
aylward authored May 22, 2024
1 parent 712accf commit 0b6838d
Show file tree
Hide file tree
Showing 16 changed files with 520 additions and 114 deletions.
42 changes: 41 additions & 1 deletion src/minder3d/lib/sovImageTablePanelWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,41 @@ def __init__(self, gui, state, parent=None):

self.imageTableWidget.cellClicked.connect(self.select_data_by_table)

self.imageTableUnloadButton.clicked.connect(self.unload_image)
self.imageTableRemoveButton.clicked.connect(self.remove_image)
self.imageTableRemoveAllButton.clicked.connect(self.remove_all)
self.imageTableExpandButton.clicked.connect(self.expand_table)

self.enlarged_table = None

self.fill_table()

@time_and_log
def unload_image(self):
self.gui.unload_image(self.state.current_image_num, False)
self.fill_table()

def remove_image(self):
self.settings.remove_data(
self.state.image_filename[self.state.current_image_num]
)
self.gui.unload_image(self.state.current_image_num, False)
self.fill_table()

def remove_all(self):
num_images = len(self.state.image_filename)
for i in range(num_images - 1, 0, -1):
self.settings.remove_data(self.state.image_filename[i])
self.gui.unload_image(self.state.current_image_num, False)
self.settings.clear_data()
self.fill_table()

def expand_table(self):
if self.enlarged_table is None:
self.enlarged_table = ImageTablePanelWidget(self.gui, self.state)
self.enlarged_table.setWindowTitle('Image Table')
self.enlarged_table.show()

@time_and_log
def update_image(self):
self.fill_table()
Expand Down Expand Up @@ -272,9 +305,16 @@ def select_data_by_table(self, row, _):
if row < len(self.state.image_filename):
self.state.current_image_num = row
self.gui.update_image()

if self.state.view2D_overlay_auto_update:
self.gui.update_overlay()
elif (
row > 0
and row == len(self.state.image_filename)
and self.state.scene_filename
== self.imageTableWidget.item(row, 3).text()
):
# current scene
return
else:
if self.imageTableWidget.item(row, 1).text() == 'Image':
self.gui.load_image(self.imageTableWidget.item(row, 3).text())
Expand Down
153 changes: 139 additions & 14 deletions src/minder3d/lib/sovImageTablePanelWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,145 @@
<number>3</number>
</property>
<item>
<widget class="QTableWidget" name="imageTableWidget">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="imageTableWidget">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="imageTableUnloadButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>7</pointsize>
</font>
</property>
<property name="text">
<string>Unload</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="imageTableRemoveButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>7</pointsize>
</font>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="imageTableRemoveAllButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>7</pointsize>
</font>
</property>
<property name="text">
<string>Remove All</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="imageTableExpandButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>23</width>
<height>23</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>23</width>
<height>23</height>
</size>
</property>
<property name="font">
<font>
<pointsize>7</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>. . .</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
Expand Down
49 changes: 49 additions & 0 deletions src/minder3d/lib/sovImageTableSettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ def __init__(self):
os.makedirs(os.path.dirname(settings_file), exist_ok=True)
super().__init__(settings_file, QSettings.IniFormat)

@time_and_log
def clear_data(self):
self.clear()
self.sync()

@time_and_log
def get_file_records(self):
"""Get file records from the settings.
Expand Down Expand Up @@ -150,6 +155,50 @@ def add_data(self, obj, filename, file_type, thumbnail_pixmap=None):
self.endArray()
self.sync()

@time_and_log
def remove_data(self, filename):
"""Remove a file from the settings.
This function removes a file from the settings.
Args:
filename: The name of the file to be removed from settings.
Raises:
IndexError: If the input list is empty.
"""
file_records = self.get_file_records()
if len(file_records) == 1 and file_records[0].filename == filename:
self.clear()
self.sync()
return
self.beginWriteArray('files')
for i, file in enumerate(file_records):
if file.filename == filename:
if file.file_thumbnail != '' and os.path.exists(
file.file_thumbnail
):
os.remove(file.file_thumbnail)
for j in range(i + 1, len(file_records)):
next_file = file_records[j]
self.setArrayIndex(j - 1)
self.setValue('file_filename', next_file.file_filename)
self.setValue('file_type', next_file.file_type)
self.setValue('file_spacing', next_file.file_spacing)
self.setValue('file_size', next_file.file_size)
self.setValue('file_thumbnail', next_file.file_thumbnail)
self.sync()
return
else:
self.setArrayIndex(i)
self.setValue('filename', file.filename)
self.setValue('file_type', next_file.file_type)
self.setValue('file_spacing', next_file.file_spacing)
self.setValue('file_size', next_file.file_size)
self.setValue('file_thumbnail', next_file.file_thumbnail)
self.sync()
return

@time_and_log
def get_thumbnail(self, obj, filename, file_type):
"""Get the thumbnail of a file.
Expand Down
7 changes: 3 additions & 4 deletions src/minder3d/lib/sovObjectPanelWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def update_highlight_selected(self, value):
"""
self.state.highlight_selected = value
for selected_id in self.state.selected_ids:
self.log(f'update_highlight_selected: Id={selected_id}')
self.gui.log(f'update_highlight_selected: Id={selected_id}')
so = self.state.scene_list[
self.state.scene_list_ids.index(selected_id)
]
Expand All @@ -101,10 +101,10 @@ def unselect_all_objects(self):
"""
for selected_idx, selected_so_id in enumerate(self.state.selected_ids):
if selected_so_id != -1:
scene_idx = self.state.scene_list_ids.index(selected_so_id)
self.state.selected_ids[selected_idx] = -1
scene_idx = self.state.scene_list_ids.index(selected_so_id)
selected_so = self.state.scene_list[scene_idx]
self.redraw_object(selected_so)
self.gui.redraw_object(selected_so)
self.state.selected_ids = []
self.state.selected_point_ids = []

Expand Down Expand Up @@ -248,7 +248,6 @@ def delete_selected_objects(self):
This function deletes the selected objects from the scene by removing them from the scene list and updating the GUI accordingly.
"""
for so_id in self.state.selected_ids:
print('deleting so_id:', so_id)
scene_idx = self.state.scene_list_ids.index(so_id)
so = self.state.scene_list[scene_idx]
so_parent = so.GetParent()
Expand Down
Loading

0 comments on commit 0b6838d

Please sign in to comment.