- QRCode Tool: added ability to save the generated QRCode as SVG file or PNG file
- QRCode Tool: added the feature to save the PNG file with transparent background - QRCode Tool: added GUI category in Preferences window
This commit is contained in:
parent
ae7fbdf7c0
commit
97809b6de1
@ -849,6 +849,17 @@ class App(QtCore.QObject):
|
|||||||
"tools_cr_dh": self.ui.tools2_defaults_form.tools2_checkrules_group.drill_size_cb,
|
"tools_cr_dh": self.ui.tools2_defaults_form.tools2_checkrules_group.drill_size_cb,
|
||||||
"tools_cr_dh_val": self.ui.tools2_defaults_form.tools2_checkrules_group.drill_size_entry,
|
"tools_cr_dh_val": self.ui.tools2_defaults_form.tools2_checkrules_group.drill_size_entry,
|
||||||
|
|
||||||
|
# QRCode Tool
|
||||||
|
"tools_qrcode_version": self.ui.tools2_defaults_form.tools2_qrcode_group.version_entry,
|
||||||
|
"tools_qrcode_error": self.ui.tools2_defaults_form.tools2_qrcode_group.error_radio,
|
||||||
|
"tools_qrcode_box_size": self.ui.tools2_defaults_form.tools2_qrcode_group.bsize_entry,
|
||||||
|
"tools_qrcode_border_size": self.ui.tools2_defaults_form.tools2_qrcode_group.border_size_entry,
|
||||||
|
"tools_qrcode_qrdata": self.ui.tools2_defaults_form.tools2_qrcode_group.text_data,
|
||||||
|
"tools_qrcode_polarity": self.ui.tools2_defaults_form.tools2_qrcode_group.pol_radio,
|
||||||
|
"tools_qrcode_rounded": self.ui.tools2_defaults_form.tools2_qrcode_group.bb_radio,
|
||||||
|
"tools_qrcode_fill_color": self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_entry,
|
||||||
|
"tools_qrcode_back_color": self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_entry,
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
# File associations
|
# File associations
|
||||||
"fa_excellon": self.ui.util_defaults_form.fa_excellon_group.exc_list_text,
|
"fa_excellon": self.ui.util_defaults_form.fa_excellon_group.exc_list_text,
|
||||||
@ -1308,6 +1319,17 @@ class App(QtCore.QObject):
|
|||||||
"tools_cr_dh": True,
|
"tools_cr_dh": True,
|
||||||
"tools_cr_dh_val": 0.011811,
|
"tools_cr_dh_val": 0.011811,
|
||||||
|
|
||||||
|
# QRCode Tool
|
||||||
|
"tools_qrcode_version": 1,
|
||||||
|
"tools_qrcode_error": 'L',
|
||||||
|
"tools_qrcode_box_size": 3,
|
||||||
|
"tools_qrcode_border_size": 4,
|
||||||
|
"tools_qrcode_qrdata": '',
|
||||||
|
"tools_qrcode_polarity": 'pos',
|
||||||
|
"tools_qrcode_rounded": 's',
|
||||||
|
"tools_qrcode_fill_color": '#000000',
|
||||||
|
"tools_qrcode_back_color": '#FFFFFF',
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
# file associations
|
# file associations
|
||||||
"fa_excellon": 'drd, drl, exc, ncd, tap, xln',
|
"fa_excellon": 'drd, drl, exc, ncd, tap, xln',
|
||||||
@ -1731,6 +1753,17 @@ class App(QtCore.QObject):
|
|||||||
self.ui.tools_defaults_form.tools_film_group.film_color_button.setStyleSheet(
|
self.ui.tools_defaults_form.tools_film_group.film_color_button.setStyleSheet(
|
||||||
"background-color:%s" % str(self.defaults['tools_film_color'])[:7])
|
"background-color:%s" % str(self.defaults['tools_film_color'])[:7])
|
||||||
|
|
||||||
|
# Init the Tool QRCode colors
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_entry.set_value(
|
||||||
|
self.defaults['tools_qrcode_fill_color'])
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_button.setStyleSheet(
|
||||||
|
"background-color:%s" % str(self.defaults['tools_qrcode_fill_color'])[:7])
|
||||||
|
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_entry.set_value(
|
||||||
|
self.defaults['tools_qrcode_back_color'])
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_button.setStyleSheet(
|
||||||
|
"background-color:%s" % str(self.defaults['tools_qrcode_back_color'])[:7])
|
||||||
|
|
||||||
# ### End of Data ####
|
# ### End of Data ####
|
||||||
|
|
||||||
# ##############################################
|
# ##############################################
|
||||||
@ -2113,11 +2146,22 @@ class App(QtCore.QObject):
|
|||||||
self.on_annotation_fontcolor_button)
|
self.on_annotation_fontcolor_button)
|
||||||
|
|
||||||
# ########## Tools related signals #############
|
# ########## Tools related signals #############
|
||||||
|
# Film Tool
|
||||||
self.ui.tools_defaults_form.tools_film_group.film_color_entry.editingFinished.connect(
|
self.ui.tools_defaults_form.tools_film_group.film_color_entry.editingFinished.connect(
|
||||||
self.on_film_color_entry)
|
self.on_film_color_entry)
|
||||||
self.ui.tools_defaults_form.tools_film_group.film_color_button.clicked.connect(
|
self.ui.tools_defaults_form.tools_film_group.film_color_button.clicked.connect(
|
||||||
self.on_film_color_button)
|
self.on_film_color_button)
|
||||||
|
|
||||||
|
# QRCode Tool
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_entry.editingFinished.connect(
|
||||||
|
self.on_qrcode_fill_color_entry)
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_button.clicked.connect(
|
||||||
|
self.on_qrcode_fill_color_button)
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_entry.editingFinished.connect(
|
||||||
|
self.on_qrcode_back_color_entry)
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_button.clicked.connect(
|
||||||
|
self.on_qrcode_back_color_button)
|
||||||
|
|
||||||
# portability changed signal
|
# portability changed signal
|
||||||
self.ui.general_defaults_form.general_app_group.portability_cb.stateChanged.connect(self.on_portable_checked)
|
self.ui.general_defaults_form.general_app_group.portability_cb.stateChanged.connect(self.on_portable_checked)
|
||||||
|
|
||||||
@ -6701,6 +6745,58 @@ class App(QtCore.QObject):
|
|||||||
self.ui.tools_defaults_form.tools_film_group.film_color_entry.set_value(new_val_sel)
|
self.ui.tools_defaults_form.tools_film_group.film_color_entry.set_value(new_val_sel)
|
||||||
self.defaults['tools_film_color'] = new_val_sel
|
self.defaults['tools_film_color'] = new_val_sel
|
||||||
|
|
||||||
|
def on_qrcode_fill_color_entry(self):
|
||||||
|
self.defaults['tools_qrcode_fill_color'] = \
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_entry.get_value()
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_button.setStyleSheet(
|
||||||
|
"background-color:%s" % str(self.defaults['tools_qrcode_fill_color']))
|
||||||
|
|
||||||
|
def on_qrcode_fill_color_button(self):
|
||||||
|
current_color = QtGui.QColor(self.defaults['tools_qrcode_fill_color'])
|
||||||
|
|
||||||
|
c_dialog = QtWidgets.QColorDialog()
|
||||||
|
fill_color = c_dialog.getColor(initial=current_color)
|
||||||
|
|
||||||
|
if fill_color.isValid() is False:
|
||||||
|
return
|
||||||
|
|
||||||
|
# if new color is different then mark that the Preferences are changed
|
||||||
|
if fill_color != current_color:
|
||||||
|
self.on_preferences_edited()
|
||||||
|
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_button.setStyleSheet(
|
||||||
|
"background-color:%s" % str(fill_color.name()))
|
||||||
|
|
||||||
|
new_val_sel = str(fill_color.name())
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.fill_color_entry.set_value(new_val_sel)
|
||||||
|
self.defaults['tools_qrcode_fill_color'] = new_val_sel
|
||||||
|
|
||||||
|
def on_qrcode_back_color_entry(self):
|
||||||
|
self.defaults['tools_qrcode_back_color'] = \
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_entry.get_value()
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_button.setStyleSheet(
|
||||||
|
"background-color:%s" % str(self.defaults['tools_qrcode_back_color']))
|
||||||
|
|
||||||
|
def on_qrcode_back_color_button(self):
|
||||||
|
current_color = QtGui.QColor(self.defaults['tools_qrcode_back_color'])
|
||||||
|
|
||||||
|
c_dialog = QtWidgets.QColorDialog()
|
||||||
|
back_color = c_dialog.getColor(initial=current_color)
|
||||||
|
|
||||||
|
if back_color.isValid() is False:
|
||||||
|
return
|
||||||
|
|
||||||
|
# if new color is different then mark that the Preferences are changed
|
||||||
|
if back_color != current_color:
|
||||||
|
self.on_preferences_edited()
|
||||||
|
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_button.setStyleSheet(
|
||||||
|
"background-color:%s" % str(back_color.name()))
|
||||||
|
|
||||||
|
new_val_sel = str(back_color.name())
|
||||||
|
self.ui.tools2_defaults_form.tools2_qrcode_group.back_color_entry.set_value(new_val_sel)
|
||||||
|
self.defaults['tools_qrcode_back_color'] = new_val_sel
|
||||||
|
|
||||||
def on_splash_changed(self, state):
|
def on_splash_changed(self, state):
|
||||||
settings = QSettings("Open Source", "FlatCAM")
|
settings = QSettings("Open Source", "FlatCAM")
|
||||||
settings.setValue('splash_screen', 1) if state else settings.setValue('splash_screen', 0)
|
settings.setValue('splash_screen', 1) if state else settings.setValue('splash_screen', 0)
|
||||||
|
@ -17,6 +17,9 @@ CAD program, and create G-Code for Isolation routing.
|
|||||||
- fixed imports in all TclCommands
|
- fixed imports in all TclCommands
|
||||||
- fixed the requirements.txt and setup_ubuntu.sh files
|
- fixed the requirements.txt and setup_ubuntu.sh files
|
||||||
- QRCode Tool: change the plot method parameter
|
- QRCode Tool: change the plot method parameter
|
||||||
|
- QRCode Tool: added ability to save the generated QRCode as SVG file or PNG file
|
||||||
|
- QRCode Tool: added the feature to save the PNG file with transparent background
|
||||||
|
- QRCode Tool: added GUI category in Preferences window
|
||||||
|
|
||||||
24.10.2019
|
24.10.2019
|
||||||
|
|
||||||
|
@ -216,11 +216,15 @@ class Tools2PreferencesUI(QtWidgets.QWidget):
|
|||||||
self.tools2_optimal_group = Tools2OptimalPrefGroupUI()
|
self.tools2_optimal_group = Tools2OptimalPrefGroupUI()
|
||||||
self.tools2_optimal_group.setMinimumWidth(220)
|
self.tools2_optimal_group.setMinimumWidth(220)
|
||||||
|
|
||||||
|
self.tools2_qrcode_group = Tools2QRCodePrefGroupUI()
|
||||||
|
self.tools2_qrcode_group.setMinimumWidth(220)
|
||||||
|
|
||||||
self.vlay = QtWidgets.QVBoxLayout()
|
self.vlay = QtWidgets.QVBoxLayout()
|
||||||
self.vlay.addWidget(self.tools2_checkrules_group)
|
self.vlay.addWidget(self.tools2_checkrules_group)
|
||||||
self.vlay.addWidget(self.tools2_optimal_group)
|
self.vlay.addWidget(self.tools2_optimal_group)
|
||||||
|
|
||||||
self.vlay1 = QtWidgets.QVBoxLayout()
|
self.vlay1 = QtWidgets.QVBoxLayout()
|
||||||
|
self.vlay1.addWidget(self.tools2_qrcode_group)
|
||||||
|
|
||||||
|
|
||||||
self.vlay2 = QtWidgets.QVBoxLayout()
|
self.vlay2 = QtWidgets.QVBoxLayout()
|
||||||
@ -5388,6 +5392,178 @@ class Tools2OptimalPrefGroupUI(OptionsGroupUI):
|
|||||||
self.layout.addStretch()
|
self.layout.addStretch()
|
||||||
|
|
||||||
|
|
||||||
|
class Tools2QRCodePrefGroupUI(OptionsGroupUI):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
|
||||||
|
super(Tools2QRCodePrefGroupUI, self).__init__(self)
|
||||||
|
|
||||||
|
self.setTitle(str(_("QRCode Tool Options")))
|
||||||
|
self.decimals = 4
|
||||||
|
|
||||||
|
# ## Parameters
|
||||||
|
self.qrlabel = QtWidgets.QLabel("<b>%s:</b>" % _("Parameters"))
|
||||||
|
self.qrlabel.setToolTip(
|
||||||
|
_("A tool to create a QRCode that can be inserted\n"
|
||||||
|
"into a selected Gerber file, or it can be exported as a file.")
|
||||||
|
)
|
||||||
|
self.layout.addWidget(self.qrlabel)
|
||||||
|
|
||||||
|
# ## Grid Layout
|
||||||
|
grid_lay = QtWidgets.QGridLayout()
|
||||||
|
self.layout.addLayout(grid_lay)
|
||||||
|
grid_lay.setColumnStretch(0, 0)
|
||||||
|
grid_lay.setColumnStretch(1, 1)
|
||||||
|
|
||||||
|
# VERSION #
|
||||||
|
self.version_label = QtWidgets.QLabel('%s:' % _("Version"))
|
||||||
|
self.version_label.setToolTip(
|
||||||
|
_("QRCode version can have values from 1 (21x21 boxes)\n"
|
||||||
|
"to 40 (177x177 boxes).")
|
||||||
|
)
|
||||||
|
self.version_entry = FCSpinner()
|
||||||
|
self.version_entry.set_range(1, 40)
|
||||||
|
self.version_entry.setWrapping(True)
|
||||||
|
|
||||||
|
grid_lay.addWidget(self.version_label, 1, 0)
|
||||||
|
grid_lay.addWidget(self.version_entry, 1, 1)
|
||||||
|
|
||||||
|
# ERROR CORRECTION #
|
||||||
|
self.error_label = QtWidgets.QLabel('%s:' % _("Error correction"))
|
||||||
|
self.error_label.setToolTip(
|
||||||
|
_("Parameter that controls the error correction used for the QR Code.\n"
|
||||||
|
"L = maximum 7% errors can be corrected\n"
|
||||||
|
"M = maximum 15% errors can be corrected\n"
|
||||||
|
"Q = maximum 25% errors can be corrected\n"
|
||||||
|
"H = maximum 30% errors can be corrected.")
|
||||||
|
)
|
||||||
|
self.error_radio = RadioSet([{'label': 'L', 'value': 'L'},
|
||||||
|
{'label': 'M', 'value': 'M'},
|
||||||
|
{'label': 'Q', 'value': 'Q'},
|
||||||
|
{'label': 'H', 'value': 'H'}])
|
||||||
|
self.error_radio.setToolTip(
|
||||||
|
_("Parameter that controls the error correction used for the QR Code.\n"
|
||||||
|
"L = maximum 7% errors can be corrected\n"
|
||||||
|
"M = maximum 15% errors can be corrected\n"
|
||||||
|
"Q = maximum 25% errors can be corrected\n"
|
||||||
|
"H = maximum 30% errors can be corrected.")
|
||||||
|
)
|
||||||
|
grid_lay.addWidget(self.error_label, 2, 0)
|
||||||
|
grid_lay.addWidget(self.error_radio, 2, 1)
|
||||||
|
|
||||||
|
# BOX SIZE #
|
||||||
|
self.bsize_label = QtWidgets.QLabel('%s:' % _("Box Size"))
|
||||||
|
self.bsize_label.setToolTip(
|
||||||
|
_("Box size control the overall size of the QRcode\n"
|
||||||
|
"by adjusting the size of each box in the code.")
|
||||||
|
)
|
||||||
|
self.bsize_entry = FCSpinner()
|
||||||
|
self.bsize_entry.set_range(1, 9999)
|
||||||
|
self.bsize_entry.setWrapping(True)
|
||||||
|
|
||||||
|
grid_lay.addWidget(self.bsize_label, 3, 0)
|
||||||
|
grid_lay.addWidget(self.bsize_entry, 3, 1)
|
||||||
|
|
||||||
|
# BORDER SIZE #
|
||||||
|
self.border_size_label = QtWidgets.QLabel('%s:' % _("Border Size"))
|
||||||
|
self.border_size_label.setToolTip(
|
||||||
|
_("Size of the QRCode border. How many boxes thick is the border.\n"
|
||||||
|
"Default value is 4. The width of the clearance around the QRCode.")
|
||||||
|
)
|
||||||
|
self.border_size_entry = FCSpinner()
|
||||||
|
self.border_size_entry.set_range(1, 9999)
|
||||||
|
self.border_size_entry.setWrapping(True)
|
||||||
|
|
||||||
|
grid_lay.addWidget(self.border_size_label, 4, 0)
|
||||||
|
grid_lay.addWidget(self.border_size_entry, 4, 1)
|
||||||
|
|
||||||
|
# Text box
|
||||||
|
self.text_label = QtWidgets.QLabel('%s:' % _("QRCode Data"))
|
||||||
|
self.text_label.setToolTip(
|
||||||
|
_("QRCode Data. Alphanumeric text to be encoded in the QRCode.")
|
||||||
|
)
|
||||||
|
self.text_data = FCTextArea()
|
||||||
|
self.text_data.setPlaceholderText(
|
||||||
|
_("Add here the text to be included in the QRCode...")
|
||||||
|
)
|
||||||
|
grid_lay.addWidget(self.text_label, 5, 0)
|
||||||
|
grid_lay.addWidget(self.text_data, 6, 0, 1, 2)
|
||||||
|
|
||||||
|
# POLARITY CHOICE #
|
||||||
|
self.pol_label = QtWidgets.QLabel('%s:' % _("Polarity"))
|
||||||
|
self.pol_label.setToolTip(
|
||||||
|
_("Choose the polarity of the QRCode.\n"
|
||||||
|
"It can be drawn in a negative way (squares are clear)\n"
|
||||||
|
"or in a positive way (squares are opaque).")
|
||||||
|
)
|
||||||
|
self.pol_radio = RadioSet([{'label': _('Negative'), 'value': 'neg'},
|
||||||
|
{'label': _('Positive'), 'value': 'pos'}])
|
||||||
|
self.pol_radio.setToolTip(
|
||||||
|
_("Choose the type of QRCode to be created.\n"
|
||||||
|
"If added on a Silkscreen Gerber file the QRCode may\n"
|
||||||
|
"be added as positive. If it is added to a Copper Gerber\n"
|
||||||
|
"file then perhaps the QRCode can be added as negative.")
|
||||||
|
)
|
||||||
|
grid_lay.addWidget(self.pol_label, 7, 0)
|
||||||
|
grid_lay.addWidget(self.pol_radio, 7, 1)
|
||||||
|
|
||||||
|
# BOUNDING BOX TYPE #
|
||||||
|
self.bb_label = QtWidgets.QLabel('%s:' % _("Bounding Box"))
|
||||||
|
self.bb_label.setToolTip(
|
||||||
|
_("The bounding box, meaning the empty space that surrounds\n"
|
||||||
|
"the QRCode geometry, can have a rounded or a square shape.")
|
||||||
|
)
|
||||||
|
self.bb_radio = RadioSet([{'label': _('Rounded'), 'value': 'r'},
|
||||||
|
{'label': _('Square'), 'value': 's'}])
|
||||||
|
self.bb_radio.setToolTip(
|
||||||
|
_("The bounding box, meaning the empty space that surrounds\n"
|
||||||
|
"the QRCode geometry, can have a rounded or a square shape.")
|
||||||
|
)
|
||||||
|
grid_lay.addWidget(self.bb_label, 8, 0)
|
||||||
|
grid_lay.addWidget(self.bb_radio, 8, 1)
|
||||||
|
|
||||||
|
# FILL COLOR #
|
||||||
|
self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill Color'))
|
||||||
|
self.fill_color_label.setToolTip(
|
||||||
|
_("Set the QRCode fill color (squares color).")
|
||||||
|
)
|
||||||
|
self.fill_color_entry = FCEntry()
|
||||||
|
self.fill_color_button = QtWidgets.QPushButton()
|
||||||
|
self.fill_color_button.setFixedSize(15, 15)
|
||||||
|
|
||||||
|
fill_lay_child = QtWidgets.QHBoxLayout()
|
||||||
|
fill_lay_child.setContentsMargins(0, 0, 0, 0)
|
||||||
|
fill_lay_child.addWidget(self.fill_color_entry)
|
||||||
|
fill_lay_child.addWidget(self.fill_color_button, alignment=Qt.AlignRight)
|
||||||
|
fill_lay_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
|
||||||
|
|
||||||
|
fill_color_widget = QtWidgets.QWidget()
|
||||||
|
fill_color_widget.setLayout(fill_lay_child)
|
||||||
|
|
||||||
|
grid_lay.addWidget(self.fill_color_label, 9, 0)
|
||||||
|
grid_lay.addWidget(fill_color_widget, 9, 1)
|
||||||
|
|
||||||
|
# BACK COLOR #
|
||||||
|
self.back_color_label = QtWidgets.QLabel('%s:' % _('Back Color'))
|
||||||
|
self.back_color_label.setToolTip(
|
||||||
|
_("Set the QRCode background color.")
|
||||||
|
)
|
||||||
|
self.back_color_entry = FCEntry()
|
||||||
|
self.back_color_button = QtWidgets.QPushButton()
|
||||||
|
self.back_color_button.setFixedSize(15, 15)
|
||||||
|
|
||||||
|
back_lay_child = QtWidgets.QHBoxLayout()
|
||||||
|
back_lay_child.setContentsMargins(0, 0, 0, 0)
|
||||||
|
back_lay_child.addWidget(self.back_color_entry)
|
||||||
|
back_lay_child.addWidget(self.back_color_button, alignment=Qt.AlignRight)
|
||||||
|
back_lay_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
|
||||||
|
|
||||||
|
back_color_widget = QtWidgets.QWidget()
|
||||||
|
back_color_widget.setLayout(back_lay_child)
|
||||||
|
|
||||||
|
grid_lay.addWidget(self.back_color_label, 10, 0)
|
||||||
|
grid_lay.addWidget(back_color_widget, 10, 1)
|
||||||
|
|
||||||
|
|
||||||
class FAExcPrefGroupUI(OptionsGroupUI):
|
class FAExcPrefGroupUI(OptionsGroupUI):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
# OptionsGroupUI.__init__(self, "Excellon File associations Preferences", parent=None)
|
# OptionsGroupUI.__init__(self, "Excellon File associations Preferences", parent=None)
|
||||||
|
@ -5,10 +5,11 @@
|
|||||||
# MIT Licence #
|
# MIT Licence #
|
||||||
# ##########################################################
|
# ##########################################################
|
||||||
|
|
||||||
from PyQt5 import QtWidgets, QtCore
|
from PyQt5 import QtWidgets, QtCore, QtGui
|
||||||
|
from PyQt5.QtCore import Qt
|
||||||
|
|
||||||
from FlatCAMTool import FlatCAMTool
|
from FlatCAMTool import FlatCAMTool
|
||||||
from flatcamGUI.GUIElements import RadioSet, FCTextArea, FCSpinner, FCDoubleSpinner
|
from flatcamGUI.GUIElements import RadioSet, FCTextArea, FCSpinner, FCEntry, FCCheckBox, OptionalInputSection
|
||||||
from flatcamParsers.ParseSVG import *
|
from flatcamParsers.ParseSVG import *
|
||||||
|
|
||||||
from shapely.geometry.base import *
|
from shapely.geometry.base import *
|
||||||
@ -23,6 +24,7 @@ from copy import deepcopy
|
|||||||
|
|
||||||
import qrcode
|
import qrcode
|
||||||
import qrcode.image.svg
|
import qrcode.image.svg
|
||||||
|
import qrcode.image.pil
|
||||||
from lxml import etree as ET
|
from lxml import etree as ET
|
||||||
|
|
||||||
import gettext
|
import gettext
|
||||||
@ -164,7 +166,7 @@ class QRCode(FlatCAMTool):
|
|||||||
)
|
)
|
||||||
self.text_data = FCTextArea()
|
self.text_data = FCTextArea()
|
||||||
self.text_data.setPlaceholderText(
|
self.text_data.setPlaceholderText(
|
||||||
_("Add here the text to be included in the QRData...")
|
_("Add here the text to be included in the QRCode...")
|
||||||
)
|
)
|
||||||
grid_lay.addWidget(self.text_label, 5, 0)
|
grid_lay.addWidget(self.text_label, 5, 0)
|
||||||
grid_lay.addWidget(self.text_data, 6, 0, 1, 2)
|
grid_lay.addWidget(self.text_data, 6, 0, 1, 2)
|
||||||
@ -202,13 +204,92 @@ class QRCode(FlatCAMTool):
|
|||||||
grid_lay.addWidget(self.bb_label, 8, 0)
|
grid_lay.addWidget(self.bb_label, 8, 0)
|
||||||
grid_lay.addWidget(self.bb_radio, 8, 1)
|
grid_lay.addWidget(self.bb_radio, 8, 1)
|
||||||
|
|
||||||
# ## Create QRCode
|
# Export QRCode
|
||||||
self.qrcode_button = QtWidgets.QPushButton(_("Create QRCode"))
|
self.export_cb = FCCheckBox(_("Export QRCode"))
|
||||||
|
self.export_cb.setToolTip(
|
||||||
|
_("Show a set of controls allowing to export the QRCode\n"
|
||||||
|
"to a SVG file or an PNG file.")
|
||||||
|
)
|
||||||
|
grid_lay.addWidget(self.export_cb, 9, 0, 1, 2)
|
||||||
|
|
||||||
|
# this way I can hide/show the frame
|
||||||
|
self.export_frame = QtWidgets.QFrame()
|
||||||
|
self.export_frame.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.layout.addWidget(self.export_frame)
|
||||||
|
self.export_lay = QtWidgets.QGridLayout()
|
||||||
|
self.export_lay.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.export_frame.setLayout(self.export_lay)
|
||||||
|
self.export_lay.setColumnStretch(0, 0)
|
||||||
|
self.export_lay.setColumnStretch(1, 1)
|
||||||
|
|
||||||
|
# default is hidden
|
||||||
|
self.export_frame.hide()
|
||||||
|
|
||||||
|
# FILL COLOR #
|
||||||
|
self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill Color'))
|
||||||
|
self.fill_color_label.setToolTip(
|
||||||
|
_("Set the QRCode fill color (squares color).")
|
||||||
|
)
|
||||||
|
self.fill_color_entry = FCEntry()
|
||||||
|
self.fill_color_button = QtWidgets.QPushButton()
|
||||||
|
self.fill_color_button.setFixedSize(15, 15)
|
||||||
|
|
||||||
|
fill_lay_child = QtWidgets.QHBoxLayout()
|
||||||
|
fill_lay_child.setContentsMargins(0, 0, 0, 0)
|
||||||
|
fill_lay_child.addWidget(self.fill_color_entry)
|
||||||
|
fill_lay_child.addWidget(self.fill_color_button, alignment=Qt.AlignRight)
|
||||||
|
fill_lay_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
|
||||||
|
|
||||||
|
fill_color_widget = QtWidgets.QWidget()
|
||||||
|
fill_color_widget.setLayout(fill_lay_child)
|
||||||
|
|
||||||
|
self.export_lay.addWidget(self.fill_color_label, 0, 0)
|
||||||
|
self.export_lay.addWidget(fill_color_widget, 0, 1)
|
||||||
|
|
||||||
|
self.transparent_cb = FCCheckBox(_("Transparent back color"))
|
||||||
|
self.export_lay.addWidget(self.transparent_cb, 1, 0, 1, 2)
|
||||||
|
|
||||||
|
# BACK COLOR #
|
||||||
|
self.back_color_label = QtWidgets.QLabel('%s:' % _('Back Color'))
|
||||||
|
self.back_color_label.setToolTip(
|
||||||
|
_("Set the QRCode background color.")
|
||||||
|
)
|
||||||
|
self.back_color_entry = FCEntry()
|
||||||
|
self.back_color_button = QtWidgets.QPushButton()
|
||||||
|
self.back_color_button.setFixedSize(15, 15)
|
||||||
|
|
||||||
|
back_lay_child = QtWidgets.QHBoxLayout()
|
||||||
|
back_lay_child.setContentsMargins(0, 0, 0, 0)
|
||||||
|
back_lay_child.addWidget(self.back_color_entry)
|
||||||
|
back_lay_child.addWidget(self.back_color_button, alignment=Qt.AlignRight)
|
||||||
|
back_lay_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
|
||||||
|
|
||||||
|
back_color_widget = QtWidgets.QWidget()
|
||||||
|
back_color_widget.setLayout(back_lay_child)
|
||||||
|
|
||||||
|
self.export_lay.addWidget(self.back_color_label, 2, 0)
|
||||||
|
self.export_lay.addWidget(back_color_widget, 2, 1)
|
||||||
|
|
||||||
|
# ## Export QRCode as SVG image
|
||||||
|
self.export_svg_button = QtWidgets.QPushButton(_("Export QRCode SVG"))
|
||||||
|
self.export_svg_button.setToolTip(
|
||||||
|
_("Export a SVG file with the QRCode content.")
|
||||||
|
)
|
||||||
|
self.export_lay.addWidget(self.export_svg_button, 3, 0, 1, 2)
|
||||||
|
|
||||||
|
# ## Export QRCode as PNG image
|
||||||
|
self.export_png_button = QtWidgets.QPushButton(_("Export QRCode PNG"))
|
||||||
|
self.export_png_button.setToolTip(
|
||||||
|
_("Export a PNG image file with the QRCode content.")
|
||||||
|
)
|
||||||
|
self.export_lay.addWidget(self.export_png_button, 4, 0, 1, 2)
|
||||||
|
|
||||||
|
# ## Insert QRCode
|
||||||
|
self.qrcode_button = QtWidgets.QPushButton(_("Insert QRCode"))
|
||||||
self.qrcode_button.setToolTip(
|
self.qrcode_button.setToolTip(
|
||||||
_("Create the QRCode object.")
|
_("Create the QRCode object.")
|
||||||
)
|
)
|
||||||
grid_lay.addWidget(self.qrcode_button, 9, 0, 1, 2)
|
self.layout.addWidget(self.qrcode_button)
|
||||||
grid_lay.addWidget(QtWidgets.QLabel(''), 10, 0)
|
|
||||||
|
|
||||||
self.layout.addStretch()
|
self.layout.addStretch()
|
||||||
|
|
||||||
@ -226,6 +307,21 @@ class QRCode(FlatCAMTool):
|
|||||||
self.qrcode_geometry = MultiPolygon()
|
self.qrcode_geometry = MultiPolygon()
|
||||||
self.qrcode_utility_geometry = MultiPolygon()
|
self.qrcode_utility_geometry = MultiPolygon()
|
||||||
|
|
||||||
|
self.old_back_color = ''
|
||||||
|
|
||||||
|
# Signals #
|
||||||
|
self.qrcode_button.clicked.connect(self.execute)
|
||||||
|
self.export_cb.stateChanged.connect(self.on_export_frame)
|
||||||
|
self.export_png_button.clicked.connect(self.export_png_file)
|
||||||
|
self.export_svg_button.clicked.connect(self.export_svg_file)
|
||||||
|
|
||||||
|
self.fill_color_entry.editingFinished.connect(self.on_qrcode_fill_color_entry)
|
||||||
|
self.fill_color_button.clicked.connect(self.on_qrcode_fill_color_button)
|
||||||
|
self.back_color_entry.editingFinished.connect(self.on_qrcode_back_color_entry)
|
||||||
|
self.back_color_button.clicked.connect(self.on_qrcode_back_color_button)
|
||||||
|
|
||||||
|
self.transparent_cb.stateChanged.connect(self.on_transparent_back_color)
|
||||||
|
|
||||||
def run(self, toggle=True):
|
def run(self, toggle=True):
|
||||||
self.app.report_usage("QRCode()")
|
self.app.report_usage("QRCode()")
|
||||||
|
|
||||||
@ -259,15 +355,24 @@ class QRCode(FlatCAMTool):
|
|||||||
|
|
||||||
def set_tool_ui(self):
|
def set_tool_ui(self):
|
||||||
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value()
|
self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value()
|
||||||
self.version_entry.set_value(1)
|
self.version_entry.set_value(int(self.app.defaults["tools_qrcode_version"]))
|
||||||
self.error_radio.set_value('M')
|
self.error_radio.set_value(self.app.defaults["tools_qrcode_error"])
|
||||||
self.bsize_entry.set_value(3)
|
self.bsize_entry.set_value(int(self.app.defaults["tools_qrcode_box_size"]))
|
||||||
self.border_size_entry.set_value(4)
|
self.border_size_entry.set_value(int(self.app.defaults["tools_qrcode_border_size"]))
|
||||||
self.pol_radio.set_value('pos')
|
self.pol_radio.set_value(self.app.defaults["tools_qrcode_polarity"])
|
||||||
self.bb_radio.set_value('r')
|
self.bb_radio.set_value(self.app.defaults["tools_qrcode_rounded"])
|
||||||
|
|
||||||
# Signals #
|
self.fill_color_entry.set_value(self.app.defaults['tools_qrcode_fill_color'])
|
||||||
self.qrcode_button.clicked.connect(self.execute)
|
self.fill_color_button.setStyleSheet("background-color:%s" %
|
||||||
|
str(self.app.defaults['tools_qrcode_fill_color'])[:7])
|
||||||
|
|
||||||
|
self.back_color_entry.set_value(self.app.defaults['tools_qrcode_back_color'])
|
||||||
|
self.back_color_button.setStyleSheet("background-color:%s" %
|
||||||
|
str(self.app.defaults['tools_qrcode_back_color'])[:7])
|
||||||
|
|
||||||
|
def on_export_frame(self, state):
|
||||||
|
self.export_frame.setVisible(state)
|
||||||
|
self.qrcode_button.setVisible(not state)
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
text_data = self.text_data.get_value()
|
text_data = self.text_data.get_value()
|
||||||
@ -327,8 +432,8 @@ class QRCode(FlatCAMTool):
|
|||||||
try:
|
try:
|
||||||
a, b, c, d = self.qrcode_utility_geometry.bounds
|
a, b, c, d = self.qrcode_utility_geometry.bounds
|
||||||
self.box_poly = box(minx=a, miny=b, maxx=c, maxy=d)
|
self.box_poly = box(minx=a, miny=b, maxx=c, maxy=d)
|
||||||
except Exception as e:
|
except Exception as ee:
|
||||||
log.debug("QRCode.make() bounds error --> %s" % str(e))
|
log.debug("QRCode.make() bounds error --> %s" % str(ee))
|
||||||
|
|
||||||
app_obj.call_source = 'qrcode_tool'
|
app_obj.call_source = 'qrcode_tool'
|
||||||
app_obj.inform.emit(_("Click on the Destination point ..."))
|
app_obj.inform.emit(_("Click on the Destination point ..."))
|
||||||
@ -602,3 +707,146 @@ class QRCode(FlatCAMTool):
|
|||||||
# delete the utility geometry
|
# delete the utility geometry
|
||||||
self.delete_utility_geo()
|
self.delete_utility_geo()
|
||||||
self.app.call_source = 'app'
|
self.app.call_source = 'app'
|
||||||
|
|
||||||
|
def export_png_file(self):
|
||||||
|
text_data = self.text_data.get_value()
|
||||||
|
if text_data == '':
|
||||||
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Cancelled. There is no QRCode Data in the text box."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
def job_thread_qr_png(app_obj, fname):
|
||||||
|
error_code = {
|
||||||
|
'L': qrcode.constants.ERROR_CORRECT_L,
|
||||||
|
'M': qrcode.constants.ERROR_CORRECT_M,
|
||||||
|
'Q': qrcode.constants.ERROR_CORRECT_Q,
|
||||||
|
'H': qrcode.constants.ERROR_CORRECT_H
|
||||||
|
}[self.error_radio.get_value()]
|
||||||
|
|
||||||
|
qr = qrcode.QRCode(
|
||||||
|
version=self.version_entry.get_value(),
|
||||||
|
error_correction=error_code,
|
||||||
|
box_size=self.bsize_entry.get_value(),
|
||||||
|
border=self.border_size_entry.get_value(),
|
||||||
|
image_factory=qrcode.image.pil.PilImage
|
||||||
|
)
|
||||||
|
qr.add_data(text_data)
|
||||||
|
qr.make(fit=True)
|
||||||
|
|
||||||
|
img = qr.make_image(fill_color=self.fill_color_entry.get_value(),
|
||||||
|
back_color=self.back_color_entry.get_value())
|
||||||
|
img.save(fname)
|
||||||
|
|
||||||
|
app_obj.call_source = 'qrcode_tool'
|
||||||
|
|
||||||
|
name = 'qr_code'
|
||||||
|
|
||||||
|
_filter = "PNG File (*.png);;All Files (*.*)"
|
||||||
|
try:
|
||||||
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(
|
||||||
|
caption=_("Export PNG"),
|
||||||
|
directory=self.app.get_last_save_folder() + '/' + str(name) + '_png',
|
||||||
|
filter=_filter)
|
||||||
|
except TypeError:
|
||||||
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export PNG"), filter=_filter)
|
||||||
|
|
||||||
|
filename = str(filename)
|
||||||
|
|
||||||
|
if filename == "":
|
||||||
|
self.app.inform.emit('[WARNING_NOTCL]%s' % _(" Export PNG cancelled."))
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.app.worker_task.emit({'fcn': job_thread_qr_png, 'params': [self.app, filename]})
|
||||||
|
|
||||||
|
def export_svg_file(self):
|
||||||
|
text_data = self.text_data.get_value()
|
||||||
|
if text_data == '':
|
||||||
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Cancelled. There is no QRCode Data in the text box."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
def job_thread_qr_svg(app_obj, fname):
|
||||||
|
error_code = {
|
||||||
|
'L': qrcode.constants.ERROR_CORRECT_L,
|
||||||
|
'M': qrcode.constants.ERROR_CORRECT_M,
|
||||||
|
'Q': qrcode.constants.ERROR_CORRECT_Q,
|
||||||
|
'H': qrcode.constants.ERROR_CORRECT_H
|
||||||
|
}[self.error_radio.get_value()]
|
||||||
|
|
||||||
|
qr = qrcode.QRCode(
|
||||||
|
version=self.version_entry.get_value(),
|
||||||
|
error_correction=error_code,
|
||||||
|
box_size=self.bsize_entry.get_value(),
|
||||||
|
border=self.border_size_entry.get_value(),
|
||||||
|
image_factory=qrcode.image.svg.SvgPathImage
|
||||||
|
)
|
||||||
|
qr.add_data(text_data)
|
||||||
|
img = qr.make_image(fill_color=self.fill_color_entry.get_value(),
|
||||||
|
back_color=self.back_color_entry.get_value())
|
||||||
|
img.save(fname)
|
||||||
|
|
||||||
|
app_obj.call_source = 'qrcode_tool'
|
||||||
|
|
||||||
|
name = 'qr_code'
|
||||||
|
|
||||||
|
_filter = "SVG File (*.svg);;All Files (*.*)"
|
||||||
|
try:
|
||||||
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(
|
||||||
|
caption=_("Export SVG"),
|
||||||
|
directory=self.app.get_last_save_folder() + '/' + str(name) + '_svg',
|
||||||
|
filter=_filter)
|
||||||
|
except TypeError:
|
||||||
|
filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export SVG"), filter=_filter)
|
||||||
|
|
||||||
|
filename = str(filename)
|
||||||
|
|
||||||
|
if filename == "":
|
||||||
|
self.app.inform.emit('[WARNING_NOTCL]%s' % _(" Export SVG cancelled."))
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.app.worker_task.emit({'fcn': job_thread_qr_svg, 'params': [self.app, filename]})
|
||||||
|
|
||||||
|
def on_qrcode_fill_color_entry(self):
|
||||||
|
color = self.fill_color_entry.get_value()
|
||||||
|
self.fill_color_button.setStyleSheet("background-color:%s" % str(color))
|
||||||
|
|
||||||
|
def on_qrcode_fill_color_button(self):
|
||||||
|
current_color = QtGui.QColor(self.fill_color_entry.get_value())
|
||||||
|
|
||||||
|
c_dialog = QtWidgets.QColorDialog()
|
||||||
|
fill_color = c_dialog.getColor(initial=current_color)
|
||||||
|
|
||||||
|
if fill_color.isValid() is False:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.fill_color_button.setStyleSheet("background-color:%s" % str(fill_color.name()))
|
||||||
|
|
||||||
|
new_val_sel = str(fill_color.name())
|
||||||
|
self.fill_color_entry.set_value(new_val_sel)
|
||||||
|
|
||||||
|
def on_qrcode_back_color_entry(self):
|
||||||
|
color = self.back_color_entry.get_value()
|
||||||
|
self.back_color_button.setStyleSheet("background-color:%s" % str(color))
|
||||||
|
|
||||||
|
def on_qrcode_back_color_button(self):
|
||||||
|
current_color = QtGui.QColor(self.back_color_entry.get_value())
|
||||||
|
|
||||||
|
c_dialog = QtWidgets.QColorDialog()
|
||||||
|
back_color = c_dialog.getColor(initial=current_color)
|
||||||
|
|
||||||
|
if back_color.isValid() is False:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.back_color_button.setStyleSheet("background-color:%s" % str(back_color.name()))
|
||||||
|
|
||||||
|
new_val_sel = str(back_color.name())
|
||||||
|
self.back_color_entry.set_value(new_val_sel)
|
||||||
|
|
||||||
|
def on_transparent_back_color(self, state):
|
||||||
|
if state:
|
||||||
|
self.back_color_entry.setDisabled(True)
|
||||||
|
self.back_color_button.setDisabled(True)
|
||||||
|
self.old_back_color = self.back_color_entry.get_value()
|
||||||
|
self.back_color_entry.set_value('transparent')
|
||||||
|
else:
|
||||||
|
self.back_color_entry.setDisabled(False)
|
||||||
|
self.back_color_button.setDisabled(False)
|
||||||
|
self.back_color_entry.set_value(self.old_back_color)
|
||||||
|
@ -46,6 +46,8 @@ class TclCommandAlignDrill(TclCommandSignaled):
|
|||||||
('name', 'Name of the object (Gerber or Excellon) to mirror.'),
|
('name', 'Name of the object (Gerber or Excellon) to mirror.'),
|
||||||
('dia', 'Tool diameter'),
|
('dia', 'Tool diameter'),
|
||||||
('box', 'Name of object which act as box (cutout for example.)'),
|
('box', 'Name of object which act as box (cutout for example.)'),
|
||||||
|
('holes', 'Tuple of tuples where each tuple it is a set of x, y coordinates. '
|
||||||
|
'E.g: (x0, y0), (x1, y1), ... '),
|
||||||
('grid', 'Aligning to grid, for those, who have aligning pins'
|
('grid', 'Aligning to grid, for those, who have aligning pins'
|
||||||
'inside table in grid (-5,0),(5,0),(15,0)...'),
|
'inside table in grid (-5,0),(5,0),(15,0)...'),
|
||||||
('gridoffset', 'offset of grid from 0 position.'),
|
('gridoffset', 'offset of grid from 0 position.'),
|
||||||
|
Loading…
Reference in New Issue
Block a user