Skip to content

Commit

Permalink
Add root directory line edit to Tool properties
Browse files Browse the repository at this point in the history
- Enable saving & loading the while item is loaded
- Enable undo/redo
  • Loading branch information
ptsavol committed Dec 4, 2024
1 parent e0a901b commit 1587ea6
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 56 deletions.
26 changes: 26 additions & 0 deletions spine_items/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,29 @@ def redo(self):
def undo(self):
item = self._project.get_item(self._item_name)
item.do_set_group_id(self._undo_group_id)


class UpdateRootDirCommand(SpineToolboxCommand):
def __init__(self, item_name, root_dir, project):
"""Command to update Tool root directory.
Args:
item_name (str): Item's name
root_dir (str): Root directory
project (SpineToolboxProject): Project
"""
super().__init__()
self._item_name = item_name
self._redo_root_dir = root_dir
item = project.get_item(item_name)
self._undo_root_dir = item.root_dir
self._project = project
self.setText(f"change root directory of {item_name}")

def redo(self):
item = self._project.get_item(self._item_name)
item.do_set_root_directory(self._redo_root_dir)

def undo(self):
item = self._project.get_item(self._item_name)
item.do_set_root_directory(self._undo_root_dir)
46 changes: 43 additions & 3 deletions spine_items/tool/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
from spine_engine.config import TOOL_OUTPUT_DIR
from spine_engine.project_item.project_item_resource import CmdLineArg, LabelArg, make_cmd_line_arg
from spine_engine.utils.helpers import ExecutionDirection, resolve_julia_executable, resolve_python_interpreter
from spinetoolbox.helpers import open_url
from spinetoolbox.helpers import open_url, select_root_directory
from spinetoolbox.mvcmodels.file_list_models import FileListModel
from ..commands import UpdateCmdLineArgsCommand, UpdateGroupIdCommand
from ..commands import UpdateCmdLineArgsCommand, UpdateGroupIdCommand, UpdateRootDirCommand
from ..db_writer_item_base import DBWriterItemBase
from ..models import ToolCommandLineArgsModel
from .commands import (
Expand Down Expand Up @@ -52,6 +52,7 @@ def __init__(
kill_completed_processes=False,
log_process_output=False,
group_id=None,
root_dir="",
):
"""
Args:
Expand All @@ -68,6 +69,7 @@ def __init__(
kill_completed_processes (bool): whether to kill completed persistent processes
log_process_output (bool): whether to log process output to a file
group_id (str, optional): execution group id
root_dir (str, optional): Root directory for the Tool Spec's program
"""
super().__init__(name, description, x, y, project)
self._toolbox = toolbox
Expand All @@ -83,6 +85,7 @@ def __init__(
f"<b>{specification_name}</b> but it was not found"
)
self._group_id = group_id
self._root_directory = root_dir
self._cmdline_args_model.args_updated.connect(self._push_update_cmd_line_args_command)
self._populate_cmdline_args_model()
self._input_file_model = FileListModel(header_label="Available resources", draggable=True)
Expand Down Expand Up @@ -122,6 +125,10 @@ def update_specification_icon(self):
def group_id(self):
return self._group_id

@property
def root_dir(self):
return self._root_directory

def _get_options_widget(self):
"""Returns a widget to specify the options for this tool.
It is embedded in the ui in ``self._update_tool_ui()``.
Expand Down Expand Up @@ -164,6 +171,8 @@ def make_signal_handler_dict(self):
self._update_remove_args_button_enabled
)
s[self._properties_ui.lineEdit_group_id.editingFinished] = self._set_group_id
s[self._properties_ui.lineEdit_root_directory.editingFinished] = self._set_root_directory
s[self._properties_ui.toolButton_browse_root_directory.clicked] = self._browse_root_directory
s[self._properties_ui.kill_consoles_check_box.clicked] = self._set_kill_completed_processes
s[self._properties_ui.log_process_output_check_box.clicked] = self._set_log_process_output
return s
Expand Down Expand Up @@ -211,12 +220,34 @@ def restore_selections(self):
self._properties_ui.treeView_cmdline_args.setModel(self._cmdline_args_model)
self._properties_ui.treeView_cmdline_args.expandAll()
self.update_execute_in_work_button()
self._properties_ui.label_jupyter.elided_mode = Qt.ElideMiddle
self._properties_ui.label_jupyter.elided_mode = Qt.TextElideMode.ElideMiddle
self._properties_ui.label_jupyter.hide()
self._update_tool_ui()
self._do_update_add_args_button_enabled()
self._do_update_remove_args_button_enabled()
self._properties_ui.lineEdit_group_id.setText(self._group_id)
self._properties_ui.lineEdit_root_directory.setText(self._root_directory)

@Slot(bool)
def _browse_root_directory(self, _=False):
"""Calls static method that shows a file browser for selecting a Python interpreter."""
select_root_directory(self._toolbox, self._properties_ui.lineEdit_root_directory)

@Slot()
def _set_root_directory(self):
"""Pushes a command to update root directory whenever the user edits the line edit."""
root_dir = self._properties_ui.lineEdit_root_directory.text()
if not root_dir:
root_dir = None
if self._root_directory == root_dir:
return
self._toolbox.undo_stack.push(UpdateRootDirCommand(self.name, root_dir, self._project))

def do_set_root_directory(self, root_dir):
"""Sets root directory."""
self._root_directory = root_dir
if self._active:
self._properties_ui.lineEdit_root_directory.setText(root_dir)

@Slot(bool)
def show_specification_window(self, _=True):
Expand Down Expand Up @@ -590,8 +621,15 @@ def item_dict(self):
d["log_process_output"] = self._log_process_output
if self._group_id:
d["group_id"] = self._group_id
if self._root_directory:
d["root_directory"] = self._root_directory
return d

@staticmethod
def item_dict_local_entries():
"""See base class."""
return [("root_directory",)]

@staticmethod
def from_dict(name, item_dict, toolbox, project):
"""See base class."""
Expand All @@ -604,6 +642,7 @@ def from_dict(name, item_dict, toolbox, project):
kill_completed_processes = item_dict.get("kill_completed_processes", False)
log_process_output = item_dict.get("log_process_output", False)
group_id = item_dict.get("group_id")
root_dir = item_dict.get("root_directory", "")
return Tool(
name,
description,
Expand All @@ -618,6 +657,7 @@ def from_dict(name, item_dict, toolbox, project):
kill_completed_processes,
log_process_output,
group_id,
root_dir,
)

def rename(self, new_name, rename_data_dir_message):
Expand Down
45 changes: 36 additions & 9 deletions spine_items/tool/ui/tool_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Ui_Form(object):
def setupUi(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
Form.resize(312, 603)
Form.resize(312, 612)
Form.setStyleSheet(u"QScrollArea { background: transparent; }\n"
"QScrollArea > QWidget > QWidget { background: transparent; }")
self.verticalLayout = QVBoxLayout(Form)
Expand All @@ -53,15 +53,16 @@ def setupUi(self, Form):
self.scrollArea.setWidgetResizable(True)
self.scrollAreaWidgetContents = QWidget()
self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents")
self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 312, 603))
self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 312, 612))
self.scrollAreaWidgetContents.setAutoFillBackground(False)
self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents)
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_9 = QHBoxLayout()
self.horizontalLayout_9.setSpacing(4)
self.horizontalLayout_9.setSpacing(6)
self.horizontalLayout_9.setObjectName(u"horizontalLayout_9")
self.horizontalLayout_9.setContentsMargins(-1, -1, -1, 6)
self.label_tool_specification = QLabel(self.scrollAreaWidgetContents)
self.label_tool_specification.setObjectName(u"label_tool_specification")
sizePolicy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
Expand Down Expand Up @@ -97,6 +98,7 @@ def setupUi(self, Form):

self.horizontalLayout_options = QHBoxLayout()
self.horizontalLayout_options.setObjectName(u"horizontalLayout_options")
self.horizontalLayout_options.setContentsMargins(-1, 0, -1, 6)

self.verticalLayout_3.addLayout(self.horizontalLayout_options)

Expand Down Expand Up @@ -168,13 +170,14 @@ def setupUi(self, Form):
self.frame.setFrameShadow(QFrame.Shadow.Raised)
self.verticalLayout_2 = QVBoxLayout(self.frame)
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.label_2 = QLabel(self.frame)
self.label_2.setObjectName(u"label_2")

self.verticalLayout_2.addWidget(self.label_2)
self.horizontalLayout.addWidget(self.label_2)

self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.radioButton_execute_in_source = QRadioButton(self.frame)
self.radioButton_execute_in_source.setObjectName(u"radioButton_execute_in_source")

Expand All @@ -189,6 +192,24 @@ def setupUi(self, Form):

self.verticalLayout_2.addLayout(self.horizontalLayout)

self.horizontalLayout_3 = QHBoxLayout()
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.lineEdit_root_directory = QLineEdit(self.frame)
self.lineEdit_root_directory.setObjectName(u"lineEdit_root_directory")

self.horizontalLayout_3.addWidget(self.lineEdit_root_directory)

self.toolButton_browse_root_directory = QToolButton(self.frame)
self.toolButton_browse_root_directory.setObjectName(u"toolButton_browse_root_directory")
icon3 = QIcon()
icon3.addFile(u":/icons/folder-open-solid.svg", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
self.toolButton_browse_root_directory.setIcon(icon3)

self.horizontalLayout_3.addWidget(self.toolButton_browse_root_directory)


self.verticalLayout_2.addLayout(self.horizontalLayout_3)

self.horizontalLayout_2 = QHBoxLayout()
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.label_group_id = QLabel(self.frame)
Expand Down Expand Up @@ -253,9 +274,13 @@ def setupUi(self, Form):
QWidget.setTabOrder(self.toolButton_remove_arg, self.treeView_input_files)
QWidget.setTabOrder(self.treeView_input_files, self.radioButton_execute_in_source)
QWidget.setTabOrder(self.radioButton_execute_in_source, self.radioButton_execute_in_work)
QWidget.setTabOrder(self.radioButton_execute_in_work, self.lineEdit_group_id)
QWidget.setTabOrder(self.radioButton_execute_in_work, self.lineEdit_root_directory)
QWidget.setTabOrder(self.lineEdit_root_directory, self.toolButton_browse_root_directory)
QWidget.setTabOrder(self.toolButton_browse_root_directory, self.lineEdit_group_id)
QWidget.setTabOrder(self.lineEdit_group_id, self.kill_consoles_check_box)
QWidget.setTabOrder(self.kill_consoles_check_box, self.log_process_output_check_box)
QWidget.setTabOrder(self.log_process_output_check_box, self.pushButton_tool_results)
QWidget.setTabOrder(self.pushButton_tool_results, self.scrollArea)

self.retranslateUi(Form)

Expand All @@ -280,8 +305,10 @@ def retranslateUi(self, Form):
#endif // QT_CONFIG(tooltip)
self.toolButton_add_file_path_arg.setText("")
self.label_2.setText(QCoreApplication.translate("Form", u"Execute in", None))
self.radioButton_execute_in_source.setText(QCoreApplication.translate("Form", u"Source directory", None))
self.radioButton_execute_in_work.setText(QCoreApplication.translate("Form", u"Work directory", None))
self.radioButton_execute_in_source.setText(QCoreApplication.translate("Form", u"Source dir", None))
self.radioButton_execute_in_work.setText(QCoreApplication.translate("Form", u"Work dir", None))
self.lineEdit_root_directory.setText("")
self.lineEdit_root_directory.setPlaceholderText(QCoreApplication.translate("Form", u"Root directory...", None))
self.label_group_id.setText(QCoreApplication.translate("Form", u"Reuse console id:", None))
#if QT_CONFIG(tooltip)
self.lineEdit_group_id.setToolTip(QCoreApplication.translate("Form", u"<html><head/><body><p>Enter an id for sharing a console with other Tools in this project. Leave empty to run this Tool in isolation.</p></body></html>", None))
Expand Down
74 changes: 61 additions & 13 deletions spine_items/tool/ui/tool_properties.ui
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<x>0</x>
<y>0</y>
<width>312</width>
<height>603</height>
<height>612</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -60,7 +60,7 @@ QScrollArea &gt; QWidget &gt; QWidget { background: transparent; }</string>
<x>0</x>
<y>0</y>
<width>312</width>
<height>603</height>
<height>612</height>
</rect>
</property>
<property name="autoFillBackground">
Expand All @@ -85,7 +85,10 @@ QScrollArea &gt; QWidget &gt; QWidget { background: transparent; }</string>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="spacing">
<number>4</number>
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_tool_specification">
Expand Down Expand Up @@ -136,7 +139,14 @@ QScrollArea &gt; QWidget &gt; QWidget { background: transparent; }</string>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_options"/>
<layout class="QHBoxLayout" name="horizontalLayout_options">
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter">
Expand Down Expand Up @@ -262,26 +272,38 @@ QScrollArea &gt; QWidget &gt; QWidget { background: transparent; }</string>
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Execute in</string>
</property>
</widget>
</item>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Execute in</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_execute_in_source">
<property name="text">
<string>Source directory</string>
<string>Source dir</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_execute_in_work">
<property name="text">
<string>Work directory</string>
<string>Work dir</string>
</property>
<property name="checked">
<bool>true</bool>
Expand All @@ -290,6 +312,28 @@ QScrollArea &gt; QWidget &gt; QWidget { background: transparent; }</string>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="lineEdit_root_directory">
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>Root directory...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton_browse_root_directory">
<property name="icon">
<iconset resource="../../ui/resources/resources_icons.qrc">
<normaloff>:/icons/folder-open-solid.svg</normaloff>:/icons/folder-open-solid.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
Expand Down Expand Up @@ -398,9 +442,13 @@ QScrollArea &gt; QWidget &gt; QWidget { background: transparent; }</string>
<tabstop>treeView_input_files</tabstop>
<tabstop>radioButton_execute_in_source</tabstop>
<tabstop>radioButton_execute_in_work</tabstop>
<tabstop>lineEdit_root_directory</tabstop>
<tabstop>toolButton_browse_root_directory</tabstop>
<tabstop>lineEdit_group_id</tabstop>
<tabstop>kill_consoles_check_box</tabstop>
<tabstop>log_process_output_check_box</tabstop>
<tabstop>pushButton_tool_results</tabstop>
<tabstop>scrollArea</tabstop>
</tabstops>
<resources>
<include location="../../ui/resources/resources_icons.qrc"/>
Expand Down
Loading

0 comments on commit 1587ea6

Please sign in to comment.