2
2
3
3
from __future__ import annotations
4
4
5
- from PySide2 import QtCore
6
-
7
- from model import ProjectCreatorModel
5
+ from model import ProjectCreatorModel , ValidationError
6
+ from view import ProjectCreatorView
8
7
9
8
10
9
class ProjectCreatorController :
11
10
"""Controller for the ShotGrid Project Creator.
12
11
13
12
This controller handles all interactions between the view and the model.
14
- It also creates the model.
13
+ """
15
14
16
- Attributes:
17
- view: The ProjectCreatorView class."""
15
+ def __init__ (self ):
16
+ """Initializes the controller class and creates the view and model."""
17
+ self .view = ProjectCreatorView ()
18
+ self .view .show ()
19
+ self .view .start_button .clicked .connect (self .connect_to_shotgrid )
18
20
19
- def __init__ (self , view ):
20
- """Initializes the controller class and creates the model."""
21
- self .view = view
22
21
self .model = ProjectCreatorModel ()
23
22
24
23
def connect_to_shotgrid (self ) -> None :
25
- """Starts the ShotGrid model connection on a seperate thread ."""
24
+ """Starts the ShotGrid model connection."""
26
25
self .view .start_widget .hide ()
27
26
self .view .layout .addWidget (self .view .get_loading_widget ())
28
27
29
- self .shotgrid_connection_thread = ShotGridConnectionThread ( self . model )
30
- self .shotgrid_connection_thread . connection_response_received . connect (
31
- self .connection_response_received
28
+ self .model . connect_to_shotgrid (
29
+ self .shotgrid_connection_successful ,
30
+ self .shotgrid_connection_failed ,
32
31
)
33
- self .shotgrid_connection_thread .start ()
34
32
35
- def connection_response_received (
36
- self , connection_information : tuple (bool , str )
37
- ) -> None :
38
- """Runs when the ShotGrid connection thread is finished.
39
- Shows error if needed, else moves on to finding the username.
33
+ def shotgrid_connection_successful (self ) -> None :
34
+ """Runs when model is connected to ShotGrid. Triggers the username search."""
35
+ self .find_username ()
36
+
37
+ def shotgrid_connection_failed (self , error : str ) -> None :
38
+ """Show an error message when the ShotGrid connection failed.
40
39
41
40
Args:
42
- connection_information: ShotGrid connection information
41
+ error: Python error message in string format.
43
42
"""
44
- connected , error = connection_information
45
-
46
- if connected :
47
- self .find_username ()
48
- else :
49
- self .view .loading_widget .hide ()
50
- self .view .layout .addWidget (self .view .get_error_widget ())
51
- self .view .error_text .setText (
52
- f"Error: { error } . Please contact a pipeliner if problem persist."
53
- )
43
+ self .view .loading_widget .hide ()
44
+ self .view .layout .addWidget (self .view .get_error_widget ())
45
+ self .view .error_text .setText (
46
+ f"ShotGrid connection error: { error } . Please contact a pipeline TD if problem persist."
47
+ )
54
48
55
49
def find_username (self ) -> None :
56
50
"""Checks the username with the model. If we can't find a ShotGrid username,
57
- we show the username selection sceen to the user.
51
+ we show the username selection screen to the user.
58
52
"""
59
53
self .view .loading_widget .hide ()
60
54
@@ -67,14 +61,17 @@ def find_username(self) -> None:
67
61
shotgrid_user .get ("name" ), self .model .usernames
68
62
)
69
63
)
64
+ self .connect_view_functions ()
65
+
70
66
else :
71
67
self .view .layout .addWidget (
72
68
self .view .get_username_widget (self .model .usernames )
73
69
)
70
+ self .view .continue_button .clicked .connect (self .validate_username )
74
71
75
72
def validate_username (self ) -> None :
76
73
"""Checks if user submitted username is in ShotGrid. Moves on to next
77
- step if username is correct ."""
74
+ step if username exists ."""
78
75
shotgrid_user = self .model .get_shotgrid_user (
79
76
self .view .username_lineedit .text ()
80
77
)
@@ -95,17 +92,61 @@ def validate_username(self) -> None:
95
92
shotgrid_user .get ("name" ), self .model .usernames
96
93
)
97
94
)
95
+ self .connect_view_functions ()
98
96
self .model .set_user_information (shotgrid_user )
99
97
98
+ def connect_view_functions (self ) -> None :
99
+ """Connects all our view buttons and text changes to corresponding
100
+ functions in this controller."""
101
+ self .view .project_name_lineedit .textChanged .connect (
102
+ self .validate_project_name
103
+ )
104
+ self .view .production_code_yes_button .clicked .connect (
105
+ self .set_production_code_yes
106
+ )
107
+ self .view .production_code_no_button .clicked .connect (
108
+ self .set_production_code_no
109
+ )
110
+ self .view .project_code_lineedit .textChanged .connect (
111
+ self .validate_project_code
112
+ )
113
+ self .view .supervisor_add_button .clicked .connect (self .add_supervisor )
114
+ self .view .supervisor_remove_button .clicked .connect (
115
+ self .remove_supervisor
116
+ )
117
+ self .view .render_engine_list .currentTextChanged .connect (
118
+ self .set_render_engine
119
+ )
120
+ self .view .project_type_fiction_button .clicked .connect (
121
+ self .set_project_type_fiction
122
+ )
123
+ self .view .project_type_documentary_button .clicked .connect (
124
+ self .set_project_type_documentary
125
+ )
126
+ self .view .fps_spinbox .valueChanged .connect (self .set_fps )
127
+ self .view .create_project_button .clicked .connect (self .create_project )
128
+
100
129
def validate_project_name (self , project_name : str ) -> None :
101
- """Validates project name and updates view."""
102
- validated , message = self .model .validate_project_name (project_name )
130
+ """Validates project name and updates view.
131
+
132
+ Args:
133
+ project_name: Name of project
134
+ """
103
135
project_name_validation_text = self .view .project_name_validation_text
104
136
105
- project_name_validation_text .setText (message )
106
- project_name_validation_text .setStyleSheet (
107
- f"color: { '#8BFF3E' if validated else '#FF3E3E' } ; font-size: 12px;"
108
- )
137
+ try :
138
+ self .model .validate_project_name (project_name )
139
+ project_name_validation_text .setText ("Project name available!" )
140
+ project_name_validation_text .setStyleSheet (
141
+ "color: '#8BFF3E'; font-size: 12px;"
142
+ )
143
+
144
+ except ValidationError as validation_message :
145
+ project_name_validation_text .setText (str (validation_message ))
146
+ project_name_validation_text .setStyleSheet (
147
+ "color: '#FF3E3E'; font-size: 12px;"
148
+ )
149
+
109
150
project_name_validation_text .show ()
110
151
111
152
def set_production_code_yes (self ) -> None :
@@ -136,53 +177,79 @@ def validate_project_code(self, project_code: str) -> None:
136
177
Args:
137
178
project_code: String project code, either P#### or ABC.
138
179
"""
139
- validated , message = self .model .validate_project_code (project_code )
140
180
production_code_validation_text = (
141
181
self .view .production_code_validation_text
142
182
)
143
183
144
- production_code_validation_text .setText (message )
145
- production_code_validation_text .setStyleSheet (
146
- f"color: { '#8BFF3E' if validated else '#FF3E3E' } ; font-size: 12px;"
147
- )
184
+ try :
185
+ self .model .validate_project_code (project_code )
186
+ production_code_validation_text .setText ("Project code available!" )
187
+ production_code_validation_text .setStyleSheet (
188
+ "color: '#8BFF3E'; font-size: 12px;"
189
+ )
190
+
191
+ except ValidationError as validation_message :
192
+ production_code_validation_text .setText (str (validation_message ))
193
+ production_code_validation_text .setStyleSheet (
194
+ "color: '#FF3E3E'; font-size: 12px;"
195
+ )
196
+
148
197
production_code_validation_text .show ()
149
198
150
199
def add_supervisor (self ) -> None :
151
200
"""Tries to add the supervisor from the LineEdit to the list of supervisors."""
152
- validated , username , message = self .model .add_supervisor (
153
- self .view .supervisors_lineedit .text ()
154
- )
155
201
supervisors_validation_text = self .view .supervisors_validation_text
156
202
157
- if validated :
203
+ try :
204
+ username = self .model .add_supervisor (
205
+ self .view .supervisors_lineedit .text ()
206
+ )
207
+
208
+ supervisors_validation_text .setText ("Added supervisor to list!" )
209
+ supervisors_validation_text .setStyleSheet (
210
+ "color: '#8BFF3E'; font-size: 12px;"
211
+ )
212
+
158
213
self .view .supervisors_list .insertItem (0 , username )
159
214
self .view .supervisors_list .setCurrentIndex (0 )
160
215
self .view .supervisors_lineedit .setText ("" )
161
216
162
- supervisors_validation_text .setText (message )
163
- supervisors_validation_text .setStyleSheet (
164
- f"color: { '#8BFF3E' if validated else '#FF3E3E' } ; font-size: 12px;"
165
- )
217
+ except ValidationError as validation_message :
218
+ supervisors_validation_text .setText (str (validation_message ))
219
+ supervisors_validation_text .setStyleSheet (
220
+ "color: '#FF3E3E'; font-size: 12px;"
221
+ )
222
+
166
223
supervisors_validation_text .show ()
167
224
168
225
def remove_supervisor (self ) -> None :
169
226
"""Tries to remove a supervisor from the list."""
170
- removed , message = self .model .remove_supervisor (
171
- self .view .supervisors_list .currentText ()
172
- )
173
227
supervisors_validation_text = self .view .supervisors_validation_text
174
228
175
- if removed :
229
+ try :
230
+ self .model .remove_supervisor (
231
+ self .view .supervisors_list .currentText ()
232
+ )
233
+
176
234
self .view .supervisors_list .removeItem (
177
235
self .view .supervisors_list .findText (
178
236
self .view .supervisors_list .currentText ()
179
237
)
180
238
)
181
239
182
- supervisors_validation_text .setText (message )
183
- supervisors_validation_text .setStyleSheet (
184
- f"color: { '#8BFF3E' if removed else '#FF3E3E' } ; font-size: 12px;"
185
- )
240
+ supervisors_validation_text .setText (
241
+ "Removed supervisor from list!"
242
+ )
243
+ supervisors_validation_text .setStyleSheet (
244
+ "color: '#8BFF3E'; font-size: 12px;"
245
+ )
246
+
247
+ except ValidationError as validation_message :
248
+ supervisors_validation_text .setText (str (validation_message ))
249
+ supervisors_validation_text .setStyleSheet (
250
+ "color: '#FF3E3E'; font-size: 12px;"
251
+ )
252
+
186
253
supervisors_validation_text .show ()
187
254
188
255
def set_render_engine (self , render_engine : str ) -> None :
@@ -202,15 +269,19 @@ def set_project_type_documentary(self) -> None:
202
269
self .model .set_project_type ("Documentary" )
203
270
204
271
def set_fps (self , fps : int ) -> None :
205
- """Informs the model of the new FPS."""
272
+ """Informs the model of the new FPS.
273
+
274
+ Args:
275
+ fps: New project FPS"""
206
276
self .model .set_fps (fps )
207
277
208
278
def create_project (self ) -> None :
209
- """Validates, then creates the project."""
210
- validated , message = self .model .validate_project ()
279
+ """Validates the project, then starts project creation on a separate thread."""
280
+ try :
281
+ self .model .validate_project ()
211
282
212
- if not validated :
213
- self .view .project_validation_text .setText (message )
283
+ except ValidationError as validation_message :
284
+ self .view .project_validation_text .setText (str ( validation_message ) )
214
285
self .view .project_validation_text .setStyleSheet (
215
286
"color: '#FF3E3E'; font-size: 12px;"
216
287
)
@@ -221,59 +292,30 @@ def create_project(self) -> None:
221
292
self .view .loading_text .setText ("Creating project..." )
222
293
self .view .loading_widget .show ()
223
294
224
- self .project_creation_thread = ProjectCreationThread (self .model )
225
- self .project_creation_thread .project_creation_finished .connect (
226
- self .project_creation_finished
295
+ self .model .start_project_creation (
296
+ self .project_creation_successful , self .project_creation_failed
227
297
)
228
- self .project_creation_thread .start ()
229
298
230
- def project_creation_finished (self , project_information : tuple ) -> None :
231
- """Runs when project creation is finished on the seperate thread .
299
+ def project_creation_successful (self , project_url : str ) -> None :
300
+ """Runs when project creation has successfully finished .
232
301
233
302
Args:
234
- project_information: Whether or not creation was successful and error/link
303
+ project_url: Link to ShotGrid site for project.
235
304
"""
236
- created , message = project_information
237
305
self .view .loading_widget .hide ()
238
306
239
- if not created :
240
- self .view .main_widget .hide ()
241
- self .view .layout .addWidget (self .view .get_error_widget ())
242
- self .view .error_text .setText (
243
- f"Error: { message } . Please contact a pipeliner if problem persist."
244
- )
245
- return
246
-
247
307
self .view .layout .addWidget (
248
- self .view .get_project_creation_successful_widget (message )
308
+ self .view .get_project_creation_successful_widget (project_url )
249
309
)
250
310
311
+ def project_creation_failed (self , error : str ) -> None :
312
+ """Runs when project creation has failed.
251
313
252
- class ShotGridConnectionThread (QtCore .QThread ):
253
- """Class for connecting to ShotGrid on a seperate thread
254
- so the UI doesn't freeze."""
255
-
256
- connection_response_received = QtCore .Signal (object )
257
-
258
- def __init__ (self , model ):
259
- super ().__init__ ()
260
- self .model = model
261
-
262
- def run (self ):
263
- connection_information = self .model .connect_to_shotgrid ()
264
- self .connection_response_received .emit (connection_information )
265
-
266
-
267
- class ProjectCreationThread (QtCore .QThread ):
268
- """Class for creating the ShotGrid project on a seperate thread
269
- so the UI doesn't freeze."""
270
-
271
- project_creation_finished = QtCore .Signal (object )
272
-
273
- def __init__ (self , model ):
274
- super ().__init__ ()
275
- self .model = model
276
-
277
- def run (self ):
278
- created_project_information = self .model .create_project ()
279
- self .project_creation_finished .emit (created_project_information )
314
+ Args:
315
+ error: Python error message in string format.
316
+ """
317
+ self .view .loading_widget .hide ()
318
+ self .view .layout .addWidget (self .view .get_error_widget ())
319
+ self .view .error_text .setText (
320
+ f"Project creation error: { error } . Please contact a pipeline TD if problem persist."
321
+ )
0 commit comments