Fixed the majority of the functionality to where scripts can now be opened, saved, and executed in a multi-window environment.

This commit is contained in:
Jeremy Mack Wright 2016-10-03 21:38:44 -04:00
parent c53da16bde
commit cb1221da2c
13 changed files with 98 additions and 77 deletions

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Adds all of the commands that are used for the menus of the CadQuery module"""
# (c) 2014-2015 Jeremy Wright LGPL v3
# (c) 2014-2016 Jeremy Wright Apache 2.0 License
import imp, os, sys, tempfile
import FreeCAD, FreeCADGui
@ -8,22 +8,13 @@ from PySide import QtGui
import ExportCQ, ImportCQ
import module_locator
import Settings
import Shared
#Distinguish python built-in open function from the one declared here
if open.__module__ == '__builtin__':
pythonopen = open
def clearActiveDocument():
"""Clears the currently active 3D view so that we can re-render"""
doc = FreeCAD.ActiveDocument
#Make sure we have an active document to work with
if doc is not None:
for obj in doc.Objects:
doc.removeObject(obj.Name)
class CadQueryClearOutput:
"""Allows the user to clear the reports view when it gets overwhelmed with output"""
@ -64,7 +55,7 @@ class CadQueryCloseScript:
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
#If there's nothing open in the code pane, we don't need to close it
if len(cqCodePane.file.path) == 0:
if cqCodePane is None or len(cqCodePane.file.path) == 0:
return
#Check to see if we need to save the script
@ -120,7 +111,7 @@ class CadQueryExecuteExample:
exs_dir_path = os.path.join(module_base_path, 'Examples')
#We need to close any file that's already open in the editor window
CadQueryCloseScript().Activated()
# CadQueryCloseScript().Activated()
#Append this script's directory to sys.path
sys.path.append(os.path.dirname(exs_dir_path))
@ -153,17 +144,18 @@ class CadQueryExecuteScript:
def Activated(self):
#Grab our code editor so we can interact with it
mw = FreeCADGui.getMainWindow()
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
cqCodePane = Shared.getActiveCodePane()
#Clear the old render before re-rendering
clearActiveDocument()
Shared.clearActiveDocument()
#Save our code to a tempfile and render it
tempFile = tempfile.NamedTemporaryFile(delete=False)
tempFile.write(cqCodePane.toPlainText().encode('utf-8'))
tempFile.close()
#mdi = mw.findChild(QtGui.QMdiArea)
#docname = mdi.currentSubWindow().getWindowTitle()
docname = os.path.splitext(os.path.basename(cqCodePane.file.path))[0]
# Make sure we replace any troublesome characters
@ -276,8 +268,7 @@ class CadQuerySaveScript:
def Activated(self):
#Grab our code editor so we can interact with it
mw = FreeCADGui.getMainWindow()
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
cqCodePane = Shared.getActiveCodePane()
#If the code pane doesn't have a filename, we need to present the save as dialog
if len(cqCodePane.file.path) == 0 or os.path.basename(cqCodePane.file.path) == 'script_template.py' \

View File

@ -1,8 +1,9 @@
"""Adds the ability to save a script file to the CadQuery module"""
# (c) 2014 Jeremy Wright LGPL v3
# (c) 2014-2016 Jeremy Wright Apache 2.0 License
import FreeCAD, FreeCADGui
from PySide import QtGui
import Shared
def export(self, filename):
save(filename)
@ -14,8 +15,7 @@ def save(filename=None):
"""
#Grab our code editor so we can interact with it
mw = FreeCADGui.getMainWindow()
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
cqCodePane = Shared.getActiveCodePane()
#If we weren't provided a file name, we need to find it from the text field
if filename is None:

View File

@ -1,6 +1,5 @@
"""Adds the ability to open files from disk to the CadQuery FreeCAD module"""
# (c) 2014 Jeremy Wright LGPL v3
# (c) 2014-2016 Jeremy Wright Apache 2.0 License
import os
import sys
import FreeCAD, FreeCADGui
@ -59,40 +58,39 @@ def open(filename):
#Getting the main window will allow us to find the children we need to work with
mw = FreeCADGui.getMainWindow()
# The code editor can be displayed as a docked window or as a FreeCAD tab
if Settings.tabbed_mode:
# Set up the text area for our CQ code
server_path = os.path.join(module_base_path, 'cq_server.py')
# Grab just the file name from the path/file that's being executed
# docname = os.path.splitext(os.path.basename(filename))[0]
docname = os.path.basename(filename)
# Windows needs some extra help with paths
if sys.platform.startswith('win'):
codePane = PyCodeEdit(server_script=server_path, interpreter=interpreter
, args=['-s', fc_lib_path, libs_dir_path])
else:
codePane = PyCodeEdit(server_script=server_path, interpreter=interpreter
, args=['-s', libs_dir_path])
# Set up the text area for our CQ code
server_path = os.path.join(module_base_path, 'cq_server.py')
# Allow easy use of an external editor
if Settings.use_external_editor:
codePane.modes.append(FileWatcherMode())
codePane.modes.get(FileWatcherMode).file_reloaded.connect(AutoExecute)
codePane.modes.get(FileWatcherMode).auto_reload = True
# Set the margin to be at 119 characters instead of 79
codePane.modes.get(RightMarginMode).position = Settings.max_line_length
codePane.setObjectName("cqCodePane")
mdi = mw.findChild(QtGui.QMdiArea)
# add a widget to the mdi area
sub = mdi.addSubWindow(codePane)
sub.setWindowTitle('script_template')
sub.setWindowIcon(QtGui.QIcon(':/icons/applications-python.svg'))
sub.show()
mw.update()
# Windows needs some extra help with paths
if sys.platform.startswith('win'):
codePane = PyCodeEdit(server_script=server_path, interpreter=interpreter
, args=['-s', fc_lib_path, libs_dir_path])
else:
# We need this so we can load the file into it
codePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
codePane = PyCodeEdit(server_script=server_path, interpreter=interpreter
, args=['-s', libs_dir_path])
# Allow easy use of an external editor
if Settings.use_external_editor:
codePane.modes.append(FileWatcherMode())
codePane.modes.get(FileWatcherMode).file_reloaded.connect(AutoExecute)
codePane.modes.get(FileWatcherMode).auto_reload = True
# Set the margin to be at 119 characters instead of 79
codePane.modes.get(RightMarginMode).position = Settings.max_line_length
codePane.setObjectName("cqCodePane_" + os.path.splitext(os.path.basename(filename))[0])
mdi = mw.findChild(QtGui.QMdiArea)
# add a widget to the mdi area
sub = mdi.addSubWindow(codePane)
sub.setWindowTitle(docname)
sub.setWindowIcon(QtGui.QIcon(':/icons/applications-python.svg'))
sub.show()
mw.update()
#Pull the text of the CQ script file into our code pane
codePane.file.open(filename)

View File

@ -1,3 +1,5 @@
# (c) 2014-2016 Jeremy Wright Apache 2.0 License
def show(cqObject, rgba=(204, 204, 204, 0.0)):
import FreeCAD
from random import random

View File

@ -1,5 +1,5 @@
"""FreeCAD init script of the CadQuery module"""
# (c) 2014 Jeremy Wright LGPL v3
# (c) 2014-2016 Jeremy Wright Apache 2.0 License
#TODO: The FreeCAD devs like to put as much init code as possible in here so that the module can be used without the
#TODO: GUI if desired

View File

@ -1,12 +1,10 @@
"""CadQuery GUI init module for FreeCAD
This adds a workbench with a scripting editor to FreeCAD's GUI."""
# (c) 2014-2015 Jeremy Wright LGPL v3
# (c) 2014-2016 Jeremy Wright Apache 2.0 License
import FreeCAD, FreeCADGui
from Gui.Command import *
import CadQuery_rc
class CadQueryWorkbench (Workbench):
"""CadQuery workbench for FreeCAD"""
MenuText = "CadQuery"
@ -118,18 +116,18 @@ class CadQueryWorkbench (Workbench):
# #Put the UI back the way we found it
# FreeCAD.Console.PrintMessage(msg)
#Getting the main window will allow us to start setting things up the way we want
mw = FreeCADGui.getMainWindow()
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
cqCodePane.close()
cqCodePane.setParent(None)
dockWidgets = mw.findChildren(QtGui.QDockWidget)
for widget in dockWidgets:
if widget.objectName() == "cqCodeView":
mw.removeDockWidget(widget)
# # Getting the main window will allow us to start setting things up the way we want
# mw = FreeCADGui.getMainWindow()
#
# cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
# cqCodePane.close()
# cqCodePane.setParent(None)
#
# dockWidgets = mw.findChildren(QtGui.QDockWidget)
#
# for widget in dockWidgets:
# if widget.objectName() == "cqCodeView":
# mw.removeDockWidget(widget)
@staticmethod
def ListExamples():

View File

@ -135,7 +135,7 @@ class _ResultMixinBytes(object):
class _NetlocResultMixinBase(object):
"""Shared methods for the parsed result objects containing a netloc element"""
"""Shared.py methods for the parsed result objects containing a netloc element"""
__slots__ = ()
@property

View File

@ -3734,7 +3734,7 @@ MODULES = {'.NET': ('dotnet_load',),
'session_pgsql_reset',
'session_pgsql_set_field',
'session_pgsql_status'),
'Shared Memory': ('shmop_close',
'Shared.py Memory': ('shmop_close',
'shmop_delete',
'shmop_open',
'shmop_read',

View File

@ -408,7 +408,7 @@ class VbNetLexer(RegexLexer):
r'Operator|Option|Optional|Overloads|Overridable|'
r'Overrides|ParamArray|Partial|Private|Protected|'
r'Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|'
r'Return|Select|Set|Shadows|Shared|Single|'
r'Return|Select|Set|Shadows|Shared.py|Single|'
r'Static|Step|Stop|SyncLock|Then|'
r'Throw|To|True|Try|TryCast|Wend|'
r'Using|When|While|Widening|With|WithEvents|'

View File

@ -1,4 +1,3 @@
execute_on_save = False # Automatically execute a script every time you save
use_external_editor = False # Automatically reloads and executes a file when an external change is made
max_line_length = 79 # The number of characters per line that is allowed before a warning is given
tabbed_mode = True # Whether or not the editor should make use of FreeCAD tabs
max_line_length = 79 # The number of characters per line that is allowed before a warning is given

32
CadQuery/Shared.py Normal file
View File

@ -0,0 +1,32 @@
import FreeCAD
import FreeCADGui
from PySide import QtGui
def clearActiveDocument():
"""Clears the currently active 3D view so that we can re-render"""
# Grab our code editor so we can interact with it
mw = FreeCADGui.getMainWindow()
mdi = mw.findChild(QtGui.QMdiArea)
winName = mdi.currentSubWindow().windowTitle().split('.')[0]
try:
doc = FreeCAD.getDocument(winName)
# Make sure we have an active document to work with
if doc is not None:
for obj in doc.Objects:
doc.removeObject(obj.Name)
except:
pass
def getActiveCodePane():
# Grab our code editor so we can interact with it
mw = FreeCADGui.getMainWindow()
mdi = mw.findChild(QtGui.QMdiArea)
winName = mdi.currentSubWindow().windowTitle().split('.')[0]
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane_" + winName)
return cqCodePane

View File

@ -1,6 +1,6 @@
__author__ = "Jeremy Wright (jmwright)"
__copyright__ = "Copyright 2015"
__copyright__ = "Copyright 2014-2016"
__license__ = "LGPL v3"
__version__ = "0.3.0"
__version__ = "0.5.2"
__maintainer__ = "Jeremy Wright"
__status__ = "Production/Stable"

View File

@ -1,3 +1,4 @@
# (c) 2014-2016 Jeremy Wright Apache 2.0 License
import os, sys
def we_are_frozen():