|
|
@@ -8,7 +8,7 @@
|
|
|
|
|
|
import sys
|
|
|
import traceback
|
|
|
-import urllib
|
|
|
+import urllib.request, urllib.parse, urllib.error
|
|
|
import getopt
|
|
|
import random
|
|
|
import logging
|
|
|
@@ -16,8 +16,8 @@ import simplejson as json
|
|
|
import re
|
|
|
import webbrowser
|
|
|
import os
|
|
|
-import Tkinter
|
|
|
-from PyQt4 import QtCore
|
|
|
+import tkinter
|
|
|
+from PyQt4 import Qt, QtCore, QtGui
|
|
|
import time # Just used for debugging. Double check before removing.
|
|
|
from xml.dom.minidom import parseString as parse_xml_string
|
|
|
from contextlib import contextmanager
|
|
|
@@ -27,10 +27,10 @@ from contextlib import contextmanager
|
|
|
########################################
|
|
|
import FlatCAMVersion
|
|
|
from FlatCAMWorker import Worker
|
|
|
-from ObjectCollection import *
|
|
|
-from FlatCAMObj import *
|
|
|
-from PlotCanvas import *
|
|
|
-from FlatCAMGUI import *
|
|
|
+import ObjectCollection
|
|
|
+from FlatCAMObj import FlatCAMCNCjob, FlatCAMExcellon, FlatCAMGerber, FlatCAMGeometry, FlatCAMObj
|
|
|
+from PlotCanvas import PlotCanvas
|
|
|
+from FlatCAMGUI import FlatCAMGUI, GlobalOptionsUI, FlatCAMActivityView, FlatCAMInfoBar
|
|
|
from FlatCAMCommon import LoudDict
|
|
|
from FlatCAMShell import FCShell
|
|
|
from FlatCAMDraw import FlatCAMDraw
|
|
|
@@ -39,6 +39,8 @@ from MeasurementTool import Measurement
|
|
|
from DblSidedTool import DblSidedTool
|
|
|
import tclCommands
|
|
|
|
|
|
+from camlib import *
|
|
|
+
|
|
|
|
|
|
########################################
|
|
|
## App ##
|
|
|
@@ -54,11 +56,11 @@ class App(QtCore.QObject):
|
|
|
try:
|
|
|
cmd_line_options, args = getopt.getopt(sys.argv[1:], "h:", "shellfile=")
|
|
|
except getopt.GetoptError:
|
|
|
- print cmd_line_help
|
|
|
+ print(cmd_line_help)
|
|
|
sys.exit(2)
|
|
|
for opt, arg in cmd_line_options:
|
|
|
if opt == '-h':
|
|
|
- print cmd_line_help
|
|
|
+ print(cmd_line_help)
|
|
|
sys.exit()
|
|
|
elif opt == '--shellfile':
|
|
|
cmd_line_shellfile = arg
|
|
|
@@ -106,16 +108,16 @@ class App(QtCore.QObject):
|
|
|
# Note: Setting the parameters to unicode does not seem
|
|
|
# to have an effect. Then are received as Qstring
|
|
|
# anyway.
|
|
|
- file_opened = QtCore.pyqtSignal(unicode, unicode) # File type and filename
|
|
|
+ file_opened = QtCore.pyqtSignal(str, str) # File type and filename
|
|
|
|
|
|
progress = QtCore.pyqtSignal(int) # Percentage of progress
|
|
|
|
|
|
plots_updated = QtCore.pyqtSignal()
|
|
|
|
|
|
- # Emitted by new_object() and passes the new object as argument.
|
|
|
- # on_object_created() adds the object to the collection,
|
|
|
+ # Emitted by new_object() and passes the new object as argument and a plot flag
|
|
|
+ # on_object_created() adds the object to the collection, plot the object if plot flag is True
|
|
|
# and emits new_object_available.
|
|
|
- object_created = QtCore.pyqtSignal(object)
|
|
|
+ object_created = QtCore.pyqtSignal(object, bool)
|
|
|
|
|
|
# Emitted when a new object has been added to the collection
|
|
|
# and is ready to be used.
|
|
|
@@ -471,7 +473,7 @@ class App(QtCore.QObject):
|
|
|
#self.options_write_form()
|
|
|
self.on_options_combo_change(0) # Will show the initial form
|
|
|
|
|
|
- self.collection = ObjectCollection()
|
|
|
+ self.collection = ObjectCollection.ObjectCollection()
|
|
|
self.ui.project_tab_layout.addWidget(self.collection.view)
|
|
|
#### End of Data ####
|
|
|
|
|
|
@@ -619,7 +621,7 @@ class App(QtCore.QObject):
|
|
|
cmd_line_shellfile_text = myfile.read()
|
|
|
self.shell._sysShell.exec_command(cmd_line_shellfile_text)
|
|
|
except Exception as ext:
|
|
|
- print "ERROR: ", ext
|
|
|
+ print(("ERROR: ", ext))
|
|
|
sys.exit(2)
|
|
|
|
|
|
# Post-GUI initialization: Experimental attempt
|
|
|
@@ -637,7 +639,7 @@ class App(QtCore.QObject):
|
|
|
# because tcl was execudted in old instance of TCL
|
|
|
pass
|
|
|
else:
|
|
|
- self.tcl = Tkinter.Tcl()
|
|
|
+ self.tcl = tkinter.Tcl()
|
|
|
self.setup_shell()
|
|
|
|
|
|
def defaults_read_form(self):
|
|
|
@@ -700,7 +702,7 @@ class App(QtCore.QObject):
|
|
|
:return: None
|
|
|
"""
|
|
|
if not isinstance(self.collection.get_active(), FlatCAMGeometry):
|
|
|
- self.info("Select a Geometry Object to edit.")
|
|
|
+ self.inform.emit("Select a Geometry Object to edit.")
|
|
|
return
|
|
|
|
|
|
self.ui.updategeo_btn.setEnabled(True)
|
|
|
@@ -715,7 +717,7 @@ class App(QtCore.QObject):
|
|
|
"""
|
|
|
geo = self.collection.get_active()
|
|
|
if not isinstance(geo, FlatCAMGeometry):
|
|
|
- self.info("Select a Geometry Object to update.")
|
|
|
+ self.inform.emit("Select a Geometry Object to update.")
|
|
|
return
|
|
|
|
|
|
self.draw.update_fcgeometry(geo)
|
|
|
@@ -856,7 +858,7 @@ class App(QtCore.QObject):
|
|
|
if result != 'None':
|
|
|
self.shell.append_output(result + '\n')
|
|
|
|
|
|
- except Tkinter.TclError, e:
|
|
|
+ except tkinter.TclError as e:
|
|
|
# This will display more precise answer if something in TCL shell fails
|
|
|
result = self.tcl.eval("set errorInfo")
|
|
|
self.log.error("Exec command Exception: %s" % (result + '\n'))
|
|
|
@@ -902,7 +904,7 @@ class App(QtCore.QObject):
|
|
|
if retval and retfcn(retval):
|
|
|
self.shell.append_output(retfcn(retval) + "\n")
|
|
|
|
|
|
- except Exception, e:
|
|
|
+ except Exception as e:
|
|
|
#self.shell.append_error(''.join(traceback.format_exc()))
|
|
|
#self.shell.append_error("?\n")
|
|
|
self.shell.append_error(str(e) + "\n")
|
|
|
@@ -922,14 +924,14 @@ class App(QtCore.QObject):
|
|
|
if match:
|
|
|
level = match.group(1)
|
|
|
msg_ = match.group(2)
|
|
|
- self.ui.fcinfo.set_status(QtCore.QString(msg_), level=level)
|
|
|
+ self.ui.fcinfo.set_status(str(msg_), level=level)
|
|
|
|
|
|
if toshell:
|
|
|
error = level == "error" or level == "warning"
|
|
|
self.shell_message(msg, error=error, show=True)
|
|
|
|
|
|
else:
|
|
|
- self.ui.fcinfo.set_status(QtCore.QString(msg), level="info")
|
|
|
+ self.ui.fcinfo.set_status(str(msg), level="info")
|
|
|
|
|
|
if toshell:
|
|
|
self.shell_message(msg)
|
|
|
@@ -980,7 +982,7 @@ class App(QtCore.QObject):
|
|
|
self.log.debug(" %s" % kind)
|
|
|
self.log.debug(" %s" % filename)
|
|
|
|
|
|
- record = {'kind': unicode(kind), 'filename': unicode(filename)}
|
|
|
+ record = {'kind': str(kind), 'filename': str(filename)}
|
|
|
if record in self.recent:
|
|
|
return
|
|
|
|
|
|
@@ -1028,9 +1030,12 @@ class App(QtCore.QObject):
|
|
|
but before it is attached to the application. The function is
|
|
|
called with 2 parameters: the new object and the App instance.
|
|
|
:type initialize: function
|
|
|
+ :param plot: Whether to plot the object or not
|
|
|
+ :type plot: Bool
|
|
|
:return: None
|
|
|
:rtype: None
|
|
|
"""
|
|
|
+ self.plot = plot
|
|
|
|
|
|
App.log.debug("new_object()")
|
|
|
|
|
|
@@ -1054,6 +1059,10 @@ class App(QtCore.QObject):
|
|
|
oname = option[len(kind) + 1:]
|
|
|
obj.options[oname] = self.options[option]
|
|
|
|
|
|
+ # make sure that the plot option of the new object is reflecting the current status and not the general option
|
|
|
+ # solve issues with the modelview currently used (checkbox on the Project Tab)
|
|
|
+ obj.options['plot'] = self.plot
|
|
|
+
|
|
|
# Initialize as per user request
|
|
|
# User must take care to implement initialize
|
|
|
# in a thread-safe way as is is likely that we
|
|
|
@@ -1072,11 +1081,11 @@ class App(QtCore.QObject):
|
|
|
t3 = time.time()
|
|
|
self.log.debug("%f seconds converting units." % (t3 - t2))
|
|
|
|
|
|
- FlatCAMApp.App.log.debug("Moving new object back to main thread.")
|
|
|
+ self.log.debug("Moving new object back to main thread.")
|
|
|
|
|
|
# Move the object to the main thread and let the app know that it is available.
|
|
|
obj.moveToThread(QtGui.QApplication.instance().thread())
|
|
|
- self.object_created.emit(obj)
|
|
|
+ self.object_created.emit(obj, self.plot)
|
|
|
|
|
|
return obj
|
|
|
|
|
|
@@ -1123,7 +1132,7 @@ class App(QtCore.QObject):
|
|
|
layout1.addLayout(layout2)
|
|
|
|
|
|
logo = QtGui.QLabel()
|
|
|
- logo.setPixmap(QtGui.QPixmap('share:flatcam_icon256.png'))
|
|
|
+ logo.setPixmap(QtGui.QPixmap('share/flatcam_icon256.png'))
|
|
|
layout2.addWidget(logo, stretch=0)
|
|
|
|
|
|
title = QtGui.QLabel(
|
|
|
@@ -1490,12 +1499,14 @@ class App(QtCore.QObject):
|
|
|
# Keep this for later
|
|
|
try:
|
|
|
name = self.collection.get_active().options["name"]
|
|
|
+ isPlotted = self.collection.get_active().options["plot"]
|
|
|
except AttributeError:
|
|
|
self.log.debug("Nothing selected for deletion")
|
|
|
return
|
|
|
|
|
|
- # Remove plot
|
|
|
- self.plotcanvas.figure.delaxes(self.collection.get_active().axes)
|
|
|
+ # Remove plot only if the object was plotted otherwise delaxes will fail
|
|
|
+ if isPlotted:
|
|
|
+ self.plotcanvas.figure.delaxes(self.collection.get_active().axes)
|
|
|
self.plotcanvas.auto_adjust_axes()
|
|
|
|
|
|
# Clear form
|
|
|
@@ -1537,11 +1548,12 @@ class App(QtCore.QObject):
|
|
|
def on_row_activated(self, index):
|
|
|
self.ui.notebook.setCurrentWidget(self.ui.selected_tab)
|
|
|
|
|
|
- def on_object_created(self, obj):
|
|
|
+ def on_object_created(self, obj, plot):
|
|
|
"""
|
|
|
Event callback for object creation.
|
|
|
|
|
|
:param obj: The newly created FlatCAM object.
|
|
|
+ :param plot: If to plot the new object, bool
|
|
|
:return: None
|
|
|
"""
|
|
|
t0 = time.time() # DEBUG
|
|
|
@@ -1552,7 +1564,9 @@ class App(QtCore.QObject):
|
|
|
|
|
|
self.inform.emit("Object (%s) created: %s" % (obj.kind, obj.options['name']))
|
|
|
self.new_object_available.emit(obj)
|
|
|
- obj.plot()
|
|
|
+ if plot:
|
|
|
+ obj.plot()
|
|
|
+
|
|
|
self.on_zoom_fit(None)
|
|
|
t1 = time.time() # DEBUG
|
|
|
self.log.debug("%f seconds adding object and plotting." % (t1 - t0))
|
|
|
@@ -1634,10 +1648,11 @@ class App(QtCore.QObject):
|
|
|
try:
|
|
|
App.log.debug('button=%d, x=%d, y=%d, xdata=%f, ydata=%f' % (
|
|
|
event.button, event.x, event.y, event.xdata, event.ydata))
|
|
|
+ modifiers = QtGui.QApplication.keyboardModifiers()
|
|
|
+ if modifiers == QtCore.Qt.ControlModifier:
|
|
|
+ self.clipboard.setText(self.defaults["point_clipboard_format"] % (event.xdata, event.ydata))
|
|
|
|
|
|
- self.clipboard.setText(self.defaults["point_clipboard_format"] % (event.xdata, event.ydata))
|
|
|
-
|
|
|
- except Exception, e:
|
|
|
+ except Exception as e:
|
|
|
App.log.debug("Outside plot?")
|
|
|
App.log.debug(str(e))
|
|
|
|
|
|
@@ -1707,7 +1722,7 @@ class App(QtCore.QObject):
|
|
|
# The Qt methods above will return a QString which can cause problems later.
|
|
|
# So far json.dump() will fail to serialize it.
|
|
|
# TODO: Improve the serialization methods and remove this fix.
|
|
|
- filename = unicode(filename)
|
|
|
+ filename = str(filename)
|
|
|
|
|
|
if filename == "":
|
|
|
self.inform.emit("Open cancelled.")
|
|
|
@@ -1734,7 +1749,7 @@ class App(QtCore.QObject):
|
|
|
# The Qt methods above will return a QString which can cause problems later.
|
|
|
# So far json.dump() will fail to serialize it.
|
|
|
# TODO: Improve the serialization methods and remove this fix.
|
|
|
- filename = unicode(filename)
|
|
|
+ filename = str(filename)
|
|
|
|
|
|
if filename == "":
|
|
|
self.inform.emit("Open cancelled.")
|
|
|
@@ -1761,7 +1776,7 @@ class App(QtCore.QObject):
|
|
|
# The Qt methods above will return a QString which can cause problems later.
|
|
|
# So far json.dump() will fail to serialize it.
|
|
|
# TODO: Improve the serialization methods and remove this fix.
|
|
|
- filename = unicode(filename)
|
|
|
+ filename = str(filename)
|
|
|
|
|
|
if filename == "":
|
|
|
self.inform.emit("Open cancelled.")
|
|
|
@@ -1788,7 +1803,7 @@ class App(QtCore.QObject):
|
|
|
# The Qt methods above will return a QString which can cause problems later.
|
|
|
# So far json.dump() will fail to serialize it.
|
|
|
# TODO: Improve the serialization methods and remove this fix.
|
|
|
- filename = unicode(filename)
|
|
|
+ filename = str(filename)
|
|
|
|
|
|
if filename == "":
|
|
|
self.inform.emit("Open cancelled.")
|
|
|
@@ -1838,7 +1853,7 @@ class App(QtCore.QObject):
|
|
|
except TypeError:
|
|
|
filename = QtGui.QFileDialog.getSaveFileName(caption="Export SVG")
|
|
|
|
|
|
- filename = unicode(filename)
|
|
|
+ filename = str(filename)
|
|
|
|
|
|
if filename == "":
|
|
|
self.inform.emit("Export SVG cancelled.")
|
|
|
@@ -1861,7 +1876,7 @@ class App(QtCore.QObject):
|
|
|
except TypeError:
|
|
|
filename = QtGui.QFileDialog.getOpenFileName(caption="Import SVG")
|
|
|
|
|
|
- filename = unicode(filename)
|
|
|
+ filename = str(filename)
|
|
|
|
|
|
if filename == "":
|
|
|
self.inform.emit("Open cancelled.")
|
|
|
@@ -1904,7 +1919,7 @@ class App(QtCore.QObject):
|
|
|
except TypeError:
|
|
|
filename = QtGui.QFileDialog.getSaveFileName(caption="Save Project As ...")
|
|
|
|
|
|
- filename = unicode(filename)
|
|
|
+ filename = str(filename)
|
|
|
|
|
|
try:
|
|
|
f = open(filename, 'r')
|
|
|
@@ -2038,7 +2053,7 @@ class App(QtCore.QObject):
|
|
|
app_obj.progress.emit(0)
|
|
|
raise IOError('Failed to open file: ' + filename)
|
|
|
|
|
|
- except ParseError, e:
|
|
|
+ except ParseError as e:
|
|
|
app_obj.inform.emit("[error] Failed to parse file: " + filename + ". " + e[0])
|
|
|
app_obj.progress.emit(0)
|
|
|
self.log.error(str(e))
|
|
|
@@ -2339,7 +2354,7 @@ class App(QtCore.QObject):
|
|
|
self.worker_task.emit({'fcn': worker_task, 'params': [self]})
|
|
|
|
|
|
def register_folder(self, filename):
|
|
|
- self.defaults["last_folder"] = os.path.split(unicode(filename))[0]
|
|
|
+ self.defaults["last_folder"] = os.path.split(str(filename))[0]
|
|
|
|
|
|
def set_progress_bar(self, percentage, text=""):
|
|
|
self.ui.progress_bar.setValue(int(percentage))
|
|
|
@@ -3591,7 +3606,7 @@ class App(QtCore.QObject):
|
|
|
output = ''
|
|
|
import collections
|
|
|
od = collections.OrderedDict(sorted(commands.items()))
|
|
|
- for cmd_, val in od.iteritems():
|
|
|
+ for cmd_, val in list(od.items()):
|
|
|
#print cmd, '\n', ''.join(['~']*len(cmd))
|
|
|
output += cmd_ + ' \n' + ''.join(['~'] * len(cmd_)) + '\n'
|
|
|
|
|
|
@@ -3645,7 +3660,7 @@ class App(QtCore.QObject):
|
|
|
|
|
|
try:
|
|
|
obj.follow(**kwa)
|
|
|
- except Exception, e:
|
|
|
+ except Exception as e:
|
|
|
return "ERROR: %s" % str(e)
|
|
|
|
|
|
# def get_sys(param):
|
|
|
@@ -4139,11 +4154,11 @@ class App(QtCore.QObject):
|
|
|
|
|
|
# TODO: Move this to constructor
|
|
|
icons = {
|
|
|
- "gerber": "share:flatcam_icon16.png",
|
|
|
- "excellon": "share:drill16.png",
|
|
|
- "cncjob": "share:cnc16.png",
|
|
|
- "project": "share:project16.png",
|
|
|
- "svg": "share:geometry16.png"
|
|
|
+ "gerber": "share/flatcam_icon16.png",
|
|
|
+ "excellon": "share/drill16.png",
|
|
|
+ "cncjob": "share/cnc16.png",
|
|
|
+ "project": "share/project16.png",
|
|
|
+ "svg": "share/geometry16.png"
|
|
|
}
|
|
|
|
|
|
openers = {
|
|
|
@@ -4232,12 +4247,12 @@ class App(QtCore.QObject):
|
|
|
"?s=" + str(self.defaults['serial']) + \
|
|
|
"&v=" + str(self.version) + \
|
|
|
"&os=" + str(self.os) + \
|
|
|
- "&" + urllib.urlencode(self.defaults["stats"])
|
|
|
+ "&" + urllib.parse.urlencode(self.defaults["stats"])
|
|
|
App.log.debug("Checking for updates @ %s" % full_url)
|
|
|
|
|
|
### Get the data
|
|
|
try:
|
|
|
- f = urllib.urlopen(full_url)
|
|
|
+ f = urllib.request.urlopen(full_url)
|
|
|
except:
|
|
|
# App.log.warning("Failed checking for latest version. Could not connect.")
|
|
|
self.log.warning("Failed checking for latest version. Could not connect.")
|
|
|
@@ -4246,7 +4261,7 @@ class App(QtCore.QObject):
|
|
|
|
|
|
try:
|
|
|
data = json.load(f)
|
|
|
- except Exception, e:
|
|
|
+ except Exception as e:
|
|
|
App.log.error("Could not parse information about latest version.")
|
|
|
self.inform.emit("[error] Could not parse information about latest version.")
|
|
|
App.log.debug("json.load(): %s" % str(e))
|
|
|
@@ -4264,7 +4279,7 @@ class App(QtCore.QObject):
|
|
|
App.log.debug("Newer version available.")
|
|
|
self.message.emit(
|
|
|
"Newer Version Available",
|
|
|
- QtCore.QString("There is a newer version of FlatCAM " +
|
|
|
+ str("There is a newer version of FlatCAM " +
|
|
|
"available for download:<br><br>" +
|
|
|
"<B>" + data["name"] + "</b><br>" +
|
|
|
data["message"].replace("\n", "<br>")),
|