From 5ad21cbc53649cb3c9eeb9617d38066c49e8c804 Mon Sep 17 00:00:00 2001 From: Jaehun You Date: Fri, 14 Feb 2025 11:57:58 +0900 Subject: [PATCH 1/4] Implement widgets for builder info dialog See also: #322 --- iquip/apps/explorer.py | 60 +++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/iquip/apps/explorer.py b/iquip/apps/explorer.py index 8d46c60b..0eba15fa 100644 --- a/iquip/apps/explorer.py +++ b/iquip/apps/explorer.py @@ -7,7 +7,8 @@ import requests from PyQt5.QtCore import QObject, Qt, QThread, pyqtSlot, pyqtSignal from PyQt5.QtWidgets import ( - QInputDialog, QPushButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget + QComboBox, QDialog, QHBoxLayout, QLineEdit, QPushButton, QTreeWidget, QTreeWidgetItem, + QVBoxLayout, QWidget, ) import qiwis @@ -96,6 +97,40 @@ def run(self): self.fetched.emit(experimentList, self.widget) +class BuilderInfoDialog(QDialog): + """Dialog for setting builder info. + + There are two types of info. + experiment class: Target experiment class name. + tag: Additive tag for multiple builder apps. + """ + + def __init__(self, experimentInfos: List[str], parent: Optional[QWidget] = None): + """Extended. + + Args: + See thread.ExperimentInfoThread.fetched signal. + """ + super().__init__(parent=parent) + # widgets + self.comboBox = QComboBox(self) + self.comboBox.addItems(experimentInfos) + self.lineEdit = QLineEdit(self) + self.lineEdit.setPlaceholderText("Tag") + self.okButton = QPushButton("OK", self) + self.okButton.clicked.connect(self.accept) + self.cancelButton = QPushButton("Cancel", self) + self.cancelButton.clicked.connect(self.reject) + # layout + buttonLayout = QHBoxLayout() + buttonLayout.addWidget(self.okButton) + buttonLayout.addWidget(self.cancelButton) + layout = QVBoxLayout(self) + layout.addWidget(self.comboBox) + layout.addWidget(self.lineEdit) + layout.addLayout(buttonLayout) + + class ExplorerApp(qiwis.BaseApp): """App for showing the experiment list and opening an experiment. @@ -216,31 +251,24 @@ def fetchExperimentInfo(self, item: QTreeWidgetItem): self.proxy_port, self ) - self.experimentInfoThread.fetched.connect(self.selectExperimentCls, + self.experimentInfoThread.fetched.connect(self.openBuilderInfoDialog, type=Qt.QueuedConnection) self.experimentInfoThread.finished.connect(self.experimentInfoThread.deleteLater) self.experimentInfoThread.start() @pyqtSlot(dict) - def selectExperimentCls(self, experimentInfos: Dict[str, ExperimentInfo]): - """Selects an experiment class to be opened as a builder. + def openBuilderInfoDialog(self, experimentInfos: Dict[str, ExperimentInfo]): + """Opens a dialog for setting builder info. - After selected, self.openBuilder() is called to open a builder. - - If there is only one class, it is selected automatically without showing a QInputDialog. - If no class is selected, nothing happens. + If the dialog is confirmed, self.openBuilder() is called with the configured builder info. + Otherwise, nothing happens. Args: See thread.ExperimentInfoThread.fetched signal. """ - if len(experimentInfos) > 1: - cls, ok = QInputDialog().getItem(None, "Select an experiment class", - "Experiment class: ", experimentInfos, editable=False) - if not ok: - return - else: - cls = next(iter(experimentInfos)) - self.openBuilder(cls, experimentInfos[cls]) + dialog = BuilderInfoDialog(experimentInfos) + if dialog.exec_(): + pass def openBuilder( self, From ca4f5cb7b621a9bbbf7cef1781974947279ac650 Mon Sep 17 00:00:00 2001 From: Jaehun You Date: Fri, 14 Feb 2025 14:16:19 +0900 Subject: [PATCH 2/4] Open builder with configured builder info See also: #322 --- iquip/apps/explorer.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/iquip/apps/explorer.py b/iquip/apps/explorer.py index 0eba15fa..d72308d3 100644 --- a/iquip/apps/explorer.py +++ b/iquip/apps/explorer.py @@ -101,7 +101,7 @@ class BuilderInfoDialog(QDialog): """Dialog for setting builder info. There are two types of info. - experiment class: Target experiment class name. + cls: Target experiment class name. tag: Additive tag for multiple builder apps. """ @@ -130,6 +130,10 @@ def __init__(self, experimentInfos: List[str], parent: Optional[QWidget] = None) layout.addWidget(self.lineEdit) layout.addLayout(buttonLayout) + def getBuilderInfo(self) -> Tuple[str, str]: + """Returns the configured builder info""" + return self.comboBox.currentText(), self.lineEdit.text() + class ExplorerApp(qiwis.BaseApp): """App for showing the experiment list and opening an experiment. @@ -268,30 +272,30 @@ def openBuilderInfoDialog(self, experimentInfos: Dict[str, ExperimentInfo]): """ dialog = BuilderInfoDialog(experimentInfos) if dialog.exec_(): - pass + cls, tag = dialog.getBuilderInfo() + self.openBuilder(cls, tag, experimentInfos[cls]) - def openBuilder( - self, - experimentClsName: str, - experimentInfo: ExperimentInfo - ): + + def openBuilder(self, cls: str, tag: str, experimentInfo: ExperimentInfo): """Opens the experiment builder with its information. The experiment is guaranteed to be the correct experiment file. Args: - experimentClsName: The class name of the experiment. + cls, tag: See BuilderInfoDialog. experimentInfo: The experiment information. See protocols.ExperimentInfo. """ + if tag: + tag = f"({tag})" self.qiwiscall.createApp( - name=f"builder - {self.selectedExperimentPath}:{experimentClsName}", + name=f"builder {tag} - {self.selectedExperimentPath}:{cls}", info=qiwis.AppInfo( module="iquip.apps.builder", cls="BuilderApp", pos="center", args={ "experimentPath": self.selectedExperimentPath, - "experimentClsName": experimentClsName, + "experimentClsName": cls, "experimentInfo": experimentInfo } ) From 8bb13a602c5e09cf3903798b17c8a7f28c555971 Mon Sep 17 00:00:00 2001 From: Jaehun You Date: Fri, 14 Feb 2025 14:34:14 +0900 Subject: [PATCH 3/4] Fix Pylint and unittest warnings See also: #322 --- iquip/apps/explorer.py | 6 +++++- tests/test_explorer.py | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/iquip/apps/explorer.py b/iquip/apps/explorer.py index d72308d3..4a3c0ceb 100644 --- a/iquip/apps/explorer.py +++ b/iquip/apps/explorer.py @@ -131,7 +131,11 @@ def __init__(self, experimentInfos: List[str], parent: Optional[QWidget] = None) layout.addLayout(buttonLayout) def getBuilderInfo(self) -> Tuple[str, str]: - """Returns the configured builder info""" + """Returns the configured builder info. + + Returns: + See BuilderInfoDialog. + """ return self.comboBox.currentText(), self.lineEdit.text() diff --git a/tests/test_explorer.py b/tests/test_explorer.py index 746617be..7d17ff85 100644 --- a/tests/test_explorer.py +++ b/tests/test_explorer.py @@ -200,16 +200,16 @@ def test_open_builder(self): app.selectedExperimentPath = "experimentPath" experimentInfo = protocols.ExperimentInfo("name", {"arg0": "value0"}) with mock.patch.object(app, "qiwiscall") as mocked_qiwiscall: - app.openBuilder("experimentClsName", experimentInfo) + app.openBuilder("cls", "tag", experimentInfo) mocked_qiwiscall.createApp.assert_called_with( - name="builder - experimentPath:experimentClsName", + name="builder (tag) - experimentPath:cls", info=qiwis.AppInfo( module="iquip.apps.builder", cls="BuilderApp", pos="center", args={ "experimentPath": "experimentPath", - "experimentClsName": "experimentClsName", + "experimentClsName": "cls", "experimentInfo": experimentInfo } ) From c8db9ec278c23ceccd442f1c2d4a35a81da597e4 Mon Sep 17 00:00:00 2001 From: Jaehun You Date: Fri, 14 Feb 2025 17:47:23 +0900 Subject: [PATCH 4/4] Apply reviews See also: #322 --- iquip/apps/explorer.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/iquip/apps/explorer.py b/iquip/apps/explorer.py index 4a3c0ceb..a088d4f0 100644 --- a/iquip/apps/explorer.py +++ b/iquip/apps/explorer.py @@ -2,7 +2,7 @@ import posixpath import logging -from typing import Dict, List, Optional, Tuple, Union +from typing import Dict, Iterable, List, Optional, Tuple, Union import requests from PyQt5.QtCore import QObject, Qt, QThread, pyqtSlot, pyqtSignal @@ -101,11 +101,11 @@ class BuilderInfoDialog(QDialog): """Dialog for setting builder info. There are two types of info. - cls: Target experiment class name. + clsName: Target experiment class name. tag: Additive tag for multiple builder apps. """ - def __init__(self, experimentInfos: List[str], parent: Optional[QWidget] = None): + def __init__(self, clsNames: Iterable[str], parent: Optional[QWidget] = None): """Extended. Args: @@ -114,7 +114,7 @@ def __init__(self, experimentInfos: List[str], parent: Optional[QWidget] = None) super().__init__(parent=parent) # widgets self.comboBox = QComboBox(self) - self.comboBox.addItems(experimentInfos) + self.comboBox.addItems(clsNames) self.lineEdit = QLineEdit(self) self.lineEdit.setPlaceholderText("Tag") self.okButton = QPushButton("OK", self) @@ -134,7 +134,7 @@ def getBuilderInfo(self) -> Tuple[str, str]: """Returns the configured builder info. Returns: - See BuilderInfoDialog. + (clsName, tag): See BuilderInfoDialog. """ return self.comboBox.currentText(), self.lineEdit.text() @@ -276,30 +276,30 @@ def openBuilderInfoDialog(self, experimentInfos: Dict[str, ExperimentInfo]): """ dialog = BuilderInfoDialog(experimentInfos) if dialog.exec_(): - cls, tag = dialog.getBuilderInfo() - self.openBuilder(cls, tag, experimentInfos[cls]) + clsName, tag = dialog.getBuilderInfo() + self.openBuilder(clsName, tag, experimentInfos[clsName]) - def openBuilder(self, cls: str, tag: str, experimentInfo: ExperimentInfo): + def openBuilder(self, clsName: str, tag: str, experimentInfo: ExperimentInfo): """Opens the experiment builder with its information. The experiment is guaranteed to be the correct experiment file. Args: - cls, tag: See BuilderInfoDialog. + clsName, tag: See BuilderInfoDialog. experimentInfo: The experiment information. See protocols.ExperimentInfo. """ if tag: - tag = f"({tag})" + tag = f" ({tag})" self.qiwiscall.createApp( - name=f"builder {tag} - {self.selectedExperimentPath}:{cls}", + name=f"builder{tag} - {self.selectedExperimentPath}:{clsName}", info=qiwis.AppInfo( module="iquip.apps.builder", cls="BuilderApp", pos="center", args={ "experimentPath": self.selectedExperimentPath, - "experimentClsName": cls, + "experimentClsName": clsName, "experimentInfo": experimentInfo } )