Skip to content

Commit

Permalink
Merge pull request #153 from hanjinliu/fix-eval-line-edit
Browse files Browse the repository at this point in the history
Fix EvalLineEdit
  • Loading branch information
hanjinliu authored Oct 8, 2024
2 parents a4cc53f + 25de03b commit 63507d7
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
2 changes: 1 addition & 1 deletion magicclass/utils/qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def show_messagebox(
"""
show_dialog = _QMESSAGE_MODES[MessageBoxMode(mode)]
result = show_dialog(parent, title, text)
return result in (QMessageBox.Ok, QMessageBox.Yes)
return result in (QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.Yes)


def open_url(link: str) -> None:
Expand Down
35 changes: 29 additions & 6 deletions magicclass/widgets/eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from magicgui.widgets.bases import ValueWidget
from magicclass.widgets._const import FONT

_BUILTINS = "__builtins__"


def _get_last_group(text: str) -> str | None:
if text.endswith(" "):
Expand Down Expand Up @@ -96,6 +98,19 @@ def setFirst(self):
self.setCurrentRow(0)


_EVENTS_TO_HIDE = frozenset(
[QtCore.QEvent.Type.Move, QtCore.QEvent.Type.Resize, QtCore.QEvent.Type.Hide]
)


def _is_int(s: str) -> bool:
try:
int(s)
return True
except ValueError:
return False


class QEvalLineEdit(QtW.QLineEdit):
def __init__(self, parent=None):
super().__init__(parent)
Expand All @@ -111,7 +126,7 @@ def namespace(self) -> dict[str, Any]:

def setNamespace(self, ns: Mapping[str, Any]):
self._namespace = dict(ns)
self._namespace["__builtins__"] = {} # for safety
self._namespace.setdefault(_BUILTINS, {}) # for safety

def setAutoSuggest(self, auto_suggest: bool):
self._auto_suggest = auto_suggest
Expand Down Expand Up @@ -149,19 +164,26 @@ def _create_list_widget(self):
self._list_widget.setCurrentRow(0)
self.setFocus()

def _has_completion(self) -> bool:
if self._list_widget is None:
return False
return self._list_widget.count() > 0

def _get_completion_list(self, text: str) -> tuple[str, list[str]]:
last_found = _get_last_group(text)
if last_found is None:
return "", []

ns = self._namespace
if len(last_found) == 0:
return "", list(k for k in ns.keys() if k != "__builtins__")
return "", list(k for k in ns.keys() if k != _BUILTINS)
*strs, last = last_found.split(".")
if len(strs) == 0:
return last, [
k for k in ns.keys() if k.startswith(last_found) and k != "__builtins__"
k for k in ns.keys() if k.startswith(last_found) and k != _BUILTINS
]
elif len(strs) == 1 and _is_int(strs[0]):
return last, []
else:
try:
val = eval(".".join(strs), self.namespace(), {})
Expand Down Expand Up @@ -211,8 +233,9 @@ def event(self, event: QtCore.QEvent):
if event.type() == QtCore.QEvent.Type.KeyPress:
assert isinstance(event, QtGui.QKeyEvent)
if event.key() == Qt.Key.Key_Tab:
self.show_completion()
return True
if self._has_completion():
self.show_completion()
return True
elif event.key() == Qt.Key.Key_Down:
if self._list_widget is not None:
if event.modifiers() == Qt.KeyboardModifier.NoModifier:
Expand Down Expand Up @@ -248,7 +271,7 @@ def event(self, event: QtCore.QEvent):
self._list_widget.deleteLater()
self._list_widget = None
return True
elif event.type() == QtCore.QEvent.Type.Move:
elif event.type() in _EVENTS_TO_HIDE:
if self._list_widget is not None:
self._list_widget.close()
self._list_widget = None
Expand Down

0 comments on commit 63507d7

Please sign in to comment.