11from PyQt6 .QtCore import Qt , pyqtSignal , pyqtSlot
2- from PyQt6 .QtWidgets import QHBoxLayout , QLabel , QVBoxLayout , QWidget
3- from std_srvs .srv import Trigger
2+ from PyQt6 .QtWidgets import QGridLayout , QHBoxLayout , QLabel , QVBoxLayout , QWidget
43
54from gui .gui_node import GUINode
65from gui .styles .custom_styles import ButtonIndicator , WidgetState
76from gui .widgets .logger import Logger
87from gui .widgets .video_widget import CameraDescription , CameraType , VideoWidget
9- from rov_msgs .srv import GeneratePhotosphere
8+ from rov_msgs .srv import GeneratePhotosphere , TakePhotosphere
109
1110FISHEYE1_TOPIC = 'photosphere/image_1'
1211FISHEYE2_TOPIC = 'photosphere/image_2'
1312
1413
1514class PhotosphereTab (QWidget ):
16- take_photos_response_signal = pyqtSignal (Trigger .Response )
15+ take_photos_response_signal = pyqtSignal (TakePhotosphere .Response )
1716 generate_response_signal = pyqtSignal (GeneratePhotosphere .Response )
1817
1918 def __init__ (self ) -> None :
@@ -29,7 +28,7 @@ def __init__(self) -> None:
2928 )
3029
3130 self .take_photos_client = GUINode ().create_client_multithreaded (
32- Trigger , 'photosphere/take_photos'
31+ TakePhotosphere , 'photosphere/take_photos'
3332 )
3433 self .generate_photosphere_client = GUINode ().create_client_multithreaded (
3534 GeneratePhotosphere , 'photosphere/generate_photosphere'
@@ -47,22 +46,36 @@ def __init__(self) -> None:
4746 alignment = Qt .AlignmentFlag .AlignTop | Qt .AlignmentFlag .AlignLeft ,
4847 )
4948
50- button_pane = QHBoxLayout ()
49+ button_pane = QGridLayout ()
5150
5251 self .take_photos_button = ButtonIndicator ('Take Photos' )
53- self .take_photos_button .setMinimumHeight (60 )
54- self .take_photos_button .setMinimumWidth (150 )
55- self .take_photos_button .clicked .connect (self .take_photos_clicked )
52+ self .take_photos_button .clicked .connect (
53+ lambda : self .take_photo_clicked (TakePhotosphere .Request .BOTH )
54+ )
55+
56+ self .take_cam0_button = ButtonIndicator ('Take 0' )
57+ self .take_cam1_button = ButtonIndicator ('Take 1' )
58+ self .take_cam0_button .clicked .connect (
59+ lambda : self .take_photo_clicked (cam = TakePhotosphere .Request .CAM0 )
60+ )
61+ self .take_cam1_button .clicked .connect (
62+ lambda : self .take_photo_clicked (cam = TakePhotosphere .Request .CAM1 )
63+ )
64+
65+ self .photo_buttons : dict [int , tuple [ButtonIndicator , ...]] = {
66+ TakePhotosphere .Request .CAM0 : (self .take_cam0_button ,),
67+ TakePhotosphere .Request .CAM1 : (self .take_cam1_button ,),
68+ TakePhotosphere .Request .BOTH : (self .take_cam0_button , self .take_cam1_button ),
69+ }
5670
5771 self .generate_button = ButtonIndicator ('Generate Photosphere' )
58- self .generate_button .setMinimumHeight (60 )
59- self .generate_button .setMinimumWidth (150 )
6072 self .generate_button .set_state (WidgetState .INACTIVE )
6173 self .generate_button .clicked .connect (self .generate_clicked )
6274
63- button_pane .addWidget (self .take_photos_button )
64- button_pane .addWidget (self .generate_button )
65- button_pane .addStretch ()
75+ button_pane .addWidget (self .take_photos_button , 0 , 0 , 1 , 2 )
76+ button_pane .addWidget (self .take_cam0_button , 1 , 0 )
77+ button_pane .addWidget (self .take_cam1_button , 1 , 1 )
78+ button_pane .addWidget (self .generate_button , 2 , 0 , 1 , 2 )
6679
6780 root_layout = QVBoxLayout ()
6881 root_layout .addLayout (video_pane )
@@ -78,10 +91,13 @@ def __init__(self) -> None:
7891 root_layout .addWidget (Logger ())
7992 self .setLayout (root_layout )
8093
81- def take_photos_clicked (self ) -> None :
82- self .take_photos_button .set_state (WidgetState .INACTIVE )
94+ def take_photo_clicked (self , cam : int ) -> None :
95+ for button in self .photo_buttons [cam ]:
96+ button .set_state (WidgetState .INACTIVE )
8397 GUINode ().send_request_multithreaded (
84- self .take_photos_client , Trigger .Request (), self .take_photos_response_signal
98+ self .take_photos_client ,
99+ TakePhotosphere .Request (cam = cam ),
100+ self .take_photos_response_signal ,
85101 )
86102
87103 def generate_clicked (self ) -> None :
@@ -100,11 +116,19 @@ def generate_response_handler(self, res: GeneratePhotosphere.Response) -> None:
100116 self .photosphere_status_label .setText ('Photosphere generated' )
101117 self .generate_button .set_state (WidgetState .ON )
102118
103- @pyqtSlot (Trigger .Response )
104- def take_photos_response_handler (self , res : Trigger .Response ) -> None :
105- if res and res .success :
106- self .take_photos_button .set_state (WidgetState .ON )
107- if self .generate_button .current_state == WidgetState .INACTIVE :
119+ @pyqtSlot (TakePhotosphere .Response )
120+ def take_photos_response_handler (self , res : TakePhotosphere .Response ) -> None :
121+ if not res :
122+ for button in self .photo_buttons [TakePhotosphere .Request .BOTH ]:
123+ button .set_state (WidgetState .OFF )
124+ elif res .success :
125+ for button in self .photo_buttons [res .cam ]:
126+ button .set_state (WidgetState .ON )
127+ if self .generate_button .current_state == WidgetState .INACTIVE and all (
128+ button .current_state == WidgetState .ON
129+ for button in self .photo_buttons [TakePhotosphere .Request .BOTH ]
130+ ):
108131 self .generate_button .set_state (WidgetState .NONE )
109132 else :
110- self .take_photos_button .set_state (WidgetState .OFF )
133+ for button in self .photo_buttons [res .cam ]:
134+ button .set_state (WidgetState .OFF )
0 commit comments