[QGIS Commit] r12725 - in trunk/qgis: python src/app src/python
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Sat Jan 9 19:10:23 EST 2010
Author: wonder
Date: 2010-01-09 19:10:23 -0500 (Sat, 09 Jan 2010)
New Revision: 12725
Added:
trunk/qgis/python/console.py
Removed:
trunk/qgis/src/app/qgspythondialog.cpp
trunk/qgis/src/app/qgspythondialog.h
Modified:
trunk/qgis/python/CMakeLists.txt
trunk/qgis/python/utils.py
trunk/qgis/src/app/CMakeLists.txt
trunk/qgis/src/app/qgisapp.cpp
trunk/qgis/src/app/qgisapp.h
trunk/qgis/src/python/qgspythonutils.h
trunk/qgis/src/python/qgspythonutilsimpl.cpp
trunk/qgis/src/python/qgspythonutilsimpl.h
Log:
Converted Python console from C++ to Python.
This cleans python support a bit and makes a starting point for further improvements of the console.
It's possible to run the console also outside QGIS:
import qgis.console
qgis.console.show_console()
Modified: trunk/qgis/python/CMakeLists.txt
===================================================================
--- trunk/qgis/python/CMakeLists.txt 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/python/CMakeLists.txt 2010-01-10 00:10:23 UTC (rev 12725)
@@ -99,6 +99,12 @@
ENDIF (BINDINGS_GLOBAL_INSTALL)
+# python console
+PYQT4_WRAP_UI(PYUI_FILE ${CMAKE_SOURCE_DIR}/src/ui/qgspythondialog.ui)
+
+ADD_CUSTOM_TARGET(pythonconsole ALL DEPENDS ${PYUI_FILE})
+
+
# Step 4: install built libs to python's site packages
-INSTALL(FILES __init__.py utils.py ${CMAKE_CURRENT_BINARY_DIR}/qgisconfig.py ${BINDINGS_LIBS} DESTINATION ${SITE_PKG_PATH}/qgis)
+INSTALL(FILES __init__.py utils.py console.py ${PYUI_FILE} ${CMAKE_CURRENT_BINARY_DIR}/qgisconfig.py ${BINDINGS_LIBS} DESTINATION ${SITE_PKG_PATH}/qgis)
Added: trunk/qgis/python/console.py
===================================================================
--- trunk/qgis/python/console.py (rev 0)
+++ trunk/qgis/python/console.py 2010-01-10 00:10:23 UTC (rev 12725)
@@ -0,0 +1,180 @@
+# -*- coding: utf-8 -*-
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+import traceback
+import sys
+
+from ui_qgspythondialog import Ui_QgsPythonDialog
+
+_console = None
+
+
+def show_console():
+ """ called from QGIS to open the console """
+ global _console
+ if _console is None:
+ _console = QgsPythonConsole()
+ _console.show()
+ _console.raise_()
+ _console.setWindowState( _console.windowState() & ~Qt.WindowMinimized )
+ _console.activateWindow()
+
+
+
+_old_stdout = sys.stdout
+
+class QgisOutputCatcher:
+ def __init__(self):
+ self.data = ''
+ def write(self, stuff):
+ self.data += stuff
+ def get_and_clean_data(self):
+ tmp = self.data
+ self.data = ''
+ return tmp
+ def flush(self):
+ pass
+
+def installConsoleHook():
+ sys.stdout = QgisOutputCatcher()
+
+def uninstallConsoleHook():
+ sys.stdout = _old_stdout
+
+
+
+class ConsoleHistory(object):
+ def __init__(self):
+ self.cmds = []
+ self.pos = 0
+ self.active_cmd = u"" # active, not yet entered command
+
+ def add_cmd(self, command):
+ if len(command) != 0:
+ self.cmds.append(command)
+ self.pos = len(self.cmds)
+ self.active_cmd = u""
+
+ def get_previous_cmd(self, current):
+ if self.pos == 0:
+ return None
+
+ if self.pos == len(self.cmds):
+ self.active_cmd = current
+ else:
+ self.cmds[self.pos] = current
+
+ self.pos -= 1
+ return self.cmds[self.pos]
+
+ def get_next_cmd(self, current):
+
+ # if we're at active (last) command, don't move
+ if self.pos == len(self.cmds):
+ return None
+
+ self.cmds[self.pos] = current
+ self.pos += 1
+
+ if self.pos == len(self.cmds):
+ return self.active_cmd
+ else:
+ return self.cmds[self.pos]
+
+
+
+class QgsPythonConsole(QWidget, Ui_QgsPythonDialog):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+
+ self.setupUi(self)
+
+ # minimize button was not enabled on mac
+ self.setWindowFlags( self.windowFlags() | Qt.WindowMinimizeButtonHint )
+
+ self.history = ConsoleHistory()
+
+ self.console_globals = {}
+
+ def escapeHtml(self, text):
+ return text.replace("<", "<").replace(">", ">")
+
+ @pyqtSlot()
+ def on_pbnPrev_clicked(self):
+ cmd = self.history.get_previous_cmd( self.getCommand() )
+ if cmd is not None:
+ self.edtCmdLine.setText(cmd)
+
+ @pyqtSlot()
+ def on_pbnNext_clicked(self):
+ cmd = self.history.get_next_cmd( self.getCommand() )
+ if cmd is not None:
+ self.edtCmdLine.setText(cmd)
+
+ def getCommand(self):
+ return unicode(self.edtCmdLine.toPlainText())
+
+ def execute(self, single):
+ command = self.getCommand()
+
+ self.history.add_cmd(command)
+
+ try:
+ # run command
+ code = compile(command, '<console>', 'single' if single else 'exec')
+ res = eval(code, self.console_globals)
+ result = unicode( res ) if res is not None else u''
+
+ # get standard output
+ output = sys.stdout.get_and_clean_data()
+
+ #_old_stdout.write("cmd: '"+command+"'\n")
+ #_old_stdout.write("res: '"+result+"'\n")
+ #_old_stdout.write("out: '"+output+"'\n")
+ #_old_stdout.flush()
+
+ # escape the result so python objects display properly and
+ # we can still use html output to get nicely formatted display
+ output = self.escapeHtml( output ) + self.escapeHtml( result )
+ if len(output) != 0:
+ output += "<br>"
+
+ except Exception, e:
+ #lst = traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)
+ lst = traceback.format_exception_only(sys.exc_type, sys.exc_value)
+ errorText = "<br>".join(map(self.escapeHtml, lst))
+ output = "<font color=\"red\">" + errorText + "</font><br>"
+
+ s = "<b><font color=\"green\">>>></font> " + self.escapeHtml( command ) + "</b><br>" + output
+ self.edtCmdLine.setText("")
+
+ self.txtHistory.moveCursor(QTextCursor.End)
+ self.txtHistory.insertHtml(s)
+ self.txtHistory.moveCursor(QTextCursor.End)
+ self.txtHistory.ensureCursorVisible()
+
+ @pyqtSlot()
+ def on_pbnExecute_clicked(self):
+ self.execute(False)
+
+ @pyqtSlot()
+ def on_pbnEval_clicked(self):
+ self.execute(True)
+
+ def showEvent(self, event):
+ QWidget.showEvent(self, event)
+ installConsoleHook()
+
+ def closeEvent(self, event):
+ uninstallConsoleHook()
+ QWidget.closeEvent(self, event)
+
+
+if __name__ == '__main__':
+ import sys
+ a = QApplication(sys.argv)
+ w = QgsPythonConsole()
+ w.show()
+ a.exec_()
Modified: trunk/qgis/python/utils.py
===================================================================
--- trunk/qgis/python/utils.py 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/python/utils.py 2010-01-10 00:10:23 UTC (rev 12725)
@@ -56,40 +56,6 @@
#######################
-# CONSOLE OUTPUT
-
-old_stdout = sys.stdout
-console_output = None
-
-# hook for python console so all output will be redirected
-# and then shown in console
-def console_displayhook(obj):
- global console_output
- console_output = obj
-
-class QgisOutputCatcher:
- def __init__(self):
- self.data = ''
- def write(self, stuff):
- self.data += stuff
- def get_and_clean_data(self):
- tmp = self.data
- self.data = ''
- return tmp
- def flush(self):
- pass
-
-
-def installConsoleHooks():
- sys.displayhook = console_displayhook
- sys.stdout = QgisOutputCatcher()
-
-def uninstallConsoleHooks():
- sys.displayhook = sys.__displayhook__
- sys.stdout = old_stdout
-
-
-#######################
# PLUGINS
# dictionary of plugins
Modified: trunk/qgis/src/app/CMakeLists.txt
===================================================================
--- trunk/qgis/src/app/CMakeLists.txt 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/src/app/CMakeLists.txt 2010-01-10 00:10:23 UTC (rev 12725)
@@ -60,7 +60,6 @@
qgspluginmanager.cpp
qgspluginmetadata.cpp
qgspluginregistry.cpp
- qgspythondialog.cpp
qgsprojectproperties.cpp
qgsrasterlayerproperties.cpp
qgssearchquerybuilder.cpp
@@ -162,7 +161,6 @@
qgsoptions.h
qgspastetransformations.h
qgspluginmanager.h
- qgspythondialog.h
qgsprojectproperties.h
qgsrasterlayerproperties.h
qgssearchquerybuilder.h
Modified: trunk/qgis/src/app/qgisapp.cpp
===================================================================
--- trunk/qgis/src/app/qgisapp.cpp 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/src/app/qgisapp.cpp 2010-01-10 00:10:23 UTC (rev 12725)
@@ -197,7 +197,6 @@
#include "qgsspatialitesourceselect.h"
#endif
-#include "qgspythondialog.h"
#include "qgspythonutils.h"
#ifndef WIN32
@@ -329,7 +328,6 @@
QgisApp::QgisApp( QSplashScreen *splash, QWidget * parent, Qt::WFlags fl )
: QMainWindow( parent, fl ),
mSplash( splash ),
- mPythonConsole( NULL ),
mPythonUtils( NULL )
#ifdef HAVE_QWT
,
@@ -507,7 +505,6 @@
delete mMapTools.mAddIsland;
delete mMapTools.mNodeTool;
- delete mPythonConsole;
delete mPythonUtils;
deletePrintComposers();
@@ -1110,12 +1107,16 @@
if ( !mPythonUtils || !mPythonUtils->isEnabled() )
return;
- if ( mPythonConsole == NULL )
- mPythonConsole = new QgsPythonDialog( mQgisInterface, mPythonUtils );
- mPythonConsole->show();
- mPythonConsole->raise();
- mPythonConsole->setWindowState( mPythonConsole->windowState() & ~Qt::WindowMinimized );
- mPythonConsole->activateWindow();
+ bool res = mPythonUtils->runStringUnsafe(
+ "import qgis.console\n"
+ "qgis.console.show_console()\n", false );
+
+ if ( !res )
+ {
+ QString className, text;
+ mPythonUtils->getError( className, text );
+ QMessageBox::critical( this, tr( "Error" ), tr( "Failed to open Python console:" ) + "\n" + className + ": " + text );
+ }
}
void QgisApp::createActionGroups()
Modified: trunk/qgis/src/app/qgisapp.h
===================================================================
--- trunk/qgis/src/app/qgisapp.h 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/src/app/qgisapp.h 2010-01-10 00:10:23 UTC (rev 12725)
@@ -53,7 +53,6 @@
class QgsMapTool;
class QgsPoint;
class QgsProviderRegistry;
-class QgsPythonDialog;
class QgsPythonUtils;
class QgsRasterLayer;
class QgsRectangle;
@@ -1045,7 +1044,6 @@
//!flag to indicate that the previous screen mode was 'maximised'
bool mPrevScreenModeMaximized;
- QgsPythonDialog* mPythonConsole;
QgsPythonUtils* mPythonUtils;
static QgisApp *smInstance;
Deleted: trunk/qgis/src/app/qgspythondialog.cpp
===================================================================
--- trunk/qgis/src/app/qgspythondialog.cpp 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/src/app/qgspythondialog.cpp 2010-01-10 00:10:23 UTC (rev 12725)
@@ -1,137 +0,0 @@
-/***************************************************************************
- qgspythondialog.h - dialog with embedded python console
- ---------------------
- begin : October 2006
- copyright : (C) 2006 by Martin Dobias
- email : wonder.sk at gmail dot com
- ***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-/* $Id$ */
-
-#include "qgspythondialog.h"
-#include "qgspythonutils.h"
-#include "qgslogger.h"
-
-#include <QShowEvent>
-#include <QCloseEvent>
-
-QgsPythonDialog::QgsPythonDialog( QgisInterface* pIface, QgsPythonUtils* pythonUtils, QWidget *parent )
- : QDialog( parent )
-{
- setupUi( this );
-#ifdef Q_WS_MAC
- // Qt4.3+ bug?: Mac window minimize control isn't enabled
- setWindowFlags( windowFlags() | Qt::WindowMinimizeButtonHint );
-#endif
- mIface = pIface;
- mPythonUtils = pythonUtils;
-
- pos = 0;
-}
-
-QgsPythonDialog::~QgsPythonDialog()
-{
-}
-
-QString QgsPythonDialog::escapeHtml( QString text )
-{
- return text.replace( "<", "<" ).replace( ">", ">" );
-}
-
-void QgsPythonDialog::on_pbnPrev_clicked()
-{
- if ( pos > 0 )
- {
- if ( pos == history.size() )
- history << edtCmdLine->toPlainText();
- else
- history[pos] = edtCmdLine->toPlainText();
- pos--;
- edtCmdLine->setText( history[pos] );
- }
-}
-
-void QgsPythonDialog::on_pbnNext_clicked()
-{
- if ( pos < history.size() - 1 )
- {
- history[pos] = edtCmdLine->toPlainText();
- pos++;
- edtCmdLine->setText( history[pos] );
- }
-}
-
-void QgsPythonDialog::execute( bool single )
-{
- QString command = edtCmdLine->toPlainText();
-
- QgsDebugMsg( QString( "command: |%1| %2" ).arg( command ).arg( single ) );
-
- if ( !command.isEmpty() )
- {
- history << command;
- pos = history.size();
- }
-
- QString output;
-
- // when using Py_single_input the return value will be always null
- // we're using custom hooks for output and exceptions to show output in console
- if ( mPythonUtils->runStringUnsafe( command, single ) )
- {
- mPythonUtils->evalString( "sys.stdout.get_and_clean_data()", output );
- QString result = mPythonUtils->getResult();
- // escape the result so python objects display properly and
- // we can still use html output to get nicely formatted display
- output = escapeHtml( output ) + escapeHtml( result );
-
- if ( !output.isEmpty() )
- output += "<br>";
- }
- else
- {
- QString className, errorText;
- mPythonUtils->getError( className, errorText );
-
- output = "<font color=\"red\">" + escapeHtml( className ) + ": " + escapeHtml( errorText ) + "</font><br>";
- }
-
- QString str = "<b><font color=\"green\">>>></font> " + escapeHtml( command ) + "</b><br>" + output;
-
- edtCmdLine->setText( "" );
-
- txtHistory->moveCursor( QTextCursor::End );
- txtHistory->insertHtml( str );
- txtHistory->moveCursor( QTextCursor::End );
- txtHistory->ensureCursorVisible();
-}
-
-void QgsPythonDialog::on_pbnExecute_clicked()
-{
- execute( false );
-}
-
-void QgsPythonDialog::on_pbnEval_clicked()
-{
- execute( true );
-}
-
-void QgsPythonDialog::showEvent( QShowEvent* event )
-{
- QDialog::showEvent( event );
-
- mPythonUtils->installConsoleHooks();
-}
-
-void QgsPythonDialog::closeEvent( QCloseEvent* event )
-{
- mPythonUtils->uninstallConsoleHooks();
-
- QDialog::closeEvent( event );
-}
Deleted: trunk/qgis/src/app/qgspythondialog.h
===================================================================
--- trunk/qgis/src/app/qgspythondialog.h 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/src/app/qgspythondialog.h 2010-01-10 00:10:23 UTC (rev 12725)
@@ -1,60 +0,0 @@
-/***************************************************************************
- qgspythondialog.h - dialog with embedded python console
- ---------------------
- begin : October 2006
- copyright : (C) 2006 by Martin Dobias
- email : wonder.sk at gmail dot com
- ***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-/* $Id$ */
-
-#ifndef QGSPYTHONDIALOG_H
-#define QGSPYTHONDIALOG_H
-
-#include "ui_qgspythondialog.h"
-
-class QgisInterface;
-class QgsPythonUtils;
-class QCloseEvent;
-class QShowEvent;
-
-class QgsPythonDialog : public QDialog, private Ui::QgsPythonDialog
-{
- Q_OBJECT
-
- public:
- QgsPythonDialog( QgisInterface* pIface, QgsPythonUtils* pythonUtils, QWidget *parent = 0 );
-
- ~QgsPythonDialog();
-
- QString escapeHtml( QString text );
-
- public slots:
-
- void on_pbnPrev_clicked();
- void on_pbnExecute_clicked();
- void on_pbnEval_clicked();
- void on_pbnNext_clicked();
-
- protected:
-
- void closeEvent( QCloseEvent *event );
- void showEvent( QShowEvent *event );
-
- private:
- void execute( bool single );
-
- QgisInterface* mIface;
- QgsPythonUtils* mPythonUtils;
-
- QStringList history;
- int pos;
-};
-
-#endif
Modified: trunk/qgis/src/python/qgspythonutils.h
===================================================================
--- trunk/qgis/src/python/qgspythonutils.h 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/src/python/qgspythonutils.h 2010-01-10 00:10:23 UTC (rev 12725)
@@ -56,17 +56,6 @@
virtual bool evalString( const QString& command, QString& result ) = 0;
- //! change displayhook and excepthook
- //! our hooks will just save the result to special variables
- //! and those can be used in the program
- virtual void installConsoleHooks() = 0;
-
- //! get back to the original settings (i.e. write output to stdout)
- virtual void uninstallConsoleHooks() = 0;
-
- //! get result from the last statement as a string
- virtual QString getResult() = 0;
-
//! get information about error to the supplied arguments
//! @return false if there was no python error
virtual bool getError( QString& errorClassName, QString& errorText ) = 0;
Modified: trunk/qgis/src/python/qgspythonutilsimpl.cpp
===================================================================
--- trunk/qgis/src/python/qgspythonutilsimpl.cpp 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/src/python/qgspythonutilsimpl.cpp 2010-01-10 00:10:23 UTC (rev 12725)
@@ -121,17 +121,8 @@
runString( "qgis.utils.uninstallErrorHook()" );
}
-void QgsPythonUtilsImpl::installConsoleHooks()
-{
- runString( "qgis.utils.installConsoleHooks()" );
-}
-void QgsPythonUtilsImpl::uninstallConsoleHooks()
-{
- runString( "qgis.utils.uninstallConsoleHooks()" );
-}
-
bool QgsPythonUtilsImpl::runStringUnsafe( const QString& command, bool single )
{
// TODO: convert special characters from unicode strings u"..." to \uXXXX
@@ -299,14 +290,6 @@
return true;
}
-QString QgsPythonUtilsImpl::getResult()
-{
- QString res;
- evalString( "qgis.utils.console_output", res );
- // clear output
- runString( "qgis.utils.console_output = None" );
- return res;
-}
QString QgsPythonUtilsImpl::PyObjectToQString( PyObject* obj )
{
@@ -368,25 +351,7 @@
return "(qgis error)";
}
-QString QgsPythonUtilsImpl::getVariableFromMain( QString name )
-{
- PyObject* obj;
- QString output;
- // get the result
- obj = PyDict_GetItemString( mMainDict, name.toUtf8() ); // obj is borrowed reference
-
- if ( obj != NULL && obj != Py_None )
- {
- output = PyObjectToQString( obj );
- }
-
- // erase result
- PyDict_SetItemString( mMainDict, name.toUtf8(), Py_None );
-
- return output;
-}
-
bool QgsPythonUtilsImpl::evalString( const QString& command, QString& result )
{
PyObject* res = PyRun_String( command.toUtf8().data(), Py_eval_input, mMainDict, mMainDict );
Modified: trunk/qgis/src/python/qgspythonutilsimpl.h
===================================================================
--- trunk/qgis/src/python/qgspythonutilsimpl.h 2010-01-09 23:10:34 UTC (rev 12724)
+++ trunk/qgis/src/python/qgspythonutilsimpl.h 2010-01-10 00:10:23 UTC (rev 12725)
@@ -68,22 +68,6 @@
//! @return false if there was no python error
bool getError( QString& errorClassName, QString& errorText );
- //! get variable from main dictionary
- QString getVariableFromMain( QString name );
-
- /* python console related functions */
-
- //! change displayhook and excepthook
- //! our hooks will just save the result to special variables
- //! and those can be used in the program
- void installConsoleHooks();
-
- //! get back to the original settings (i.e. write output to stdout)
- void uninstallConsoleHooks();
-
- //! get result from the last statement as a string
- QString getResult();
-
/* plugins related functions */
//! return current path for python plugins
More information about the QGIS-commit
mailing list