Semapp 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of Semapp might be problematic. Click here for more details.

@@ -0,0 +1,26 @@
1
+ """
2
+ Layout package initialization.
3
+ Contains GUI components and style definitions.
4
+ """
5
+
6
+ from .create_button import ButtonFrame
7
+ from .styles import (
8
+ RADIO_BUTTON_STYLE,
9
+ SETTINGS_BUTTON_STYLE,
10
+ RUN_BUTTON_STYLE,
11
+ GROUP_BOX_STYLE,
12
+ WAFER_BUTTON_DEFAULT_STYLE,
13
+ WAFER_BUTTON_EXISTING_STYLE,
14
+ WAFER_BUTTON_MISSING_STYLE
15
+ )
16
+
17
+ __all__ = [
18
+ 'ButtonFrame',
19
+ 'RADIO_BUTTON_STYLE',
20
+ 'SETTINGS_BUTTON_STYLE',
21
+ 'RUN_BUTTON_STYLE',
22
+ 'GROUP_BOX_STYLE',
23
+ 'WAFER_BUTTON_DEFAULT_STYLE',
24
+ 'WAFER_BUTTON_EXISTING_STYLE',
25
+ 'WAFER_BUTTON_MISSING_STYLE'
26
+ ]
@@ -0,0 +1,496 @@
1
+ """Module for buttons"""
2
+ # pylint: disable=no-name-in-module, trailing-whitespace, too-many-branches, too-many-statements
3
+
4
+
5
+ import sys
6
+ import os
7
+ import time
8
+ from PyQt5.QtWidgets import QApplication
9
+ from PyQt5.QtWidgets import (
10
+ QWidget, QButtonGroup, QPushButton, QLabel, QGroupBox, QGridLayout,
11
+ QFileDialog, QProgressDialog, QRadioButton, QSizePolicy)
12
+ from PyQt5.QtGui import QFont
13
+ from PyQt5.QtCore import Qt
14
+ from semapp.Processing.processing import Process
15
+ from semapp.Layout.styles import (
16
+ RADIO_BUTTON_STYLE,
17
+ SETTINGS_BUTTON_STYLE,
18
+ RUN_BUTTON_STYLE,
19
+ GROUP_BOX_STYLE,
20
+ WAFER_BUTTON_DEFAULT_STYLE,
21
+ WAFER_BUTTON_EXISTING_STYLE,
22
+ WAFER_BUTTON_MISSING_STYLE,
23
+ SELECT_BUTTON_STYLE,
24
+ PATH_LABEL_STYLE,
25
+ )
26
+ from semapp.Layout.settings import SettingsWindow
27
+
28
+ class ButtonFrame(QWidget):
29
+ """Class to create the various buttons of the interface"""
30
+
31
+ def __init__(self, layout):
32
+ super().__init__()
33
+ self.layout = layout
34
+ self.folder_path = None
35
+ self.check_vars = {}
36
+ self.common_class = None
37
+ self.folder_path_label = None
38
+ self.radio_vars = {}
39
+ self.selected_option = None
40
+ self.selected_image = None
41
+ self.table_data = None
42
+ self.table_vars = None
43
+
44
+ self.rename = QRadioButton("Rename")
45
+ self.split_rename = QRadioButton("Split .tif and rename (w/ tag)")
46
+ self.split_rename_all = QRadioButton("Split .tif and rename (w/ tag)")
47
+ self.clean = QRadioButton("Clean")
48
+ self.rename = QRadioButton("Rename (w/o tag)")
49
+ self.rename_all = QRadioButton("Rename (w/o tag)")
50
+ self.clean_all = QRadioButton("Clean")
51
+ self.create_folder = QRadioButton("Create folders")
52
+
53
+ self.line_edits = {}
54
+
55
+ tool_radiobuttons = [self.rename, self.split_rename,
56
+ self.clean, self.rename_all,
57
+ self.split_rename_all, self.clean_all,
58
+ self.create_folder]
59
+
60
+ for radiobutton in tool_radiobuttons:
61
+ radiobutton.setStyleSheet(RADIO_BUTTON_STYLE)
62
+
63
+ # Example of adding them to a layout
64
+ self.entries = {}
65
+ self.dirname = None
66
+ # self.dirname = r"C:\Users\TM273821\Desktop\SEM\Amel"
67
+
68
+
69
+ max_characters = 30 # Set character limit
70
+ if self.dirname:
71
+ self.display_text = self.dirname if len(
72
+ self.dirname) <= max_characters else self.dirname[
73
+ :max_characters] + '...'
74
+
75
+ # Get the user's folder path (C:\Users\XXXXX)
76
+ self.user_folder = os.path.expanduser(
77
+ "~") # This gets C:\Users\XXXXX
78
+
79
+ # Define the new folder you want to create
80
+ self.new_folder = os.path.join(self.user_folder, "SEM")
81
+
82
+
83
+ # Create the folder if it doesn't exist
84
+ self.create_directory(self.new_folder)
85
+
86
+ self.button_group = QButtonGroup(self)
87
+
88
+ self.init_ui()
89
+
90
+ def create_directory(self, path):
91
+ """Create the directory if it does not exist."""
92
+ if not os.path.exists(path):
93
+ os.makedirs(path)
94
+ print(f"Directory created: {path}")
95
+ else:
96
+ print(f"Directory already exists: {path}")
97
+
98
+ def init_ui(self):
99
+ """Initialize the user interface"""
100
+ # Add widgets to the grid layout provided by the main window
101
+
102
+ self.settings_window = SettingsWindow()
103
+ self.dir_box()
104
+ self.create_wafer()
105
+ self.create_radiobuttons_other()
106
+ self.create_radiobuttons()
107
+ self.create_radiobuttons_all()
108
+ self.image_radiobuttons()
109
+ self.add_settings_button()
110
+ self.create_run_button()
111
+ self.update_wafer()
112
+ self.settings_window.data_updated.connect(self.refresh_radiobuttons)
113
+
114
+
115
+ def add_settings_button(self):
116
+ """Add a Settings button that opens a new dialog"""
117
+ settings_button = QPushButton("Settings")
118
+ settings_button.setStyleSheet(SETTINGS_BUTTON_STYLE)
119
+ settings_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
120
+ settings_button.clicked.connect(self.open_settings_window)
121
+
122
+ self.layout.addWidget(settings_button, 0, 4, 1, 1)
123
+
124
+ def open_settings_window(self):
125
+ """Open the settings window"""
126
+
127
+ self.settings_window.exec_()
128
+
129
+ def dir_box(self):
130
+ """Create a smaller directory selection box"""
131
+
132
+ # Create layout for this frame
133
+ frame_dir = QGroupBox("Directory")
134
+
135
+ frame_dir.setStyleSheet(GROUP_BOX_STYLE)
136
+
137
+ # Button for selecting folder
138
+ select_folder_button = QPushButton("Select Parent Folder...")
139
+ select_folder_button.setStyleSheet(SELECT_BUTTON_STYLE)
140
+
141
+ # Create layout for the frame and reduce its margins
142
+ frame_dir_layout = QGridLayout()
143
+ frame_dir_layout.setContentsMargins(5, 20, 5, 5) # Reduced margins
144
+ frame_dir.setLayout(frame_dir_layout)
145
+
146
+ # label for folder path
147
+ if self.dirname:
148
+ self.folder_path_label = QLabel(self.display_text)
149
+ else:
150
+ self.folder_path_label = QLabel()
151
+
152
+ self.folder_path_label.setStyleSheet(PATH_LABEL_STYLE)
153
+
154
+ # Connect the button to folder selection method
155
+ select_folder_button.clicked.connect(self.on_select_folder_and_update)
156
+
157
+ # Add widgets to layout
158
+ frame_dir_layout.addWidget(select_folder_button, 0, 0, 1, 1)
159
+ frame_dir_layout.addWidget(self.folder_path_label, 1, 0, 1, 1)
160
+
161
+ # Add frame to the main layout with a smaller footprint
162
+ self.layout.addWidget(frame_dir, 0, 0)
163
+
164
+ def folder_var_changed(self):
165
+ """Update parent folder"""
166
+ return self.dirname
167
+
168
+ def on_select_folder_and_update(self):
169
+ """Method to select folder and update checkbuttons"""
170
+ self.select_folder()
171
+ self.update_wafer()
172
+
173
+ def update_wafer(self):
174
+ """Update the appearance of radio buttons based on the existing
175
+ subdirectories in the specified directory."""
176
+ if self.dirname:
177
+ # List the subdirectories in the specified directory
178
+ subdirs = [d for d in os.listdir(self.dirname) if
179
+ os.path.isdir(os.path.join(self.dirname, d))]
180
+
181
+ # Update the style of radio buttons based on the subdirectory presence
182
+ for number in range(1, 27):
183
+ radio_button = self.radio_vars.get(number)
184
+ if radio_button:
185
+ if str(number) in subdirs:
186
+ radio_button.setStyleSheet(WAFER_BUTTON_EXISTING_STYLE)
187
+ else:
188
+ radio_button.setStyleSheet(WAFER_BUTTON_MISSING_STYLE)
189
+ else:
190
+ # Default style for all radio buttons if no directory is specified
191
+ for number in range(1, 27):
192
+ radio_button = self.radio_vars.get(number)
193
+ radio_button.setStyleSheet(WAFER_BUTTON_MISSING_STYLE)
194
+
195
+ def create_wafer(self):
196
+ """Create a grid of radio buttons for wafer slots with exclusive selection."""
197
+ group_box = QGroupBox("Wafer Slots") # Add a title to the group
198
+ group_box.setStyleSheet(GROUP_BOX_STYLE)
199
+
200
+ wafer_layout = QGridLayout()
201
+ wafer_layout.setContentsMargins(2, 20, 2, 2) # Reduce internal margins
202
+ wafer_layout.setSpacing(5) # Reduce spacing between widgets
203
+
204
+
205
+
206
+ # Add radio buttons from 1 to 24, with 12 buttons per row
207
+ for number in range(1, 27):
208
+ radio_button = QRadioButton(str(number))
209
+ radio_button.setStyleSheet(WAFER_BUTTON_DEFAULT_STYLE)
210
+
211
+ # Connect the radio button to a handler for exclusive selection
212
+ radio_button.toggled.connect(self.get_selected_option)
213
+ self.radio_vars[number] = radio_button
214
+
215
+ # Calculate the row and column for each radio button in the layout
216
+ row = (number - 1) // 13 # Row starts at 0
217
+ col = (number - 1) % 13 # Column ranges from 0 to 12
218
+
219
+ wafer_layout.addWidget(radio_button, row, col)
220
+
221
+ group_box.setLayout(wafer_layout)
222
+
223
+ # Add the QGroupBox to the main layout
224
+ self.layout.addWidget(group_box, 1, 0, 1, 4)
225
+
226
+ def get_selected_option(self):
227
+ """Ensure only one radio button is selected at a time and track the selected button."""
228
+ selected_number = None # Variable to store the selected radio button number
229
+
230
+ # Iterate over all radio buttons
231
+ for number, radio_button in self.radio_vars.items():
232
+ if radio_button.isChecked():
233
+ selected_number = number # Track the currently selected radio button
234
+
235
+ if selected_number is not None:
236
+ self.selected_option = selected_number # Store the selected option for further use
237
+ return self.selected_option
238
+
239
+ def image_radiobuttons(self):
240
+ """Create a grid of radio buttons for wafer slots with exclusive selection."""
241
+ self.table_data = self.settings_window.get_table_data()
242
+ print(self.table_data)
243
+ number = len(self.table_data)
244
+
245
+ group_box = QGroupBox("Image type") # Add a title to the group
246
+ group_box.setStyleSheet(GROUP_BOX_STYLE) # Style the title
247
+
248
+ wafer_layout = QGridLayout()
249
+ wafer_layout.setContentsMargins(2, 20, 2, 2) # Reduce internal margins
250
+ wafer_layout.setSpacing(5) # Reduce spacing between widgets
251
+
252
+ self.table_vars = {} # Store references to radio buttons
253
+
254
+ # Add radio buttons from 1 to 24, with 12 radio buttons per row
255
+ for i in range(number):
256
+ label = str(self.table_data[i]["Scale"]) + " - " + str(
257
+ self.table_data[i]["Image Type"])
258
+ radio_button = QRadioButton(label)
259
+ radio_button.setStyleSheet(WAFER_BUTTON_DEFAULT_STYLE)
260
+
261
+ # Connect the radio button to a handler for exclusive selection
262
+ radio_button.toggled.connect(self.get_selected_image)
263
+ self.table_vars[i] = radio_button
264
+
265
+ # Calculate the row and column for each radio button in the layout
266
+ row = (i) // 3 # Row starts at 1 after the label
267
+ col = (i) % 3 # Column ranges from 0 to 11
268
+
269
+ wafer_layout.addWidget(radio_button, row, col)
270
+
271
+ group_box.setLayout(wafer_layout)
272
+
273
+ # Add the QGroupBox to the main layout
274
+ self.layout.addWidget(group_box, 1, 4, 1, 1)
275
+
276
+ def refresh_radiobuttons(self):
277
+ """Recreates the radio buttons after updating the data in Settings."""
278
+ self.image_radiobuttons() # Call your method to recreate the radio buttons
279
+
280
+ def get_selected_image(self):
281
+ """Track the selected radio button."""
282
+ selected_number = None # Variable to store the selected radio button number
283
+ n_types= len(self.table_vars.items())
284
+ # Iterate over all radio buttons
285
+ for number, radio_button in self.table_vars.items():
286
+
287
+ if radio_button.isChecked():
288
+ selected_number = number # Track the currently selected radio button
289
+
290
+ if selected_number is not None:
291
+ self.selected_image = selected_number # Store the selected option for further use
292
+ return self.selected_image, n_types
293
+
294
+ def create_radiobuttons(self):
295
+ """Create radio buttons for tools and a settings button."""
296
+
297
+ # Create a QGroupBox for "Functions (Wafer)"
298
+ frame = QGroupBox("Functions (Wafer)")
299
+ frame.setStyleSheet(GROUP_BOX_STYLE)
300
+
301
+ frame_layout = QGridLayout(frame)
302
+
303
+ # Add radio buttons to the frame layout
304
+ frame_layout.addWidget(self.split_rename, 0, 0)
305
+ frame_layout.addWidget(self.rename, 1, 0)
306
+ frame_layout.addWidget(self.clean, 2, 0)
307
+ frame_layout.setContentsMargins(5, 20, 5, 5)
308
+ # Add the frame to the main layout
309
+ self.layout.addWidget(frame, 0, 2) # Add frame to main layout
310
+
311
+ # Add buttons to the shared button group
312
+ self.button_group.addButton(self.split_rename)
313
+ self.button_group.addButton(self.rename)
314
+ self.button_group.addButton(self.clean)
315
+
316
+ def create_radiobuttons_all(self):
317
+ """Create radio buttons for tools and a settings button."""
318
+
319
+ # Create a QGroupBox for "Functions (Lot)"
320
+ frame = QGroupBox("Functions (Lot)")
321
+ frame.setStyleSheet(GROUP_BOX_STYLE)
322
+
323
+ frame_layout = QGridLayout(frame)
324
+
325
+ # Add radio buttons to the frame layout
326
+ frame_layout.addWidget(self.split_rename_all, 0, 0)
327
+ frame_layout.addWidget(self.rename_all, 1, 0)
328
+ frame_layout.addWidget(self.clean_all, 2, 0)
329
+
330
+ frame_layout.setContentsMargins(5, 20, 5, 5)
331
+ # Add the frame to the main layout
332
+ self.layout.addWidget(frame, 0, 3) # Add frame to main layout
333
+
334
+ # Add buttons to the shared button group
335
+ self.button_group.addButton(self.split_rename_all)
336
+ self.button_group.addButton(self.rename_all)
337
+ self.button_group.addButton(self.clean_all)
338
+
339
+
340
+ def create_radiobuttons_other(self):
341
+ """Create radio buttons for tools and a settings button."""
342
+
343
+ # Create a QGroupBox for "Functions (Other)"
344
+ frame = QGroupBox("Functions (Other)")
345
+ frame.setStyleSheet(GROUP_BOX_STYLE)
346
+
347
+ frame_layout = QGridLayout(frame)
348
+
349
+ # Add radio buttons to the frame layout
350
+ frame_layout.addWidget(self.create_folder, 0, 0)
351
+ frame_layout.setContentsMargins(5, 20, 5, 5)
352
+
353
+ # Add the frame to the main layout
354
+ self.layout.addWidget(frame, 0, 1) # Add frame to main layout
355
+
356
+ # Add buttons to the shared button group
357
+ self.button_group.addButton(self.create_folder)
358
+
359
+ def select_folder(self):
360
+ """Select a parent folder"""
361
+ folder = QFileDialog.getExistingDirectory(self, "Select a Folder")
362
+
363
+ if folder:
364
+ self.dirname = folder
365
+ max_characters = 20 # Set character limit
366
+
367
+ # Truncate text if it exceeds the limit
368
+ display_text = self.dirname if len(
369
+ self.dirname) <= max_characters else self.dirname[
370
+ :max_characters] + '...'
371
+ self.folder_path_label.setText(display_text)
372
+
373
+ def create_run_button(self):
374
+ """Create a button to run data processing"""
375
+
376
+ # Create the QPushButton
377
+ run_button = QPushButton("Run function")
378
+ run_button.setStyleSheet(RUN_BUTTON_STYLE)
379
+ run_button.setFixedWidth(150)
380
+ run_button.clicked.connect(self.run_data_processing)
381
+
382
+ # Add the button to the layout at position (0, 3)
383
+ self.layout.addWidget(run_button, 0, 5)
384
+
385
+ def run_data_processing(self):
386
+ """Handles photoluminescence data processing and updates progress."""
387
+
388
+ scale_data = self.new_folder + os.sep + "settings_data.json"
389
+ wafer_number= self.get_selected_option()
390
+
391
+
392
+ if not self.dirname or not any([self.rename.isChecked()
393
+ or not self.clean.isChecked()
394
+ or not self.split_rename.isChecked()
395
+ or not self.rename_all.isChecked()
396
+ or not self.clean_all.isChecked()
397
+ or not self.split_rename_all.isChecked()
398
+ ]):
399
+ return
400
+
401
+ # Initialize processing classes
402
+ sem_class = Process(self.dirname, wafer=wafer_number, scale = scale_data)
403
+ total_steps = 0
404
+ if self.split_rename.isChecked():
405
+ total_steps = 3
406
+ if self.rename.isChecked():
407
+ total_steps = 1
408
+ if self.clean.isChecked():
409
+ total_steps = 1
410
+
411
+ if self.split_rename_all.isChecked():
412
+ total_steps = 3
413
+ if self.rename_all.isChecked():
414
+ total_steps = 1
415
+ if self.clean_all.isChecked():
416
+ total_steps = 1
417
+ if self.create_folder.isChecked():
418
+ total_steps = 1
419
+
420
+
421
+ progress_dialog = QProgressDialog("Data processing in progress...",
422
+ "Cancel", 0, total_steps, self)
423
+
424
+ font = QFont()
425
+ font.setPointSize(20) # Set the font size to 14
426
+ # (or any size you prefer)
427
+ progress_dialog.setFont(font)
428
+
429
+ progress_dialog.setWindowTitle("Processing")
430
+ progress_dialog.setWindowModality(Qt.ApplicationModal)
431
+ progress_dialog.setAutoClose(
432
+ False) # Ensure the dialog is not closed automatically
433
+ progress_dialog.setCancelButton(None) # Hide the cancel button
434
+ progress_dialog.resize(400, 150) # Set a larger size for the dialog
435
+
436
+ progress_dialog.show()
437
+
438
+ QApplication.processEvents()
439
+
440
+ def execute_with_timer(task_name, task_function, *args, **kwargs):
441
+ """Executes a task and displays the time taken."""
442
+ start_time = time.time()
443
+ progress_dialog.setLabelText(task_name)
444
+ QApplication.processEvents() # Ensures the interface is updated
445
+ task_function(*args, **kwargs)
446
+ elapsed_time = time.time() - start_time
447
+ print(f"{task_name} completed in {elapsed_time:.2f} seconds.")
448
+
449
+ if self.split_rename.isChecked():
450
+ execute_with_timer("Cleaning of folders", sem_class.clean)
451
+ execute_with_timer("Create folders",
452
+ sem_class.organize_and_rename_files)
453
+
454
+ execute_with_timer("Split w/ tag", sem_class.split_tiff)
455
+ execute_with_timer("Rename w/ tag", sem_class.rename)
456
+ self.update_wafer()
457
+
458
+ if self.split_rename_all.isChecked():
459
+ execute_with_timer("Cleaning of folders", sem_class.clean_all)
460
+ execute_with_timer("Create folders",
461
+ sem_class.organize_and_rename_files)
462
+
463
+ execute_with_timer("Split w/ tag", sem_class.split_tiff_all)
464
+ execute_with_timer("Rename w/ tag", sem_class.rename_all)
465
+ self.update_wafer()
466
+
467
+ if self.rename_all.isChecked():
468
+ execute_with_timer("Rename files w/o tag", sem_class.clean_folders_and_files)
469
+ execute_with_timer("Create folders", sem_class.organize_and_rename_files)
470
+ self.update_wafer()
471
+ execute_with_timer("Rename files w/o tag", sem_class.rename_wo_legend_all)
472
+
473
+ if self.rename.isChecked():
474
+ execute_with_timer("Rename files w/o tag", sem_class.clean_folders_and_files)
475
+ execute_with_timer("Create folders", sem_class.organize_and_rename_files)
476
+ self.update_wafer()
477
+ execute_with_timer("Rename files w/o tag", sem_class.rename_wo_legend)
478
+
479
+ if self.clean.isChecked():
480
+ execute_with_timer("Cleaning of folders", sem_class.clean)
481
+
482
+ if self.clean_all.isChecked():
483
+ execute_with_timer("Cleaning of folders", sem_class.clean_all)
484
+
485
+ if self.create_folder.isChecked():
486
+ execute_with_timer("Create folders", sem_class.organize_and_rename_files)
487
+ self.update_wafer()
488
+
489
+ progress_dialog.close()
490
+
491
+
492
+ if __name__ == "__main__":
493
+ app = QApplication(sys.argv)
494
+ settings_window = SettingsWindow()
495
+ settings_window.show()
496
+ sys.exit(app.exec_())
@@ -0,0 +1,54 @@
1
+ """
2
+ Manage the scrollbar and the functions for the window size
3
+ """
4
+ from PyQt5.QtCore import Qt, QSize
5
+ from PyQt5.QtWidgets import QScrollArea, QVBoxLayout
6
+ from PyQt5.QtGui import QGuiApplication
7
+
8
+
9
+ class LayoutFrame:
10
+ """Class for setting up layout and scroll area"""
11
+
12
+ def __init__(self, main_window):
13
+ self.main_window = main_window
14
+ self.canvas_widget = None
15
+ self.canvas_layout = None
16
+ self.scroll_area = QScrollArea(main_window)
17
+
18
+ def setup_layout(self, canvas_widget, canvas_layout):
19
+ """Set up layout with scroll area and other settings"""
20
+ self.canvas_widget = canvas_widget
21
+ self.canvas_layout = canvas_layout
22
+
23
+ # Set up the QScrollArea
24
+ self.scroll_area.setWidget(self.canvas_widget)
25
+ self.scroll_area.setWidgetResizable(True)
26
+ self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
27
+ self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
28
+
29
+ # Set layout for the main window
30
+ layout = QVBoxLayout(self.main_window)
31
+ layout.addWidget(self.scroll_area)
32
+ self.main_window.setLayout(layout)
33
+
34
+ def set_max_window_size(self):
35
+ """Set the maximum window size based on the screen size"""
36
+ screen_geometry = QGuiApplication.primaryScreen().availableGeometry()
37
+ max_width = screen_geometry.width()
38
+ max_height = screen_geometry.height() - 50
39
+ self.main_window.setMaximumSize(max_width, max_height)
40
+
41
+ def position_window_top_left(self):
42
+ """Position the window at the top-left corner of the screen"""
43
+ screen_geometry = QGuiApplication.primaryScreen().availableGeometry()
44
+ self.main_window.move(screen_geometry.topLeft())
45
+
46
+ def adjust_scroll_area_size(self):
47
+ """Adjust the size of the window based on the content"""
48
+ self.canvas_widget.adjustSize()
49
+ optimal_size = self.canvas_widget.sizeHint()
50
+
51
+ screen_size = QGuiApplication.primaryScreen().availableSize()
52
+ new_size = QSize(min(optimal_size.width(), screen_size.width()) + 50,
53
+ min(optimal_size.height(), screen_size.height()) + 50)
54
+ self.main_window.resize(new_size)