diff --git a/python/console.py b/python/console.py
index b16c61c..e3e18f4 100755
--- a/python/console.py
+++ b/python/console.py
@@ -16,6 +16,14 @@ Has +- the same behaviour as command-line interactive console:
- has command history, accessible using up/down keys
- supports pasting of commands
+Can be opened as a QWidget (top-level window, unowned) or as a QDockWidget;
+/Qgis/dockPythonConsole in the registry controls this; set in Settings, Options, General tab, Open Python console in a dock window
+Takes effect the next time Plugins, Python Console is chosen. It is not necessary to restart QGIS.
+The editor is retained so none of its content is lost.
+- as a QWidget: Plugins, Python Console will show it; it can be hidden by its Close (X) button or minimized
+- as a QDockWidget: Plugins, Python Console toggles show/hide; is hidden (actually, not constructed) on QGIS start up
+ also, this appears in the main window context menu and can be toggled off and on there
+
TODO:
- configuration - init commands, font, ...
- python code highlighting
@@ -33,19 +41,50 @@ import code
_init_commands = ["from qgis.core import *", "import qgis.utils"]
_console = None
+_consoleEditor = None
+_consoleAsDock = None
def show_console():
""" called from QGIS to open the console """
global _console
- if _console is None:
- _console = PythonConsole(iface.mainWindow())
- _console.show() # force show even if it was restored as hidden
+ global _consoleEditor
+ global _consoleAsDock
+
+ s = QSettings()
+ tempConsoleAsDock = s.value("/Qgis/dockPythonConsole",False).toBool()
+
+ if _consoleAsDock != tempConsoleAsDock:
+ if _consoleEditor is None:
+ _consoleEditor = PythonEdit()
+
+ if _console is not None:
+ if _consoleAsDock:
+ iface.mainWindow().removeDockWidget(_console)
+ else:
+ _console.hide()
+
+ if tempConsoleAsDock: # re-parent the editor object
+ newconsole = PythonConsole(_consoleEditor, iface.mainWindow())
+ else:
+ newconsole = PythonConsoleW(_consoleEditor) # unowned window
+
+ newconsole.setWindowTitle(QCoreApplication.translate("PythonConsole", "Python Console"))
+
+ _console = None # then delete the old console window
+ _console = newconsole # and remember the new console window
+ _consoleAsDock = tempConsoleAsDock # save current state
+
+ if _consoleAsDock:
+ _console.setVisible(not _console.isVisible()) # toggle on each call if QDockWidget
else:
- _console.setVisible(not _console.isVisible())
+ _console.show() # always show if QWidget
+ _console.raise_()
+ _console.setWindowState( _console.windowState() & ~Qt.WindowMinimized )
+
# set focus to the edit box so the user can start typing
if _console.isVisible():
_console.activateWindow()
- _console.edit.setFocus()
+ _consoleEditor.setFocus()
_old_stdout = sys.stdout
@@ -56,7 +95,7 @@ def clearConsole():
global _console
if _console is None:
return
- _console.edit.clearConsole()
+ _consoleEditor.clearConsole()
# hook for python console so all output will be redirected
@@ -80,26 +119,57 @@ class QgisOutputCatcher:
sys.stdout = QgisOutputCatcher()
class PythonConsole(QDockWidget):
- def __init__(self, parent=None):
+ """ as a QDockWidget """
+ def __init__(self, editor, parent=None):
QDockWidget.__init__(self, parent)
self.setObjectName("Python Console")
self.setAllowedAreas(Qt.BottomDockWidgetArea)
- self.widget = QWidget()
- self.l = QVBoxLayout(self.widget)
- self.l.setContentsMargins(0,0,0,0)
- self.edit = PythonEdit()
- self.l.addWidget(self.edit)
- self.setWidget(self.widget)
- self.setWindowTitle(QCoreApplication.translate("PythonConsole", "Python Console"))
+ widget = QWidget()
+ l = QVBoxLayout(widget)
+ l.setContentsMargins(0,0,0,0)
+ l.addWidget(editor)
+ self.setWidget(widget)
# try to restore position from stored main window state
if not iface.mainWindow().restoreDockWidget(self):
iface.mainWindow().addDockWidget(Qt.BottomDockWidgetArea, self)
-
+ self.hide() # visibility toggling will show console on first use
+
+ def sizeHint(self):
+ return QSize(500,300)
+
+ def closeEvent(self, event):
+ QWidget.closeEvent(self, event)
+
+class PythonConsoleW(QWidget):
+ """ as a QWidget """
+ def __init__(self, editor, parent=None):
+ QWidget.__init__(self, parent)
+ l = QVBoxLayout()
+ l.addWidget(editor)
+ l.setContentsMargins(0,0,0,0)
+ self.setLayout(l)
+ s = QSettings()
+ self.restoreGeometry(s.value("/python/console/geometry").toByteArray())
+
+ def __del__(self):
+ """
+ note that this isn't called when QGIS exits, so the window geometry
+ is not saved at program exit
+ """
+ s = QSettings()
+ s.setValue("/python/console/geometry", QVariant(self.saveGeometry()))
+ QWidget.__del__(self)
def sizeHint(self):
return QSize(500,300)
def closeEvent(self, event):
+ """
+ save settings here as well as in destructor to handle more
+ situations where the window geometry should be saved
+ """
+ s = QSettings()
+ s.setValue("/python/console/geometry", QVariant(self.saveGeometry()))
QWidget.closeEvent(self, event)
diff --git a/src/app/qgsoptions.cpp b/src/app/qgsoptions.cpp
index 0dd9c4b..0772442 100644
--- a/src/app/qgsoptions.cpp
+++ b/src/app/qgsoptions.cpp
@@ -285,6 +285,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
cbxShowTips->setChecked( settings.value( "/qgis/showTips", true ).toBool() );
cbxAttributeTableDocked->setChecked( settings.value( "/qgis/dockAttributeTable", false ).toBool() );
cbxIdentifyResultsDocked->setChecked( settings.value( "/qgis/dockIdentifyResults", false ).toBool() );
+ cbxPythonConsoleDocked->setChecked( settings.value( "/qgis/dockPythonConsole", false ).toBool() );
cbxSnappingOptionsDocked->setChecked( settings.value( "/qgis/dockSnapping", false ).toBool() );
cbxAddPostgisDC->setChecked( settings.value( "/qgis/addPostgisDC", false ).toBool() );
cbxAddNewLayersToCurrentGroup->setChecked( settings.value( "/qgis/addNewLayersToCurrentGroup", false ).toBool() );
@@ -570,6 +571,7 @@ void QgsOptions::saveOptions()
settings.setValue( "/qgis/dockAttributeTable", cbxAttributeTableDocked->isChecked() );
settings.setValue( "/qgis/attributeTableBehaviour", cmbAttrTableBehaviour->currentIndex() );
settings.setValue( "/qgis/dockIdentifyResults", cbxIdentifyResultsDocked->isChecked() );
+ settings.setValue( "/qgis/dockPythonConsole", cbxPythonConsoleDocked->isChecked() );
settings.setValue( "/qgis/dockSnapping", cbxSnappingOptionsDocked->isChecked() );
settings.setValue( "/qgis/addPostgisDC", cbxAddPostgisDC->isChecked() );
settings.setValue( "/qgis/addNewLayersToCurrentGroup", cbxAddNewLayersToCurrentGroup->isChecked() );
diff --git a/src/ui/qgsoptionsbase.ui b/src/ui/qgsoptionsbase.ui
index 41b7865..90a4fa8 100644
--- a/src/ui/qgsoptionsbase.ui
+++ b/src/ui/qgsoptionsbase.ui
@@ -343,6 +343,13 @@
-
+
+
+ Open Python console in a dock window (next time console is opened)
+
+
+
+ -
Add PostGIS layers with double click and select in extended mode
@@ -1858,6 +1865,7 @@
cbxIdentifyResultsDocked
cbxSnappingOptionsDocked
cbxAttributeTableDocked
+ cbxPythonConsoleDocked
cbxAddPostgisDC
cbxAddNewLayersToCurrentGroup
cmbAttrTableBehaviour