Skip to content

Commit de61fc3

Browse files
committed
Changes after code review
1 parent c59c8aa commit de61fc3

File tree

4 files changed

+403
-351
lines changed

4 files changed

+403
-351
lines changed

controller.py

Lines changed: 151 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,53 @@
22

33
from __future__ import annotations
44

5-
from PySide2 import QtCore
6-
7-
from model import ProjectCreatorModel
5+
from model import ProjectCreatorModel, ValidationError
6+
from view import ProjectCreatorView
87

98

109
class ProjectCreatorController:
1110
"""Controller for the ShotGrid Project Creator.
1211
1312
This controller handles all interactions between the view and the model.
14-
It also creates the model.
13+
"""
1514

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)
1820

19-
def __init__(self, view):
20-
"""Initializes the controller class and creates the model."""
21-
self.view = view
2221
self.model = ProjectCreatorModel()
2322

2423
def connect_to_shotgrid(self) -> None:
25-
"""Starts the ShotGrid model connection on a seperate thread."""
24+
"""Starts the ShotGrid model connection."""
2625
self.view.start_widget.hide()
2726
self.view.layout.addWidget(self.view.get_loading_widget())
2827

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,
3231
)
33-
self.shotgrid_connection_thread.start()
3432

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.
4039
4140
Args:
42-
connection_information: ShotGrid connection information
41+
error: Python error message in string format.
4342
"""
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+
)
5448

5549
def find_username(self) -> None:
5650
"""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.
5852
"""
5953
self.view.loading_widget.hide()
6054

@@ -67,14 +61,17 @@ def find_username(self) -> None:
6761
shotgrid_user.get("name"), self.model.usernames
6862
)
6963
)
64+
self.connect_view_functions()
65+
7066
else:
7167
self.view.layout.addWidget(
7268
self.view.get_username_widget(self.model.usernames)
7369
)
70+
self.view.continue_button.clicked.connect(self.validate_username)
7471

7572
def validate_username(self) -> None:
7673
"""Checks if user submitted username is in ShotGrid. Moves on to next
77-
step if username is correct."""
74+
step if username exists."""
7875
shotgrid_user = self.model.get_shotgrid_user(
7976
self.view.username_lineedit.text()
8077
)
@@ -95,17 +92,61 @@ def validate_username(self) -> None:
9592
shotgrid_user.get("name"), self.model.usernames
9693
)
9794
)
95+
self.connect_view_functions()
9896
self.model.set_user_information(shotgrid_user)
9997

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+
100129
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+
"""
103135
project_name_validation_text = self.view.project_name_validation_text
104136

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+
109150
project_name_validation_text.show()
110151

111152
def set_production_code_yes(self) -> None:
@@ -136,53 +177,79 @@ def validate_project_code(self, project_code: str) -> None:
136177
Args:
137178
project_code: String project code, either P#### or ABC.
138179
"""
139-
validated, message = self.model.validate_project_code(project_code)
140180
production_code_validation_text = (
141181
self.view.production_code_validation_text
142182
)
143183

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+
148197
production_code_validation_text.show()
149198

150199
def add_supervisor(self) -> None:
151200
"""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-
)
155201
supervisors_validation_text = self.view.supervisors_validation_text
156202

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+
158213
self.view.supervisors_list.insertItem(0, username)
159214
self.view.supervisors_list.setCurrentIndex(0)
160215
self.view.supervisors_lineedit.setText("")
161216

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+
166223
supervisors_validation_text.show()
167224

168225
def remove_supervisor(self) -> None:
169226
"""Tries to remove a supervisor from the list."""
170-
removed, message = self.model.remove_supervisor(
171-
self.view.supervisors_list.currentText()
172-
)
173227
supervisors_validation_text = self.view.supervisors_validation_text
174228

175-
if removed:
229+
try:
230+
self.model.remove_supervisor(
231+
self.view.supervisors_list.currentText()
232+
)
233+
176234
self.view.supervisors_list.removeItem(
177235
self.view.supervisors_list.findText(
178236
self.view.supervisors_list.currentText()
179237
)
180238
)
181239

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+
186253
supervisors_validation_text.show()
187254

188255
def set_render_engine(self, render_engine: str) -> None:
@@ -202,15 +269,19 @@ def set_project_type_documentary(self) -> None:
202269
self.model.set_project_type("Documentary")
203270

204271
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"""
206276
self.model.set_fps(fps)
207277

208278
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()
211282

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))
214285
self.view.project_validation_text.setStyleSheet(
215286
"color: '#FF3E3E'; font-size: 12px;"
216287
)
@@ -221,59 +292,30 @@ def create_project(self) -> None:
221292
self.view.loading_text.setText("Creating project...")
222293
self.view.loading_widget.show()
223294

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
227297
)
228-
self.project_creation_thread.start()
229298

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.
232301
233302
Args:
234-
project_information: Whether or not creation was successful and error/link
303+
project_url: Link to ShotGrid site for project.
235304
"""
236-
created, message = project_information
237305
self.view.loading_widget.hide()
238306

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-
247307
self.view.layout.addWidget(
248-
self.view.get_project_creation_successful_widget(message)
308+
self.view.get_project_creation_successful_widget(project_url)
249309
)
250310

311+
def project_creation_failed(self, error: str) -> None:
312+
"""Runs when project creation has failed.
251313
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+
)

main.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44

55
from PySide2 import QtWidgets
66

7-
from view import ProjectCreatorView
7+
from controller import ProjectCreatorController
88

99
if __name__ == "__main__":
1010
app = QtWidgets.QApplication(sys.argv)
1111

12-
widget = ProjectCreatorView()
13-
widget.show()
12+
controller = ProjectCreatorController()
1413

1514
sys.exit(app.exec_())

0 commit comments

Comments
 (0)