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

feat(data_hierarchy): implement changes for data type row #351

Merged
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
1 change: 1 addition & 0 deletions .codespellignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
aline
ore
jkd
te
6 changes: 3 additions & 3 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ name: PyTest&Coverage
on:
push:
branches:
- main
- main
pull_request:
branches:
- main
- main

jobs:
build:
Expand All @@ -30,7 +30,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -r requirements-linux.txt
pip install pytest pytest-asyncio pytest-qt pytest-qt-app pytest-mock coverage aiohttp
pip install typing_extensions pytest pytest-asyncio pytest-qt pytest-qt-app pytest-mock coverage aiohttp
- name: Test with pytest
run: |
mkdir -p htmlcov
Expand Down
3 changes: 2 additions & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ignore=CVS

# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=data_hierarchy_editor_dialog_base.py,create_type_dialog_base.py,terminology_lookup_dialog_base.py,completed_upload_task.py,completed_uploads_base.py,config_dialog_base.py,edit_metadata_dialog_base.py,main_dialog_base.py,primitive_compound_controlled_frame_base.py,project_item_frame_base.py,upload_config_dialog_base.py,upload_widget_base.py,edit_metadata_summary_dialog_base.py
ignore-patterns=data_hierarchy_editor_dialog_base.py,create_type_dialog_base.py,terminology_lookup_dialog_base.py,completed_upload_task.py,completed_uploads_base.py,config_dialog_base.py,edit_metadata_dialog_base.py,main_dialog_base.py,primitive_compound_controlled_frame_base.py,project_item_frame_base.py,upload_config_dialog_base.py,upload_widget_base.py,edit_metadata_summary_dialog_base.py,type_dialog_base.py

# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
Expand Down Expand Up @@ -423,6 +423,7 @@ valid-metaclass-classmethod-first-arg=mcs

# Maximum number of arguments for function / method
max-args=10 #Steffen's change
max-positional-arguments=10

# Maximum number of attributes for a class (see R0902).
max-attributes=25
Expand Down
158 changes: 80 additions & 78 deletions pasta_eln/GUI/data_hierarchy/create_type_dialog.py
Original file line number Diff line number Diff line change
@@ -1,115 +1,117 @@
""" CreateTypeDialog used for the create type dialog """
"""A dialog for creating a new data type within the application."""
# PASTA-ELN and all its sub-parts are covered by the MIT license.
#
# Copyright (c) 2023
# Copyright (c) 2024
#
# Author: Jithu Murugan
# Filename: create_type_dialog.py
#
# You should have received a copy of the license with this file. Please refer the license file for more information.

import logging
from collections.abc import Callable
from typing import Any
from typing import Any, Callable

from PySide6 import QtCore
from PySide6.QtCore import QRegularExpression
from PySide6.QtGui import QRegularExpressionValidator
from PySide6.QtWidgets import QDialog
from PySide6 import QtWidgets
from PySide6.QtWidgets import QMessageBox

from pasta_eln.GUI.data_hierarchy.create_type_dialog_base import Ui_CreateTypeDialogBase
from pasta_eln.GUI.data_hierarchy.generic_exception import GenericException
from pasta_eln.GUI.data_hierarchy.type_dialog import TypeDialog
from pasta_eln.GUI.data_hierarchy.utility_functions import generate_data_hierarchy_type, show_message


class CreateTypeDialog(Ui_CreateTypeDialogBase):
"""
Abstracted dialog for the create type
class CreateTypeDialog(TypeDialog):
"""
A dialog for creating a new data type within the application.

def __new__(cls, *_: Any, **__: Any) -> Any:
"""
Instantiates the create type dialog
"""
return super(CreateTypeDialog, cls).__new__(cls)
This class extends the TypeDialog to provide functionality for adding new data types.
It initializes the dialog with specific UI elements and behavior tailored for creating new types.

Args:
accepted_callback (Callable[[], None]): A callback function to be executed when the action is accepted.
rejected_callback (Callable[[], None]): A callback function to be executed when the action is rejected.
"""

def __init__(self,
accepted_callback: Callable[[], None],
rejected_callback: Callable[[], None]) -> None:
rejected_callback: Callable[[], None]):
"""
Initializes the create type dialog
Initializes a new instance of the class with specified callback functions.

This constructor sets up the instance by initializing the parent class and configuring the logger.
It also initializes an empty dictionary for data hierarchy types and sets the window title for the dialog.

Args:
accepted_callback (Callable): Accepted button parent callback.
rejected_callback (Callable): Rejected button parent callback.
accepted_callback (Callable[[], None]): A callback function to be executed when the action is accepted.
rejected_callback (Callable[[], None]): A callback function to be executed when the action is rejected.
"""
super().__init__(accepted_callback, rejected_callback)
self.logger = logging.getLogger(f"{__name__}.{self.__class__.__name__}")
self.next_struct_level: str | None = ""
self.instance = QDialog()
super().setupUi(self.instance)
# Restricts the title input to allow anything except x or space
# as the first character which is reserved for structural level
self.titleLineEdit.setValidator(QRegularExpressionValidator(QRegularExpression("^[^ Ax].*")))
self.setup_slots(accepted_callback, rejected_callback)

def setup_slots(self,
accepted_callback: Callable[[], None],
rejected_callback: Callable[[], None]) -> None:
"""
Sets up the slots for the dialog
Args:
accepted_callback (Callable): Accepted button parent callback.
rejected_callback (Callable): Rejected button parent callback.

Returns: None
self.data_hierarchy_types: dict[str, Any] = {}
self.instance.setWindowTitle("Create new type")

def accepted_callback(self) -> None:
"""
self.buttonBox.accepted.connect(accepted_callback)
self.buttonBox.rejected.connect(rejected_callback)
self.structuralLevelCheckBox.stateChanged.connect(self.structural_level_checkbox_callback)
Handles the acceptance of a new data type by validating input and updating the data hierarchy.

def structural_level_checkbox_callback(self) -> None:
"""
Callback invoked when the state changes for structuralLevelCheckBox
This method checks if the type information is valid and whether the data type already exists in the hierarchy.
If the type is valid and does not exist, it logs the creation of the new type, updates the data hierarchy,
and closes the dialog. If the type already exists, it shows a warning message. If the data hierarchy types
are null, it logs an error and raises an exception.

Returns: Nothing
Raises:
GenericException: If the data hierarchy types are null.
"""
if self.structuralLevelCheckBox.isChecked():
self.titleLineEdit.setText(self.next_struct_level.replace("x", "Structure level ")
if self.next_struct_level else "")
self.titleLineEdit.setDisabled(True)
if not self.validate_type_info():
return
if self.data_hierarchy_types is None:
self.logger.error("Null data_hierarchy_types, erroneous app state")
raise GenericException("Null data_hierarchy_types, erroneous app state", {})
if self.type_info.datatype in self.data_hierarchy_types:
self.logger.error(
"Type (datatype: {%s} displayed title: {%s}) cannot be added since it exists in DB already....",
self.type_info.datatype,
self.type_info.title
)
show_message(
f"Type (datatype: {self.type_info.datatype} displayed title: {self.type_info.title}) cannot be added since it exists in DB already....",
QMessageBox.Icon.Warning)
else:
self.titleLineEdit.clear()
self.titleLineEdit.setDisabled(False)

def show(self) -> None:
self.logger.info("User created a new type and added "
"to the data_hierarchy document: Datatype: {%s}, Displayed Title: {%s}",
self.type_info.datatype,
self.type_info.title)
if isinstance(self.type_info.datatype, str):
self.data_hierarchy_types[self.type_info.datatype] = generate_data_hierarchy_type(self.type_info)
self.instance.close()
self.accepted_callback_parent()

def rejected_callback(self) -> None:
"""
Displays the dialog
Calls the parent rejection callback method.

Returns: None

"""
self.instance.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
self.instance.show()
This method is intended to handle the rejection of a dialog or action by invoking
the corresponding parent method that manages the rejection behavior. It does not
perform any additional logic or checks.
"""
self.rejected_callback_parent()

def clear_ui(self) -> None:
def set_data_hierarchy_types(self, data_hierarchy_types: dict[str, Any]) -> None:
"""
Clear the Dialog UI
Sets the data hierarchy types for the instance.

Returns: Nothing
This method updates the internal state of the instance by assigning the provided dictionary of data hierarchy types.
It allows the instance to manage and utilize the specified types in its operations.

Args:
self: The instance of the class.
data_hierarchy_types (dict[str, Any]): A dictionary containing data hierarchy types to be set.
"""
self.displayedTitleLineEdit.clear()
self.titleLineEdit.clear()
self.structuralLevelCheckBox.setChecked(False)
self.data_hierarchy_types = data_hierarchy_types

def set_structural_level_title(self,
structural_level: str | None) -> None:
"""
Set the next possible structural type level title

Args:
structural_level (str): Passed in structural level of the format (x0, x1, x2 ...)
if __name__ == "__main__":
import sys

Returns: Nothing

"""
self.logger.info("Next structural level set: {%s}...", structural_level)
self.next_struct_level = structural_level
app = QtWidgets.QApplication(sys.argv)
ui = CreateTypeDialog(lambda: None, lambda: None)
ui.show()
sys.exit(app.exec())
91 changes: 0 additions & 91 deletions pasta_eln/GUI/data_hierarchy/create_type_dialog_base.py

This file was deleted.

Loading
Loading