Improve sys.stdin redirection mechanism

This commit is contained in:
wmayer 2012-02-28 13:20:34 +01:00
parent e3cbca1062
commit fa12664f87
4 changed files with 50 additions and 14 deletions

View File

@ -392,7 +392,7 @@ PythonConsole::PythonConsole(QWidget *parent)
"Type 'help', 'copyright', 'credits' or 'license' for more information.") "Type 'help', 'copyright', 'credits' or 'license' for more information.")
.arg(QString::fromAscii(version)).arg(QString::fromAscii(platform)); .arg(QString::fromAscii(version)).arg(QString::fromAscii(platform));
d->output = d->info; d->output = d->info;
printPrompt(false); printPrompt(PythonConsole::Complete);
} }
/** Destroys the object and frees any allocated resources */ /** Destroys the object and frees any allocated resources */
@ -504,7 +504,9 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
d->history.append( QLatin1String("# ") + inputLine ); //< put line to history ... d->history.append( QLatin1String("# ") + inputLine ); //< put line to history ...
inputLineBegin.insertText( QString::fromAscii("# ") ); //< but comment it on console inputLineBegin.insertText( QString::fromAscii("# ") ); //< but comment it on console
setTextCursor( inputLineBegin ); setTextCursor( inputLineBegin );
printPrompt( d->interpreter->hasPendingInput() ); //< print adequate prompt printPrompt(d->interpreter->hasPendingInput() //< print adequate prompt
? PythonConsole::Incomplete
: PythonConsole::Complete);
} }
} break; } break;
@ -600,10 +602,15 @@ void PythonConsole::insertPythonError ( const QString& err )
d->error += err; d->error += err;
} }
void PythonConsole::onFlush()
{
printPrompt(PythonConsole::Flush);
}
/** Prints the ps1 prompt (>>> ) for complete and ps2 prompt (... ) for /** Prints the ps1 prompt (>>> ) for complete and ps2 prompt (... ) for
* incomplete commands to the console window. * incomplete commands to the console window.
*/ */
void PythonConsole::printPrompt(bool incomplete) void PythonConsole::printPrompt(PythonConsole::Prompt mode)
{ {
// write normal messages // write normal messages
if (!d->output.isEmpty()) { if (!d->output.isEmpty()) {
@ -632,8 +639,15 @@ void PythonConsole::printPrompt(bool incomplete)
else else
block.setUserState(0); block.setUserState(0);
incomplete ? cursor.insertText(QString::fromAscii("... ")) switch (mode)
: cursor.insertText(QString::fromAscii(">>> ")); {
case PythonConsole::Incomplete:
cursor.insertText(QString::fromAscii("... "));
case PythonConsole::Complete:
cursor.insertText(QString::fromAscii(">>> "));
default:
break;
}
cursor.endEditBlock(); cursor.endEditBlock();
// move cursor to the end // move cursor to the end
@ -706,9 +720,10 @@ void PythonConsole::runSource(const QString& line)
QMessageBox::critical(this, tr("Python console"), tr("Unhandled unknown C++ exception.")); QMessageBox::critical(this, tr("Python console"), tr("Unhandled unknown C++ exception."));
} }
printPrompt(incomplete ? PythonConsole::Incomplete
: PythonConsole::Complete);
PySys_SetObject("stdout", default_stdout); PySys_SetObject("stdout", default_stdout);
PySys_SetObject("stderr", default_stderr); PySys_SetObject("stderr", default_stderr);
printPrompt(incomplete);
d->interactive = false; d->interactive = false;
for (QStringList::Iterator it = d->statements.begin(); it != d->statements.end(); ++it) for (QStringList::Iterator it = d->statements.begin(); it != d->statements.end(); ++it)
printStatement(*it); printStatement(*it);
@ -751,7 +766,7 @@ void PythonConsole::printStatement( const QString& cmd )
cursor.movePosition(QTextCursor::End); cursor.movePosition(QTextCursor::End);
cursor.insertText( *it ); cursor.insertText( *it );
d->history.append( *it ); d->history.append( *it );
printPrompt(false); printPrompt(PythonConsole::Complete);
} }
} }
@ -984,7 +999,7 @@ void PythonConsole::runSourceFromMimeData(const QString& source)
buffer.append(line); buffer.append(line);
int ret = d->interpreter->compileCommand(buffer.join(QLatin1String("\n")).toUtf8()); int ret = d->interpreter->compileCommand(buffer.join(QLatin1String("\n")).toUtf8());
if (ret == 1) { // incomplete if (ret == 1) { // incomplete
printPrompt(true); printPrompt(PythonConsole::Incomplete);
} }
else if (ret == 0) { // complete else if (ret == 0) { // complete
// check if the following lines belong to the previous block // check if the following lines belong to the previous block
@ -1001,7 +1016,7 @@ void PythonConsole::runSourceFromMimeData(const QString& source)
// is finished // is finished
if (ret == -1) { if (ret == -1) {
// the command is not finished yet // the command is not finished yet
printPrompt(true); printPrompt(PythonConsole::Incomplete);
} }
else { else {
runSource(buffer.join(QLatin1String("\n"))); runSource(buffer.join(QLatin1String("\n")));
@ -1094,7 +1109,7 @@ void PythonConsole::onClearConsole()
{ {
clear(); clear();
d->output = d->info; d->output = d->info;
printPrompt(false); printPrompt(PythonConsole::Complete);
} }
void PythonConsole::onSaveHistoryAs() void PythonConsole::onSaveHistoryAs()
@ -1312,6 +1327,7 @@ PythonInputField::PythonInputField(QWidget* parent)
editField = new PythonEditor(this); editField = new PythonEditor(this);
gridLayout->addWidget(editField, 0, 0, 1, 1); gridLayout->addWidget(editField, 0, 0, 1, 1);
setFocusProxy(editField);
QHBoxLayout* hboxLayout = new QHBoxLayout(); QHBoxLayout* hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(6); hboxLayout->setSpacing(6);

View File

@ -96,6 +96,12 @@ class GuiExport PythonConsole : public TextEdit, public WindowParameter
Q_OBJECT Q_OBJECT
public: public:
enum Prompt {
Complete = 0,
Incomplete = 1,
Flush = 2
};
PythonConsole(QWidget *parent = 0); PythonConsole(QWidget *parent = 0);
~PythonConsole(); ~PythonConsole();
@ -108,6 +114,7 @@ public Q_SLOTS:
void onCopyHistory(); void onCopyHistory();
void onCopyCommand(); void onCopyCommand();
void onClearConsole(); void onClearConsole();
void onFlush();
private Q_SLOTS: private Q_SLOTS:
void visibilityChanged (bool visible); void visibilityChanged (bool visible);
@ -131,7 +138,7 @@ protected:
private: private:
void runSource(const QString&); void runSource(const QString&);
bool isComment(const QString&) const; bool isComment(const QString&) const;
void printPrompt(bool); void printPrompt(Prompt);
void insertPythonOutput(const QString&); void insertPythonOutput(const QString&);
void insertPythonError (const QString&); void insertPythonError (const QString&);
void runSourceFromMimeData(const QString&); void runSourceFromMimeData(const QString&);

View File

@ -26,6 +26,7 @@
# include <QByteArray> # include <QByteArray>
# include <QInputDialog> # include <QInputDialog>
# include <QEventLoop> # include <QEventLoop>
# include <QTimer>
#endif #endif
#include "PythonConsolePy.h" #include "PythonConsolePy.h"
@ -292,12 +293,18 @@ PythonStdin::PythonStdin(PythonConsole *pc)
: pyConsole(pc) : pyConsole(pc)
{ {
editField = new PythonInputField(/*getMainWindow()*/); editField = new PythonInputField(/*getMainWindow()*/);
timer = new QTimer();
timer->setInterval(250);
QObject::connect(timer, SIGNAL(timeout()),
editField, SLOT(hide()));
console = getMainWindow()->findChild<PythonConsole*>();
} }
PythonStdin::~PythonStdin() PythonStdin::~PythonStdin()
{ {
// call deleteLater() because deleting immediately causes problems // call deleteLater() because deleting immediately causes problems
editField->deleteLater(); editField->deleteLater();
timer->deleteLater();
} }
Py::Object PythonStdin::repr() Py::Object PythonStdin::repr()
@ -310,14 +317,16 @@ Py::Object PythonStdin::repr()
Py::Object PythonStdin::readline(const Py::Tuple& args) Py::Object PythonStdin::readline(const Py::Tuple& args)
{ {
if (console)
console->onFlush();
timer->stop();
QEventLoop loop; QEventLoop loop;
QObject::connect(editField, SIGNAL(textEntered()), &loop, SLOT(quit())); QObject::connect(editField, SIGNAL(textEntered()), &loop, SLOT(quit()));
editField->clear(); editField->clear();
editField->show(); editField->show();
editField->setFocus();
loop.exec(); loop.exec();
QString txt = editField->getText(); QString txt = editField->getText();
if (txt.isEmpty()) timer->start();
editField->hide();
return Py::String((const char*)txt.toAscii()); return Py::String((const char*)txt.toAscii());
} }

View File

@ -26,6 +26,8 @@
#include <CXX/Extensions.hxx> #include <CXX/Extensions.hxx>
class QTimer;
namespace Gui { namespace Gui {
class PythonConsole; class PythonConsole;
class PythonInputField; class PythonInputField;
@ -140,6 +142,8 @@ public:
private: private:
PythonInputField* editField; PythonInputField* editField;
PythonConsole* console;
QTimer* timer;
}; };
} // namespace Gui } // namespace Gui