mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 17:40:39 +00:00
Add python shell qt window
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
#include "Windows/MainWindow.h"
|
||||
#include "Windows/PipelineState/PipelineStateViewer.h"
|
||||
#include "Windows/PixelHistoryView.h"
|
||||
#include "Windows/PythonShell.h"
|
||||
#include "Windows/ShaderViewer.h"
|
||||
#include "Windows/StatisticsViewer.h"
|
||||
#include "Windows/TextureViewer.h"
|
||||
@@ -732,6 +733,18 @@ IStatisticsViewer *CaptureContext::GetStatisticsViewer()
|
||||
return m_StatisticsViewer;
|
||||
}
|
||||
|
||||
IPythonShell *CaptureContext::GetPythonShell()
|
||||
{
|
||||
if(m_PythonShell)
|
||||
return m_PythonShell;
|
||||
|
||||
m_PythonShell = new PythonShell(*this, m_MainWindow);
|
||||
m_PythonShell->setObjectName("pythonShell");
|
||||
setupDockWindow(m_PythonShell);
|
||||
|
||||
return m_PythonShell;
|
||||
}
|
||||
|
||||
void CaptureContext::ShowEventBrowser()
|
||||
{
|
||||
m_MainWindow->showEventBrowser();
|
||||
@@ -772,6 +785,11 @@ void CaptureContext::ShowStatisticsViewer()
|
||||
m_MainWindow->showStatisticsViewer();
|
||||
}
|
||||
|
||||
void CaptureContext::ShowPythonShell()
|
||||
{
|
||||
m_MainWindow->showPythonShell();
|
||||
}
|
||||
|
||||
IShaderViewer *CaptureContext::EditShader(bool customShader, const QString &entryPoint,
|
||||
const QStringMap &files,
|
||||
IShaderViewer::SaveCallback saveCallback,
|
||||
@@ -865,6 +883,10 @@ QWidget *CaptureContext::CreateBuiltinWindow(const QString &objectName)
|
||||
{
|
||||
return GetStatisticsViewer()->Widget();
|
||||
}
|
||||
else if(objectName == "pythonShell")
|
||||
{
|
||||
return GetPythonShell()->Widget();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -887,6 +909,8 @@ void CaptureContext::BuiltinWindowClosed(QWidget *window)
|
||||
m_DebugMessageView = NULL;
|
||||
else if(m_StatisticsViewer && m_StatisticsViewer->Widget() == window)
|
||||
m_StatisticsViewer = NULL;
|
||||
else if(m_PythonShell && m_PythonShell->Widget() == window)
|
||||
m_PythonShell = NULL;
|
||||
else
|
||||
qCritical() << "Unrecognised window being closed: " << window;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ class TextureViewer;
|
||||
class CaptureDialog;
|
||||
class DebugMessageView;
|
||||
class StatisticsViewer;
|
||||
class PythonShell;
|
||||
|
||||
QString ConfigFilePath(const QString &filename);
|
||||
|
||||
@@ -128,6 +129,7 @@ public:
|
||||
ICaptureDialog *GetCaptureDialog() override;
|
||||
IDebugMessageView *GetDebugMessageView() override;
|
||||
IStatisticsViewer *GetStatisticsViewer() override;
|
||||
IPythonShell *GetPythonShell() override;
|
||||
|
||||
bool HasEventBrowser() override { return m_EventBrowser != NULL; }
|
||||
bool HasAPIInspector() override { return m_APIInspector != NULL; }
|
||||
@@ -137,6 +139,7 @@ public:
|
||||
bool HasCaptureDialog() override { return m_CaptureDialog != NULL; }
|
||||
bool HasDebugMessageView() override { return m_DebugMessageView != NULL; }
|
||||
bool HasStatisticsViewer() override { return m_StatisticsViewer != NULL; }
|
||||
bool HasPythonShell() override { return m_PythonShell != NULL; }
|
||||
void ShowEventBrowser() override;
|
||||
void ShowAPIInspector() override;
|
||||
void ShowTextureViewer() override;
|
||||
@@ -145,6 +148,7 @@ public:
|
||||
void ShowCaptureDialog() override;
|
||||
void ShowDebugMessageView() override;
|
||||
void ShowStatisticsViewer() override;
|
||||
void ShowPythonShell() override;
|
||||
|
||||
IShaderViewer *EditShader(bool customShader, const QString &entryPoint, const QStringMap &files,
|
||||
IShaderViewer::SaveCallback saveCallback,
|
||||
@@ -265,4 +269,5 @@ private:
|
||||
CaptureDialog *m_CaptureDialog = NULL;
|
||||
DebugMessageView *m_DebugMessageView = NULL;
|
||||
StatisticsViewer *m_StatisticsViewer = NULL;
|
||||
PythonShell *m_PythonShell = NULL;
|
||||
};
|
||||
|
||||
@@ -318,6 +318,21 @@ protected:
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(IStatisticsViewer);
|
||||
|
||||
DOCUMENT("The interactive python shell.");
|
||||
struct IPythonShell
|
||||
{
|
||||
DOCUMENT(
|
||||
"Retrieves the QWidget for this :class:`PythonShell` if PySide2 is available, or "
|
||||
"``None``.");
|
||||
virtual QWidget *Widget() = 0;
|
||||
|
||||
protected:
|
||||
IPythonShell() = default;
|
||||
~IPythonShell() = default;
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(IPythonShell);
|
||||
|
||||
DOCUMENT(R"(A shader window used for viewing, editing, or debugging.
|
||||
|
||||
.. function:: SaveCallback(context, viewer, files)
|
||||
@@ -990,6 +1005,13 @@ as well as messages generated during replay and analysis.
|
||||
)");
|
||||
virtual IStatisticsViewer *GetStatisticsViewer() = 0;
|
||||
|
||||
DOCUMENT(R"(Retrieve the current singleton :class:`PythonShell`.
|
||||
|
||||
:return: The current window, which is created (but not shown) it there wasn't one open.
|
||||
:rtype: PythonShell
|
||||
)");
|
||||
virtual IPythonShell *GetPythonShell() = 0;
|
||||
|
||||
DOCUMENT(R"(Check if there is a current :class:`EventBrowser` open.
|
||||
|
||||
:return: ``True`` if there is a window open.
|
||||
@@ -1046,6 +1068,13 @@ as well as messages generated during replay and analysis.
|
||||
)");
|
||||
virtual bool HasStatisticsViewer() = 0;
|
||||
|
||||
DOCUMENT(R"(Check if there is a current :class:`PythonShell` open.
|
||||
|
||||
:return: ``True`` if there is a window open.
|
||||
:rtype: ``bool``
|
||||
)");
|
||||
virtual bool HasPythonShell() = 0;
|
||||
|
||||
DOCUMENT("Raise the current :class:`EventBrowser`, showing it in the default place if needed.");
|
||||
virtual void ShowEventBrowser() = 0;
|
||||
DOCUMENT("Raise the current :class:`APIInspector`, showing it in the default place if needed.");
|
||||
@@ -1064,6 +1093,8 @@ as well as messages generated during replay and analysis.
|
||||
DOCUMENT(
|
||||
"Raise the current :class:`StatisticsViewer`, showing it in the default place if needed.");
|
||||
virtual void ShowStatisticsViewer() = 0;
|
||||
DOCUMENT("Raise the current :class:`PythonShell`, showing it in the default place if needed.");
|
||||
virtual void ShowPythonShell() = 0;
|
||||
|
||||
DOCUMENT(R"(Show a new :class:`ShaderViewer` window, showing an editable view of a given shader.
|
||||
|
||||
|
||||
@@ -424,6 +424,11 @@ void PythonContext::GlobalShutdown()
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
QString PythonContext::versionString()
|
||||
{
|
||||
return QString("%1.%2.%3").arg(PY_MAJOR_VERSION).arg(PY_MINOR_VERSION).arg(PY_MICRO_VERSION);
|
||||
}
|
||||
|
||||
void PythonContext::executeString(const QString &filename, const QString &source, bool interactive)
|
||||
{
|
||||
if(!initialised())
|
||||
|
||||
@@ -55,6 +55,8 @@ public:
|
||||
static void GlobalInit();
|
||||
static void GlobalShutdown();
|
||||
|
||||
QString versionString();
|
||||
|
||||
template <typename T>
|
||||
void setGlobal(const char *varName, T *object)
|
||||
{
|
||||
|
||||
@@ -1399,6 +1399,16 @@ void MainWindow::on_action_Statistics_Viewer_triggered()
|
||||
ui->toolWindowManager->addToolWindow(stats, mainToolArea());
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Python_Shell_triggered()
|
||||
{
|
||||
QWidget *py = m_Ctx.GetPythonShell()->Widget();
|
||||
|
||||
if(ui->toolWindowManager->toolWindows().contains(py))
|
||||
ToolWindowManager::raiseToolWindow(py);
|
||||
else
|
||||
ui->toolWindowManager->addToolWindow(py, mainToolArea());
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Resolve_Symbols_triggered()
|
||||
{
|
||||
m_Ctx.Replay().AsyncInvoke([this](IReplayController *r) { r->InitResolver(); });
|
||||
|
||||
@@ -89,6 +89,7 @@ public:
|
||||
void showCaptureDialog() { on_action_Capture_Log_triggered(); }
|
||||
void showDebugMessageView() { on_action_Errors_and_Warnings_triggered(); }
|
||||
void showStatisticsViewer() { on_action_Statistics_Viewer_triggered(); }
|
||||
void showPythonShell() { on_action_Python_Shell_triggered(); }
|
||||
private slots:
|
||||
// automatic slots
|
||||
void on_action_Exit_triggered();
|
||||
@@ -104,6 +105,7 @@ private slots:
|
||||
void on_action_Capture_Log_triggered();
|
||||
void on_action_Errors_and_Warnings_triggered();
|
||||
void on_action_Statistics_Viewer_triggered();
|
||||
void on_action_Python_Shell_triggered();
|
||||
void on_action_Inject_into_Process_triggered();
|
||||
void on_action_Resolve_Symbols_triggered();
|
||||
void on_action_Attach_to_Running_Instance_triggered();
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "PythonShell.h"
|
||||
#include <QFontDatabase>
|
||||
#include <QKeyEvent>
|
||||
#include <QScrollBar>
|
||||
#include "3rdparty/scintilla/include/SciLexer.h"
|
||||
#include "3rdparty/scintilla/include/qt/ScintillaEdit.h"
|
||||
#include "Code/ScintillaSyntax.h"
|
||||
#include "Code/pyrenderdoc/PythonContext.h"
|
||||
#include "ui_PythonShell.h"
|
||||
|
||||
PythonShell::PythonShell(ICaptureContext &ctx, QWidget *parent)
|
||||
: QFrame(parent), ui(new Ui::PythonShell), m_Ctx(ctx)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QObject::connect(ui->lineInput, &RDLineEdit::keyPress, this, &PythonShell::interactive_keypress);
|
||||
|
||||
ui->lineInput->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
ui->interactiveOutput->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
ui->scriptOutput->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
|
||||
scriptEditor = new ScintillaEdit(this);
|
||||
|
||||
scriptEditor->setMarginLeft(4);
|
||||
scriptEditor->setMarginWidthN(0, 32);
|
||||
scriptEditor->setMarginWidthN(1, 0);
|
||||
scriptEditor->setMarginWidthN(2, 16);
|
||||
scriptEditor->setObjectName("scriptEditor");
|
||||
|
||||
scriptEditor->markerSetBack(CURRENT_MARKER, SCINTILLA_COLOUR(240, 128, 128));
|
||||
scriptEditor->markerSetBack(CURRENT_MARKER + 1, SCINTILLA_COLOUR(240, 128, 128));
|
||||
scriptEditor->markerDefine(CURRENT_MARKER, SC_MARK_SHORTARROW);
|
||||
scriptEditor->markerDefine(CURRENT_MARKER + 1, SC_MARK_BACKGROUND);
|
||||
|
||||
ConfigureSyntax(scriptEditor, SCLEX_PYTHON);
|
||||
|
||||
scriptEditor->setTabWidth(4);
|
||||
|
||||
scriptEditor->setScrollWidth(1);
|
||||
scriptEditor->setScrollWidthTracking(true);
|
||||
|
||||
scriptEditor->colourise(0, -1);
|
||||
|
||||
QObject::connect(scriptEditor, &ScintillaEdit::modified, [this](int type, int, int, int,
|
||||
const QByteArray &, int, int, int) {
|
||||
if(type & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT | SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE))
|
||||
{
|
||||
scriptEditor->markerDeleteAll(CURRENT_MARKER);
|
||||
scriptEditor->markerDeleteAll(CURRENT_MARKER + 1);
|
||||
}
|
||||
});
|
||||
|
||||
ui->scriptSplitter->insertWidget(0, scriptEditor);
|
||||
int w = ui->scriptSplitter->rect().width();
|
||||
ui->scriptSplitter->setSizes({w * 2 / 3, w / 3});
|
||||
|
||||
ui->tabWidget->setCurrentIndex(0);
|
||||
|
||||
interactiveContext = NULL;
|
||||
|
||||
enableButtons(true);
|
||||
|
||||
// reset output to default
|
||||
on_clear_clicked();
|
||||
on_newScript_clicked();
|
||||
}
|
||||
|
||||
PythonShell::~PythonShell()
|
||||
{
|
||||
m_Ctx.BuiltinWindowClosed(this);
|
||||
|
||||
interactiveContext->Finish();
|
||||
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void PythonShell::on_execute_clicked()
|
||||
{
|
||||
QString command = ui->lineInput->text();
|
||||
|
||||
appendText(ui->interactiveOutput, command + "\n");
|
||||
|
||||
if(command.trimmed().length() > 0)
|
||||
interactiveContext->executeString(command, true);
|
||||
|
||||
history.push_front(command);
|
||||
historyidx = -1;
|
||||
|
||||
ui->lineInput->clear();
|
||||
|
||||
appendText(ui->interactiveOutput, ">> ");
|
||||
}
|
||||
|
||||
void PythonShell::on_clear_clicked()
|
||||
{
|
||||
QString minidocHeader = scriptHeader();
|
||||
|
||||
minidocHeader += "\n\n>> ";
|
||||
|
||||
ui->interactiveOutput->setText(minidocHeader);
|
||||
|
||||
if(interactiveContext)
|
||||
interactiveContext->Finish();
|
||||
|
||||
interactiveContext = newContext();
|
||||
}
|
||||
|
||||
void PythonShell::on_newScript_clicked()
|
||||
{
|
||||
QString minidocHeader = scriptHeader();
|
||||
|
||||
minidocHeader.replace('\n', "\n# ");
|
||||
|
||||
minidocHeader = "# " + minidocHeader + "\n\n";
|
||||
|
||||
scriptEditor->setText(minidocHeader.toUtf8().data());
|
||||
|
||||
scriptEditor->emptyUndoBuffer();
|
||||
}
|
||||
|
||||
void PythonShell::on_openScript_clicked()
|
||||
{
|
||||
QString filename =
|
||||
RDDialog::getOpenFileName(this, "Open Python Script", "", tr("Python scripts (*.py)"));
|
||||
|
||||
if(filename != "")
|
||||
{
|
||||
QFile f(filename);
|
||||
if(f.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
scriptEditor->setText(f.readAll().data());
|
||||
}
|
||||
else
|
||||
{
|
||||
RDDialog::critical(this, "Error loading script", tr("Couldn't open path %1.").arg(filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PythonShell::on_saveScript_clicked()
|
||||
{
|
||||
QString filename = RDDialog::getSaveFileName(this, tr("Save Python Script"), QString(),
|
||||
tr("Python scripts (*.py)"));
|
||||
|
||||
if(filename != "")
|
||||
{
|
||||
QDir dirinfo = QFileInfo(filename).dir();
|
||||
if(dirinfo.exists())
|
||||
{
|
||||
QFile f(filename);
|
||||
if(f.open(QIODevice::WriteOnly | QIODevice::Truncate))
|
||||
{
|
||||
f.write(scriptEditor->getText(scriptEditor->textLength() + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
RDDialog::critical(
|
||||
this, tr("Error saving script"),
|
||||
tr("Couldn't open path %1 for write.\n%2").arg(filename).arg(f.errorString()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDDialog::critical(this, tr("Invalid directory"),
|
||||
tr("Cannot find target directory to save to"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PythonShell::on_runScript_clicked()
|
||||
{
|
||||
PythonContext *context = newContext();
|
||||
|
||||
ui->scriptOutput->clear();
|
||||
|
||||
QString script = QString::fromUtf8(scriptEditor->getText(scriptEditor->textLength() + 1));
|
||||
|
||||
enableButtons(false);
|
||||
|
||||
LambdaThread *thread = new LambdaThread([this, script, context]() {
|
||||
|
||||
scriptContext = context;
|
||||
context->executeString("script.py", script);
|
||||
scriptContext = NULL;
|
||||
|
||||
context->Finish();
|
||||
|
||||
GUIInvoke::call([this]() { enableButtons(true); });
|
||||
});
|
||||
|
||||
thread->selfDelete(true);
|
||||
thread->start();
|
||||
}
|
||||
|
||||
void PythonShell::on_abortRun_clicked()
|
||||
{
|
||||
if(scriptContext)
|
||||
scriptContext->abort();
|
||||
}
|
||||
|
||||
void PythonShell::traceLine(const QString &file, int line)
|
||||
{
|
||||
if(QObject::sender() == (QObject *)interactiveContext)
|
||||
return;
|
||||
|
||||
scriptEditor->markerDeleteAll(CURRENT_MARKER);
|
||||
scriptEditor->markerDeleteAll(CURRENT_MARKER + 1);
|
||||
|
||||
scriptEditor->markerAdd(line > 0 ? line - 1 : 0, CURRENT_MARKER);
|
||||
scriptEditor->markerAdd(line > 0 ? line - 1 : 0, CURRENT_MARKER + 1);
|
||||
}
|
||||
|
||||
void PythonShell::exception(const QString &type, const QString &value, QList<QString> frames)
|
||||
{
|
||||
QTextEdit *out = ui->scriptOutput;
|
||||
if(QObject::sender() == (QObject *)interactiveContext)
|
||||
out = ui->interactiveOutput;
|
||||
|
||||
QString exString;
|
||||
|
||||
if(!out->toPlainText().endsWith('\n'))
|
||||
exString = "\n";
|
||||
if(!frames.isEmpty())
|
||||
{
|
||||
exString += "Traceback (most recent call last):\n";
|
||||
for(const QString &f : frames)
|
||||
exString += QString(" %1\n").arg(f);
|
||||
}
|
||||
exString += QString("%1: %2\n").arg(type).arg(value);
|
||||
|
||||
appendText(out, exString);
|
||||
}
|
||||
|
||||
void PythonShell::textOutput(bool isStdError, const QString &output)
|
||||
{
|
||||
QTextEdit *out = ui->scriptOutput;
|
||||
if(QObject::sender() == (QObject *)interactiveContext)
|
||||
out = ui->interactiveOutput;
|
||||
|
||||
appendText(out, output);
|
||||
}
|
||||
|
||||
void PythonShell::interactive_keypress(QKeyEvent *event)
|
||||
{
|
||||
if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
||||
on_execute_clicked();
|
||||
|
||||
bool moved = false;
|
||||
|
||||
if(event->key() == Qt::Key_Down && historyidx > -1)
|
||||
{
|
||||
historyidx--;
|
||||
|
||||
moved = true;
|
||||
}
|
||||
|
||||
QString workingtext = "";
|
||||
|
||||
if(event->key() == Qt::Key_Up && historyidx + 1 < history.count())
|
||||
{
|
||||
if(historyidx == -1)
|
||||
workingtext = ui->lineInput->text();
|
||||
|
||||
historyidx++;
|
||||
|
||||
moved = true;
|
||||
}
|
||||
|
||||
if(moved)
|
||||
{
|
||||
if(historyidx == -1)
|
||||
ui->lineInput->setText(workingtext);
|
||||
else
|
||||
ui->lineInput->setText(history[historyidx]);
|
||||
|
||||
ui->lineInput->deselect();
|
||||
}
|
||||
}
|
||||
|
||||
QString PythonShell::scriptHeader()
|
||||
{
|
||||
return tr(R"(RenderDoc Python console, powered by python %1.
|
||||
The 'pyrenderdoc' object is the current CaptureContext instance.
|
||||
The 'renderdoc' and 'qrenderdoc' modules are available.
|
||||
Documentation is available: https://renderdoc.org/docs/python_api/index.html)")
|
||||
.arg(interactiveContext->versionString());
|
||||
}
|
||||
|
||||
void PythonShell::appendText(QTextEdit *output, const QString &text)
|
||||
{
|
||||
output->moveCursor(QTextCursor::End);
|
||||
output->insertPlainText(text);
|
||||
|
||||
// scroll to the bottom
|
||||
QScrollBar *vscroll = output->verticalScrollBar();
|
||||
vscroll->setValue(vscroll->maximum());
|
||||
}
|
||||
|
||||
void PythonShell::enableButtons(bool enable)
|
||||
{
|
||||
ui->newScript->setEnabled(enable);
|
||||
ui->openScript->setEnabled(enable);
|
||||
ui->saveScript->setEnabled(enable);
|
||||
ui->runScript->setEnabled(enable);
|
||||
ui->abortRun->setEnabled(!enable);
|
||||
}
|
||||
|
||||
PythonContext *PythonShell::newContext()
|
||||
{
|
||||
PythonContext *ret = new PythonContext();
|
||||
|
||||
QObject::connect(ret, &PythonContext::traceLine, this, &PythonShell::traceLine);
|
||||
QObject::connect(ret, &PythonContext::exception, this, &PythonShell::exception);
|
||||
QObject::connect(ret, &PythonContext::textOutput, this, &PythonShell::textOutput);
|
||||
|
||||
ret->setGlobal("pyrenderdoc", &m_Ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include "Code/CaptureContext.h"
|
||||
|
||||
class PythonContext;
|
||||
class ScintillaEdit;
|
||||
class QTextEdit;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class PythonShell;
|
||||
}
|
||||
|
||||
class PythonShell : public QFrame, public IPythonShell
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PythonShell(ICaptureContext &ctx, QWidget *parent = 0);
|
||||
|
||||
~PythonShell();
|
||||
|
||||
// IPythonShell
|
||||
QWidget *Widget() override { return this; }
|
||||
private slots:
|
||||
// automatic slots
|
||||
void on_execute_clicked();
|
||||
void on_clear_clicked();
|
||||
void on_newScript_clicked();
|
||||
void on_openScript_clicked();
|
||||
void on_saveScript_clicked();
|
||||
void on_runScript_clicked();
|
||||
void on_abortRun_clicked();
|
||||
|
||||
// manual slots
|
||||
void interactive_keypress(QKeyEvent *e);
|
||||
void traceLine(const QString &file, int line);
|
||||
void exception(const QString &type, const QString &value, QList<QString> frames);
|
||||
void textOutput(bool isStdError, const QString &output);
|
||||
|
||||
private:
|
||||
Ui::PythonShell *ui;
|
||||
ICaptureContext &m_Ctx;
|
||||
|
||||
ScintillaEdit *scriptEditor;
|
||||
|
||||
static const int CURRENT_MARKER = 0;
|
||||
|
||||
PythonContext *interactiveContext, *scriptContext;
|
||||
|
||||
QList<QString> history;
|
||||
int historyidx = -1;
|
||||
|
||||
PythonContext *newContext();
|
||||
|
||||
QString scriptHeader();
|
||||
void appendText(QTextEdit *output, const QString &text);
|
||||
void enableButtons(bool enable);
|
||||
};
|
||||
@@ -0,0 +1,315 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PythonShell</class>
|
||||
<widget class="QFrame" name="PythonShell">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>544</width>
|
||||
<height>346</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Interactive Python Shell</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="interactiveTab">
|
||||
<attribute name="title">
|
||||
<string>Interactive Shell</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="RDTextEdit" name="interactiveOutput">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="RDLineEdit" name="lineInput"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="execute">
|
||||
<property name="text">
|
||||
<string>Execute</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clear">
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="scriptTab">
|
||||
<attribute name="title">
|
||||
<string>Run Scripts</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="toolbar">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="newScript">
|
||||
<property name="toolTip">
|
||||
<string>Create a new blank script</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="openScript">
|
||||
<property name="toolTip">
|
||||
<string>Open an existing python script</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/folder_page.png</normaloff>:/folder_page.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::InstantPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="saveScript">
|
||||
<property name="toolTip">
|
||||
<string>Save the current script to disk</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save As</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/save.png</normaloff>:/save.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="sep">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="runScript">
|
||||
<property name="toolTip">
|
||||
<string>Begin running the script in python</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Run</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/runfwd.png</normaloff>:/runfwd.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="abortRun">
|
||||
<property name="toolTip">
|
||||
<string>Stop execution of the current script</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Abort</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/del.png</normaloff>:/del.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="scriptSplitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="RDTextEdit" name="scriptOutput">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RDLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>Widgets/Extended/RDLineEdit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RDTextEdit</class>
|
||||
<extends>QTextEdit</extends>
|
||||
<header>Widgets/Extended/RDTextEdit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../Resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -203,7 +203,8 @@ SOURCES += Code/qrenderdoc.cpp \
|
||||
Windows/Dialogs/EnvironmentEditor.cpp \
|
||||
Widgets/FindReplace.cpp \
|
||||
Widgets/Extended/RDSplitter.cpp \
|
||||
Windows/Dialogs/TipsDialog.cpp
|
||||
Windows/Dialogs/TipsDialog.cpp \
|
||||
Windows/PythonShell.cpp
|
||||
HEADERS += Code/CaptureContext.h \
|
||||
Code/qprocessinfo.h \
|
||||
Code/ReplayManager.h \
|
||||
@@ -260,7 +261,8 @@ HEADERS += Code/CaptureContext.h \
|
||||
Windows/Dialogs/EnvironmentEditor.h \
|
||||
Widgets/FindReplace.h \
|
||||
Widgets/Extended/RDSplitter.h \
|
||||
Windows/Dialogs/TipsDialog.h
|
||||
Windows/Dialogs/TipsDialog.h \
|
||||
Windows/PythonShell.h
|
||||
FORMS += Windows/Dialogs/AboutDialog.ui \
|
||||
Windows/MainWindow.ui \
|
||||
Windows/EventBrowser.ui \
|
||||
@@ -290,7 +292,8 @@ FORMS += Windows/Dialogs/AboutDialog.ui \
|
||||
Windows/PixelHistoryView.ui \
|
||||
Windows/Dialogs/EnvironmentEditor.ui \
|
||||
Widgets/FindReplace.ui \
|
||||
Windows/Dialogs/TipsDialog.ui
|
||||
Windows/Dialogs/TipsDialog.ui \
|
||||
Windows/PythonShell.ui
|
||||
|
||||
RESOURCES += Resources/resources.qrc
|
||||
|
||||
|
||||
@@ -673,6 +673,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(IntDir)generated\moc_SettingsDialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_ShaderViewer.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_PythonShell.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_PixelHistoryView.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_StatisticsViewer.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_SuggestRemoteDialog.cpp" />
|
||||
@@ -740,6 +741,7 @@
|
||||
<ClCompile Include="Windows\PipelineState\PipelineStateViewer.cpp" />
|
||||
<ClCompile Include="Windows\PipelineState\VulkanPipelineStateViewer.cpp" />
|
||||
<ClCompile Include="Windows\ShaderViewer.cpp" />
|
||||
<ClCompile Include="Windows\PythonShell.cpp" />
|
||||
<ClCompile Include="Windows\PixelHistoryView.cpp" />
|
||||
<ClCompile Include="Windows\StatisticsViewer.cpp" />
|
||||
<ClCompile Include="Windows\TextureViewer.cpp" />
|
||||
@@ -884,6 +886,7 @@
|
||||
<ClInclude Include="$(IntDir)generated\ui_ResourcePreview.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_SettingsDialog.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_ShaderViewer.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_PythonShell.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_PixelHistoryView.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_StatisticsViewer.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_SuggestRemoteDialog.h" />
|
||||
@@ -1168,6 +1171,12 @@
|
||||
<Message>MOC %(Filename).h</Message>
|
||||
<Outputs>$(IntDir)generated\moc_%(Filename).cpp</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\PythonShell.h">
|
||||
<AdditionalInputs>%(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -D_WIN32 -D_WIN64 -DRENDERDOC_PLATFORM_WIN32 -DSCINTILLA_QT=1 -DSCI_LEXER=1 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1900 -I$(ProjectDir) -I$(SolutionDir)\renderdoc\api\replay -I$(ProjectDir)3rdparty\qt\$(Platform)\mkspecs/win32-msvc2015 -I$(ProjectDir)3rdparty\qt\$(Platform)\include -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtWidgets -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtGui -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtCore %(Fullpath) -o $(IntDir)generated\moc_%(Filename).cpp</Command>
|
||||
<Message>MOC %(Filename).h</Message>
|
||||
<Outputs>$(IntDir)generated\moc_%(Filename).cpp</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\StatisticsViewer.h">
|
||||
<AdditionalInputs>%(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -D_WIN32 -D_WIN64 -DRENDERDOC_PLATFORM_WIN32 -DSCINTILLA_QT=1 -DSCI_LEXER=1 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1900 -I$(ProjectDir) -I$(SolutionDir)\renderdoc\api\replay -I$(ProjectDir)3rdparty\qt\$(Platform)\mkspecs/win32-msvc2015 -I$(ProjectDir)3rdparty\qt\$(Platform)\include -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtWidgets -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtGui -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtCore %(Fullpath) -o $(IntDir)generated\moc_%(Filename).cpp</Command>
|
||||
@@ -1368,6 +1377,12 @@
|
||||
<Message>UIC %(Filename).ui</Message>
|
||||
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\PythonShell.ui">
|
||||
<AdditionalInputs>%(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe %(Fullpath) -o $(IntDir)generated\ui_%(Filename).h</Command>
|
||||
<Message>UIC %(Filename).ui</Message>
|
||||
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\StatisticsViewer.ui">
|
||||
<AdditionalInputs>%(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe %(Fullpath) -o $(IntDir)generated\ui_%(Filename).h</Command>
|
||||
@@ -1569,4 +1584,4 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -576,6 +576,12 @@
|
||||
<ClCompile Include="Code\ReplayManager.cpp">
|
||||
<Filter>Code</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(IntDir)generated\moc_PythonShell.cpp">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Windows\PythonShell.cpp">
|
||||
<Filter>Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Widgets\Extended\RDTextEdit.cpp">
|
||||
<Filter>Widgets\Extended</Filter>
|
||||
</ClCompile>
|
||||
@@ -887,6 +893,9 @@
|
||||
<ClInclude Include="Code\ReplayManager.h">
|
||||
<Filter>Code</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(IntDir)generated\ui_PythonShell.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\128.png">
|
||||
@@ -1337,5 +1346,11 @@
|
||||
<CustomBuild Include="Widgets\Extended\RDTextEdit.h">
|
||||
<Filter>Widgets\Extended</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\PythonShell.h">
|
||||
<Filter>Windows</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\PythonShell.ui">
|
||||
<Filter>Windows</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user