Skip to content

Commit

Permalink
refactored
Browse files Browse the repository at this point in the history
  • Loading branch information
RabiyaF committed Sep 3, 2024
1 parent d0045e2 commit 8ea0205
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 114 deletions.
107 changes: 42 additions & 65 deletions rascal2/dialogs/project_dialog.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
from typing import Literal

from PyQt6 import QtCore, QtGui, QtWidgets

Expand Down Expand Up @@ -38,11 +37,10 @@ def __init__(self, parent):
self.setModal(True)
self.setMinimumWidth(700)

self.name_error = False
self.folder_error = False
self.folder_path = ""

self.create_buttons()
self.create_labels()
self.create_form()
self.add_widgets_to_layout()

def add_widgets_to_layout(self) -> None:
Expand Down Expand Up @@ -79,11 +77,11 @@ def add_widgets_to_layout(self) -> None:

self.setLayout(self.main_layout)

def create_labels(self) -> None:
def create_form(self) -> None:
"""
Create labels.
Create form widgets.
"""
# Project name labels
# Project name widgets
self.project_name_label = QtWidgets.QLabel("Project Name:", self)
self.project_name_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeft)
self.project_name_label.setStyleSheet(self._label_style)
Expand All @@ -95,7 +93,7 @@ def create_labels(self) -> None:
self.project_name_error.setStyleSheet(self._error_style)
self.project_name_error.hide()

# Project folder labels
# Project folder widgets
self.project_folder_label = QtWidgets.QLabel("Project Folder:", self)
self.project_folder_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeft)
self.project_folder_label.setStyleSheet(self._label_style)
Expand Down Expand Up @@ -131,79 +129,58 @@ def cancel_project_creation(self) -> None:
"""
Cancel project creation.
"""
self.close() if self.parent().new_project_action_called else self.parent().toggleView()
self.reset_variables()

def reset_variables(self) -> None:
"""
Reset variables.
"""
self.close() if self.parent().toolbar.isEnabled() else self.parent().toggleView()
self.project_folder.setText("")
self.project_name.setText("")
self.name_error = False
self.folder_error = False

def open_folder_selector(self) -> None:
"""
Open folder selector.
"""
folder_path = QtWidgets.QFileDialog.getExistingDirectory(self, "Select Folder")
if folder_path:
files_in_folder = list(filter(lambda x: x[0] != ".", os.listdir(folder_path)))
if files_in_folder:
self.handle_error("folder")
else:
self.handle_success("folder")
self.project_folder.setText(folder_path)

def handle_error(self, tag: Literal["name", "folder"]) -> None:
"""
Display error msgs.
Parameters
----------
tag: Literal["name", "folder"]
Specifies whether to show the error
for the project name or folder.
"""
getattr(self, "project_" + tag).setStyleSheet(self._line_edit_error_style)
getattr(self, "project_" + tag + "_error").show()
setattr(self, tag + "_error", True)
self.folder_path = QtWidgets.QFileDialog.getExistingDirectory(self, "Select Folder")
if self.folder_path:
self.verify_folder()

def handle_success(self, tag: Literal["name", "folder"]) -> None:
def verify_folder(self) -> None:
"""
Hide error msgs.
Parameters
----------
tag: Literal["name", "folder"]
Specifies whether to clear the error
for the project name or folder.
Verify the project folder.
"""
getattr(self, "project_" + tag).setStyleSheet("")
getattr(self, "project_" + tag + "_error").hide()
setattr(self, tag + "_error", False)
error = False
if self.folder_path:
files_in_folder = [file for file in os.listdir(self.folder_path) if not file.startswith(".")]
if files_in_folder:
error = True
elif self.project_folder.text() == "":
error = True

if error:
self.project_folder.setStyleSheet(self._line_edit_error_style)
self.project_folder_error.show()
self.project_folder.setText("")
else:
self.project_folder.setStyleSheet("")
self.project_folder_error.hide()
self.project_folder.setText(self.folder_path)

def verify_inputs(self, tag: Literal["name", "folder"]) -> None:
def verify_name(self) -> None:
"""
Verify inputs.
Parameters
----------
tag: Literal["name", "folder"]
Specifies whether the input verification
is for the project name or folder.
Verify the project name.
"""
if getattr(self, "project_" + tag).text() == "":
self.handle_error(tag)
if self.project_name.text() == "":
self.project_name.setStyleSheet(self._line_edit_error_style)
self.project_name_error.show()
else:
self.handle_success(tag)
self.project_name.setStyleSheet("")
self.project_name_error.hide()

def create_project(self) -> None:
"""
Create project if inputs verified.
"""
self.verify_inputs("name")
self.verify_inputs("folder")
if not self.name_error and not self.folder_error:
self.parent().createNewProject()
self.verify_name()
self.verify_folder()
if self.project_name_error.isHidden() and self.project_folder_error.isHidden():
self.parent().presenter.createProject(self.project_name.text(), self.project_folder.text())
if not self.parent().toolbar.isEnabled():
self.parent().toolbar.setEnabled(True)
self.close()
1 change: 1 addition & 0 deletions rascal2/ui/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def createProject(self, name: str, save_path: str):
"""

self.model.createProject(name, save_path)
self.view.setWindowTitle(name)
# TODO if the view's central widget is the startup one then setup MDI else reset the widgets.
self.view.init_settings_and_log(save_path)
self.view.setupMDI()
12 changes: 0 additions & 12 deletions rascal2/ui/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from rascal2.dialogs.project_dialog import ProjectDialog
from rascal2.widgets.startup_widget import StartUpWidget


from .presenter import MainWindowPresenter

MAIN_WINDOW_TITLE = "RasCAL-2"
Expand Down Expand Up @@ -48,7 +47,6 @@ def __init__(self):

def showProjectDialog(self):
"""Shows the dialog to create a new rascal project"""
self.new_project_action_called = True
self.project_dlg = ProjectDialog(self)
self.project_dlg.show()

Expand All @@ -57,23 +55,13 @@ def toggleView(self):
self.startup_dlg.hide() if self.startup_dlg.isVisible() else self.startup_dlg.show()
self.project_dlg.hide() if self.project_dlg.isVisible() else self.project_dlg.show()

def createNewProject(self):
"""Creates a new rascal project"""
self.setWindowTitle(MAIN_WINDOW_TITLE + " - " + self.project_dlg.project_name.text())
if not self.new_project_action_called:
self.startup_dlg.close()
self.project_dlg.close()
self.toolbar.setEnabled(True)
self.setupMDI()

def createActions(self):
"""Creates the menu and toolbar actions"""

self.new_project_action = QtGui.QAction("&New", self)
self.new_project_action.setStatusTip("Create a new project")
self.new_project_action.setIcon(QtGui.QIcon(path_for("new-project.png")))
self.new_project_action.triggered.connect(self.showProjectDialog)
self.new_project_action_called = False
self.new_project_action.setShortcut(QtGui.QKeySequence.StandardKey.New)

self.open_project_action = QtGui.QAction("&Open", self)
Expand Down
2 changes: 1 addition & 1 deletion rascal2/widgets/startup_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ def create_labels(self) -> None:
self.import_project_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.import_project_label.setStyleSheet(self._label_style)

self.import_r1_label = QtWidgets.QLabel("Import R1\nProject", self)
self.import_r1_label = QtWidgets.QLabel("Import RasCAL-1\nProject", self)
self.import_r1_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.import_r1_label.setStyleSheet(self._label_style)
70 changes: 37 additions & 33 deletions tests/test_dialogs.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
from unittest.mock import patch

import pytest
from PyQt6 import QtCore, QtTest, QtWidgets
from PyQt6 import QtCore, QtWidgets

from rascal2.dialogs.project_dialog import ProjectDialog


class MockPresenter(QtWidgets.QMainWindow):
def createProject(self, name: str, folder: str):
pass


class MockParentWindow(QtWidgets.QMainWindow):
new_project_action_called = False
def __init__(self):
super().__init__()
self.presenter = MockPresenter()
self.toolbar = self.addToolBar("ToolBar")
self.toolbar.setEnabled(False)

def toggleView(self):
pass
Expand Down Expand Up @@ -53,55 +62,56 @@ def test_project_dialog_initial_state(setup_project_dialog_widget):
assert project_dialog.project_folder_error.isHidden()
assert project_dialog.project_folder.isReadOnly()

assert not project_dialog.name_error
assert not project_dialog.folder_error


def test_inline_error_msgs(setup_project_dialog_widget):
@patch("os.listdir")
def test_inline_error_msgs(mock_listdir, setup_project_dialog_widget):
"""
Tests the project name and folder inline errors.
"""
project_dialog, _ = setup_project_dialog_widget

# tests the project name and folder line edit errors displayed.
QtTest.QTest.mouseClick(project_dialog.create_button, QtCore.Qt.MouseButton.LeftButton)
mock_listdir.return_value = [".hiddenfile"]

# tests the project name and folder inline errors.
project_dialog.create_button.click()

assert not project_dialog.project_name_error.isHidden()
assert project_dialog.name_error
assert not project_dialog.project_folder_error.isHidden()
assert project_dialog.folder_error

# tests the project name line edit error displayed.
# tests the project name inline error.
project_dialog.project_folder.setText("test-folder")
QtTest.QTest.mouseClick(project_dialog.create_button, QtCore.Qt.MouseButton.LeftButton)
project_dialog.folder_path = "test-folder"
project_dialog.create_button.click()

assert not project_dialog.project_name_error.isHidden()
assert project_dialog.name_error
assert project_dialog.project_folder_error.isHidden()
assert not project_dialog.folder_error

# tests the project folder line edit error displayed.
# tests the project folder inline error.
project_dialog.project_name.setText("test-name")
project_dialog.project_folder.setText("")
QtTest.QTest.mouseClick(project_dialog.create_button, QtCore.Qt.MouseButton.LeftButton)
project_dialog.folder_path = ""
project_dialog.create_button.click()

assert project_dialog.project_name_error.isHidden()
assert not project_dialog.name_error
assert not project_dialog.project_folder_error.isHidden()
assert project_dialog.folder_error


@patch.object(MockParentWindow, "createNewProject")
def test_create_button(mock_create_new_project, setup_project_dialog_widget):
@patch("os.listdir")
@patch.object(MockPresenter, "createProject")
def test_create_button(mock_create_project, mock_listdir, setup_project_dialog_widget):
"""
Tests create button on the ProjectDialog class.
"""
project_dialog, _ = setup_project_dialog_widget

mock_listdir.return_value = []

project_dialog.project_name.setText("test-name")
project_dialog.project_folder.setText("test-folder")
QtTest.QTest.mouseClick(project_dialog.create_button, QtCore.Qt.MouseButton.LeftButton)
mock_create_new_project.assert_called_once()
project_dialog.folder_path = "test-folder"
project_dialog.create_button.click()
mock_create_project.assert_called_once()
assert project_dialog.parent().toolbar.isEnabled()


@patch.object(MockParentWindow, "toggleView")
Expand All @@ -112,18 +122,14 @@ def test_cancel_button(mock_toggle_view, setup_project_dialog_widget):
project_dialog, _ = setup_project_dialog_widget

project_dialog.project_name.setText("test-name")
project_dialog.name_error = True
project_dialog.project_folder.setText("test-folder")
project_dialog.folder_error = True

QtTest.QTest.mouseClick(project_dialog.cancel_button, QtCore.Qt.MouseButton.LeftButton)
project_dialog.cancel_button.click()

mock_toggle_view.assert_called_once()

assert project_dialog.project_name.text() == ""
assert not project_dialog.name_error
assert project_dialog.project_folder.text() == ""
assert not project_dialog.folder_error


@patch("os.listdir")
Expand All @@ -138,17 +144,15 @@ def test_browse_button(mock_get_existing_directory, mock_listdir, setup_project_
mock_get_existing_directory.return_value = "/test/folder/path"
mock_listdir.return_value = [".hiddenfile"]

QtTest.QTest.mouseClick(project_dialog.browse_button, QtCore.Qt.MouseButton.LeftButton)
project_dialog.browse_button.click()

assert project_dialog.project_folder.text() == "/test/folder/path"
assert not project_dialog.folder_error

project_dialog.reset_variables()
assert project_dialog.project_folder_error.isHidden()

# When a non empty folder is selected.
mock_listdir.return_value = [".hiddenfile", "testfile"]

QtTest.QTest.mouseClick(project_dialog.browse_button, QtCore.Qt.MouseButton.LeftButton)
project_dialog.browse_button.click()

assert project_dialog.project_folder.text() == ""
assert project_dialog.folder_error
assert not project_dialog.project_folder_error.isHidden()
5 changes: 2 additions & 3 deletions tests/test_widgets.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from unittest.mock import patch

import pytest
from PyQt6 import QtCore, QtTest

from rascal2.widgets.startup_widget import StartUpWidget
from tests.test_dialogs import MockParentWindow
Expand All @@ -25,7 +24,7 @@ def test_startup_widget_initial_state(setup_startup_widget):

assert startup_widget.new_project_label.text() == "New\nProject"
assert startup_widget.import_project_label.text() == "Import Existing\nProject"
assert startup_widget.import_r1_label.text() == "Import R1\nProject"
assert startup_widget.import_r1_label.text() == "Import RasCAL-1\nProject"


@patch.object(MockParentWindow, "toggleView")
Expand All @@ -34,5 +33,5 @@ def test_toggle_view_called(mock, setup_startup_widget):
Tests the toggleView method is called once.
"""
startup_widget, _ = setup_startup_widget
QtTest.QTest.mouseClick(startup_widget.new_project_button, QtCore.Qt.MouseButton.LeftButton)
startup_widget.new_project_button.click()
mock.assert_called_once()

0 comments on commit 8ea0205

Please sign in to comment.