commit
a4a8258730
|
@ -1,15 +1,14 @@
|
||||||
import sys, os
|
import sys, os
|
||||||
from PyQt5 import sip
|
|
||||||
|
|
||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
from PyQt5 import QtWidgets
|
||||||
from PyQt5.QtCore import QSettings, Qt
|
from PyQt5.QtCore import QSettings, Qt
|
||||||
from FlatCAMApp import App
|
from FlatCAMApp import App
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
import VisPyPatches
|
from flatcamGUI import VisPyPatches
|
||||||
|
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
# cx_freeze 'module win32' workaround
|
# cx_freeze 'module win32' workaround
|
||||||
import OpenGL.platform.win32
|
pass
|
||||||
|
|
||||||
def debug_trace():
|
def debug_trace():
|
||||||
"""
|
"""
|
||||||
|
|
959
FlatCAMApp.py
959
FlatCAMApp.py
File diff suppressed because it is too large
Load Diff
676
FlatCAMEditor.py
676
FlatCAMEditor.py
File diff suppressed because it is too large
Load Diff
479
FlatCAMObj.py
479
FlatCAMObj.py
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Matthieu Berthomé #
|
||||||
|
# Date: 5/26/2017 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from importlib.machinery import SourceFileLoader
|
from importlib.machinery import SourceFileLoader
|
||||||
import os
|
import os
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# MIT Licence #
|
# MIT Licence #
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
from FlatCAMGUI import FlatCAMActivityView
|
from flatcamGUI.FlatCAMGUI import FlatCAMActivityView
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
|
|
|
@ -83,11 +83,11 @@ class FlatCAMTool(QtWidgets.QWidget):
|
||||||
# Put ourself in the GUI
|
# Put ourself in the GUI
|
||||||
self.app.ui.tool_scroll_area.setWidget(self)
|
self.app.ui.tool_scroll_area.setWidget(self)
|
||||||
|
|
||||||
# Set the tool name as the widget object name
|
|
||||||
self.app.ui.tool_scroll_area.widget().setObjectName(self.toolName)
|
|
||||||
|
|
||||||
# Switch notebook to tool page
|
# Switch notebook to tool page
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.tool_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.tool_tab)
|
||||||
|
|
||||||
|
# Set the tool name as the widget object name
|
||||||
|
self.app.ui.tool_scroll_area.widget().setObjectName(self.toolName)
|
||||||
|
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from PyQt5 import QtWidgets, QtGui
|
||||||
|
from PyQt5.QtCore import QSettings
|
||||||
|
|
||||||
|
from flatcamGUI.GUIElements import log
|
||||||
|
import gettext
|
||||||
|
|
||||||
|
# ISO639-1 codes from here: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
||||||
|
languages_dict = {
|
||||||
|
'zh': 'Chinese',
|
||||||
|
'de': 'German',
|
||||||
|
'en': 'English',
|
||||||
|
'es': 'Spanish',
|
||||||
|
'fr': 'French',
|
||||||
|
'it': 'Italian',
|
||||||
|
'ro': 'Romanian',
|
||||||
|
'ru': 'Russian',
|
||||||
|
}
|
||||||
|
|
||||||
|
translations = {}
|
||||||
|
|
||||||
|
languages_path_search = ''
|
||||||
|
|
||||||
|
|
||||||
|
def load_languages():
|
||||||
|
languages_path_search = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'locale')
|
||||||
|
|
||||||
|
available_translations = next(os.walk(languages_path_search))[1]
|
||||||
|
|
||||||
|
for lang in available_translations:
|
||||||
|
try:
|
||||||
|
if lang in languages_dict.keys():
|
||||||
|
translations[lang] = languages_dict[lang]
|
||||||
|
except KeyError as e:
|
||||||
|
log.debug("FlatCAMTranslations.load_languages() --> %s" % str(e))
|
||||||
|
return translations
|
||||||
|
|
||||||
|
|
||||||
|
def languages_dir():
|
||||||
|
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'locale')
|
||||||
|
|
||||||
|
|
||||||
|
def on_language_apply_click(app, restart=False):
|
||||||
|
"""
|
||||||
|
Using instructions from here:
|
||||||
|
https://inventwithpython.com/blog/2014/12/20/translate-your-python-3-program-with-the-gettext-module/
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
name = app.ui.general_defaults_form.general_app_group.language_cb.currentText()
|
||||||
|
|
||||||
|
# do nothing if trying to apply the language that is the current language (already applied).
|
||||||
|
settings = QSettings("Open Source", "FlatCAM")
|
||||||
|
if settings.contains("language"):
|
||||||
|
current_language = settings.value('language', type=str)
|
||||||
|
if current_language == name:
|
||||||
|
return
|
||||||
|
|
||||||
|
if restart:
|
||||||
|
msgbox = QtWidgets.QMessageBox()
|
||||||
|
msgbox.setText("The application will restart.")
|
||||||
|
msgbox.setInformativeText("Are you sure do you want to change the current language to %s?" % name.capitalize())
|
||||||
|
msgbox.setWindowTitle("Apply Language ...")
|
||||||
|
msgbox.setWindowIcon(QtGui.QIcon('share/language32.png'))
|
||||||
|
msgbox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel)
|
||||||
|
msgbox.setDefaultButton(QtWidgets.QMessageBox.Yes)
|
||||||
|
|
||||||
|
response = msgbox.exec_()
|
||||||
|
|
||||||
|
if response == QtWidgets.QMessageBox.Cancel:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
settings = QSettings("Open Source", "FlatCAM")
|
||||||
|
saved_language = name
|
||||||
|
settings.setValue('language', saved_language)
|
||||||
|
# This will write the setting to the platform specific storage.
|
||||||
|
del settings
|
||||||
|
|
||||||
|
restart_program(app=app)
|
||||||
|
|
||||||
|
def apply_language(domain, lang=None):
|
||||||
|
lang_code = ''
|
||||||
|
|
||||||
|
if lang is None:
|
||||||
|
settings = QSettings("Open Source", "FlatCAM")
|
||||||
|
if settings.contains("language"):
|
||||||
|
name = settings.value('language')
|
||||||
|
else:
|
||||||
|
name = settings.value('English')
|
||||||
|
else:
|
||||||
|
name = str(lang)
|
||||||
|
|
||||||
|
for lang_code, lang_usable in load_languages().items():
|
||||||
|
if lang_usable == name:
|
||||||
|
# break and then use the current key as language
|
||||||
|
break
|
||||||
|
|
||||||
|
if lang_code == '':
|
||||||
|
return "no language"
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
current_lang = gettext.translation(str(domain), localedir=languages_dir(), languages=[lang_code])
|
||||||
|
current_lang.install()
|
||||||
|
except Exception as e:
|
||||||
|
log.debug("FlatCAMTranslation.apply_language() --> %s" % str(e))
|
||||||
|
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def restart_program(app):
|
||||||
|
"""Restarts the current program.
|
||||||
|
Note: this function does not return. Any cleanup action (like
|
||||||
|
saving data) must be done before calling this function.
|
||||||
|
"""
|
||||||
|
app.save_defaults()
|
||||||
|
python = sys.executable
|
||||||
|
os.execl(python, python, *sys.argv)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
# MIT Licence #
|
# MIT Licence #
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
# File modified by: Dennis Hayrullin #
|
||||||
|
############################################################
|
||||||
|
|
||||||
# from PyQt5.QtCore import QModelIndex
|
# from PyQt5.QtCore import QModelIndex
|
||||||
from FlatCAMObj import *
|
from FlatCAMObj import *
|
||||||
import inspect # TODO: Remove
|
import inspect # TODO: Remove
|
||||||
|
@ -14,6 +18,14 @@ from PyQt5 import QtGui, QtCore, QtWidgets
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
# import webbrowser
|
# import webbrowser
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class KeySensitiveListView(QtWidgets.QTreeView):
|
class KeySensitiveListView(QtWidgets.QTreeView):
|
||||||
"""
|
"""
|
||||||
|
@ -65,7 +77,7 @@ class KeySensitiveListView(QtWidgets.QTreeView):
|
||||||
# file drop from outside application
|
# file drop from outside application
|
||||||
if drop_indicator == QtWidgets.QAbstractItemView.OnItem:
|
if drop_indicator == QtWidgets.QAbstractItemView.OnItem:
|
||||||
if self.filename == "":
|
if self.filename == "":
|
||||||
self.app.inform.emit("Open cancelled.")
|
self.app.inform.emit(_("Open cancelled."))
|
||||||
else:
|
else:
|
||||||
if self.filename.lower().rpartition('.')[-1] in self.app.grb_list:
|
if self.filename.lower().rpartition('.')[-1] in self.app.grb_list:
|
||||||
self.app.worker_task.emit({'fcn': self.app.open_gerber,
|
self.app.worker_task.emit({'fcn': self.app.open_gerber,
|
||||||
|
@ -387,7 +399,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
||||||
"setData() --> Could not remove the old object name from auto-completer model list")
|
"setData() --> Could not remove the old object name from auto-completer model list")
|
||||||
|
|
||||||
obj.build_ui()
|
obj.build_ui()
|
||||||
self.app.inform.emit("Object renamed from %s to %s" % (old_name, new_name))
|
self.app.inform.emit(_("Object renamed from {old} to {new}").format(old=old_name, new=new_name))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -681,17 +693,17 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
||||||
obj = current.indexes()[0].internalPointer().obj
|
obj = current.indexes()[0].internalPointer().obj
|
||||||
|
|
||||||
if obj.kind == 'gerber':
|
if obj.kind == 'gerber':
|
||||||
self.app.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
|
self.app.inform.emit(_('[selected]<span style="color:{color};">{name}</span> selected').format(
|
||||||
('green', str(obj.options['name'])))
|
color='green', name=str(obj.options['name'])))
|
||||||
elif obj.kind == 'excellon':
|
elif obj.kind == 'excellon':
|
||||||
self.app.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
|
self.app.inform.emit(_('[selected]<span style="color:{color};">{name}</span> selected').format(
|
||||||
('brown', str(obj.options['name'])))
|
color='brown', name=str(obj.options['name'])))
|
||||||
elif obj.kind == 'cncjob':
|
elif obj.kind == 'cncjob':
|
||||||
self.app.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
|
self.app.inform.emit(_('[selected]<span style="color:{color};">{name}</span> selected').format(
|
||||||
('blue', str(obj.options['name'])))
|
color='blue', name=str(obj.options['name'])))
|
||||||
elif obj.kind == 'geometry':
|
elif obj.kind == 'geometry':
|
||||||
self.app.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
|
self.app.inform.emit(_('[selected]<span style="color:{color};">{name}</span> selected').format(
|
||||||
('red', str(obj.options['name'])))
|
color='red', name=str(obj.options['name'])))
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
FlatCAMApp.App.log.debug("on_list_selection_change(): Index Error (Nothing selected?)")
|
FlatCAMApp.App.log.debug("on_list_selection_change(): Index Error (Nothing selected?)")
|
||||||
|
@ -721,7 +733,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
||||||
try:
|
try:
|
||||||
a_idx.build_ui()
|
a_idx.build_ui()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[ERROR] Cause of error: %s" % str(e))
|
self.app.inform.emit(_("[ERROR] Cause of error: %s") % str(e))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def get_list(self):
|
def get_list(self):
|
||||||
|
|
81
README.md
81
README.md
|
@ -9,6 +9,87 @@ CAD program, and create G-Code for Isolation routing.
|
||||||
|
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
17.03.2019
|
||||||
|
|
||||||
|
- remade the layout in 2Sided Tool
|
||||||
|
- work in progress for translation in Romanian - 91%
|
||||||
|
- changed some of the app strings formatting to work better with Poedit translation software
|
||||||
|
- fixed bug in Drillcncjob TclCommand
|
||||||
|
- finished translation in Romanian
|
||||||
|
|
||||||
|
|
||||||
|
16.03.2019
|
||||||
|
|
||||||
|
- fixed bug in Paint Tool - Single Poly: no geometry was generated
|
||||||
|
- work in progress for translation in Romanian - 70%
|
||||||
|
|
||||||
|
13.03.2019
|
||||||
|
|
||||||
|
- made the layout combobox current item from Preferences -> General window to reflect the current layout
|
||||||
|
- remade the POT translate file
|
||||||
|
- work in progress in translation for Romanian language 44%
|
||||||
|
- fix for showing tools by activating them from the Menu - final fix.
|
||||||
|
|
||||||
|
11.03.2019
|
||||||
|
|
||||||
|
- changed some icons here and there
|
||||||
|
- fixed the Properties Project menu entry to work on the new way
|
||||||
|
- in Properties tool now the Gerber apertures show the number of polygons in 'solid_geometry' instead of listing the objects
|
||||||
|
- added a visual cue in Menu -> Edit about the entries to enter the Editor and to Save & Exit Editor. When one is enabled the other is disabled.
|
||||||
|
- grouped all the UI files in flatcamGUI folder
|
||||||
|
- grouped all parser files in flatcamParsers folder
|
||||||
|
- another changes to the final_save() function
|
||||||
|
- some strings were left outside the translation formatting - fixed
|
||||||
|
- finished the replacement of '_' symbols throughout the app which conflicted with the _() function used by the i18n
|
||||||
|
- reverted changes in Tools regarding the toggle effect - now they work as expected
|
||||||
|
|
||||||
|
10.03.2019
|
||||||
|
|
||||||
|
- added a fix in the Gerber parser when adding the geometry in the self.apertures dict for the case that the current aperture is None (Allegro does that)
|
||||||
|
- finished support for internationalization by adding a set of .po/.mo files for the English language. Unfortunately the final action can be done only when Beta will be out of Beta (no more changes) or when I will decide to stop working on this app.
|
||||||
|
- changed the tooltip for 'feedrate_rapids' parameter to point out that this parameter is useful only for the Marlin postprocessor
|
||||||
|
- fix app crash for the case that there are no translation files
|
||||||
|
- fixed some forgotten strings to be prepared for internationalization in ToolCalculators
|
||||||
|
- fixed Tools menu no longer working due of changes
|
||||||
|
- added some test translation for the ToolCalculators (in Romanian)
|
||||||
|
- fixed bug in ToolCutOut where for each tool invocation the signals were reconnected
|
||||||
|
- fixed some issues with ToolMeasurement due of above changes
|
||||||
|
- updated the App.final_save() function
|
||||||
|
- fixed an issue created by the fact that I used the '_' char inside the app to designate unused info and that conflicted with the _() function used by gettext
|
||||||
|
- made impossible to try to reapply current language that it's already applied (un-necessary)
|
||||||
|
|
||||||
|
8.03.2019
|
||||||
|
|
||||||
|
- fixed issue when doing th CTRL (or SHIFT) + LMB, the focus is automatically moved to Project Tab
|
||||||
|
- further work in internationalization, added a fallback to English language in case there is no translation for a string
|
||||||
|
- fix for issue #262: when doing Edit-> Save & Close Editor on a Geometry that is not generated through first entering into an Editor, the geometry disappear
|
||||||
|
- finished preparing for internationalization for the files: camlib and objectCollection
|
||||||
|
- fixed tools shortcuts not working anymore due of the new toggle parameter for the .run().
|
||||||
|
- finished preparing for internationalization for the files: FlatCAMEditor, FlatCAMGUI
|
||||||
|
- finished preparing for internationalization for the files: FlatCAMObj, ObjectUI
|
||||||
|
- sorted the languages in the Preferences combobox
|
||||||
|
|
||||||
|
7.03.2019
|
||||||
|
|
||||||
|
- made showing a shape when hovering over objects, optional, by adding a Preferences -> General parameter
|
||||||
|
- starting to work in internationalization using gettext()
|
||||||
|
- Finished adding _() in FlatCAM Tools
|
||||||
|
- fixed Measuring Tool - after doing a measurement the Notebook was switching to Project Tab without letting the user see the results
|
||||||
|
- more work on the translation engine; the app now restarts after a language is applied
|
||||||
|
- added protection against using Travel Z parameter with negative or zero value (in Geometry).
|
||||||
|
- made sure that when the Measuring Tools is active after last click the Status bar is no longer deleted
|
||||||
|
|
||||||
|
6.03.2019
|
||||||
|
|
||||||
|
- modified the way the FlatCAM Tools are run from toolbar as opposed of running them from other sources
|
||||||
|
- some Gerber UI changes
|
||||||
|
|
||||||
|
5.03.2019
|
||||||
|
|
||||||
|
- modified the grbl-laser postprocessor lift_code()
|
||||||
|
- treated an error created by Z_Cut parameter being None
|
||||||
|
- changed the hover and selection box transparency
|
||||||
|
|
||||||
4.03.2019
|
4.03.2019
|
||||||
|
|
||||||
- finished work on object hovering
|
- finished work on object hovering
|
||||||
|
|
241
camlib.py
241
camlib.py
|
@ -9,17 +9,21 @@
|
||||||
#import traceback
|
#import traceback
|
||||||
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos, dot, float32, \
|
from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos, dot, float32, \
|
||||||
transpose
|
transpose
|
||||||
from numpy.linalg import solve, norm
|
from numpy.linalg import solve, norm
|
||||||
import re
|
|
||||||
import sys
|
import re, sys, os, platform
|
||||||
|
import math
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
import collections
|
|
||||||
|
|
||||||
from rtree import index as rtindex
|
from rtree import index as rtindex
|
||||||
|
from lxml import etree as ET
|
||||||
|
|
||||||
# See: http://toblerity.org/shapely/manual.html
|
# See: http://toblerity.org/shapely/manual.html
|
||||||
from shapely.geometry import Polygon, LineString, Point, LinearRing, MultiLineString
|
from shapely.geometry import Polygon, LineString, Point, LinearRing, MultiLineString
|
||||||
|
@ -31,47 +35,43 @@ from shapely.wkt import loads as sloads
|
||||||
from shapely.wkt import dumps as sdumps
|
from shapely.wkt import dumps as sdumps
|
||||||
from shapely.geometry.base import BaseGeometry
|
from shapely.geometry.base import BaseGeometry
|
||||||
from shapely.geometry import shape
|
from shapely.geometry import shape
|
||||||
from shapely import speedups
|
|
||||||
|
|
||||||
|
import collections
|
||||||
from collections import Iterable
|
from collections import Iterable
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import rasterio
|
import rasterio
|
||||||
from rasterio.features import shapes
|
from rasterio.features import shapes
|
||||||
|
import ezdxf
|
||||||
from copy import deepcopy
|
|
||||||
|
|
||||||
# TODO: Commented for FlatCAM packaging with cx_freeze
|
# TODO: Commented for FlatCAM packaging with cx_freeze
|
||||||
|
|
||||||
from xml.dom.minidom import parseString as parse_xml_string
|
|
||||||
|
|
||||||
# from scipy.spatial import KDTree, Delaunay
|
# from scipy.spatial import KDTree, Delaunay
|
||||||
|
|
||||||
from ParseSVG import *
|
from flatcamParsers.ParseSVG import *
|
||||||
from ParseDXF import *
|
from flatcamParsers.ParseDXF import *
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
# import pprint
|
|
||||||
import platform
|
|
||||||
import FlatCAMApp
|
import FlatCAMApp
|
||||||
|
|
||||||
import math
|
|
||||||
|
|
||||||
if platform.architecture()[0] == '64bit':
|
if platform.architecture()[0] == '64bit':
|
||||||
from ortools.constraint_solver import pywrapcp
|
from ortools.constraint_solver import pywrapcp
|
||||||
from ortools.constraint_solver import routing_enums_pb2
|
from ortools.constraint_solver import routing_enums_pb2
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('base2')
|
log = logging.getLogger('base2')
|
||||||
log.setLevel(logging.DEBUG)
|
log.setLevel(logging.DEBUG)
|
||||||
# log.setLevel(logging.WARNING)
|
|
||||||
# log.setLevel(logging.INFO)
|
|
||||||
formatter = logging.Formatter('[%(levelname)s] %(message)s')
|
formatter = logging.Formatter('[%(levelname)s] %(message)s')
|
||||||
handler = logging.StreamHandler()
|
handler = logging.StreamHandler()
|
||||||
handler.setFormatter(formatter)
|
handler.setFormatter(formatter)
|
||||||
log.addHandler(handler)
|
log.addHandler(handler)
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class ParseError(Exception):
|
class ParseError(Exception):
|
||||||
pass
|
pass
|
||||||
|
@ -197,7 +197,7 @@ class Geometry(object):
|
||||||
if isinstance(self.solid_geometry, list):
|
if isinstance(self.solid_geometry, list):
|
||||||
return len(self.solid_geometry) == 0
|
return len(self.solid_geometry) == 0
|
||||||
|
|
||||||
self.app.inform.emit("[ERROR_NOTCL] self.solid_geometry is neither BaseGeometry or list.")
|
self.app.inform.emit(_("[ERROR_NOTCL] self.solid_geometry is neither BaseGeometry or list."))
|
||||||
return
|
return
|
||||||
|
|
||||||
def subtract_polygon(self, points):
|
def subtract_polygon(self, points):
|
||||||
|
@ -1384,9 +1384,9 @@ class Geometry(object):
|
||||||
self.tools[tool]['solid_geometry'] = mirror_geom(self.tools[tool]['solid_geometry'])
|
self.tools[tool]['solid_geometry'] = mirror_geom(self.tools[tool]['solid_geometry'])
|
||||||
else:
|
else:
|
||||||
self.solid_geometry = mirror_geom(self.solid_geometry)
|
self.solid_geometry = mirror_geom(self.solid_geometry)
|
||||||
self.app.inform.emit('[success]Object was mirrored ...')
|
self.app.inform.emit(_('[success]Object was mirrored ...'))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Failed to mirror. No object selected")
|
self.app.inform.emit(_("[ERROR_NOTCL] Failed to mirror. No object selected"))
|
||||||
|
|
||||||
def rotate(self, angle, point):
|
def rotate(self, angle, point):
|
||||||
"""
|
"""
|
||||||
|
@ -1422,9 +1422,9 @@ class Geometry(object):
|
||||||
self.tools[tool]['solid_geometry'] = rotate_geom(self.tools[tool]['solid_geometry'])
|
self.tools[tool]['solid_geometry'] = rotate_geom(self.tools[tool]['solid_geometry'])
|
||||||
else:
|
else:
|
||||||
self.solid_geometry = rotate_geom(self.solid_geometry)
|
self.solid_geometry = rotate_geom(self.solid_geometry)
|
||||||
self.app.inform.emit('[success]Object was rotated ...')
|
self.app.inform.emit(_('[success]Object was rotated ...'))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Failed to rotate. No object selected")
|
self.app.inform.emit(_("[ERROR_NOTCL] Failed to rotate. No object selected"))
|
||||||
|
|
||||||
def skew(self, angle_x, angle_y, point):
|
def skew(self, angle_x, angle_y, point):
|
||||||
"""
|
"""
|
||||||
|
@ -1458,9 +1458,9 @@ class Geometry(object):
|
||||||
self.tools[tool]['solid_geometry'] = skew_geom(self.tools[tool]['solid_geometry'])
|
self.tools[tool]['solid_geometry'] = skew_geom(self.tools[tool]['solid_geometry'])
|
||||||
else:
|
else:
|
||||||
self.solid_geometry = skew_geom(self.solid_geometry)
|
self.solid_geometry = skew_geom(self.solid_geometry)
|
||||||
self.app.inform.emit('[success]Object was skewed ...')
|
self.app.inform.emit(_('[success]Object was skewed ...'))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Failed to skew. No object selected")
|
self.app.inform.emit(_("[ERROR_NOTCL] Failed to skew. No object selected"))
|
||||||
|
|
||||||
# if type(self.solid_geometry) == list:
|
# if type(self.solid_geometry) == list:
|
||||||
# self.solid_geometry = [affinity.skew(g, angle_x, angle_y, origin=(px, py))
|
# self.solid_geometry = [affinity.skew(g, angle_x, angle_y, origin=(px, py))
|
||||||
|
@ -2548,8 +2548,8 @@ class Gerber (Geometry):
|
||||||
else:
|
else:
|
||||||
if '0' not in self.apertures:
|
if '0' not in self.apertures:
|
||||||
self.apertures['0'] = {}
|
self.apertures['0'] = {}
|
||||||
self.apertures['0']['solid_geometry'] = []
|
|
||||||
self.apertures['0']['type'] = 'REG'
|
self.apertures['0']['type'] = 'REG'
|
||||||
|
self.apertures['0']['solid_geometry'] = []
|
||||||
used_aperture = '0'
|
used_aperture = '0'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -2611,7 +2611,7 @@ class Gerber (Geometry):
|
||||||
if path[-1] != [linear_x, linear_y]:
|
if path[-1] != [linear_x, linear_y]:
|
||||||
path.append([linear_x, linear_y])
|
path.append([linear_x, linear_y])
|
||||||
|
|
||||||
if making_region is False:
|
if making_region is False:
|
||||||
# if the aperture is rectangle then add a rectangular shape having as parameters the
|
# if the aperture is rectangle then add a rectangular shape having as parameters the
|
||||||
# coordinates of the start and end point and also the width and height
|
# coordinates of the start and end point and also the width and height
|
||||||
# of the 'R' aperture
|
# of the 'R' aperture
|
||||||
|
@ -2635,29 +2635,56 @@ class Gerber (Geometry):
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
last_path_aperture = current_aperture
|
last_path_aperture = current_aperture
|
||||||
|
# we do this for the case that a region is done without having defined any aperture
|
||||||
|
# Allegro does that
|
||||||
|
if last_path_aperture is None:
|
||||||
|
if '0' not in self.apertures:
|
||||||
|
self.apertures['0'] = {}
|
||||||
|
self.apertures['0']['type'] = 'REG'
|
||||||
|
self.apertures['0']['solid_geometry'] = []
|
||||||
|
last_path_aperture = '0'
|
||||||
else:
|
else:
|
||||||
self.app.inform.emit("[WARNING] Coordinates missing, line ignored: %s" % str(gline))
|
self.app.inform.emit(_("[WARNING] Coordinates missing, line ignored: %s") % str(gline))
|
||||||
self.app.inform.emit("[WARNING_NOTCL] GERBER file might be CORRUPT. Check the file !!!")
|
self.app.inform.emit(_("[WARNING_NOTCL] GERBER file might be CORRUPT. Check the file !!!"))
|
||||||
|
|
||||||
elif current_operation_code == 2:
|
elif current_operation_code == 2:
|
||||||
if len(path) > 1:
|
if len(path) > 1:
|
||||||
geo = None
|
geo = None
|
||||||
|
|
||||||
## --- BUFFERED ---
|
# --- BUFFERED ---
|
||||||
# this treats the case when we are storing geometry as paths only
|
# this treats the case when we are storing geometry as paths only
|
||||||
if making_region:
|
if making_region:
|
||||||
|
# we do this for the case that a region is done without having defined any aperture
|
||||||
|
# Allegro does that
|
||||||
|
if last_path_aperture is None:
|
||||||
|
if '0' not in self.apertures:
|
||||||
|
self.apertures['0'] = {}
|
||||||
|
self.apertures['0']['type'] = 'REG'
|
||||||
|
self.apertures['0']['solid_geometry'] = []
|
||||||
|
last_path_aperture = '0'
|
||||||
geo = Polygon()
|
geo = Polygon()
|
||||||
else:
|
else:
|
||||||
geo = LineString(path)
|
geo = LineString(path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.apertures[last_path_aperture]["type"] != 'R':
|
if self.apertures[last_path_aperture]["type"] != 'R':
|
||||||
if not geo.is_empty:
|
if not geo.is_empty:
|
||||||
follow_buffer.append(geo)
|
follow_buffer.append(geo)
|
||||||
except:
|
except Exception as e:
|
||||||
follow_buffer.append(geo)
|
log.debug("camlib.Gerber.parse_lines() --> %s" % str(e))
|
||||||
|
if not geo.is_empty:
|
||||||
|
follow_buffer.append(geo)
|
||||||
|
|
||||||
# this treats the case when we are storing geometry as solids
|
# this treats the case when we are storing geometry as solids
|
||||||
if making_region:
|
if making_region:
|
||||||
|
# we do this for the case that a region is done without having defined any aperture
|
||||||
|
# Allegro does that
|
||||||
|
if last_path_aperture is None:
|
||||||
|
if '0' not in self.apertures:
|
||||||
|
self.apertures['0'] = {}
|
||||||
|
self.apertures['0']['type'] = 'REG'
|
||||||
|
self.apertures['0']['solid_geometry'] = []
|
||||||
|
last_path_aperture = '0'
|
||||||
elem = [linear_x, linear_y]
|
elem = [linear_x, linear_y]
|
||||||
if elem != path[-1]:
|
if elem != path[-1]:
|
||||||
path.append([linear_x, linear_y])
|
path.append([linear_x, linear_y])
|
||||||
|
@ -2666,9 +2693,9 @@ class Gerber (Geometry):
|
||||||
geo = Polygon(path)
|
geo = Polygon(path)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
log.warning("Problem %s %s" % (gline, line_num))
|
log.warning("Problem %s %s" % (gline, line_num))
|
||||||
self.app.inform.emit("[ERROR] Region does not have enough points. "
|
self.app.inform.emit(_("[ERROR] Region does not have enough points. "
|
||||||
"File will be processed but there are parser errors. "
|
"File will be processed but there are parser errors. "
|
||||||
"Line number: %s" % str(line_num))
|
"Line number: %s") % str(line_num))
|
||||||
else:
|
else:
|
||||||
if last_path_aperture is None:
|
if last_path_aperture is None:
|
||||||
log.warning("No aperture defined for curent path. (%d)" % line_num)
|
log.warning("No aperture defined for curent path. (%d)" % line_num)
|
||||||
|
@ -2684,7 +2711,8 @@ class Gerber (Geometry):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.apertures[last_path_aperture]['solid_geometry'] = []
|
self.apertures[last_path_aperture]['solid_geometry'] = []
|
||||||
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
|
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
|
||||||
except:
|
except Exception as e:
|
||||||
|
log.debug("camlib.Gerber.parse_lines() --> %s" % str(e))
|
||||||
poly_buffer.append(geo)
|
poly_buffer.append(geo)
|
||||||
try:
|
try:
|
||||||
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
|
self.apertures[last_path_aperture]['solid_geometry'].append(geo)
|
||||||
|
@ -2696,8 +2724,8 @@ class Gerber (Geometry):
|
||||||
if linear_x is not None and linear_y is not None:
|
if linear_x is not None and linear_y is not None:
|
||||||
path = [[linear_x, linear_y]] # Start new path
|
path = [[linear_x, linear_y]] # Start new path
|
||||||
else:
|
else:
|
||||||
self.app.inform.emit("[WARNING] Coordinates missing, line ignored: %s" % str(gline))
|
self.app.inform.emit(_("[WARNING] Coordinates missing, line ignored: %s") % str(gline))
|
||||||
self.app.inform.emit("[WARNING_NOTCL] GERBER file might be CORRUPT. Check the file !!!")
|
self.app.inform.emit(_("[WARNING_NOTCL] GERBER file might be CORRUPT. Check the file !!!"))
|
||||||
|
|
||||||
# Flash
|
# Flash
|
||||||
# Not allowed in region mode.
|
# Not allowed in region mode.
|
||||||
|
@ -3020,7 +3048,7 @@ class Gerber (Geometry):
|
||||||
|
|
||||||
log.error("Gerber PARSING FAILED. Line %d: %s" % (line_num, gline))
|
log.error("Gerber PARSING FAILED. Line %d: %s" % (line_num, gline))
|
||||||
loc = 'Gerber Line #%d Gerber Line Content: %s\n' % (line_num, gline) + repr(err)
|
loc = 'Gerber Line #%d Gerber Line Content: %s\n' % (line_num, gline) + repr(err)
|
||||||
self.app.inform.emit("[ERROR]Gerber Parser ERROR.\n%s:" % loc)
|
self.app.inform.emit(_("[ERROR]Gerber Parser ERROR.\n%s:") % loc)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_flash_geometry(location, aperture, steps_per_circle=None):
|
def create_flash_geometry(location, aperture, steps_per_circle=None):
|
||||||
|
@ -3198,7 +3226,7 @@ class Gerber (Geometry):
|
||||||
try:
|
try:
|
||||||
xfactor = float(xfactor)
|
xfactor = float(xfactor)
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Scale factor has to be a number: integer or float.")
|
self.app.inform.emit(_("[ERROR_NOTCL] Scale factor has to be a number: integer or float."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if yfactor is None:
|
if yfactor is None:
|
||||||
|
@ -3207,7 +3235,7 @@ class Gerber (Geometry):
|
||||||
try:
|
try:
|
||||||
yfactor = float(yfactor)
|
yfactor = float(yfactor)
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Scale factor has to be a number: integer or float.")
|
self.app.inform.emit(_("[ERROR_NOTCL] Scale factor has to be a number: integer or float."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if point is None:
|
if point is None:
|
||||||
|
@ -3236,7 +3264,7 @@ class Gerber (Geometry):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug('FlatCAMGeometry.scale() --> %s' % str(e))
|
log.debug('FlatCAMGeometry.scale() --> %s' % str(e))
|
||||||
|
|
||||||
self.app.inform.emit("[success]Gerber Scale done.")
|
self.app.inform.emit(_("[success]Gerber Scale done."))
|
||||||
|
|
||||||
|
|
||||||
## solid_geometry ???
|
## solid_geometry ???
|
||||||
|
@ -3269,8 +3297,8 @@ class Gerber (Geometry):
|
||||||
try:
|
try:
|
||||||
dx, dy = vect
|
dx, dy = vect
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]An (x,y) pair of values are needed. "
|
self.app.inform.emit(_("[ERROR_NOTCL]An (x,y) pair of values are needed. "
|
||||||
"Probable you entered only one value in the Offset field.")
|
"Probable you entered only one value in the Offset field."))
|
||||||
return
|
return
|
||||||
|
|
||||||
def offset_geom(obj):
|
def offset_geom(obj):
|
||||||
|
@ -3293,7 +3321,7 @@ class Gerber (Geometry):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug('FlatCAMGeometry.offset() --> %s' % str(e))
|
log.debug('FlatCAMGeometry.offset() --> %s' % str(e))
|
||||||
|
|
||||||
self.app.inform.emit("[success]Gerber Offset done.")
|
self.app.inform.emit(_("[success]Gerber Offset done."))
|
||||||
|
|
||||||
def mirror(self, axis, point):
|
def mirror(self, axis, point):
|
||||||
"""
|
"""
|
||||||
|
@ -3669,7 +3697,7 @@ class Excellon(Geometry):
|
||||||
# and we need to exit from here
|
# and we need to exit from here
|
||||||
if self.detect_gcode_re.search(eline):
|
if self.detect_gcode_re.search(eline):
|
||||||
log.warning("This is GCODE mark: %s" % eline)
|
log.warning("This is GCODE mark: %s" % eline)
|
||||||
self.app.inform.emit('[ERROR_NOTCL] This is GCODE mark: %s' % eline)
|
self.app.inform.emit(_('[ERROR_NOTCL] This is GCODE mark: %s') % eline)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Header Begin (M48) #
|
# Header Begin (M48) #
|
||||||
|
@ -4198,8 +4226,8 @@ class Excellon(Geometry):
|
||||||
log.info("Zeros: %s, Units %s." % (self.zeros, self.units))
|
log.info("Zeros: %s, Units %s." % (self.zeros, self.units))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error("Excellon PARSING FAILED. Line %d: %s" % (line_num, eline))
|
log.error("Excellon PARSING FAILED. Line %d: %s" % (line_num, eline))
|
||||||
msg = "[ERROR_NOTCL] An internal error has ocurred. See shell.\n"
|
msg = _("[ERROR_NOTCL] An internal error has ocurred. See shell.\n")
|
||||||
msg += '[ERROR] Excellon Parser error.\nParsing Failed. Line %d: %s\n' % (line_num, eline)
|
msg += _('[ERROR] Excellon Parser error.\nParsing Failed. Line {l_nr}: {line}\n').format(l_nr=line_num, line=eline)
|
||||||
msg += traceback.format_exc()
|
msg += traceback.format_exc()
|
||||||
self.app.inform.emit(msg)
|
self.app.inform.emit(msg)
|
||||||
|
|
||||||
|
@ -4276,9 +4304,9 @@ class Excellon(Geometry):
|
||||||
for drill in self.drills:
|
for drill in self.drills:
|
||||||
# poly = drill['point'].buffer(self.tools[drill['tool']]["C"]/2.0)
|
# poly = drill['point'].buffer(self.tools[drill['tool']]["C"]/2.0)
|
||||||
if drill['tool'] is '':
|
if drill['tool'] is '':
|
||||||
self.app.inform.emit("[WARNING] Excellon.create_geometry() -> a drill location was skipped "
|
self.app.inform.emit(_("[WARNING] Excellon.create_geometry() -> a drill location was skipped "
|
||||||
"due of not having a tool associated.\n"
|
"due of not having a tool associated.\n"
|
||||||
"Check the resulting GCode.")
|
"Check the resulting GCode."))
|
||||||
log.debug("Excellon.create_geometry() -> a drill location was skipped "
|
log.debug("Excellon.create_geometry() -> a drill location was skipped "
|
||||||
"due of not having a tool associated")
|
"due of not having a tool associated")
|
||||||
continue
|
continue
|
||||||
|
@ -4812,7 +4840,7 @@ class CNCjob(Geometry):
|
||||||
try:
|
try:
|
||||||
value = getattr(self, command)
|
value = getattr(self, command)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit("[ERROR] There is no such parameter: %s" % str(match))
|
self.app.inform.emit(_("[ERROR] There is no such parameter: %s") % str(match))
|
||||||
log.debug("CNCJob.parse_custom_toolchange_code() --> AttributeError ")
|
log.debug("CNCJob.parse_custom_toolchange_code() --> AttributeError ")
|
||||||
return 'fail'
|
return 'fail'
|
||||||
text = text.replace(match, str(value))
|
text = text.replace(match, str(value))
|
||||||
|
@ -4877,15 +4905,15 @@ class CNCjob(Geometry):
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if drillz > 0:
|
if drillz > 0:
|
||||||
self.app.inform.emit("[WARNING] The Cut Z parameter has positive value. "
|
self.app.inform.emit(_("[WARNING] The Cut Z parameter has positive value. "
|
||||||
"It is the depth value to drill into material.\n"
|
"It is the depth value to drill into material.\n"
|
||||||
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
|
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
|
||||||
"therefore the app will convert the value to negative. "
|
"therefore the app will convert the value to negative. "
|
||||||
"Check the resulting CNC code (Gcode etc).")
|
"Check the resulting CNC code (Gcode etc)."))
|
||||||
self.z_cut = -drillz
|
self.z_cut = -drillz
|
||||||
elif drillz == 0:
|
elif drillz == 0:
|
||||||
self.app.inform.emit("[WARNING] The Cut Z parameter is zero. "
|
self.app.inform.emit(_("[WARNING] The Cut Z parameter is zero. "
|
||||||
"There will be no cut, skipping %s file" % exobj.options['name'])
|
"There will be no cut, skipping %s file") % exobj.options['name'])
|
||||||
return 'fail'
|
return 'fail'
|
||||||
else:
|
else:
|
||||||
self.z_cut = drillz
|
self.z_cut = drillz
|
||||||
|
@ -4898,8 +4926,8 @@ class CNCjob(Geometry):
|
||||||
else:
|
else:
|
||||||
self.xy_toolchange = [float(eval(a)) for a in toolchangexy.split(",")]
|
self.xy_toolchange = [float(eval(a)) for a in toolchangexy.split(",")]
|
||||||
if len(self.xy_toolchange) < 2:
|
if len(self.xy_toolchange) < 2:
|
||||||
self.app.inform.emit("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
|
self.app.inform.emit(_("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
|
||||||
"in the format (x, y) \nbut now there is only one value, not two. ")
|
"in the format (x, y) \nbut now there is only one value, not two. "))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> %s" % str(e))
|
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> %s" % str(e))
|
||||||
|
@ -5100,7 +5128,7 @@ class CNCjob(Geometry):
|
||||||
else:
|
else:
|
||||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
||||||
"The loaded Excellon file has no drills ...")
|
"The loaded Excellon file has no drills ...")
|
||||||
self.app.inform.emit('[ERROR_NOTCL]The loaded Excellon file has no drills ...')
|
self.app.inform.emit(_('[ERROR_NOTCL]The loaded Excellon file has no drills ...'))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
log.debug("The total travel distance with OR-TOOLS Metaheuristics is: %s" % str(measured_distance))
|
log.debug("The total travel distance with OR-TOOLS Metaheuristics is: %s" % str(measured_distance))
|
||||||
|
@ -5172,7 +5200,12 @@ class CNCjob(Geometry):
|
||||||
else:
|
else:
|
||||||
current_tooldia = float('%.3f' % float(exobj.tools[tool]["C"]))
|
current_tooldia = float('%.3f' % float(exobj.tools[tool]["C"]))
|
||||||
|
|
||||||
z_offset = float(self.tool_offset[current_tooldia]) * (-1)
|
# TODO apply offset only when using the GUI, for TclCommand this will create an error
|
||||||
|
# because the values for Z offset are created in build_ui()
|
||||||
|
try:
|
||||||
|
z_offset = float(self.tool_offset[current_tooldia]) * (-1)
|
||||||
|
except KeyError:
|
||||||
|
z_offset = 0
|
||||||
self.z_cut += z_offset
|
self.z_cut += z_offset
|
||||||
|
|
||||||
# Drillling!
|
# Drillling!
|
||||||
|
@ -5190,12 +5223,12 @@ class CNCjob(Geometry):
|
||||||
else:
|
else:
|
||||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
||||||
"The loaded Excellon file has no drills ...")
|
"The loaded Excellon file has no drills ...")
|
||||||
self.app.inform.emit('[ERROR_NOTCL]The loaded Excellon file has no drills ...')
|
self.app.inform.emit(_('[ERROR_NOTCL]The loaded Excellon file has no drills ...'))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" % str(measured_distance))
|
log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" % str(measured_distance))
|
||||||
else:
|
else:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Wrong optimization type selected.")
|
self.app.inform.emit(_("[ERROR_NOTCL] Wrong optimization type selected."))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
else:
|
else:
|
||||||
log.debug("Using Travelling Salesman drill path optimization.")
|
log.debug("Using Travelling Salesman drill path optimization.")
|
||||||
|
@ -5241,7 +5274,7 @@ class CNCjob(Geometry):
|
||||||
else:
|
else:
|
||||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
||||||
"The loaded Excellon file has no drills ...")
|
"The loaded Excellon file has no drills ...")
|
||||||
self.app.inform.emit('[ERROR_NOTCL]The loaded Excellon file has no drills ...')
|
self.app.inform.emit(_('[ERROR_NOTCL]The loaded Excellon file has no drills ...'))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
log.debug("The total travel distance with Travelling Salesman Algorithm is: %s" % str(measured_distance))
|
log.debug("The total travel distance with Travelling Salesman Algorithm is: %s" % str(measured_distance))
|
||||||
|
|
||||||
|
@ -5329,8 +5362,8 @@ class CNCjob(Geometry):
|
||||||
else:
|
else:
|
||||||
self.xy_toolchange = [float(eval(a)) for a in toolchangexy.split(",")]
|
self.xy_toolchange = [float(eval(a)) for a in toolchangexy.split(",")]
|
||||||
if len(self.xy_toolchange) < 2:
|
if len(self.xy_toolchange) < 2:
|
||||||
self.app.inform.emit("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
|
self.app.inform.emit(_("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
|
||||||
"in the format (x, y) \nbut now there is only one value, not two. ")
|
"in the format (x, y) \nbut now there is only one value, not two. "))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("camlib.CNCJob.generate_from_multitool_geometry() --> %s" % str(e))
|
log.debug("camlib.CNCJob.generate_from_multitool_geometry() --> %s" % str(e))
|
||||||
|
@ -5339,16 +5372,38 @@ class CNCjob(Geometry):
|
||||||
self.pp_geometry_name = pp_geometry_name if pp_geometry_name else 'default'
|
self.pp_geometry_name = pp_geometry_name if pp_geometry_name else 'default'
|
||||||
self.f_plunge = self.app.defaults["geometry_f_plunge"]
|
self.f_plunge = self.app.defaults["geometry_f_plunge"]
|
||||||
|
|
||||||
|
if self.z_cut is None:
|
||||||
|
self.app.inform.emit(_("[ERROR_NOTCL] Cut_Z parameter is None or zero. Most likely a bad combinations of "
|
||||||
|
"other parameters."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
if self.z_cut > 0:
|
if self.z_cut > 0:
|
||||||
self.app.inform.emit("[WARNING] The Cut Z parameter has positive value. "
|
self.app.inform.emit(_("[WARNING] The Cut Z parameter has positive value. "
|
||||||
"It is the depth value to cut into material.\n"
|
"It is the depth value to cut into material.\n"
|
||||||
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
|
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
|
||||||
"therefore the app will convert the value to negative."
|
"therefore the app will convert the value to negative."
|
||||||
"Check the resulting CNC code (Gcode etc).")
|
"Check the resulting CNC code (Gcode etc)."))
|
||||||
self.z_cut = -self.z_cut
|
self.z_cut = -self.z_cut
|
||||||
elif self.z_cut == 0:
|
elif self.z_cut == 0:
|
||||||
self.app.inform.emit("[WARNING] The Cut Z parameter is zero. "
|
self.app.inform.emit(_("[WARNING] The Cut Z parameter is zero. "
|
||||||
"There will be no cut, skipping %s file" % self.options['name'])
|
"There will be no cut, skipping %s file") % self.options['name'])
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
if self.z_move is None:
|
||||||
|
self.app.inform.emit(_("[ERROR_NOTCL] Travel Z parameter is None or zero."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
if self.z_move < 0:
|
||||||
|
self.app.inform.emit(_("[WARNING] The Travel Z parameter has negative value. "
|
||||||
|
"It is the height value to travel between cuts.\n"
|
||||||
|
"The Z Travel parameter needs to have a positive value, assuming it is a typo "
|
||||||
|
"therefore the app will convert the value to positive."
|
||||||
|
"Check the resulting CNC code (Gcode etc)."))
|
||||||
|
self.z_move = -self.z_move
|
||||||
|
elif self.z_move == 0:
|
||||||
|
self.app.inform.emit(_("[WARNING] The Z Travel parameter is zero. "
|
||||||
|
"This is dangerous, skipping %s file") % self.options['name'])
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
## Index first and last points in paths
|
## Index first and last points in paths
|
||||||
# What points to index.
|
# What points to index.
|
||||||
|
@ -5476,14 +5531,14 @@ class CNCjob(Geometry):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(geometry, Geometry):
|
if not isinstance(geometry, Geometry):
|
||||||
self.app.inform.emit("[ERROR]Expected a Geometry, got %s" % type(geometry))
|
self.app.inform.emit(_("[ERROR]Expected a Geometry, got %s") % type(geometry))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
log.debug("Generate_from_geometry_2()")
|
log.debug("Generate_from_geometry_2()")
|
||||||
|
|
||||||
# if solid_geometry is empty raise an exception
|
# if solid_geometry is empty raise an exception
|
||||||
if not geometry.solid_geometry:
|
if not geometry.solid_geometry:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Trying to generate a CNC Job "
|
self.app.inform.emit(_("[ERROR_NOTCL]Trying to generate a CNC Job "
|
||||||
"from a Geometry object without solid_geometry.")
|
"from a Geometry object without solid_geometry."))
|
||||||
|
|
||||||
temp_solid_geometry = []
|
temp_solid_geometry = []
|
||||||
|
|
||||||
|
@ -5521,9 +5576,9 @@ class CNCjob(Geometry):
|
||||||
# if the offset is less than half of the total length or less than half of the total width of the
|
# if the offset is less than half of the total length or less than half of the total width of the
|
||||||
# solid geometry it's obvious we can't do the offset
|
# solid geometry it's obvious we can't do the offset
|
||||||
if -offset > ((c - a) / 2) or -offset > ((d - b) / 2):
|
if -offset > ((c - a) / 2) or -offset > ((d - b) / 2):
|
||||||
self.app.inform.emit("[ERROR_NOTCL]The Tool Offset value is too negative to use "
|
self.app.inform.emit(_("[ERROR_NOTCL]The Tool Offset value is too negative to use "
|
||||||
"for the current_geometry.\n"
|
"for the current_geometry.\n"
|
||||||
"Raise the value (in module) and try again.")
|
"Raise the value (in module) and try again."))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
# hack: make offset smaller by 0.0000000001 which is insignificant difference but allow the job
|
# hack: make offset smaller by 0.0000000001 which is insignificant difference but allow the job
|
||||||
# to continue
|
# to continue
|
||||||
|
@ -5578,8 +5633,8 @@ class CNCjob(Geometry):
|
||||||
else:
|
else:
|
||||||
self.xy_toolchange = [float(eval(a)) for a in toolchangexy.split(",")]
|
self.xy_toolchange = [float(eval(a)) for a in toolchangexy.split(",")]
|
||||||
if len(self.xy_toolchange) < 2:
|
if len(self.xy_toolchange) < 2:
|
||||||
self.app.inform.emit("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
|
self.app.inform.emit(_("[ERROR]The Toolchange X,Y field in Edit -> Preferences has to be "
|
||||||
"in the format (x, y) \nbut now there is only one value, not two. ")
|
"in the format (x, y) \nbut now there is only one value, not two. "))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("camlib.CNCJob.generate_from_geometry_2() --> %s" % str(e))
|
log.debug("camlib.CNCJob.generate_from_geometry_2() --> %s" % str(e))
|
||||||
|
@ -5588,16 +5643,38 @@ class CNCjob(Geometry):
|
||||||
self.pp_geometry_name = pp_geometry_name if pp_geometry_name else 'default'
|
self.pp_geometry_name = pp_geometry_name if pp_geometry_name else 'default'
|
||||||
self.f_plunge = self.app.defaults["geometry_f_plunge"]
|
self.f_plunge = self.app.defaults["geometry_f_plunge"]
|
||||||
|
|
||||||
|
if self.z_cut is None:
|
||||||
|
self.app.inform.emit(_("[ERROR_NOTCL] Cut_Z parameter is None or zero. Most likely a bad combinations of "
|
||||||
|
"other parameters."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
if self.z_cut > 0:
|
if self.z_cut > 0:
|
||||||
self.app.inform.emit("[WARNING] The Cut Z parameter has positive value. "
|
self.app.inform.emit(_("[WARNING] The Cut Z parameter has positive value. "
|
||||||
"It is the depth value to cut into material.\n"
|
"It is the depth value to cut into material.\n"
|
||||||
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
|
"The Cut Z parameter needs to have a negative value, assuming it is a typo "
|
||||||
"therefore the app will convert the value to negative."
|
"therefore the app will convert the value to negative."
|
||||||
"Check the resulting CNC code (Gcode etc).")
|
"Check the resulting CNC code (Gcode etc)."))
|
||||||
self.z_cut = -self.z_cut
|
self.z_cut = -self.z_cut
|
||||||
elif self.z_cut == 0:
|
elif self.z_cut == 0:
|
||||||
self.app.inform.emit("[WARNING] The Cut Z parameter is zero. "
|
self.app.inform.emit(_("[WARNING] The Cut Z parameter is zero. "
|
||||||
"There will be no cut, skipping %s file" % geometry.options['name'])
|
"There will be no cut, skipping %s file") % geometry.options['name'])
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
if self.z_move is None:
|
||||||
|
self.app.inform.emit(_("[ERROR_NOTCL] Travel Z parameter is None or zero."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
if self.z_move < 0:
|
||||||
|
self.app.inform.emit(_("[WARNING] The Travel Z parameter has negative value. "
|
||||||
|
"It is the height value to travel between cuts.\n"
|
||||||
|
"The Z Travel parameter needs to have a positive value, assuming it is a typo "
|
||||||
|
"therefore the app will convert the value to positive."
|
||||||
|
"Check the resulting CNC code (Gcode etc)."))
|
||||||
|
self.z_move = -self.z_move
|
||||||
|
elif self.z_move == 0:
|
||||||
|
self.app.inform.emit(_("[WARNING] The Z Travel parameter is zero. "
|
||||||
|
"This is dangerous, skipping %s file") % self.options['name'])
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
## Index first and last points in paths
|
## Index first and last points in paths
|
||||||
# What points to index.
|
# What points to index.
|
||||||
|
@ -5721,7 +5798,7 @@ class CNCjob(Geometry):
|
||||||
|
|
||||||
if not kwargs:
|
if not kwargs:
|
||||||
log.debug("camlib.generate_from_solderpaste_geo() --> No tool in the solderpaste geometry.")
|
log.debug("camlib.generate_from_solderpaste_geo() --> No tool in the solderpaste geometry.")
|
||||||
self.app.inform.emit("[ERROR_NOTCL] There is no tool data in the SolderPaste geometry.")
|
self.app.inform.emit(_("[ERROR_NOTCL] There is no tool data in the SolderPaste geometry."))
|
||||||
|
|
||||||
|
|
||||||
# this is the tool diameter, it is used as such to accommodate the postprocessor who need the tool diameter
|
# this is the tool diameter, it is used as such to accommodate the postprocessor who need the tool diameter
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,16 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# Author: Juan Pablo Caram (c) #
|
||||||
|
# Date: 2/5/2014 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
# File Modified (major mod): Marius Adrian Stanciu #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
from PyQt5 import QtGui, QtCore, QtWidgets
|
||||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import QTextEdit, QCompleter, QAction
|
from PyQt5.QtWidgets import QTextEdit, QCompleter, QAction
|
File diff suppressed because it is too large
Load Diff
|
@ -9,12 +9,11 @@
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from VisPyCanvas import VisPyCanvas
|
from flatcamGUI.VisPyCanvas import VisPyCanvas, time
|
||||||
from VisPyVisuals import ShapeGroup, ShapeCollection, TextCollection, TextGroup, Cursor
|
from flatcamGUI.VisPyVisuals import ShapeGroup, ShapeCollection, TextCollection, TextGroup, Cursor
|
||||||
from vispy.scene.visuals import InfiniteLine, Line
|
from vispy.scene.visuals import InfiniteLine, Line
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from vispy.geometry import Rect
|
from vispy.geometry import Rect
|
||||||
import time
|
|
||||||
|
|
||||||
log = logging.getLogger('base')
|
log = logging.getLogger('base')
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Dennis Hayrullin #
|
||||||
|
# Date: 2/5/2016 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from PyQt5.QtGui import QPalette
|
from PyQt5.QtGui import QPalette
|
||||||
import vispy.scene as scene
|
import vispy.scene as scene
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Dennis Hayrullin #
|
||||||
|
# Date: 2/5/2016 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from vispy.visuals import markers, LineVisual, InfiniteLineVisual
|
from vispy.visuals import markers, LineVisual, InfiniteLineVisual
|
||||||
from vispy.visuals.axis import Ticker, _get_ticks_talbot
|
from vispy.visuals.axis import Ticker, _get_ticks_talbot
|
||||||
from vispy.scene.widgets import Grid
|
from vispy.scene.widgets import Grid
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Dennis Hayrullin #
|
||||||
|
# Date: 2/5/2016 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from OpenGL import GLU
|
from OpenGL import GLU
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Dennis Hayrullin #
|
||||||
|
# Date: 2/5/2016 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from vispy.visuals import CompoundVisual, LineVisual, MeshVisual, TextVisual, MarkersVisual
|
from vispy.visuals import CompoundVisual, LineVisual, MeshVisual, TextVisual, MarkersVisual
|
||||||
from vispy.scene.visuals import VisualNode, generate_docstring, visuals
|
from vispy.scene.visuals import VisualNode, generate_docstring, visuals
|
||||||
from vispy.gloo import set_state
|
from vispy.gloo import set_state
|
||||||
|
@ -5,7 +13,7 @@ from vispy.color import Color
|
||||||
from shapely.geometry import Polygon, LineString, LinearRing
|
from shapely.geometry import Polygon, LineString, LinearRing
|
||||||
import threading
|
import threading
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from VisPyTesselators import GLUTess
|
from flatcamGUI.VisPyTesselators import GLUTess
|
||||||
|
|
||||||
|
|
||||||
class FlatCAMLineVisual(LineVisual):
|
class FlatCAMLineVisual(LineVisual):
|
|
@ -1,18 +1,18 @@
|
||||||
import re
|
############################################################
|
||||||
import itertools
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
import math
|
# http://flatcam.org #
|
||||||
import ezdxf
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from shapely.geometry import LinearRing, LineString, Point, Polygon
|
from shapely.geometry import LineString
|
||||||
from shapely.affinity import translate, rotate, scale, skew, affine_transform
|
|
||||||
import numpy
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
log = logging.getLogger('base2')
|
log = logging.getLogger('base2')
|
||||||
import FlatCAMApp
|
|
||||||
|
|
||||||
from ParseFont import *
|
from flatcamParsers.ParseFont import *
|
||||||
from ParseDXF_Spline import *
|
from flatcamParsers.ParseDXF_Spline import *
|
||||||
|
|
||||||
|
|
||||||
def distance(pt1, pt2):
|
def distance(pt1, pt2):
|
|
@ -2,6 +2,13 @@
|
||||||
# Vasilis Vlachoudis
|
# Vasilis Vlachoudis
|
||||||
# Date: 20-Oct-2015
|
# Date: 20-Oct-2015
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File modified: Marius Adrian Stanciu #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
############################################################
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
#########################################################################
|
#########################################################################
|
||||||
### Borrowed code from 'https://github.com/gddc/ttfquery/blob/master/ ###
|
### Borrowed code from 'https://github.com/gddc/ttfquery/blob/master/ ###
|
||||||
### and made it work with Python 3 #############
|
### and made it work with Python 3 #############
|
|
@ -20,17 +20,13 @@
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
# import xml.etree.ElementTree as ET
|
# import xml.etree.ElementTree as ET
|
||||||
from lxml import etree as ET
|
from svg.path import Line, Arc, CubicBezier, QuadraticBezier, parse_path
|
||||||
import re
|
|
||||||
import itertools
|
|
||||||
from svg.path import Path, Line, Arc, CubicBezier, QuadraticBezier, parse_path
|
|
||||||
from svg.path.path import Move
|
from svg.path.path import Move
|
||||||
from shapely.geometry import LinearRing, LineString, Point, Polygon
|
from shapely.geometry import LineString
|
||||||
from shapely.affinity import translate, rotate, scale, skew, affine_transform
|
from shapely.affinity import skew, affine_transform
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import logging
|
|
||||||
|
|
||||||
from ParseFont import *
|
from flatcamParsers.ParseFont import *
|
||||||
|
|
||||||
log = logging.getLogger('base2')
|
log = logging.getLogger('base2')
|
||||||
|
|
|
@ -1,16 +1,30 @@
|
||||||
from PyQt5 import QtGui
|
############################################################
|
||||||
from GUIElements import FCEntry
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from FlatCAMObj import *
|
from FlatCAMObj import *
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class ToolCalculator(FlatCAMTool):
|
class ToolCalculator(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "Calculators"
|
toolName = _("Calculators")
|
||||||
v_shapeName = "V-Shape Tool Calculator"
|
v_shapeName = _("V-Shape Tool Calculator")
|
||||||
unitsName = "Units Calculator"
|
unitsName = _("Units Calculator")
|
||||||
eplateName = "ElectroPlating Calculator"
|
eplateName = _("ElectroPlating Calculator")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
FlatCAMTool.__init__(self, app)
|
FlatCAMTool.__init__(self, app)
|
||||||
|
@ -51,12 +65,12 @@ class ToolCalculator(FlatCAMTool):
|
||||||
self.inch_entry = FCEntry()
|
self.inch_entry = FCEntry()
|
||||||
# self.inch_entry.setFixedWidth(70)
|
# self.inch_entry.setFixedWidth(70)
|
||||||
self.inch_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.inch_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.inch_entry.setToolTip("Here you enter the value to be converted from INCH to MM")
|
self.inch_entry.setToolTip(_("Here you enter the value to be converted from INCH to MM"))
|
||||||
|
|
||||||
self.mm_entry = FCEntry()
|
self.mm_entry = FCEntry()
|
||||||
# self.mm_entry.setFixedWidth(130)
|
# self.mm_entry.setFixedWidth(130)
|
||||||
self.mm_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.mm_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.mm_entry.setToolTip("Here you enter the value to be converted from MM to INCH")
|
self.mm_entry.setToolTip(_("Here you enter the value to be converted from MM to INCH"))
|
||||||
|
|
||||||
grid_units_layout.addWidget(self.mm_entry, 1, 0)
|
grid_units_layout.addWidget(self.mm_entry, 1, 0)
|
||||||
grid_units_layout.addWidget(self.inch_entry, 1, 1)
|
grid_units_layout.addWidget(self.inch_entry, 1, 1)
|
||||||
|
@ -77,34 +91,34 @@ class ToolCalculator(FlatCAMTool):
|
||||||
form_layout = QtWidgets.QFormLayout()
|
form_layout = QtWidgets.QFormLayout()
|
||||||
self.layout.addLayout(form_layout)
|
self.layout.addLayout(form_layout)
|
||||||
|
|
||||||
self.tipDia_label = QtWidgets.QLabel("Tip Diameter:")
|
self.tipDia_label = QtWidgets.QLabel(_("Tip Diameter:"))
|
||||||
self.tipDia_entry = FCEntry()
|
self.tipDia_entry = FCEntry()
|
||||||
# self.tipDia_entry.setFixedWidth(70)
|
# self.tipDia_entry.setFixedWidth(70)
|
||||||
self.tipDia_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.tipDia_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.tipDia_label.setToolTip('This is the diameter of the tool tip.\n'
|
self.tipDia_label.setToolTip(_('This is the diameter of the tool tip.\n'
|
||||||
'The manufacturer specifies it.')
|
'The manufacturer specifies it.'))
|
||||||
|
|
||||||
self.tipAngle_label = QtWidgets.QLabel("Tip Angle:")
|
self.tipAngle_label = QtWidgets.QLabel(_("Tip Angle:"))
|
||||||
self.tipAngle_entry = FCEntry()
|
self.tipAngle_entry = FCEntry()
|
||||||
# self.tipAngle_entry.setFixedWidth(70)
|
# self.tipAngle_entry.setFixedWidth(70)
|
||||||
self.tipAngle_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.tipAngle_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.tipAngle_label.setToolTip("This is the angle of the tip of the tool.\n"
|
self.tipAngle_label.setToolTip(_("This is the angle of the tip of the tool.\n"
|
||||||
"It is specified by manufacturer.")
|
"It is specified by manufacturer."))
|
||||||
|
|
||||||
self.cutDepth_label = QtWidgets.QLabel("Cut Z:")
|
self.cutDepth_label = QtWidgets.QLabel(_("Cut Z:"))
|
||||||
self.cutDepth_entry = FCEntry()
|
self.cutDepth_entry = FCEntry()
|
||||||
# self.cutDepth_entry.setFixedWidth(70)
|
# self.cutDepth_entry.setFixedWidth(70)
|
||||||
self.cutDepth_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.cutDepth_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.cutDepth_label.setToolTip("This is the depth to cut into the material.\n"
|
self.cutDepth_label.setToolTip(_("This is the depth to cut into the material.\n"
|
||||||
"In the CNCJob is the CutZ parameter.")
|
"In the CNCJob is the CutZ parameter."))
|
||||||
|
|
||||||
self.effectiveToolDia_label = QtWidgets.QLabel("Tool Diameter:")
|
self.effectiveToolDia_label = QtWidgets.QLabel(_("Tool Diameter:"))
|
||||||
self.effectiveToolDia_entry = FCEntry()
|
self.effectiveToolDia_entry = FCEntry()
|
||||||
# self.effectiveToolDia_entry.setFixedWidth(70)
|
# self.effectiveToolDia_entry.setFixedWidth(70)
|
||||||
self.effectiveToolDia_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.effectiveToolDia_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.effectiveToolDia_label.setToolTip("This is the tool diameter to be entered into\n"
|
self.effectiveToolDia_label.setToolTip(_("This is the tool diameter to be entered into\n"
|
||||||
"FlatCAM Gerber section.\n"
|
"FlatCAM Gerber section.\n"
|
||||||
"In the CNCJob section it is called >Tool dia<.")
|
"In the CNCJob section it is called >Tool dia<."))
|
||||||
# self.effectiveToolDia_entry.setEnabled(False)
|
# self.effectiveToolDia_entry.setEnabled(False)
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,11 +128,11 @@ class ToolCalculator(FlatCAMTool):
|
||||||
form_layout.addRow(self.effectiveToolDia_label, self.effectiveToolDia_entry)
|
form_layout.addRow(self.effectiveToolDia_label, self.effectiveToolDia_entry)
|
||||||
|
|
||||||
## Buttons
|
## Buttons
|
||||||
self.calculate_vshape_button = QtWidgets.QPushButton("Calculate")
|
self.calculate_vshape_button = QtWidgets.QPushButton(_("Calculate"))
|
||||||
# self.calculate_button.setFixedWidth(70)
|
# self.calculate_button.setFixedWidth(70)
|
||||||
self.calculate_vshape_button.setToolTip(
|
self.calculate_vshape_button.setToolTip(
|
||||||
"Calculate either the Cut Z or the effective tool diameter,\n "
|
_("Calculate either the Cut Z or the effective tool diameter,\n "
|
||||||
"depending on which is desired and which is known. "
|
"depending on which is desired and which is known. ")
|
||||||
)
|
)
|
||||||
self.empty_label = QtWidgets.QLabel(" ")
|
self.empty_label = QtWidgets.QLabel(" ")
|
||||||
|
|
||||||
|
@ -135,8 +149,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
## Title of the ElectroPlating Tools Calculator
|
## Title of the ElectroPlating Tools Calculator
|
||||||
plate_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.eplateName)
|
plate_title_label = QtWidgets.QLabel("<font size=3><b>%s</b></font>" % self.eplateName)
|
||||||
plate_title_label.setToolTip(
|
plate_title_label.setToolTip(
|
||||||
"This calculator is useful for those who plate the via/pad/drill holes,\n"
|
_("This calculator is useful for those who plate the via/pad/drill holes,\n"
|
||||||
"using a method like grahite ink or calcium hypophosphite ink or palladium chloride."
|
"using a method like grahite ink or calcium hypophosphite ink or palladium chloride.")
|
||||||
)
|
)
|
||||||
self.layout.addWidget(plate_title_label)
|
self.layout.addWidget(plate_title_label)
|
||||||
|
|
||||||
|
@ -144,49 +158,49 @@ class ToolCalculator(FlatCAMTool):
|
||||||
plate_form_layout = QtWidgets.QFormLayout()
|
plate_form_layout = QtWidgets.QFormLayout()
|
||||||
self.layout.addLayout(plate_form_layout)
|
self.layout.addLayout(plate_form_layout)
|
||||||
|
|
||||||
self.pcblengthlabel = QtWidgets.QLabel("Board Length:")
|
self.pcblengthlabel = QtWidgets.QLabel(_("Board Length:"))
|
||||||
self.pcblength_entry = FCEntry()
|
self.pcblength_entry = FCEntry()
|
||||||
# self.pcblengthlabel.setFixedWidth(70)
|
# self.pcblengthlabel.setFixedWidth(70)
|
||||||
self.pcblength_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.pcblength_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.pcblengthlabel.setToolTip('This is the board length. In centimeters.')
|
self.pcblengthlabel.setToolTip(_('This is the board length. In centimeters.'))
|
||||||
|
|
||||||
self.pcbwidthlabel = QtWidgets.QLabel("Board Width:")
|
self.pcbwidthlabel = QtWidgets.QLabel(_("Board Width:"))
|
||||||
self.pcbwidth_entry = FCEntry()
|
self.pcbwidth_entry = FCEntry()
|
||||||
# self.pcbwidthlabel.setFixedWidth(70)
|
# self.pcbwidthlabel.setFixedWidth(70)
|
||||||
self.pcbwidth_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.pcbwidth_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.pcbwidthlabel.setToolTip('This is the board width.In centimeters.')
|
self.pcbwidthlabel.setToolTip(_('This is the board width.In centimeters.'))
|
||||||
|
|
||||||
self.cdensity_label = QtWidgets.QLabel("Current Density:")
|
self.cdensity_label = QtWidgets.QLabel(_("Current Density:"))
|
||||||
self.cdensity_entry = FCEntry()
|
self.cdensity_entry = FCEntry()
|
||||||
# self.cdensity_entry.setFixedWidth(70)
|
# self.cdensity_entry.setFixedWidth(70)
|
||||||
self.cdensity_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.cdensity_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.cdensity_label.setToolTip("Current density to pass through the board. \n"
|
self.cdensity_label.setToolTip(_("Current density to pass through the board. \n"
|
||||||
"In Amps per Square Feet ASF.")
|
"In Amps per Square Feet ASF."))
|
||||||
|
|
||||||
|
|
||||||
self.growth_label = QtWidgets.QLabel("Copper Growth:")
|
self.growth_label = QtWidgets.QLabel(_("Copper Growth:"))
|
||||||
self.growth_entry = FCEntry()
|
self.growth_entry = FCEntry()
|
||||||
# self.growth_entry.setFixedWidth(70)
|
# self.growth_entry.setFixedWidth(70)
|
||||||
self.growth_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.growth_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.growth_label.setToolTip("How thick the copper growth is intended to be.\n"
|
self.growth_label.setToolTip(_("How thick the copper growth is intended to be.\n"
|
||||||
"In microns.")
|
"In microns."))
|
||||||
|
|
||||||
# self.growth_entry.setEnabled(False)
|
# self.growth_entry.setEnabled(False)
|
||||||
|
|
||||||
self.cvaluelabel = QtWidgets.QLabel("Current Value:")
|
self.cvaluelabel = QtWidgets.QLabel(_("Current Value:"))
|
||||||
self.cvalue_entry = FCEntry()
|
self.cvalue_entry = FCEntry()
|
||||||
# self.cvaluelabel.setFixedWidth(70)
|
# self.cvaluelabel.setFixedWidth(70)
|
||||||
self.cvalue_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.cvalue_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.cvaluelabel.setToolTip('This is the current intensity value\n'
|
self.cvaluelabel.setToolTip(_('This is the current intensity value\n'
|
||||||
'to be set on the Power Supply. In Amps.')
|
'to be set on the Power Supply. In Amps.'))
|
||||||
self.cvalue_entry.setDisabled(True)
|
self.cvalue_entry.setDisabled(True)
|
||||||
|
|
||||||
self.timelabel = QtWidgets.QLabel("Time:")
|
self.timelabel = QtWidgets.QLabel(_("Time:"))
|
||||||
self.time_entry = FCEntry()
|
self.time_entry = FCEntry()
|
||||||
# self.timelabel.setFixedWidth(70)
|
# self.timelabel.setFixedWidth(70)
|
||||||
self.time_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.time_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.timelabel.setToolTip('This is the calculated time required for the procedure.\n'
|
self.timelabel.setToolTip(_('This is the calculated time required for the procedure.\n'
|
||||||
'In minutes.')
|
'In minutes.'))
|
||||||
self.time_entry.setDisabled(True)
|
self.time_entry.setDisabled(True)
|
||||||
|
|
||||||
plate_form_layout.addRow(self.pcblengthlabel, self.pcblength_entry)
|
plate_form_layout.addRow(self.pcblengthlabel, self.pcblength_entry)
|
||||||
|
@ -197,11 +211,11 @@ class ToolCalculator(FlatCAMTool):
|
||||||
plate_form_layout.addRow(self.timelabel, self.time_entry)
|
plate_form_layout.addRow(self.timelabel, self.time_entry)
|
||||||
|
|
||||||
## Buttons
|
## Buttons
|
||||||
self.calculate_plate_button = QtWidgets.QPushButton("Calculate")
|
self.calculate_plate_button = QtWidgets.QPushButton(_("Calculate"))
|
||||||
# self.calculate_button.setFixedWidth(70)
|
# self.calculate_button.setFixedWidth(70)
|
||||||
self.calculate_plate_button.setToolTip(
|
self.calculate_plate_button.setToolTip(
|
||||||
"Calculate the current intensity value and the procedure time,\n "
|
_("Calculate the current intensity value and the procedure time,\n "
|
||||||
"depending on the parameters above"
|
"depending on the parameters above")
|
||||||
)
|
)
|
||||||
self.empty_label_2 = QtWidgets.QLabel(" ")
|
self.empty_label_2 = QtWidgets.QLabel(" ")
|
||||||
|
|
||||||
|
@ -221,21 +235,25 @@ class ToolCalculator(FlatCAMTool):
|
||||||
|
|
||||||
self.calculate_plate_button.clicked.connect(self.on_calculate_eplate)
|
self.calculate_plate_button.clicked.connect(self.on_calculate_eplate)
|
||||||
|
|
||||||
|
def run(self, toggle=True):
|
||||||
def run(self):
|
|
||||||
self.app.report_usage("ToolCalculators()")
|
self.app.report_usage("ToolCalculators()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
|
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
|
||||||
self.app.ui.notebook.setTabText(2, "Calc. Tool")
|
self.app.ui.notebook.setTabText(2, "Calc. Tool")
|
||||||
|
@ -286,8 +304,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
tip_diameter = float(self.tipDia_entry.get_value().replace(',', '.'))
|
tip_diameter = float(self.tipDia_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -297,8 +315,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
half_tip_angle = float(self.tipAngle_entry.get_value().replace(',', '.'))
|
half_tip_angle = float(self.tipAngle_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
half_tip_angle /= 2
|
half_tip_angle /= 2
|
||||||
|
|
||||||
|
@ -309,8 +327,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
cut_depth = float(self.cutDepth_entry.get_value().replace(',', '.'))
|
cut_depth = float(self.cutDepth_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
tool_diameter = tip_diameter + (2 * cut_depth * math.tan(math.radians(half_tip_angle)))
|
tool_diameter = tip_diameter + (2 * cut_depth * math.tan(math.radians(half_tip_angle)))
|
||||||
|
@ -324,8 +342,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
mm_val = float(self.mm_entry.get_value().replace(',', '.'))
|
mm_val = float(self.mm_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
self.inch_entry.set_value('%.6f' % (mm_val / 25.4))
|
self.inch_entry.set_value('%.6f' % (mm_val / 25.4))
|
||||||
|
|
||||||
|
@ -337,8 +355,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
inch_val = float(self.inch_entry.get_value().replace(',', '.'))
|
inch_val = float(self.inch_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
self.mm_entry.set_value('%.6f' % (inch_val * 25.4))
|
self.mm_entry.set_value('%.6f' % (inch_val * 25.4))
|
||||||
|
|
||||||
|
@ -351,8 +369,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
length = float(self.pcblength_entry.get_value().replace(',', '.'))
|
length = float(self.pcblength_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -362,8 +380,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
width = float(self.pcbwidth_entry.get_value().replace(',', '.'))
|
width = float(self.pcbwidth_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -373,8 +391,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
density = float(self.cdensity_entry.get_value().replace(',', '.'))
|
density = float(self.cdensity_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -384,8 +402,8 @@ class ToolCalculator(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
copper = float(self.growth_entry.get_value().replace(',', '.'))
|
copper = float(self.growth_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
calculated_current = (length * width * density) * 0.0021527820833419
|
calculated_current = (length * width * density) * 0.0021527820833419
|
||||||
|
|
|
@ -3,10 +3,18 @@ from ObjectCollection import *
|
||||||
from FlatCAMApp import *
|
from FlatCAMApp import *
|
||||||
from shapely.geometry import box
|
from shapely.geometry import box
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class CutOut(FlatCAMTool):
|
class CutOut(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "Cutout PCB"
|
toolName = _("Cutout PCB")
|
||||||
gapFinished = pyqtSignal()
|
gapFinished = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
|
@ -42,12 +50,12 @@ class CutOut(FlatCAMTool):
|
||||||
# self.type_obj_combo.setItemIcon(1, QtGui.QIcon("share/drill16.png"))
|
# self.type_obj_combo.setItemIcon(1, QtGui.QIcon("share/drill16.png"))
|
||||||
self.type_obj_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
self.type_obj_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
||||||
|
|
||||||
self.type_obj_combo_label = QtWidgets.QLabel("Obj Type:")
|
self.type_obj_combo_label = QtWidgets.QLabel(_("Obj Type:"))
|
||||||
self.type_obj_combo_label.setToolTip(
|
self.type_obj_combo_label.setToolTip(
|
||||||
"Specify the type of object to be cutout.\n"
|
_("Specify the type of object to be cutout.\n"
|
||||||
"It can be of type: Gerber or Geometry.\n"
|
"It can be of type: Gerber or Geometry.\n"
|
||||||
"What is selected here will dictate the kind\n"
|
"What is selected here will dictate the kind\n"
|
||||||
"of objects that will populate the 'Object' combobox."
|
"of objects that will populate the 'Object' combobox.")
|
||||||
)
|
)
|
||||||
self.type_obj_combo_label.setFixedWidth(60)
|
self.type_obj_combo_label.setFixedWidth(60)
|
||||||
form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo)
|
form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo)
|
||||||
|
@ -58,39 +66,39 @@ class CutOut(FlatCAMTool):
|
||||||
self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
||||||
self.obj_combo.setCurrentIndex(1)
|
self.obj_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.object_label = QtWidgets.QLabel("Object:")
|
self.object_label = QtWidgets.QLabel(_("Object:"))
|
||||||
self.object_label.setToolTip(
|
self.object_label.setToolTip(
|
||||||
"Object to be cutout. "
|
_("Object to be cutout. ")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.object_label, self.obj_combo)
|
form_layout.addRow(self.object_label, self.obj_combo)
|
||||||
|
|
||||||
# Tool Diameter
|
# Tool Diameter
|
||||||
self.dia = FCEntry()
|
self.dia = FCEntry()
|
||||||
self.dia_label = QtWidgets.QLabel("Tool Dia:")
|
self.dia_label = QtWidgets.QLabel(_("Tool Dia:"))
|
||||||
self.dia_label.setToolTip(
|
self.dia_label.setToolTip(
|
||||||
"Diameter of the tool used to cutout\n"
|
_( "Diameter of the tool used to cutout\n"
|
||||||
"the PCB shape out of the surrounding material."
|
"the PCB shape out of the surrounding material.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.dia_label, self.dia)
|
form_layout.addRow(self.dia_label, self.dia)
|
||||||
|
|
||||||
# Margin
|
# Margin
|
||||||
self.margin = FCEntry()
|
self.margin = FCEntry()
|
||||||
self.margin_label = QtWidgets.QLabel("Margin:")
|
self.margin_label = QtWidgets.QLabel(_("Margin:"))
|
||||||
self.margin_label.setToolTip(
|
self.margin_label.setToolTip(
|
||||||
"Margin over bounds. A positive value here\n"
|
_( "Margin over bounds. A positive value here\n"
|
||||||
"will make the cutout of the PCB further from\n"
|
"will make the cutout of the PCB further from\n"
|
||||||
"the actual PCB border"
|
"the actual PCB border")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.margin_label, self.margin)
|
form_layout.addRow(self.margin_label, self.margin)
|
||||||
|
|
||||||
# Gapsize
|
# Gapsize
|
||||||
self.gapsize = FCEntry()
|
self.gapsize = FCEntry()
|
||||||
self.gapsize_label = QtWidgets.QLabel("Gap size:")
|
self.gapsize_label = QtWidgets.QLabel(_("Gap size:"))
|
||||||
self.gapsize_label.setToolTip(
|
self.gapsize_label.setToolTip(
|
||||||
"The size of the bridge gaps in the cutout\n"
|
_( "The size of the bridge gaps in the cutout\n"
|
||||||
"used to keep the board connected to\n"
|
"used to keep the board connected to\n"
|
||||||
"the surrounding material (the one \n"
|
"the surrounding material (the one \n"
|
||||||
"from which the PCB is cutout)."
|
"from which the PCB is cutout).")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.gapsize_label, self.gapsize)
|
form_layout.addRow(self.gapsize_label, self.gapsize)
|
||||||
|
|
||||||
|
@ -103,9 +111,9 @@ class CutOut(FlatCAMTool):
|
||||||
# 8 - 2*left + 2*right +2*top + 2*bottom
|
# 8 - 2*left + 2*right +2*top + 2*bottom
|
||||||
|
|
||||||
## Title2
|
## Title2
|
||||||
title_param_label = QtWidgets.QLabel("<font size=4><b>A. Automatic Bridge Gaps</b></font>")
|
title_param_label = QtWidgets.QLabel("<font size=4><b>%s</b></font>" % _('A. Automatic Bridge Gaps'))
|
||||||
title_param_label.setToolTip(
|
title_param_label.setToolTip(
|
||||||
"This section handle creation of automatic bridge gaps."
|
_("This section handle creation of automatic bridge gaps.")
|
||||||
)
|
)
|
||||||
self.layout.addWidget(title_param_label)
|
self.layout.addWidget(title_param_label)
|
||||||
|
|
||||||
|
@ -114,9 +122,9 @@ class CutOut(FlatCAMTool):
|
||||||
self.layout.addLayout(form_layout_2)
|
self.layout.addLayout(form_layout_2)
|
||||||
|
|
||||||
# Gaps
|
# Gaps
|
||||||
gaps_label = QtWidgets.QLabel('Gaps:')
|
gaps_label = QtWidgets.QLabel(_('Gaps:'))
|
||||||
gaps_label.setToolTip(
|
gaps_label.setToolTip(
|
||||||
"Number of gaps used for the Automatic cutout.\n"
|
_("Number of gaps used for the Automatic cutout.\n"
|
||||||
"There can be maximum 8 bridges/gaps.\n"
|
"There can be maximum 8 bridges/gaps.\n"
|
||||||
"The choices are:\n"
|
"The choices are:\n"
|
||||||
"- lr - left + right\n"
|
"- lr - left + right\n"
|
||||||
|
@ -124,7 +132,7 @@ class CutOut(FlatCAMTool):
|
||||||
"- 4 - left + right +top + bottom\n"
|
"- 4 - left + right +top + bottom\n"
|
||||||
"- 2lr - 2*left + 2*right\n"
|
"- 2lr - 2*left + 2*right\n"
|
||||||
"- 2tb - 2*top + 2*bottom\n"
|
"- 2tb - 2*top + 2*bottom\n"
|
||||||
"- 8 - 2*left + 2*right +2*top + 2*bottom"
|
"- 8 - 2*left + 2*right +2*top + 2*bottom")
|
||||||
)
|
)
|
||||||
gaps_label.setFixedWidth(60)
|
gaps_label.setFixedWidth(60)
|
||||||
|
|
||||||
|
@ -139,50 +147,50 @@ class CutOut(FlatCAMTool):
|
||||||
hlay = QtWidgets.QHBoxLayout()
|
hlay = QtWidgets.QHBoxLayout()
|
||||||
self.layout.addLayout(hlay)
|
self.layout.addLayout(hlay)
|
||||||
|
|
||||||
title_ff_label = QtWidgets.QLabel("<b>FreeForm:</b>")
|
title_ff_label = QtWidgets.QLabel("<b>%s</b>" % _('FreeForm:'))
|
||||||
title_ff_label.setToolTip(
|
title_ff_label.setToolTip(
|
||||||
"The cutout shape can be of ny shape.\n"
|
_("The cutout shape can be of ny shape.\n"
|
||||||
"Useful when the PCB has a non-rectangular shape."
|
"Useful when the PCB has a non-rectangular shape.")
|
||||||
)
|
)
|
||||||
hlay.addWidget(title_ff_label)
|
hlay.addWidget(title_ff_label)
|
||||||
|
|
||||||
hlay.addStretch()
|
hlay.addStretch()
|
||||||
|
|
||||||
self.ff_cutout_object_btn = QtWidgets.QPushButton("Generate Geo")
|
self.ff_cutout_object_btn = QtWidgets.QPushButton(_("Generate Geo"))
|
||||||
self.ff_cutout_object_btn.setToolTip(
|
self.ff_cutout_object_btn.setToolTip(
|
||||||
"Cutout the selected object.\n"
|
_("Cutout the selected object.\n"
|
||||||
"The cutout shape can be of any shape.\n"
|
"The cutout shape can be of any shape.\n"
|
||||||
"Useful when the PCB has a non-rectangular shape."
|
"Useful when the PCB has a non-rectangular shape.")
|
||||||
)
|
)
|
||||||
hlay.addWidget(self.ff_cutout_object_btn)
|
hlay.addWidget(self.ff_cutout_object_btn)
|
||||||
|
|
||||||
hlay2 = QtWidgets.QHBoxLayout()
|
hlay2 = QtWidgets.QHBoxLayout()
|
||||||
self.layout.addLayout(hlay2)
|
self.layout.addLayout(hlay2)
|
||||||
|
|
||||||
title_rct_label = QtWidgets.QLabel("<b>Rectangular:</b>")
|
title_rct_label = QtWidgets.QLabel("<b>%s</b>" % _('Rectangular:'))
|
||||||
title_rct_label.setToolTip(
|
title_rct_label.setToolTip(
|
||||||
"The resulting cutout shape is\n"
|
_("The resulting cutout shape is\n"
|
||||||
"always a rectangle shape and it will be\n"
|
"always a rectangle shape and it will be\n"
|
||||||
"the bounding box of the Object."
|
"the bounding box of the Object.")
|
||||||
)
|
)
|
||||||
hlay2.addWidget(title_rct_label)
|
hlay2.addWidget(title_rct_label)
|
||||||
|
|
||||||
hlay2.addStretch()
|
hlay2.addStretch()
|
||||||
self.rect_cutout_object_btn = QtWidgets.QPushButton("Generate Geo")
|
self.rect_cutout_object_btn = QtWidgets.QPushButton(_("Generate Geo"))
|
||||||
self.rect_cutout_object_btn.setToolTip(
|
self.rect_cutout_object_btn.setToolTip(
|
||||||
"Cutout the selected object.\n"
|
_("Cutout the selected object.\n"
|
||||||
"The resulting cutout shape is\n"
|
"The resulting cutout shape is\n"
|
||||||
"always a rectangle shape and it will be\n"
|
"always a rectangle shape and it will be\n"
|
||||||
"the bounding box of the Object."
|
"the bounding box of the Object.")
|
||||||
)
|
)
|
||||||
hlay2.addWidget(self.rect_cutout_object_btn)
|
hlay2.addWidget(self.rect_cutout_object_btn)
|
||||||
|
|
||||||
## Title5
|
## Title5
|
||||||
title_manual_label = QtWidgets.QLabel("<font size=4><b>B. Manual Bridge Gaps</b></font>")
|
title_manual_label = QtWidgets.QLabel("<font size=4><b>%s</b></font>" % _('B. Manual Bridge Gaps'))
|
||||||
title_manual_label.setToolTip(
|
title_manual_label.setToolTip(
|
||||||
"This section handle creation of manual bridge gaps.\n"
|
_("This section handle creation of manual bridge gaps.\n"
|
||||||
"This is done by mouse clicking on the perimeter of the\n"
|
"This is done by mouse clicking on the perimeter of the\n"
|
||||||
"Geometry object that is used as a cutout object. "
|
"Geometry object that is used as a cutout object. ")
|
||||||
)
|
)
|
||||||
self.layout.addWidget(title_manual_label)
|
self.layout.addWidget(title_manual_label)
|
||||||
|
|
||||||
|
@ -196,9 +204,9 @@ class CutOut(FlatCAMTool):
|
||||||
self.man_object_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
|
self.man_object_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
|
||||||
self.man_object_combo.setCurrentIndex(1)
|
self.man_object_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.man_object_label = QtWidgets.QLabel("Geo Obj:")
|
self.man_object_label = QtWidgets.QLabel(_("Geo Obj:"))
|
||||||
self.man_object_label.setToolTip(
|
self.man_object_label.setToolTip(
|
||||||
"Geometry object used to create the manual cutout."
|
_("Geometry object used to create the manual cutout.")
|
||||||
)
|
)
|
||||||
self.man_object_label.setFixedWidth(60)
|
self.man_object_label.setFixedWidth(60)
|
||||||
# e_lab_0 = QtWidgets.QLabel('')
|
# e_lab_0 = QtWidgets.QLabel('')
|
||||||
|
@ -209,44 +217,44 @@ class CutOut(FlatCAMTool):
|
||||||
hlay3 = QtWidgets.QHBoxLayout()
|
hlay3 = QtWidgets.QHBoxLayout()
|
||||||
self.layout.addLayout(hlay3)
|
self.layout.addLayout(hlay3)
|
||||||
|
|
||||||
self.man_geo_label = QtWidgets.QLabel("Manual Geo:")
|
self.man_geo_label = QtWidgets.QLabel(_("Manual Geo:"))
|
||||||
self.man_geo_label.setToolTip(
|
self.man_geo_label.setToolTip(
|
||||||
"If the object to be cutout is a Gerber\n"
|
_("If the object to be cutout is a Gerber\n"
|
||||||
"first create a Geometry that surrounds it,\n"
|
"first create a Geometry that surrounds it,\n"
|
||||||
"to be used as the cutout, if one doesn't exist yet.\n"
|
"to be used as the cutout, if one doesn't exist yet.\n"
|
||||||
"Select the source Gerber file in the top object combobox."
|
"Select the source Gerber file in the top object combobox.")
|
||||||
)
|
)
|
||||||
hlay3.addWidget(self.man_geo_label)
|
hlay3.addWidget(self.man_geo_label)
|
||||||
|
|
||||||
hlay3.addStretch()
|
hlay3.addStretch()
|
||||||
self.man_geo_creation_btn = QtWidgets.QPushButton("Generate Geo")
|
self.man_geo_creation_btn = QtWidgets.QPushButton(_("Generate Geo"))
|
||||||
self.man_geo_creation_btn.setToolTip(
|
self.man_geo_creation_btn.setToolTip(
|
||||||
"If the object to be cutout is a Gerber\n"
|
_("If the object to be cutout is a Gerber\n"
|
||||||
"first create a Geometry that surrounds it,\n"
|
"first create a Geometry that surrounds it,\n"
|
||||||
"to be used as the cutout, if one doesn't exist yet.\n"
|
"to be used as the cutout, if one doesn't exist yet.\n"
|
||||||
"Select the source Gerber file in the top object combobox."
|
"Select the source Gerber file in the top object combobox.")
|
||||||
)
|
)
|
||||||
hlay3.addWidget(self.man_geo_creation_btn)
|
hlay3.addWidget(self.man_geo_creation_btn)
|
||||||
|
|
||||||
hlay4 = QtWidgets.QHBoxLayout()
|
hlay4 = QtWidgets.QHBoxLayout()
|
||||||
self.layout.addLayout(hlay4)
|
self.layout.addLayout(hlay4)
|
||||||
|
|
||||||
self.man_bridge_gaps_label = QtWidgets.QLabel("Manual Add Bridge Gaps:")
|
self.man_bridge_gaps_label = QtWidgets.QLabel(_("Manual Add Bridge Gaps:"))
|
||||||
self.man_bridge_gaps_label.setToolTip(
|
self.man_bridge_gaps_label.setToolTip(
|
||||||
"Use the left mouse button (LMB) click\n"
|
_("Use the left mouse button (LMB) click\n"
|
||||||
"to create a bridge gap to separate the PCB from\n"
|
"to create a bridge gap to separate the PCB from\n"
|
||||||
"the surrounding material."
|
"the surrounding material.")
|
||||||
)
|
)
|
||||||
hlay4.addWidget(self.man_bridge_gaps_label)
|
hlay4.addWidget(self.man_bridge_gaps_label)
|
||||||
|
|
||||||
hlay4.addStretch()
|
hlay4.addStretch()
|
||||||
self.man_gaps_creation_btn = QtWidgets.QPushButton("Generate Gap")
|
self.man_gaps_creation_btn = QtWidgets.QPushButton(_("Generate Gap"))
|
||||||
self.man_gaps_creation_btn.setToolTip(
|
self.man_gaps_creation_btn.setToolTip(
|
||||||
"Use the left mouse button (LMB) click\n"
|
_("Use the left mouse button (LMB) click\n"
|
||||||
"to create a bridge gap to separate the PCB from\n"
|
"to create a bridge gap to separate the PCB from\n"
|
||||||
"the surrounding material.\n"
|
"the surrounding material.\n"
|
||||||
"The LMB click has to be done on the perimeter of\n"
|
"The LMB click has to be done on the perimeter of\n"
|
||||||
"the Geometry object used as a cutout geometry."
|
"the Geometry object used as a cutout geometry.")
|
||||||
)
|
)
|
||||||
hlay4.addWidget(self.man_gaps_creation_btn)
|
hlay4.addWidget(self.man_gaps_creation_btn)
|
||||||
|
|
||||||
|
@ -258,23 +266,36 @@ class CutOut(FlatCAMTool):
|
||||||
# true if we want to repeat the gap without clicking again on the button
|
# true if we want to repeat the gap without clicking again on the button
|
||||||
self.repeat_gap = False
|
self.repeat_gap = False
|
||||||
|
|
||||||
|
## Signals
|
||||||
|
self.ff_cutout_object_btn.clicked.connect(self.on_freeform_cutout)
|
||||||
|
self.rect_cutout_object_btn.clicked.connect(self.on_rectangular_cutout)
|
||||||
|
|
||||||
|
self.type_obj_combo.currentIndexChanged.connect(self.on_type_obj_index_changed)
|
||||||
|
self.man_geo_creation_btn.clicked.connect(self.on_manual_geo)
|
||||||
|
self.man_gaps_creation_btn.clicked.connect(self.on_manual_gap_click)
|
||||||
|
|
||||||
def on_type_obj_index_changed(self, index):
|
def on_type_obj_index_changed(self, index):
|
||||||
obj_type = self.type_obj_combo.currentIndex()
|
obj_type = self.type_obj_combo.currentIndex()
|
||||||
self.obj_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
|
self.obj_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
|
||||||
self.obj_combo.setCurrentIndex(0)
|
self.obj_combo.setCurrentIndex(0)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolCutOut()")
|
self.app.report_usage("ToolCutOut()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
|
||||||
|
@ -291,14 +312,6 @@ class CutOut(FlatCAMTool):
|
||||||
self.gapsize.set_value(float(self.app.defaults["tools_cutoutgapsize"]))
|
self.gapsize.set_value(float(self.app.defaults["tools_cutoutgapsize"]))
|
||||||
self.gaps.set_value(4)
|
self.gaps.set_value(4)
|
||||||
|
|
||||||
## Signals
|
|
||||||
self.ff_cutout_object_btn.clicked.connect(self.on_freeform_cutout)
|
|
||||||
self.rect_cutout_object_btn.clicked.connect(self.on_rectangular_cutout)
|
|
||||||
|
|
||||||
self.type_obj_combo.currentIndexChanged.connect(self.on_type_obj_index_changed)
|
|
||||||
self.man_geo_creation_btn.clicked.connect(self.on_manual_geo)
|
|
||||||
self.man_gaps_creation_btn.clicked.connect(self.on_manual_gap_click)
|
|
||||||
|
|
||||||
self.gapFinished.connect(self.on_gap_finished)
|
self.gapFinished.connect(self.on_gap_finished)
|
||||||
|
|
||||||
def on_freeform_cutout(self):
|
def on_freeform_cutout(self):
|
||||||
|
@ -313,11 +326,11 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
cutout_obj = self.app.collection.get_by_name(str(name))
|
cutout_obj = self.app.collection.get_by_name(str(name))
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Could not retrieve object: %s" % name)
|
self.app.inform.emit(_("[ERROR_NOTCL]Could not retrieve object: %s") % name)
|
||||||
return "Could not retrieve object: %s" % name
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
if cutout_obj is None:
|
if cutout_obj is None:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]There is no object selected for Cutout.\nSelect one and try again.")
|
self.app.inform.emit(_("[ERROR_NOTCL]There is no object selected for Cutout.\nSelect one and try again."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -327,13 +340,13 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
dia = float(self.dia.get_value().replace(',', '.'))
|
dia = float(self.dia.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
if 0 in {dia}:
|
if 0 in {dia}:
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Tool Diameter is zero value. Change it to a positive integer.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Tool Diameter is zero value. Change it to a positive integer."))
|
||||||
return "Tool Diameter is zero value. Change it to a positive integer."
|
return "Tool Diameter is zero value. Change it to a positive integer."
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -343,8 +356,8 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
margin = float(self.margin.get_value().replace(',', '.'))
|
margin = float(self.margin.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Margin value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Margin value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -354,25 +367,25 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
gapsize = float(self.gapsize.get_value().replace(',', '.'))
|
gapsize = float(self.gapsize.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Gap size value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Gap size value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
gaps = self.gaps.get_value()
|
gaps = self.gaps.get_value()
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Number of gaps value is missing. Add it and retry.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Number of gaps value is missing. Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if gaps not in ['LR', 'TB', '2LR', '2TB', '4', '8']:
|
if gaps not in ['LR', 'TB', '2LR', '2TB', '4', '8']:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Gaps value can be only one of: 'lr', 'tb', '2lr', '2tb', 4 or 8. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Gaps value can be only one of: 'lr', 'tb', '2lr', '2tb', 4 or 8. "
|
||||||
"Fill in a correct value and retry. ")
|
"Fill in a correct value and retry. "))
|
||||||
return
|
return
|
||||||
|
|
||||||
if cutout_obj.multigeo is True:
|
if cutout_obj.multigeo is True:
|
||||||
self.app.inform.emit("[ERROR]Cutout operation cannot be done on a multi-geo Geometry.\n"
|
self.app.inform.emit(_("[ERROR]Cutout operation cannot be done on a multi-geo Geometry.\n"
|
||||||
"Optionally, this Multi-geo Geometry can be converted to Single-geo Geometry,\n"
|
"Optionally, this Multi-geo Geometry can be converted to Single-geo Geometry,\n"
|
||||||
"and after that perform Cutout.")
|
"and after that perform Cutout."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get min and max data for each object as we just cut rectangles across X or Y
|
# Get min and max data for each object as we just cut rectangles across X or Y
|
||||||
|
@ -436,7 +449,7 @@ class CutOut(FlatCAMTool):
|
||||||
ymax + gapsize)
|
ymax + gapsize)
|
||||||
|
|
||||||
cutout_obj.plot()
|
cutout_obj.plot()
|
||||||
self.app.inform.emit("[success] Any form CutOut operation finished.")
|
self.app.inform.emit(_("[success] Any form CutOut operation finished."))
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
||||||
self.app.should_we_save = True
|
self.app.should_we_save = True
|
||||||
|
|
||||||
|
@ -452,11 +465,11 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
cutout_obj = self.app.collection.get_by_name(str(name))
|
cutout_obj = self.app.collection.get_by_name(str(name))
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Could not retrieve object: %s" % name)
|
self.app.inform.emit(_("[ERROR_NOTCL]Could not retrieve object: %s") % name)
|
||||||
return "Could not retrieve object: %s" % name
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
if cutout_obj is None:
|
if cutout_obj is None:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Object not found: %s" % cutout_obj)
|
self.app.inform.emit(_("[ERROR_NOTCL]Object not found: %s") % cutout_obj)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dia = float(self.dia.get_value())
|
dia = float(self.dia.get_value())
|
||||||
|
@ -465,12 +478,12 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
dia = float(self.dia.get_value().replace(',', '.'))
|
dia = float(self.dia.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if 0 in {dia}:
|
if 0 in {dia}:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Tool Diameter is zero value. Change it to a positive integer.")
|
self.app.inform.emit(_("[ERROR_NOTCL]Tool Diameter is zero value. Change it to a positive integer."))
|
||||||
return "Tool Diameter is zero value. Change it to a positive integer."
|
return "Tool Diameter is zero value. Change it to a positive integer."
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -480,8 +493,8 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
margin = float(self.margin.get_value().replace(',', '.'))
|
margin = float(self.margin.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Margin value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Margin value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -491,25 +504,25 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
gapsize = float(self.gapsize.get_value().replace(',', '.'))
|
gapsize = float(self.gapsize.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Gap size value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Gap size value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
gaps = self.gaps.get_value()
|
gaps = self.gaps.get_value()
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Number of gaps value is missing. Add it and retry.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Number of gaps value is missing. Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if gaps not in ['LR', 'TB', '2LR', '2TB', '4', '8']:
|
if gaps not in ['LR', 'TB', '2LR', '2TB', '4', '8']:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Gaps value can be only one of: 'lr', 'tb', '2lr', '2tb', 4 or 8. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Gaps value can be only one of: 'lr', 'tb', '2lr', '2tb', 4 or 8. "
|
||||||
"Fill in a correct value and retry. ")
|
"Fill in a correct value and retry. "))
|
||||||
return
|
return
|
||||||
|
|
||||||
if cutout_obj.multigeo is True:
|
if cutout_obj.multigeo is True:
|
||||||
self.app.inform.emit("[ERROR]Cutout operation cannot be done on a multi-geo Geometry.\n"
|
self.app.inform.emit(_("[ERROR]Cutout operation cannot be done on a multi-geo Geometry.\n"
|
||||||
"Optionally, this Multi-geo Geometry can be converted to Single-geo Geometry,\n"
|
"Optionally, this Multi-geo Geometry can be converted to Single-geo Geometry,\n"
|
||||||
"and after that perform Cutout.")
|
"and after that perform Cutout."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get min and max data for each object as we just cut rectangles across X or Y
|
# Get min and max data for each object as we just cut rectangles across X or Y
|
||||||
|
@ -570,12 +583,12 @@ class CutOut(FlatCAMTool):
|
||||||
ymax + gapsize)
|
ymax + gapsize)
|
||||||
|
|
||||||
cutout_obj.plot()
|
cutout_obj.plot()
|
||||||
self.app.inform.emit("[success] Any form CutOut operation finished.")
|
self.app.inform.emit(_("[success] Any form CutOut operation finished."))
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
||||||
self.app.should_we_save = True
|
self.app.should_we_save = True
|
||||||
|
|
||||||
def on_manual_gap_click(self):
|
def on_manual_gap_click(self):
|
||||||
self.app.inform.emit("Click on the selected geometry object perimeter to create a bridge gap ...")
|
self.app.inform.emit(_("Click on the selected geometry object perimeter to create a bridge gap ..."))
|
||||||
self.app.geo_editor.tool_shape.enabled = True
|
self.app.geo_editor.tool_shape.enabled = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -585,12 +598,12 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
self.cutting_dia = float(self.dia.get_value().replace(',', '.'))
|
self.cutting_dia = float(self.dia.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if 0 in {self.cutting_dia}:
|
if 0 in {self.cutting_dia}:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Tool Diameter is zero value. Change it to a positive integer.")
|
self.app.inform.emit(_("[ERROR_NOTCL]Tool Diameter is zero value. Change it to a positive integer."))
|
||||||
return "Tool Diameter is zero value. Change it to a positive integer."
|
return "Tool Diameter is zero value. Change it to a positive integer."
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -600,8 +613,8 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
self.cutting_gapsize = float(self.gapsize.get_value().replace(',', '.'))
|
self.cutting_gapsize = float(self.gapsize.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Gap size value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Gap size value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.app.plotcanvas.vis_disconnect('key_press', self.app.ui.keyPressEvent)
|
self.app.plotcanvas.vis_disconnect('key_press', self.app.ui.keyPressEvent)
|
||||||
|
@ -616,7 +629,7 @@ class CutOut(FlatCAMTool):
|
||||||
def doit(self, event):
|
def doit(self, event):
|
||||||
# do paint single only for left mouse clicks
|
# do paint single only for left mouse clicks
|
||||||
if event.button == 1:
|
if event.button == 1:
|
||||||
self.app.inform.emit("Making manual bridge gap...")
|
self.app.inform.emit(_("Making manual bridge gap..."))
|
||||||
pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
|
pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
|
||||||
self.on_manual_cutout(click_pos=pos)
|
self.on_manual_cutout(click_pos=pos)
|
||||||
|
|
||||||
|
@ -639,11 +652,11 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
cutout_obj = self.app.collection.get_by_name(str(name))
|
cutout_obj = self.app.collection.get_by_name(str(name))
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Could not retrieve Geoemtry object: %s" % name)
|
self.app.inform.emit(_("[ERROR_NOTCL]Could not retrieve Geoemtry object: %s") % name)
|
||||||
return "Could not retrieve object: %s" % name
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
if cutout_obj is None:
|
if cutout_obj is None:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Geometry object for manual cutout not found: %s" % cutout_obj)
|
self.app.inform.emit(_("[ERROR_NOTCL]Geometry object for manual cutout not found: %s") % cutout_obj)
|
||||||
return
|
return
|
||||||
|
|
||||||
# use the snapped position as reference
|
# use the snapped position as reference
|
||||||
|
@ -653,7 +666,7 @@ class CutOut(FlatCAMTool):
|
||||||
cutout_obj.subtract_polygon(cut_poly)
|
cutout_obj.subtract_polygon(cut_poly)
|
||||||
|
|
||||||
cutout_obj.plot()
|
cutout_obj.plot()
|
||||||
self.app.inform.emit("[success] Added manual Bridge Gap.")
|
self.app.inform.emit(_("[success] Added manual Bridge Gap."))
|
||||||
|
|
||||||
self.app.should_we_save = True
|
self.app.should_we_save = True
|
||||||
|
|
||||||
|
@ -670,17 +683,17 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
cutout_obj = self.app.collection.get_by_name(str(name))
|
cutout_obj = self.app.collection.get_by_name(str(name))
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Could not retrieve Gerber object: %s" % name)
|
self.app.inform.emit(_("[ERROR_NOTCL]Could not retrieve Gerber object: %s") % name)
|
||||||
return "Could not retrieve object: %s" % name
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
if cutout_obj is None:
|
if cutout_obj is None:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]There is no Gerber object selected for Cutout.\n"
|
self.app.inform.emit(_("[ERROR_NOTCL]There is no Gerber object selected for Cutout.\n"
|
||||||
"Select one and try again.")
|
"Select one and try again."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if not isinstance(cutout_obj, FlatCAMGerber):
|
if not isinstance(cutout_obj, FlatCAMGerber):
|
||||||
self.app.inform.emit("[ERROR_NOTCL]The selected object has to be of Gerber type.\n"
|
self.app.inform.emit(_("[ERROR_NOTCL]The selected object has to be of Gerber type.\n"
|
||||||
"Select a Gerber file and try again.")
|
"Select a Gerber file and try again."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -690,12 +703,12 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
dia = float(self.dia.get_value().replace(',', '.'))
|
dia = float(self.dia.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if 0 in {dia}:
|
if 0 in {dia}:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Tool Diameter is zero value. Change it to a positive integer.")
|
self.app.inform.emit(_("[ERROR_NOTCL]Tool Diameter is zero value. Change it to a positive integer."))
|
||||||
return "Tool Diameter is zero value. Change it to a positive integer."
|
return "Tool Diameter is zero value. Change it to a positive integer."
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -705,8 +718,8 @@ class CutOut(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
margin = float(self.margin.get_value().replace(',', '.'))
|
margin = float(self.margin.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Margin value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Margin value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
def geo_init(geo_obj, app_obj):
|
def geo_init(geo_obj, app_obj):
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
from PyQt5 import QtGui
|
|
||||||
from GUIElements import RadioSet, EvalEntry, LengthEntry
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from FlatCAMObj import *
|
from FlatCAMObj import *
|
||||||
from shapely.geometry import Point
|
from shapely.geometry import Point
|
||||||
from shapely import affinity
|
from shapely import affinity
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class DblSidedTool(FlatCAMTool):
|
class DblSidedTool(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "2-Sided PCB"
|
toolName = _("2-Sided PCB")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
FlatCAMTool.__init__(self, app)
|
FlatCAMTool.__init__(self, app)
|
||||||
|
@ -43,18 +49,18 @@ class DblSidedTool(FlatCAMTool):
|
||||||
"Gerber to be mirrored."
|
"Gerber to be mirrored."
|
||||||
)
|
)
|
||||||
|
|
||||||
self.mirror_gerber_button = QtWidgets.QPushButton("Mirror")
|
self.mirror_gerber_button = QtWidgets.QPushButton(_("Mirror"))
|
||||||
self.mirror_gerber_button.setToolTip(
|
self.mirror_gerber_button.setToolTip(
|
||||||
"Mirrors (flips) the specified object around \n"
|
_("Mirrors (flips) the specified object around \n"
|
||||||
"the specified axis. Does not create a new \n"
|
"the specified axis. Does not create a new \n"
|
||||||
"object, but modifies it."
|
"object, but modifies it.")
|
||||||
)
|
)
|
||||||
self.mirror_gerber_button.setFixedWidth(40)
|
self.mirror_gerber_button.setFixedWidth(60)
|
||||||
|
|
||||||
# grid_lay.addRow("Bottom Layer:", self.object_combo)
|
# grid_lay.addRow("Bottom Layer:", self.object_combo)
|
||||||
grid_lay.addWidget(self.botlay_label, 0, 0)
|
grid_lay.addWidget(self.botlay_label, 0, 0)
|
||||||
grid_lay.addWidget(self.gerber_object_combo, 1, 0, 1, 2)
|
grid_lay.addWidget(self.gerber_object_combo, 1, 0)
|
||||||
grid_lay.addWidget(self.mirror_gerber_button, 1, 3)
|
grid_lay.addWidget(self.mirror_gerber_button, 1, 1)
|
||||||
|
|
||||||
## Excellon Object to mirror
|
## Excellon Object to mirror
|
||||||
self.exc_object_combo = QtWidgets.QComboBox()
|
self.exc_object_combo = QtWidgets.QComboBox()
|
||||||
|
@ -64,21 +70,21 @@ class DblSidedTool(FlatCAMTool):
|
||||||
|
|
||||||
self.excobj_label = QtWidgets.QLabel("<b>EXCELLON:</b>")
|
self.excobj_label = QtWidgets.QLabel("<b>EXCELLON:</b>")
|
||||||
self.excobj_label.setToolTip(
|
self.excobj_label.setToolTip(
|
||||||
"Excellon Object to be mirrored."
|
_("Excellon Object to be mirrored.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.mirror_exc_button = QtWidgets.QPushButton("Mirror")
|
self.mirror_exc_button = QtWidgets.QPushButton(_("Mirror"))
|
||||||
self.mirror_exc_button.setToolTip(
|
self.mirror_exc_button.setToolTip(
|
||||||
"Mirrors (flips) the specified object around \n"
|
_("Mirrors (flips) the specified object around \n"
|
||||||
"the specified axis. Does not create a new \n"
|
"the specified axis. Does not create a new \n"
|
||||||
"object, but modifies it."
|
"object, but modifies it.")
|
||||||
)
|
)
|
||||||
self.mirror_exc_button.setFixedWidth(40)
|
self.mirror_exc_button.setFixedWidth(60)
|
||||||
|
|
||||||
# grid_lay.addRow("Bottom Layer:", self.object_combo)
|
# grid_lay.addRow("Bottom Layer:", self.object_combo)
|
||||||
grid_lay.addWidget(self.excobj_label, 2, 0)
|
grid_lay.addWidget(self.excobj_label, 2, 0)
|
||||||
grid_lay.addWidget(self.exc_object_combo, 3, 0, 1, 2)
|
grid_lay.addWidget(self.exc_object_combo, 3, 0)
|
||||||
grid_lay.addWidget(self.mirror_exc_button, 3, 3)
|
grid_lay.addWidget(self.mirror_exc_button, 3, 1)
|
||||||
|
|
||||||
## Geometry Object to mirror
|
## Geometry Object to mirror
|
||||||
self.geo_object_combo = QtWidgets.QComboBox()
|
self.geo_object_combo = QtWidgets.QComboBox()
|
||||||
|
@ -88,73 +94,81 @@ class DblSidedTool(FlatCAMTool):
|
||||||
|
|
||||||
self.geoobj_label = QtWidgets.QLabel("<b>GEOMETRY</b>:")
|
self.geoobj_label = QtWidgets.QLabel("<b>GEOMETRY</b>:")
|
||||||
self.geoobj_label.setToolTip(
|
self.geoobj_label.setToolTip(
|
||||||
"Geometry Obj to be mirrored."
|
_("Geometry Obj to be mirrored.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.mirror_geo_button = QtWidgets.QPushButton("Mirror")
|
self.mirror_geo_button = QtWidgets.QPushButton(_("Mirror"))
|
||||||
self.mirror_geo_button.setToolTip(
|
self.mirror_geo_button.setToolTip(
|
||||||
"Mirrors (flips) the specified object around \n"
|
_("Mirrors (flips) the specified object around \n"
|
||||||
"the specified axis. Does not create a new \n"
|
"the specified axis. Does not create a new \n"
|
||||||
"object, but modifies it."
|
"object, but modifies it.")
|
||||||
)
|
)
|
||||||
self.mirror_geo_button.setFixedWidth(40)
|
self.mirror_geo_button.setFixedWidth(60)
|
||||||
|
|
||||||
# grid_lay.addRow("Bottom Layer:", self.object_combo)
|
# grid_lay.addRow("Bottom Layer:", self.object_combo)
|
||||||
grid_lay.addWidget(self.geoobj_label, 4, 0)
|
grid_lay.addWidget(self.geoobj_label, 4, 0)
|
||||||
grid_lay.addWidget(self.geo_object_combo, 5, 0, 1, 2)
|
grid_lay.addWidget(self.geo_object_combo, 5, 0)
|
||||||
grid_lay.addWidget(self.mirror_geo_button, 5, 3)
|
grid_lay.addWidget(self.mirror_geo_button, 5, 1)
|
||||||
|
|
||||||
|
## Grid Layout
|
||||||
|
grid_lay1 = QtWidgets.QGridLayout()
|
||||||
|
self.layout.addLayout(grid_lay1)
|
||||||
|
|
||||||
## Axis
|
## Axis
|
||||||
self.mirror_axis = RadioSet([{'label': 'X', 'value': 'X'},
|
self.mirror_axis = RadioSet([{'label': 'X', 'value': 'X'},
|
||||||
{'label': 'Y', 'value': 'Y'}])
|
{'label': 'Y', 'value': 'Y'}])
|
||||||
self.mirax_label = QtWidgets.QLabel("Mirror Axis:")
|
self.mirax_label = QtWidgets.QLabel(_("Mirror Axis:"))
|
||||||
self.mirax_label.setToolTip(
|
self.mirax_label.setToolTip(
|
||||||
"Mirror vertically (X) or horizontally (Y)."
|
_("Mirror vertically (X) or horizontally (Y).")
|
||||||
)
|
)
|
||||||
# grid_lay.addRow("Mirror Axis:", self.mirror_axis)
|
# grid_lay.addRow("Mirror Axis:", self.mirror_axis)
|
||||||
self.empty_lb1 = QtWidgets.QLabel("")
|
self.empty_lb1 = QtWidgets.QLabel("")
|
||||||
grid_lay.addWidget(self.empty_lb1, 6, 0)
|
grid_lay1.addWidget(self.empty_lb1, 6, 0)
|
||||||
grid_lay.addWidget(self.mirax_label, 7, 0)
|
grid_lay1.addWidget(self.mirax_label, 7, 0)
|
||||||
grid_lay.addWidget(self.mirror_axis, 7, 1)
|
grid_lay1.addWidget(self.mirror_axis, 7, 1)
|
||||||
|
|
||||||
## Axis Location
|
## Axis Location
|
||||||
self.axis_location = RadioSet([{'label': 'Point', 'value': 'point'},
|
self.axis_location = RadioSet([{'label': 'Point', 'value': 'point'},
|
||||||
{'label': 'Box', 'value': 'box'}])
|
{'label': 'Box', 'value': 'box'}])
|
||||||
self.axloc_label = QtWidgets.QLabel("Axis Ref:")
|
self.axloc_label = QtWidgets.QLabel(_("Axis Ref:"))
|
||||||
self.axloc_label.setToolTip(
|
self.axloc_label.setToolTip(
|
||||||
"The axis should pass through a <b>point</b> or cut\n "
|
_("The axis should pass through a <b>point</b> or cut\n "
|
||||||
"a specified <b>box</b> (in a FlatCAM object) through \n"
|
"a specified <b>box</b> (in a FlatCAM object) through \n"
|
||||||
"the center."
|
"the center.")
|
||||||
)
|
)
|
||||||
# grid_lay.addRow("Axis Location:", self.axis_location)
|
# grid_lay.addRow("Axis Location:", self.axis_location)
|
||||||
grid_lay.addWidget(self.axloc_label, 8, 0)
|
grid_lay1.addWidget(self.axloc_label, 8, 0)
|
||||||
grid_lay.addWidget(self.axis_location, 8, 1)
|
grid_lay1.addWidget(self.axis_location, 8, 1)
|
||||||
|
|
||||||
self.empty_lb2 = QtWidgets.QLabel("")
|
self.empty_lb2 = QtWidgets.QLabel("")
|
||||||
grid_lay.addWidget(self.empty_lb2, 9, 0)
|
grid_lay1.addWidget(self.empty_lb2, 9, 0)
|
||||||
|
|
||||||
|
## Grid Layout
|
||||||
|
grid_lay2 = QtWidgets.QGridLayout()
|
||||||
|
self.layout.addLayout(grid_lay2)
|
||||||
|
|
||||||
## Point/Box
|
## Point/Box
|
||||||
self.point_box_container = QtWidgets.QVBoxLayout()
|
self.point_box_container = QtWidgets.QVBoxLayout()
|
||||||
self.pb_label = QtWidgets.QLabel("<b>Point/Box Reference:</b>")
|
self.pb_label = QtWidgets.QLabel("<b>%s</b>" % _('Point/Box Reference:'))
|
||||||
self.pb_label.setToolTip(
|
self.pb_label.setToolTip(
|
||||||
"If 'Point' is selected above it store the coordinates (x, y) through which\n"
|
_("If 'Point' is selected above it store the coordinates (x, y) through which\n"
|
||||||
"the mirroring axis passes.\n"
|
"the mirroring axis passes.\n"
|
||||||
"If 'Box' is selected above, select here a FlatCAM object (Gerber, Exc or Geo).\n"
|
"If 'Box' is selected above, select here a FlatCAM object (Gerber, Exc or Geo).\n"
|
||||||
"Through the center of this object pass the mirroring axis selected above."
|
"Through the center of this object pass the mirroring axis selected above.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.add_point_button = QtWidgets.QPushButton("Add")
|
self.add_point_button = QtWidgets.QPushButton(_("Add"))
|
||||||
self.add_point_button.setToolTip(
|
self.add_point_button.setToolTip(
|
||||||
"Add the coordinates in format <b>(x, y)</b> through which the mirroring axis \n "
|
_("Add the coordinates in format <b>(x, y)</b> through which the mirroring axis \n "
|
||||||
"selected in 'MIRROR AXIS' pass.\n"
|
"selected in 'MIRROR AXIS' pass.\n"
|
||||||
"The (x, y) coordinates are captured by pressing SHIFT key\n"
|
"The (x, y) coordinates are captured by pressing SHIFT key\n"
|
||||||
"and left mouse button click on canvas or you can enter the coords manually."
|
"and left mouse button click on canvas or you can enter the coords manually.")
|
||||||
)
|
)
|
||||||
self.add_point_button.setFixedWidth(40)
|
self.add_point_button.setFixedWidth(60)
|
||||||
|
|
||||||
grid_lay.addWidget(self.pb_label, 10, 0)
|
grid_lay2.addWidget(self.pb_label, 10, 0)
|
||||||
grid_lay.addLayout(self.point_box_container, 11, 0, 1, 3)
|
grid_lay2.addLayout(self.point_box_container, 11, 0)
|
||||||
grid_lay.addWidget(self.add_point_button, 11, 3)
|
grid_lay2.addWidget(self.add_point_button, 11, 1)
|
||||||
|
|
||||||
self.point_entry = EvalEntry()
|
self.point_entry = EvalEntry()
|
||||||
|
|
||||||
|
@ -165,9 +179,9 @@ class DblSidedTool(FlatCAMTool):
|
||||||
self.box_combo.setCurrentIndex(1)
|
self.box_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.box_combo_type = QtWidgets.QComboBox()
|
self.box_combo_type = QtWidgets.QComboBox()
|
||||||
self.box_combo_type.addItem("Gerber Reference Box Object")
|
self.box_combo_type.addItem(_("Gerber Reference Box Object"))
|
||||||
self.box_combo_type.addItem("Excellon Reference Box Object")
|
self.box_combo_type.addItem(_("Excellon Reference Box Object"))
|
||||||
self.box_combo_type.addItem("Geometry Reference Box Object")
|
self.box_combo_type.addItem(_("Geometry Reference Box Object"))
|
||||||
|
|
||||||
self.point_box_container.addWidget(self.box_combo_type)
|
self.point_box_container.addWidget(self.box_combo_type)
|
||||||
self.point_box_container.addWidget(self.box_combo)
|
self.point_box_container.addWidget(self.box_combo)
|
||||||
|
@ -176,70 +190,74 @@ class DblSidedTool(FlatCAMTool):
|
||||||
|
|
||||||
|
|
||||||
## Alignment holes
|
## Alignment holes
|
||||||
self.ah_label = QtWidgets.QLabel("<b>Alignment Drill Coordinates:</b>")
|
self.ah_label = QtWidgets.QLabel("<b%s</b>" % _('Alignment Drill Coordinates:'))
|
||||||
self.ah_label.setToolTip(
|
self.ah_label.setToolTip(
|
||||||
"Alignment holes (x1, y1), (x2, y2), ... "
|
_( "Alignment holes (x1, y1), (x2, y2), ... "
|
||||||
"on one side of the mirror axis. For each set of (x, y) coordinates\n"
|
"on one side of the mirror axis. For each set of (x, y) coordinates\n"
|
||||||
"entered here, a pair of drills will be created:\n\n"
|
"entered here, a pair of drills will be created:\n\n"
|
||||||
"- one drill at the coordinates from the field\n"
|
"- one drill at the coordinates from the field\n"
|
||||||
"- one drill in mirror position over the axis selected above in the 'Mirror Axis'."
|
"- one drill in mirror position over the axis selected above in the 'Mirror Axis'.")
|
||||||
)
|
)
|
||||||
self.layout.addWidget(self.ah_label)
|
self.layout.addWidget(self.ah_label)
|
||||||
|
|
||||||
grid_lay1 = QtWidgets.QGridLayout()
|
grid_lay3 = QtWidgets.QGridLayout()
|
||||||
self.layout.addLayout(grid_lay1)
|
self.layout.addLayout(grid_lay3)
|
||||||
|
|
||||||
self.alignment_holes = EvalEntry()
|
self.alignment_holes = EvalEntry()
|
||||||
|
|
||||||
self.add_drill_point_button = QtWidgets.QPushButton("Add")
|
self.add_drill_point_button = QtWidgets.QPushButton(_("Add"))
|
||||||
self.add_drill_point_button.setToolTip(
|
self.add_drill_point_button.setToolTip(
|
||||||
"Add alignment drill holes coords in the format: (x1, y1), (x2, y2), ... \n"
|
_("Add alignment drill holes coords in the format: (x1, y1), (x2, y2), ... \n"
|
||||||
"on one side of the mirror axis.\n\n"
|
"on one side of the mirror axis.\n\n"
|
||||||
"The coordinates set can be obtained:\n"
|
"The coordinates set can be obtained:\n"
|
||||||
"- press SHIFT key and left mouse clicking on canvas. Then click Add.\n"
|
"- press SHIFT key and left mouse clicking on canvas. Then click Add.\n"
|
||||||
"- press SHIFT key and left mouse clicking on canvas. Then CTRL+V in the field.\n"
|
"- press SHIFT key and left mouse clicking on canvas. Then CTRL+V in the field.\n"
|
||||||
"- press SHIFT key and left mouse clicking on canvas. Then RMB click in the field and click Paste.\n"
|
"- press SHIFT key and left mouse clicking on canvas. Then RMB click in the field and click Paste.\n"
|
||||||
"- by entering the coords manually in the format: (x1, y1), (x2, y2), ..."
|
"- by entering the coords manually in the format: (x1, y1), (x2, y2), ...")
|
||||||
)
|
)
|
||||||
self.add_drill_point_button.setFixedWidth(40)
|
self.add_drill_point_button.setFixedWidth(60)
|
||||||
|
|
||||||
grid_lay1.addWidget(self.alignment_holes, 0, 0, 1, 2)
|
grid_lay3.addWidget(self.alignment_holes, 0, 0)
|
||||||
grid_lay1.addWidget(self.add_drill_point_button, 0, 3)
|
grid_lay3.addWidget(self.add_drill_point_button, 0, 1)
|
||||||
|
|
||||||
## Drill diameter for alignment holes
|
## Drill diameter for alignment holes
|
||||||
self.dt_label = QtWidgets.QLabel("<b>Alignment Drill Diameter</b>:")
|
self.dt_label = QtWidgets.QLabel("<b>%s</b>:" % _('Alignment Drill Diameter'))
|
||||||
self.dt_label.setToolTip(
|
self.dt_label.setToolTip(
|
||||||
"Diameter of the drill for the "
|
_("Diameter of the drill for the "
|
||||||
"alignment holes."
|
"alignment holes.")
|
||||||
)
|
)
|
||||||
self.layout.addWidget(self.dt_label)
|
self.layout.addWidget(self.dt_label)
|
||||||
|
|
||||||
grid_lay2 = QtWidgets.QGridLayout()
|
hlay = QtWidgets.QHBoxLayout()
|
||||||
self.layout.addLayout(grid_lay2)
|
self.layout.addLayout(hlay)
|
||||||
|
|
||||||
self.drill_dia = FCEntry()
|
self.drill_dia = FCEntry()
|
||||||
self.dd_label = QtWidgets.QLabel("Drill diam.:")
|
self.dd_label = QtWidgets.QLabel(_("Drill diam.:"))
|
||||||
self.dd_label.setToolTip(
|
self.dd_label.setToolTip(
|
||||||
"Diameter of the drill for the "
|
_("Diameter of the drill for the "
|
||||||
"alignment holes."
|
"alignment holes.")
|
||||||
)
|
)
|
||||||
grid_lay2.addWidget(self.dd_label, 0, 0)
|
hlay.addWidget(self.dd_label)
|
||||||
grid_lay2.addWidget(self.drill_dia, 0, 1)
|
hlay.addWidget(self.drill_dia)
|
||||||
|
|
||||||
|
hlay2 = QtWidgets.QHBoxLayout()
|
||||||
|
self.layout.addLayout(hlay2)
|
||||||
|
|
||||||
## Buttons
|
## Buttons
|
||||||
self.create_alignment_hole_button = QtWidgets.QPushButton("Create Excellon Object")
|
self.create_alignment_hole_button = QtWidgets.QPushButton(_("Create Excellon Object"))
|
||||||
self.create_alignment_hole_button.setToolTip(
|
self.create_alignment_hole_button.setToolTip(
|
||||||
"Creates an Excellon Object containing the\n"
|
_("Creates an Excellon Object containing the\n"
|
||||||
"specified alignment holes and their mirror\n"
|
"specified alignment holes and their mirror\n"
|
||||||
"images.")
|
"images.")
|
||||||
# self.create_alignment_hole_button.setFixedWidth(40)
|
)
|
||||||
grid_lay2.addWidget(self.create_alignment_hole_button, 1,0, 1, 2)
|
hlay2.addWidget(self.create_alignment_hole_button)
|
||||||
|
|
||||||
self.reset_button = QtWidgets.QPushButton("Reset")
|
self.reset_button = QtWidgets.QPushButton(_("Reset"))
|
||||||
self.reset_button.setToolTip(
|
self.reset_button.setToolTip(
|
||||||
"Resets all the fields.")
|
_("Resets all the fields.")
|
||||||
self.reset_button.setFixedWidth(40)
|
)
|
||||||
grid_lay2.addWidget(self.reset_button, 1, 2)
|
self.reset_button.setFixedWidth(60)
|
||||||
|
hlay2.addWidget(self.reset_button)
|
||||||
|
|
||||||
self.layout.addStretch()
|
self.layout.addStretch()
|
||||||
|
|
||||||
|
@ -261,23 +279,27 @@ class DblSidedTool(FlatCAMTool):
|
||||||
def install(self, icon=None, separator=None, **kwargs):
|
def install(self, icon=None, separator=None, **kwargs):
|
||||||
FlatCAMTool.install(self, icon, separator, shortcut='ALT+D', **kwargs)
|
FlatCAMTool.install(self, icon, separator, shortcut='ALT+D', **kwargs)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("Tool2Sided()")
|
self.app.report_usage("Tool2Sided()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
|
||||||
self.app.ui.notebook.setTabText(2, "2-Sided Tool")
|
self.app.ui.notebook.setTabText(2, _("2-Sided Tool"))
|
||||||
|
|
||||||
def set_tool_ui(self):
|
def set_tool_ui(self):
|
||||||
self.reset_fields()
|
self.reset_fields()
|
||||||
|
@ -302,8 +324,8 @@ class DblSidedTool(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
px, py = self.point_entry.get_value()
|
px, py = self.point_entry.get_value()
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] 'Point' reference is selected and 'Point' coordinates "
|
self.app.inform.emit(_("[WARNING_NOTCL] 'Point' reference is selected and 'Point' coordinates "
|
||||||
"are missing. Add them and retry.")
|
"are missing. Add them and retry."))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
selection_index = self.box_combo.currentIndex()
|
selection_index = self.box_combo.currentIndex()
|
||||||
|
@ -321,7 +343,7 @@ class DblSidedTool(FlatCAMTool):
|
||||||
bb_obj = model_index.internalPointer().obj
|
bb_obj = model_index.internalPointer().obj
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit(
|
self.app.inform.emit(
|
||||||
"[WARNING_NOTCL] There is no Box reference object loaded. Load one and retry.")
|
_("[WARNING_NOTCL] There is no Box reference object loaded. Load one and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
xmin, ymin, xmax, ymax = bb_obj.bounds()
|
xmin, ymin, xmax, ymax = bb_obj.bounds()
|
||||||
|
@ -338,19 +360,19 @@ class DblSidedTool(FlatCAMTool):
|
||||||
dia = float(self.drill_dia.get_value().replace(',', '.'))
|
dia = float(self.drill_dia.get_value().replace(',', '.'))
|
||||||
self.drill_dia.set_value(dia)
|
self.drill_dia.set_value(dia)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
self.app.inform.emit(_("[WARNING_NOTCL] Tool diameter value is missing or wrong format. "
|
||||||
"Add it and retry.")
|
"Add it and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if dia is '':
|
if dia is '':
|
||||||
self.app.inform.emit("[WARNING_NOTCL]No value or wrong format in Drill Dia entry. Add it and retry.")
|
self.app.inform.emit(_("[WARNING_NOTCL]No value or wrong format in Drill Dia entry. Add it and retry."))
|
||||||
return
|
return
|
||||||
tools = {"1": {"C": dia}}
|
tools = {"1": {"C": dia}}
|
||||||
|
|
||||||
# holes = self.alignment_holes.get_value()
|
# holes = self.alignment_holes.get_value()
|
||||||
holes = eval('[{}]'.format(self.alignment_holes.text()))
|
holes = eval('[{}]'.format(self.alignment_holes.text()))
|
||||||
if not holes:
|
if not holes:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] There are no Alignment Drill Coordinates to use. Add them and retry.")
|
self.app.inform.emit(_("[WARNING_NOTCL] There are no Alignment Drill Coordinates to use. Add them and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
drills = []
|
drills = []
|
||||||
|
@ -372,7 +394,7 @@ class DblSidedTool(FlatCAMTool):
|
||||||
|
|
||||||
self.app.new_object("excellon", "Alignment Drills", obj_init)
|
self.app.new_object("excellon", "Alignment Drills", obj_init)
|
||||||
self.drill_values = ''
|
self.drill_values = ''
|
||||||
self.app.inform.emit("[success] Excellon object with alignment drills created...")
|
self.app.inform.emit(_("[success] Excellon object with alignment drills created..."))
|
||||||
|
|
||||||
def on_mirror_gerber(self):
|
def on_mirror_gerber(self):
|
||||||
selection_index = self.gerber_object_combo.currentIndex()
|
selection_index = self.gerber_object_combo.currentIndex()
|
||||||
|
@ -381,11 +403,11 @@ class DblSidedTool(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
fcobj = model_index.internalPointer().obj
|
fcobj = model_index.internalPointer().obj
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] There is no Gerber object loaded ...")
|
self.app.inform.emit(_("[WARNING_NOTCL] There is no Gerber object loaded ..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if not isinstance(fcobj, FlatCAMGerber):
|
if not isinstance(fcobj, FlatCAMGerber):
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Only Gerber, Excellon and Geometry objects can be mirrored.")
|
self.app.inform.emit(_("[ERROR_NOTCL] Only Gerber, Excellon and Geometry objects can be mirrored."))
|
||||||
return
|
return
|
||||||
|
|
||||||
axis = self.mirror_axis.get_value()
|
axis = self.mirror_axis.get_value()
|
||||||
|
@ -395,8 +417,8 @@ class DblSidedTool(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
px, py = self.point_entry.get_value()
|
px, py = self.point_entry.get_value()
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] 'Point' coordinates missing. "
|
self.app.inform.emit(_("[WARNING_NOTCL] 'Point' coordinates missing. "
|
||||||
"Using Origin (0, 0) as mirroring reference.")
|
"Using Origin (0, 0) as mirroring reference."))
|
||||||
px, py = (0, 0)
|
px, py = (0, 0)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -405,7 +427,7 @@ class DblSidedTool(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
bb_obj = model_index_box.internalPointer().obj
|
bb_obj = model_index_box.internalPointer().obj
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] There is no Box object loaded ...")
|
self.app.inform.emit(_("[WARNING_NOTCL] There is no Box object loaded ..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
xmin, ymin, xmax, ymax = bb_obj.bounds()
|
xmin, ymin, xmax, ymax = bb_obj.bounds()
|
||||||
|
@ -415,7 +437,7 @@ class DblSidedTool(FlatCAMTool):
|
||||||
fcobj.mirror(axis, [px, py])
|
fcobj.mirror(axis, [px, py])
|
||||||
self.app.object_changed.emit(fcobj)
|
self.app.object_changed.emit(fcobj)
|
||||||
fcobj.plot()
|
fcobj.plot()
|
||||||
self.app.inform.emit("[success] Gerber %s was mirrored..." % str(fcobj.options['name']))
|
self.app.inform.emit(_("[success] Gerber %s was mirrored...") % str(fcobj.options['name']))
|
||||||
|
|
||||||
def on_mirror_exc(self):
|
def on_mirror_exc(self):
|
||||||
selection_index = self.exc_object_combo.currentIndex()
|
selection_index = self.exc_object_combo.currentIndex()
|
||||||
|
@ -424,11 +446,11 @@ class DblSidedTool(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
fcobj = model_index.internalPointer().obj
|
fcobj = model_index.internalPointer().obj
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] There is no Excellon object loaded ...")
|
self.app.inform.emit(_("[WARNING_NOTCL] There is no Excellon object loaded ..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if not isinstance(fcobj, FlatCAMExcellon):
|
if not isinstance(fcobj, FlatCAMExcellon):
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Only Gerber, Excellon and Geometry objects can be mirrored.")
|
self.app.inform.emit(_("[ERROR_NOTCL] Only Gerber, Excellon and Geometry objects can be mirrored."))
|
||||||
return
|
return
|
||||||
|
|
||||||
axis = self.mirror_axis.get_value()
|
axis = self.mirror_axis.get_value()
|
||||||
|
@ -439,8 +461,8 @@ class DblSidedTool(FlatCAMTool):
|
||||||
px, py = self.point_entry.get_value()
|
px, py = self.point_entry.get_value()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("DblSidedTool.on_mirror_geo() --> %s" % str(e))
|
log.debug("DblSidedTool.on_mirror_geo() --> %s" % str(e))
|
||||||
self.app.inform.emit("[WARNING_NOTCL] There are no Point coordinates in the Point field. "
|
self.app.inform.emit(_("[WARNING_NOTCL] There are no Point coordinates in the Point field. "
|
||||||
"Add coords and try again ...")
|
"Add coords and try again ..."))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
selection_index_box = self.box_combo.currentIndex()
|
selection_index_box = self.box_combo.currentIndex()
|
||||||
|
@ -449,7 +471,7 @@ class DblSidedTool(FlatCAMTool):
|
||||||
bb_obj = model_index_box.internalPointer().obj
|
bb_obj = model_index_box.internalPointer().obj
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("DblSidedTool.on_mirror_geo() --> %s" % str(e))
|
log.debug("DblSidedTool.on_mirror_geo() --> %s" % str(e))
|
||||||
self.app.inform.emit("[WARNING_NOTCL] There is no Box object loaded ...")
|
self.app.inform.emit(_("[WARNING_NOTCL] There is no Box object loaded ..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
xmin, ymin, xmax, ymax = bb_obj.bounds()
|
xmin, ymin, xmax, ymax = bb_obj.bounds()
|
||||||
|
@ -459,7 +481,7 @@ class DblSidedTool(FlatCAMTool):
|
||||||
fcobj.mirror(axis, [px, py])
|
fcobj.mirror(axis, [px, py])
|
||||||
self.app.object_changed.emit(fcobj)
|
self.app.object_changed.emit(fcobj)
|
||||||
fcobj.plot()
|
fcobj.plot()
|
||||||
self.app.inform.emit("[success] Excellon %s was mirrored..." % str(fcobj.options['name']))
|
self.app.inform.emit(_("[success] Excellon %s was mirrored...") % str(fcobj.options['name']))
|
||||||
|
|
||||||
def on_mirror_geo(self):
|
def on_mirror_geo(self):
|
||||||
selection_index = self.geo_object_combo.currentIndex()
|
selection_index = self.geo_object_combo.currentIndex()
|
||||||
|
@ -468,11 +490,11 @@ class DblSidedTool(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
fcobj = model_index.internalPointer().obj
|
fcobj = model_index.internalPointer().obj
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] There is no Geometry object loaded ...")
|
self.app.inform.emit(_("[WARNING_NOTCL] There is no Geometry object loaded ..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if not isinstance(fcobj, FlatCAMGeometry):
|
if not isinstance(fcobj, FlatCAMGeometry):
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Only Gerber, Excellon and Geometry objects can be mirrored.")
|
self.app.inform.emit(_("[ERROR_NOTCL] Only Gerber, Excellon and Geometry objects can be mirrored."))
|
||||||
return
|
return
|
||||||
|
|
||||||
axis = self.mirror_axis.get_value()
|
axis = self.mirror_axis.get_value()
|
||||||
|
@ -486,7 +508,7 @@ class DblSidedTool(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
bb_obj = model_index_box.internalPointer().obj
|
bb_obj = model_index_box.internalPointer().obj
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] There is no Box object loaded ...")
|
self.app.inform.emit(_("[WARNING_NOTCL] There is no Box object loaded ..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
xmin, ymin, xmax, ymax = bb_obj.bounds()
|
xmin, ymin, xmax, ymax = bb_obj.bounds()
|
||||||
|
@ -496,7 +518,7 @@ class DblSidedTool(FlatCAMTool):
|
||||||
fcobj.mirror(axis, [px, py])
|
fcobj.mirror(axis, [px, py])
|
||||||
self.app.object_changed.emit(fcobj)
|
self.app.object_changed.emit(fcobj)
|
||||||
fcobj.plot()
|
fcobj.plot()
|
||||||
self.app.inform.emit("[success] Geometry %s was mirrored..." % str(fcobj.options['name']))
|
self.app.inform.emit(_("[success] Geometry %s was mirrored...") % str(fcobj.options['name']))
|
||||||
|
|
||||||
def on_point_add(self):
|
def on_point_add(self):
|
||||||
val = self.app.defaults["global_point_clipboard_format"] % (self.app.pos[0], self.app.pos[1])
|
val = self.app.defaults["global_point_clipboard_format"] % (self.app.pos[0], self.app.pos[1])
|
||||||
|
|
|
@ -1,12 +1,28 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
|
|
||||||
from GUIElements import RadioSet, FCEntry
|
from flatcamGUI.GUIElements import RadioSet, FCEntry
|
||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
from PyQt5 import QtGui, QtCore, QtWidgets
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class Film(FlatCAMTool):
|
class Film(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "Film PCB"
|
toolName = _("Film PCB")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
FlatCAMTool.__init__(self, app)
|
FlatCAMTool.__init__(self, app)
|
||||||
|
@ -37,12 +53,12 @@ class Film(FlatCAMTool):
|
||||||
self.tf_type_obj_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png"))
|
self.tf_type_obj_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png"))
|
||||||
self.tf_type_obj_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
self.tf_type_obj_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
||||||
|
|
||||||
self.tf_type_obj_combo_label = QtWidgets.QLabel("Object Type:")
|
self.tf_type_obj_combo_label = QtWidgets.QLabel(_("Object Type:"))
|
||||||
self.tf_type_obj_combo_label.setToolTip(
|
self.tf_type_obj_combo_label.setToolTip(
|
||||||
"Specify the type of object for which to create the film.\n"
|
_("Specify the type of object for which to create the film.\n"
|
||||||
"The object can be of type: Gerber or Geometry.\n"
|
"The object can be of type: Gerber or Geometry.\n"
|
||||||
"The selection here decide the type of objects that will be\n"
|
"The selection here decide the type of objects that will be\n"
|
||||||
"in the Film Object combobox."
|
"in the Film Object combobox.")
|
||||||
)
|
)
|
||||||
tf_form_layout.addRow(self.tf_type_obj_combo_label, self.tf_type_obj_combo)
|
tf_form_layout.addRow(self.tf_type_obj_combo_label, self.tf_type_obj_combo)
|
||||||
|
|
||||||
|
@ -52,9 +68,9 @@ class Film(FlatCAMTool):
|
||||||
self.tf_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
self.tf_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
||||||
self.tf_object_combo.setCurrentIndex(1)
|
self.tf_object_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.tf_object_label = QtWidgets.QLabel("Film Object:")
|
self.tf_object_label = QtWidgets.QLabel(_("Film Object:"))
|
||||||
self.tf_object_label.setToolTip(
|
self.tf_object_label.setToolTip(
|
||||||
"Object for which to create the film."
|
_("Object for which to create the film.")
|
||||||
)
|
)
|
||||||
tf_form_layout.addRow(self.tf_object_label, self.tf_object_combo)
|
tf_form_layout.addRow(self.tf_object_label, self.tf_object_combo)
|
||||||
|
|
||||||
|
@ -70,12 +86,12 @@ class Film(FlatCAMTool):
|
||||||
self.tf_type_box_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png"))
|
self.tf_type_box_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png"))
|
||||||
self.tf_type_box_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
self.tf_type_box_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
||||||
|
|
||||||
self.tf_type_box_combo_label = QtWidgets.QLabel("Box Type:")
|
self.tf_type_box_combo_label = QtWidgets.QLabel(_("Box Type:"))
|
||||||
self.tf_type_box_combo_label.setToolTip(
|
self.tf_type_box_combo_label.setToolTip(
|
||||||
"Specify the type of object to be used as an container for\n"
|
_("Specify the type of object to be used as an container for\n"
|
||||||
"film creation. It can be: Gerber or Geometry type."
|
"film creation. It can be: Gerber or Geometry type."
|
||||||
"The selection here decide the type of objects that will be\n"
|
"The selection here decide the type of objects that will be\n"
|
||||||
"in the Box Object combobox."
|
"in the Box Object combobox.")
|
||||||
)
|
)
|
||||||
tf_form_layout.addRow(self.tf_type_box_combo_label, self.tf_type_box_combo)
|
tf_form_layout.addRow(self.tf_type_box_combo_label, self.tf_type_box_combo)
|
||||||
|
|
||||||
|
@ -85,50 +101,51 @@ class Film(FlatCAMTool):
|
||||||
self.tf_box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
self.tf_box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
||||||
self.tf_box_combo.setCurrentIndex(1)
|
self.tf_box_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.tf_box_combo_label = QtWidgets.QLabel("Box Object:")
|
self.tf_box_combo_label = QtWidgets.QLabel(_("Box Object:"))
|
||||||
self.tf_box_combo_label.setToolTip(
|
self.tf_box_combo_label.setToolTip(
|
||||||
"The actual object that is used a container for the\n "
|
_("The actual object that is used a container for the\n "
|
||||||
"selected object for which we create the film.\n"
|
"selected object for which we create the film.\n"
|
||||||
"Usually it is the PCB outline but it can be also the\n"
|
"Usually it is the PCB outline but it can be also the\n"
|
||||||
"same object for which the film is created.")
|
"same object for which the film is created.")
|
||||||
|
)
|
||||||
tf_form_layout.addRow(self.tf_box_combo_label, self.tf_box_combo)
|
tf_form_layout.addRow(self.tf_box_combo_label, self.tf_box_combo)
|
||||||
|
|
||||||
# Film Type
|
# Film Type
|
||||||
self.film_type = RadioSet([{'label': 'Positive', 'value': 'pos'},
|
self.film_type = RadioSet([{'label': 'Positive', 'value': 'pos'},
|
||||||
{'label': 'Negative', 'value': 'neg'}])
|
{'label': 'Negative', 'value': 'neg'}])
|
||||||
self.film_type_label = QtWidgets.QLabel("Film Type:")
|
self.film_type_label = QtWidgets.QLabel(_("Film Type:"))
|
||||||
self.film_type_label.setToolTip(
|
self.film_type_label.setToolTip(
|
||||||
"Generate a Positive black film or a Negative film.\n"
|
_("Generate a Positive black film or a Negative film.\n"
|
||||||
"Positive means that it will print the features\n"
|
"Positive means that it will print the features\n"
|
||||||
"with black on a white canvas.\n"
|
"with black on a white canvas.\n"
|
||||||
"Negative means that it will print the features\n"
|
"Negative means that it will print the features\n"
|
||||||
"with white on a black canvas.\n"
|
"with white on a black canvas.\n"
|
||||||
"The Film format is SVG."
|
"The Film format is SVG.")
|
||||||
)
|
)
|
||||||
tf_form_layout.addRow(self.film_type_label, self.film_type)
|
tf_form_layout.addRow(self.film_type_label, self.film_type)
|
||||||
|
|
||||||
# Boundary for negative film generation
|
# Boundary for negative film generation
|
||||||
|
|
||||||
self.boundary_entry = FCEntry()
|
self.boundary_entry = FCEntry()
|
||||||
self.boundary_label = QtWidgets.QLabel("Border:")
|
self.boundary_label = QtWidgets.QLabel(_("Border:"))
|
||||||
self.boundary_label.setToolTip(
|
self.boundary_label.setToolTip(
|
||||||
"Specify a border around the object.\n"
|
_("Specify a border around the object.\n"
|
||||||
"Only for negative film.\n"
|
"Only for negative film.\n"
|
||||||
"It helps if we use as a Box Object the same \n"
|
"It helps if we use as a Box Object the same \n"
|
||||||
"object as in Film Object. It will create a thick\n"
|
"object as in Film Object. It will create a thick\n"
|
||||||
"black bar around the actual print allowing for a\n"
|
"black bar around the actual print allowing for a\n"
|
||||||
"better delimitation of the outline features which are of\n"
|
"better delimitation of the outline features which are of\n"
|
||||||
"white color like the rest and which may confound with the\n"
|
"white color like the rest and which may confound with the\n"
|
||||||
"surroundings if not for this border."
|
"surroundings if not for this border.")
|
||||||
)
|
)
|
||||||
tf_form_layout.addRow(self.boundary_label, self.boundary_entry)
|
tf_form_layout.addRow(self.boundary_label, self.boundary_entry)
|
||||||
|
|
||||||
self.film_scale_entry = FCEntry()
|
self.film_scale_entry = FCEntry()
|
||||||
self.film_scale_label = QtWidgets.QLabel("Scale Stroke:")
|
self.film_scale_label = QtWidgets.QLabel(_("Scale Stroke:"))
|
||||||
self.film_scale_label.setToolTip(
|
self.film_scale_label.setToolTip(
|
||||||
"Scale the line stroke thickness of each feature in the SVG file.\n"
|
_("Scale the line stroke thickness of each feature in the SVG file.\n"
|
||||||
"It means that the line that envelope each SVG feature will be thicker or thinner,\n"
|
"It means that the line that envelope each SVG feature will be thicker or thinner,\n"
|
||||||
"therefore the fine features may be more affected by this parameter."
|
"therefore the fine features may be more affected by this parameter.")
|
||||||
)
|
)
|
||||||
tf_form_layout.addRow(self.film_scale_label, self.film_scale_entry)
|
tf_form_layout.addRow(self.film_scale_label, self.film_scale_entry)
|
||||||
|
|
||||||
|
@ -137,12 +154,12 @@ class Film(FlatCAMTool):
|
||||||
self.layout.addLayout(hlay)
|
self.layout.addLayout(hlay)
|
||||||
hlay.addStretch()
|
hlay.addStretch()
|
||||||
|
|
||||||
self.film_object_button = QtWidgets.QPushButton("Save Film")
|
self.film_object_button = QtWidgets.QPushButton(_("Save Film"))
|
||||||
self.film_object_button.setToolTip(
|
self.film_object_button.setToolTip(
|
||||||
"Create a Film for the selected object, within\n"
|
_("Create a Film for the selected object, within\n"
|
||||||
"the specified box. Does not create a new \n "
|
"the specified box. Does not create a new \n "
|
||||||
"FlatCAM object, but directly save it in SVG format\n"
|
"FlatCAM object, but directly save it in SVG format\n"
|
||||||
"which can be opened with Inkscape."
|
"which can be opened with Inkscape.")
|
||||||
)
|
)
|
||||||
hlay.addWidget(self.film_object_button)
|
hlay.addWidget(self.film_object_button)
|
||||||
|
|
||||||
|
@ -163,23 +180,28 @@ class Film(FlatCAMTool):
|
||||||
self.tf_box_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
|
self.tf_box_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
|
||||||
self.tf_box_combo.setCurrentIndex(0)
|
self.tf_box_combo.setCurrentIndex(0)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolFilm()")
|
self.app.report_usage("ToolFilm()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
|
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
|
||||||
self.app.ui.notebook.setTabText(2, "Film Tool")
|
self.app.ui.notebook.setTabText(2, _("Film Tool"))
|
||||||
|
|
||||||
def install(self, icon=None, separator=None, **kwargs):
|
def install(self, icon=None, separator=None, **kwargs):
|
||||||
FlatCAMTool.install(self, icon, separator, shortcut='ALT+L', **kwargs)
|
FlatCAMTool.install(self, icon, separator, shortcut='ALT+L', **kwargs)
|
||||||
|
@ -190,7 +212,7 @@ class Film(FlatCAMTool):
|
||||||
f_type = self.app.defaults["tools_film_type"] if self.app.defaults["tools_film_type"] else 'neg'
|
f_type = self.app.defaults["tools_film_type"] if self.app.defaults["tools_film_type"] else 'neg'
|
||||||
self.film_type.set_value(str(f_type))
|
self.film_type.set_value(str(f_type))
|
||||||
|
|
||||||
b_entry = self.app.defaults[ "tools_film_boundary"] if self.app.defaults[ "tools_film_boundary"] else 0.0
|
b_entry = self.app.defaults["tools_film_boundary"] if self.app.defaults["tools_film_boundary"] else 0.0
|
||||||
self.boundary_entry.set_value(float(b_entry))
|
self.boundary_entry.set_value(float(b_entry))
|
||||||
|
|
||||||
scale_stroke_width = self.app.defaults["tools_film_scale"] if self.app.defaults["tools_film_scale"] else 0.0
|
scale_stroke_width = self.app.defaults["tools_film_scale"] if self.app.defaults["tools_film_scale"] else 0.0
|
||||||
|
@ -200,13 +222,13 @@ class Film(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
name = self.tf_object_combo.currentText()
|
name = self.tf_object_combo.currentText()
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] No FlatCAM object selected. Load an object for Film and retry.")
|
self.app.inform.emit(_("[ERROR_NOTCL] No FlatCAM object selected. Load an object for Film and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
boxname = self.tf_box_combo.currentText()
|
boxname = self.tf_box_combo.currentText()
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] No FlatCAM object selected. Load an object for Box and retry.")
|
self.app.inform.emit(_("[ERROR_NOTCL] No FlatCAM object selected. Load an object for Box and retry."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -216,51 +238,51 @@ class Film(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
border = float(self.boundary_entry.get_value().replace(',', '.'))
|
border = float(self.boundary_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
scale_stroke_width = int(self.film_scale_entry.get_value())
|
scale_stroke_width = int(self.film_scale_entry.get_value())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if border is None:
|
if border is None:
|
||||||
border = 0
|
border = 0
|
||||||
|
|
||||||
self.app.inform.emit("Generating Film ...")
|
self.app.inform.emit(_("Generating Film ..."))
|
||||||
|
|
||||||
if self.film_type.get_value() == "pos":
|
if self.film_type.get_value() == "pos":
|
||||||
try:
|
try:
|
||||||
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(
|
||||||
caption="Export SVG positive",
|
caption=_("Export SVG positive"),
|
||||||
directory=self.app.get_last_save_folder() + '/' + name,
|
directory=self.app.get_last_save_folder() + '/' + name,
|
||||||
filter="*.svg")
|
filter="*.svg")
|
||||||
except TypeError:
|
except TypeError:
|
||||||
filename, _ = QtWidgets.QFileDialog.getSaveFileName(caption="Export SVG positive")
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export SVG positive"))
|
||||||
|
|
||||||
filename = str(filename)
|
filename = str(filename)
|
||||||
|
|
||||||
if str(filename) == "":
|
if str(filename) == "":
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Export SVG positive cancelled.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Export SVG positive cancelled."))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.app.export_svg_black(name, boxname, filename, scale_factor=scale_stroke_width)
|
self.app.export_svg_black(name, boxname, filename, scale_factor=scale_stroke_width)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(
|
||||||
caption="Export SVG negative",
|
caption=_("Export SVG negative"),
|
||||||
directory=self.app.get_last_save_folder() + '/' + name,
|
directory=self.app.get_last_save_folder() + '/' + name,
|
||||||
filter="*.svg")
|
filter="*.svg")
|
||||||
except TypeError:
|
except TypeError:
|
||||||
filename, _ = QtWidgets.QFileDialog.getSaveFileName(caption="Export SVG negative")
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export SVG negative"))
|
||||||
|
|
||||||
filename = str(filename)
|
filename = str(filename)
|
||||||
|
|
||||||
if str(filename) == "":
|
if str(filename) == "":
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Export SVG negative cancelled.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Export SVG negative cancelled."))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.app.export_svg_negative(name, boxname, filename, border, scale_factor=scale_stroke_width)
|
self.app.export_svg_negative(name, boxname, filename, border, scale_factor=scale_stroke_width)
|
||||||
|
|
|
@ -1,18 +1,34 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
|
|
||||||
from GUIElements import RadioSet, FloatEntry, FCComboBox, IntEntry
|
from flatcamGUI.GUIElements import RadioSet, FCComboBox, IntEntry
|
||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
from PyQt5 import QtGui, QtWidgets
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class ToolImage(FlatCAMTool):
|
class ToolImage(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "Image as Object"
|
toolName = _("Image as Object")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
FlatCAMTool.__init__(self, app)
|
FlatCAMTool.__init__(self, app)
|
||||||
|
|
||||||
# Title
|
# Title
|
||||||
title_label = QtWidgets.QLabel("%s" % 'Image to PCB')
|
title_label = QtWidgets.QLabel("%s" % _('Image to PCB'))
|
||||||
title_label.setStyleSheet("""
|
title_label.setStyleSheet("""
|
||||||
QLabel
|
QLabel
|
||||||
{
|
{
|
||||||
|
@ -34,26 +50,26 @@ class ToolImage(FlatCAMTool):
|
||||||
self.tf_type_obj_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png"))
|
self.tf_type_obj_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png"))
|
||||||
self.tf_type_obj_combo.setItemIcon(1, QtGui.QIcon("share/geometry16.png"))
|
self.tf_type_obj_combo.setItemIcon(1, QtGui.QIcon("share/geometry16.png"))
|
||||||
|
|
||||||
self.tf_type_obj_combo_label = QtWidgets.QLabel("Object Type:")
|
self.tf_type_obj_combo_label = QtWidgets.QLabel(_("Object Type:"))
|
||||||
self.tf_type_obj_combo_label.setToolTip(
|
self.tf_type_obj_combo_label.setToolTip(
|
||||||
"Specify the type of object to create from the image.\n"
|
_( "Specify the type of object to create from the image.\n"
|
||||||
"It can be of type: Gerber or Geometry."
|
"It can be of type: Gerber or Geometry.")
|
||||||
|
|
||||||
)
|
)
|
||||||
ti_form_layout.addRow(self.tf_type_obj_combo_label, self.tf_type_obj_combo)
|
ti_form_layout.addRow(self.tf_type_obj_combo_label, self.tf_type_obj_combo)
|
||||||
|
|
||||||
# DPI value of the imported image
|
# DPI value of the imported image
|
||||||
self.dpi_entry = IntEntry()
|
self.dpi_entry = IntEntry()
|
||||||
self.dpi_label = QtWidgets.QLabel("DPI value:")
|
self.dpi_label = QtWidgets.QLabel(_("DPI value:"))
|
||||||
self.dpi_label.setToolTip(
|
self.dpi_label.setToolTip(
|
||||||
"Specify a DPI value for the image."
|
_( "Specify a DPI value for the image.")
|
||||||
)
|
)
|
||||||
ti_form_layout.addRow(self.dpi_label, self.dpi_entry)
|
ti_form_layout.addRow(self.dpi_label, self.dpi_entry)
|
||||||
|
|
||||||
self.emty_lbl = QtWidgets.QLabel("")
|
self.emty_lbl = QtWidgets.QLabel("")
|
||||||
self.layout.addWidget(self.emty_lbl)
|
self.layout.addWidget(self.emty_lbl)
|
||||||
|
|
||||||
self.detail_label = QtWidgets.QLabel("<font size=4><b>Level of detail:</b>")
|
self.detail_label = QtWidgets.QLabel("<font size=4><b>%s:</b>" % _('Level of detail'))
|
||||||
self.layout.addWidget(self.detail_label)
|
self.layout.addWidget(self.detail_label)
|
||||||
|
|
||||||
ti2_form_layout = QtWidgets.QFormLayout()
|
ti2_form_layout = QtWidgets.QFormLayout()
|
||||||
|
@ -62,56 +78,56 @@ class ToolImage(FlatCAMTool):
|
||||||
# Type of image interpretation
|
# Type of image interpretation
|
||||||
self.image_type = RadioSet([{'label': 'B/W', 'value': 'black'},
|
self.image_type = RadioSet([{'label': 'B/W', 'value': 'black'},
|
||||||
{'label': 'Color', 'value': 'color'}])
|
{'label': 'Color', 'value': 'color'}])
|
||||||
self.image_type_label = QtWidgets.QLabel("<b>Image type:</b>")
|
self.image_type_label = QtWidgets.QLabel("<b>%s:</b>" % _('Image type'))
|
||||||
self.image_type_label.setToolTip(
|
self.image_type_label.setToolTip(
|
||||||
"Choose a method for the image interpretation.\n"
|
_("Choose a method for the image interpretation.\n"
|
||||||
"B/W means a black & white image. Color means a colored image."
|
"B/W means a black & white image. Color means a colored image.")
|
||||||
)
|
)
|
||||||
ti2_form_layout.addRow(self.image_type_label, self.image_type)
|
ti2_form_layout.addRow(self.image_type_label, self.image_type)
|
||||||
|
|
||||||
# Mask value of the imported image when image monochrome
|
# Mask value of the imported image when image monochrome
|
||||||
self.mask_bw_entry = IntEntry()
|
self.mask_bw_entry = IntEntry()
|
||||||
self.mask_bw_label = QtWidgets.QLabel("Mask value <b>B/W</b>:")
|
self.mask_bw_label = QtWidgets.QLabel("%s <b>B/W</b>:" % _('Mask value'))
|
||||||
self.mask_bw_label.setToolTip(
|
self.mask_bw_label.setToolTip(
|
||||||
"Mask for monochrome image.\n"
|
_("Mask for monochrome image.\n"
|
||||||
"Takes values between [0 ... 255].\n"
|
"Takes values between [0 ... 255].\n"
|
||||||
"Decides the level of details to include\n"
|
"Decides the level of details to include\n"
|
||||||
"in the resulting geometry.\n"
|
"in the resulting geometry.\n"
|
||||||
"0 means no detail and 255 means everything \n"
|
"0 means no detail and 255 means everything \n"
|
||||||
"(which is totally black)."
|
"(which is totally black).")
|
||||||
)
|
)
|
||||||
ti2_form_layout.addRow(self.mask_bw_label, self.mask_bw_entry)
|
ti2_form_layout.addRow(self.mask_bw_label, self.mask_bw_entry)
|
||||||
|
|
||||||
# Mask value of the imported image for RED color when image color
|
# Mask value of the imported image for RED color when image color
|
||||||
self.mask_r_entry = IntEntry()
|
self.mask_r_entry = IntEntry()
|
||||||
self.mask_r_label = QtWidgets.QLabel("Mask value <b>R:</b>")
|
self.mask_r_label = QtWidgets.QLabel("%s <b>R:</b>" % _('Mask value'))
|
||||||
self.mask_r_label.setToolTip(
|
self.mask_r_label.setToolTip(
|
||||||
"Mask for RED color.\n"
|
_("Mask for RED color.\n"
|
||||||
"Takes values between [0 ... 255].\n"
|
"Takes values between [0 ... 255].\n"
|
||||||
"Decides the level of details to include\n"
|
"Decides the level of details to include\n"
|
||||||
"in the resulting geometry."
|
"in the resulting geometry.")
|
||||||
)
|
)
|
||||||
ti2_form_layout.addRow(self.mask_r_label, self.mask_r_entry)
|
ti2_form_layout.addRow(self.mask_r_label, self.mask_r_entry)
|
||||||
|
|
||||||
# Mask value of the imported image for GREEN color when image color
|
# Mask value of the imported image for GREEN color when image color
|
||||||
self.mask_g_entry = IntEntry()
|
self.mask_g_entry = IntEntry()
|
||||||
self.mask_g_label = QtWidgets.QLabel("Mask value <b>G:</b>")
|
self.mask_g_label = QtWidgets.QLabel("%s <b>G:</b>" % _('Mask value'))
|
||||||
self.mask_g_label.setToolTip(
|
self.mask_g_label.setToolTip(
|
||||||
"Mask for GREEN color.\n"
|
_("Mask for GREEN color.\n"
|
||||||
"Takes values between [0 ... 255].\n"
|
"Takes values between [0 ... 255].\n"
|
||||||
"Decides the level of details to include\n"
|
"Decides the level of details to include\n"
|
||||||
"in the resulting geometry."
|
"in the resulting geometry.")
|
||||||
)
|
)
|
||||||
ti2_form_layout.addRow(self.mask_g_label, self.mask_g_entry)
|
ti2_form_layout.addRow(self.mask_g_label, self.mask_g_entry)
|
||||||
|
|
||||||
# Mask value of the imported image for BLUE color when image color
|
# Mask value of the imported image for BLUE color when image color
|
||||||
self.mask_b_entry = IntEntry()
|
self.mask_b_entry = IntEntry()
|
||||||
self.mask_b_label = QtWidgets.QLabel("Mask value <b>B:</b>")
|
self.mask_b_label = QtWidgets.QLabel("%s <b>B:</b>" % _('Mask value'))
|
||||||
self.mask_b_label.setToolTip(
|
self.mask_b_label.setToolTip(
|
||||||
"Mask for BLUE color.\n"
|
_("Mask for BLUE color.\n"
|
||||||
"Takes values between [0 ... 255].\n"
|
"Takes values between [0 ... 255].\n"
|
||||||
"Decides the level of details to include\n"
|
"Decides the level of details to include\n"
|
||||||
"in the resulting geometry."
|
"in the resulting geometry.")
|
||||||
)
|
)
|
||||||
ti2_form_layout.addRow(self.mask_b_label, self.mask_b_entry)
|
ti2_form_layout.addRow(self.mask_b_label, self.mask_b_entry)
|
||||||
|
|
||||||
|
@ -120,9 +136,9 @@ class ToolImage(FlatCAMTool):
|
||||||
self.layout.addLayout(hlay)
|
self.layout.addLayout(hlay)
|
||||||
hlay.addStretch()
|
hlay.addStretch()
|
||||||
|
|
||||||
self.import_button = QtWidgets.QPushButton("Import image")
|
self.import_button = QtWidgets.QPushButton(_("Import image"))
|
||||||
self.import_button.setToolTip(
|
self.import_button.setToolTip(
|
||||||
"Open a image of raster type and then import it in FlatCAM."
|
_("Open a image of raster type and then import it in FlatCAM.")
|
||||||
)
|
)
|
||||||
hlay.addWidget(self.import_button)
|
hlay.addWidget(self.import_button)
|
||||||
|
|
||||||
|
@ -131,23 +147,27 @@ class ToolImage(FlatCAMTool):
|
||||||
## Signals
|
## Signals
|
||||||
self.import_button.clicked.connect(self.on_file_importimage)
|
self.import_button.clicked.connect(self.on_file_importimage)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolImage()")
|
self.app.report_usage("ToolImage()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
|
||||||
self.app.ui.notebook.setTabText(2, "Image Tool")
|
self.app.ui.notebook.setTabText(2, _("Image Tool"))
|
||||||
|
|
||||||
def install(self, icon=None, separator=None, **kwargs):
|
def install(self, icon=None, separator=None, **kwargs):
|
||||||
FlatCAMTool.install(self, icon, separator, **kwargs)
|
FlatCAMTool.install(self, icon, separator, **kwargs)
|
||||||
|
@ -177,10 +197,10 @@ class ToolImage(FlatCAMTool):
|
||||||
"Jpeg File (*.JPG);;" \
|
"Jpeg File (*.JPG);;" \
|
||||||
"All Files (*.*)"
|
"All Files (*.*)"
|
||||||
try:
|
try:
|
||||||
filename, _ = QtWidgets.QFileDialog.getOpenFileName(caption="Import IMAGE",
|
filename, _f = QtWidgets.QFileDialog.getOpenFileName(caption=_("Import IMAGE"),
|
||||||
directory=self.app.get_last_folder(), filter=filter)
|
directory=self.app.get_last_folder(), filter=filter)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
filename, _ = QtWidgets.QFileDialog.getOpenFileName(caption="Import IMAGE", filter=filter)
|
filename, _f = QtWidgets.QFileDialog.getOpenFileName(caption=_("Import IMAGE"), filter=filter)
|
||||||
|
|
||||||
filename = str(filename)
|
filename = str(filename)
|
||||||
type = self.tf_type_obj_combo.get_value().lower()
|
type = self.tf_type_obj_combo.get_value().lower()
|
||||||
|
@ -190,7 +210,7 @@ class ToolImage(FlatCAMTool):
|
||||||
self.mask_b_entry.get_value()]
|
self.mask_b_entry.get_value()]
|
||||||
|
|
||||||
if filename == "":
|
if filename == "":
|
||||||
self.app.inform.emit("Open cancelled.")
|
self.app.inform.emit(_("Open cancelled."))
|
||||||
else:
|
else:
|
||||||
self.app.worker_task.emit({'fcn': self.app.import_image,
|
self.app.worker_task.emit({'fcn': self.app.import_image,
|
||||||
'params': [filename, type, dpi, mode, mask]})
|
'params': [filename, type, dpi, mode, mask]})
|
||||||
|
|
|
@ -1,13 +1,29 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from FlatCAMObj import *
|
from FlatCAMObj import *
|
||||||
from VisPyVisuals import *
|
from flatcamGUI.VisPyVisuals import *
|
||||||
|
|
||||||
from copy import copy
|
|
||||||
from math import sqrt
|
from math import sqrt
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class Measurement(FlatCAMTool):
|
class Measurement(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "Measurement"
|
toolName = _("Measurement")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
FlatCAMTool.__init__(self, app)
|
FlatCAMTool.__init__(self, app)
|
||||||
|
@ -28,51 +44,51 @@ class Measurement(FlatCAMTool):
|
||||||
form_layout_child_2 = QtWidgets.QFormLayout()
|
form_layout_child_2 = QtWidgets.QFormLayout()
|
||||||
form_layout_child_3 = QtWidgets.QFormLayout()
|
form_layout_child_3 = QtWidgets.QFormLayout()
|
||||||
|
|
||||||
self.start_label = QtWidgets.QLabel("<b>Start</b> Coords:")
|
self.start_label = QtWidgets.QLabel("<b>%s</b> %s:" % (_('Start'), _('Coords')))
|
||||||
self.start_label.setToolTip("This is measuring Start point coordinates.")
|
self.start_label.setToolTip(_("This is measuring Start point coordinates."))
|
||||||
|
|
||||||
self.stop_label = QtWidgets.QLabel("<b>Stop</b> Coords:")
|
self.stop_label = QtWidgets.QLabel("<b>%s</b> %s:" % (_('Stop'), _('Coords')))
|
||||||
self.stop_label.setToolTip("This is the measuring Stop point coordinates.")
|
self.stop_label.setToolTip(_("This is the measuring Stop point coordinates."))
|
||||||
|
|
||||||
self.distance_x_label = QtWidgets.QLabel("Dx:")
|
self.distance_x_label = QtWidgets.QLabel("Dx:")
|
||||||
self.distance_x_label.setToolTip("This is the distance measured over the X axis.")
|
self.distance_x_label.setToolTip(_("This is the distance measured over the X axis."))
|
||||||
|
|
||||||
self.distance_y_label = QtWidgets.QLabel("Dy:")
|
self.distance_y_label = QtWidgets.QLabel("Dy:")
|
||||||
self.distance_y_label.setToolTip("This is the distance measured over the Y axis.")
|
self.distance_y_label.setToolTip(_("This is the distance measured over the Y axis."))
|
||||||
|
|
||||||
self.total_distance_label = QtWidgets.QLabel("<b>DISTANCE:</b>")
|
self.total_distance_label = QtWidgets.QLabel("<b>%s:</b>" % _('DISTANCE'))
|
||||||
self.total_distance_label.setToolTip("This is the point to point Euclidian distance.")
|
self.total_distance_label.setToolTip(_("This is the point to point Euclidian distance."))
|
||||||
|
|
||||||
self.units_entry_1 = FCEntry()
|
self.units_entry_1 = FCEntry()
|
||||||
self.units_entry_1.setToolTip("Those are the units in which the distance is measured.")
|
self.units_entry_1.setToolTip(_("Those are the units in which the distance is measured."))
|
||||||
self.units_entry_1.setDisabled(True)
|
self.units_entry_1.setDisabled(True)
|
||||||
self.units_entry_1.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.units_entry_1.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.units_entry_1.setFrame(False)
|
self.units_entry_1.setFrame(False)
|
||||||
self.units_entry_1.setFixedWidth(30)
|
self.units_entry_1.setFixedWidth(30)
|
||||||
|
|
||||||
self.units_entry_2 = FCEntry()
|
self.units_entry_2 = FCEntry()
|
||||||
self.units_entry_2.setToolTip("Those are the units in which the distance is measured.")
|
self.units_entry_2.setToolTip(_("Those are the units in which the distance is measured."))
|
||||||
self.units_entry_2.setDisabled(True)
|
self.units_entry_2.setDisabled(True)
|
||||||
self.units_entry_2.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.units_entry_2.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.units_entry_2.setFrame(False)
|
self.units_entry_2.setFrame(False)
|
||||||
self.units_entry_2.setFixedWidth(30)
|
self.units_entry_2.setFixedWidth(30)
|
||||||
|
|
||||||
self.units_entry_3 = FCEntry()
|
self.units_entry_3 = FCEntry()
|
||||||
self.units_entry_3.setToolTip("Those are the units in which the distance is measured.")
|
self.units_entry_3.setToolTip(_("Those are the units in which the distance is measured."))
|
||||||
self.units_entry_3.setDisabled(True)
|
self.units_entry_3.setDisabled(True)
|
||||||
self.units_entry_3.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.units_entry_3.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.units_entry_3.setFrame(False)
|
self.units_entry_3.setFrame(False)
|
||||||
self.units_entry_3.setFixedWidth(30)
|
self.units_entry_3.setFixedWidth(30)
|
||||||
|
|
||||||
self.units_entry_4 = FCEntry()
|
self.units_entry_4 = FCEntry()
|
||||||
self.units_entry_4.setToolTip("Those are the units in which the distance is measured.")
|
self.units_entry_4.setToolTip(_("Those are the units in which the distance is measured."))
|
||||||
self.units_entry_4.setDisabled(True)
|
self.units_entry_4.setDisabled(True)
|
||||||
self.units_entry_4.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.units_entry_4.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.units_entry_4.setFrame(False)
|
self.units_entry_4.setFrame(False)
|
||||||
self.units_entry_4.setFixedWidth(30)
|
self.units_entry_4.setFixedWidth(30)
|
||||||
|
|
||||||
self.units_entry_5 = FCEntry()
|
self.units_entry_5 = FCEntry()
|
||||||
self.units_entry_5.setToolTip("Those are the units in which the distance is measured.")
|
self.units_entry_5.setToolTip(_("Those are the units in which the distance is measured."))
|
||||||
self.units_entry_5.setDisabled(True)
|
self.units_entry_5.setDisabled(True)
|
||||||
self.units_entry_5.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.units_entry_5.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.units_entry_5.setFrame(False)
|
self.units_entry_5.setFrame(False)
|
||||||
|
@ -80,32 +96,32 @@ class Measurement(FlatCAMTool):
|
||||||
|
|
||||||
self.start_entry = FCEntry()
|
self.start_entry = FCEntry()
|
||||||
self.start_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.start_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.start_entry.setToolTip("This is measuring Start point coordinates.")
|
self.start_entry.setToolTip(_("This is measuring Start point coordinates."))
|
||||||
self.start_entry.setFixedWidth(100)
|
self.start_entry.setFixedWidth(100)
|
||||||
|
|
||||||
self.stop_entry = FCEntry()
|
self.stop_entry = FCEntry()
|
||||||
self.stop_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.stop_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.stop_entry.setToolTip("This is the measuring Stop point coordinates.")
|
self.stop_entry.setToolTip(_("This is the measuring Stop point coordinates."))
|
||||||
self.stop_entry.setFixedWidth(100)
|
self.stop_entry.setFixedWidth(100)
|
||||||
|
|
||||||
self.distance_x_entry = FCEntry()
|
self.distance_x_entry = FCEntry()
|
||||||
self.distance_x_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.distance_x_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.distance_x_entry.setToolTip("This is the distance measured over the X axis.")
|
self.distance_x_entry.setToolTip(_("This is the distance measured over the X axis."))
|
||||||
self.distance_x_entry.setFixedWidth(100)
|
self.distance_x_entry.setFixedWidth(100)
|
||||||
|
|
||||||
|
|
||||||
self.distance_y_entry = FCEntry()
|
self.distance_y_entry = FCEntry()
|
||||||
self.distance_y_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.distance_y_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.distance_y_entry.setToolTip("This is the distance measured over the Y axis.")
|
self.distance_y_entry.setToolTip(_("This is the distance measured over the Y axis."))
|
||||||
self.distance_y_entry.setFixedWidth(100)
|
self.distance_y_entry.setFixedWidth(100)
|
||||||
|
|
||||||
|
|
||||||
self.total_distance_entry = FCEntry()
|
self.total_distance_entry = FCEntry()
|
||||||
self.total_distance_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.total_distance_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
self.total_distance_entry.setToolTip("This is the point to point Euclidian distance.")
|
self.total_distance_entry.setToolTip(_("This is the point to point Euclidian distance."))
|
||||||
self.total_distance_entry.setFixedWidth(100)
|
self.total_distance_entry.setFixedWidth(100)
|
||||||
|
|
||||||
self.measure_btn = QtWidgets.QPushButton("Measure")
|
self.measure_btn = QtWidgets.QPushButton(_("Measure"))
|
||||||
self.measure_btn.setFixedWidth(70)
|
self.measure_btn.setFixedWidth(70)
|
||||||
self.layout.addWidget(self.measure_btn)
|
self.layout.addWidget(self.measure_btn)
|
||||||
|
|
||||||
|
@ -149,17 +165,22 @@ class Measurement(FlatCAMTool):
|
||||||
# VisPy visuals
|
# VisPy visuals
|
||||||
self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.vispy_canvas.view.scene, layers=1)
|
self.sel_shapes = ShapeCollection(parent=self.app.plotcanvas.vispy_canvas.view.scene, layers=1)
|
||||||
|
|
||||||
self.measure_btn.clicked.connect(self.toggle)
|
self.measure_btn.clicked.connect(self.toggle_f)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=False):
|
||||||
self.app.report_usage("ToolMeasurement()")
|
self.app.report_usage("ToolMeasurement()")
|
||||||
|
|
||||||
if self.app.tool_tab_locked is True:
|
if self.app.tool_tab_locked is True:
|
||||||
return
|
return
|
||||||
self.toggle()
|
|
||||||
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
|
||||||
|
self.toggle_f()
|
||||||
|
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
self.app.ui.notebook.setTabText(2, "Meas. Tool")
|
self.app.ui.notebook.setTabText(2, _("Meas. Tool"))
|
||||||
|
|
||||||
def install(self, icon=None, separator=None, **kwargs):
|
def install(self, icon=None, separator=None, **kwargs):
|
||||||
FlatCAMTool.install(self, icon, separator, shortcut='CTRL+M', **kwargs)
|
FlatCAMTool.install(self, icon, separator, shortcut='CTRL+M', **kwargs)
|
||||||
|
@ -176,11 +197,12 @@ class Measurement(FlatCAMTool):
|
||||||
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
|
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().lower()
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
def toggle(self):
|
def toggle_f(self):
|
||||||
# the self.active var is doing the 'toggle'
|
# the self.active var is doing the 'toggle'
|
||||||
if self.active is True:
|
if self.active is True:
|
||||||
# DISABLE the Measuring TOOL
|
# DISABLE the Measuring TOOL
|
||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
# disconnect the mouse/key events from functions of measurement tool
|
# disconnect the mouse/key events from functions of measurement tool
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move_meas)
|
self.app.plotcanvas.vis_disconnect('mouse_move', self.on_mouse_move_meas)
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_press', self.on_click_meas)
|
self.app.plotcanvas.vis_disconnect('mouse_press', self.on_click_meas)
|
||||||
|
@ -202,6 +224,7 @@ class Measurement(FlatCAMTool):
|
||||||
self.app.exc_editor.canvas.vis_connect('key_press', self.app.exc_editor.on_canvas_key)
|
self.app.exc_editor.canvas.vis_connect('key_press', self.app.exc_editor.on_canvas_key)
|
||||||
self.app.exc_editor.canvas.vis_connect('mouse_release', self.app.exc_editor.on_canvas_click_release)
|
self.app.exc_editor.canvas.vis_connect('mouse_release', self.app.exc_editor.on_canvas_click_release)
|
||||||
|
|
||||||
|
self.app.call_source = 'measurement'
|
||||||
self.clicked_meas = 0
|
self.clicked_meas = 0
|
||||||
self.app.command_active = None
|
self.app.command_active = None
|
||||||
# delete the measuring line
|
# delete the measuring line
|
||||||
|
@ -250,7 +273,7 @@ class Measurement(FlatCAMTool):
|
||||||
self.units_entry_4.set_value(str(self.units))
|
self.units_entry_4.set_value(str(self.units))
|
||||||
self.units_entry_5.set_value(str(self.units))
|
self.units_entry_5.set_value(str(self.units))
|
||||||
|
|
||||||
self.app.inform.emit("MEASURING: Click on the Start point ...")
|
self.app.inform.emit(_("MEASURING: Click on the Start point ..."))
|
||||||
|
|
||||||
def on_key_release_meas(self, event):
|
def on_key_release_meas(self, event):
|
||||||
if event.key == 'escape':
|
if event.key == 'escape':
|
||||||
|
@ -279,7 +302,7 @@ class Measurement(FlatCAMTool):
|
||||||
pos = pos_canvas[0], pos_canvas[1]
|
pos = pos_canvas[0], pos_canvas[1]
|
||||||
self.point1 = pos
|
self.point1 = pos
|
||||||
self.start_entry.set_value("(%.4f, %.4f)" % pos)
|
self.start_entry.set_value("(%.4f, %.4f)" % pos)
|
||||||
self.app.inform.emit("MEASURING: Click on the Destination point ...")
|
self.app.inform.emit(_("MEASURING: Click on the Destination point ..."))
|
||||||
|
|
||||||
if self.clicked_meas == 1:
|
if self.clicked_meas == 1:
|
||||||
try:
|
try:
|
||||||
|
@ -300,15 +323,15 @@ class Measurement(FlatCAMTool):
|
||||||
|
|
||||||
self.stop_entry.set_value("(%.4f, %.4f)" % pos)
|
self.stop_entry.set_value("(%.4f, %.4f)" % pos)
|
||||||
|
|
||||||
self.app.inform.emit("MEASURING: Result D(x) = %.4f | D(y) = %.4f | Distance = %.4f" %
|
self.app.inform.emit(_("MEASURING: Result D(x) = {d_x} | D(y) = {d_y} | Distance = {d_z}").format(
|
||||||
(abs(dx), abs(dy), abs(d)))
|
d_x='%4f' % abs(dx), d_y='%4f' % abs(dy), d_z='%4f' % abs(d)))
|
||||||
|
|
||||||
self.distance_x_entry.set_value('%.4f' % abs(dx))
|
self.distance_x_entry.set_value('%.4f' % abs(dx))
|
||||||
self.distance_y_entry.set_value('%.4f' % abs(dy))
|
self.distance_y_entry.set_value('%.4f' % abs(dy))
|
||||||
self.total_distance_entry.set_value('%.4f' % abs(d))
|
self.total_distance_entry.set_value('%.4f' % abs(d))
|
||||||
|
|
||||||
self.clicked_meas = 0
|
self.clicked_meas = 0
|
||||||
self.toggle()
|
self.toggle_f()
|
||||||
|
|
||||||
# delete the measuring line
|
# delete the measuring line
|
||||||
self.delete_shape()
|
self.delete_shape()
|
||||||
|
|
|
@ -1,14 +1,29 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from FlatCAMObj import *
|
from FlatCAMObj import *
|
||||||
from VisPyVisuals import *
|
from flatcamGUI.VisPyVisuals import *
|
||||||
|
|
||||||
from io import StringIO
|
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class ToolMove(FlatCAMTool):
|
class ToolMove(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "Move"
|
toolName = _("Move")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
FlatCAMTool.__init__(self, app)
|
FlatCAMTool.__init__(self, app)
|
||||||
|
@ -33,14 +48,14 @@ class ToolMove(FlatCAMTool):
|
||||||
def install(self, icon=None, separator=None, **kwargs):
|
def install(self, icon=None, separator=None, **kwargs):
|
||||||
FlatCAMTool.install(self, icon, separator, shortcut='M', **kwargs)
|
FlatCAMTool.install(self, icon, separator, shortcut='M', **kwargs)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle):
|
||||||
self.app.report_usage("ToolMove()")
|
self.app.report_usage("ToolMove()")
|
||||||
|
|
||||||
if self.app.tool_tab_locked is True:
|
if self.app.tool_tab_locked is True:
|
||||||
return
|
return
|
||||||
self.toggle()
|
self.toggle()
|
||||||
|
|
||||||
def toggle(self):
|
def toggle(self, toggle=False):
|
||||||
if self.isVisible():
|
if self.isVisible():
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
|
||||||
|
@ -63,14 +78,14 @@ class ToolMove(FlatCAMTool):
|
||||||
self.app.command_active = "Move"
|
self.app.command_active = "Move"
|
||||||
|
|
||||||
if self.app.collection.get_selected():
|
if self.app.collection.get_selected():
|
||||||
self.app.inform.emit("MOVE: Click on the Start point ...")
|
self.app.inform.emit(_("MOVE: Click on the Start point ..."))
|
||||||
# draw the selection box
|
# draw the selection box
|
||||||
self.draw_sel_bbox()
|
self.draw_sel_bbox()
|
||||||
else:
|
else:
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
# signal that there is no command active
|
# signal that there is no command active
|
||||||
self.app.command_active = None
|
self.app.command_active = None
|
||||||
self.app.inform.emit("[WARNING_NOTCL]MOVE action cancelled. No object(s) to move.")
|
self.app.inform.emit(_("[WARNING_NOTCL] MOVE action cancelled. No object(s) to move."))
|
||||||
|
|
||||||
def on_left_click(self, event):
|
def on_left_click(self, event):
|
||||||
# mouse click will be accepted only if the left button is clicked
|
# mouse click will be accepted only if the left button is clicked
|
||||||
|
@ -92,7 +107,7 @@ class ToolMove(FlatCAMTool):
|
||||||
else:
|
else:
|
||||||
self.point2 = copy(self.point1)
|
self.point2 = copy(self.point1)
|
||||||
self.point1 = pos
|
self.point1 = pos
|
||||||
self.app.inform.emit("MOVE: Click on the Destination point ...")
|
self.app.inform.emit(_("MOVE: Click on the Destination point ..."))
|
||||||
|
|
||||||
if self.clicked_move == 1:
|
if self.clicked_move == 1:
|
||||||
try:
|
try:
|
||||||
|
@ -110,14 +125,14 @@ class ToolMove(FlatCAMTool):
|
||||||
dx = pos[0] - self.point1[0]
|
dx = pos[0] - self.point1[0]
|
||||||
dy = pos[1] - self.point1[1]
|
dy = pos[1] - self.point1[1]
|
||||||
|
|
||||||
proc = self.app.proc_container.new("Moving ...")
|
proc = self.app.proc_container.new(_("Moving ..."))
|
||||||
|
|
||||||
def job_move(app_obj):
|
def job_move(app_obj):
|
||||||
obj_list = self.app.collection.get_selected()
|
obj_list = self.app.collection.get_selected()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] No object(s) selected.")
|
self.app.inform.emit(_("[WARNING_NOTCL] No object(s) selected."))
|
||||||
return "fail"
|
return "fail"
|
||||||
else:
|
else:
|
||||||
for sel_obj in obj_list:
|
for sel_obj in obj_list:
|
||||||
|
@ -140,13 +155,13 @@ class ToolMove(FlatCAMTool):
|
||||||
# self.app.collection.set_active(sel_obj.options['name'])
|
# self.app.collection.set_active(sel_obj.options['name'])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
proc.done()
|
proc.done()
|
||||||
self.app.inform.emit('[ERROR_NOTCL] '
|
self.app.inform.emit(_('[ERROR_NOTCL] '
|
||||||
'ToolMove.on_left_click() --> %s' % str(e))
|
'ToolMove.on_left_click() --> %s') % str(e))
|
||||||
return "fail"
|
return "fail"
|
||||||
proc.done()
|
proc.done()
|
||||||
# delete the selection bounding box
|
# delete the selection bounding box
|
||||||
self.delete_shape()
|
self.delete_shape()
|
||||||
self.app.inform.emit('[success]%s object was moved ...' %
|
self.app.inform.emit(_('[success]%s object was moved ...') %
|
||||||
str(sel_obj.kind).capitalize())
|
str(sel_obj.kind).capitalize())
|
||||||
|
|
||||||
self.app.worker_task.emit({'fcn': job_move, 'params': [self]})
|
self.app.worker_task.emit({'fcn': job_move, 'params': [self]})
|
||||||
|
@ -156,8 +171,8 @@ class ToolMove(FlatCAMTool):
|
||||||
return
|
return
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] '
|
self.app.inform.emit(_('[ERROR_NOTCL] '
|
||||||
'ToolMove.on_left_click() --> Error when mouse left click.')
|
'ToolMove.on_left_click() --> Error when mouse left click.'))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.clicked_move = 1
|
self.clicked_move = 1
|
||||||
|
@ -184,7 +199,7 @@ class ToolMove(FlatCAMTool):
|
||||||
def on_key_press(self, event):
|
def on_key_press(self, event):
|
||||||
if event.key == 'escape':
|
if event.key == 'escape':
|
||||||
# abort the move action
|
# abort the move action
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Move action cancelled.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Move action cancelled."))
|
||||||
self.toggle()
|
self.toggle()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -196,7 +211,7 @@ class ToolMove(FlatCAMTool):
|
||||||
|
|
||||||
obj_list = self.app.collection.get_selected()
|
obj_list = self.app.collection.get_selected()
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Object(s) not selected")
|
self.app.inform.emit(_("[WARNING_NOTCL]Object(s) not selected"))
|
||||||
self.toggle()
|
self.toggle()
|
||||||
else:
|
else:
|
||||||
# if we have an object selected then we can safely activate the mouse events
|
# if we have an object selected then we can safely activate the mouse events
|
||||||
|
|
|
@ -1,12 +1,28 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Modified by: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from copy import copy,deepcopy
|
from copy import copy,deepcopy
|
||||||
from ObjectCollection import *
|
from ObjectCollection import *
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class NonCopperClear(FlatCAMTool, Gerber):
|
class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
|
|
||||||
toolName = "Non-Copper Clearing"
|
toolName = _("Non-Copper Clearing")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
self.app = app
|
self.app = app
|
||||||
|
@ -44,7 +60,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
|
|
||||||
self.object_label = QtWidgets.QLabel("Gerber:")
|
self.object_label = QtWidgets.QLabel("Gerber:")
|
||||||
self.object_label.setToolTip(
|
self.object_label.setToolTip(
|
||||||
"Gerber object to be cleared of excess copper. "
|
_("Gerber object to be cleared of excess copper. ")
|
||||||
)
|
)
|
||||||
e_lab_0 = QtWidgets.QLabel('')
|
e_lab_0 = QtWidgets.QLabel('')
|
||||||
|
|
||||||
|
@ -52,10 +68,10 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
form_layout.addRow(e_lab_0)
|
form_layout.addRow(e_lab_0)
|
||||||
|
|
||||||
#### Tools ####
|
#### Tools ####
|
||||||
self.tools_table_label = QtWidgets.QLabel('<b>Tools Table</b>')
|
self.tools_table_label = QtWidgets.QLabel('<b>%s</b>' % _('Tools Table'))
|
||||||
self.tools_table_label.setToolTip(
|
self.tools_table_label.setToolTip(
|
||||||
"Tools pool from which the algorithm\n"
|
_("Tools pool from which the algorithm\n"
|
||||||
"will pick the ones used for copper clearing."
|
"will pick the ones used for copper clearing.")
|
||||||
)
|
)
|
||||||
self.tools_box.addWidget(self.tools_table_label)
|
self.tools_box.addWidget(self.tools_table_label)
|
||||||
|
|
||||||
|
@ -63,25 +79,25 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
self.tools_box.addWidget(self.tools_table)
|
self.tools_box.addWidget(self.tools_table)
|
||||||
|
|
||||||
self.tools_table.setColumnCount(4)
|
self.tools_table.setColumnCount(4)
|
||||||
self.tools_table.setHorizontalHeaderLabels(['#', 'Diameter', 'TT', ''])
|
self.tools_table.setHorizontalHeaderLabels(['#', _('Diameter'), 'TT', ''])
|
||||||
self.tools_table.setColumnHidden(3, True)
|
self.tools_table.setColumnHidden(3, True)
|
||||||
self.tools_table.setSortingEnabled(False)
|
self.tools_table.setSortingEnabled(False)
|
||||||
# self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
# self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||||
|
|
||||||
self.tools_table.horizontalHeaderItem(0).setToolTip(
|
self.tools_table.horizontalHeaderItem(0).setToolTip(
|
||||||
"This is the Tool Number.\n"
|
_("This is the Tool Number.\n"
|
||||||
"Non copper clearing will start with the tool with the biggest \n"
|
"Non copper clearing will start with the tool with the biggest \n"
|
||||||
"diameter, continuing until there are no more tools.\n"
|
"diameter, continuing until there are no more tools.\n"
|
||||||
"Only tools that create NCC clearing geometry will still be present\n"
|
"Only tools that create NCC clearing geometry will still be present\n"
|
||||||
"in the resulting geometry. This is because with some tools\n"
|
"in the resulting geometry. This is because with some tools\n"
|
||||||
"this function will not be able to create painting geometry."
|
"this function will not be able to create painting geometry.")
|
||||||
)
|
)
|
||||||
self.tools_table.horizontalHeaderItem(1).setToolTip(
|
self.tools_table.horizontalHeaderItem(1).setToolTip(
|
||||||
"Tool Diameter. It's value (in current FlatCAM units) \n"
|
_("Tool Diameter. It's value (in current FlatCAM units) \n"
|
||||||
"is the cut width into the material.")
|
"is the cut width into the material."))
|
||||||
|
|
||||||
self.tools_table.horizontalHeaderItem(2).setToolTip(
|
self.tools_table.horizontalHeaderItem(2).setToolTip(
|
||||||
"The Tool Type (TT) can be:<BR>"
|
_("The Tool Type (TT) can be:<BR>"
|
||||||
"- <B>Circular</B> with 1 ... 4 teeth -> it is informative only. Being circular, <BR>"
|
"- <B>Circular</B> with 1 ... 4 teeth -> it is informative only. Being circular, <BR>"
|
||||||
"the cut width in material is exactly the tool diameter.<BR>"
|
"the cut width in material is exactly the tool diameter.<BR>"
|
||||||
"- <B>Ball</B> -> informative only and make reference to the Ball type endmill.<BR>"
|
"- <B>Ball</B> -> informative only and make reference to the Ball type endmill.<BR>"
|
||||||
|
@ -91,7 +107,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
"as the cut width into material will be equal with the value in the Tool Diameter "
|
"as the cut width into material will be equal with the value in the Tool Diameter "
|
||||||
"column of this table.<BR>"
|
"column of this table.<BR>"
|
||||||
"Choosing the <B>V-Shape</B> Tool Type automatically will select the Operation Type "
|
"Choosing the <B>V-Shape</B> Tool Type automatically will select the Operation Type "
|
||||||
"in the resulting geometry as Isolation.")
|
"in the resulting geometry as Isolation."))
|
||||||
|
|
||||||
self.empty_label = QtWidgets.QLabel('')
|
self.empty_label = QtWidgets.QLabel('')
|
||||||
self.tools_box.addWidget(self.empty_label)
|
self.tools_box.addWidget(self.empty_label)
|
||||||
|
@ -100,9 +116,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
hlay = QtWidgets.QHBoxLayout()
|
hlay = QtWidgets.QHBoxLayout()
|
||||||
self.tools_box.addLayout(hlay)
|
self.tools_box.addLayout(hlay)
|
||||||
|
|
||||||
self.addtool_entry_lbl = QtWidgets.QLabel('<b>Tool Dia:</b>')
|
self.addtool_entry_lbl = QtWidgets.QLabel('<b>%s:</b>' % _('Tool Dia'))
|
||||||
self.addtool_entry_lbl.setToolTip(
|
self.addtool_entry_lbl.setToolTip(
|
||||||
"Diameter for the new tool to add in the Tool Table"
|
_("Diameter for the new tool to add in the Tool Table")
|
||||||
)
|
)
|
||||||
self.addtool_entry = FCEntry()
|
self.addtool_entry = FCEntry()
|
||||||
|
|
||||||
|
@ -114,10 +130,10 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
grid2 = QtWidgets.QGridLayout()
|
grid2 = QtWidgets.QGridLayout()
|
||||||
self.tools_box.addLayout(grid2)
|
self.tools_box.addLayout(grid2)
|
||||||
|
|
||||||
self.addtool_btn = QtWidgets.QPushButton('Add')
|
self.addtool_btn = QtWidgets.QPushButton(_('Add'))
|
||||||
self.addtool_btn.setToolTip(
|
self.addtool_btn.setToolTip(
|
||||||
"Add a new tool to the Tool Table\n"
|
_("Add a new tool to the Tool Table\n"
|
||||||
"with the diameter specified above."
|
"with the diameter specified above.")
|
||||||
)
|
)
|
||||||
|
|
||||||
# self.copytool_btn = QtWidgets.QPushButton('Copy')
|
# self.copytool_btn = QtWidgets.QPushButton('Copy')
|
||||||
|
@ -126,10 +142,10 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
# "by first selecting a row in the Tool Table."
|
# "by first selecting a row in the Tool Table."
|
||||||
# )
|
# )
|
||||||
|
|
||||||
self.deltool_btn = QtWidgets.QPushButton('Delete')
|
self.deltool_btn = QtWidgets.QPushButton(_('Delete'))
|
||||||
self.deltool_btn.setToolTip(
|
self.deltool_btn.setToolTip(
|
||||||
"Delete a selection of tools in the Tool Table\n"
|
_("Delete a selection of tools in the Tool Table\n"
|
||||||
"by first selecting a row(s) in the Tool Table."
|
"by first selecting a row(s) in the Tool Table.")
|
||||||
)
|
)
|
||||||
|
|
||||||
grid2.addWidget(self.addtool_btn, 0, 0)
|
grid2.addWidget(self.addtool_btn, 0, 0)
|
||||||
|
@ -145,9 +161,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
e_lab_1 = QtWidgets.QLabel('')
|
e_lab_1 = QtWidgets.QLabel('')
|
||||||
grid3.addWidget(e_lab_1, 0, 0)
|
grid3.addWidget(e_lab_1, 0, 0)
|
||||||
|
|
||||||
nccoverlabel = QtWidgets.QLabel('Overlap:')
|
nccoverlabel = QtWidgets.QLabel(_('Overlap:'))
|
||||||
nccoverlabel.setToolTip(
|
nccoverlabel.setToolTip(
|
||||||
"How much (fraction) of the tool width to overlap each tool pass.\n"
|
_("How much (fraction) of the tool width to overlap each tool pass.\n"
|
||||||
"Example:\n"
|
"Example:\n"
|
||||||
"A value here of 0.25 means 25% from the tool diameter found above.\n\n"
|
"A value here of 0.25 means 25% from the tool diameter found above.\n\n"
|
||||||
"Adjust the value starting with lower values\n"
|
"Adjust the value starting with lower values\n"
|
||||||
|
@ -155,27 +171,27 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
"not cleared.\n"
|
"not cleared.\n"
|
||||||
"Lower values = faster processing, faster execution on PCB.\n"
|
"Lower values = faster processing, faster execution on PCB.\n"
|
||||||
"Higher values = slow processing and slow execution on CNC\n"
|
"Higher values = slow processing and slow execution on CNC\n"
|
||||||
"due of too many paths."
|
"due of too many paths.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(nccoverlabel, 1, 0)
|
grid3.addWidget(nccoverlabel, 1, 0)
|
||||||
self.ncc_overlap_entry = FCEntry()
|
self.ncc_overlap_entry = FCEntry()
|
||||||
grid3.addWidget(self.ncc_overlap_entry, 1, 1)
|
grid3.addWidget(self.ncc_overlap_entry, 1, 1)
|
||||||
|
|
||||||
nccmarginlabel = QtWidgets.QLabel('Margin:')
|
nccmarginlabel = QtWidgets.QLabel(_('Margin:'))
|
||||||
nccmarginlabel.setToolTip(
|
nccmarginlabel.setToolTip(
|
||||||
"Bounding box margin."
|
_("Bounding box margin.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(nccmarginlabel, 2, 0)
|
grid3.addWidget(nccmarginlabel, 2, 0)
|
||||||
self.ncc_margin_entry = FCEntry()
|
self.ncc_margin_entry = FCEntry()
|
||||||
grid3.addWidget(self.ncc_margin_entry, 2, 1)
|
grid3.addWidget(self.ncc_margin_entry, 2, 1)
|
||||||
|
|
||||||
# Method
|
# Method
|
||||||
methodlabel = QtWidgets.QLabel('Method:')
|
methodlabel = QtWidgets.QLabel(_('Method:'))
|
||||||
methodlabel.setToolTip(
|
methodlabel.setToolTip(
|
||||||
"Algorithm for non-copper clearing:<BR>"
|
_("Algorithm for non-copper clearing:<BR>"
|
||||||
"<B>Standard</B>: Fixed step inwards.<BR>"
|
"<B>Standard</B>: Fixed step inwards.<BR>"
|
||||||
"<B>Seed-based</B>: Outwards from seed.<BR>"
|
"<B>Seed-based</B>: Outwards from seed.<BR>"
|
||||||
"<B>Line-based</B>: Parallel lines."
|
"<B>Line-based</B>: Parallel lines.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(methodlabel, 3, 0)
|
grid3.addWidget(methodlabel, 3, 0)
|
||||||
self.ncc_method_radio = RadioSet([
|
self.ncc_method_radio = RadioSet([
|
||||||
|
@ -186,42 +202,42 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
grid3.addWidget(self.ncc_method_radio, 3, 1)
|
grid3.addWidget(self.ncc_method_radio, 3, 1)
|
||||||
|
|
||||||
# Connect lines
|
# Connect lines
|
||||||
pathconnectlabel = QtWidgets.QLabel("Connect:")
|
pathconnectlabel = QtWidgets.QLabel(_("Connect:"))
|
||||||
pathconnectlabel.setToolTip(
|
pathconnectlabel.setToolTip(
|
||||||
"Draw lines between resulting\n"
|
_("Draw lines between resulting\n"
|
||||||
"segments to minimize tool lifts."
|
"segments to minimize tool lifts.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(pathconnectlabel, 4, 0)
|
grid3.addWidget(pathconnectlabel, 4, 0)
|
||||||
self.ncc_connect_cb = FCCheckBox()
|
self.ncc_connect_cb = FCCheckBox()
|
||||||
grid3.addWidget(self.ncc_connect_cb, 4, 1)
|
grid3.addWidget(self.ncc_connect_cb, 4, 1)
|
||||||
|
|
||||||
contourlabel = QtWidgets.QLabel("Contour:")
|
contourlabel = QtWidgets.QLabel(_("Contour:"))
|
||||||
contourlabel.setToolTip(
|
contourlabel.setToolTip(
|
||||||
"Cut around the perimeter of the polygon\n"
|
_("Cut around the perimeter of the polygon\n"
|
||||||
"to trim rough edges."
|
"to trim rough edges.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(contourlabel, 5, 0)
|
grid3.addWidget(contourlabel, 5, 0)
|
||||||
self.ncc_contour_cb = FCCheckBox()
|
self.ncc_contour_cb = FCCheckBox()
|
||||||
grid3.addWidget(self.ncc_contour_cb, 5, 1)
|
grid3.addWidget(self.ncc_contour_cb, 5, 1)
|
||||||
|
|
||||||
restlabel = QtWidgets.QLabel("Rest M.:")
|
restlabel = QtWidgets.QLabel(_("Rest M.:"))
|
||||||
restlabel.setToolTip(
|
restlabel.setToolTip(
|
||||||
"If checked, use 'rest machining'.\n"
|
_("If checked, use 'rest machining'.\n"
|
||||||
"Basically it will clear copper outside PCB features,\n"
|
"Basically it will clear copper outside PCB features,\n"
|
||||||
"using the biggest tool and continue with the next tools,\n"
|
"using the biggest tool and continue with the next tools,\n"
|
||||||
"from bigger to smaller, to clear areas of copper that\n"
|
"from bigger to smaller, to clear areas of copper that\n"
|
||||||
"could not be cleared by previous tool, until there is\n"
|
"could not be cleared by previous tool, until there is\n"
|
||||||
"no more copper to clear or there are no more tools.\n"
|
"no more copper to clear or there are no more tools.\n"
|
||||||
"If not checked, use the standard algorithm."
|
"If not checked, use the standard algorithm.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(restlabel, 6, 0)
|
grid3.addWidget(restlabel, 6, 0)
|
||||||
self.ncc_rest_cb = FCCheckBox()
|
self.ncc_rest_cb = FCCheckBox()
|
||||||
grid3.addWidget(self.ncc_rest_cb, 6, 1)
|
grid3.addWidget(self.ncc_rest_cb, 6, 1)
|
||||||
|
|
||||||
self.generate_ncc_button = QtWidgets.QPushButton('Generate Geometry')
|
self.generate_ncc_button = QtWidgets.QPushButton(_('Generate Geometry'))
|
||||||
self.generate_ncc_button.setToolTip(
|
self.generate_ncc_button.setToolTip(
|
||||||
"Create the Geometry Object\n"
|
_("Create the Geometry Object\n"
|
||||||
"for non-copper routing."
|
"for non-copper routing.")
|
||||||
)
|
)
|
||||||
self.tools_box.addWidget(self.generate_ncc_button)
|
self.tools_box.addWidget(self.generate_ncc_button)
|
||||||
|
|
||||||
|
@ -243,24 +259,28 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
def install(self, icon=None, separator=None, **kwargs):
|
def install(self, icon=None, separator=None, **kwargs):
|
||||||
FlatCAMTool.install(self, icon, separator, shortcut='ALT+N', **kwargs)
|
FlatCAMTool.install(self, icon, separator, shortcut='ALT+N', **kwargs)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolNonCopperClear()")
|
self.app.report_usage("ToolNonCopperClear()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
self.app.ui.notebook.setTabText(2, "NCC Tool")
|
self.app.ui.notebook.setTabText(2, _("NCC Tool"))
|
||||||
|
|
||||||
def set_tool_ui(self):
|
def set_tool_ui(self):
|
||||||
self.tools_frame.show()
|
self.tools_frame.show()
|
||||||
|
@ -455,16 +475,16 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
|
tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
if tool_dia is None:
|
if tool_dia is None:
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Please enter a tool diameter to add, in Float format.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Please enter a tool diameter to add, in Float format."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if tool_dia == 0:
|
if tool_dia == 0:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, in Float format.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, in Float format."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# construct a list of all 'tooluid' in the self.tools
|
# construct a list of all 'tooluid' in the self.tools
|
||||||
|
@ -488,12 +508,12 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
|
|
||||||
if float('%.4f' % tool_dia) in tool_dias:
|
if float('%.4f' % tool_dia) in tool_dias:
|
||||||
if muted is None:
|
if muted is None:
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Adding tool cancelled. Tool already in Tool Table.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Adding tool cancelled. Tool already in Tool Table."))
|
||||||
self.tools_table.itemChanged.connect(self.on_tool_edit)
|
self.tools_table.itemChanged.connect(self.on_tool_edit)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
if muted is None:
|
if muted is None:
|
||||||
self.app.inform.emit("[success] New tool added to Tool Table.")
|
self.app.inform.emit(_("[success] New tool added to Tool Table."))
|
||||||
self.ncc_tools.update({
|
self.ncc_tools.update({
|
||||||
int(self.tooluid): {
|
int(self.tooluid): {
|
||||||
'tooldia': float('%.4f' % tool_dia),
|
'tooldia': float('%.4f' % tool_dia),
|
||||||
|
@ -526,8 +546,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.'))
|
new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
tooluid = int(self.tools_table.item(row, 3).text())
|
tooluid = int(self.tools_table.item(row, 3).text())
|
||||||
|
@ -535,7 +555,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
# identify the tool that was edited and get it's tooluid
|
# identify the tool that was edited and get it's tooluid
|
||||||
if new_tool_dia not in tool_dias:
|
if new_tool_dia not in tool_dias:
|
||||||
self.ncc_tools[tooluid]['tooldia'] = new_tool_dia
|
self.ncc_tools[tooluid]['tooldia'] = new_tool_dia
|
||||||
self.app.inform.emit("[success] Tool from Tool Table was edited.")
|
self.app.inform.emit(_("[success] Tool from Tool Table was edited."))
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -546,7 +566,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
break
|
break
|
||||||
restore_dia_item = self.tools_table.item(row, 1)
|
restore_dia_item = self.tools_table.item(row, 1)
|
||||||
restore_dia_item.setText(str(old_tool_dia))
|
restore_dia_item.setText(str(old_tool_dia))
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Edit cancelled. New diameter value is already in the Tool Table.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Edit cancelled. New diameter value is already in the Tool Table."))
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
|
|
||||||
def on_tool_delete(self, rows_to_delete=None, all=None):
|
def on_tool_delete(self, rows_to_delete=None, all=None):
|
||||||
|
@ -585,12 +605,12 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
self.ncc_tools.pop(t, None)
|
self.ncc_tools.pop(t, None)
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Delete failed. Select a tool to delete.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Delete failed. Select a tool to delete."))
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug(str(e))
|
log.debug(str(e))
|
||||||
|
|
||||||
self.app.inform.emit("[success] Tool(s) deleted from Tool Table.")
|
self.app.inform.emit(_("[success] Tool(s) deleted from Tool Table."))
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
|
|
||||||
def on_ncc(self):
|
def on_ncc(self):
|
||||||
|
@ -602,8 +622,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
over = float(self.ncc_overlap_entry.get_value().replace(',', '.'))
|
over = float(self.ncc_overlap_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
over = over if over else self.app.defaults["tools_nccoverlap"]
|
over = over if over else self.app.defaults["tools_nccoverlap"]
|
||||||
|
|
||||||
|
@ -614,8 +634,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
margin = float(self.ncc_margin_entry.get_value().replace(',', '.'))
|
margin = float(self.ncc_margin_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
margin = margin if margin else self.app.defaults["tools_nccmargin"]
|
margin = margin if margin else self.app.defaults["tools_nccmargin"]
|
||||||
|
|
||||||
|
@ -636,14 +656,14 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
self.ncc_obj = self.app.collection.get_by_name(self.obj_name)
|
self.ncc_obj = self.app.collection.get_by_name(self.obj_name)
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Could not retrieve object: %s" % self.obj_name)
|
self.app.inform.emit(_("[ERROR_NOTCL]Could not retrieve object: %s") % self.obj_name)
|
||||||
return "Could not retrieve object: %s" % self.obj_name
|
return "Could not retrieve object: %s" % self.obj_name
|
||||||
|
|
||||||
# Prepare non-copper polygons
|
# Prepare non-copper polygons
|
||||||
try:
|
try:
|
||||||
bounding_box = self.ncc_obj.solid_geometry.envelope.buffer(distance=margin, join_style=JOIN_STYLE.mitre)
|
bounding_box = self.ncc_obj.solid_geometry.envelope.buffer(distance=margin, join_style=JOIN_STYLE.mitre)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]No Gerber file available.")
|
self.app.inform.emit(_("[ERROR_NOTCL]No Gerber file available."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# calculate the empty area by subtracting the solid_geometry from the object bounding box geometry
|
# calculate the empty area by subtracting the solid_geometry from the object bounding box geometry
|
||||||
|
@ -681,7 +701,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
sorted_tools.sort(reverse=True)
|
sorted_tools.sort(reverse=True)
|
||||||
|
|
||||||
# Do job in background
|
# Do job in background
|
||||||
proc = self.app.proc_container.new("Clearing Non-Copper areas.")
|
proc = self.app.proc_container.new(_("Clearing Non-Copper areas."))
|
||||||
|
|
||||||
def initialize(geo_obj, app_obj):
|
def initialize(geo_obj, app_obj):
|
||||||
assert isinstance(geo_obj, FlatCAMGeometry), \
|
assert isinstance(geo_obj, FlatCAMGeometry), \
|
||||||
|
@ -699,7 +719,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
current_uid = int(1)
|
current_uid = int(1)
|
||||||
|
|
||||||
for tool in sorted_tools:
|
for tool in sorted_tools:
|
||||||
self.app.inform.emit('[success] Non-Copper Clearing with ToolDia = %s started.' % str(tool))
|
self.app.inform.emit(_('[success] Non-Copper Clearing with ToolDia = %s started.') % str(tool))
|
||||||
cleared_geo[:] = []
|
cleared_geo[:] = []
|
||||||
|
|
||||||
# Get remaining tools offset
|
# Get remaining tools offset
|
||||||
|
@ -768,22 +788,22 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
app_obj.new_object("geometry", name, initialize)
|
app_obj.new_object("geometry", name, initialize)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
proc.done()
|
proc.done()
|
||||||
self.app.inform.emit('[ERROR_NOTCL] NCCTool.clear_non_copper() --> %s' % str(e))
|
self.app.inform.emit(_('[ERROR_NOTCL] NCCTool.clear_non_copper() --> %s') % str(e))
|
||||||
return
|
return
|
||||||
proc.done()
|
proc.done()
|
||||||
|
|
||||||
if app_obj.poly_not_cleared is False:
|
if app_obj.poly_not_cleared is False:
|
||||||
self.app.inform.emit('[success] NCC Tool finished.')
|
self.app.inform.emit(_('[success] NCC Tool finished.'))
|
||||||
else:
|
else:
|
||||||
self.app.inform.emit('[WARNING_NOTCL] NCC Tool finished but some PCB features could not be cleared. '
|
self.app.inform.emit(_('[WARNING_NOTCL] NCC Tool finished but some PCB features could not be cleared. '
|
||||||
'Check the result.')
|
'Check the result.'))
|
||||||
# reset the variable for next use
|
# reset the variable for next use
|
||||||
app_obj.poly_not_cleared = False
|
app_obj.poly_not_cleared = False
|
||||||
|
|
||||||
# focus on Selected Tab
|
# focus on Selected Tab
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
||||||
self.tools_frame.hide()
|
self.tools_frame.hide()
|
||||||
self.app.ui.notebook.setTabText(2, "Tools")
|
self.app.ui.notebook.setTabText(2, _("Tools"))
|
||||||
|
|
||||||
# Promise object with the new name
|
# Promise object with the new name
|
||||||
self.app.collection.promise(name)
|
self.app.collection.promise(name)
|
||||||
|
@ -803,7 +823,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
sorted_tools.sort(reverse=True)
|
sorted_tools.sort(reverse=True)
|
||||||
|
|
||||||
# Do job in background
|
# Do job in background
|
||||||
proc = self.app.proc_container.new("Clearing Non-Copper areas.")
|
proc = self.app.proc_container.new(_("Clearing Non-Copper areas."))
|
||||||
|
|
||||||
def initialize_rm(geo_obj, app_obj):
|
def initialize_rm(geo_obj, app_obj):
|
||||||
assert isinstance(geo_obj, FlatCAMGeometry), \
|
assert isinstance(geo_obj, FlatCAMGeometry), \
|
||||||
|
@ -821,7 +841,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
# Generate area for each tool
|
# Generate area for each tool
|
||||||
while sorted_tools:
|
while sorted_tools:
|
||||||
tool = sorted_tools.pop(0)
|
tool = sorted_tools.pop(0)
|
||||||
self.app.inform.emit('[success] Non-Copper Rest Clearing with ToolDia = %s started.' % str(tool))
|
self.app.inform.emit(_('[success] Non-Copper Rest Clearing with ToolDia = %s started.') % str(tool))
|
||||||
|
|
||||||
tool_used = tool - 1e-12
|
tool_used = tool - 1e-12
|
||||||
cleared_geo[:] = []
|
cleared_geo[:] = []
|
||||||
|
@ -919,7 +939,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
app_obj.new_object("geometry", name, initialize_rm)
|
app_obj.new_object("geometry", name, initialize_rm)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
proc.done()
|
proc.done()
|
||||||
self.app.inform.emit('[ERROR_NOTCL] NCCTool.clear_non_copper_rest() --> %s' % str(e))
|
self.app.inform.emit(_('[ERROR_NOTCL] NCCTool.clear_non_copper_rest() --> %s') % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
if app_obj.poly_not_cleared is True:
|
if app_obj.poly_not_cleared is True:
|
||||||
|
@ -927,8 +947,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
|
||||||
# focus on Selected Tab
|
# focus on Selected Tab
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
||||||
else:
|
else:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] NCC Tool finished but could not clear the object '
|
self.app.inform.emit(_('[ERROR_NOTCL] NCC Tool finished but could not clear the object '
|
||||||
'with current settings.')
|
'with current settings.'))
|
||||||
# focus on Project Tab
|
# focus on Project Tab
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
||||||
proc.done()
|
proc.done()
|
||||||
|
|
|
@ -1,11 +1,27 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Modified: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from copy import copy,deepcopy
|
from copy import copy,deepcopy
|
||||||
from ObjectCollection import *
|
from ObjectCollection import *
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class ToolPaint(FlatCAMTool, Gerber):
|
class ToolPaint(FlatCAMTool, Gerber):
|
||||||
|
|
||||||
toolName = "Paint Area"
|
toolName = _("Paint Area")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
self.app = app
|
self.app = app
|
||||||
|
@ -41,19 +57,19 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
self.object_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
|
self.object_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
|
||||||
self.object_combo.setCurrentIndex(1)
|
self.object_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.object_label = QtWidgets.QLabel("Geometry:")
|
self.object_label = QtWidgets.QLabel(_("Geometry:"))
|
||||||
self.object_label.setToolTip(
|
self.object_label.setToolTip(
|
||||||
"Geometry object to be painted. "
|
_("Geometry object to be painted. ")
|
||||||
)
|
)
|
||||||
e_lab_0 = QtWidgets.QLabel('')
|
e_lab_0 = QtWidgets.QLabel('')
|
||||||
form_layout.addRow(self.object_label, self.object_combo)
|
form_layout.addRow(self.object_label, self.object_combo)
|
||||||
form_layout.addRow(e_lab_0)
|
form_layout.addRow(e_lab_0)
|
||||||
|
|
||||||
#### Tools ####
|
#### Tools ####
|
||||||
self.tools_table_label = QtWidgets.QLabel('<b>Tools Table</b>')
|
self.tools_table_label = QtWidgets.QLabel('<b>%s</b>' % _('Tools Table'))
|
||||||
self.tools_table_label.setToolTip(
|
self.tools_table_label.setToolTip(
|
||||||
"Tools pool from which the algorithm\n"
|
_("Tools pool from which the algorithm\n"
|
||||||
"will pick the ones used for painting."
|
"will pick the ones used for painting.")
|
||||||
)
|
)
|
||||||
self.tools_box.addWidget(self.tools_table_label)
|
self.tools_box.addWidget(self.tools_table_label)
|
||||||
|
|
||||||
|
@ -61,25 +77,25 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
self.tools_box.addWidget(self.tools_table)
|
self.tools_box.addWidget(self.tools_table)
|
||||||
|
|
||||||
self.tools_table.setColumnCount(4)
|
self.tools_table.setColumnCount(4)
|
||||||
self.tools_table.setHorizontalHeaderLabels(['#', 'Diameter', 'TT', ''])
|
self.tools_table.setHorizontalHeaderLabels(['#', _('Diameter'), 'TT', ''])
|
||||||
self.tools_table.setColumnHidden(3, True)
|
self.tools_table.setColumnHidden(3, True)
|
||||||
# self.tools_table.setSortingEnabled(False)
|
# self.tools_table.setSortingEnabled(False)
|
||||||
# self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
# self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||||
|
|
||||||
self.tools_table.horizontalHeaderItem(0).setToolTip(
|
self.tools_table.horizontalHeaderItem(0).setToolTip(
|
||||||
"This is the Tool Number.\n"
|
_("This is the Tool Number.\n"
|
||||||
"Painting will start with the tool with the biggest diameter,\n"
|
"Painting will start with the tool with the biggest diameter,\n"
|
||||||
"continuing until there are no more tools.\n"
|
"continuing until there are no more tools.\n"
|
||||||
"Only tools that create painting geometry will still be present\n"
|
"Only tools that create painting geometry will still be present\n"
|
||||||
"in the resulting geometry. This is because with some tools\n"
|
"in the resulting geometry. This is because with some tools\n"
|
||||||
"this function will not be able to create painting geometry."
|
"this function will not be able to create painting geometry.")
|
||||||
)
|
)
|
||||||
self.tools_table.horizontalHeaderItem(1).setToolTip(
|
self.tools_table.horizontalHeaderItem(1).setToolTip(
|
||||||
"Tool Diameter. It's value (in current FlatCAM units) \n"
|
_("Tool Diameter. It's value (in current FlatCAM units) \n"
|
||||||
"is the cut width into the material.")
|
"is the cut width into the material."))
|
||||||
|
|
||||||
self.tools_table.horizontalHeaderItem(2).setToolTip(
|
self.tools_table.horizontalHeaderItem(2).setToolTip(
|
||||||
"The Tool Type (TT) can be:<BR>"
|
_("The Tool Type (TT) can be:<BR>"
|
||||||
"- <B>Circular</B> with 1 ... 4 teeth -> it is informative only. Being circular, <BR>"
|
"- <B>Circular</B> with 1 ... 4 teeth -> it is informative only. Being circular, <BR>"
|
||||||
"the cut width in material is exactly the tool diameter.<BR>"
|
"the cut width in material is exactly the tool diameter.<BR>"
|
||||||
"- <B>Ball</B> -> informative only and make reference to the Ball type endmill.<BR>"
|
"- <B>Ball</B> -> informative only and make reference to the Ball type endmill.<BR>"
|
||||||
|
@ -89,7 +105,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
"as the cut width into material will be equal with the value in the Tool Diameter "
|
"as the cut width into material will be equal with the value in the Tool Diameter "
|
||||||
"column of this table.<BR>"
|
"column of this table.<BR>"
|
||||||
"Choosing the <B>V-Shape</B> Tool Type automatically will select the Operation Type "
|
"Choosing the <B>V-Shape</B> Tool Type automatically will select the Operation Type "
|
||||||
"in the resulting geometry as Isolation.")
|
"in the resulting geometry as Isolation."))
|
||||||
|
|
||||||
self.empty_label = QtWidgets.QLabel('')
|
self.empty_label = QtWidgets.QLabel('')
|
||||||
self.tools_box.addWidget(self.empty_label)
|
self.tools_box.addWidget(self.empty_label)
|
||||||
|
@ -98,9 +114,9 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
hlay = QtWidgets.QHBoxLayout()
|
hlay = QtWidgets.QHBoxLayout()
|
||||||
self.tools_box.addLayout(hlay)
|
self.tools_box.addLayout(hlay)
|
||||||
|
|
||||||
self.addtool_entry_lbl = QtWidgets.QLabel('<b>Tool Dia:</b>')
|
self.addtool_entry_lbl = QtWidgets.QLabel('<b>%s:</b>' % _('Tool Dia'))
|
||||||
self.addtool_entry_lbl.setToolTip(
|
self.addtool_entry_lbl.setToolTip(
|
||||||
"Diameter for the new tool."
|
_("Diameter for the new tool.")
|
||||||
)
|
)
|
||||||
self.addtool_entry = FCEntry()
|
self.addtool_entry = FCEntry()
|
||||||
|
|
||||||
|
@ -112,10 +128,10 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
grid2 = QtWidgets.QGridLayout()
|
grid2 = QtWidgets.QGridLayout()
|
||||||
self.tools_box.addLayout(grid2)
|
self.tools_box.addLayout(grid2)
|
||||||
|
|
||||||
self.addtool_btn = QtWidgets.QPushButton('Add')
|
self.addtool_btn = QtWidgets.QPushButton(_('Add'))
|
||||||
self.addtool_btn.setToolTip(
|
self.addtool_btn.setToolTip(
|
||||||
"Add a new tool to the Tool Table\n"
|
_("Add a new tool to the Tool Table\n"
|
||||||
"with the diameter specified above."
|
"with the diameter specified above.")
|
||||||
)
|
)
|
||||||
|
|
||||||
# self.copytool_btn = QtWidgets.QPushButton('Copy')
|
# self.copytool_btn = QtWidgets.QPushButton('Copy')
|
||||||
|
@ -124,10 +140,10 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
# "by first selecting a row in the Tool Table."
|
# "by first selecting a row in the Tool Table."
|
||||||
# )
|
# )
|
||||||
|
|
||||||
self.deltool_btn = QtWidgets.QPushButton('Delete')
|
self.deltool_btn = QtWidgets.QPushButton(_('Delete'))
|
||||||
self.deltool_btn.setToolTip(
|
self.deltool_btn.setToolTip(
|
||||||
"Delete a selection of tools in the Tool Table\n"
|
_("Delete a selection of tools in the Tool Table\n"
|
||||||
"by first selecting a row(s) in the Tool Table."
|
"by first selecting a row(s) in the Tool Table.")
|
||||||
)
|
)
|
||||||
|
|
||||||
grid2.addWidget(self.addtool_btn, 0, 0)
|
grid2.addWidget(self.addtool_btn, 0, 0)
|
||||||
|
@ -141,9 +157,9 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
self.tools_box.addLayout(grid3)
|
self.tools_box.addLayout(grid3)
|
||||||
|
|
||||||
# Overlap
|
# Overlap
|
||||||
ovlabel = QtWidgets.QLabel('Overlap:')
|
ovlabel = QtWidgets.QLabel(_('Overlap:'))
|
||||||
ovlabel.setToolTip(
|
ovlabel.setToolTip(
|
||||||
"How much (fraction) of the tool width to overlap each tool pass.\n"
|
_("How much (fraction) of the tool width to overlap each tool pass.\n"
|
||||||
"Example:\n"
|
"Example:\n"
|
||||||
"A value here of 0.25 means 25% from the tool diameter found above.\n\n"
|
"A value here of 0.25 means 25% from the tool diameter found above.\n\n"
|
||||||
"Adjust the value starting with lower values\n"
|
"Adjust the value starting with lower values\n"
|
||||||
|
@ -151,30 +167,30 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
"not painted.\n"
|
"not painted.\n"
|
||||||
"Lower values = faster processing, faster execution on PCB.\n"
|
"Lower values = faster processing, faster execution on PCB.\n"
|
||||||
"Higher values = slow processing and slow execution on CNC\n"
|
"Higher values = slow processing and slow execution on CNC\n"
|
||||||
"due of too many paths."
|
"due of too many paths.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(ovlabel, 1, 0)
|
grid3.addWidget(ovlabel, 1, 0)
|
||||||
self.paintoverlap_entry = FCEntry()
|
self.paintoverlap_entry = FCEntry()
|
||||||
grid3.addWidget(self.paintoverlap_entry, 1, 1)
|
grid3.addWidget(self.paintoverlap_entry, 1, 1)
|
||||||
|
|
||||||
# Margin
|
# Margin
|
||||||
marginlabel = QtWidgets.QLabel('Margin:')
|
marginlabel = QtWidgets.QLabel(_('Margin:'))
|
||||||
marginlabel.setToolTip(
|
marginlabel.setToolTip(
|
||||||
"Distance by which to avoid\n"
|
_("Distance by which to avoid\n"
|
||||||
"the edges of the polygon to\n"
|
"the edges of the polygon to\n"
|
||||||
"be painted."
|
"be painted.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(marginlabel, 2, 0)
|
grid3.addWidget(marginlabel, 2, 0)
|
||||||
self.paintmargin_entry = FCEntry()
|
self.paintmargin_entry = FCEntry()
|
||||||
grid3.addWidget(self.paintmargin_entry, 2, 1)
|
grid3.addWidget(self.paintmargin_entry, 2, 1)
|
||||||
|
|
||||||
# Method
|
# Method
|
||||||
methodlabel = QtWidgets.QLabel('Method:')
|
methodlabel = QtWidgets.QLabel(_('Method:'))
|
||||||
methodlabel.setToolTip(
|
methodlabel.setToolTip(
|
||||||
"Algorithm for non-copper clearing:<BR>"
|
_("Algorithm for non-copper clearing:<BR>"
|
||||||
"<B>Standard</B>: Fixed step inwards.<BR>"
|
"<B>Standard</B>: Fixed step inwards.<BR>"
|
||||||
"<B>Seed-based</B>: Outwards from seed.<BR>"
|
"<B>Seed-based</B>: Outwards from seed.<BR>"
|
||||||
"<B>Line-based</B>: Parallel lines."
|
"<B>Line-based</B>: Parallel lines.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(methodlabel, 3, 0)
|
grid3.addWidget(methodlabel, 3, 0)
|
||||||
self.paintmethod_combo = RadioSet([
|
self.paintmethod_combo = RadioSet([
|
||||||
|
@ -185,45 +201,45 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
grid3.addWidget(self.paintmethod_combo, 3, 1)
|
grid3.addWidget(self.paintmethod_combo, 3, 1)
|
||||||
|
|
||||||
# Connect lines
|
# Connect lines
|
||||||
pathconnectlabel = QtWidgets.QLabel("Connect:")
|
pathconnectlabel = QtWidgets.QLabel(_("Connect:"))
|
||||||
pathconnectlabel.setToolTip(
|
pathconnectlabel.setToolTip(
|
||||||
"Draw lines between resulting\n"
|
_("Draw lines between resulting\n"
|
||||||
"segments to minimize tool lifts."
|
"segments to minimize tool lifts.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(pathconnectlabel, 4, 0)
|
grid3.addWidget(pathconnectlabel, 4, 0)
|
||||||
self.pathconnect_cb = FCCheckBox()
|
self.pathconnect_cb = FCCheckBox()
|
||||||
grid3.addWidget(self.pathconnect_cb, 4, 1)
|
grid3.addWidget(self.pathconnect_cb, 4, 1)
|
||||||
|
|
||||||
contourlabel = QtWidgets.QLabel("Contour:")
|
contourlabel = QtWidgets.QLabel(_("Contour:"))
|
||||||
contourlabel.setToolTip(
|
contourlabel.setToolTip(
|
||||||
"Cut around the perimeter of the polygon\n"
|
_("Cut around the perimeter of the polygon\n"
|
||||||
"to trim rough edges."
|
"to trim rough edges.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(contourlabel, 5, 0)
|
grid3.addWidget(contourlabel, 5, 0)
|
||||||
self.paintcontour_cb = FCCheckBox()
|
self.paintcontour_cb = FCCheckBox()
|
||||||
grid3.addWidget(self.paintcontour_cb, 5, 1)
|
grid3.addWidget(self.paintcontour_cb, 5, 1)
|
||||||
|
|
||||||
restlabel = QtWidgets.QLabel("Rest M.:")
|
restlabel = QtWidgets.QLabel(_("Rest M.:"))
|
||||||
restlabel.setToolTip(
|
restlabel.setToolTip(
|
||||||
"If checked, use 'rest machining'.\n"
|
_("If checked, use 'rest machining'.\n"
|
||||||
"Basically it will clear copper outside PCB features,\n"
|
"Basically it will clear copper outside PCB features,\n"
|
||||||
"using the biggest tool and continue with the next tools,\n"
|
"using the biggest tool and continue with the next tools,\n"
|
||||||
"from bigger to smaller, to clear areas of copper that\n"
|
"from bigger to smaller, to clear areas of copper that\n"
|
||||||
"could not be cleared by previous tool, until there is\n"
|
"could not be cleared by previous tool, until there is\n"
|
||||||
"no more copper to clear or there are no more tools.\n\n"
|
"no more copper to clear or there are no more tools.\n\n"
|
||||||
"If not checked, use the standard algorithm."
|
"If not checked, use the standard algorithm.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(restlabel, 6, 0)
|
grid3.addWidget(restlabel, 6, 0)
|
||||||
self.rest_cb = FCCheckBox()
|
self.rest_cb = FCCheckBox()
|
||||||
grid3.addWidget(self.rest_cb, 6, 1)
|
grid3.addWidget(self.rest_cb, 6, 1)
|
||||||
|
|
||||||
# Polygon selection
|
# Polygon selection
|
||||||
selectlabel = QtWidgets.QLabel('Selection:')
|
selectlabel = QtWidgets.QLabel(_('Selection:'))
|
||||||
selectlabel.setToolTip(
|
selectlabel.setToolTip(
|
||||||
"How to select the polygons to paint.<BR>"
|
_("How to select the polygons to paint.<BR>"
|
||||||
"Options:<BR>"
|
"Options:<BR>"
|
||||||
"- <B>Single</B>: left mouse click on the polygon to be painted.<BR>"
|
"- <B>Single</B>: left mouse click on the polygon to be painted.<BR>"
|
||||||
"- <B>All</B>: paint all polygons."
|
"- <B>All</B>: paint all polygons.")
|
||||||
)
|
)
|
||||||
grid3.addWidget(selectlabel, 7, 0)
|
grid3.addWidget(selectlabel, 7, 0)
|
||||||
# grid3 = QtWidgets.QGridLayout()
|
# grid3 = QtWidgets.QGridLayout()
|
||||||
|
@ -235,13 +251,13 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
grid3.addWidget(self.selectmethod_combo, 7, 1)
|
grid3.addWidget(self.selectmethod_combo, 7, 1)
|
||||||
|
|
||||||
# GO Button
|
# GO Button
|
||||||
self.generate_paint_button = QtWidgets.QPushButton('Create Paint Geometry')
|
self.generate_paint_button = QtWidgets.QPushButton(_('Create Paint Geometry'))
|
||||||
self.generate_paint_button.setToolTip(
|
self.generate_paint_button.setToolTip(
|
||||||
"After clicking here, click inside<BR>"
|
_("After clicking here, click inside<BR>"
|
||||||
"the polygon you wish to be painted if <B>Single</B> is selected.<BR>"
|
"the polygon you wish to be painted if <B>Single</B> is selected.<BR>"
|
||||||
"If <B>All</B> is selected then the Paint will start after click.<BR>"
|
"If <B>All</B> is selected then the Paint will start after click.<BR>"
|
||||||
"A new Geometry object with the tool<BR>"
|
"A new Geometry object with the tool<BR>"
|
||||||
"paths will be created."
|
"paths will be created.")
|
||||||
)
|
)
|
||||||
self.tools_box.addWidget(self.generate_paint_button)
|
self.tools_box.addWidget(self.generate_paint_button)
|
||||||
|
|
||||||
|
@ -301,23 +317,27 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
def install(self, icon=None, separator=None, **kwargs):
|
def install(self, icon=None, separator=None, **kwargs):
|
||||||
FlatCAMTool.install(self, icon, separator, shortcut='ALT+P', **kwargs)
|
FlatCAMTool.install(self, icon, separator, shortcut='ALT+P', **kwargs)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolPaint()")
|
self.app.report_usage("ToolPaint()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
|
||||||
self.app.ui.notebook.setTabText(2, "Paint Tool")
|
self.app.ui.notebook.setTabText(2, _("Paint Tool"))
|
||||||
|
|
||||||
def on_radio_selection(self):
|
def on_radio_selection(self):
|
||||||
if self.selectmethod_combo.get_value() == 'single':
|
if self.selectmethod_combo.get_value() == 'single':
|
||||||
|
@ -514,13 +534,13 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
|
tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if tool_dia is None:
|
if tool_dia is None:
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Please enter a tool diameter to add, in Float format.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Please enter a tool diameter to add, in Float format."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# construct a list of all 'tooluid' in the self.tools
|
# construct a list of all 'tooluid' in the self.tools
|
||||||
|
@ -544,12 +564,12 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
|
|
||||||
if float('%.4f' % tool_dia) in tool_dias:
|
if float('%.4f' % tool_dia) in tool_dias:
|
||||||
if muted is None:
|
if muted is None:
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Adding tool cancelled. Tool already in Tool Table.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Adding tool cancelled. Tool already in Tool Table."))
|
||||||
self.tools_table.itemChanged.connect(self.on_tool_edit)
|
self.tools_table.itemChanged.connect(self.on_tool_edit)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
if muted is None:
|
if muted is None:
|
||||||
self.app.inform.emit("[success] New tool added to Tool Table.")
|
self.app.inform.emit(_("[success] New tool added to Tool Table."))
|
||||||
self.paint_tools.update({
|
self.paint_tools.update({
|
||||||
int(self.tooluid): {
|
int(self.tooluid): {
|
||||||
'tooldia': float('%.4f' % tool_dia),
|
'tooldia': float('%.4f' % tool_dia),
|
||||||
|
@ -584,15 +604,15 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.'))
|
new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
tooluid = int(self.tools_table.item(row, 3).text())
|
tooluid = int(self.tools_table.item(row, 3).text())
|
||||||
|
|
||||||
# identify the tool that was edited and get it's tooluid
|
# identify the tool that was edited and get it's tooluid
|
||||||
if new_tool_dia not in tool_dias:
|
if new_tool_dia not in tool_dias:
|
||||||
self.paint_tools[tooluid]['tooldia'] = new_tool_dia
|
self.paint_tools[tooluid]['tooldia'] = new_tool_dia
|
||||||
self.app.inform.emit("[success] Tool from Tool Table was edited.")
|
self.app.inform.emit(_("[success] Tool from Tool Table was edited."))
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -603,7 +623,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
break
|
break
|
||||||
restore_dia_item = self.tools_table.item(row, 1)
|
restore_dia_item = self.tools_table.item(row, 1)
|
||||||
restore_dia_item.setText(str(old_tool_dia))
|
restore_dia_item.setText(str(old_tool_dia))
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Edit cancelled. New diameter value is already in the Tool Table.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Edit cancelled. New diameter value is already in the Tool Table."))
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
|
|
||||||
# def on_tool_copy(self, all=None):
|
# def on_tool_copy(self, all=None):
|
||||||
|
@ -700,18 +720,19 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
self.paint_tools.pop(t, None)
|
self.paint_tools.pop(t, None)
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Delete failed. Select a tool to delete.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Delete failed. Select a tool to delete."))
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug(str(e))
|
log.debug(str(e))
|
||||||
|
|
||||||
self.app.inform.emit("[success] Tool(s) deleted from Tool Table.")
|
self.app.inform.emit(_("[success] Tool(s) deleted from Tool Table."))
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
|
|
||||||
def on_paint_button_click(self):
|
def on_paint_button_click(self):
|
||||||
self.app.report_usage("geometry_on_paint_button")
|
self.app.report_usage(_("geometry_on_paint_button"))
|
||||||
|
self.app.call_source = 'paint'
|
||||||
|
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Click inside the desired polygon.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Click inside the desired polygon."))
|
||||||
try:
|
try:
|
||||||
overlap = float(self.paintoverlap_entry.get_value())
|
overlap = float(self.paintoverlap_entry.get_value())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -719,8 +740,8 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
overlap = float(self.paintoverlap_entry.get_value().replace(',', '.'))
|
overlap = float(self.paintoverlap_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
connect = self.pathconnect_cb.get_value()
|
connect = self.pathconnect_cb.get_value()
|
||||||
|
@ -733,17 +754,17 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
self.paint_obj = self.app.collection.get_by_name(str(self.obj_name))
|
self.paint_obj = self.app.collection.get_by_name(str(self.obj_name))
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Could not retrieve object: %s" % self.obj_name)
|
self.app.inform.emit(_("[ERROR_NOTCL]Could not retrieve object: %s") % self.obj_name)
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.paint_obj is None:
|
if self.paint_obj is None:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Object not found: %s" % self.paint_obj)
|
self.app.inform.emit(_("[ERROR_NOTCL]Object not found: %s") % self.paint_obj)
|
||||||
return
|
return
|
||||||
|
|
||||||
# test if the Geometry Object is multigeo and return Fail if True because
|
# test if the Geometry Object is multigeo and return Fail if True because
|
||||||
# for now Paint don't work on MultiGeo
|
# for now Paint don't work on MultiGeo
|
||||||
if self.paint_obj.multigeo is True:
|
if self.paint_obj.multigeo is True:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Can't do Paint on MultiGeo geometries ...")
|
self.app.inform.emit(_("[ERROR_NOTCL] Can't do Paint on MultiGeo geometries ..."))
|
||||||
return 'Fail'
|
return 'Fail'
|
||||||
|
|
||||||
o_name = '%s_multitool_paint' % (self.obj_name)
|
o_name = '%s_multitool_paint' % (self.obj_name)
|
||||||
|
@ -756,7 +777,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
contour=contour)
|
contour=contour)
|
||||||
|
|
||||||
if select_method == "single":
|
if select_method == "single":
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Click inside the desired polygon.")
|
self.app.inform.emit(_("[WARNING_NOTCL]Click inside the desired polygon."))
|
||||||
|
|
||||||
# use the first tool in the tool table; get the diameter
|
# use the first tool in the tool table; get the diameter
|
||||||
tooldia = float('%.4f' % float(self.tools_table.item(0, 1).text()))
|
tooldia = float('%.4f' % float(self.tools_table.item(0, 1).text()))
|
||||||
|
@ -765,7 +786,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
def doit(event):
|
def doit(event):
|
||||||
# do paint single only for left mouse clicks
|
# do paint single only for left mouse clicks
|
||||||
if event.button == 1:
|
if event.button == 1:
|
||||||
self.app.inform.emit("Painting polygon...")
|
self.app.inform.emit(_("Painting polygon..."))
|
||||||
self.app.plotcanvas.vis_disconnect('mouse_press', doit)
|
self.app.plotcanvas.vis_disconnect('mouse_press', doit)
|
||||||
pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
|
pos = self.app.plotcanvas.vispy_canvas.translate_coords(event.pos)
|
||||||
self.paint_poly(self.paint_obj,
|
self.paint_poly(self.paint_obj,
|
||||||
|
@ -799,7 +820,6 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
|
|
||||||
# Which polygon.
|
# Which polygon.
|
||||||
# poly = find_polygon(self.solid_geometry, inside_pt)
|
# poly = find_polygon(self.solid_geometry, inside_pt)
|
||||||
|
|
||||||
poly = obj.find_polygon(inside_pt)
|
poly = obj.find_polygon(inside_pt)
|
||||||
paint_method = self.paintmethod_combo.get_value()
|
paint_method = self.paintmethod_combo.get_value()
|
||||||
|
|
||||||
|
@ -810,17 +830,17 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
paint_margin = float(self.paintmargin_entry.get_value().replace(',', '.'))
|
paint_margin = float(self.paintmargin_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# No polygon?
|
# No polygon?
|
||||||
if poly is None:
|
if poly is None:
|
||||||
self.app.log.warning('No polygon found.')
|
self.app.log.warning('No polygon found.')
|
||||||
self.app.inform.emit('[WARNING] No polygon found.')
|
self.app.inform.emit(_('[WARNING] No polygon found.'))
|
||||||
return
|
return
|
||||||
|
|
||||||
proc = self.app.proc_container.new("Painting polygon.")
|
proc = self.app.proc_container.new(_("Painting polygon."))
|
||||||
|
|
||||||
name = outname if outname else self.obj_name + "_paint"
|
name = outname if outname else self.obj_name + "_paint"
|
||||||
|
|
||||||
|
@ -862,13 +882,13 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
geo_obj.solid_geometry += list(cp.get_objects())
|
geo_obj.solid_geometry += list(cp.get_objects())
|
||||||
return cp
|
return cp
|
||||||
else:
|
else:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] Geometry could not be painted completely')
|
self.app.inform.emit(_('[ERROR_NOTCL] Geometry could not be painted completely'))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
geo_obj.solid_geometry = []
|
geo_obj.solid_geometry = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
a, b, c, d = poly.bounds()
|
a, b, c, d = poly.bounds
|
||||||
geo_obj.options['xmin'] = a
|
geo_obj.options['xmin'] = a
|
||||||
geo_obj.options['ymin'] = b
|
geo_obj.options['ymin'] = b
|
||||||
geo_obj.options['xmax'] = c
|
geo_obj.options['xmax'] = c
|
||||||
|
@ -888,8 +908,8 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("Could not Paint the polygons. %s" % str(e))
|
log.debug("Could not Paint the polygons. %s" % str(e))
|
||||||
self.app.inform.emit(
|
self.app.inform.emit(
|
||||||
"[ERROR] Could not do Paint. Try a different combination of parameters. "
|
_("[ERROR] Could not do Paint. Try a different combination of parameters. "
|
||||||
"Or a different strategy of paint\n%s" % str(e))
|
"Or a different strategy of paint\n%s") % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
if cp is not None:
|
if cp is not None:
|
||||||
|
@ -930,13 +950,13 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
app_obj.new_object("geometry", name, gen_paintarea)
|
app_obj.new_object("geometry", name, gen_paintarea)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
proc.done()
|
proc.done()
|
||||||
self.app.inform.emit('[ERROR_NOTCL] PaintTool.paint_poly() --> %s' % str(e))
|
self.app.inform.emit(_('[ERROR_NOTCL] PaintTool.paint_poly() --> %s') % str(e))
|
||||||
return
|
return
|
||||||
proc.done()
|
proc.done()
|
||||||
# focus on Selected Tab
|
# focus on Selected Tab
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
||||||
|
|
||||||
self.app.inform.emit("Polygon Paint started ...")
|
self.app.inform.emit(_("Polygon Paint started ..."))
|
||||||
|
|
||||||
# Promise object with the new name
|
# Promise object with the new name
|
||||||
self.app.collection.promise(name)
|
self.app.collection.promise(name)
|
||||||
|
@ -965,11 +985,11 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
try:
|
try:
|
||||||
paint_margin = float(self.paintmargin_entry.get_value().replace(',', '.'))
|
paint_margin = float(self.paintmargin_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
proc = self.app.proc_container.new("Painting polygon.")
|
proc = self.app.proc_container.new(_("Painting polygon..."))
|
||||||
name = outname if outname else self.obj_name + "_paint"
|
name = outname if outname else self.obj_name + "_paint"
|
||||||
over = overlap
|
over = overlap
|
||||||
conn = connect
|
conn = connect
|
||||||
|
@ -1084,8 +1104,8 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("Could not Paint the polygons. %s" % str(e))
|
log.debug("Could not Paint the polygons. %s" % str(e))
|
||||||
self.app.inform.emit(
|
self.app.inform.emit(
|
||||||
"[ERROR] Could not do Paint All. Try a different combination of parameters. "
|
_("[ERROR] Could not do Paint All. Try a different combination of parameters. "
|
||||||
"Or a different Method of paint\n%s" % str(e))
|
"Or a different Method of paint\n%s") % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
# add the solid_geometry to the current too in self.paint_tools dictionary and then reset the
|
# add the solid_geometry to the current too in self.paint_tools dictionary and then reset the
|
||||||
|
@ -1108,16 +1128,16 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
if geo_obj.tools[tooluid]['solid_geometry']:
|
if geo_obj.tools[tooluid]['solid_geometry']:
|
||||||
has_solid_geo += 1
|
has_solid_geo += 1
|
||||||
if has_solid_geo == 0:
|
if has_solid_geo == 0:
|
||||||
self.app.inform.emit("[ERROR] There is no Painting Geometry in the file.\n"
|
self.app.inform.emit(_("[ERROR] There is no Painting Geometry in the file.\n"
|
||||||
"Usually it means that the tool diameter is too big for the painted geometry.\n"
|
"Usually it means that the tool diameter is too big for the painted geometry.\n"
|
||||||
"Change the painting parameters and try again.")
|
"Change the painting parameters and try again."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Experimental...
|
# Experimental...
|
||||||
# print("Indexing...", end=' ')
|
# print("Indexing...", end=' ')
|
||||||
# geo_obj.make_index()
|
# geo_obj.make_index()
|
||||||
|
|
||||||
self.app.inform.emit("[success] Paint All Done.")
|
self.app.inform.emit(_("[success] Paint All Done."))
|
||||||
|
|
||||||
# Initializes the new geometry object
|
# Initializes the new geometry object
|
||||||
def gen_paintarea_rest_machining(geo_obj, app_obj):
|
def gen_paintarea_rest_machining(geo_obj, app_obj):
|
||||||
|
@ -1173,8 +1193,8 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("Could not Paint the polygons. %s" % str(e))
|
log.debug("Could not Paint the polygons. %s" % str(e))
|
||||||
self.app.inform.emit(
|
self.app.inform.emit(
|
||||||
"[ERROR] Could not do Paint All. Try a different combination of parameters. "
|
_("[ERROR] Could not do Paint All. Try a different combination of parameters. "
|
||||||
"Or a different Method of paint\n%s" % str(e))
|
"Or a different Method of paint\n%s") % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
# find the tooluid associated with the current tool_dia so we know where to add the tool solid_geometry
|
# find the tooluid associated with the current tool_dia so we know where to add the tool solid_geometry
|
||||||
|
@ -1203,16 +1223,16 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
if geo_obj.tools[tooluid]['solid_geometry']:
|
if geo_obj.tools[tooluid]['solid_geometry']:
|
||||||
has_solid_geo += 1
|
has_solid_geo += 1
|
||||||
if has_solid_geo == 0:
|
if has_solid_geo == 0:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] There is no Painting Geometry in the file.\n"
|
self.app.inform.emit(_("[ERROR_NOTCL] There is no Painting Geometry in the file.\n"
|
||||||
"Usually it means that the tool diameter is too big for the painted geometry.\n"
|
"Usually it means that the tool diameter is too big for the painted geometry.\n"
|
||||||
"Change the painting parameters and try again.")
|
"Change the painting parameters and try again."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Experimental...
|
# Experimental...
|
||||||
# print("Indexing...", end=' ')
|
# print("Indexing...", end=' ')
|
||||||
# geo_obj.make_index()
|
# geo_obj.make_index()
|
||||||
|
|
||||||
self.app.inform.emit("[success] Paint All with Rest-Machining Done.")
|
self.app.inform.emit(_("[success] Paint All with Rest-Machining done."))
|
||||||
|
|
||||||
def job_thread(app_obj):
|
def job_thread(app_obj):
|
||||||
try:
|
try:
|
||||||
|
@ -1228,7 +1248,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||||
# focus on Selected Tab
|
# focus on Selected Tab
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
|
||||||
|
|
||||||
self.app.inform.emit("Polygon Paint started ...")
|
self.app.inform.emit(_("Polygon Paint started ..."))
|
||||||
|
|
||||||
# Promise object with the new name
|
# Promise object with the new name
|
||||||
self.app.collection.promise(name)
|
self.app.collection.promise(name)
|
||||||
|
|
|
@ -1,12 +1,28 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from copy import copy, deepcopy
|
from copy import copy, deepcopy
|
||||||
from ObjectCollection import *
|
from ObjectCollection import *
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class Panelize(FlatCAMTool):
|
class Panelize(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "Panelize PCB"
|
toolName = _("Panelize PCB")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
super(Panelize, self).__init__(self)
|
super(Panelize, self).__init__(self)
|
||||||
|
@ -37,12 +53,12 @@ class Panelize(FlatCAMTool):
|
||||||
self.type_obj_combo.setItemIcon(1, QtGui.QIcon("share/drill16.png"))
|
self.type_obj_combo.setItemIcon(1, QtGui.QIcon("share/drill16.png"))
|
||||||
self.type_obj_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
self.type_obj_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
||||||
|
|
||||||
self.type_obj_combo_label = QtWidgets.QLabel("Object Type:")
|
self.type_obj_combo_label = QtWidgets.QLabel(_("Object Type:"))
|
||||||
self.type_obj_combo_label.setToolTip(
|
self.type_obj_combo_label.setToolTip(
|
||||||
"Specify the type of object to be panelized\n"
|
_("Specify the type of object to be panelized\n"
|
||||||
"It can be of type: Gerber, Excellon or Geometry.\n"
|
"It can be of type: Gerber, Excellon or Geometry.\n"
|
||||||
"The selection here decide the type of objects that will be\n"
|
"The selection here decide the type of objects that will be\n"
|
||||||
"in the Object combobox."
|
"in the Object combobox.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo)
|
form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo)
|
||||||
|
|
||||||
|
@ -52,10 +68,10 @@ class Panelize(FlatCAMTool):
|
||||||
self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
||||||
self.object_combo.setCurrentIndex(1)
|
self.object_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.object_label = QtWidgets.QLabel("Object:")
|
self.object_label = QtWidgets.QLabel(_("Object:"))
|
||||||
self.object_label.setToolTip(
|
self.object_label.setToolTip(
|
||||||
"Object to be panelized. This means that it will\n"
|
_("Object to be panelized. This means that it will\n"
|
||||||
"be duplicated in an array of rows and columns."
|
"be duplicated in an array of rows and columns.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.object_label, self.object_combo)
|
form_layout.addRow(self.object_label, self.object_combo)
|
||||||
|
|
||||||
|
@ -70,12 +86,12 @@ class Panelize(FlatCAMTool):
|
||||||
self.type_box_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png"))
|
self.type_box_combo.setItemIcon(0, QtGui.QIcon("share/flatcam_icon16.png"))
|
||||||
self.type_box_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
self.type_box_combo.setItemIcon(2, QtGui.QIcon("share/geometry16.png"))
|
||||||
|
|
||||||
self.type_box_combo_label = QtWidgets.QLabel("Box Type:")
|
self.type_box_combo_label = QtWidgets.QLabel(_("Box Type:"))
|
||||||
self.type_box_combo_label.setToolTip(
|
self.type_box_combo_label.setToolTip(
|
||||||
"Specify the type of object to be used as an container for\n"
|
_("Specify the type of object to be used as an container for\n"
|
||||||
"panelization. It can be: Gerber or Geometry type.\n"
|
"panelization. It can be: Gerber or Geometry type.\n"
|
||||||
"The selection here decide the type of objects that will be\n"
|
"The selection here decide the type of objects that will be\n"
|
||||||
"in the Box Object combobox."
|
"in the Box Object combobox.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.type_box_combo_label, self.type_box_combo)
|
form_layout.addRow(self.type_box_combo_label, self.type_box_combo)
|
||||||
|
|
||||||
|
@ -85,83 +101,83 @@ class Panelize(FlatCAMTool):
|
||||||
self.box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
self.box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
||||||
self.box_combo.setCurrentIndex(1)
|
self.box_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.box_combo_label = QtWidgets.QLabel("Box Object:")
|
self.box_combo_label = QtWidgets.QLabel(_("Box Object:"))
|
||||||
self.box_combo_label.setToolTip(
|
self.box_combo_label.setToolTip(
|
||||||
"The actual object that is used a container for the\n "
|
_("The actual object that is used a container for the\n "
|
||||||
"selected object that is to be panelized."
|
"selected object that is to be panelized.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.box_combo_label, self.box_combo)
|
form_layout.addRow(self.box_combo_label, self.box_combo)
|
||||||
|
|
||||||
## Spacing Columns
|
## Spacing Columns
|
||||||
self.spacing_columns = FCEntry()
|
self.spacing_columns = FCEntry()
|
||||||
self.spacing_columns_label = QtWidgets.QLabel("Spacing cols:")
|
self.spacing_columns_label = QtWidgets.QLabel(_("Spacing cols:"))
|
||||||
self.spacing_columns_label.setToolTip(
|
self.spacing_columns_label.setToolTip(
|
||||||
"Spacing between columns of the desired panel.\n"
|
_("Spacing between columns of the desired panel.\n"
|
||||||
"In current units."
|
"In current units.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.spacing_columns_label, self.spacing_columns)
|
form_layout.addRow(self.spacing_columns_label, self.spacing_columns)
|
||||||
|
|
||||||
## Spacing Rows
|
## Spacing Rows
|
||||||
self.spacing_rows = FCEntry()
|
self.spacing_rows = FCEntry()
|
||||||
self.spacing_rows_label = QtWidgets.QLabel("Spacing rows:")
|
self.spacing_rows_label = QtWidgets.QLabel(_("Spacing rows:"))
|
||||||
self.spacing_rows_label.setToolTip(
|
self.spacing_rows_label.setToolTip(
|
||||||
"Spacing between rows of the desired panel.\n"
|
_("Spacing between rows of the desired panel.\n"
|
||||||
"In current units."
|
"In current units.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.spacing_rows_label, self.spacing_rows)
|
form_layout.addRow(self.spacing_rows_label, self.spacing_rows)
|
||||||
|
|
||||||
## Columns
|
## Columns
|
||||||
self.columns = FCEntry()
|
self.columns = FCEntry()
|
||||||
self.columns_label = QtWidgets.QLabel("Columns:")
|
self.columns_label = QtWidgets.QLabel(_("Columns:"))
|
||||||
self.columns_label.setToolTip(
|
self.columns_label.setToolTip(
|
||||||
"Number of columns of the desired panel"
|
_("Number of columns of the desired panel")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.columns_label, self.columns)
|
form_layout.addRow(self.columns_label, self.columns)
|
||||||
|
|
||||||
## Rows
|
## Rows
|
||||||
self.rows = FCEntry()
|
self.rows = FCEntry()
|
||||||
self.rows_label = QtWidgets.QLabel("Rows:")
|
self.rows_label = QtWidgets.QLabel(_("Rows:"))
|
||||||
self.rows_label.setToolTip(
|
self.rows_label.setToolTip(
|
||||||
"Number of rows of the desired panel"
|
_("Number of rows of the desired panel")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.rows_label, self.rows)
|
form_layout.addRow(self.rows_label, self.rows)
|
||||||
|
|
||||||
## Type of resulting Panel object
|
## Type of resulting Panel object
|
||||||
self.panel_type_radio = RadioSet([{'label': 'Gerber', 'value': 'gerber'},
|
self.panel_type_radio = RadioSet([{'label': 'Gerber', 'value': 'gerber'},
|
||||||
{'label': 'Geometry', 'value': 'geometry'}])
|
{'label': 'Geometry', 'value': 'geometry'}])
|
||||||
self.panel_type_label = QtWidgets.QLabel("Panel Type:")
|
self.panel_type_label = QtWidgets.QLabel(_("Panel Type:"))
|
||||||
self.panel_type_label.setToolTip(
|
self.panel_type_label.setToolTip(
|
||||||
"Choose the type of object for the panel object:\n"
|
_("Choose the type of object for the panel object:\n"
|
||||||
"- Geometry\n"
|
"- Geometry\n"
|
||||||
"- Gerber"
|
"- Gerber")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.panel_type_label)
|
form_layout.addRow(self.panel_type_label)
|
||||||
form_layout.addRow(self.panel_type_radio)
|
form_layout.addRow(self.panel_type_radio)
|
||||||
|
|
||||||
## Constrains
|
## Constrains
|
||||||
self.constrain_cb = FCCheckBox("Constrain panel within:")
|
self.constrain_cb = FCCheckBox(_("Constrain panel within:"))
|
||||||
self.constrain_cb.setToolTip(
|
self.constrain_cb.setToolTip(
|
||||||
"Area define by DX and DY within to constrain the panel.\n"
|
_("Area define by DX and DY within to constrain the panel.\n"
|
||||||
"DX and DY values are in current units.\n"
|
"DX and DY values are in current units.\n"
|
||||||
"Regardless of how many columns and rows are desired,\n"
|
"Regardless of how many columns and rows are desired,\n"
|
||||||
"the final panel will have as many columns and rows as\n"
|
"the final panel will have as many columns and rows as\n"
|
||||||
"they fit completely within selected area."
|
"they fit completely within selected area.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.constrain_cb)
|
form_layout.addRow(self.constrain_cb)
|
||||||
|
|
||||||
self.x_width_entry = FCEntry()
|
self.x_width_entry = FCEntry()
|
||||||
self.x_width_lbl = QtWidgets.QLabel("Width (DX):")
|
self.x_width_lbl = QtWidgets.QLabel(_("Width (DX):"))
|
||||||
self.x_width_lbl.setToolTip(
|
self.x_width_lbl.setToolTip(
|
||||||
"The width (DX) within which the panel must fit.\n"
|
_("The width (DX) within which the panel must fit.\n"
|
||||||
"In current units."
|
"In current units.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.x_width_lbl, self.x_width_entry)
|
form_layout.addRow(self.x_width_lbl, self.x_width_entry)
|
||||||
|
|
||||||
self.y_height_entry = FCEntry()
|
self.y_height_entry = FCEntry()
|
||||||
self.y_height_lbl = QtWidgets.QLabel("Height (DY):")
|
self.y_height_lbl = QtWidgets.QLabel(_("Height (DY):"))
|
||||||
self.y_height_lbl.setToolTip(
|
self.y_height_lbl.setToolTip(
|
||||||
"The height (DY)within which the panel must fit.\n"
|
_("The height (DY)within which the panel must fit.\n"
|
||||||
"In current units."
|
"In current units.")
|
||||||
)
|
)
|
||||||
form_layout.addRow(self.y_height_lbl, self.y_height_entry)
|
form_layout.addRow(self.y_height_lbl, self.y_height_entry)
|
||||||
|
|
||||||
|
@ -173,11 +189,11 @@ class Panelize(FlatCAMTool):
|
||||||
self.layout.addLayout(hlay_2)
|
self.layout.addLayout(hlay_2)
|
||||||
|
|
||||||
hlay_2.addStretch()
|
hlay_2.addStretch()
|
||||||
self.panelize_object_button = QtWidgets.QPushButton("Panelize Object")
|
self.panelize_object_button = QtWidgets.QPushButton(_("Panelize Object"))
|
||||||
self.panelize_object_button.setToolTip(
|
self.panelize_object_button.setToolTip(
|
||||||
"Panelize the specified object around the specified box.\n"
|
_("Panelize the specified object around the specified box.\n"
|
||||||
"In other words it creates multiple copies of the source object,\n"
|
"In other words it creates multiple copies of the source object,\n"
|
||||||
"arranged in a 2D array of rows and columns."
|
"arranged in a 2D array of rows and columns.")
|
||||||
)
|
)
|
||||||
hlay_2.addWidget(self.panelize_object_button)
|
hlay_2.addWidget(self.panelize_object_button)
|
||||||
|
|
||||||
|
@ -197,18 +213,22 @@ class Panelize(FlatCAMTool):
|
||||||
# flag to signal the constrain was activated
|
# flag to signal the constrain was activated
|
||||||
self.constrain_flag = False
|
self.constrain_flag = False
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolPanelize()")
|
self.app.report_usage("ToolPanelize()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
@ -270,13 +290,13 @@ class Panelize(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
obj = self.app.collection.get_by_name(str(name))
|
obj = self.app.collection.get_by_name(str(name))
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Could not retrieve object: %s" % name)
|
self.app.inform.emit(_("[ERROR_NOTCL]Could not retrieve object: %s") % name)
|
||||||
return "Could not retrieve object: %s" % name
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
panel_obj = obj
|
panel_obj = obj
|
||||||
|
|
||||||
if panel_obj is None:
|
if panel_obj is None:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Object not found: %s" % panel_obj)
|
self.app.inform.emit(_("[ERROR_NOTCL]Object not found: %s") % panel_obj)
|
||||||
return "Object not found: %s" % panel_obj
|
return "Object not found: %s" % panel_obj
|
||||||
|
|
||||||
boxname = self.box_combo.currentText()
|
boxname = self.box_combo.currentText()
|
||||||
|
@ -284,11 +304,11 @@ class Panelize(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
box = self.app.collection.get_by_name(boxname)
|
box = self.app.collection.get_by_name(boxname)
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Could not retrieve object: %s" % boxname)
|
self.app.inform.emit(_("[ERROR_NOTCL]Could not retrieve object: %s") % boxname)
|
||||||
return "Could not retrieve object: %s" % boxname
|
return "Could not retrieve object: %s" % boxname
|
||||||
|
|
||||||
if box is None:
|
if box is None:
|
||||||
self.app.inform.emit("[WARNING]No object Box. Using instead %s" % panel_obj)
|
self.app.inform.emit(_("[WARNING]No object Box. Using instead %s") % panel_obj)
|
||||||
box = panel_obj
|
box = panel_obj
|
||||||
|
|
||||||
self.outname = name + '_panelized'
|
self.outname = name + '_panelized'
|
||||||
|
@ -300,8 +320,8 @@ class Panelize(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
spacing_columns = float(self.spacing_columns.get_value().replace(',', '.'))
|
spacing_columns = float(self.spacing_columns.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
spacing_columns = spacing_columns if spacing_columns is not None else 0
|
spacing_columns = spacing_columns if spacing_columns is not None else 0
|
||||||
|
|
||||||
|
@ -312,8 +332,8 @@ class Panelize(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
spacing_rows = float(self.spacing_rows.get_value().replace(',', '.'))
|
spacing_rows = float(self.spacing_rows.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
spacing_rows = spacing_rows if spacing_rows is not None else 0
|
spacing_rows = spacing_rows if spacing_rows is not None else 0
|
||||||
|
|
||||||
|
@ -325,8 +345,8 @@ class Panelize(FlatCAMTool):
|
||||||
rows = float(self.rows.get_value().replace(',', '.'))
|
rows = float(self.rows.get_value().replace(',', '.'))
|
||||||
rows = int(rows)
|
rows = int(rows)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
rows = rows if rows is not None else 1
|
rows = rows if rows is not None else 1
|
||||||
|
|
||||||
|
@ -338,8 +358,8 @@ class Panelize(FlatCAMTool):
|
||||||
columns = float(self.columns.get_value().replace(',', '.'))
|
columns = float(self.columns.get_value().replace(',', '.'))
|
||||||
columns = int(columns)
|
columns = int(columns)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
columns = columns if columns is not None else 1
|
columns = columns if columns is not None else 1
|
||||||
|
|
||||||
|
@ -350,8 +370,8 @@ class Panelize(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
constrain_dx = float(self.x_width_entry.get_value().replace(',', '.'))
|
constrain_dx = float(self.x_width_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -361,15 +381,15 @@ class Panelize(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
constrain_dy = float(self.y_height_entry.get_value().replace(',', '.'))
|
constrain_dy = float(self.y_height_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
panel_type = str(self.panel_type_radio.get_value())
|
panel_type = str(self.panel_type_radio.get_value())
|
||||||
|
|
||||||
|
|
||||||
if 0 in {columns, rows}:
|
if 0 in {columns, rows}:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Columns or Rows are zero value. Change them to a positive integer.")
|
self.app.inform.emit(_("[ERROR_NOTCL]Columns or Rows are zero value. Change them to a positive integer."))
|
||||||
return "Columns or Rows are zero value. Change them to a positive integer."
|
return "Columns or Rows are zero value. Change them to a positive integer."
|
||||||
|
|
||||||
xmin, ymin, xmax, ymax = box.bounds()
|
xmin, ymin, xmax, ymax = box.bounds()
|
||||||
|
@ -392,88 +412,9 @@ class Panelize(FlatCAMTool):
|
||||||
rows -= 1
|
rows -= 1
|
||||||
panel_lengthy = ((ymax - ymin) * rows) + (spacing_rows * (rows - 1))
|
panel_lengthy = ((ymax - ymin) * rows) + (spacing_rows * (rows - 1))
|
||||||
|
|
||||||
# def clean_temp():
|
|
||||||
# # deselect all to avoid delete selected object when run delete from shell
|
|
||||||
# self.app.collection.set_all_inactive()
|
|
||||||
#
|
|
||||||
# for del_obj in self.objs:
|
|
||||||
# self.app.collection.set_active(del_obj.options['name'])
|
|
||||||
# self.app.on_delete()
|
|
||||||
#
|
|
||||||
# self.objs[:] = []
|
|
||||||
|
|
||||||
# def panelize():
|
|
||||||
# if panel_obj is not None:
|
|
||||||
# self.app.inform.emit("Generating panel ... Please wait.")
|
|
||||||
#
|
|
||||||
# self.app.progress.emit(10)
|
|
||||||
#
|
|
||||||
# if isinstance(panel_obj, FlatCAMExcellon):
|
|
||||||
# currenty = 0.0
|
|
||||||
# self.app.progress.emit(0)
|
|
||||||
#
|
|
||||||
# def initialize_local_excellon(obj_init, app):
|
|
||||||
# obj_init.tools = panel_obj.tools
|
|
||||||
# # drills are offset, so they need to be deep copied
|
|
||||||
# obj_init.drills = deepcopy(panel_obj.drills)
|
|
||||||
# obj_init.offset([float(currentx), float(currenty)])
|
|
||||||
# obj_init.create_geometry()
|
|
||||||
# self.objs.append(obj_init)
|
|
||||||
#
|
|
||||||
# self.app.progress.emit(0)
|
|
||||||
# for row in range(rows):
|
|
||||||
# currentx = 0.0
|
|
||||||
# for col in range(columns):
|
|
||||||
# local_outname = self.outname + ".tmp." + str(col) + "." + str(row)
|
|
||||||
# self.app.new_object("excellon", local_outname, initialize_local_excellon, plot=False,
|
|
||||||
# autoselected=False)
|
|
||||||
# currentx += lenghtx
|
|
||||||
# currenty += lenghty
|
|
||||||
# else:
|
|
||||||
# currenty = 0
|
|
||||||
# self.app.progress.emit(0)
|
|
||||||
#
|
|
||||||
# def initialize_local_geometry(obj_init, app):
|
|
||||||
# obj_init.solid_geometry = panel_obj.solid_geometry
|
|
||||||
# obj_init.offset([float(currentx), float(currenty)])
|
|
||||||
# self.objs.append(obj_init)
|
|
||||||
#
|
|
||||||
# self.app.progress.emit(0)
|
|
||||||
# for row in range(rows):
|
|
||||||
# currentx = 0
|
|
||||||
#
|
|
||||||
# for col in range(columns):
|
|
||||||
# local_outname = self.outname + ".tmp." + str(col) + "." + str(row)
|
|
||||||
# self.app.new_object("geometry", local_outname, initialize_local_geometry, plot=False,
|
|
||||||
# autoselected=False)
|
|
||||||
# currentx += lenghtx
|
|
||||||
# currenty += lenghty
|
|
||||||
#
|
|
||||||
# def job_init_geometry(obj_fin, app_obj):
|
|
||||||
# FlatCAMGeometry.merge(self.objs, obj_fin)
|
|
||||||
#
|
|
||||||
# def job_init_excellon(obj_fin, app_obj):
|
|
||||||
# # merge expects tools to exist in the target object
|
|
||||||
# obj_fin.tools = panel_obj.tools.copy()
|
|
||||||
# FlatCAMExcellon.merge(self.objs, obj_fin)
|
|
||||||
#
|
|
||||||
# if isinstance(panel_obj, FlatCAMExcellon):
|
|
||||||
# self.app.progress.emit(50)
|
|
||||||
# self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True)
|
|
||||||
# else:
|
|
||||||
# self.app.progress.emit(50)
|
|
||||||
# self.app.new_object("geometry", self.outname, job_init_geometry, plot=True, autoselected=True)
|
|
||||||
#
|
|
||||||
# else:
|
|
||||||
# self.app.inform.emit("[ERROR_NOTCL] Obj is None")
|
|
||||||
# return "ERROR: Obj is None"
|
|
||||||
|
|
||||||
# panelize()
|
|
||||||
# clean_temp()
|
|
||||||
|
|
||||||
def panelize_2():
|
def panelize_2():
|
||||||
if panel_obj is not None:
|
if panel_obj is not None:
|
||||||
self.app.inform.emit("Generating panel ... Please wait.")
|
self.app.inform.emit(_("Generating panel ... Please wait."))
|
||||||
|
|
||||||
self.app.progress.emit(0)
|
self.app.progress.emit(0)
|
||||||
|
|
||||||
|
@ -576,18 +517,18 @@ class Panelize(FlatCAMTool):
|
||||||
plot=True, autoselected=True)
|
plot=True, autoselected=True)
|
||||||
|
|
||||||
if self.constrain_flag is False:
|
if self.constrain_flag is False:
|
||||||
self.app.inform.emit("[success]Panel done...")
|
self.app.inform.emit(_("[success]Panel done..."))
|
||||||
else:
|
else:
|
||||||
self.constrain_flag = False
|
self.constrain_flag = False
|
||||||
self.app.inform.emit("[WARNING] Too big for the constrain area. Final panel has %s columns and %s rows" %
|
self.app.inform.emit(_("[WARNING] Too big for the constrain area. Final panel has {col} columns and {row} rows").format(
|
||||||
(columns, rows))
|
col=columns, row=rows))
|
||||||
|
|
||||||
proc = self.app.proc_container.new("Generating panel ... Please wait.")
|
proc = self.app.proc_container.new(_("Generating panel ... Please wait."))
|
||||||
|
|
||||||
def job_thread(app_obj):
|
def job_thread(app_obj):
|
||||||
try:
|
try:
|
||||||
panelize_2()
|
panelize_2()
|
||||||
self.app.inform.emit("[success]Panel created successfully.")
|
self.app.inform.emit(_("[success]Panel created successfully."))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
proc.done()
|
proc.done()
|
||||||
log.debug(str(e))
|
log.debug(str(e))
|
||||||
|
|
|
@ -1,12 +1,28 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
from PyQt5 import QtGui, QtCore, QtWidgets
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from FlatCAMObj import *
|
from FlatCAMObj import *
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class Properties(FlatCAMTool):
|
class Properties(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "Properties"
|
toolName = _("Properties")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
FlatCAMTool.__init__(self, app)
|
FlatCAMTool.__init__(self, app)
|
||||||
|
@ -48,24 +64,29 @@ class Properties(FlatCAMTool):
|
||||||
self.vlay.addWidget(self.treeWidget)
|
self.vlay.addWidget(self.treeWidget)
|
||||||
self.vlay.setStretch(0,0)
|
self.vlay.setStretch(0,0)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolProperties()")
|
self.app.report_usage("ToolProperties()")
|
||||||
|
|
||||||
if self.app.tool_tab_locked is True:
|
if self.app.tool_tab_locked is True:
|
||||||
return
|
return
|
||||||
self.set_tool_ui()
|
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
|
self.set_tool_ui()
|
||||||
|
|
||||||
self.properties()
|
self.properties()
|
||||||
|
|
||||||
def install(self, icon=None, separator=None, **kwargs):
|
def install(self, icon=None, separator=None, **kwargs):
|
||||||
|
@ -79,15 +100,15 @@ class Properties(FlatCAMTool):
|
||||||
def properties(self):
|
def properties(self):
|
||||||
obj_list = self.app.collection.get_selected()
|
obj_list = self.app.collection.get_selected()
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Properties Tool was not displayed. No object selected.")
|
self.app.inform.emit(_("[ERROR_NOTCL] Properties Tool was not displayed. No object selected."))
|
||||||
self.app.ui.notebook.setTabText(2, "Tools")
|
self.app.ui.notebook.setTabText(2, _("Tools"))
|
||||||
self.properties_frame.hide()
|
self.properties_frame.hide()
|
||||||
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
|
||||||
return
|
return
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
self.addItems(obj)
|
self.addItems(obj)
|
||||||
self.app.inform.emit("[success] Object Properties are displayed.")
|
self.app.inform.emit(_("[success] Object Properties are displayed."))
|
||||||
self.app.ui.notebook.setTabText(2, "Properties Tool")
|
self.app.ui.notebook.setTabText(2, _("Properties Tool"))
|
||||||
|
|
||||||
def addItems(self, obj):
|
def addItems(self, obj):
|
||||||
parent = self.treeWidget.invisibleRootItem()
|
parent = self.treeWidget.invisibleRootItem()
|
||||||
|
@ -150,8 +171,14 @@ class Properties(FlatCAMTool):
|
||||||
self.addChild(options, [str(option), str(obj.options[option])], True)
|
self.addChild(options, [str(option), str(obj.options[option])], True)
|
||||||
|
|
||||||
if obj.kind.lower() == 'gerber':
|
if obj.kind.lower() == 'gerber':
|
||||||
|
temp_ap = {}
|
||||||
for ap in obj.apertures:
|
for ap in obj.apertures:
|
||||||
self.addChild(apertures, [str(ap), str(obj.apertures[ap])], True)
|
temp_ap.clear()
|
||||||
|
temp_ap = deepcopy(obj.apertures[ap])
|
||||||
|
if obj.apertures[ap]['solid_geometry']:
|
||||||
|
elems = len(obj.apertures[ap]['solid_geometry'])
|
||||||
|
temp_ap['solid_geometry'] = '%s Polygons' % str(elems)
|
||||||
|
self.addChild(apertures, [str(ap), str(temp_ap)], True)
|
||||||
elif obj.kind.lower() == 'excellon':
|
elif obj.kind.lower() == 'excellon':
|
||||||
for tool, value in obj.tools.items():
|
for tool, value in obj.tools.items():
|
||||||
self.addChild(tools, [str(tool), str(value['C'])], True)
|
self.addChild(tools, [str(tool), str(value['C'])], True)
|
||||||
|
|
|
@ -10,9 +10,17 @@
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtGui import QTextCursor
|
from PyQt5.QtGui import QTextCursor
|
||||||
from PyQt5.QtWidgets import QVBoxLayout, QWidget
|
from PyQt5.QtWidgets import QVBoxLayout, QWidget
|
||||||
from GUIElements import _BrowserTextEdit, _ExpandableTextEdit
|
from flatcamGUI.GUIElements import _BrowserTextEdit, _ExpandableTextEdit
|
||||||
import html
|
import html
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class TermWidget(QWidget):
|
class TermWidget(QWidget):
|
||||||
"""
|
"""
|
||||||
|
@ -58,9 +66,9 @@ class TermWidget(QWidget):
|
||||||
self._edit.setTextColor(Qt.white)
|
self._edit.setTextColor(Qt.white)
|
||||||
self._edit.setTextBackgroundColor(Qt.darkGreen)
|
self._edit.setTextBackgroundColor(Qt.darkGreen)
|
||||||
if detail is None:
|
if detail is None:
|
||||||
self._edit.setPlainText("...proccessing...")
|
self._edit.setPlainText(_("...proccessing..."))
|
||||||
else:
|
else:
|
||||||
self._edit.setPlainText("...proccessing... [%s]" % detail)
|
self._edit.setPlainText(_("...proccessing... [%s]") % detail)
|
||||||
|
|
||||||
self._edit.setDisabled(True)
|
self._edit.setDisabled(True)
|
||||||
self._edit.setFocus()
|
self._edit.setFocus()
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from FlatCAMCommon import LoudDict
|
from FlatCAMCommon import LoudDict
|
||||||
from GUIElements import FCComboBox, FCEntry, FCTable
|
from flatcamGUI.GUIElements import FCComboBox, FCEntry, FCTable
|
||||||
from FlatCAMApp import log
|
from FlatCAMApp import log
|
||||||
from camlib import distance, CNCjob
|
from camlib import distance
|
||||||
from FlatCAMObj import FlatCAMCNCjob
|
from FlatCAMObj import FlatCAMCNCjob
|
||||||
|
|
||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
from PyQt5 import QtGui, QtCore, QtWidgets
|
||||||
|
@ -10,16 +18,23 @@ from PyQt5.QtCore import Qt
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from shapely.geometry import MultiPolygon, Polygon, LineString
|
from shapely.geometry import Polygon, LineString
|
||||||
from shapely.geometry.base import BaseGeometry
|
|
||||||
from shapely.ops import cascaded_union
|
from shapely.ops import cascaded_union
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class SolderPaste(FlatCAMTool):
|
class SolderPaste(FlatCAMTool):
|
||||||
toolName = "Solder Paste Tool"
|
toolName = _("Solder Paste Tool")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
FlatCAMTool.__init__(self, app)
|
FlatCAMTool.__init__(self, app)
|
||||||
|
@ -47,15 +62,15 @@ class SolderPaste(FlatCAMTool):
|
||||||
|
|
||||||
self.object_label = QtWidgets.QLabel("Gerber: ")
|
self.object_label = QtWidgets.QLabel("Gerber: ")
|
||||||
self.object_label.setToolTip(
|
self.object_label.setToolTip(
|
||||||
"Gerber Solder paste object. "
|
_("Gerber Solder paste object. ")
|
||||||
)
|
)
|
||||||
obj_form_layout.addRow(self.object_label, self.obj_combo)
|
obj_form_layout.addRow(self.object_label, self.obj_combo)
|
||||||
|
|
||||||
#### Tools ####
|
#### Tools ####
|
||||||
self.tools_table_label = QtWidgets.QLabel('<b>Tools Table</b>')
|
self.tools_table_label = QtWidgets.QLabel('<b>%s</b>' % _('Tools Table'))
|
||||||
self.tools_table_label.setToolTip(
|
self.tools_table_label.setToolTip(
|
||||||
"Tools pool from which the algorithm\n"
|
_("Tools pool from which the algorithm\n"
|
||||||
"will pick the ones used for dispensing solder paste."
|
"will pick the ones used for dispensing solder paste.")
|
||||||
)
|
)
|
||||||
self.layout.addWidget(self.tools_table_label)
|
self.layout.addWidget(self.tools_table_label)
|
||||||
|
|
||||||
|
@ -63,29 +78,29 @@ class SolderPaste(FlatCAMTool):
|
||||||
self.layout.addWidget(self.tools_table)
|
self.layout.addWidget(self.tools_table)
|
||||||
|
|
||||||
self.tools_table.setColumnCount(3)
|
self.tools_table.setColumnCount(3)
|
||||||
self.tools_table.setHorizontalHeaderLabels(['#', 'Diameter', ''])
|
self.tools_table.setHorizontalHeaderLabels(['#', _('Diameter'), ''])
|
||||||
self.tools_table.setColumnHidden(2, True)
|
self.tools_table.setColumnHidden(2, True)
|
||||||
self.tools_table.setSortingEnabled(False)
|
self.tools_table.setSortingEnabled(False)
|
||||||
# self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
# self.tools_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||||
|
|
||||||
self.tools_table.horizontalHeaderItem(0).setToolTip(
|
self.tools_table.horizontalHeaderItem(0).setToolTip(
|
||||||
"This is the Tool Number.\n"
|
_("This is the Tool Number.\n"
|
||||||
"The solder dispensing will start with the tool with the biggest \n"
|
"The solder dispensing will start with the tool with the biggest \n"
|
||||||
"diameter, continuing until there are no more Nozzle tools.\n"
|
"diameter, continuing until there are no more Nozzle tools.\n"
|
||||||
"If there are no longer tools but there are still pads not covered\n "
|
"If there are no longer tools but there are still pads not covered\n "
|
||||||
"with solder paste, the app will issue a warning message box."
|
"with solder paste, the app will issue a warning message box.")
|
||||||
)
|
)
|
||||||
self.tools_table.horizontalHeaderItem(1).setToolTip(
|
self.tools_table.horizontalHeaderItem(1).setToolTip(
|
||||||
"Nozzle tool Diameter. It's value (in current FlatCAM units)\n"
|
_( "Nozzle tool Diameter. It's value (in current FlatCAM units)\n"
|
||||||
"is the width of the solder paste dispensed.")
|
"is the width of the solder paste dispensed."))
|
||||||
|
|
||||||
#### Add a new Tool ####
|
#### Add a new Tool ####
|
||||||
hlay_tools = QtWidgets.QHBoxLayout()
|
hlay_tools = QtWidgets.QHBoxLayout()
|
||||||
self.layout.addLayout(hlay_tools)
|
self.layout.addLayout(hlay_tools)
|
||||||
|
|
||||||
self.addtool_entry_lbl = QtWidgets.QLabel('<b>New Nozzle Tool:</b>')
|
self.addtool_entry_lbl = QtWidgets.QLabel('<b>%s:</b>' % _('New Nozzle Tool'))
|
||||||
self.addtool_entry_lbl.setToolTip(
|
self.addtool_entry_lbl.setToolTip(
|
||||||
"Diameter for the new Nozzle tool to add in the Tool Table"
|
_("Diameter for the new Nozzle tool to add in the Tool Table")
|
||||||
)
|
)
|
||||||
self.addtool_entry = FCEntry()
|
self.addtool_entry = FCEntry()
|
||||||
|
|
||||||
|
@ -97,21 +112,21 @@ class SolderPaste(FlatCAMTool):
|
||||||
grid0 = QtWidgets.QGridLayout()
|
grid0 = QtWidgets.QGridLayout()
|
||||||
self.layout.addLayout(grid0)
|
self.layout.addLayout(grid0)
|
||||||
|
|
||||||
self.addtool_btn = QtWidgets.QPushButton('Add')
|
self.addtool_btn = QtWidgets.QPushButton(_('Add'))
|
||||||
self.addtool_btn.setToolTip(
|
self.addtool_btn.setToolTip(
|
||||||
"Add a new nozzle tool to the Tool Table\n"
|
_("Add a new nozzle tool to the Tool Table\n"
|
||||||
"with the diameter specified above."
|
"with the diameter specified above.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.deltool_btn = QtWidgets.QPushButton('Delete')
|
self.deltool_btn = QtWidgets.QPushButton(_('Delete'))
|
||||||
self.deltool_btn.setToolTip(
|
self.deltool_btn.setToolTip(
|
||||||
"Delete a selection of tools in the Tool Table\n"
|
_( "Delete a selection of tools in the Tool Table\n"
|
||||||
"by first selecting a row(s) in the Tool Table."
|
"by first selecting a row(s) in the Tool Table.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.soldergeo_btn = QtWidgets.QPushButton("Generate Geo")
|
self.soldergeo_btn = QtWidgets.QPushButton(_("Generate Geo"))
|
||||||
self.soldergeo_btn.setToolTip(
|
self.soldergeo_btn.setToolTip(
|
||||||
"Generate solder paste dispensing geometry."
|
_("Generate solder paste dispensing geometry.")
|
||||||
)
|
)
|
||||||
|
|
||||||
grid0.addWidget(self.addtool_btn, 0, 0)
|
grid0.addWidget(self.addtool_btn, 0, 0)
|
||||||
|
@ -124,13 +139,13 @@ class SolderPaste(FlatCAMTool):
|
||||||
grid0_1 = QtWidgets.QGridLayout()
|
grid0_1 = QtWidgets.QGridLayout()
|
||||||
self.layout.addLayout(grid0_1)
|
self.layout.addLayout(grid0_1)
|
||||||
|
|
||||||
step1_lbl = QtWidgets.QLabel("<b>STEP 1:</b>")
|
step1_lbl = QtWidgets.QLabel("<b>%s:</b>" % _('STEP 1'))
|
||||||
step1_lbl.setToolTip(
|
step1_lbl.setToolTip(
|
||||||
"First step is to select a number of nozzle tools for usage\n"
|
_("First step is to select a number of nozzle tools for usage\n"
|
||||||
"and then optionally modify the GCode parameters bellow."
|
"and then optionally modify the GCode parameters bellow.")
|
||||||
)
|
)
|
||||||
step1_description_lbl = QtWidgets.QLabel("Select tools.\n"
|
step1_description_lbl = QtWidgets.QLabel(_("Select tools.\n"
|
||||||
"Modify parameters.")
|
"Modify parameters."))
|
||||||
|
|
||||||
grid0_1.addWidget(step1_lbl, 0, 0, alignment=Qt.AlignTop)
|
grid0_1.addWidget(step1_lbl, 0, 0, alignment=Qt.AlignTop)
|
||||||
grid0_1.addWidget(step1_description_lbl, 0, 2, alignment=Qt.AlignBottom)
|
grid0_1.addWidget(step1_description_lbl, 0, 2, alignment=Qt.AlignBottom)
|
||||||
|
@ -148,120 +163,120 @@ class SolderPaste(FlatCAMTool):
|
||||||
|
|
||||||
# Z dispense start
|
# Z dispense start
|
||||||
self.z_start_entry = FCEntry()
|
self.z_start_entry = FCEntry()
|
||||||
self.z_start_label = QtWidgets.QLabel("Z Dispense Start:")
|
self.z_start_label = QtWidgets.QLabel(_("Z Dispense Start:"))
|
||||||
self.z_start_label.setToolTip(
|
self.z_start_label.setToolTip(
|
||||||
"The height (Z) when solder paste dispensing starts."
|
_("The height (Z) when solder paste dispensing starts.")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.z_start_label, self.z_start_entry)
|
self.gcode_form_layout.addRow(self.z_start_label, self.z_start_entry)
|
||||||
|
|
||||||
# Z dispense
|
# Z dispense
|
||||||
self.z_dispense_entry = FCEntry()
|
self.z_dispense_entry = FCEntry()
|
||||||
self.z_dispense_label = QtWidgets.QLabel("Z Dispense:")
|
self.z_dispense_label = QtWidgets.QLabel(_("Z Dispense:"))
|
||||||
self.z_dispense_label.setToolTip(
|
self.z_dispense_label.setToolTip(
|
||||||
"The height (Z) when doing solder paste dispensing."
|
_("The height (Z) when doing solder paste dispensing.")
|
||||||
|
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.z_dispense_label, self.z_dispense_entry)
|
self.gcode_form_layout.addRow(self.z_dispense_label, self.z_dispense_entry)
|
||||||
|
|
||||||
# Z dispense stop
|
# Z dispense stop
|
||||||
self.z_stop_entry = FCEntry()
|
self.z_stop_entry = FCEntry()
|
||||||
self.z_stop_label = QtWidgets.QLabel("Z Dispense Stop:")
|
self.z_stop_label = QtWidgets.QLabel(_("Z Dispense Stop:"))
|
||||||
self.z_stop_label.setToolTip(
|
self.z_stop_label.setToolTip(
|
||||||
"The height (Z) when solder paste dispensing stops."
|
_("The height (Z) when solder paste dispensing stops.")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.z_stop_label, self.z_stop_entry)
|
self.gcode_form_layout.addRow(self.z_stop_label, self.z_stop_entry)
|
||||||
|
|
||||||
# Z travel
|
# Z travel
|
||||||
self.z_travel_entry = FCEntry()
|
self.z_travel_entry = FCEntry()
|
||||||
self.z_travel_label = QtWidgets.QLabel("Z Travel:")
|
self.z_travel_label = QtWidgets.QLabel(_("Z Travel:"))
|
||||||
self.z_travel_label.setToolTip(
|
self.z_travel_label.setToolTip(
|
||||||
"The height (Z) for travel between pads\n"
|
_( "The height (Z) for travel between pads\n"
|
||||||
"(without dispensing solder paste)."
|
"(without dispensing solder paste).")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.z_travel_label, self.z_travel_entry)
|
self.gcode_form_layout.addRow(self.z_travel_label, self.z_travel_entry)
|
||||||
|
|
||||||
# Z toolchange location
|
# Z toolchange location
|
||||||
self.z_toolchange_entry = FCEntry()
|
self.z_toolchange_entry = FCEntry()
|
||||||
self.z_toolchange_label = QtWidgets.QLabel("Z Toolchange:")
|
self.z_toolchange_label = QtWidgets.QLabel(_("Z Toolchange:"))
|
||||||
self.z_toolchange_label.setToolTip(
|
self.z_toolchange_label.setToolTip(
|
||||||
"The height (Z) for tool (nozzle) change."
|
_( "The height (Z) for tool (nozzle) change.")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.z_toolchange_label, self.z_toolchange_entry)
|
self.gcode_form_layout.addRow(self.z_toolchange_label, self.z_toolchange_entry)
|
||||||
|
|
||||||
# X,Y Toolchange location
|
# X,Y Toolchange location
|
||||||
self.xy_toolchange_entry = FCEntry()
|
self.xy_toolchange_entry = FCEntry()
|
||||||
self.xy_toolchange_label = QtWidgets.QLabel("XY Toolchange:")
|
self.xy_toolchange_label = QtWidgets.QLabel(_("XY Toolchange:"))
|
||||||
self.xy_toolchange_label.setToolTip(
|
self.xy_toolchange_label.setToolTip(
|
||||||
"The X,Y location for tool (nozzle) change.\n"
|
_("The X,Y location for tool (nozzle) change.\n"
|
||||||
"The format is (x, y) where x and y are real numbers."
|
"The format is (x, y) where x and y are real numbers.")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.xy_toolchange_label, self.xy_toolchange_entry)
|
self.gcode_form_layout.addRow(self.xy_toolchange_label, self.xy_toolchange_entry)
|
||||||
|
|
||||||
# Feedrate X-Y
|
# Feedrate X-Y
|
||||||
self.frxy_entry = FCEntry()
|
self.frxy_entry = FCEntry()
|
||||||
self.frxy_label = QtWidgets.QLabel("Feedrate X-Y:")
|
self.frxy_label = QtWidgets.QLabel(_("Feedrate X-Y:"))
|
||||||
self.frxy_label.setToolTip(
|
self.frxy_label.setToolTip(
|
||||||
"Feedrate (speed) while moving on the X-Y plane."
|
_( "Feedrate (speed) while moving on the X-Y plane.")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.frxy_label, self.frxy_entry)
|
self.gcode_form_layout.addRow(self.frxy_label, self.frxy_entry)
|
||||||
|
|
||||||
# Feedrate Z
|
# Feedrate Z
|
||||||
self.frz_entry = FCEntry()
|
self.frz_entry = FCEntry()
|
||||||
self.frz_label = QtWidgets.QLabel("Feedrate Z:")
|
self.frz_label = QtWidgets.QLabel(_("Feedrate Z:"))
|
||||||
self.frz_label.setToolTip(
|
self.frz_label.setToolTip(
|
||||||
"Feedrate (speed) while moving vertically\n"
|
_("Feedrate (speed) while moving vertically\n"
|
||||||
"(on Z plane)."
|
"(on Z plane).")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.frz_label, self.frz_entry)
|
self.gcode_form_layout.addRow(self.frz_label, self.frz_entry)
|
||||||
|
|
||||||
# Feedrate Z Dispense
|
# Feedrate Z Dispense
|
||||||
self.frz_dispense_entry = FCEntry()
|
self.frz_dispense_entry = FCEntry()
|
||||||
self.frz_dispense_label = QtWidgets.QLabel("Feedrate Z Dispense:")
|
self.frz_dispense_label = QtWidgets.QLabel(_("Feedrate Z Dispense:"))
|
||||||
self.frz_dispense_label.setToolTip(
|
self.frz_dispense_label.setToolTip(
|
||||||
"Feedrate (speed) while moving up vertically\n"
|
_( "Feedrate (speed) while moving up vertically\n"
|
||||||
" to Dispense position (on Z plane)."
|
" to Dispense position (on Z plane).")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.frz_dispense_label, self.frz_dispense_entry)
|
self.gcode_form_layout.addRow(self.frz_dispense_label, self.frz_dispense_entry)
|
||||||
|
|
||||||
# Spindle Speed Forward
|
# Spindle Speed Forward
|
||||||
self.speedfwd_entry = FCEntry()
|
self.speedfwd_entry = FCEntry()
|
||||||
self.speedfwd_label = QtWidgets.QLabel("Spindle Speed FWD:")
|
self.speedfwd_label = QtWidgets.QLabel(_("Spindle Speed FWD:"))
|
||||||
self.speedfwd_label.setToolTip(
|
self.speedfwd_label.setToolTip(
|
||||||
"The dispenser speed while pushing solder paste\n"
|
_( "The dispenser speed while pushing solder paste\n"
|
||||||
"through the dispenser nozzle."
|
"through the dispenser nozzle.")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.speedfwd_label, self.speedfwd_entry)
|
self.gcode_form_layout.addRow(self.speedfwd_label, self.speedfwd_entry)
|
||||||
|
|
||||||
# Dwell Forward
|
# Dwell Forward
|
||||||
self.dwellfwd_entry = FCEntry()
|
self.dwellfwd_entry = FCEntry()
|
||||||
self.dwellfwd_label = QtWidgets.QLabel("Dwell FWD:")
|
self.dwellfwd_label = QtWidgets.QLabel(_("Dwell FWD:"))
|
||||||
self.dwellfwd_label.setToolTip(
|
self.dwellfwd_label.setToolTip(
|
||||||
"Pause after solder dispensing."
|
_("Pause after solder dispensing.")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.dwellfwd_label, self.dwellfwd_entry)
|
self.gcode_form_layout.addRow(self.dwellfwd_label, self.dwellfwd_entry)
|
||||||
|
|
||||||
# Spindle Speed Reverse
|
# Spindle Speed Reverse
|
||||||
self.speedrev_entry = FCEntry()
|
self.speedrev_entry = FCEntry()
|
||||||
self.speedrev_label = QtWidgets.QLabel("Spindle Speed REV:")
|
self.speedrev_label = QtWidgets.QLabel(_("Spindle Speed REV:"))
|
||||||
self.speedrev_label.setToolTip(
|
self.speedrev_label.setToolTip(
|
||||||
"The dispenser speed while retracting solder paste\n"
|
_( "The dispenser speed while retracting solder paste\n"
|
||||||
"through the dispenser nozzle."
|
"through the dispenser nozzle.")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.speedrev_label, self.speedrev_entry)
|
self.gcode_form_layout.addRow(self.speedrev_label, self.speedrev_entry)
|
||||||
|
|
||||||
# Dwell Reverse
|
# Dwell Reverse
|
||||||
self.dwellrev_entry = FCEntry()
|
self.dwellrev_entry = FCEntry()
|
||||||
self.dwellrev_label = QtWidgets.QLabel("Dwell REV:")
|
self.dwellrev_label = QtWidgets.QLabel(_("Dwell REV:"))
|
||||||
self.dwellrev_label.setToolTip(
|
self.dwellrev_label.setToolTip(
|
||||||
"Pause after solder paste dispenser retracted,\n"
|
_("Pause after solder paste dispenser retracted,\n"
|
||||||
"to allow pressure equilibrium."
|
"to allow pressure equilibrium.")
|
||||||
)
|
)
|
||||||
self.gcode_form_layout.addRow(self.dwellrev_label, self.dwellrev_entry)
|
self.gcode_form_layout.addRow(self.dwellrev_label, self.dwellrev_entry)
|
||||||
|
|
||||||
# Postprocessors
|
# Postprocessors
|
||||||
pp_label = QtWidgets.QLabel('PostProcessors:')
|
pp_label = QtWidgets.QLabel(_('PostProcessors:'))
|
||||||
pp_label.setToolTip(
|
pp_label.setToolTip(
|
||||||
"Files that control the GCode generation."
|
_("Files that control the GCode generation.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.pp_combo = FCComboBox()
|
self.pp_combo = FCComboBox()
|
||||||
|
@ -272,10 +287,10 @@ class SolderPaste(FlatCAMTool):
|
||||||
grid1 = QtWidgets.QGridLayout()
|
grid1 = QtWidgets.QGridLayout()
|
||||||
self.gcode_box.addLayout(grid1)
|
self.gcode_box.addLayout(grid1)
|
||||||
|
|
||||||
self.solder_gcode_btn = QtWidgets.QPushButton("Generate GCode")
|
self.solder_gcode_btn = QtWidgets.QPushButton(_("Generate GCode"))
|
||||||
self.solder_gcode_btn.setToolTip(
|
self.solder_gcode_btn.setToolTip(
|
||||||
"Generate GCode for Solder Paste dispensing\n"
|
_( "Generate GCode for Solder Paste dispensing\n"
|
||||||
"on PCB pads."
|
"on PCB pads.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.generation_frame = QtWidgets.QFrame()
|
self.generation_frame = QtWidgets.QFrame()
|
||||||
|
@ -290,10 +305,10 @@ class SolderPaste(FlatCAMTool):
|
||||||
grid2 = QtWidgets.QGridLayout()
|
grid2 = QtWidgets.QGridLayout()
|
||||||
self.generation_box.addLayout(grid2)
|
self.generation_box.addLayout(grid2)
|
||||||
|
|
||||||
step2_lbl = QtWidgets.QLabel("<b>STEP 2:</b>")
|
step2_lbl = QtWidgets.QLabel("<b>%s</b>" % _('STEP 2:'))
|
||||||
step2_lbl.setToolTip(
|
step2_lbl.setToolTip(
|
||||||
"Second step is to create a solder paste dispensing\n"
|
_("Second step is to create a solder paste dispensing\n"
|
||||||
"geometry out of an Solder Paste Mask Gerber file."
|
"geometry out of an Solder Paste Mask Gerber file.")
|
||||||
)
|
)
|
||||||
grid2.addWidget(step2_lbl, 0, 0)
|
grid2.addWidget(step2_lbl, 0, 0)
|
||||||
grid2.addWidget(self.soldergeo_btn, 0, 2)
|
grid2.addWidget(self.soldergeo_btn, 0, 2)
|
||||||
|
@ -308,24 +323,24 @@ class SolderPaste(FlatCAMTool):
|
||||||
self.geo_obj_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
|
self.geo_obj_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))
|
||||||
self.geo_obj_combo.setCurrentIndex(1)
|
self.geo_obj_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.geo_object_label = QtWidgets.QLabel("Geo Result:")
|
self.geo_object_label = QtWidgets.QLabel(_("Geo Result:"))
|
||||||
self.geo_object_label.setToolTip(
|
self.geo_object_label.setToolTip(
|
||||||
"Geometry Solder Paste object.\n"
|
_( "Geometry Solder Paste object.\n"
|
||||||
"The name of the object has to end in:\n"
|
"The name of the object has to end in:\n"
|
||||||
"'_solderpaste' as a protection."
|
"'_solderpaste' as a protection.")
|
||||||
)
|
)
|
||||||
geo_form_layout.addRow(self.geo_object_label, self.geo_obj_combo)
|
geo_form_layout.addRow(self.geo_object_label, self.geo_obj_combo)
|
||||||
|
|
||||||
grid3 = QtWidgets.QGridLayout()
|
grid3 = QtWidgets.QGridLayout()
|
||||||
self.generation_box.addLayout(grid3)
|
self.generation_box.addLayout(grid3)
|
||||||
|
|
||||||
step3_lbl = QtWidgets.QLabel("<b>STEP 3:</b>")
|
step3_lbl = QtWidgets.QLabel("<b>%s</b>" % _('STEP 3:'))
|
||||||
step3_lbl.setToolTip(
|
step3_lbl.setToolTip(
|
||||||
"Third step is to select a solder paste dispensing geometry,\n"
|
_( "Third step is to select a solder paste dispensing geometry,\n"
|
||||||
"and then generate a CNCJob object.\n\n"
|
"and then generate a CNCJob object.\n\n"
|
||||||
"REMEMBER: if you want to create a CNCJob with new parameters,\n"
|
"REMEMBER: if you want to create a CNCJob with new parameters,\n"
|
||||||
"first you need to generate a geometry with those new params,\n"
|
"first you need to generate a geometry with those new params,\n"
|
||||||
"and only after that you can generate an updated CNCJob."
|
"and only after that you can generate an updated CNCJob.")
|
||||||
)
|
)
|
||||||
|
|
||||||
grid3.addWidget(step3_lbl, 0, 0)
|
grid3.addWidget(step3_lbl, 0, 0)
|
||||||
|
@ -341,34 +356,34 @@ class SolderPaste(FlatCAMTool):
|
||||||
self.cnc_obj_combo.setRootModelIndex(self.app.collection.index(3, 0, QtCore.QModelIndex()))
|
self.cnc_obj_combo.setRootModelIndex(self.app.collection.index(3, 0, QtCore.QModelIndex()))
|
||||||
self.cnc_obj_combo.setCurrentIndex(1)
|
self.cnc_obj_combo.setCurrentIndex(1)
|
||||||
|
|
||||||
self.cnc_object_label = QtWidgets.QLabel("CNC Result:")
|
self.cnc_object_label = QtWidgets.QLabel(_("CNC Result:"))
|
||||||
self.cnc_object_label.setToolTip(
|
self.cnc_object_label.setToolTip(
|
||||||
"CNCJob Solder paste object.\n"
|
_( "CNCJob Solder paste object.\n"
|
||||||
"In order to enable the GCode save section,\n"
|
"In order to enable the GCode save section,\n"
|
||||||
"the name of the object has to end in:\n"
|
"the name of the object has to end in:\n"
|
||||||
"'_solderpaste' as a protection."
|
"'_solderpaste' as a protection.")
|
||||||
)
|
)
|
||||||
cnc_form_layout.addRow(self.cnc_object_label, self.cnc_obj_combo)
|
cnc_form_layout.addRow(self.cnc_object_label, self.cnc_obj_combo)
|
||||||
|
|
||||||
grid4 = QtWidgets.QGridLayout()
|
grid4 = QtWidgets.QGridLayout()
|
||||||
self.generation_box.addLayout(grid4)
|
self.generation_box.addLayout(grid4)
|
||||||
|
|
||||||
self.solder_gcode_view_btn = QtWidgets.QPushButton("View GCode")
|
self.solder_gcode_view_btn = QtWidgets.QPushButton(_("View GCode"))
|
||||||
self.solder_gcode_view_btn.setToolTip(
|
self.solder_gcode_view_btn.setToolTip(
|
||||||
"View the generated GCode for Solder Paste dispensing\n"
|
_("View the generated GCode for Solder Paste dispensing\n"
|
||||||
"on PCB pads."
|
"on PCB pads.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.solder_gcode_save_btn = QtWidgets.QPushButton("Save GCode")
|
self.solder_gcode_save_btn = QtWidgets.QPushButton(_("Save GCode"))
|
||||||
self.solder_gcode_save_btn.setToolTip(
|
self.solder_gcode_save_btn.setToolTip(
|
||||||
"Save the generated GCode for Solder Paste dispensing\n"
|
_( "Save the generated GCode for Solder Paste dispensing\n"
|
||||||
"on PCB pads, to a file."
|
"on PCB pads, to a file.")
|
||||||
)
|
)
|
||||||
|
|
||||||
step4_lbl = QtWidgets.QLabel("<b>STEP 4:</b>")
|
step4_lbl = QtWidgets.QLabel("<b>%s</b>" % _('STEP 4:'))
|
||||||
step4_lbl.setToolTip(
|
step4_lbl.setToolTip(
|
||||||
"Fourth step (and last) is to select a CNCJob made from \n"
|
_( "Fourth step (and last) is to select a CNCJob made from \n"
|
||||||
"a solder paste dispensing geometry, and then view/save it's GCode."
|
"a solder paste dispensing geometry, and then view/save it's GCode.")
|
||||||
)
|
)
|
||||||
|
|
||||||
grid4.addWidget(step4_lbl, 0, 0)
|
grid4.addWidget(step4_lbl, 0, 0)
|
||||||
|
@ -395,7 +410,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
self.flat_geometry = []
|
self.flat_geometry = []
|
||||||
|
|
||||||
# action to be added in the combobox context menu
|
# action to be added in the combobox context menu
|
||||||
self.combo_context_del_action = QtWidgets.QAction(QtGui.QIcon('share/trash16.png'), "Delete Object")
|
self.combo_context_del_action = QtWidgets.QAction(QtGui.QIcon('share/trash16.png'), _("Delete Object"))
|
||||||
|
|
||||||
## Signals
|
## Signals
|
||||||
self.combo_context_del_action.triggered.connect(self.on_delete_object)
|
self.combo_context_del_action.triggered.connect(self.on_delete_object)
|
||||||
|
@ -411,18 +426,22 @@ class SolderPaste(FlatCAMTool):
|
||||||
|
|
||||||
self.app.object_status_changed.connect(self.update_comboboxes)
|
self.app.object_status_changed.connect(self.update_comboboxes)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolSolderPaste()")
|
self.app.report_usage("ToolSolderPaste()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
@ -456,9 +475,9 @@ class SolderPaste(FlatCAMTool):
|
||||||
|
|
||||||
self.tools_table.setupContextMenu()
|
self.tools_table.setupContextMenu()
|
||||||
self.tools_table.addContextMenu(
|
self.tools_table.addContextMenu(
|
||||||
"Add", lambda: self.on_tool_add(dia=None, muted=None), icon=QtGui.QIcon("share/plus16.png"))
|
_("Add"), lambda: self.on_tool_add(dia=None, muted=None), icon=QtGui.QIcon("share/plus16.png"))
|
||||||
self.tools_table.addContextMenu(
|
self.tools_table.addContextMenu(
|
||||||
"Delete", lambda:
|
_("Delete"), lambda:
|
||||||
self.on_tool_delete(rows_to_delete=None, all=None), icon=QtGui.QIcon("share/delete32.png"))
|
self.on_tool_delete(rows_to_delete=None, all=None), icon=QtGui.QIcon("share/delete32.png"))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -733,16 +752,16 @@ class SolderPaste(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
|
tool_dia = float(self.addtool_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
if tool_dia is None:
|
if tool_dia is None:
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Please enter a tool diameter to add, in Float format.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Please enter a tool diameter to add, in Float format."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if tool_dia == 0:
|
if tool_dia == 0:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, in Float format.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, in Float format."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# construct a list of all 'tooluid' in the self.tooltable_tools
|
# construct a list of all 'tooluid' in the self.tooltable_tools
|
||||||
|
@ -766,12 +785,12 @@ class SolderPaste(FlatCAMTool):
|
||||||
|
|
||||||
if float('%.4f' % tool_dia) in tool_dias:
|
if float('%.4f' % tool_dia) in tool_dias:
|
||||||
if muted is None:
|
if muted is None:
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Adding Nozzle tool cancelled. Tool already in Tool Table.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Adding Nozzle tool cancelled. Tool already in Tool Table."))
|
||||||
self.tools_table.itemChanged.connect(self.on_tool_edit)
|
self.tools_table.itemChanged.connect(self.on_tool_edit)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
if muted is None:
|
if muted is None:
|
||||||
self.app.inform.emit("[success] New Nozzle tool added to Tool Table.")
|
self.app.inform.emit(_("[success] New Nozzle tool added to Tool Table."))
|
||||||
self.tooltable_tools.update({
|
self.tooltable_tools.update({
|
||||||
int(self.tooluid): {
|
int(self.tooluid): {
|
||||||
'tooldia': float('%.4f' % tool_dia),
|
'tooldia': float('%.4f' % tool_dia),
|
||||||
|
@ -804,8 +823,8 @@ class SolderPaste(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.'))
|
new_tool_dia = float(self.tools_table.item(row, 1).text().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
tooluid = int(self.tools_table.item(row, 2).text())
|
tooluid = int(self.tools_table.item(row, 2).text())
|
||||||
|
@ -813,7 +832,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
# identify the tool that was edited and get it's tooluid
|
# identify the tool that was edited and get it's tooluid
|
||||||
if new_tool_dia not in tool_dias:
|
if new_tool_dia not in tool_dias:
|
||||||
self.tooltable_tools[tooluid]['tooldia'] = new_tool_dia
|
self.tooltable_tools[tooluid]['tooldia'] = new_tool_dia
|
||||||
self.app.inform.emit("[success] Nozzle tool from Tool Table was edited.")
|
self.app.inform.emit(_("[success] Nozzle tool from Tool Table was edited."))
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -824,7 +843,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
break
|
break
|
||||||
restore_dia_item = self.tools_table.item(row, 1)
|
restore_dia_item = self.tools_table.item(row, 1)
|
||||||
restore_dia_item.setText(str(old_tool_dia))
|
restore_dia_item.setText(str(old_tool_dia))
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Edit cancelled. New diameter value is already in the Tool Table.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Edit cancelled. New diameter value is already in the Tool Table."))
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
|
|
||||||
def on_tool_delete(self, rows_to_delete=None, all=None):
|
def on_tool_delete(self, rows_to_delete=None, all=None):
|
||||||
|
@ -869,12 +888,12 @@ class SolderPaste(FlatCAMTool):
|
||||||
self.tooltable_tools.pop(t, None)
|
self.tooltable_tools.pop(t, None)
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] Delete failed. Select a Nozzle tool to delete.")
|
self.app.inform.emit(_("[WARNING_NOTCL] Delete failed. Select a Nozzle tool to delete."))
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug(str(e))
|
log.debug(str(e))
|
||||||
|
|
||||||
self.app.inform.emit("[success] Nozzle tool(s) deleted from Tool Table.")
|
self.app.inform.emit(_("[success] Nozzle tool(s) deleted from Tool Table."))
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
|
|
||||||
def on_rmb_combo(self, pos, combo):
|
def on_rmb_combo(self, pos, combo):
|
||||||
|
@ -929,7 +948,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
"""
|
"""
|
||||||
name = self.obj_combo.currentText()
|
name = self.obj_combo.currentText()
|
||||||
if name == '':
|
if name == '':
|
||||||
self.app.inform.emit("[WARNING_NOTCL] No SolderPaste mask Gerber object loaded.")
|
self.app.inform.emit(_("[WARNING_NOTCL] No SolderPaste mask Gerber object loaded."))
|
||||||
return
|
return
|
||||||
|
|
||||||
obj = self.app.collection.get_by_name(name)
|
obj = self.app.collection.get_by_name(name)
|
||||||
|
@ -946,7 +965,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
:param work_object: the source Gerber object from which the geometry is created
|
:param work_object: the source Gerber object from which the geometry is created
|
||||||
:return: a Geometry type object
|
:return: a Geometry type object
|
||||||
"""
|
"""
|
||||||
proc = self.app.proc_container.new("Creating Solder Paste dispensing geometry.")
|
proc = self.app.proc_container.new(_("Creating Solder Paste dispensing geometry."))
|
||||||
obj = work_object
|
obj = work_object
|
||||||
|
|
||||||
# Sort tools in descending order
|
# Sort tools in descending order
|
||||||
|
@ -958,7 +977,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
sorted_tools.sort(reverse=True)
|
sorted_tools.sort(reverse=True)
|
||||||
|
|
||||||
if not sorted_tools:
|
if not sorted_tools:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] No Nozzle tools in the tool table.")
|
self.app.inform.emit(_("[WARNING_NOTCL] No Nozzle tools in the tool table."))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
def flatten(geometry=None, reset=True, pathonly=False):
|
def flatten(geometry=None, reset=True, pathonly=False):
|
||||||
|
@ -1084,17 +1103,17 @@ class SolderPaste(FlatCAMTool):
|
||||||
if not geo_obj.tools[tooluid_key]['solid_geometry']:
|
if not geo_obj.tools[tooluid_key]['solid_geometry']:
|
||||||
a += 1
|
a += 1
|
||||||
if a == len(geo_obj.tools):
|
if a == len(geo_obj.tools):
|
||||||
self.app.inform.emit('[ERROR_NOTCL]Cancelled. Empty file, it has no geometry...')
|
self.app.inform.emit(_('[ERROR_NOTCL] Cancelled. Empty file, it has no geometry...'))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
app_obj.inform.emit("[success] Solder Paste geometry generated successfully...")
|
app_obj.inform.emit(_("[success] Solder Paste geometry generated successfully..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# if we still have geometry not processed at the end of the tools then we failed
|
# if we still have geometry not processed at the end of the tools then we failed
|
||||||
# some or all the pads are not covered with solder paste
|
# some or all the pads are not covered with solder paste
|
||||||
if work_geo:
|
if work_geo:
|
||||||
app_obj.inform.emit("[WARNING_NOTCL] Some or all pads have no solder "
|
app_obj.inform.emit(_("[WARNING_NOTCL] Some or all pads have no solder "
|
||||||
"due of inadequate nozzle diameters...")
|
"due of inadequate nozzle diameters..."))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
if use_thread:
|
if use_thread:
|
||||||
|
@ -1107,7 +1126,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
return
|
return
|
||||||
proc.done()
|
proc.done()
|
||||||
|
|
||||||
self.app.inform.emit("Generating Solder Paste dispensing geometry...")
|
self.app.inform.emit(_("Generating Solder Paste dispensing geometry..."))
|
||||||
# Promise object with the new name
|
# Promise object with the new name
|
||||||
self.app.collection.promise(name)
|
self.app.collection.promise(name)
|
||||||
|
|
||||||
|
@ -1127,11 +1146,11 @@ class SolderPaste(FlatCAMTool):
|
||||||
obj = self.app.collection.get_by_name(name)
|
obj = self.app.collection.get_by_name(name)
|
||||||
|
|
||||||
if name == '':
|
if name == '':
|
||||||
self.app.inform.emit("[WARNING_NOTCL]There is no Geometry object available.")
|
self.app.inform.emit(_("[WARNING_NOTCL] There is no Geometry object available."))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
if obj.special_group != 'solder_paste_tool':
|
if obj.special_group != 'solder_paste_tool':
|
||||||
self.app.inform.emit("[WARNING_NOTCL]This Geometry can't be processed. NOT a solder_paste_tool geometry.")
|
self.app.inform.emit(_("[WARNING_NOTCL] This Geometry can't be processed. NOT a solder_paste_tool geometry."))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
a = 0
|
a = 0
|
||||||
|
@ -1139,7 +1158,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
if obj.tools[tooluid_key]['solid_geometry'] is None:
|
if obj.tools[tooluid_key]['solid_geometry'] is None:
|
||||||
a += 1
|
a += 1
|
||||||
if a == len(obj.tools):
|
if a == len(obj.tools):
|
||||||
self.app.inform.emit('[ERROR_NOTCL]Cancelled. Empty file, it has no geometry...')
|
self.app.inform.emit(_('[ERROR_NOTCL] Cancelled. Empty file, it has no geometry...'))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
# use the name of the first tool selected in self.geo_tools_table which has the diameter passed as tool_dia
|
# use the name of the first tool selected in self.geo_tools_table which has the diameter passed as tool_dia
|
||||||
|
@ -1236,7 +1255,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
def job_thread(app_obj):
|
def job_thread(app_obj):
|
||||||
with self.app.proc_container.new("Generating CNC Code"):
|
with self.app.proc_container.new("Generating CNC Code"):
|
||||||
if app_obj.new_object("cncjob", name, job_init) != 'fail':
|
if app_obj.new_object("cncjob", name, job_init) != 'fail':
|
||||||
app_obj.inform.emit("[success]ToolSolderPaste CNCjob created: %s" % name)
|
app_obj.inform.emit(_("[success] ToolSolderPaste CNCjob created: %s") % name)
|
||||||
app_obj.progress.emit(100)
|
app_obj.progress.emit(100)
|
||||||
|
|
||||||
# Create a promise with the name
|
# Create a promise with the name
|
||||||
|
@ -1268,12 +1287,12 @@ class SolderPaste(FlatCAMTool):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if obj.special_group != 'solder_paste_tool':
|
if obj.special_group != 'solder_paste_tool':
|
||||||
self.app.inform.emit("[WARNING_NOTCL]This CNCJob object can't be processed. "
|
self.app.inform.emit(_("[WARNING_NOTCL] This CNCJob object can't be processed. "
|
||||||
"NOT a solder_paste_tool CNCJob object.")
|
"NOT a solder_paste_tool CNCJob object."))
|
||||||
return
|
return
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL]This CNCJob object can't be processed. "
|
self.app.inform.emit(_("[WARNING_NOTCL] This CNCJob object can't be processed. "
|
||||||
"NOT a solder_paste_tool CNCJob object.")
|
"NOT a solder_paste_tool CNCJob object."))
|
||||||
return
|
return
|
||||||
|
|
||||||
gcode = '(G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s)\n' % \
|
gcode = '(G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s)\n' % \
|
||||||
|
@ -1295,7 +1314,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
lines = StringIO(gcode)
|
lines = StringIO(gcode)
|
||||||
except:
|
except:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] No Gcode in the object...")
|
self.app.inform.emit(_("[ERROR_NOTCL] No Gcode in the object..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1304,7 +1323,7 @@ class SolderPaste(FlatCAMTool):
|
||||||
self.app.ui.code_editor.append(proc_line)
|
self.app.ui.code_editor.append(proc_line)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug('ToolSolderPaste.on_view_gcode() -->%s' % str(e))
|
log.debug('ToolSolderPaste.on_view_gcode() -->%s' % str(e))
|
||||||
self.app.inform.emit('[ERROR]ToolSolderPaste.on_view_gcode() -->%s' % str(e))
|
self.app.inform.emit(_('[ERROR] ToolSolderPaste.on_view_gcode() -->%s') % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.app.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
|
self.app.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
|
||||||
|
@ -1323,8 +1342,8 @@ class SolderPaste(FlatCAMTool):
|
||||||
obj = self.app.collection.get_by_name(name)
|
obj = self.app.collection.get_by_name(name)
|
||||||
|
|
||||||
if obj.special_group != 'solder_paste_tool':
|
if obj.special_group != 'solder_paste_tool':
|
||||||
self.app.inform.emit("[WARNING_NOTCL]This CNCJob object can't be processed. "
|
self.app.inform.emit(_("[WARNING_NOTCL] This CNCJob object can't be processed. "
|
||||||
"NOT a solder_paste_tool CNCJob object.")
|
"NOT a solder_paste_tool CNCJob object."))
|
||||||
return
|
return
|
||||||
|
|
||||||
_filter_ = "G-Code Files (*.nc);;G-Code Files (*.txt);;G-Code Files (*.tap);;G-Code Files (*.cnc);;" \
|
_filter_ = "G-Code Files (*.nc);;G-Code Files (*.txt);;G-Code Files (*.tap);;G-Code Files (*.cnc);;" \
|
||||||
|
@ -1332,16 +1351,16 @@ class SolderPaste(FlatCAMTool):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dir_file_to_save = self.app.get_last_save_folder() + '/' + str(name)
|
dir_file_to_save = self.app.get_last_save_folder() + '/' + str(name)
|
||||||
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(
|
||||||
caption="Export GCode ...",
|
caption=_("Export GCode ..."),
|
||||||
directory=dir_file_to_save,
|
directory=dir_file_to_save,
|
||||||
filter=_filter_
|
filter=_filter_
|
||||||
)
|
)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
filename, _ = QtWidgets.QFileDialog.getSaveFileName(caption="Export Machine Code ...", filter=_filter_)
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export Machine Code ..."), filter=_filter_)
|
||||||
|
|
||||||
if filename == '':
|
if filename == '':
|
||||||
self.app.inform.emit("[WARNING_NOTCL]Export Machine Code cancelled ...")
|
self.app.inform.emit(_("[WARNING_NOTCL] Export Machine Code cancelled ..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
gcode = '(G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s)\n' % \
|
gcode = '(G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s)\n' % \
|
||||||
|
@ -1367,11 +1386,11 @@ class SolderPaste(FlatCAMTool):
|
||||||
for line in lines:
|
for line in lines:
|
||||||
f.write(line)
|
f.write(line)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] No such file or directory")
|
self.app.inform.emit(_("[WARNING_NOTCL] No such file or directory"))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.app.file_saved.emit("gcode", filename)
|
self.app.file_saved.emit("gcode", filename)
|
||||||
self.app.inform.emit("[success] Solder paste dispenser GCode file saved to: %s" % filename)
|
self.app.inform.emit(_("[success] Solder paste dispenser GCode file saved to: %s") % filename)
|
||||||
|
|
||||||
def reset_fields(self):
|
def reset_fields(self):
|
||||||
self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
||||||
|
|
|
@ -1,18 +1,31 @@
|
||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
############################################################
|
||||||
from PyQt5.QtCore import Qt
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
from GUIElements import FCEntry, FCButton, OptionalInputSection
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from FlatCAMObj import *
|
from FlatCAMObj import *
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import FlatCAMTranslation as fcTranslate
|
||||||
|
|
||||||
|
fcTranslate.apply_language('strings')
|
||||||
|
import builtins
|
||||||
|
if '_' not in builtins.__dict__:
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
|
|
||||||
class ToolTransform(FlatCAMTool):
|
class ToolTransform(FlatCAMTool):
|
||||||
|
|
||||||
toolName = "Object Transform"
|
toolName = _("Object Transform")
|
||||||
rotateName = "Rotate"
|
rotateName = _("Rotate")
|
||||||
skewName = "Skew/Shear"
|
skewName = _("Skew/Shear")
|
||||||
scaleName = "Scale"
|
scaleName = _("Scale")
|
||||||
flipName = "Mirror (Flip)"
|
flipName = _("Mirror (Flip)")
|
||||||
offsetName = "Offset"
|
offsetName = _("Offset")
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
FlatCAMTool.__init__(self, app)
|
FlatCAMTool.__init__(self, app)
|
||||||
|
@ -31,7 +44,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
self.transform_lay.addWidget(title_label)
|
self.transform_lay.addWidget(title_label)
|
||||||
|
|
||||||
self.empty_label = QtWidgets.QLabel("")
|
self.empty_label = QtWidgets.QLabel("")
|
||||||
self.empty_label.setFixedWidth(50)
|
self.empty_label.setFixedWidth(70)
|
||||||
|
|
||||||
self.empty_label1 = QtWidgets.QLabel("")
|
self.empty_label1 = QtWidgets.QLabel("")
|
||||||
self.empty_label1.setFixedWidth(70)
|
self.empty_label1.setFixedWidth(70)
|
||||||
|
@ -52,27 +65,27 @@ class ToolTransform(FlatCAMTool):
|
||||||
self.transform_lay.addLayout(form_layout)
|
self.transform_lay.addLayout(form_layout)
|
||||||
form_child = QtWidgets.QHBoxLayout()
|
form_child = QtWidgets.QHBoxLayout()
|
||||||
|
|
||||||
self.rotate_label = QtWidgets.QLabel("Angle:")
|
self.rotate_label = QtWidgets.QLabel(_("Angle:"))
|
||||||
self.rotate_label.setToolTip(
|
self.rotate_label.setToolTip(
|
||||||
"Angle for Rotation action, in degrees.\n"
|
_("Angle for Rotation action, in degrees.\n"
|
||||||
"Float number between -360 and 359.\n"
|
"Float number between -360 and 359.\n"
|
||||||
"Positive numbers for CW motion.\n"
|
"Positive numbers for CW motion.\n"
|
||||||
"Negative numbers for CCW motion."
|
"Negative numbers for CCW motion.")
|
||||||
)
|
)
|
||||||
self.rotate_label.setFixedWidth(50)
|
self.rotate_label.setFixedWidth(70)
|
||||||
|
|
||||||
self.rotate_entry = FCEntry()
|
self.rotate_entry = FCEntry()
|
||||||
# self.rotate_entry.setFixedWidth(60)
|
# self.rotate_entry.setFixedWidth(70)
|
||||||
self.rotate_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.rotate_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
|
|
||||||
self.rotate_button = FCButton()
|
self.rotate_button = FCButton()
|
||||||
self.rotate_button.set_value("Rotate")
|
self.rotate_button.set_value(_("Rotate"))
|
||||||
self.rotate_button.setToolTip(
|
self.rotate_button.setToolTip(
|
||||||
"Rotate the selected object(s).\n"
|
_("Rotate the selected object(s).\n"
|
||||||
"The point of reference is the middle of\n"
|
"The point of reference is the middle of\n"
|
||||||
"the bounding box for all selected objects."
|
"the bounding box for all selected objects.")
|
||||||
)
|
)
|
||||||
self.rotate_button.setFixedWidth(60)
|
self.rotate_button.setFixedWidth(90)
|
||||||
|
|
||||||
form_child.addWidget(self.rotate_entry)
|
form_child.addWidget(self.rotate_entry)
|
||||||
form_child.addWidget(self.rotate_button)
|
form_child.addWidget(self.rotate_button)
|
||||||
|
@ -91,41 +104,41 @@ class ToolTransform(FlatCAMTool):
|
||||||
form1_child_1 = QtWidgets.QHBoxLayout()
|
form1_child_1 = QtWidgets.QHBoxLayout()
|
||||||
form1_child_2 = QtWidgets.QHBoxLayout()
|
form1_child_2 = QtWidgets.QHBoxLayout()
|
||||||
|
|
||||||
self.skewx_label = QtWidgets.QLabel("Angle X:")
|
self.skewx_label = QtWidgets.QLabel(_("Angle X:"))
|
||||||
self.skewx_label.setToolTip(
|
self.skewx_label.setToolTip(
|
||||||
"Angle for Skew action, in degrees.\n"
|
_("Angle for Skew action, in degrees.\n"
|
||||||
"Float number between -360 and 359."
|
"Float number between -360 and 359.")
|
||||||
)
|
)
|
||||||
self.skewx_label.setFixedWidth(50)
|
self.skewx_label.setFixedWidth(70)
|
||||||
self.skewx_entry = FCEntry()
|
self.skewx_entry = FCEntry()
|
||||||
self.skewx_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.skewx_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
# self.skewx_entry.setFixedWidth(60)
|
# self.skewx_entry.setFixedWidth(70)
|
||||||
|
|
||||||
self.skewx_button = FCButton()
|
self.skewx_button = FCButton()
|
||||||
self.skewx_button.set_value("Skew X")
|
self.skewx_button.set_value(_("Skew X"))
|
||||||
self.skewx_button.setToolTip(
|
self.skewx_button.setToolTip(
|
||||||
"Skew/shear the selected object(s).\n"
|
_("Skew/shear the selected object(s).\n"
|
||||||
"The point of reference is the middle of\n"
|
"The point of reference is the middle of\n"
|
||||||
"the bounding box for all selected objects.")
|
"the bounding box for all selected objects."))
|
||||||
self.skewx_button.setFixedWidth(60)
|
self.skewx_button.setFixedWidth(90)
|
||||||
|
|
||||||
self.skewy_label = QtWidgets.QLabel("Angle Y:")
|
self.skewy_label = QtWidgets.QLabel(_("Angle Y:"))
|
||||||
self.skewy_label.setToolTip(
|
self.skewy_label.setToolTip(
|
||||||
"Angle for Skew action, in degrees.\n"
|
_("Angle for Skew action, in degrees.\n"
|
||||||
"Float number between -360 and 359."
|
"Float number between -360 and 359.")
|
||||||
)
|
)
|
||||||
self.skewy_label.setFixedWidth(50)
|
self.skewy_label.setFixedWidth(70)
|
||||||
self.skewy_entry = FCEntry()
|
self.skewy_entry = FCEntry()
|
||||||
self.skewy_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.skewy_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
# self.skewy_entry.setFixedWidth(60)
|
# self.skewy_entry.setFixedWidth(70)
|
||||||
|
|
||||||
self.skewy_button = FCButton()
|
self.skewy_button = FCButton()
|
||||||
self.skewy_button.set_value("Skew Y")
|
self.skewy_button.set_value(_("Skew Y"))
|
||||||
self.skewy_button.setToolTip(
|
self.skewy_button.setToolTip(
|
||||||
"Skew/shear the selected object(s).\n"
|
_("Skew/shear the selected object(s).\n"
|
||||||
"The point of reference is the middle of\n"
|
"The point of reference is the middle of\n"
|
||||||
"the bounding box for all selected objects.")
|
"the bounding box for all selected objects."))
|
||||||
self.skewy_button.setFixedWidth(60)
|
self.skewy_button.setFixedWidth(90)
|
||||||
|
|
||||||
form1_child_1.addWidget(self.skewx_entry)
|
form1_child_1.addWidget(self.skewx_entry)
|
||||||
form1_child_1.addWidget(self.skewx_button)
|
form1_child_1.addWidget(self.skewx_button)
|
||||||
|
@ -148,56 +161,56 @@ class ToolTransform(FlatCAMTool):
|
||||||
form2_child_1 = QtWidgets.QHBoxLayout()
|
form2_child_1 = QtWidgets.QHBoxLayout()
|
||||||
form2_child_2 = QtWidgets.QHBoxLayout()
|
form2_child_2 = QtWidgets.QHBoxLayout()
|
||||||
|
|
||||||
self.scalex_label = QtWidgets.QLabel("Factor X:")
|
self.scalex_label = QtWidgets.QLabel(_("Factor X:"))
|
||||||
self.scalex_label.setToolTip(
|
self.scalex_label.setToolTip(
|
||||||
"Factor for Scale action over X axis."
|
_("Factor for Scale action over X axis.")
|
||||||
)
|
)
|
||||||
self.scalex_label.setFixedWidth(50)
|
self.scalex_label.setFixedWidth(70)
|
||||||
self.scalex_entry = FCEntry()
|
self.scalex_entry = FCEntry()
|
||||||
self.scalex_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.scalex_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
# self.scalex_entry.setFixedWidth(60)
|
# self.scalex_entry.setFixedWidth(70)
|
||||||
|
|
||||||
self.scalex_button = FCButton()
|
self.scalex_button = FCButton()
|
||||||
self.scalex_button.set_value("Scale X")
|
self.scalex_button.set_value(_("Scale X"))
|
||||||
self.scalex_button.setToolTip(
|
self.scalex_button.setToolTip(
|
||||||
"Scale the selected object(s).\n"
|
_("Scale the selected object(s).\n"
|
||||||
"The point of reference depends on \n"
|
"The point of reference depends on \n"
|
||||||
"the Scale reference checkbox state.")
|
"the Scale reference checkbox state."))
|
||||||
self.scalex_button.setFixedWidth(60)
|
self.scalex_button.setFixedWidth(90)
|
||||||
|
|
||||||
self.scaley_label = QtWidgets.QLabel("Factor Y:")
|
self.scaley_label = QtWidgets.QLabel(_("Factor Y:"))
|
||||||
self.scaley_label.setToolTip(
|
self.scaley_label.setToolTip(
|
||||||
"Factor for Scale action over Y axis."
|
_("Factor for Scale action over Y axis.")
|
||||||
)
|
)
|
||||||
self.scaley_label.setFixedWidth(50)
|
self.scaley_label.setFixedWidth(70)
|
||||||
self.scaley_entry = FCEntry()
|
self.scaley_entry = FCEntry()
|
||||||
self.scaley_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.scaley_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
# self.scaley_entry.setFixedWidth(60)
|
# self.scaley_entry.setFixedWidth(70)
|
||||||
|
|
||||||
self.scaley_button = FCButton()
|
self.scaley_button = FCButton()
|
||||||
self.scaley_button.set_value("Scale Y")
|
self.scaley_button.set_value(_("Scale Y"))
|
||||||
self.scaley_button.setToolTip(
|
self.scaley_button.setToolTip(
|
||||||
"Scale the selected object(s).\n"
|
_("Scale the selected object(s).\n"
|
||||||
"The point of reference depends on \n"
|
"The point of reference depends on \n"
|
||||||
"the Scale reference checkbox state.")
|
"the Scale reference checkbox state."))
|
||||||
self.scaley_button.setFixedWidth(60)
|
self.scaley_button.setFixedWidth(90)
|
||||||
|
|
||||||
self.scale_link_cb = FCCheckBox()
|
self.scale_link_cb = FCCheckBox()
|
||||||
self.scale_link_cb.set_value(True)
|
self.scale_link_cb.set_value(True)
|
||||||
self.scale_link_cb.setText("Link")
|
self.scale_link_cb.setText(_("Link"))
|
||||||
self.scale_link_cb.setToolTip(
|
self.scale_link_cb.setToolTip(
|
||||||
"Scale the selected object(s)\n"
|
_("Scale the selected object(s)\n"
|
||||||
"using the Scale Factor X for both axis.")
|
"using the Scale Factor X for both axis."))
|
||||||
self.scale_link_cb.setFixedWidth(50)
|
self.scale_link_cb.setFixedWidth(70)
|
||||||
|
|
||||||
self.scale_zero_ref_cb = FCCheckBox()
|
self.scale_zero_ref_cb = FCCheckBox()
|
||||||
self.scale_zero_ref_cb.set_value(True)
|
self.scale_zero_ref_cb.set_value(True)
|
||||||
self.scale_zero_ref_cb.setText("Scale Reference")
|
self.scale_zero_ref_cb.setText(_("Scale Reference"))
|
||||||
self.scale_zero_ref_cb.setToolTip(
|
self.scale_zero_ref_cb.setToolTip(
|
||||||
"Scale the selected object(s)\n"
|
_("Scale the selected object(s)\n"
|
||||||
"using the origin reference when checked,\n"
|
"using the origin reference when checked,\n"
|
||||||
"and the center of the biggest bounding box\n"
|
"and the center of the biggest bounding box\n"
|
||||||
"of the selected objects when unchecked.")
|
"of the selected objects when unchecked."))
|
||||||
|
|
||||||
form2_child_1.addWidget(self.scalex_entry)
|
form2_child_1.addWidget(self.scalex_entry)
|
||||||
form2_child_1.addWidget(self.scalex_button)
|
form2_child_1.addWidget(self.scalex_button)
|
||||||
|
@ -222,39 +235,39 @@ class ToolTransform(FlatCAMTool):
|
||||||
form3_child_1 = QtWidgets.QHBoxLayout()
|
form3_child_1 = QtWidgets.QHBoxLayout()
|
||||||
form3_child_2 = QtWidgets.QHBoxLayout()
|
form3_child_2 = QtWidgets.QHBoxLayout()
|
||||||
|
|
||||||
self.offx_label = QtWidgets.QLabel("Value X:")
|
self.offx_label = QtWidgets.QLabel(_("Value X:"))
|
||||||
self.offx_label.setToolTip(
|
self.offx_label.setToolTip(
|
||||||
"Value for Offset action on X axis."
|
_("Value for Offset action on X axis.")
|
||||||
)
|
)
|
||||||
self.offx_label.setFixedWidth(50)
|
self.offx_label.setFixedWidth(70)
|
||||||
self.offx_entry = FCEntry()
|
self.offx_entry = FCEntry()
|
||||||
self.offx_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.offx_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
# self.offx_entry.setFixedWidth(60)
|
# self.offx_entry.setFixedWidth(70)
|
||||||
|
|
||||||
self.offx_button = FCButton()
|
self.offx_button = FCButton()
|
||||||
self.offx_button.set_value("Offset X")
|
self.offx_button.set_value(_("Offset X"))
|
||||||
self.offx_button.setToolTip(
|
self.offx_button.setToolTip(
|
||||||
"Offset the selected object(s).\n"
|
_("Offset the selected object(s).\n"
|
||||||
"The point of reference is the middle of\n"
|
"The point of reference is the middle of\n"
|
||||||
"the bounding box for all selected objects.\n")
|
"the bounding box for all selected objects.\n"))
|
||||||
self.offx_button.setFixedWidth(60)
|
self.offx_button.setFixedWidth(90)
|
||||||
|
|
||||||
self.offy_label = QtWidgets.QLabel("Value Y:")
|
self.offy_label = QtWidgets.QLabel(_("Value Y:"))
|
||||||
self.offy_label.setToolTip(
|
self.offy_label.setToolTip(
|
||||||
"Value for Offset action on Y axis."
|
_("Value for Offset action on Y axis.")
|
||||||
)
|
)
|
||||||
self.offy_label.setFixedWidth(50)
|
self.offy_label.setFixedWidth(70)
|
||||||
self.offy_entry = FCEntry()
|
self.offy_entry = FCEntry()
|
||||||
self.offy_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.offy_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
# self.offy_entry.setFixedWidth(60)
|
# self.offy_entry.setFixedWidth(70)
|
||||||
|
|
||||||
self.offy_button = FCButton()
|
self.offy_button = FCButton()
|
||||||
self.offy_button.set_value("Offset Y")
|
self.offy_button.set_value(_("Offset Y"))
|
||||||
self.offy_button.setToolTip(
|
self.offy_button.setToolTip(
|
||||||
"Offset the selected object(s).\n"
|
_("Offset the selected object(s).\n"
|
||||||
"The point of reference is the middle of\n"
|
"The point of reference is the middle of\n"
|
||||||
"the bounding box for all selected objects.\n")
|
"the bounding box for all selected objects.\n"))
|
||||||
self.offy_button.setFixedWidth(60)
|
self.offy_button.setFixedWidth(90)
|
||||||
|
|
||||||
form3_child_1.addWidget(self.offx_entry)
|
form3_child_1.addWidget(self.offx_entry)
|
||||||
form3_child_1.addWidget(self.offx_button)
|
form3_child_1.addWidget(self.offx_button)
|
||||||
|
@ -279,26 +292,26 @@ class ToolTransform(FlatCAMTool):
|
||||||
form4_child_1 = QtWidgets.QHBoxLayout()
|
form4_child_1 = QtWidgets.QHBoxLayout()
|
||||||
|
|
||||||
self.flipx_button = FCButton()
|
self.flipx_button = FCButton()
|
||||||
self.flipx_button.set_value("Flip on X")
|
self.flipx_button.set_value(_("Flip on X"))
|
||||||
self.flipx_button.setToolTip(
|
self.flipx_button.setToolTip(
|
||||||
"Flip the selected object(s) over the X axis.\n"
|
_("Flip the selected object(s) over the X axis.\n"
|
||||||
"Does not create a new object.\n "
|
"Does not create a new object.\n ")
|
||||||
)
|
)
|
||||||
self.flipx_button.setFixedWidth(60)
|
self.flipx_button.setFixedWidth(100)
|
||||||
|
|
||||||
self.flipy_button = FCButton()
|
self.flipy_button = FCButton()
|
||||||
self.flipy_button.set_value("Flip on Y")
|
self.flipy_button.set_value(_("Flip on Y"))
|
||||||
self.flipy_button.setToolTip(
|
self.flipy_button.setToolTip(
|
||||||
"Flip the selected object(s) over the X axis.\n"
|
_("Flip the selected object(s) over the X axis.\n"
|
||||||
"Does not create a new object.\n "
|
"Does not create a new object.\n ")
|
||||||
)
|
)
|
||||||
self.flipy_button.setFixedWidth(60)
|
self.flipy_button.setFixedWidth(90)
|
||||||
|
|
||||||
self.flip_ref_cb = FCCheckBox()
|
self.flip_ref_cb = FCCheckBox()
|
||||||
self.flip_ref_cb.set_value(True)
|
self.flip_ref_cb.set_value(True)
|
||||||
self.flip_ref_cb.setText("Ref Pt")
|
self.flip_ref_cb.setText(_("Ref Pt"))
|
||||||
self.flip_ref_cb.setToolTip(
|
self.flip_ref_cb.setToolTip(
|
||||||
"Flip the selected object(s)\n"
|
_("Flip the selected object(s)\n"
|
||||||
"around the point in Point Entry Field.\n"
|
"around the point in Point Entry Field.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The point coordinates can be captured by\n"
|
"The point coordinates can be captured by\n"
|
||||||
|
@ -306,27 +319,27 @@ class ToolTransform(FlatCAMTool):
|
||||||
"SHIFT key. \n"
|
"SHIFT key. \n"
|
||||||
"Then click Add button to insert coordinates.\n"
|
"Then click Add button to insert coordinates.\n"
|
||||||
"Or enter the coords in format (x, y) in the\n"
|
"Or enter the coords in format (x, y) in the\n"
|
||||||
"Point Entry field and click Flip on X(Y)")
|
"Point Entry field and click Flip on X(Y)"))
|
||||||
self.flip_ref_cb.setFixedWidth(50)
|
self.flip_ref_cb.setFixedWidth(70)
|
||||||
|
|
||||||
self.flip_ref_label = QtWidgets.QLabel("Point:")
|
self.flip_ref_label = QtWidgets.QLabel(_("Point:"))
|
||||||
self.flip_ref_label.setToolTip(
|
self.flip_ref_label.setToolTip(
|
||||||
"Coordinates in format (x, y) used as reference for mirroring.\n"
|
_("Coordinates in format (x, y) used as reference for mirroring.\n"
|
||||||
"The 'x' in (x, y) will be used when using Flip on X and\n"
|
"The 'x' in (x, y) will be used when using Flip on X and\n"
|
||||||
"the 'y' in (x, y) will be used when using Flip on Y and"
|
"the 'y' in (x, y) will be used when using Flip on Y and")
|
||||||
)
|
)
|
||||||
self.flip_ref_label.setFixedWidth(50)
|
self.flip_ref_label.setFixedWidth(70)
|
||||||
self.flip_ref_entry = EvalEntry2("(0, 0)")
|
self.flip_ref_entry = EvalEntry2("(0, 0)")
|
||||||
self.flip_ref_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
self.flip_ref_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
# self.flip_ref_entry.setFixedWidth(60)
|
# self.flip_ref_entry.setFixedWidth(70)
|
||||||
|
|
||||||
self.flip_ref_button = FCButton()
|
self.flip_ref_button = FCButton()
|
||||||
self.flip_ref_button.set_value("Add")
|
self.flip_ref_button.set_value(_("Add"))
|
||||||
self.flip_ref_button.setToolTip(
|
self.flip_ref_button.setToolTip(
|
||||||
"The point coordinates can be captured by\n"
|
_("The point coordinates can be captured by\n"
|
||||||
"left click on canvas together with pressing\n"
|
"left click on canvas together with pressing\n"
|
||||||
"SHIFT key. Then click Add button to insert.")
|
"SHIFT key. Then click Add button to insert."))
|
||||||
self.flip_ref_button.setFixedWidth(60)
|
self.flip_ref_button.setFixedWidth(90)
|
||||||
|
|
||||||
form4_child_hlay.addStretch()
|
form4_child_hlay.addStretch()
|
||||||
form4_child_hlay.addWidget(self.flipx_button)
|
form4_child_hlay.addWidget(self.flipx_button)
|
||||||
|
@ -362,26 +375,30 @@ class ToolTransform(FlatCAMTool):
|
||||||
self.offx_entry.returnPressed.connect(self.on_offx)
|
self.offx_entry.returnPressed.connect(self.on_offx)
|
||||||
self.offy_entry.returnPressed.connect(self.on_offy)
|
self.offy_entry.returnPressed.connect(self.on_offy)
|
||||||
|
|
||||||
def run(self):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("ToolTransform()")
|
self.app.report_usage("ToolTransform()")
|
||||||
|
|
||||||
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
if toggle:
|
||||||
if self.app.ui.splitter.sizes()[0] == 0:
|
# if the splitter is hidden, display it, else hide it but only if the current widget is the same
|
||||||
self.app.ui.splitter.setSizes([1, 1])
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
||||||
|
self.app.ui.splitter.setSizes([0, 1])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
if self.app.ui.splitter.sizes()[0] == 0:
|
||||||
if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
|
self.app.ui.splitter.setSizes([1, 1])
|
||||||
self.app.ui.splitter.setSizes([0, 1])
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
FlatCAMTool.run(self)
|
FlatCAMTool.run(self)
|
||||||
self.set_tool_ui()
|
self.set_tool_ui()
|
||||||
|
|
||||||
self.app.ui.notebook.setTabText(2, "Transform Tool")
|
self.app.ui.notebook.setTabText(2, _("Transform Tool"))
|
||||||
|
|
||||||
def install(self, icon=None, separator=None, **kwargs):
|
def install(self, icon=None, separator=None, **kwargs):
|
||||||
FlatCAMTool.install(self, icon, separator, shortcut='ALT+T', **kwargs)
|
FlatCAMTool.install(self, icon, separator, shortcut='ALT+R', **kwargs)
|
||||||
|
|
||||||
def set_tool_ui(self):
|
def set_tool_ui(self):
|
||||||
## Initialize form
|
## Initialize form
|
||||||
|
@ -448,8 +465,8 @@ class ToolTransform(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
value = float(self.rotate_entry.get_value().replace(',', '.'))
|
value = float(self.rotate_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered for Rotate, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered for Rotate, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
self.app.worker_task.emit({'fcn': self.on_rotate_action,
|
self.app.worker_task.emit({'fcn': self.on_rotate_action,
|
||||||
'params': [value]})
|
'params': [value]})
|
||||||
|
@ -482,8 +499,8 @@ class ToolTransform(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
value = float(self.skewx_entry.get_value().replace(',', '.'))
|
value = float(self.skewx_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered for Skew X, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered for Skew X, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# self.on_skew("X", value)
|
# self.on_skew("X", value)
|
||||||
|
@ -500,8 +517,8 @@ class ToolTransform(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
value = float(self.skewy_entry.get_value().replace(',', '.'))
|
value = float(self.skewy_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered for Skew Y, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered for Skew Y, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# self.on_skew("Y", value)
|
# self.on_skew("Y", value)
|
||||||
|
@ -518,8 +535,8 @@ class ToolTransform(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
xvalue = float(self.scalex_entry.get_value().replace(',', '.'))
|
xvalue = float(self.scalex_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered for Scale X, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered for Scale X, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# scaling to zero has no sense so we remove it, because scaling with 1 does nothing
|
# scaling to zero has no sense so we remove it, because scaling with 1 does nothing
|
||||||
|
@ -552,8 +569,8 @@ class ToolTransform(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
yvalue = float(self.scaley_entry.get_value().replace(',', '.'))
|
yvalue = float(self.scaley_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered for Scale Y, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered for Scale Y, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# scaling to zero has no sense so we remove it, because scaling with 1 does nothing
|
# scaling to zero has no sense so we remove it, because scaling with 1 does nothing
|
||||||
|
@ -581,8 +598,8 @@ class ToolTransform(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
value = float(self.offx_entry.get_value().replace(',', '.'))
|
value = float(self.offx_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered for Offset X, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered for Offset X, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# self.on_offset("X", value)
|
# self.on_offset("X", value)
|
||||||
|
@ -599,8 +616,8 @@ class ToolTransform(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
value = float(self.offy_entry.get_value().replace(',', '.'))
|
value = float(self.offy_entry.get_value().replace(',', '.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.app.inform.emit("[ERROR_NOTCL]Wrong value format entered for Offset Y, "
|
self.app.inform.emit(_("[ERROR_NOTCL]Wrong value format entered for Offset Y, "
|
||||||
"use a number.")
|
"use a number."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# self.on_offset("Y", value)
|
# self.on_offset("Y", value)
|
||||||
|
@ -617,10 +634,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
ymaxlist = []
|
ymaxlist = []
|
||||||
|
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] No object selected. Please Select an object to rotate!")
|
self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to rotate!"))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
with self.app.proc_container.new("Appying Rotate"):
|
with self.app.proc_container.new(_("Appying Rotate")):
|
||||||
try:
|
try:
|
||||||
# first get a bounding box to fit all
|
# first get a bounding box to fit all
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
|
@ -645,7 +662,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
px = 0.5 * (xminimal + xmaximal)
|
px = 0.5 * (xminimal + xmaximal)
|
||||||
py = 0.5 * (yminimal + ymaximal)
|
py = 0.5 * (yminimal + ymaximal)
|
||||||
if isinstance(sel_obj, FlatCAMCNCjob):
|
if isinstance(sel_obj, FlatCAMCNCjob):
|
||||||
self.app.inform.emit("CNCJob objects can't be rotated.")
|
self.app.inform.emit(_("CNCJob objects can't be rotated."))
|
||||||
else:
|
else:
|
||||||
sel_obj.rotate(-num, point=(px, py))
|
sel_obj.rotate(-num, point=(px, py))
|
||||||
sel_obj.plot()
|
sel_obj.plot()
|
||||||
|
@ -654,11 +671,11 @@ class ToolTransform(FlatCAMTool):
|
||||||
# add information to the object that it was changed and how much
|
# add information to the object that it was changed and how much
|
||||||
sel_obj.options['rotate'] = num
|
sel_obj.options['rotate'] = num
|
||||||
|
|
||||||
self.app.inform.emit('[success]Rotate done ...')
|
self.app.inform.emit(_('[success]Rotate done ...'))
|
||||||
self.app.progress.emit(100)
|
self.app.progress.emit(100)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Due of %s, rotation movement was not executed." % str(e))
|
self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, rotation movement was not executed.") % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_flip(self, axis):
|
def on_flip(self, axis):
|
||||||
|
@ -669,10 +686,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
ymaxlist = []
|
ymaxlist = []
|
||||||
|
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] No object selected. Please Select an object to flip!")
|
self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to flip!"))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
with self.app.proc_container.new("Applying Flip"):
|
with self.app.proc_container.new(_("Applying Flip")):
|
||||||
try:
|
try:
|
||||||
# get mirroring coords from the point entry
|
# get mirroring coords from the point entry
|
||||||
if self.flip_ref_cb.isChecked():
|
if self.flip_ref_cb.isChecked():
|
||||||
|
@ -704,7 +721,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
# execute mirroring
|
# execute mirroring
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
if isinstance(obj, FlatCAMCNCjob):
|
if isinstance(obj, FlatCAMCNCjob):
|
||||||
self.app.inform.emit("CNCJob objects can't be mirrored/flipped.")
|
self.app.inform.emit(_("CNCJob objects can't be mirrored/flipped."))
|
||||||
else:
|
else:
|
||||||
if axis is 'X':
|
if axis is 'X':
|
||||||
obj.mirror('X', (px, py))
|
obj.mirror('X', (px, py))
|
||||||
|
@ -715,7 +732,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
else:
|
else:
|
||||||
obj.options['mirror_y'] = True
|
obj.options['mirror_y'] = True
|
||||||
obj.plot()
|
obj.plot()
|
||||||
self.app.inform.emit('[success]Flip on the Y axis done ...')
|
self.app.inform.emit(_('[success]Flip on the Y axis done ...'))
|
||||||
elif axis is 'Y':
|
elif axis is 'Y':
|
||||||
obj.mirror('Y', (px, py))
|
obj.mirror('Y', (px, py))
|
||||||
# add information to the object that it was changed and how much
|
# add information to the object that it was changed and how much
|
||||||
|
@ -725,12 +742,12 @@ class ToolTransform(FlatCAMTool):
|
||||||
else:
|
else:
|
||||||
obj.options['mirror_x'] = True
|
obj.options['mirror_x'] = True
|
||||||
obj.plot()
|
obj.plot()
|
||||||
self.app.inform.emit('[success]Flip on the X axis done ...')
|
self.app.inform.emit(_('[success]Flip on the X axis done ...'))
|
||||||
self.app.object_changed.emit(obj)
|
self.app.object_changed.emit(obj)
|
||||||
self.app.progress.emit(100)
|
self.app.progress.emit(100)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Due of %s, Flip action was not executed." % str(e))
|
self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Flip action was not executed.") % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_skew(self, axis, num):
|
def on_skew(self, axis, num):
|
||||||
|
@ -739,10 +756,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
yminlist = []
|
yminlist = []
|
||||||
|
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] No object selected. Please Select an object to shear/skew!")
|
self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to shear/skew!"))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
with self.app.proc_container.new("Applying Skew"):
|
with self.app.proc_container.new(_("Applying Skew")):
|
||||||
try:
|
try:
|
||||||
# first get a bounding box to fit all
|
# first get a bounding box to fit all
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
|
@ -761,7 +778,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
|
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
if isinstance(obj, FlatCAMCNCjob):
|
if isinstance(obj, FlatCAMCNCjob):
|
||||||
self.app.inform.emit("CNCJob objects can't be skewed.")
|
self.app.inform.emit(_("CNCJob objects can't be skewed."))
|
||||||
else:
|
else:
|
||||||
if axis is 'X':
|
if axis is 'X':
|
||||||
obj.skew(num, 0, point=(xminimal, yminimal))
|
obj.skew(num, 0, point=(xminimal, yminimal))
|
||||||
|
@ -773,11 +790,11 @@ class ToolTransform(FlatCAMTool):
|
||||||
obj.options['skew_y'] = num
|
obj.options['skew_y'] = num
|
||||||
obj.plot()
|
obj.plot()
|
||||||
self.app.object_changed.emit(obj)
|
self.app.object_changed.emit(obj)
|
||||||
self.app.inform.emit('[success]Skew on the %s axis done ...' % str(axis))
|
self.app.inform.emit(_('[success]Skew on the %s axis done ...') % str(axis))
|
||||||
self.app.progress.emit(100)
|
self.app.progress.emit(100)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Due of %s, Skew action was not executed." % str(e))
|
self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Skew action was not executed.") % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_scale(self, axis, xfactor, yfactor, point=None):
|
def on_scale(self, axis, xfactor, yfactor, point=None):
|
||||||
|
@ -788,10 +805,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
ymaxlist = []
|
ymaxlist = []
|
||||||
|
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] No object selected. Please Select an object to scale!")
|
self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to scale!"))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
with self.app.proc_container.new("Applying Scale"):
|
with self.app.proc_container.new(_("Applying Scale")):
|
||||||
try:
|
try:
|
||||||
# first get a bounding box to fit all
|
# first get a bounding box to fit all
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
|
@ -821,7 +838,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
|
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
if isinstance(obj, FlatCAMCNCjob):
|
if isinstance(obj, FlatCAMCNCjob):
|
||||||
self.app.inform.emit("CNCJob objects can't be scaled.")
|
self.app.inform.emit(_("CNCJob objects can't be scaled."))
|
||||||
else:
|
else:
|
||||||
obj.scale(xfactor, yfactor, point=(px, py))
|
obj.scale(xfactor, yfactor, point=(px, py))
|
||||||
# add information to the object that it was changed and how much
|
# add information to the object that it was changed and how much
|
||||||
|
@ -829,10 +846,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
obj.options['scale_y'] = yfactor
|
obj.options['scale_y'] = yfactor
|
||||||
obj.plot()
|
obj.plot()
|
||||||
self.app.object_changed.emit(obj)
|
self.app.object_changed.emit(obj)
|
||||||
self.app.inform.emit('[success]Scale on the %s axis done ...' % str(axis))
|
self.app.inform.emit(_('[success] Scale on the %s axis done ...') % str(axis))
|
||||||
self.app.progress.emit(100)
|
self.app.progress.emit(100)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Due of %s, Scale action was not executed." % str(e))
|
self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Scale action was not executed.") % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_offset(self, axis, num):
|
def on_offset(self, axis, num):
|
||||||
|
@ -841,10 +858,10 @@ class ToolTransform(FlatCAMTool):
|
||||||
yminlist = []
|
yminlist = []
|
||||||
|
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
self.app.inform.emit("[WARNING_NOTCL] No object selected. Please Select an object to offset!")
|
self.app.inform.emit(_("[WARNING_NOTCL] No object selected. Please Select an object to offset!"))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
with self.app.proc_container.new("Applying Offset"):
|
with self.app.proc_container.new(_("Applying Offset")):
|
||||||
try:
|
try:
|
||||||
# first get a bounding box to fit all
|
# first get a bounding box to fit all
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
|
@ -862,7 +879,7 @@ class ToolTransform(FlatCAMTool):
|
||||||
|
|
||||||
for obj in obj_list:
|
for obj in obj_list:
|
||||||
if isinstance(obj, FlatCAMCNCjob):
|
if isinstance(obj, FlatCAMCNCjob):
|
||||||
self.app.inform.emit("CNCJob objects can't be offseted.")
|
self.app.inform.emit(_("CNCJob objects can't be offseted."))
|
||||||
else:
|
else:
|
||||||
if axis is 'X':
|
if axis is 'X':
|
||||||
obj.offset((num, 0))
|
obj.offset((num, 0))
|
||||||
|
@ -874,11 +891,11 @@ class ToolTransform(FlatCAMTool):
|
||||||
obj.options['offset_y'] = num
|
obj.options['offset_y'] = num
|
||||||
obj.plot()
|
obj.plot()
|
||||||
self.app.object_changed.emit(obj)
|
self.app.object_changed.emit(obj)
|
||||||
self.app.inform.emit('[success]Offset on the %s axis done ...' % str(axis))
|
self.app.inform.emit(_('[success]Offset on the %s axis done ...') % str(axis))
|
||||||
self.app.progress.emit(100)
|
self.app.progress.emit(100)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.app.inform.emit("[ERROR_NOTCL] Due of %s, Offset action was not executed." % str(e))
|
self.app.inform.emit(_("[ERROR_NOTCL] Due of %s, Offset action was not executed.") % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
# end of file
|
# end of file
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
10
make_win.py
10
make_win.py
|
@ -2,10 +2,10 @@
|
||||||
# FlatCAM: 2D Post-processing for Manufacturing #
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
# http://flatcam.org #
|
# http://flatcam.org #
|
||||||
# Author: Juan Pablo Caram (c) #
|
# Author: Juan Pablo Caram (c) #
|
||||||
# Date: 12/20/2018 #
|
# Date: 12/20/2018 #
|
||||||
# MIT Licence #
|
# MIT Licence #
|
||||||
# #
|
# #
|
||||||
# Creates a portable copy of FlatCAM, including Python #
|
# Creates a portable copy of FlatCAM, including Python #
|
||||||
# itself and all dependencies. #
|
# itself and all dependencies. #
|
||||||
# #
|
# #
|
||||||
# This is not an aid to install FlatCAM from source on #
|
# This is not an aid to install FlatCAM from source on #
|
||||||
|
@ -13,6 +13,12 @@
|
||||||
# and running and ready to be packaged. #
|
# and running and ready to be packaged. #
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
# File Modified (major mod): Marius Adrian Stanciu #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
|
||||||
# Files not needed: Qt, tk.dll, tcl.dll, tk/, tcl/, vtk/,
|
# Files not needed: Qt, tk.dll, tcl.dll, tk/, tcl/, vtk/,
|
||||||
# scipy.lib.lapack.flapack.pyd, scipy.lib.blas.fblas.pyd,
|
# scipy.lib.lapack.flapack.pyd, scipy.lib.blas.fblas.pyd,
|
||||||
# numpy.core._dotblas.pyd, scipy.sparse.sparsetools._bsr.pyd,
|
# numpy.core._dotblas.pyd, scipy.sparse.sparsetools._bsr.pyd,
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Matthieu Berthomé #
|
||||||
|
# Date: 5/26/2017 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Matthieu Berthomé #
|
||||||
|
# Date: 5/26/2017 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Matthieu Berthomé #
|
||||||
|
# Date: 5/26/2017 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
# This post processor is configured to output code that
|
# This post processor is configured to output code that
|
||||||
|
@ -42,7 +50,7 @@ class grbl_laser(FlatCAMPostProc):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def lift_code(self, p):
|
def lift_code(self, p):
|
||||||
return 'M05'
|
return 'M05 S0'
|
||||||
|
|
||||||
def down_code(self, p):
|
def down_code(self, p):
|
||||||
if p.spindlespeed:
|
if p.spindlespeed:
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
############################################################
|
||||||
|
# FlatCAM: 2D Post-processing for Manufacturing #
|
||||||
|
# http://flatcam.org #
|
||||||
|
# File Author: Marius Adrian Stanciu (c) #
|
||||||
|
# Date: 3/10/2019 #
|
||||||
|
# MIT Licence #
|
||||||
|
############################################################
|
||||||
|
|
||||||
from FlatCAMPostProc import *
|
from FlatCAMPostProc import *
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 414 B |
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 415 B |
Binary file not shown.
After Width: | Height: | Size: 287 B |
|
@ -81,6 +81,11 @@ class TclCommandDrillcncjob(TclCommandSignaled):
|
||||||
if not isinstance(obj, FlatCAMExcellon):
|
if not isinstance(obj, FlatCAMExcellon):
|
||||||
self.raise_tcl_error('Expected FlatCAMExcellon, got %s %s.' % (name, type(obj)))
|
self.raise_tcl_error('Expected FlatCAMExcellon, got %s %s.' % (name, type(obj)))
|
||||||
|
|
||||||
|
xmin = obj.options['xmin']
|
||||||
|
ymin = obj.options['ymin']
|
||||||
|
xmax = obj.options['xmax']
|
||||||
|
ymax = obj.options['ymax']
|
||||||
|
|
||||||
def job_init(job_obj, app_obj):
|
def job_init(job_obj, app_obj):
|
||||||
|
|
||||||
drillz = args["drillz"] if "drillz" in args else obj.options["drillz"]
|
drillz = args["drillz"] if "drillz" in args else obj.options["drillz"]
|
||||||
|
@ -93,10 +98,22 @@ class TclCommandDrillcncjob(TclCommandSignaled):
|
||||||
job_obj.pp_excellon_name = args["ppname_e"] if "ppname_e" in args \
|
job_obj.pp_excellon_name = args["ppname_e"] if "ppname_e" in args \
|
||||||
else obj.options["ppname_e"]
|
else obj.options["ppname_e"]
|
||||||
|
|
||||||
|
job_obj.coords_decimals = int(self.app.defaults["cncjob_coords_decimals"])
|
||||||
|
job_obj.fr_decimals = int(self.app.defaults["cncjob_fr_decimals"])
|
||||||
|
|
||||||
|
job_obj.options['type'] = 'Excellon'
|
||||||
|
|
||||||
toolchange = True if "toolchange" in args and args["toolchange"] == 1 else False
|
toolchange = True if "toolchange" in args and args["toolchange"] == 1 else False
|
||||||
toolchangez = args["toolchangez"] if "toolchangez" in args else obj.options["toolchangez"]
|
toolchangez = args["toolchangez"] if "toolchangez" in args else obj.options["toolchangez"]
|
||||||
job_obj.toolchangexy = args["toolchangexy"] if "toolchangexy" in args else obj.options["toolchangexy"]
|
job_obj.toolchangexy = args["toolchangexy"] if "toolchangexy" in args else obj.options["toolchangexy"]
|
||||||
|
|
||||||
|
job_obj.toolchange_xy_type = "excellon"
|
||||||
|
|
||||||
|
job_obj.options['xmin'] = xmin
|
||||||
|
job_obj.options['ymin'] = ymin
|
||||||
|
job_obj.options['xmax'] = xmax
|
||||||
|
job_obj.options['ymax'] = ymax
|
||||||
|
|
||||||
endz = args["endz"] if "endz" in args else obj.options["endz"]
|
endz = args["endz"] if "endz" in args else obj.options["endz"]
|
||||||
|
|
||||||
tools = args["tools"] if "tools" in args else 'all'
|
tools = args["tools"] if "tools" in args else 'all'
|
||||||
|
|
Loading…
Reference in New Issue