Skip to content

Commit

Permalink
working widget
Browse files Browse the repository at this point in the history
  • Loading branch information
alexhroom committed Nov 20, 2024
1 parent 770e48b commit 1a2587e
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 8 deletions.
99 changes: 99 additions & 0 deletions rascal2/dialogs/custom_file_editor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"""Dialogs for editing custom files."""

import logging
from pathlib import Path

from PyQt6 import Qsci, QtWidgets
from RATapi.utils.enums import Languages
from RATapi.wrappers import start_matlab


def edit_file(filename: str, language: Languages, parent: QtWidgets.QWidget):
"""Edit a file in the file editor.
Parameters
----------
filename : str
The name of the file to edit.
language : Languages
The language for dialog highlighting.
parent : QtWidgets.QWidget
The parent of this widget.
"""
file = Path(filename)
if not file.is_file():
logger = logging.getLogger("rascal_log")
logger.error("Attempted to edit a custom file which does not exist!")
return

dialog = CustomFileEditorDialog(file, language, parent)
dialog.exec()


def edit_file_matlab(filename: str):
"""Open a file in MATLAB."""
loader = start_matlab()

if loader is None:
logger = logging.getLogger("rascal_log")
logger.error("Attempted to edit a file in MATLAB engine, but `matlabengine` is not available.")
return

engine = loader.result()
engine.edit(filename)


class CustomFileEditorDialog(QtWidgets.QDialog):
"""Dialog for editing custom files.
Parameters
----------
file : pathlib.Path
The file to edit.
language : Languages
The language for dialog highlighting.
parent : QtWidgets.QWidget
The parent of this widget.
"""

def __init__(self, file, language, parent):
super().__init__(parent)

self.setMinimumWidth(600)
self.setMinimumHeight(400)

self.file = file

self.editor = Qsci.QsciScintilla()
match language:
case Languages.Python:
self.editor.setLexer(Qsci.QsciLexerPython(self.editor))
case Languages.Matlab:
self.editor.setLexer(Qsci.QsciLexerMatlab(self.editor))
case _:
self.editor.setLexer(None)

self.editor.setText(self.file.read_text())

save_button = QtWidgets.QPushButton("Save", self)
save_button.clicked.connect(self.save_file)
cancel_button = QtWidgets.QPushButton("Cancel", self)
cancel_button.clicked.connect(self.reject)

button_layout = QtWidgets.QHBoxLayout()
button_layout.addWidget(save_button)
button_layout.addWidget(cancel_button)

layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.editor)
layout.addLayout(button_layout)

self.setLayout(layout)
self.setWindowTitle(f"Edit {str(file)}")

def save_file(self):
"""Save and close the file."""
self.file.write_text(self.editor.text())
self.accept()
35 changes: 35 additions & 0 deletions rascal2/widgets/delegates.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,41 @@ def setModelData(self, editor, model, index):
model.setData(index, data, QtCore.Qt.ItemDataRole.EditRole)


class CustomFileFunctionDelegate(QtWidgets.QStyledItemDelegate):
"""Item delegate for choosing the function from a custom file."""

def __init__(self, parent):
super().__init__(parent)
self.widget = parent

def createEditor(self, parent, option, index):
func_names = self.widget.model.func_names[
index.siblingAtColumn(index.column() - 1).data(QtCore.Qt.ItemDataRole.DisplayRole)
]
# we define the methods set_data and get_date
# so that setEditorData and setModelData don't need
# to know what kind of widget the editor is
if func_names is None:
editor = QtWidgets.QLineEdit(parent)
editor.set_data = editor.setText
editor.get_data = editor.text
else:
editor = QtWidgets.QComboBox(parent)
editor.addItems(func_names)
editor.set_data = editor.setCurrentText
editor.get_data = editor.currentText

return editor

def setEditorData(self, editor: QtWidgets.QWidget, index):
data = index.data(QtCore.Qt.ItemDataRole.DisplayRole)
editor.set_data(data)

def setModelData(self, editor, model, index):
data = editor.get_data()
model.setData(index, data, QtCore.Qt.ItemDataRole.EditRole)


class ValueSpinBoxDelegate(QtWidgets.QStyledItemDelegate):
"""Item delegate for parameter values between a dynamic min and max.
Expand Down
21 changes: 21 additions & 0 deletions rascal2/widgets/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from enum import Enum
from math import floor, log10
from pathlib import Path
from typing import Callable

from pydantic.fields import FieldInfo
Expand Down Expand Up @@ -29,6 +30,7 @@ def get_validated_input(field_info: FieldInfo, parent=None) -> QtWidgets.QWidget
int: IntInputWidget,
float: FloatInputWidget,
Enum: EnumInputWidget,
Path: PathInputWidget,
}

for input_type, widget in class_widgets.items():
Expand Down Expand Up @@ -160,6 +162,25 @@ def create_editor(self, field_info: FieldInfo) -> QtWidgets.QWidget:
return editor


class PathInputWidget(BaseInputWidget):
"""Input widget for paths."""

edit_signal = "pressed"

def create_editor(self, field_info: FieldInfo) -> QtWidgets.QWidget:
file_dialog = QtWidgets.QFileDialog(parent=self)

def open_file():
file = file_dialog.getOpenFileName(filter="*.m *.py *.cpp")[0]
if file:
browse_button.setText(file)

browse_button = QtWidgets.QPushButton("Browse...", self)
browse_button.clicked.connect(lambda: open_file())

return browse_button


class AdaptiveDoubleSpinBox(QtWidgets.QDoubleSpinBox):
"""A double spinbox which adapts to given numbers of decimals."""

Expand Down
Loading

0 comments on commit 1a2587e

Please sign in to comment.