Skip to content

Commit

Permalink
wxGUI/history: add pop-up command menu with an item for delete comman…
Browse files Browse the repository at this point in the history
…d from history + history tree refactoring (#3342)
  • Loading branch information
lindakarlovska committed Jan 18, 2024
1 parent 6f68d3c commit b0deb48
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 154 deletions.
17 changes: 15 additions & 2 deletions gui/wxpython/core/gconsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@

from grass.pydispatch.signal import Signal

from grass.grassdb.history import (
get_current_mapset_gui_history_path,
add_entry_to_history,
)

from core import globalvar
from core.gcmd import CommandThread, GError, GException
from gui_core.forms import GUI
Expand Down Expand Up @@ -495,8 +500,16 @@ def RunCmd(
Debug.msg(2, "GPrompt:RunCmd(): empty command")
return

# update history file, command prompt history and history model
self._giface.updateHistory.emit(cmd=cmd_save_to_history)
# add entry to command history log
history_path = get_current_mapset_gui_history_path()
try:
add_entry_to_history(cmd_save_to_history, history_path)
except OSError as e:
GError(str(e))

# update command prompt and history model
if self._giface:
self._giface.entryToHistoryAdded.emit(cmd=cmd_save_to_history)

if command[0] in globalvar.grassCmd:
# send GRASS command without arguments to GUI command interface
Expand Down
11 changes: 9 additions & 2 deletions gui/wxpython/core/giface.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,15 @@ def __init__(self):
# Signal emitted when workspace is changed
self.workspaceChanged = Signal("StandaloneGrassInterface.workspaceChanged")

# Signal emitted when history should be updated
self.updateHistory = Signal("StandaloneGrassInterface.updateHistory")
# Signal emitted when entry to history is added
self.entryToHistoryAdded = Signal(
"StandaloneGrassInterface.entryToHistoryAdded"
)

# Signal emitted when entry from history is removed
self.entryFromHistoryRemoved = Signal(
"StandaloneGrassInterface.entryFromHistoryRemoved"
)

# workaround, standalone grass interface should be moved to sep. file
from core.gconsole import GConsole, EVT_CMD_OUTPUT, EVT_CMD_PROGRESS
Expand Down
23 changes: 8 additions & 15 deletions gui/wxpython/gui_core/goutput.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from grass.grassdb.history import (
read_history,
create_history_file,
update_history,
copy_history,
get_current_mapset_gui_history_path,
)
Expand Down Expand Up @@ -149,12 +148,14 @@ def __init__(
if self.giface:
self.giface.currentMapsetChanged.connect(self._loadHistory)

if self._gcstyle == GC_PROMPT:
# connect update history signal only for main Console Window
self.giface.updateHistory.connect(
lambda cmd: self.cmdPrompt.UpdateCmdHistory(cmd)
)
self.giface.updateHistory.connect(lambda cmd: self.UpdateHistory(cmd))
if self._gcstyle == GC_PROMPT:
# connect update history signals only for main Console Window
self.giface.entryToHistoryAdded.connect(
lambda cmd: self.cmdPrompt.AddEntryToCmdHistoryBuffer(cmd)
)
self.giface.entryFromHistoryRemoved.connect(
lambda index: self.cmdPrompt.RemoveEntryFromCmdHistoryBuffer(index)
)

# buttons
self.btnClear = ClearButton(parent=self.panelPrompt)
Expand Down Expand Up @@ -448,14 +449,6 @@ def OnCmdProgress(self, event):
self.progressbar.SetValue(event.value)
event.Skip()

def UpdateHistory(self, cmd):
"""Update command history"""
history_path = get_current_mapset_gui_history_path()
try:
update_history(cmd, history_path)
except OSError as e:
GError(str(e))

def OnCmdExportHistory(self, event):
"""Export the history of executed commands stored
in a .wxgui_history file to a selected file."""
Expand Down
15 changes: 13 additions & 2 deletions gui/wxpython/gui_core/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ def SetTextAndFocus(self, text):
self.SetCurrentPos(pos)
self.SetFocus()

def UpdateCmdHistory(self, cmd):
"""Update command history
def AddEntryToCmdHistoryBuffer(self, cmd):
"""Add entry to command history buffer
:param cmd: command given as a string
"""
Expand All @@ -319,6 +319,17 @@ def UpdateCmdHistory(self, cmd):
del self.cmdbuffer[0]
self.cmdindex = len(self.cmdbuffer)

def RemoveEntryFromCmdHistoryBuffer(self, index):
"""Remove entry from command history buffer
:param index: index of deleted command
"""
# remove command at the given index from history buffer
if index < len(self.cmdbuffer):
self.cmdbuffer.pop(index)

# update cmd index size
self.cmdindex = len(self.cmdbuffer)

def EntityToComplete(self):
"""Determines which part of command (flags, parameters) should
be completed at current cursor position"""
Expand Down
114 changes: 17 additions & 97 deletions gui/wxpython/history/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,20 @@
for details.
@author Linda Karlovska (Kladivova) linda.karlovska@seznam.cz
@author Anna Petrasova (kratochanna gmail com)
@author Tomas Zigo
"""

import wx
import re

from core import globalvar
from core.gcmd import GError, GException
from core.utils import (
parse_mapcalc_cmd,
replace_module_cmd_special_flags,
split,
)
from gui_core.forms import GUI
from gui_core.treeview import CTreeView

from gui_core.wrap import SearchCtrl
from history.tree import HistoryBrowserTree

from grass.pydispatch.signal import Signal


class HistoryBrowser(wx.Panel):
"""History browser for executing the commands from history log.
"""History browser panel for executing the commands from history log.
Signal:
showNotification - attribute 'message'
Expand All @@ -52,22 +44,24 @@ def __init__(
self.parent = parent
self._giface = giface

self.showNotification = Signal("HistoryBrowser.showNotification")
self.runIgnoredCmdPattern = Signal("HistoryBrowser.runIgnoredCmdPattern")
wx.Panel.__init__(self, parent=parent, id=id, **kwargs)
self.SetName("HistoryBrowser")

self._createTree()

self._giface.currentMapsetChanged.connect(self.UpdateHistoryModelFromScratch)
self._giface.updateHistory.connect(
lambda cmd: self.UpdateHistoryModelByCommand(cmd)
)
self.showNotification = Signal("HistoryBrowser.showNotification")
self.runIgnoredCmdPattern = Signal("HistoryBrowser.runIgnoredCmdPattern")

# search box
self.search = SearchCtrl(self)
self.search.SetDescriptiveText(_("Search"))
self.search.ShowCancelButton(True)
self.search.Bind(wx.EVT_TEXT, lambda evt: self.Filter(evt.GetString()))
self.search.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, lambda evt: self.Filter(""))
self.search.Bind(wx.EVT_TEXT, lambda evt: self.tree.Filter(evt.GetString()))
self.search.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, lambda evt: self.tree.Filter(""))

# tree with layers
self.tree = HistoryBrowserTree(self, giface=giface)
self.tree.SetToolTip(_("Double-click to run selected tool"))
self.tree.showNotification.connect(self.showNotification)
self.tree.runIgnoredCmdPattern.connect(self.runIgnoredCmdPattern)

self._layout()

Expand All @@ -81,83 +75,9 @@ def _layout(self):
border=5,
)
sizer.Add(
self._tree, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5
self.tree, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5
)

self.SetSizerAndFit(sizer)
self.SetAutoLayout(True)
self.Layout()

def _createTree(self):
"""Create tree based on the model"""
self._model = HistoryBrowserTree()
self._tree = self._getTreeInstance()
self._tree.SetToolTip(_("Double-click to open the tool"))
self._tree.selectionChanged.connect(self.OnItemSelected)
self._tree.itemActivated.connect(lambda node: self.Run(node))

def _getTreeInstance(self):
return CTreeView(model=self._model.GetModel(), parent=self)

def _getSelectedNode(self):
selection = self._tree.GetSelected()
if not selection:
return None
return selection[0]

def _refreshTree(self):
self._tree.SetModel(self._model.GetModel())

def Filter(self, text):
"""Filter history
:param str text: text string
"""
model = self._model.GetModel()
if text:
model = self._model.model.Filtered(key=["command"], value=text)
self._tree.SetModel(model)
else:
self._tree.SetModel(model)

def UpdateHistoryModelFromScratch(self):
"""Update the model from scratch and refresh the tree"""
self._model.CreateModel()
self._refreshTree()

def UpdateHistoryModelByCommand(self, cmd):
"""Update the model by the command and refresh the tree"""
self._model.UpdateModel(cmd)
self._refreshTree()

def OnItemSelected(self, node):
"""Item selected"""
command = node.data["command"]
self.showNotification.emit(message=command)

def Run(self, node=None):
"""Parse selected history command into list and launch module dialog."""
node = node or self._getSelectedNode()
if node:
command = node.data["command"]
if (
globalvar.ignoredCmdPattern
and re.compile(globalvar.ignoredCmdPattern).search(command)
and "--help" not in command
and "--ui" not in command
):
self.runIgnoredCmdPattern.emit(cmd=split(command))
return
if re.compile(r"^r[3]?\.mapcalc").search(command):
command = parse_mapcalc_cmd(command)
command = replace_module_cmd_special_flags(command)
lst = split(command)
try:
GUI(parent=self, giface=self._giface).ParseCommand(lst)
except GException as e:
GError(
parent=self,
message=str(e),
caption=_("Cannot be parsed into command"),
showTraceback=False,
)

0 comments on commit b0deb48

Please sign in to comment.