Skip to content

Commit

Permalink
[Python console] add Execute in console context menu item (FreeCAD#18716
Browse files Browse the repository at this point in the history
)

* [Python console] add Execute in console context menu item

* Update src/Gui/PythonEditor.cpp

Co-authored-by: Kacper Donat <[email protected]>

---------

Co-authored-by: Chris Hennes <[email protected]>
Co-authored-by: Kacper Donat <[email protected]>
  • Loading branch information
3 people authored Jan 19, 2025
1 parent f381277 commit 49b304a
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
73 changes: 73 additions & 0 deletions src/Gui/PythonEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@
# include <QContextMenuEvent>
# include <QMenu>
# include <QPainter>
# include <QRegularExpression>
# include <QShortcut>
# include <QTextCursor>
#endif

#include <Base/Parameter.h>
#include <Gui/Command.h>

#include "PythonEditor.h"
#include "Application.h"
Expand Down Expand Up @@ -77,8 +79,12 @@ PythonEditor::PythonEditor(QWidget* parent)
auto uncomment = new QShortcut(this);
uncomment->setKey(QKeySequence(QString::fromLatin1("ALT+U")));

auto execInConsole = new QShortcut(this);
execInConsole->setKey(QKeySequence(QString::fromLatin1("ALT+SHIFT+P")));

connect(comment, &QShortcut::activated, this, &PythonEditor::onComment);
connect(uncomment, &QShortcut::activated, this, &PythonEditor::onUncomment);
connect(execInConsole, &QShortcut::activated, this, &PythonEditor::onExecuteInConsole);
}

/** Destroys the object and frees any allocated resources */
Expand Down Expand Up @@ -172,6 +178,9 @@ void PythonEditor::contextMenuEvent ( QContextMenuEvent * e )
comment->setShortcut(QKeySequence(QString::fromLatin1("ALT+C")));
QAction* uncomment = menu->addAction( tr("Uncomment"), this, &PythonEditor::onUncomment);
uncomment->setShortcut(QKeySequence(QString::fromLatin1("ALT+U")));
QAction* execInConsole = menu->addAction( tr("Execute in console"),
this, &PythonEditor::onExecuteInConsole);
execInConsole->setShortcut(QKeySequence(QString::fromLatin1("ALT+Shift+P")));
}

menu->exec(e->globalPos());
Expand Down Expand Up @@ -275,6 +284,70 @@ void PythonEditor::onUncomment()
cursor.endEditBlock();
}

void PythonEditor::onExecuteInConsole()
{
QTextCursor cursor = textCursor();
int selStart = cursor.selectionStart();
int selEnd = cursor.selectionEnd();
QTextBlock block;
QString selectedCode;

for (block = document()->begin(); block.isValid(); block = block.next()) {
int pos = block.position();
int off = block.length() - 1;
if (pos >= selStart || pos + off >= selStart) {
if (pos + 1 > selEnd) {
break;
}

QString lineText = block.text();
selectedCode.append(lineText + QLatin1String("\n"));
}
}

if (!selectedCode.isEmpty()) {

/** Dedent the block of code so that the first selected
* line has no indentation, but the remaining lines
* keep their indentation relative to that first line.
*/

// get the leading whitespace of the first line
QStringList lines = selectedCode.split(QLatin1Char('\n'));
QString firstLineIndent;
for (const QString& line : lines) {
if (!line.isEmpty()) {
int leadingWhitespace = line.indexOf(QRegularExpression(QLatin1String("\\S")));
if (leadingWhitespace > 0) {
firstLineIndent = line.left(leadingWhitespace);
}
break;
}
}

// remove that first line whitespace from all the lines
for (QString& line : lines) {
if (!line.isEmpty() && line.startsWith(firstLineIndent)) {
line.remove(0, firstLineIndent.length());
}
}

// join the lines into a single QString so we can execute as a single block
QString dedentedCode = lines.join(QLatin1Char('\n'));

if (!dedentedCode.isEmpty()) {
try {
Gui::Command::doCommand(Gui::Command::Doc, dedentedCode.toStdString().c_str());
} catch (const Base::Exception& e) {
QString errorMessage = QString::fromStdString(e.what());
Base::Console().Error("Error executing Python code:\n%s\n", errorMessage.toUtf8().constData());
} catch (...) {
Base::Console().Error("An unknown error occurred while executing Python code.\n");
}
}
}
}

// ------------------------------------------------------------------------

namespace Gui {
Expand Down
1 change: 1 addition & 0 deletions src/Gui/PythonEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public Q_SLOTS:
* this line is skipped.
*/
void onUncomment();
void onExecuteInConsole();
void setFileName(const QString&);
void startDebug();

Expand Down

0 comments on commit 49b304a

Please sign in to comment.