Skip to content
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

Add option to remove videos in batch #1382

Merged
merged 10 commits into from
Jul 18, 2023
106 changes: 78 additions & 28 deletions sleap/gui/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,10 @@ def removeVideo(self):
"""Removes selected video from project."""
self.execute(RemoveVideo)

def removeAllVideos(self):
'''Removes All Videos from project'''
self.execute(RemoveAllVideos)

def openSkeletonTemplate(self):
"""Shows gui for loading saved skeleton into project."""
self.execute(OpenSkeleton, template=True)
Expand Down Expand Up @@ -1836,45 +1840,91 @@ def _get_truncation_message(truncation_messages, path, video):
return len(import_list) > 0


class RemoveVideo(EditCommand):

class RemoveAllVideos(EditCommand):
topics = [UpdateTopic.video, UpdateTopic.suggestions]

@staticmethod
def do_action(context: CommandContext, params: dict):
video = params["video"]
# Remove video
context.labels.remove_video(video)

# Update view if this was the current video
if context.state["video"] == video:
if len(context.labels.videos) > 0:
context.state["video"] = context.labels.videos[-1]
else:
context.state["video"] = None
videos = context.labels.videos.copy()
for i in range(len(videos)):
context.labels.remove_video(videos[i])

if len(context.labels.videos):
context.state["video"] = context.labels.videos[-1]
else:
context.state["video"] = None

@staticmethod
def ask(context: CommandContext, params: dict) -> bool:
video = context.state["selected_video"]
if video is None:
return False
videos = context.labels.videos.copy()

for video in videos:
if video is None:
return False

# Count labeled frames for this video
n = len(context.labels.find(video))
# Count labeled frames for this video
n = len(context.labels.find(video))

# Warn if there are labels that will be deleted
if n > 0:
response = QtWidgets.QMessageBox.critical(
context.app,
"Removing video with labels",
f"{n} labeled frames in this video will be deleted, "
"are you sure you want to remove this video?",
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No,
)
if response == QtWidgets.QMessageBox.No:
# Warn if there are labels that will be deleted
if n > 0:
video_file_name = f"{video}".split(", shape")[0].split("filename=")[-1]
response = QtWidgets.QMessageBox.critical(
context.app,
"Removing video with labels",
f"{n} labeled frames in {video_file_name} video will be deleted, "
"are you sure you want to remove this video?",
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No,
)
if response == QtWidgets.QMessageBox.No:
return False

return True
gitttt-1234 marked this conversation as resolved.
Show resolved Hide resolved


class RemoveVideo(EditCommand):
topics = [UpdateTopic.video, UpdateTopic.suggestions]

@staticmethod
def do_action(context: CommandContext, params: dict):
videos = context.labels.videos.copy()
row_idxs = context.state["selected_row_indices"]
# Remove selected videos in the project
for idx in row_idxs:
context.labels.remove_video(videos[idx])

if len(context.labels.videos):
context.state["video"] = context.labels.videos[-1]
else:
context.state["video"] = None
gitttt-1234 marked this conversation as resolved.
Show resolved Hide resolved

@staticmethod
def ask(context: CommandContext, params: dict) -> bool:
videos = context.labels.videos.copy()
row_idxs = context.state["selected_row_indices"]
for idx in row_idxs:

video = videos[idx]
if video is None:
return False

params["video"] = video
# Count labeled frames for this video
n = len(context.labels.find(video))

# Warn if there are labels that will be deleted
if n > 0:
video_file_name = f"{video}".split(", shape")[0].split("filename=")[-1]
response = QtWidgets.QMessageBox.critical(
context.app,
"Removing video with labels",
f"{n} labeled frames in {video_file_name} video will be deleted, "
"are you sure you want to remove this video?",
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No,
)
gitttt-1234 marked this conversation as resolved.
Show resolved Hide resolved
if response == QtWidgets.QMessageBox.No:
return False
return True


Expand Down
5 changes: 4 additions & 1 deletion sleap/gui/dataviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def __init__(
self.setWordWrap(False)
self.horizontalHeader().setStretchLastSection(True)
self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.setSortingEnabled(self.is_sortable)

self.doubleClicked.connect(self.activateSelected)
Expand Down Expand Up @@ -370,6 +370,9 @@ def getSelectedRowItem(self) -> Any:
not the converted dict.
"""
idx = self.currentIndex()
idx_temp = set([x.row() for x in self.selectedIndexes()])
self.state["selected_row_indices"] = idx_temp
gitttt-1234 marked this conversation as resolved.
Show resolved Hide resolved

if not idx.isValid():
return None
return self.model().original_items[idx.row()]
Expand Down
2 changes: 1 addition & 1 deletion sleap/gui/widgets/docks.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def create_video_edit_and_nav_buttons(self) -> QWidget:
self.add_button(hb, "Show Video", self.table.activateSelected)
self.add_button(hb, "Add Videos", main_window.commands.addVideo)
self.add_button(hb, "Remove Video", main_window.commands.removeVideo)

self.add_button(hb, "Remove All Videos", main_window.commands.removeAllVideos)
gitttt-1234 marked this conversation as resolved.
Show resolved Hide resolved
hbw = QWidget()
hbw.setLayout(hb)
return hbw
Expand Down
Loading