diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 51decf4a19..0cef567087 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1369,3 +1369,23 @@ else(WIN32) INSTALL(FILES Icons/freecad.xpm DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps) INSTALL(FILES Icons/freecad-doc.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/mimetypes RENAME application-x-extension-fcstd.svg) endif(WIN32) + +set(FreeCADGui_Scripts + RemoteDebugger.ui + RemoteDebugger.py +) + +add_custom_target(FreeCADGui_Resources ALL + SOURCES ${FreeCADGui_Scripts} +) + +fc_copy_sources(FreeCADGui_Resources + ${CMAKE_BINARY_DIR}/Ext/freecad/gui + ${FreeCADGui_Scripts}) + +INSTALL( + FILES + ${FreeCADGui_Scripts} + DESTINATION + Ext/freecad/gui +) diff --git a/src/Gui/CommandMacro.cpp b/src/Gui/CommandMacro.cpp index dedf279898..5a38fb0ce7 100644 --- a/src/Gui/CommandMacro.cpp +++ b/src/Gui/CommandMacro.cpp @@ -151,6 +151,31 @@ bool StdCmdDlgMacroExecuteDirect::isActive(void) return getGuiApplication()->sendHasMsgToActiveView("Run"); } +DEF_STD_CMD_A(StdCmdMacroAttachDebugger) + +StdCmdMacroAttachDebugger::StdCmdMacroAttachDebugger() + : Command("Std_MacroAttachDebugger") +{ + sGroup = QT_TR_NOOP("Macro"); + sMenuText = QT_TR_NOOP("Attach to remote debugger..."); + sToolTipText = QT_TR_NOOP("Attach to a remotely running debugger"); + sWhatsThis = "Std_MacroAttachDebugger"; + sStatusTip = QT_TR_NOOP("Attach to a remotely running debugger"); + eType = 0; +} + +void StdCmdMacroAttachDebugger::activated(int iMsg) +{ + Q_UNUSED(iMsg); + doCommand(Gui, "from freecad.gui import RemoteDebugger\n" + "RemoteDebugger.attachToRemoteDebugger()"); +} + +bool StdCmdMacroAttachDebugger::isActive(void) +{ + return true; +} + DEF_STD_CMD_A(StdCmdMacroStartDebug) StdCmdMacroStartDebug::StdCmdMacroStartDebug() @@ -297,6 +322,7 @@ void CreateMacroCommands(void) rcCmdMgr.addCommand(new StdCmdMacroStopRecord()); rcCmdMgr.addCommand(new StdCmdDlgMacroExecute()); rcCmdMgr.addCommand(new StdCmdDlgMacroExecuteDirect()); + rcCmdMgr.addCommand(new StdCmdMacroAttachDebugger()); rcCmdMgr.addCommand(new StdCmdMacroStartDebug()); rcCmdMgr.addCommand(new StdCmdMacroStopDebug()); rcCmdMgr.addCommand(new StdCmdMacroStepOver()); diff --git a/src/Gui/RemoteDebugger.py b/src/Gui/RemoteDebugger.py new file mode 100644 index 0000000000..ba745b44c3 --- /dev/null +++ b/src/Gui/RemoteDebugger.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +#/****************************************************************************** +# * Copyright (c) 2020 Werner Mayer * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This library is free software; you can redistribute it and/or * +# * modify it under the terms of the GNU Library General Public * +# * License as published by the Free Software Foundation; either * +# * version 2 of the License, or (at your option) any later version. * +# * * +# * This library is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this library; see the file COPYING.LIB. If not, * +# * write to the Free Software Foundation, Inc., 59 Temple Place, * +# * Suite 330, Boston, MA 02111-1307, USA * +# * * +# ******************************************************************************/ + + +import FreeCAD as App +import FreeCADGui as Gui +from PySide import QtCore +from PySide import QtGui + +class RemoteDebugger(): + def __init__(self, parent=None): + ui = App.getHomePath() + "Ext/freecad/gui/RemoteDebugger.ui" + self.dialog = Gui.PySideUic.loadUi(ui) + self.dialog.buttonBox.accepted.connect(self.accept) + self.dialog.buttonBox.rejected.connect(self.reject) + + def accept(self): + try: + index = self.dialog.tabWidget.currentIndex() + + if index == 0: # winpdb + passwd = self.dialog.lineEditPassword.text() + + import rpdb2 + rpdb2.start_embedded_debugger(passwd, timeout = 30) + + elif index == 1: # VS code + address = self.dialog.lineEditAddress.text() + port = self.dialog.spinBoxPort.value() + redirect = self.dialog.checkRedirectOutput.isChecked() + + import ptvsd + ptvsd.enable_attach(address=(address, port), redirect_output=redirect) + ptvsd.wait_for_attach() + except Exception as e: + QtGui.QMessageBox.warning(self.dialog, "Failed to attach", str(e)) + + self.dialog.accept() + + def reject(self): + self.dialog.reject() + + def exec_(self): + self.dialog.exec_() + + +def attachToRemoteDebugger(): + dlg = RemoteDebugger(Gui.getMainWindow()) + dlg.exec_() diff --git a/src/Gui/RemoteDebugger.ui b/src/Gui/RemoteDebugger.ui new file mode 100644 index 0000000000..382eb04393 --- /dev/null +++ b/src/Gui/RemoteDebugger.ui @@ -0,0 +1,166 @@ + + + Gui::Dialog::RemoteDebugger + + + + 0 + 0 + 426 + 287 + + + + Attach to remote debugger + + + + + + 0 + + + + winpdb + + + + + + Password: + + + + + + + QLineEdit::Password + + + + + + + Qt::Vertical + + + + 20 + 155 + + + + + + + + + VS Code + + + + + + Address: + + + + + + + localhost + + + + + + + Port: + + + + + + + 65535 + + + 5678 + + + + + + + Redirect output + + + true + + + + + + + Qt::Vertical + + + + 20 + 94 + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + Gui::Dialog::RemoteDebugger + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Gui::Dialog::RemoteDebugger + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp index 2a778b9d6a..18348d2750 100644 --- a/src/Gui/Workbench.cpp +++ b/src/Gui/Workbench.cpp @@ -611,9 +611,16 @@ MenuItem* StdWorkbench::setupMenuBar() const // Macro MenuItem* macro = new MenuItem( menuBar ); macro->setCommand("&Macro"); - *macro << "Std_DlgMacroRecord" << "Std_MacroStopRecord" << "Std_DlgMacroExecute" - << "Separator" << "Std_DlgMacroExecuteDirect" << "Std_MacroStartDebug" - << "Std_MacroStopDebug" << "Std_MacroStepOver" << "Std_MacroStepInto" + *macro << "Std_DlgMacroRecord" + << "Std_MacroStopRecord" + << "Std_DlgMacroExecute" + << "Separator" + << "Std_DlgMacroExecuteDirect" + << "Std_MacroAttachDebugger" + << "Std_MacroStartDebug" + << "Std_MacroStopDebug" + << "Std_MacroStepOver" + << "Std_MacroStepInto" << "Std_ToggleBreakpoint"; // Windows