Skip to content

Commit b805894

Browse files
committed
[pyqgis-console] uses context menu to handle the command history instead of typing directly the command into the console
- shows history in dialog (much more usable)
1 parent eafe528 commit b805894

File tree

2 files changed

+195
-42
lines changed

2 files changed

+195
-42
lines changed

python/console/console_history_dlg.ui

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>HistoryDialog</class>
4+
<widget class="QDialog" name="HistoryDialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>587</width>
10+
<height>375</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Dialog</string>
15+
</property>
16+
<layout class="QGridLayout" name="gridLayout">
17+
<property name="leftMargin">
18+
<number>2</number>
19+
</property>
20+
<property name="topMargin">
21+
<number>4</number>
22+
</property>
23+
<property name="rightMargin">
24+
<number>2</number>
25+
</property>
26+
<property name="bottomMargin">
27+
<number>4</number>
28+
</property>
29+
<property name="horizontalSpacing">
30+
<number>6</number>
31+
</property>
32+
<item row="2" column="1">
33+
<widget class="QDialogButtonBox" name="buttonBox">
34+
<property name="orientation">
35+
<enum>Qt::Horizontal</enum>
36+
</property>
37+
<property name="standardButtons">
38+
<set>QDialogButtonBox::Close</set>
39+
</property>
40+
</widget>
41+
</item>
42+
<item row="2" column="0">
43+
<widget class="QPushButton" name="reloadHistory">
44+
<property name="text">
45+
<string>Reload</string>
46+
</property>
47+
</widget>
48+
</item>
49+
<item row="0" column="0" colspan="2">
50+
<widget class="QListView" name="listView">
51+
<property name="frameShape">
52+
<enum>QFrame::NoFrame</enum>
53+
</property>
54+
<property name="editTriggers">
55+
<set>QAbstractItemView::NoEditTriggers</set>
56+
</property>
57+
<property name="showDropIndicator" stdset="0">
58+
<bool>false</bool>
59+
</property>
60+
<property name="alternatingRowColors">
61+
<bool>true</bool>
62+
</property>
63+
</widget>
64+
</item>
65+
</layout>
66+
</widget>
67+
<resources/>
68+
<connections>
69+
<connection>
70+
<sender>buttonBox</sender>
71+
<signal>accepted()</signal>
72+
<receiver>HistoryDialog</receiver>
73+
<slot>accept()</slot>
74+
<hints>
75+
<hint type="sourcelabel">
76+
<x>248</x>
77+
<y>254</y>
78+
</hint>
79+
<hint type="destinationlabel">
80+
<x>157</x>
81+
<y>274</y>
82+
</hint>
83+
</hints>
84+
</connection>
85+
<connection>
86+
<sender>buttonBox</sender>
87+
<signal>rejected()</signal>
88+
<receiver>HistoryDialog</receiver>
89+
<slot>reject()</slot>
90+
<hints>
91+
<hint type="sourcelabel">
92+
<x>316</x>
93+
<y>260</y>
94+
</hint>
95+
<hint type="destinationlabel">
96+
<x>286</x>
97+
<y>274</y>
98+
</hint>
99+
</hints>
100+
</connection>
101+
</connections>
102+
</ui>

python/console/console_sci.py

+93-42
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import code
3232

3333
from qgis.core import QgsApplication
34+
from ui_console_history_dlg import Ui_HistoryDialog
3435

3536
_init_commands = ["from qgis.core import *", "import qgis.utils",
3637
"from qgis.utils import iface"]
@@ -69,6 +70,8 @@ def __init__(self, parent=None):
6970
# Read history command file
7071
self.readHistoryFile()
7172

73+
self.historyDlg = HistoryDialog(self)
74+
7275
# Brace matching: enable for a brace immediately before or after
7376
# the current position
7477
self.setBraceMatching(QsciScintilla.SloppyBraceMatch)
@@ -107,8 +110,6 @@ def __init__(self, parent=None):
107110
self.newShortcutCAS.setContext(Qt.WidgetShortcut)
108111
self.newShortcutCAS.activated.connect(self.autoCompleteKeyBinding)
109112
self.newShortcutCSS.activated.connect(self.showHistory)
110-
self.connect(self, SIGNAL('userListActivated(int, const QString)'),
111-
self.completion_list_selected)
112113

113114
def settingsShell(self):
114115
# Set Python lexer
@@ -129,7 +130,10 @@ def settingsShell(self):
129130
self.setAutoCompletionSource(self.AcsNone)
130131

131132
def showHistory(self):
132-
self.showUserList(1, QStringList(self.history))
133+
if not self.historyDlg.isVisible():
134+
self.historyDlg.show()
135+
self.historyDlg._reloadHistory()
136+
self.historyDlg.activateWindow()
133137

134138
def autoCompleteKeyBinding(self):
135139
radioButtonSource = self.settings.value("pythonConsole/autoCompleteSource").toString()
@@ -199,17 +203,6 @@ def setLexers(self):
199203

200204
## TODO: show completion list for file and directory
201205

202-
def completion_list_selected(self, id, txt):
203-
if id == 1:
204-
txt = unicode(txt)
205-
# get current cursor position
206-
line, pos = self.getCursorPosition()
207-
selCmdLength = self.text(line).length()
208-
# select typed text
209-
self.setSelection(line, 4, line, selCmdLength)
210-
self.removeSelectedText()
211-
self.insert(txt)
212-
213206
def getText(self):
214207
""" Get the text as a unicode string. """
215208
value = self.getBytes().decode('utf-8')
@@ -245,11 +238,6 @@ def move_cursor_to_end(self):
245238
self.ensureCursorVisible()
246239
self.ensureLineVisible(line)
247240

248-
#def on_new_line(self):
249-
#"""On new input line"""
250-
#self.move_cursor_to_end()
251-
#self.new_input_line = False
252-
253241
def is_cursor_on_last_line(self):
254242
"""Return True if cursor is on the last line"""
255243
cline, _ = self.getCursorPosition()
@@ -285,10 +273,19 @@ def updateHistory(self, command):
285273
self.historyIndex = len(self.history)
286274

287275
def writeHistoryFile(self):
288-
wH = open(_historyFile, 'w')
289-
for s in self.history:
290-
wH.write(s + '\n')
276+
ok = False
277+
try:
278+
wH = open(_historyFile, 'w')
279+
for s in self.history:
280+
wH.write(s + '\n')
281+
ok = True
282+
except:
283+
raise
291284
wH.close()
285+
if ok:
286+
msgText = QCoreApplication.translate('PythonConsole',
287+
'History saved successfully.')
288+
self.parent.callWidgetMessageBar(msgText)
292289

293290
def readHistoryFile(self):
294291
fileExist = QFile.exists(_historyFile)
@@ -301,9 +298,27 @@ def readHistoryFile(self):
301298
else:
302299
return
303300

304-
def clearHistoryFile(self):
305-
cH = open(_historyFile, 'w')
301+
def clearHistory(self, clearSession=False):
302+
if clearSession:
303+
self.history = QStringList()
304+
msgText = QCoreApplication.translate('PythonConsole',
305+
'Session and file history cleared successfully.')
306+
self.parent.callWidgetMessageBar(msgText)
307+
return
308+
ok = False
309+
try:
310+
cH = open(_historyFile, 'w')
311+
ok = True
312+
except:
313+
raise
306314
cH.close()
315+
if ok:
316+
msgText = QCoreApplication.translate('PythonConsole',
317+
'History cleared successfully.')
318+
self.parent.callWidgetMessageBar(msgText)
319+
320+
def clearHistorySession(self):
321+
self.clearHistory(True)
307322

308323
def showPrevious(self):
309324
if self.historyIndex < len(self.history) and not self.history.isEmpty():
@@ -402,6 +417,25 @@ def keyPressEvent(self, e):
402417

403418
def contextMenuEvent(self, e):
404419
menu = QMenu(self)
420+
subMenu = QMenu(menu)
421+
titleHistoryMenu = QCoreApplication.translate("PythonConsole", "Command History")
422+
subMenu.setTitle(titleHistoryMenu)
423+
showHistoryAction = subMenu.addAction(QCoreApplication.translate("PythonConsole",
424+
"Show"),
425+
self.showHistory, 'Ctrl+Shift+SPACE')
426+
subMenu.addSeparator()
427+
saveHistoryAction = subMenu.addAction(QCoreApplication.translate("PythonConsole",
428+
"Save"),
429+
self.writeHistoryFile)
430+
subMenu.addSeparator()
431+
clearHistoryAction = subMenu.addAction(QCoreApplication.translate("PythonConsole",
432+
"Clear File"),
433+
self.clearHistory)
434+
clearSessHistoryAction = subMenu.addAction(QCoreApplication.translate("PythonConsole",
435+
"Clear Session"),
436+
self.clearHistorySession)
437+
menu.addMenu(subMenu)
438+
menu.addSeparator()
405439
copyAction = menu.addAction(QCoreApplication.translate("PythonConsole",
406440
"Copy"),
407441
self.copy, QKeySequence.Copy)
@@ -460,14 +494,14 @@ def dropEvent(self, e):
460494
def insertFromDropPaste(self, textDP):
461495
pasteList = str(textDP).splitlines()
462496
for line in pasteList[:-1]:
463-
line.replace(">>> ", "").replace("... ", "")
464-
self.insert(unicode(line))
497+
cleanLine = line.replace(">>> ", "").replace("... ", "")
498+
self.insert(unicode(cleanLine))
465499
self.move_cursor_to_end()
466500
self.runCommand(unicode(self.currentCommand()))
467501
if pasteList[-1] != "":
468502
line = pasteList[-1]
469-
line.replace(">>> ", "").replace("... ", "")
470-
self.insert(unicode(line))
503+
cleanLine = line.replace(">>> ", "").replace("... ", "")
504+
self.insert(unicode(cleanLine))
471505
self.move_cursor_to_end()
472506

473507
def insertTextFromFile(self, listOpenFile):
@@ -485,11 +519,9 @@ def entered(self):
485519
self.runCommand( unicode(self.currentCommand()) )
486520
self.setFocus()
487521
self.move_cursor_to_end()
488-
#self.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER)
489522

490523
def currentCommand(self):
491524
linenr, index = self.getCursorPosition()
492-
#for i in range(0, linenr):
493525
txtLength = self.text(linenr).length()
494526
string = self.text()
495527
cmdLine = string.right(txtLength - 4)
@@ -500,18 +532,8 @@ def runCommand(self, cmd):
500532
self.writeCMD(cmd)
501533
import webbrowser
502534
self.updateHistory(cmd)
503-
if cmd in ('_save', '_clear', '_clearAll', '_pyqgis', '_api'):
504-
if cmd == '_save':
505-
self.writeHistoryFile()
506-
msgText = QCoreApplication.translate('PythonConsole', 'History saved successfully.')
507-
elif cmd == '_clear':
508-
self.clearHistoryFile()
509-
msgText = QCoreApplication.translate('PythonConsole', 'History cleared successfully.')
510-
elif cmd == '_clearAll':
511-
self.history = QStringList()
512-
self.clearHistoryFile()
513-
msgText = QCoreApplication.translate('PythonConsole', 'Session and file history cleared successfully.')
514-
elif cmd == '_pyqgis':
535+
if cmd in ('_pyqgis', '_api'):
536+
if cmd == '_pyqgis':
515537
webbrowser.open( "http://www.qgis.org/pyqgis-cookbook/" )
516538
elif cmd == '_api':
517539
webbrowser.open( "http://www.qgis.org/api/" )
@@ -539,3 +561,32 @@ def writeCMD(self, txt):
539561
getCmdString = self.text()
540562
prompt = getCmdString[0:4]
541563
sys.stdout.write(prompt+txt+'\n')
564+
565+
class HistoryDialog(QDialog, Ui_HistoryDialog):
566+
def __init__(self, parent):
567+
QDialog.__init__(self, parent)
568+
self.setupUi(self)
569+
self.parent = parent
570+
self.setWindowTitle(QCoreApplication.translate("PythonConsole",
571+
"Python Console - Command History"))
572+
self.listView.setToolTip(QCoreApplication.translate("PythonConsole",
573+
"Double click on item to execute"))
574+
self.model = QStandardItemModel(self.listView)
575+
576+
self._reloadHistory()
577+
578+
self.listView.doubleClicked.connect(self._runHistory)
579+
self.reloadHistory.clicked.connect(self._reloadHistory)
580+
581+
def _runHistory(self, item):
582+
cmd = item.data(Qt.DisplayRole).toString()
583+
self.parent.runCommand(unicode(cmd))
584+
585+
def _reloadHistory(self):
586+
self.model.clear()
587+
for i in self.parent.history:
588+
item = QStandardItem(i)
589+
self.model.appendRow(item)
590+
591+
self.listView.setModel(self.model)
592+
self.listView.scrollToBottom()

0 commit comments

Comments
 (0)