49
49
50
50
from typing import Optional , List , Dict
51
51
52
- Resources .addSearchPath (
53
- os .path .join (
54
- os .path .abspath (os .path .dirname (__file__ )),
55
- "resources"
56
- )
57
- ) # Plugin translation file import
58
-
59
- catalog = i18nCatalog ("meshtools" )
60
-
61
52
62
53
class MeshTools (Extension , QObject ,):
63
54
def __init__ (self , parent = None ) -> None :
64
55
QObject .__init__ (self , parent )
65
56
Extension .__init__ (self )
66
57
67
- self ._application = CuraApplication .getInstance ()
58
+ Resources .addSearchPath (
59
+ os .path .join (
60
+ os .path .abspath (os .path .dirname (__file__ )),
61
+ "resources"
62
+ )
63
+ ) # Plugin translation file import
64
+ self ._catalog = i18nCatalog ("meshtools" )
65
+
66
+ self ._qml_folder = "qml_qt6" if not USE_QT5 else "qml_qt5"
68
67
69
- self ._qml_folder = "qml" if not USE_QT5 else "qml_qt5"
68
+ self ._application = CuraApplication . getInstance ()
70
69
71
70
self ._application .engineCreatedSignal .connect (self ._onEngineCreated )
72
71
self ._application .fileLoaded .connect (self ._onFileLoaded )
@@ -88,23 +87,23 @@ def __init__(self, parent = None) -> None:
88
87
self ._preferences .addPreference ("meshtools/randomise_location_on_load" , False )
89
88
self ._preferences .addPreference ("meshtools/model_unit_factor" , 1 )
90
89
91
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Reload model" ), self .reloadMesh )
92
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Rename model..." ), self .renameMesh )
93
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Replace models..." ), self .replaceMeshes )
90
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Reload model" ), self .reloadMesh )
91
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Rename model..." ), self .renameMesh )
92
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Replace models..." ), self .replaceMeshes )
94
93
self .addMenuItem ("" , lambda : None )
95
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Check models" ), self .checkMeshes )
96
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Analyse models" ), self .analyseMeshes )
97
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Fix simple holes" ), self .fixSimpleHolesForMeshes )
98
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Fix model normals" ), self .fixNormalsForMeshes )
99
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Split model into parts" ), self .splitMeshes )
94
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Check models" ), self .checkMeshes )
95
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Analyse models" ), self .analyseMeshes )
96
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Fix simple holes" ), self .fixSimpleHolesForMeshes )
97
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Fix model normals" ), self .fixNormalsForMeshes )
98
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Split model into parts" ), self .splitMeshes )
100
99
self .addMenuItem (" " , lambda : None )
101
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Randomise location" ), self .randomiseMeshLocation )
102
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Apply transformations to mesh" ), self .bakeMeshTransformation )
103
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Reset origin to center of mesh" ), self .resetMeshOrigin )
100
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Randomise location" ), self .randomiseMeshLocation )
101
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Apply transformations to mesh" ), self .bakeMeshTransformation )
102
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Reset origin to center of mesh" ), self .resetMeshOrigin )
104
103
self .addMenuItem (" " , lambda : None )
105
- self .addMenuItem (catalog .i18nc ("@item:inmenu" , "Mesh Tools settings..." ), self .showSettingsDialog )
104
+ self .addMenuItem (self . _catalog .i18nc ("@item:inmenu" , "Mesh Tools settings..." ), self .showSettingsDialog )
106
105
107
- self ._message = Message (title = catalog .i18nc ("@info:title" , "Mesh Tools" ))
106
+ self ._message = Message (title = self . _catalog .i18nc ("@info:title" , "Mesh Tools" ))
108
107
self ._additional_menu = None # type: Optional[QObject]
109
108
110
109
def showSettingsDialog (self ) -> None :
@@ -155,7 +154,7 @@ def _onEngineCreated(self) -> None:
155
154
156
155
if USE_QT5 :
157
156
context_menu .insertSeparator (0 )
158
- context_menu .insertMenu (0 , catalog .i18nc ("@info:title" , "Mesh Tools" ))
157
+ context_menu .insertMenu (0 , self . _catalog .i18nc ("@info:title" , "Mesh Tools" ))
159
158
160
159
# Move additional menu items into context menu
161
160
self ._additional_menu .moveToContextMenu (context_menu )
@@ -223,23 +222,23 @@ def checkQueuedNodes(self) -> None:
223
222
224
223
if self ._preferences .getValue ("meshtools/check_models_on_load" ) and not tri_node .is_watertight :
225
224
if not file_name :
226
- file_name = catalog .i18nc ("@text Print job name" , "Untitled" )
225
+ file_name = self . _catalog .i18nc ("@text Print job name" , "Untitled" )
227
226
base_name = os .path .basename (file_name )
228
227
229
228
if file_name in self ._mesh_not_watertight_messages :
230
229
self ._mesh_not_watertight_messages [file_name ].hide ()
231
230
232
- message = Message (title = catalog .i18nc ("@info:title" , "Mesh Tools" ))
233
- body = catalog .i18nc ("@info:status" , "Model %s is not watertight, and may not print properly." ) % base_name
231
+ message = Message (title = self . _catalog .i18nc ("@info:title" , "Mesh Tools" ))
232
+ body = self . _catalog .i18nc ("@info:status" , "Model %s is not watertight, and may not print properly." ) % base_name
234
233
235
234
# XRayView may not be available if the plugin has been disabled
236
235
active_view = self ._controller .getActiveView ()
237
236
if active_view and "XRayView" in self ._controller .getAllViews () and active_view .getPluginId () != "XRayView" :
238
- body += " " + catalog .i18nc ("@info:status" , "Check X-Ray View and repair the model before printing it." )
239
- message .addAction ("X-Ray" , catalog .i18nc ("@action:button" , "Show X-Ray View" ), "" , "" )
237
+ body += " " + self . _catalog .i18nc ("@info:status" , "Check X-Ray View and repair the model before printing it." )
238
+ message .addAction ("X-Ray" , self . _catalog .i18nc ("@action:button" , "Show X-Ray View" ), "" , "" )
240
239
message .actionTriggered .connect (self ._showXRayView )
241
240
else :
242
- body += " " + catalog .i18nc ("@info:status" , "Repair the model before printing it." )
241
+ body += " " + self . _catalog .i18nc ("@info:status" , "Repair the model before printing it." )
243
242
244
243
message .setText (body )
245
244
message .show ()
@@ -277,12 +276,12 @@ def _getSelectedNodes(self, force_single = False) -> List[SceneNode]:
277
276
if len (selection ) == 1 :
278
277
return selection [:]
279
278
280
- self ._message .setText (catalog .i18nc ("@info:status" , "Please select a single model first" ))
279
+ self ._message .setText (self . _catalog .i18nc ("@info:status" , "Please select a single model first" ))
281
280
else :
282
281
if len (selection ) >= 1 :
283
282
return selection [:]
284
283
285
- self ._message .setText (catalog .i18nc ("@info:status" , "Please select one or more models first" ))
284
+ self ._message .setText (self . _catalog .i18nc ("@info:status" , "Please select one or more models first" ))
286
285
287
286
self ._message .show ()
288
287
return []
@@ -300,7 +299,7 @@ def _getAllSelectedNodes(self) -> List[SceneNode]:
300
299
if deep_selection :
301
300
return deep_selection
302
301
303
- self ._message .setText (catalog .i18nc ("@info:status" , "Please select one or more models first" ))
302
+ self ._message .setText (self . _catalog .i18nc ("@info:status" , "Please select one or more models first" ))
304
303
self ._message .show ()
305
304
306
305
return []
@@ -311,16 +310,16 @@ def checkMeshes(self) -> None:
311
310
if not nodes_list :
312
311
return
313
312
314
- message_body = catalog .i18nc ("@info:status" , "Check summary:" )
313
+ message_body = self . _catalog .i18nc ("@info:status" , "Check summary:" )
315
314
for node in nodes_list :
316
315
tri_node = self ._toTriMesh (node .getMeshData ())
317
316
message_body = message_body + "\n - %s" % node .getName ()
318
317
if tri_node .is_watertight :
319
- message_body = message_body + " " + catalog .i18nc ("@info:status" , "is watertight" )
318
+ message_body = message_body + " " + self . _catalog .i18nc ("@info:status" , "is watertight" )
320
319
else :
321
- message_body = message_body + " " + catalog .i18nc ("@info:status" , "is not watertight and may not print properly" )
320
+ message_body = message_body + " " + self . _catalog .i18nc ("@info:status" , "is not watertight and may not print properly" )
322
321
if tri_node .body_count > 1 :
323
- message_body = message_body + " " + catalog .i18nc ("@info:status" , "and consists of {body_count} submeshes" ).format (body_count = tri_node .body_count )
322
+ message_body = message_body + " " + self . _catalog .i18nc ("@info:status" , "and consists of {body_count} submeshes" ).format (body_count = tri_node .body_count )
324
323
325
324
self ._message .setText (message_body )
326
325
self ._message .show ()
@@ -331,13 +330,13 @@ def analyseMeshes(self) -> None:
331
330
if not nodes_list :
332
331
return
333
332
334
- message_body = catalog .i18nc ("@info:status" , "Analysis summary:" )
333
+ message_body = self . _catalog .i18nc ("@info:status" , "Analysis summary:" )
335
334
for node in nodes_list :
336
335
tri_node = self ._toTriMesh (node .getMeshDataTransformed ())
337
336
message_body = message_body + "\n - %s:" % node .getName ()
338
- message_body += "\n \t " + catalog .i18nc ("@info:status" , "%d vertices, %d faces" ) % (len (tri_node .vertices ), len (tri_node .faces ))
337
+ message_body += "\n \t " + self . _catalog .i18nc ("@info:status" , "%d vertices, %d faces" ) % (len (tri_node .vertices ), len (tri_node .faces ))
339
338
if tri_node .is_watertight :
340
- message_body += "\n \t " + catalog .i18nc ("@info:status" , "area: %d mm2, volume: %d mm3" ) % (tri_node .area , tri_node .volume )
339
+ message_body += "\n \t " + self . _catalog .i18nc ("@info:status" , "area: %d mm2, volume: %d mm3" ) % (tri_node .area , tri_node .volume )
341
340
342
341
self ._message .setText (message_body )
343
342
self ._message .show ()
@@ -353,7 +352,7 @@ def fixSimpleHolesForMeshes(self) -> None:
353
352
success = tri_node .fill_holes ()
354
353
self ._replaceSceneNode (node , [tri_node ])
355
354
if not success :
356
- self ._message .setText (catalog .i18nc (
355
+ self ._message .setText (self . _catalog .i18nc (
357
356
"@info:status" ,
358
357
"The mesh needs more extensive repair to become watertight"
359
358
))
@@ -376,15 +375,15 @@ def splitMeshes(self) -> None:
376
375
if not nodes_list :
377
376
return
378
377
379
- message_body = catalog .i18nc ("@info:status" , "Split result:" )
378
+ message_body = self . _catalog .i18nc ("@info:status" , "Split result:" )
380
379
for node in nodes_list :
381
380
message_body = message_body + "\n - %s" % node .getName ()
382
381
tri_node = self ._toTriMesh (node .getMeshData ())
383
382
if tri_node .body_count > 1 :
384
383
self ._replaceSceneNode (node , tri_node .split (only_watertight = False ))
385
- message_body = message_body + " " + catalog .i18nc ("@info:status" , "was split in %d submeshes" ) % tri_node .body_count
384
+ message_body = message_body + " " + self . _catalog .i18nc ("@info:status" , "was split in %d submeshes" ) % tri_node .body_count
386
385
else :
387
- message_body = message_body + " " + catalog .i18nc ("@info:status" , "could not be split into submeshes" )
386
+ message_body = message_body + " " + self . _catalog .i18nc ("@info:status" , "could not be split into submeshes" )
388
387
389
388
self ._message .setText (message_body )
390
389
self ._message .show ()
@@ -398,7 +397,7 @@ def replaceMeshes(self) -> None:
398
397
for node in self ._node_queue :
399
398
mesh_data = node .getMeshData ()
400
399
if not mesh_data :
401
- self ._message .setText (catalog .i18nc ("@info:status" , "Replacing a group is not supported" ))
400
+ self ._message .setText (self . _catalog .i18nc ("@info:status" , "Replacing a group is not supported" ))
402
401
self ._message .show ()
403
402
self ._node_queue = [] #type: List[SceneNode]
404
403
return
@@ -419,12 +418,12 @@ def replaceMeshes(self) -> None:
419
418
420
419
file_name , _ = QFileDialog .getOpenFileName (
421
420
parent = None ,
422
- caption = catalog .i18nc ("@title:window" , "Select Replacement Mesh File" ),
421
+ caption = self . _catalog .i18nc ("@title:window" , "Select Replacement Mesh File" ),
423
422
directory = directory , options = options , filter = filter_types
424
423
)
425
424
else :
426
425
dialog = QFileDialog ()
427
- dialog .setWindowTitle (catalog .i18nc ("@title:window" , "Select Replacement Mesh File" ))
426
+ dialog .setWindowTitle (self . _catalog .i18nc ("@title:window" , "Select Replacement Mesh File" ))
428
427
dialog .setDirectory (directory )
429
428
dialog .setNameFilters (self ._application .getMeshFileHandler ().supportedReadFileTypes )
430
429
dialog .setAcceptMode (QFileDialog .AcceptMode .AcceptOpen )
@@ -473,14 +472,14 @@ def reloadMesh(self) -> None:
473
472
474
473
mesh_data = self ._node_queue [0 ].getMeshData ()
475
474
if not mesh_data :
476
- self ._message .setText (catalog .i18nc ("@info:status" , "Reloading a group is not supported" ))
475
+ self ._message .setText (self . _catalog .i18nc ("@info:status" , "Reloading a group is not supported" ))
477
476
self ._message .show ()
478
477
self ._node_queue = [] #type: List[SceneNode]
479
478
return
480
479
481
480
file_name = mesh_data .getFileName ()
482
481
if not file_name :
483
- self ._message .setText (catalog .i18nc ("@info:status" , "No link to the original file was found" ))
482
+ self ._message .setText (self . _catalog .i18nc ("@info:status" , "No link to the original file was found" ))
484
483
self ._message .show ()
485
484
self ._node_queue = [] #type: List[SceneNode]
486
485
return
@@ -492,14 +491,14 @@ def reloadMesh(self) -> None:
492
491
def _readMeshFinished (self , job ) -> None :
493
492
job_result = job .getResult ()
494
493
if len (job_result ) == 0 :
495
- self ._message .setText (catalog .i18nc ("@info:status" , "Failed to load mesh" ))
494
+ self ._message .setText (self . _catalog .i18nc ("@info:status" , "Failed to load mesh" ))
496
495
self ._message .show ()
497
496
self ._node_queue = [] #type: List[SceneNode]
498
497
return
499
498
500
499
mesh_data = job_result [0 ].getMeshData ()
501
500
if not mesh_data :
502
- self ._message .setText (catalog .i18nc ("@info:status" , "Replacing meshes with a group of meshes is not supported" ))
501
+ self ._message .setText (self . _catalog .i18nc ("@info:status" , "Replacing meshes with a group of meshes is not supported" ))
503
502
self ._message .show ()
504
503
self ._node_queue = [] #type: List[SceneNode]
505
504
return
@@ -508,7 +507,7 @@ def _readMeshFinished(self, job) -> None:
508
507
if file_name :
509
508
mesh_name = os .path .basename (file_name )
510
509
else :
511
- mesh_name = catalog .i18nc ("@text Print job name" , "Untitled" )
510
+ mesh_name = self . _catalog .i18nc ("@text Print job name" , "Untitled" )
512
511
513
512
has_merged_nodes = False
514
513
@@ -572,7 +571,7 @@ def bakeMeshTransformation(self) -> None:
572
571
file_name = ""
573
572
mesh_name = os .path .basename (file_name )
574
573
if not mesh_name :
575
- mesh_name = catalog .i18nc ("@text Print job name" , "Untitled" )
574
+ mesh_name = self . _catalog .i18nc ("@text Print job name" , "Untitled" )
576
575
577
576
local_transformation = node .getLocalTransformation ()
578
577
position = local_transformation .getTranslation ()
0 commit comments