Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wxGUI/history: add pop-up command menu with an item for delete command from history + history tree refactoring #3342

Merged
merged 4 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) [email protected]
@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,
)
Loading
Loading