From cb1221da2c87511eb93b1c9bab04eae4e0ecec3f Mon Sep 17 00:00:00 2001 From: Jeremy Mack Wright Date: Mon, 3 Oct 2016 21:38:44 -0400 Subject: [PATCH] Fixed the majority of the functionality to where scripts can now be opened, saved, and executed in a multi-window environment. --- CadQuery/Gui/Command.py | 27 +++----- CadQuery/Gui/ExportCQ.py | 6 +- CadQuery/Gui/ImportCQ.py | 64 +++++++++---------- CadQuery/Helpers.py | 2 + CadQuery/Init.py | 2 +- CadQuery/InitGui.py | 28 ++++---- .../Libs/future/backports/urllib/parse.py | 2 +- .../Libs/pygments/lexers/_php_builtins.py | 2 +- CadQuery/Libs/pygments/lexers/dotnet.py | 2 +- CadQuery/Settings.py | 3 +- CadQuery/Shared.py | 32 ++++++++++ CadQuery/__init__.py | 4 +- CadQuery/module_locator.py | 1 + 13 files changed, 98 insertions(+), 77 deletions(-) create mode 100644 CadQuery/Shared.py diff --git a/CadQuery/Gui/Command.py b/CadQuery/Gui/Command.py index 1e7f716..77c934d 100644 --- a/CadQuery/Gui/Command.py +++ b/CadQuery/Gui/Command.py @@ -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' \ diff --git a/CadQuery/Gui/ExportCQ.py b/CadQuery/Gui/ExportCQ.py index f69e80e..cba98f8 100644 --- a/CadQuery/Gui/ExportCQ.py +++ b/CadQuery/Gui/ExportCQ.py @@ -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: diff --git a/CadQuery/Gui/ImportCQ.py b/CadQuery/Gui/ImportCQ.py index f960528..0ef5f0d 100644 --- a/CadQuery/Gui/ImportCQ.py +++ b/CadQuery/Gui/ImportCQ.py @@ -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) diff --git a/CadQuery/Helpers.py b/CadQuery/Helpers.py index 3801fa4..fd6c3c3 100644 --- a/CadQuery/Helpers.py +++ b/CadQuery/Helpers.py @@ -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 diff --git a/CadQuery/Init.py b/CadQuery/Init.py index 4c40b42..301b3da 100644 --- a/CadQuery/Init.py +++ b/CadQuery/Init.py @@ -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 \ No newline at end of file diff --git a/CadQuery/InitGui.py b/CadQuery/InitGui.py index ec2fc1c..ee873a1 100644 --- a/CadQuery/InitGui.py +++ b/CadQuery/InitGui.py @@ -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(): diff --git a/CadQuery/Libs/future/backports/urllib/parse.py b/CadQuery/Libs/future/backports/urllib/parse.py index ada2f8b..c55debb 100644 --- a/CadQuery/Libs/future/backports/urllib/parse.py +++ b/CadQuery/Libs/future/backports/urllib/parse.py @@ -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 diff --git a/CadQuery/Libs/pygments/lexers/_php_builtins.py b/CadQuery/Libs/pygments/lexers/_php_builtins.py index 51b55de..ec2c592 100644 --- a/CadQuery/Libs/pygments/lexers/_php_builtins.py +++ b/CadQuery/Libs/pygments/lexers/_php_builtins.py @@ -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', diff --git a/CadQuery/Libs/pygments/lexers/dotnet.py b/CadQuery/Libs/pygments/lexers/dotnet.py index afdb778..7b13b14 100644 --- a/CadQuery/Libs/pygments/lexers/dotnet.py +++ b/CadQuery/Libs/pygments/lexers/dotnet.py @@ -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|' diff --git a/CadQuery/Settings.py b/CadQuery/Settings.py index aef8290..200a424 100644 --- a/CadQuery/Settings.py +++ b/CadQuery/Settings.py @@ -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 \ No newline at end of file +max_line_length = 79 # The number of characters per line that is allowed before a warning is given \ No newline at end of file diff --git a/CadQuery/Shared.py b/CadQuery/Shared.py new file mode 100644 index 0000000..a68c343 --- /dev/null +++ b/CadQuery/Shared.py @@ -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 \ No newline at end of file diff --git a/CadQuery/__init__.py b/CadQuery/__init__.py index dfeb68d..4b10038 100644 --- a/CadQuery/__init__.py +++ b/CadQuery/__init__.py @@ -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" diff --git a/CadQuery/module_locator.py b/CadQuery/module_locator.py index daaf3e2..6f75a11 100644 --- a/CadQuery/module_locator.py +++ b/CadQuery/module_locator.py @@ -1,3 +1,4 @@ +# (c) 2014-2016 Jeremy Wright Apache 2.0 License import os, sys def we_are_frozen():