-
Notifications
You must be signed in to change notification settings - Fork 121
Add option to group cameras from sessions #2125
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
base: liezl/add-gui-elements-for-sessions
Are you sure you want to change the base?
Changes from 9 commits
ffe5582
3023b10
23c9dd6
16c7d88
0b963be
7182b07
e646a92
fca9e8f
baa283b
5ce4bc4
3844141
d61ea3c
4233131
8bb6b99
b508503
1292cdc
c0c28a4
ca06614
d6bf553
695500d
0cc94e6
83e2dff
b16c1af
1032c83
6836608
07de332
271ddf1
74c7160
b9ce559
8de15b0
9e6a698
fd1a93f
6cf5f0e
63aae15
8c1839b
f980680
918bc9d
4bdec1b
4a8afa3
64c0ec1
54b943b
8caa652
0544830
956d3c3
c67e634
240da9b
986d6a4
a2f83f8
8f550f7
5be482b
e634f51
957cbdf
e7e8936
6fd57c8
6bb48f9
48fcf7f
5ed8c4e
64805b1
34eec48
2939eb0
1eda317
acdf642
e947165
3b42451
637ca42
721eb32
9ccf2e0
f4a9045
47e0168
3d56c4b
7ae86ea
f98714e
115dadf
dc90117
fad7446
c208d50
5a04419
c8e6daa
612ae83
2fa7ebe
f795e62
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -683,6 +683,40 @@ def item_to_data(self, obj: RecordingSession, item: Camcorder): | |||||||||||
| video = obj.get_video(item) | ||||||||||||
| return {"camera": item.name, "video": video.filename if video else ""} | ||||||||||||
|
|
||||||||||||
| class CameraGroupsTableModel(GenericTableModel): | ||||||||||||
| """Table model for camera groups.""" | ||||||||||||
|
|
||||||||||||
| properties = ("name", "cameras") | ||||||||||||
|
|
||||||||||||
| def __init__(self, items=None, context=None): | ||||||||||||
| super().__init__(items=items, context=context) | ||||||||||||
| # Register for updates | ||||||||||||
| if context and hasattr(context, 'state'): | ||||||||||||
| context.state.connect("camera_groups", self.update_items) | ||||||||||||
|
|
||||||||||||
| def update_items(self, camera_groups): | ||||||||||||
| """Update the model when camera groups change.""" | ||||||||||||
| self.items = camera_groups | ||||||||||||
| self.beginResetModel() | ||||||||||||
| self.endResetModel() | ||||||||||||
|
||||||||||||
| if _has_topic([UpdateTopic.project, UpdateTopic.on_frame]): | |
| self.instances_dock.table.model().items = self.state["labeled_frame"] | |
| if _has_topic([UpdateTopic.suggestions]): | |
| self.suggestions_dock.table.model().items = self.labels.suggestions |
. Let's leave it for now (and possibly open a new PR to refactor all the other table updates).
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we want to call a self.context method here, this is not the one (we haven't created the method we want to call yet).
| # Mark project as changed | |
| self.context.changestack_push("rename camera group") | |
| # TODO(JS): Add `CommandContext` method that updates the camera group name | |
| raise NotImplementedError |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -20,6 +20,8 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| QTabWidget, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| QVBoxLayout, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| QWidget, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| QInputDialog, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| QMessageBox, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from sleap.gui.dataviews import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -34,6 +36,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CamerasTableModel, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SessionsTableModel, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| InstanceGroupTableModel, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CameraGroupsTableModel, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from sleap.io.cameras import RecordingSession, FrameGroup, InstanceGroup | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from sleap.gui.dialogs.formbuilder import YamlFormWidget | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -584,13 +587,15 @@ def __init__( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.sessions_model_type = SessionsTableModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.camera_model_type = CamerasTableModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.unlinked_videos_model_type = VideosTableModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.camera_groups_model_type = CameraGroupsTableModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| super().__init__( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name="Sessions", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| main_window=main_window, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model_type=[ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.sessions_model_type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.camera_model_type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.unlinked_videos_model_type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.camera_groups_model_type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tab_with=tab_with, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -625,10 +630,52 @@ def create_video_unlink_button(self) -> QWidget: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hb, "Unlink Video", main_window.commands.unlink_video_from_camera | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.add_button(hb, "Add to Group", self._add_camera_to_group) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hbw = QWidget() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hbw.setLayout(hb) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return hbw | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _add_camera_to_group(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Add the selected camera to a group.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| camera = self.main_window.state.get("camera") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not camera: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| QMessageBox.information( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.main_window, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "No Camera Selected", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Please select a camera to add to a group." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._buttons["link video"].setEnabled( | |
| has_selected_unlinked_video | |
| and has_selected_camcorder | |
| and has_selected_session | |
| ) |
.
| if not camera: | |
| QMessageBox.information( | |
| self.main_window, | |
| "No Camera Selected", | |
| "Please select a camera to add to a group." | |
| ) | |
| return |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GuiState has a __getitem__ method, so we at least won't run into an error if the key doesn't exist.
Lines 52 to 54 in 6531447
| def __getitem__(self, key: GSVarType) -> Any: | |
| """Gets value for key, or None if no value.""" | |
| return self.get(key, default=None) |
How about we use get, but with a default of an empty list:
| if not self.main_window.state.get("camera_groups") or len(self.main_window.state["camera_groups"]) == 0: | |
| if len(self.main_window.state.get("camera_groups", []) == 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ex:
In [20]: from sleap.gui.state import GuiState
In [21]: state = GuiState()
In [22]: state[3]
In [23]: state.get(3, [])
Out[23]: []
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| self.main_window.commands.addCameraGroup(name) | |
| # TODO(JS): self.main_window.commands.addCameraGroup(name) | |
| raise NotImplementedError |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entire method is a duplicate
| def _add_camera_to_group(self): | |
| """Add the selected camera to a group.""" | |
| camera = self.main_window.state.get("camera") | |
| if not camera: | |
| QMessageBox.information( | |
| self.main_window, | |
| "No Camera Selected", | |
| "Please select a camera to add to a group." | |
| ) | |
| return | |
| # Get available groups | |
| if not self.main_window.state.get("camera_groups") or len(self.main_window.state["camera_groups"]) == 0: | |
| reply = QMessageBox.question( | |
| self.main_window, | |
| "No Groups", | |
| "No camera groups exist. Would you like to create one?", | |
| QMessageBox.Yes | QMessageBox.No, | |
| QMessageBox.Yes | |
| ) | |
| if reply == QMessageBox.Yes: | |
| self._create_camera_group() | |
| return | |
| # Show group selection dialog | |
| group_names = [group.name for group in self.main_window.state["camera_groups"]] | |
| selected_name, ok = QInputDialog.getItem( | |
| self.main_window, | |
| "Select Group", | |
| "Choose a group to add the camera to:", | |
| group_names, | |
| 0, | |
| False | |
| ) | |
| if ok and selected_name: | |
| selected_idx = group_names.index(selected_name) | |
| selected_group = self.main_window.state["camera_groups"][selected_idx] | |
| self.main_window.commands.addCameraToGroup(camera, selected_group) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expose the property kwarg: