15
15
from napari .layers .utils import color_manager
16
16
from napari .utils .events import Event
17
17
from napari .utils .history import get_save_history , update_save_history
18
- from qtpy .QtCore import Qt , QTimer , Signal
19
- from qtpy .QtGui import QPainter
18
+ from qtpy .QtCore import Qt , QTimer , Signal , QSize
19
+ from qtpy .QtGui import QPainter , QIcon
20
20
from qtpy .QtWidgets import (
21
21
QButtonGroup ,
22
22
QCheckBox ,
@@ -324,6 +324,11 @@ def _store_crop_coordinates(self, *args):
324
324
325
325
def _form_dropdown_menus (self , store ):
326
326
menu = KeypointsDropdownMenu (store )
327
+ self .viewer .dims .events .current_step .connect (
328
+ menu .smart_reset ,
329
+ position = "last" ,
330
+ )
331
+ menu .smart_reset (event = None )
327
332
self ._menus .append (menu )
328
333
layout = QVBoxLayout ()
329
334
layout .addWidget (menu )
@@ -447,11 +452,7 @@ def on_insert(self, event):
447
452
layer .events .query_next_frame .connect (store ._advance_step )
448
453
layer .bind_key ("Shift-Right" , store ._find_first_unlabeled_frame )
449
454
layer .bind_key ("Shift-Left" , store ._find_first_unlabeled_frame )
450
- self .viewer .dims .events .current_step .connect (
451
- store .smart_reset ,
452
- position = "last" ,
453
- )
454
- store .smart_reset (event = None )
455
+
455
456
layer .bind_key ("Down" , store .next_keypoint , overwrite = True )
456
457
layer .bind_key ("Up" , store .prev_keypoint , overwrite = True )
457
458
layer .face_color_mode = "cycle"
@@ -548,6 +549,7 @@ def __init__(
548
549
super ().__init__ (parent )
549
550
self .store = store
550
551
self .store .layer .events .current_properties .connect (self .update_menus )
552
+ self ._locked = False
551
553
552
554
# Map individuals to their respective bodyparts
553
555
self .id2label = defaultdict (list )
@@ -571,10 +573,24 @@ def __init__(
571
573
layout2 = QVBoxLayout ()
572
574
for menu in self .menus .values ():
573
575
layout2 .addWidget (menu )
576
+ self .lock_button = QPushButton ("Lock selection" )
577
+ self .lock_button .setIcon (QIcon ('src/napari_deeplabcut/assets/unlock.svg' ))
578
+ self .lock_button .setIconSize (QSize (24 , 24 ))
579
+ self .lock_button .clicked .connect (self ._lock_current_keypoint )
580
+ layout2 .addWidget (self .lock_button )
574
581
group_box .setLayout (layout2 )
575
582
layout1 .addWidget (group_box )
576
583
self .setLayout (layout1 )
577
584
585
+ def _lock_current_keypoint (self ):
586
+ self ._locked = not self ._locked
587
+ if self ._locked :
588
+ self .lock_button .setText ("Unlock selection" )
589
+ self .lock_button .setIcon (QIcon ('src/napari_deeplabcut/assets/lock.svg' ))
590
+ else :
591
+ self .lock_button .setText ("Lock selection" )
592
+ self .lock_button .setIcon (QIcon ('src/napari_deeplabcut/assets/unlock.svg' ))
593
+
578
594
def update_menus (self , event ):
579
595
keypoint = self .store .current_keypoint
580
596
for attr , menu in self .menus .items ():
@@ -589,6 +605,18 @@ def refresh_label_menu(self, text: str):
589
605
menu .blockSignals (False )
590
606
menu .addItems (self .id2label [text ])
591
607
608
+ def smart_reset (self , event ):
609
+ """Set current keypoint to the first unlabeled one."""
610
+ if self ._locked :
611
+ return
612
+ unannotated = ""
613
+ already_annotated = self .store .annotated_keypoints
614
+ for keypoint in self .store ._keypoints :
615
+ if keypoint not in already_annotated :
616
+ unannotated = keypoint
617
+ break
618
+ self .store .current_keypoint = unannotated if unannotated else self .store ._keypoints [0 ]
619
+
592
620
593
621
def create_dropdown_menu (store , items , attr ):
594
622
menu = DropdownMenu (items )
0 commit comments