- the Code Editor tab name is changed according to the task; 'save' and 'open' buttons will have filters installed for the QOpenDialog fit to the task
This commit is contained in:
182
FlatCAMApp.py
182
FlatCAMApp.py
@@ -1429,9 +1429,9 @@ class App(QtCore.QObject):
|
|||||||
# Modify G-CODE Plot Area TAB
|
# Modify G-CODE Plot Area TAB
|
||||||
self.ui.code_editor.textChanged.connect(self.handleTextChanged)
|
self.ui.code_editor.textChanged.connect(self.handleTextChanged)
|
||||||
self.ui.buttonOpen.clicked.connect(self.handleOpen)
|
self.ui.buttonOpen.clicked.connect(self.handleOpen)
|
||||||
|
self.ui.buttonSave.clicked.connect(self.handleSaveGCode)
|
||||||
self.ui.buttonPrint.clicked.connect(self.handlePrint)
|
self.ui.buttonPrint.clicked.connect(self.handlePrint)
|
||||||
self.ui.buttonPreview.clicked.connect(self.handlePreview)
|
self.ui.buttonPreview.clicked.connect(self.handlePreview)
|
||||||
self.ui.buttonSave.clicked.connect(self.handleSaveGCode)
|
|
||||||
self.ui.buttonFind.clicked.connect(self.handleFindGCode)
|
self.ui.buttonFind.clicked.connect(self.handleFindGCode)
|
||||||
self.ui.buttonReplace.clicked.connect(self.handleReplaceGCode)
|
self.ui.buttonReplace.clicked.connect(self.handleReplaceGCode)
|
||||||
|
|
||||||
@@ -3373,27 +3373,6 @@ class App(QtCore.QObject):
|
|||||||
|
|
||||||
self.ui.grid_snap_btn.trigger()
|
self.ui.grid_snap_btn.trigger()
|
||||||
|
|
||||||
def on_toggle_code_editor(self):
|
|
||||||
self.report_usage("on_toggle_code_editor()")
|
|
||||||
|
|
||||||
if self.toggle_codeeditor is False:
|
|
||||||
# add the tab if it was closed
|
|
||||||
self.ui.plot_tab_area.addTab(self.ui.cncjob_tab, _("Code Editor"))
|
|
||||||
self.ui.cncjob_tab.setObjectName('cncjob_tab')
|
|
||||||
# first clear previous text in text editor (if any)
|
|
||||||
self.ui.code_editor.clear()
|
|
||||||
|
|
||||||
# Switch plot_area to CNCJob tab
|
|
||||||
self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab)
|
|
||||||
|
|
||||||
self.toggle_codeeditor = True
|
|
||||||
else:
|
|
||||||
for idx in range(self.ui.plot_tab_area.count()):
|
|
||||||
if self.ui.plot_tab_area.widget(idx).objectName() == "cncjob_tab":
|
|
||||||
self.ui.plot_tab_area.closeTab(idx)
|
|
||||||
break
|
|
||||||
self.toggle_codeeditor = False
|
|
||||||
|
|
||||||
def on_options_combo_change(self, sel):
|
def on_options_combo_change(self, sel):
|
||||||
"""
|
"""
|
||||||
Called when the combo box to choose between application defaults and
|
Called when the combo box to choose between application defaults and
|
||||||
@@ -3862,21 +3841,6 @@ class App(QtCore.QObject):
|
|||||||
# Re-fresh project options
|
# Re-fresh project options
|
||||||
self.on_options_app2project()
|
self.on_options_app2project()
|
||||||
|
|
||||||
def handleOpen(self):
|
|
||||||
self.report_usage("handleOpen()")
|
|
||||||
|
|
||||||
filter_group = " G-Code Files (*.nc);; G-Code Files (*.txt);; G-Code Files (*.tap);; G-Code Files (*.cnc);; " \
|
|
||||||
"All Files (*.*)"
|
|
||||||
path, _f = QtWidgets.QFileDialog.getOpenFileName(
|
|
||||||
caption=_('Open file'), directory=self.get_last_folder(), filter=filter_group)
|
|
||||||
if path:
|
|
||||||
file = QtCore.QFile(path)
|
|
||||||
if file.open(QtCore.QIODevice.ReadOnly):
|
|
||||||
stream = QtCore.QTextStream(file)
|
|
||||||
self.gcode_edited = stream.readAll()
|
|
||||||
self.ui.code_editor.setPlainText(self.gcode_edited)
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
def handlePrint(self):
|
def handlePrint(self):
|
||||||
self.report_usage("handlePrint()")
|
self.report_usage("handlePrint()")
|
||||||
|
|
||||||
@@ -3899,7 +3863,27 @@ class App(QtCore.QObject):
|
|||||||
# self.ui.buttonPreview.setEnabled(enable)
|
# self.ui.buttonPreview.setEnabled(enable)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def handleSaveGCode(self, signal, name=None, filt=None):
|
def handleOpen(self, filt=None):
|
||||||
|
self.report_usage("handleOpen()")
|
||||||
|
|
||||||
|
if filt:
|
||||||
|
_filter_ = filt
|
||||||
|
else:
|
||||||
|
_filter_ = "G-Code Files (*.nc);; G-Code Files (*.txt);; G-Code Files (*.tap);; G-Code Files (*.cnc);; " \
|
||||||
|
"All Files (*.*)"
|
||||||
|
|
||||||
|
path, _f = QtWidgets.QFileDialog.getOpenFileName(
|
||||||
|
caption=_('Open file'), directory=self.get_last_folder(), filter=_filter_)
|
||||||
|
|
||||||
|
if path:
|
||||||
|
file = QtCore.QFile(path)
|
||||||
|
if file.open(QtCore.QIODevice.ReadOnly):
|
||||||
|
stream = QtCore.QTextStream(file)
|
||||||
|
self.gcode_edited = stream.readAll()
|
||||||
|
self.ui.code_editor.setPlainText(self.gcode_edited)
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
def handleSaveGCode(self,name=None, filt=None):
|
||||||
self.report_usage("handleSaveGCode()")
|
self.report_usage("handleSaveGCode()")
|
||||||
|
|
||||||
if filt:
|
if filt:
|
||||||
@@ -5287,50 +5271,6 @@ class App(QtCore.QObject):
|
|||||||
elif type(obj) == FlatCAMGerber:
|
elif type(obj) == FlatCAMGerber:
|
||||||
self.on_file_savegerber()
|
self.on_file_savegerber()
|
||||||
|
|
||||||
def on_view_source(self):
|
|
||||||
|
|
||||||
try:
|
|
||||||
obj = self.collection.get_active()
|
|
||||||
except:
|
|
||||||
self.inform.emit(_("[WARNING_NOTCL] Select an Gerber or Excellon file to view it's source file."))
|
|
||||||
return 'fail'
|
|
||||||
|
|
||||||
# then append the text from GCode to the text editor
|
|
||||||
try:
|
|
||||||
file = StringIO(obj.source_file)
|
|
||||||
except AttributeError:
|
|
||||||
self.inform.emit(_("[WARNING_NOTCL] There is no selected object for which to see it's source file code."))
|
|
||||||
return 'fail'
|
|
||||||
|
|
||||||
# add the tab if it was closed
|
|
||||||
self.ui.plot_tab_area.addTab(self.ui.cncjob_tab, _("Source Editor"))
|
|
||||||
self.ui.cncjob_tab.setObjectName('cncjob_tab')
|
|
||||||
# first clear previous text in text editor (if any)
|
|
||||||
self.ui.code_editor.clear()
|
|
||||||
self.toggle_codeeditor = True
|
|
||||||
|
|
||||||
# Switch plot_area to CNCJob tab
|
|
||||||
self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab)
|
|
||||||
|
|
||||||
try:
|
|
||||||
for line in file:
|
|
||||||
proc_line = str(line).strip('\n')
|
|
||||||
self.ui.code_editor.append(proc_line)
|
|
||||||
except Exception as e:
|
|
||||||
log.debug('App.on_view_source() -->%s' % str(e))
|
|
||||||
self.inform.emit(_('[ERROR]App.on_view_source() -->%s') % str(e))
|
|
||||||
return
|
|
||||||
|
|
||||||
self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
|
|
||||||
|
|
||||||
self.handleTextChanged()
|
|
||||||
self.ui.show()
|
|
||||||
|
|
||||||
# if type(obj) == FlatCAMGerber:
|
|
||||||
# self.on_file_exportdxf()
|
|
||||||
# elif type(obj) == FlatCAMExcellon:
|
|
||||||
# self.on_file_exportexcellon()
|
|
||||||
|
|
||||||
def obj_move(self):
|
def obj_move(self):
|
||||||
self.report_usage("obj_move()")
|
self.report_usage("obj_move()")
|
||||||
self.move_tool.run()
|
self.move_tool.run()
|
||||||
@@ -5789,17 +5729,87 @@ class App(QtCore.QObject):
|
|||||||
self.worker_task.emit({'fcn': self.import_dxf,
|
self.worker_task.emit({'fcn': self.import_dxf,
|
||||||
'params': [filename, type_of_obj]})
|
'params': [filename, type_of_obj]})
|
||||||
|
|
||||||
def on_filenewscript(self):
|
###################################################################################################################
|
||||||
|
### The following section has the functions that are displayed are call the Editoe tab CNCJob Tab #################
|
||||||
|
###################################################################################################################
|
||||||
|
|
||||||
|
def init_code_editor(self, name):
|
||||||
|
# Signals section
|
||||||
|
# Disconnect the old signals
|
||||||
|
self.ui.buttonOpen.clicked.disconnect()
|
||||||
|
self.ui.buttonSave.clicked.disconnect()
|
||||||
|
|
||||||
# add the tab if it was closed
|
# add the tab if it was closed
|
||||||
self.ui.plot_tab_area.addTab(self.ui.cncjob_tab, _("Script Editor"))
|
self.ui.plot_tab_area.addTab(self.ui.cncjob_tab, _('%s') % name)
|
||||||
self.ui.cncjob_tab.setObjectName('cncjob_tab')
|
self.ui.cncjob_tab.setObjectName('cncjob_tab')
|
||||||
|
|
||||||
|
# delete the absolute and relative position and messages in the infobar
|
||||||
|
self.ui.position_label.setText("")
|
||||||
|
self.ui.rel_position_label.setText("")
|
||||||
|
|
||||||
# first clear previous text in text editor (if any)
|
# first clear previous text in text editor (if any)
|
||||||
self.ui.code_editor.clear()
|
self.ui.code_editor.clear()
|
||||||
|
self.toggle_codeeditor = True
|
||||||
|
|
||||||
# Switch plot_area to CNCJob tab
|
# Switch plot_area to CNCJob tab
|
||||||
self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab)
|
self.ui.plot_tab_area.setCurrentWidget(self.ui.cncjob_tab)
|
||||||
|
|
||||||
self.toggle_codeeditor = True
|
def on_view_source(self):
|
||||||
|
try:
|
||||||
|
obj = self.collection.get_active()
|
||||||
|
except:
|
||||||
|
self.inform.emit(_("[WARNING_NOTCL] Select an Gerber or Excellon file to view it's source file."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
# then append the text from GCode to the text editor
|
||||||
|
try:
|
||||||
|
file = StringIO(obj.source_file)
|
||||||
|
except AttributeError:
|
||||||
|
self.inform.emit(_("[WARNING_NOTCL] There is no selected object for which to see it's source file code."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
if obj.kind == 'gerber':
|
||||||
|
flt = "Gerber Files (*.GBR);;All Files (*.*)"
|
||||||
|
elif obj.kind == 'excellon':
|
||||||
|
flt = "Excellon Files (*.DRL);;All Files (*.*)"
|
||||||
|
|
||||||
|
self.init_code_editor(name=_("Source Editor"))
|
||||||
|
self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen(filt=flt))
|
||||||
|
self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode(filt=flt))
|
||||||
|
|
||||||
|
try:
|
||||||
|
for line in file:
|
||||||
|
proc_line = str(line).strip('\n')
|
||||||
|
self.ui.code_editor.append(proc_line)
|
||||||
|
except Exception as e:
|
||||||
|
log.debug('App.on_view_source() -->%s' % str(e))
|
||||||
|
self.inform.emit(_('[ERROR]App.on_view_source() -->%s') % str(e))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
|
||||||
|
|
||||||
|
self.handleTextChanged()
|
||||||
|
self.ui.show()
|
||||||
|
|
||||||
|
def on_toggle_code_editor(self):
|
||||||
|
self.report_usage("on_toggle_code_editor()")
|
||||||
|
|
||||||
|
if self.toggle_codeeditor is False:
|
||||||
|
self.init_code_editor(name=_("Code Editor"))
|
||||||
|
self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen())
|
||||||
|
self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode())
|
||||||
|
else:
|
||||||
|
for idx in range(self.ui.plot_tab_area.count()):
|
||||||
|
if self.ui.plot_tab_area.widget(idx).objectName() == "cncjob_tab":
|
||||||
|
self.ui.plot_tab_area.closeTab(idx)
|
||||||
|
break
|
||||||
|
self.toggle_codeeditor = False
|
||||||
|
|
||||||
|
def on_filenewscript(self):
|
||||||
|
flt = "FlatCAM Scripts (*.FlatScript);;All Files (*.*)"
|
||||||
|
self.init_code_editor(name=_("Script Editor"))
|
||||||
|
self.ui.buttonOpen.clicked.connect(lambda: self.handleOpen(filt=flt))
|
||||||
|
self.ui.buttonSave.clicked.connect(lambda: self.handleSaveGCode(filt=flt))
|
||||||
|
|
||||||
def on_fileopenscript(self):
|
def on_fileopenscript(self):
|
||||||
_filter_ = "TCL script (*.FlatScript);;TCL script (*.TCL);;TCL script (*.TXT);;All Files (*.*)"
|
_filter_ = "TCL script (*.FlatScript);;TCL script (*.TCL);;TCL script (*.TXT);;All Files (*.*)"
|
||||||
@@ -5818,6 +5828,7 @@ class App(QtCore.QObject):
|
|||||||
self.inform.emit(_("[WARNING_NOTCL]Open TCL script cancelled."))
|
self.inform.emit(_("[WARNING_NOTCL]Open TCL script cancelled."))
|
||||||
else:
|
else:
|
||||||
self.on_filenewscript()
|
self.on_filenewscript()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(filename, "r") as opened_script:
|
with open(filename, "r") as opened_script:
|
||||||
try:
|
try:
|
||||||
@@ -5837,7 +5848,6 @@ class App(QtCore.QObject):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("App.on_fileopenscript() -> %s" % str(e))
|
log.debug("App.on_fileopenscript() -> %s" % str(e))
|
||||||
|
|
||||||
|
|
||||||
def on_filerunscript(self):
|
def on_filerunscript(self):
|
||||||
"""
|
"""
|
||||||
File menu callback for loading and running a TCL script.
|
File menu callback for loading and running a TCL script.
|
||||||
|
|||||||
@@ -5305,7 +5305,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
|||||||
|
|
||||||
self.ui.updateplot_button.clicked.connect(self.on_updateplot_button_click)
|
self.ui.updateplot_button.clicked.connect(self.on_updateplot_button_click)
|
||||||
self.ui.export_gcode_button.clicked.connect(self.on_exportgcode_button_click)
|
self.ui.export_gcode_button.clicked.connect(self.on_exportgcode_button_click)
|
||||||
self.ui.modify_gcode_button.clicked.connect(self.on_modifygcode_button_click)
|
self.ui.modify_gcode_button.clicked.connect(self.on_edit_code_click)
|
||||||
|
|
||||||
self.ui.tc_variable_combo.currentIndexChanged[str].connect(self.on_cnc_custom_parameters)
|
self.ui.tc_variable_combo.currentIndexChanged[str].connect(self.on_cnc_custom_parameters)
|
||||||
|
|
||||||
@@ -5385,7 +5385,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
|||||||
self.app.file_saved.emit("gcode", filename)
|
self.app.file_saved.emit("gcode", filename)
|
||||||
self.app.inform.emit(_("[success] Machine Code file saved to: %s") % filename)
|
self.app.inform.emit(_("[success] Machine Code file saved to: %s") % filename)
|
||||||
|
|
||||||
def on_modifygcode_button_click(self, *args):
|
def on_edit_code_click(self, *args):
|
||||||
preamble = str(self.ui.prepend_text.get_value())
|
preamble = str(self.ui.prepend_text.get_value())
|
||||||
postamble = str(self.ui.append_text.get_value())
|
postamble = str(self.ui.append_text.get_value())
|
||||||
gc = self.export_gcode(preamble=preamble, postamble=postamble, to_file=True)
|
gc = self.export_gcode(preamble=preamble, postamble=postamble, to_file=True)
|
||||||
@@ -5394,18 +5394,9 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
|||||||
else:
|
else:
|
||||||
self.app.gcode_edited = gc
|
self.app.gcode_edited = gc
|
||||||
|
|
||||||
# add the tab if it was closed
|
self.app.init_code_editor(name=_("Code Editor"))
|
||||||
self.app.ui.plot_tab_area.addTab(self.app.ui.cncjob_tab, _("Code Editor"))
|
self.app.ui.buttonOpen.clicked.connect(self.app.handleOpen)
|
||||||
|
self.app.ui.buttonSave.clicked.connect(self.app.handleSaveGCode)
|
||||||
# delete the absolute and relative position and messages in the infobar
|
|
||||||
self.app.ui.position_label.setText("")
|
|
||||||
self.app.ui.rel_position_label.setText("")
|
|
||||||
|
|
||||||
# Switch plot_area to CNCJob tab
|
|
||||||
self.app.ui.plot_tab_area.setCurrentWidget(self.app.ui.cncjob_tab)
|
|
||||||
|
|
||||||
# first clear previous text in text editor (if any)
|
|
||||||
self.app.ui.code_editor.clear()
|
|
||||||
|
|
||||||
# then append the text from GCode to the text editor
|
# then append the text from GCode to the text editor
|
||||||
try:
|
try:
|
||||||
@@ -5413,8 +5404,8 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
|||||||
proc_line = str(line).strip('\n')
|
proc_line = str(line).strip('\n')
|
||||||
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('FlatCAMCNNJob.on_modifygcode_button_click() -->%s' % str(e))
|
log.debug('FlatCAMCNNJob.on_edit_code_click() -->%s' % str(e))
|
||||||
self.app.inform.emit(_('[ERROR]FlatCAMCNNJob.on_modifygcode_button_click() -->%s') % str(e))
|
self.app.inform.emit(_('[ERROR]FlatCAMCNNJob.on_edit_code_click() -->%s') % str(e))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.app.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
|
self.app.ui.code_editor.moveCursor(QtGui.QTextCursor.Start)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ CAD program, and create G-Code for Isolation routing.
|
|||||||
18.03.2019
|
18.03.2019
|
||||||
|
|
||||||
- added ability to create new scripts and open scripts in FlatCAM Script Editor
|
- added ability to create new scripts and open scripts in FlatCAM Script Editor
|
||||||
|
- the Code Editor tab name is changed according to the task; 'save' and 'open' buttons will have filters installed for the QOpenDialog fit to the task
|
||||||
|
|
||||||
17.03.2019
|
17.03.2019
|
||||||
|
|
||||||
|
|||||||
@@ -595,9 +595,12 @@ class FCTab(QtWidgets.QTabWidget):
|
|||||||
|
|
||||||
|
|
||||||
class FCDetachableTab(QtWidgets.QTabWidget):
|
class FCDetachableTab(QtWidgets.QTabWidget):
|
||||||
# From here: https://stackoverflow.com/questions/47267195/in-pyqt4-is-it-possible-to-detach-tabs-from-a-qtabwidget
|
"""
|
||||||
def __init__(self, protect=None, protect_by_name=None, parent=None):
|
From here:
|
||||||
|
https://stackoverflow.com/questions/47267195/in-pyqt4-is-it-possible-to-detach-tabs-from-a-qtabwidget
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, protect=None, protect_by_name=None, parent=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.tabBar = self.FCTabBar(self)
|
self.tabBar = self.FCTabBar(self)
|
||||||
@@ -639,25 +642,38 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
self.removeTab(currentIndex)
|
self.removeTab(currentIndex)
|
||||||
|
|
||||||
def closeTab(self, currentIndex):
|
def closeTab(self, currentIndex):
|
||||||
|
"""
|
||||||
|
Slot connected to the tabCloseRequested signal
|
||||||
|
|
||||||
|
:param currentIndex:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
self.removeTab(currentIndex)
|
self.removeTab(currentIndex)
|
||||||
|
|
||||||
def protectTab(self, currentIndex):
|
def protectTab(self, currentIndex):
|
||||||
# self.FCTabBar().setTabButton(currentIndex, QtWidgets.QTabBar.RightSide, None)
|
# self.FCTabBar().setTabButton(currentIndex, QtWidgets.QTabBar.RightSide, None)
|
||||||
self.tabBar.setTabButton(currentIndex, QtWidgets.QTabBar.RightSide, None)
|
self.tabBar.setTabButton(currentIndex, QtWidgets.QTabBar.RightSide, None)
|
||||||
|
|
||||||
##
|
|
||||||
# The default movable functionality of QTabWidget must remain disabled
|
|
||||||
# so as not to conflict with the added features
|
|
||||||
def setMovable(self, movable):
|
def setMovable(self, movable):
|
||||||
|
"""
|
||||||
|
The default movable functionality of QTabWidget must remain disabled
|
||||||
|
so as not to conflict with the added features
|
||||||
|
|
||||||
|
:param movable:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
##
|
|
||||||
# Move a tab from one position (index) to another
|
|
||||||
#
|
|
||||||
# @param fromIndex the original index location of the tab
|
|
||||||
# @param toIndex the new index location of the tab
|
|
||||||
@pyqtSlot(int, int)
|
@pyqtSlot(int, int)
|
||||||
def moveTab(self, fromIndex, toIndex):
|
def moveTab(self, fromIndex, toIndex):
|
||||||
|
"""
|
||||||
|
Move a tab from one position (index) to another
|
||||||
|
|
||||||
|
:param fromIndex: the original index location of the tab
|
||||||
|
:param toIndex: the new index location of the tab
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
widget = self.widget(fromIndex)
|
widget = self.widget(fromIndex)
|
||||||
icon = self.tabIcon(fromIndex)
|
icon = self.tabIcon(fromIndex)
|
||||||
text = self.tabText(fromIndex)
|
text = self.tabText(fromIndex)
|
||||||
@@ -666,15 +682,16 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
self.insertTab(toIndex, widget, icon, text)
|
self.insertTab(toIndex, widget, icon, text)
|
||||||
self.setCurrentIndex(toIndex)
|
self.setCurrentIndex(toIndex)
|
||||||
|
|
||||||
##
|
|
||||||
# Detach the tab by removing it's contents and placing them in
|
|
||||||
# a DetachedTab window
|
|
||||||
#
|
|
||||||
# @param index the index location of the tab to be detached
|
|
||||||
# @param point the screen position for creating the new DetachedTab window
|
|
||||||
@pyqtSlot(int, QtCore.QPoint)
|
@pyqtSlot(int, QtCore.QPoint)
|
||||||
def detachTab(self, index, point):
|
def detachTab(self, index, point):
|
||||||
|
"""
|
||||||
|
Detach the tab by removing it's contents and placing them in
|
||||||
|
a DetachedTab window
|
||||||
|
|
||||||
|
:param index: the index location of the tab to be detached
|
||||||
|
:param point: the screen position for creating the new DetachedTab window
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
self.old_index = index
|
self.old_index = index
|
||||||
|
|
||||||
# Get the tab content and add name FlatCAM to the tab so we know on which app is this tab linked
|
# Get the tab content and add name FlatCAM to the tab so we know on which app is this tab linked
|
||||||
@@ -699,20 +716,20 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
detachedTab.move(point)
|
detachedTab.move(point)
|
||||||
detachedTab.show()
|
detachedTab.show()
|
||||||
|
|
||||||
|
|
||||||
# Create a reference to maintain access to the detached tab
|
# Create a reference to maintain access to the detached tab
|
||||||
self.detachedTabs[name] = detachedTab
|
self.detachedTabs[name] = detachedTab
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# Re-attach the tab by removing the content from the DetachedTab window,
|
|
||||||
# closing it, and placing the content back into the DetachableTabWidget
|
|
||||||
#
|
|
||||||
# @param contentWidget the content widget from the DetachedTab window
|
|
||||||
# @param name the name of the detached tab
|
|
||||||
# @param icon the window icon for the detached tab
|
|
||||||
# @param insertAt insert the re-attached tab at the given index
|
|
||||||
def attachTab(self, contentWidget, name, icon, insertAt=None):
|
def attachTab(self, contentWidget, name, icon, insertAt=None):
|
||||||
|
"""
|
||||||
|
Re-attach the tab by removing the content from the DetachedTab window,
|
||||||
|
closing it, and placing the content back into the DetachableTabWidget
|
||||||
|
|
||||||
|
:param contentWidget: the content widget from the DetachedTab window
|
||||||
|
:param name: the name of the detached tab
|
||||||
|
:param icon: the window icon for the detached tab
|
||||||
|
:param insertAt: insert the re-attached tab at the given index
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
# Make the content widget a child of this widget
|
# Make the content widget a child of this widget
|
||||||
contentWidget.setParent(self)
|
contentWidget.setParent(self)
|
||||||
@@ -773,11 +790,13 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
if index > -1:
|
if index > -1:
|
||||||
self.setCurrentIndex(insert_index) if self.use_old_index else self.setCurrentIndex(index)
|
self.setCurrentIndex(insert_index) if self.use_old_index else self.setCurrentIndex(index)
|
||||||
|
|
||||||
##
|
|
||||||
# Remove the tab with the given name, even if it is detached
|
|
||||||
#
|
|
||||||
# @param name the name of the tab to be removed
|
|
||||||
def removeTabByName(self, name):
|
def removeTabByName(self, name):
|
||||||
|
"""
|
||||||
|
Remove the tab with the given name, even if it is detached
|
||||||
|
|
||||||
|
:param name: the name of the tab to be removed
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
# Remove the tab if it is attached
|
# Remove the tab if it is attached
|
||||||
attached = False
|
attached = False
|
||||||
@@ -798,17 +817,18 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
del self.detachedTabs[key]
|
del self.detachedTabs[key]
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# Handle dropping of a detached tab inside the DetachableTabWidget
|
|
||||||
#
|
|
||||||
# @param name the name of the detached tab
|
|
||||||
# @param index the index of an existing tab (if the tab bar
|
|
||||||
# determined that the drop occurred on an
|
|
||||||
# existing tab)
|
|
||||||
# @param dropPos the mouse cursor position when the drop occurred
|
|
||||||
@QtCore.pyqtSlot(str, int, QtCore.QPoint)
|
@QtCore.pyqtSlot(str, int, QtCore.QPoint)
|
||||||
def detachedTabDrop(self, name, index, dropPos):
|
def detachedTabDrop(self, name, index, dropPos):
|
||||||
|
"""
|
||||||
|
Handle dropping of a detached tab inside the DetachableTabWidget
|
||||||
|
|
||||||
|
:param name: the name of the detached tab
|
||||||
|
:param index: the index of an existing tab (if the tab bar
|
||||||
|
# determined that the drop occurred on an
|
||||||
|
# existing tab)
|
||||||
|
:param dropPos: the mouse cursor position when the drop occurred
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
# If the drop occurred on an existing tab, insert the detached
|
# If the drop occurred on an existing tab, insert the detached
|
||||||
# tab at the existing tab's location
|
# tab at the existing tab's location
|
||||||
@@ -848,10 +868,12 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
# automatically
|
# automatically
|
||||||
self.detachedTabs[name].close()
|
self.detachedTabs[name].close()
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# Close all tabs that are currently detached.
|
|
||||||
def closeDetachedTabs(self):
|
def closeDetachedTabs(self):
|
||||||
|
"""
|
||||||
|
Close all tabs that are currently detached.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
listOfDetachedTabs = []
|
listOfDetachedTabs = []
|
||||||
|
|
||||||
for key in self.detachedTabs:
|
for key in self.detachedTabs:
|
||||||
@@ -860,11 +882,12 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
for detachedTab in listOfDetachedTabs:
|
for detachedTab in listOfDetachedTabs:
|
||||||
detachedTab.close()
|
detachedTab.close()
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# When a tab is detached, the contents are placed into this QMainWindow. The tab
|
|
||||||
# can be re-attached by closing the dialog or by dragging the window into the tab bar
|
|
||||||
class FCDetachedTab(QtWidgets.QMainWindow):
|
class FCDetachedTab(QtWidgets.QMainWindow):
|
||||||
|
"""
|
||||||
|
When a tab is detached, the contents are placed into this QMainWindow. The tab
|
||||||
|
can be re-attached by closing the dialog or by dragging the window into the tab bar
|
||||||
|
"""
|
||||||
|
|
||||||
onCloseSignal = pyqtSignal(QtWidgets.QWidget, str, QtGui.QIcon)
|
onCloseSignal = pyqtSignal(QtWidgets.QWidget, str, QtGui.QIcon)
|
||||||
onDropSignal = pyqtSignal(str, QtCore.QPoint)
|
onDropSignal = pyqtSignal(str, QtCore.QPoint)
|
||||||
|
|
||||||
@@ -882,42 +905,46 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
self.installEventFilter(self.windowDropFilter)
|
self.installEventFilter(self.windowDropFilter)
|
||||||
self.windowDropFilter.onDropSignal.connect(self.windowDropSlot)
|
self.windowDropFilter.onDropSignal.connect(self.windowDropSlot)
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# Handle a window drop event
|
|
||||||
#
|
|
||||||
# @param dropPos the mouse cursor position of the drop
|
|
||||||
@QtCore.pyqtSlot(QtCore.QPoint)
|
@QtCore.pyqtSlot(QtCore.QPoint)
|
||||||
def windowDropSlot(self, dropPos):
|
def windowDropSlot(self, dropPos):
|
||||||
|
"""
|
||||||
|
Handle a window drop event
|
||||||
|
|
||||||
|
:param dropPos: the mouse cursor position of the drop
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
self.onDropSignal.emit(self.objectName(), dropPos)
|
self.onDropSignal.emit(self.objectName(), dropPos)
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# If the window is closed, emit the onCloseSignal and give the
|
|
||||||
# content widget back to the DetachableTabWidget
|
|
||||||
#
|
|
||||||
# @param event a close event
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
|
"""
|
||||||
|
If the window is closed, emit the onCloseSignal and give the
|
||||||
|
content widget back to the DetachableTabWidget
|
||||||
|
|
||||||
|
:param event: a close event
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
self.onCloseSignal.emit(self.contentWidget, self.objectName(), self.windowIcon())
|
self.onCloseSignal.emit(self.contentWidget, self.objectName(), self.windowIcon())
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# An event filter class to detect a QMainWindow drop event
|
|
||||||
class WindowDropFilter(QtCore.QObject):
|
class WindowDropFilter(QtCore.QObject):
|
||||||
|
"""
|
||||||
|
An event filter class to detect a QMainWindow drop event
|
||||||
|
"""
|
||||||
|
|
||||||
onDropSignal = pyqtSignal(QtCore.QPoint)
|
onDropSignal = pyqtSignal(QtCore.QPoint)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QtCore.QObject.__init__(self)
|
QtCore.QObject.__init__(self)
|
||||||
self.lastEvent = None
|
self.lastEvent = None
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# Detect a QMainWindow drop event by looking for a NonClientAreaMouseMove (173)
|
|
||||||
# event that immediately follows a Move event
|
|
||||||
#
|
|
||||||
# @param obj the object that generated the event
|
|
||||||
# @param event the current event
|
|
||||||
def eventFilter(self, obj, event):
|
def eventFilter(self, obj, event):
|
||||||
|
"""
|
||||||
|
Detect a QMainWindow drop event by looking for a NonClientAreaMouseMove (173)
|
||||||
|
event that immediately follows a Move event
|
||||||
|
|
||||||
|
:param obj: the object that generated the event
|
||||||
|
:param event: the current event
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
# If a NonClientAreaMouseMove (173) event immediately follows a Move event...
|
# If a NonClientAreaMouseMove (173) event immediately follows a Move event...
|
||||||
if self.lastEvent == QtCore.QEvent.Move and event.type() == 173:
|
if self.lastEvent == QtCore.QEvent.Move and event.type() == 173:
|
||||||
@@ -951,19 +978,24 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
self.mouseCursor = QtGui.QCursor()
|
self.mouseCursor = QtGui.QCursor()
|
||||||
self.dragInitiated = False
|
self.dragInitiated = False
|
||||||
|
|
||||||
|
|
||||||
# Send the onDetachTabSignal when a tab is double clicked
|
|
||||||
#
|
|
||||||
# @param event a mouse double click event
|
|
||||||
def mouseDoubleClickEvent(self, event):
|
def mouseDoubleClickEvent(self, event):
|
||||||
|
"""
|
||||||
|
Send the onDetachTabSignal when a tab is double clicked
|
||||||
|
|
||||||
|
:param event: a mouse double click event
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
event.accept()
|
event.accept()
|
||||||
self.onDetachTabSignal.emit(self.tabAt(event.pos()), self.mouseCursor.pos())
|
self.onDetachTabSignal.emit(self.tabAt(event.pos()), self.mouseCursor.pos())
|
||||||
|
|
||||||
|
|
||||||
# Set the starting position for a drag event when the mouse button is pressed
|
|
||||||
#
|
|
||||||
# @param event a mouse press event
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
|
"""
|
||||||
|
Set the starting position for a drag event when the mouse button is pressed
|
||||||
|
|
||||||
|
:param event: a mouse press event
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
if event.button() == QtCore.Qt.LeftButton:
|
if event.button() == QtCore.Qt.LeftButton:
|
||||||
self.dragStartPos = event.pos()
|
self.dragStartPos = event.pos()
|
||||||
|
|
||||||
@@ -974,14 +1006,15 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
|
|
||||||
QtWidgets.QTabBar.mousePressEvent(self, event)
|
QtWidgets.QTabBar.mousePressEvent(self, event)
|
||||||
|
|
||||||
|
|
||||||
# Determine if the current movement is a drag. If it is, convert it into a QDrag. If the
|
|
||||||
# drag ends inside the tab bar, emit an onMoveTabSignal. If the drag ends outside the tab
|
|
||||||
# bar, emit an onDetachTabSignal.
|
|
||||||
#
|
|
||||||
# @param event a mouse move event
|
|
||||||
def mouseMoveEvent(self, event):
|
def mouseMoveEvent(self, event):
|
||||||
|
"""
|
||||||
|
Determine if the current movement is a drag. If it is, convert it into a QDrag. If the
|
||||||
|
drag ends inside the tab bar, emit an onMoveTabSignal. If the drag ends outside the tab
|
||||||
|
bar, emit an onDetachTabSignal.
|
||||||
|
|
||||||
|
:param event: a mouse move event
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
# Determine if the current movement is detected as a drag
|
# Determine if the current movement is detected as a drag
|
||||||
if not self.dragStartPos.isNull() and ((event.pos() - self.dragStartPos).manhattanLength() < QtWidgets.QApplication.startDragDistance()):
|
if not self.dragStartPos.isNull() and ((event.pos() - self.dragStartPos).manhattanLength() < QtWidgets.QApplication.startDragDistance()):
|
||||||
self.dragInitiated = True
|
self.dragInitiated = True
|
||||||
@@ -1038,29 +1071,40 @@ class FCDetachableTab(QtWidgets.QTabWidget):
|
|||||||
else:
|
else:
|
||||||
QtWidgets.QTabBar.mouseMoveEvent(self, event)
|
QtWidgets.QTabBar.mouseMoveEvent(self, event)
|
||||||
|
|
||||||
# Determine if the drag has entered a tab position from another tab position
|
|
||||||
#
|
|
||||||
# @param event a drag enter event
|
|
||||||
def dragEnterEvent(self, event):
|
def dragEnterEvent(self, event):
|
||||||
|
"""
|
||||||
|
Determine if the drag has entered a tab position from another tab position
|
||||||
|
|
||||||
|
:param event: a drag enter event
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
mimeData = event.mimeData()
|
mimeData = event.mimeData()
|
||||||
# formats = mcd imeData.formats()
|
# formats = mcd imeData.formats()
|
||||||
|
|
||||||
# if formats.contains('action') and mimeData.data('action') == 'application/tab-detach':
|
# if formats.contains('action') and mimeData.data('action') == 'application/tab-detach':
|
||||||
# event.acceptProposedAction()
|
# event.acceptProposedAction()
|
||||||
|
|
||||||
QtWidgets.QTabBar.dragMoveEvent(self, event)
|
QtWidgets.QTabBar.dragMoveEvent(self, event)
|
||||||
|
|
||||||
# Get the position of the end of the drag
|
|
||||||
#
|
|
||||||
# @param event a drop event
|
|
||||||
def dropEvent(self, event):
|
def dropEvent(self, event):
|
||||||
|
"""
|
||||||
|
Get the position of the end of the drag
|
||||||
|
|
||||||
|
:param event: a drop event
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
self.dragDropedPos = event.pos()
|
self.dragDropedPos = event.pos()
|
||||||
QtWidgets.QTabBar.dropEvent(self, event)
|
QtWidgets.QTabBar.dropEvent(self, event)
|
||||||
|
|
||||||
# Determine if the detached tab drop event occurred on an existing tab,
|
|
||||||
# then send the event to the DetachableTabWidget
|
|
||||||
def detachedTabDrop(self, name, dropPos):
|
def detachedTabDrop(self, name, dropPos):
|
||||||
|
"""
|
||||||
|
Determine if the detached tab drop event occurred on an existing tab,
|
||||||
|
then send the event to the DetachableTabWidget
|
||||||
|
|
||||||
|
:param name:
|
||||||
|
:param dropPos:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
tabDropPos = self.mapFromGlobal(dropPos)
|
tabDropPos = self.mapFromGlobal(dropPos)
|
||||||
|
|
||||||
index = self.tabAt(tabDropPos)
|
index = self.tabAt(tabDropPos)
|
||||||
|
|||||||
@@ -2466,8 +2466,8 @@ msgstr "[success] Machine Code file saved to: %s"
|
|||||||
|
|
||||||
#: FlatCAMObj.py:5417
|
#: FlatCAMObj.py:5417
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "[ERROR]FlatCAMCNNJob.on_modifygcode_button_click() -->%s"
|
msgid "[ERROR]FlatCAMCNNJob.on_edit_code_click() -->%s"
|
||||||
msgstr "[ERROR]FlatCAMCNNJob.on_modifygcode_button_click() -->%s"
|
msgstr "[ERROR]FlatCAMCNNJob.on_edit_code_click() -->%s"
|
||||||
|
|
||||||
#: FlatCAMObj.py:5523
|
#: FlatCAMObj.py:5523
|
||||||
#, python-format
|
#, python-format
|
||||||
|
|||||||
@@ -2577,8 +2577,8 @@ msgstr "[success] Fişierul cu cod CNC este salvat in: %s"
|
|||||||
|
|
||||||
#: FlatCAMObj.py:5417
|
#: FlatCAMObj.py:5417
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "[ERROR]FlatCAMCNNJob.on_modifygcode_button_click() -->%s"
|
msgid "[ERROR]FlatCAMCNNJob.on_edit_code_click() -->%s"
|
||||||
msgstr "[ERROR]FlatCAMCNNJob.on_modifygcode_button_click() -->%s"
|
msgstr "[ERROR]FlatCAMCNNJob.on_edit_code_click() -->%s"
|
||||||
|
|
||||||
#: FlatCAMObj.py:5523
|
#: FlatCAMObj.py:5523
|
||||||
#, python-format
|
#, python-format
|
||||||
|
|||||||
@@ -2234,7 +2234,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: FlatCAMObj.py:5417
|
#: FlatCAMObj.py:5417
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "[ERROR]FlatCAMCNNJob.on_modifygcode_button_click() -->%s"
|
msgid "[ERROR]FlatCAMCNNJob.on_edit_code_click() -->%s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: FlatCAMObj.py:5523
|
#: FlatCAMObj.py:5523
|
||||||
|
|||||||
Reference in New Issue
Block a user