# # # Python Assistant Window # v 0.1 initial release # # #*********************************************************************************** # # provide a text editing window with functions to aid in coding Python within FreeCAD # ############ To Do ############ # - contextual window doesn't fire if cursor is on last position in file # - executing "from PySide import QtGui, QtCore" on console seems to close window # - is it possible to copy code to console and then select and execute it? ############################## #*********************************************************************************** # The next three variables define the width and height and vertical positioning # of the Python Assistant Window # 'pawWidthPercent' specifies the percentage of the screen width to be assigned to the Python Assistant Window # 'pawHeightPercent' specifies the percentage of the screen height to be assigned to the Python Assistant Window # 'pawAtBottomFlag' specifies if the Python Assistant Window is at the top or the bottom # The Python Assistant Window is automatically placed at the left, # so pawWidthPercent = 26, pawHeightPercent = 41, pawAtBottomFlag = False will cause the # following: # 1) the main FreeCAD window will be placed in the upper left corner of the screen, # it's height will be 100% of the screen height, # it's width will be 74% (=100%-26%) of the screen # 2) the Python Assistant Window will be placed in the left side of the screen, # it's height will be 41% of the screen height, # it's width will be 26% of the screen # it will be at the top (leaving empty space below it) # The empty space (either above or below the Python Assistant Window), # is left for the text editor (for editing the Macros) to be placed in. # pawWidthPercentInitial = 37.5 # percent of the screen width pawHeightPercentInitial = 32.0 # percent of the screen height pawAtBottomFlagInitial = True #*********************************************************************************** # import statements import sys, operator, os from os.path import expanduser from PySide import QtGui, QtCore # UI Class definitions class PythonAssistantWindow(QtGui.QMainWindow): """""" def __init__(self, pythonTextToEdit): self.textIn = pythonTextToEdit super(PythonAssistantWindow, self).__init__() self.initUI(pythonTextToEdit) def initUI(self, pythonTextToEdit): """Constructor""" # set default return value and pointer to subsequent child window self.result = userCancelled self.childWindow = None self.alertWindow = None # set window dimensions for Python Advisor Window from the constants at the top of Macro file self.pawWinWidth = pawWidthPercentInitial/100.0 * availableWidth self.pawWinHeight = pawHeightPercentInitial/100.0 * availableHeight self.left = screenWidth - self.pawWinWidth if pawAtBottomFlagInitial: self.top = screenHeight - self.pawWinHeight else: self.top = 0 self.editorHeight = self.pawWinHeight # set dimensions for main FreeCAD window self.mainWinWidth = availableWidth - (self.pawWinWidth+interWindowGap) self.mainWinHeight = availableHeight # define main window FreeCADGui.getMainWindow().setGeometry(0, 0, self.mainWinWidth, self.mainWinHeight) # now set up this window self.setGeometry(self.left, self.top, self.pawWinWidth, self.pawWinHeight) self.setWindowTitle("Python Assistant Window") # centralWidget = QtGui.QWidget(self) layout = QtGui.QGridLayout() centralWidget.setLayout(layout) # set up text editing widget self.text_editor = QtGui.QPlainTextEdit(self) self.text_editor.move(0,0) self.text_editor.resize(self.pawWinWidth,self.editorHeight) self.text_editor.appendPlainText(self.textIn) self.text_editor.setSizePolicy(QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding) self.text_editor.textChanged.connect(self.onTextChanged) # set up a monospace font for the text editor to match the Python console font = QtGui.QFont() font.setFamily("Courier") font.setStyleHint(QtGui.QFont.Monospace) font.setFixedPitch(True) font.setPointSize(12) self.text_editor.setFont(font) #self.text_editor.cursorPositionChanged.connect(self.onCursorPosition) self.cursor = self.text_editor.textCursor() # populate layout layout.addWidget(self.text_editor,0,0) self.setCentralWidget(centralWidget) # set contextual menu options for text editing widget # menu dividers mnuDivider1 = QtGui.QAction(self) mnuDivider1.setText(menuDividerText) mnuDivider1.triggered.connect(self.onMenuDivider) mnuDivider2 = QtGui.QAction(self) mnuDivider2.setText(menuDividerText) mnuDivider2.triggered.connect(self.onMenuDivider) mnuDivider3 = QtGui.QAction(self) mnuDivider3.setText(menuDividerText) mnuDivider3.triggered.connect(self.onMenuDivider) mnuDivider4 = QtGui.QAction(self) mnuDivider4.setText(menuDividerText) mnuDivider4.triggered.connect(self.onMenuDivider) # clear text mnuClear = QtGui.QAction(self) mnuClear.setText("Clear") mnuClear.triggered.connect(self.onClear) # paste copy/paste buffer mnuPaste = QtGui.QAction(self) mnuPaste.setText("Paste") mnuPaste.triggered.connect(self.onPaste) # paste contents of console mnuAppendFromConsole = QtGui.QAction(self) mnuAppendFromConsole.setText("Append contents of console") mnuAppendFromConsole.triggered.connect(self.onAppendFromConsole) # select between markers mnuSelectMarkers = QtGui.QAction(self) mnuSelectMarkers.setText("Select between markers") mnuSelectMarkers.triggered.connect(self.onSelectMarkers) # select all mnuSelectAll = QtGui.QAction(self) mnuSelectAll.setText("Select all") mnuSelectAll.triggered.connect(self.onSelectAll) # insert marker mnuInsertMarker = QtGui.QAction(self) mnuInsertMarker.setText("Insert marker") mnuInsertMarker.triggered.connect(self.onInsertMarker) # remove console generated ">>> " character strings mnuStripPrefix = QtGui.QAction(self) mnuStripPrefix.setText("Remove '>>> '") mnuStripPrefix.triggered.connect(self.onStripPrefix) # remove blank lines mnuReduceBlankLines = QtGui.QAction(self) mnuReduceBlankLines.setText("Delete multiple blank lines") mnuReduceBlankLines.triggered.connect(self.onReduceBlankLines) # copy selection mnuCopy = QtGui.QAction(self) mnuCopy.setText("Copy") mnuCopy.triggered.connect(self.onCopy) # copy selection to console mnuCopySelectionToConsole = QtGui.QAction(self) mnuCopySelectionToConsole.setText("Copy selection to console") mnuCopySelectionToConsole.triggered.connect(self.onCopySelectionToConsole) # copy to console mnuCopyToConsole = QtGui.QAction(self) mnuCopyToConsole.setText("Copy contents to console") mnuCopyToConsole.triggered.connect(self.onCopyToConsole) # save as file mnuSaveAsFile = QtGui.QAction(self) mnuSaveAsFile.setText("Save contents to file") mnuSaveAsFile.triggered.connect(self.onSaveAsFile) # close window mnuCloseWindow = QtGui.QAction(self) mnuCloseWindow.setText("Close window") mnuCloseWindow.triggered.connect(self.onCloseWindow) # alter GUI settings mnuSettings = QtGui.QAction(self) mnuSettings.setText("=Alter GUI settings=") mnuSettings.triggered.connect(self.onSettings) # define menu and add options self.text_editor.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) self.text_editor.addAction(mnuCopy) self.text_editor.addAction(mnuCopySelectionToConsole) self.text_editor.addAction(mnuCopyToConsole) self.text_editor.addAction(mnuDivider1) self.text_editor.addAction(mnuPaste) self.text_editor.addAction(mnuAppendFromConsole) self.text_editor.addAction(mnuSelectMarkers) self.text_editor.addAction(mnuSelectAll) self.text_editor.addAction(mnuClear) self.text_editor.addAction(mnuDivider2) self.text_editor.addAction(mnuInsertMarker) self.text_editor.addAction(mnuStripPrefix) self.text_editor.addAction(mnuReduceBlankLines) self.text_editor.addAction(mnuDivider3) self.text_editor.addAction(mnuSaveAsFile) self.text_editor.addAction(mnuSettings) self.text_editor.addAction(mnuCloseWindow) # self.show() #---------------------------------------------------------------------- def onMenuDivider(self): # just a divider in the menu so we don't do anything pass def onClear(self): # clear editing field self.text_editor.clear() def onPaste(self): # paste contents of system copy/paste buffer into QPlainTextEdit field self.text_editor.paste() def onAppendFromConsole(self): # copy text from "Python console" mainWindow = FreeCADGui.getMainWindow() pcDW = mainWindow.findChild(QtGui.QDockWidget, "Python console") pcPTE = pcDW.findChild(QtGui.QPlainTextEdit, "Python console") consoleStr = pcPTE.document().toPlainText() self.text_editor.appendPlainText(copyFromConsoleText) self.text_editor.appendPlainText("") self.text_editor.appendPlainText(consoleStr) def onCopy(self): # copy selected text to system copy/paste buffer self.text_editor.copy() def onCopySelectionToConsole(self): # copy selected text to "Python console" mainWindow = FreeCADGui.getMainWindow() pcDW = mainWindow.findChild(QtGui.QDockWidget, "Python console") pcPTE = pcDW.findChild(QtGui.QPlainTextEdit, "Python console") # cursor = self.text_editor.textCursor() cursorText = self.text_editor.toPlainText() textToCopy = cursorText[cursor.selectionStart():cursor.selectionEnd()] if len(textToCopy)>0: pcPTE.appendPlainText(textToCopy) def onCopyToConsole(self): # copy text to "Python console" mainWindow = FreeCADGui.getMainWindow() pcDW = mainWindow.findChild(QtGui.QDockWidget, "Python console") pcPTE = pcDW.findChild(QtGui.QPlainTextEdit, "Python console") pcPTE.appendPlainText(copyToConsoleText) pcPTE.appendPlainText() def onInsertMarker(self): # insert marker self.text_editor.insertPlainText(markerText) def onStripPrefix(self): # strip out ">>> " from text edit window self.text_editor.selectAll() if len(self.text_editor.toPlainText())>0: self.text_editor.selectAll() tmp = self.text_editor.toPlainText() self.text_editor.clear() self.text_editor.appendPlainText(tmp.replace(">>> ","")) def onReduceBlankLines(self): # reduce multiple blank lines to single blank lines contents = self.text_editor.toPlainText() self.text_editor.clear() self.text_editor.appendPlainText(os.linesep.join([s for s in contents.splitlines() if s])) def onSelectMarkers(self): cursor = self.text_editor.textCursor() cursorText = self.text_editor.toPlainText() bNum = cursor.blockNumber(); cNum = cursor.columnNumber() pos = cursor.position(); cursorTextLength = len(cursorText) occurrences = [i for i in range(len(cursorText)) if cursorText.startswith(markerText, i)] if len(occurrences)==0: self.alertWindow = QtGui.QMessageBox() self.alertWindow.setText("There are no markers...") self.alertWindow.show() elif len(occurrences)==1: hdrStart = occurrences[0] hdrEnd = hdrStart + markerTextLength if poshdrEnd: selectStart = hdrEnd; selectEnd = cursorTextLength self.cursor.setPosition(selectStart) self.cursor.setPosition(selectEnd, QtGui.QTextCursor.KeepAnchor) self.text_editor.setTextCursor(self.cursor) else: startOccurrences = list(); endOccurrences = list(occurrences) for i in range(len(occurrences)): startOccurrences.append(occurrences[i] + markerTextLength + 1) startOccurrences.insert( 0, 0) endOccurrences.insert( len(occurrences), cursorTextLength) for i in range(len(occurrences)+1): if startOccurrences[i]