Skip to content

Commit

Permalink
Merge pull request #551 from SPF-OST/548-open-recent-projects
Browse files Browse the repository at this point in the history
Added open recent functionality
  • Loading branch information
ahobeost authored Oct 15, 2024
2 parents a91e19c + cbf9c8c commit c288975
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 15 deletions.
10 changes: 5 additions & 5 deletions trnsysGUI/diagram/Editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def __init__(self, parent, projectFolder, jsonPath, loadValue, logger):
self.projectFolder = projectFolder

self.diagramName = os.path.split(self.projectFolder)[-1] + ".json"
self.diagramPath = os.path.join(self.projectFolder, self.diagramName)
self.saveAsPath = _pl.Path()
self.idGen = IdGenerator()

Expand Down Expand Up @@ -809,9 +810,8 @@ def save(self, showWarning=True):
"""
self.diagramName = os.path.split(self.projectFolder)[-1] + ".json"
diagramPath = os.path.join(self.projectFolder, self.diagramName)

if os.path.isfile(diagramPath) and showWarning:
if os.path.isfile(self.diagramPath) and showWarning:
qmb = _qtw.QMessageBox(self)
qmb.setText("Warning: " + "This diagram name exists already. Do you want to overwrite or cancel?")
qmb.setStandardButtons(_qtw.QMessageBox.Save | _qtw.QMessageBox.Cancel)
Expand All @@ -823,13 +823,13 @@ def save(self, showWarning=True):
return

self.logger.info("Overwriting")
self.encodeDiagram(diagramPath)
self.encodeDiagram(self.diagramPath)

self.encodeDiagram(diagramPath)
self.encodeDiagram(self.diagramPath)
if showWarning:
msgb = _qtw.QMessageBox()
msgb.setWindowTitle("Saved successfully")
msgb.setText("Saved diagram at " + diagramPath)
msgb.setText("Saved diagram at " + self.diagramPath)
msgb.setStandardButtons(_qtw.QMessageBox.Ok)
msgb.setDefaultButton(_qtw.QMessageBox.Ok)
msgb.exec()
Expand Down
26 changes: 26 additions & 0 deletions trnsysGUI/mainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from trnsysGUI.MassFlowVisualizer import MassFlowVisualizer
from trnsysGUI.ProcessMain import ProcessMain
from trnsysGUI.RunMain import RunMain
from trnsysGUI.userSettings import UserSettings
from trnsysGUI.common import cancelled as _ccl
from trnsysGUI.diagram import Editor as _de
from trnsysGUI.storageTank.widget import StorageTank
Expand Down Expand Up @@ -130,6 +131,10 @@ def __init__(self, logger, project: _prj.Project, parent=None):
fileMenuOpenAction.setShortcut("Ctrl+o")
self.fileMenu.addAction(fileMenuOpenAction)

fileMenuOpenRecentAction = _qtw.QAction("Open Recent", self)
fileMenuOpenRecentAction.triggered.connect(self.openRecentFile)
self.fileMenu.addAction(fileMenuOpenRecentAction)

fileMenuSaveAction = _qtw.QAction("Save", self)
fileMenuSaveAction.triggered.connect(self.saveDia)
fileMenuSaveAction.setShortcut("Ctrl+s")
Expand Down Expand Up @@ -256,6 +261,7 @@ def newDia(self):
createProjectMaybeCancelled = _prj.getCreateProject(startingDirectoryPath)
if _ccl.isCancelled(createProjectMaybeCancelled):
return
UserSettings.setRecentProjectJsonPath(self.editor.diagramPath)
createProject = _ccl.value(createProjectMaybeCancelled)

self._resetEditor(createProject)
Expand Down Expand Up @@ -466,13 +472,30 @@ def openFile(self):
maybeCancelled = _prj.getLoadOrMigrateProject()
if _ccl.isCancelled(maybeCancelled):
return
UserSettings.setRecentProjectJsonPath(self.editor.diagramPath)
project = _ccl.value(maybeCancelled)

self._resetEditor(project)

if isinstance(project, _prj.MigrateProject):
self.editor.save()

def openRecentFile(self):
qmb = _qtw.QMessageBox()
qmb.setText("Are you sure you want to open another project? Unsaved progress on the current one will be lost.")
qmb.setStandardButtons(_qtw.QMessageBox.Yes | _qtw.QMessageBox.Cancel)
qmb.setDefaultButton(_qtw.QMessageBox.Cancel)
ret = qmb.exec()

if ret == _qtw.QMessageBox.Cancel:
return
maybeCancelled = _prj.loadRecentProject()
if _ccl.isCancelled(maybeCancelled):
return
UserSettings.setRecentProjectJsonPath(self.editor.diagramPath)
project = _ccl.value(maybeCancelled)
self._resetEditor(project)

def _resetEditor(self, project):
wasRunning = self.editor and self.editor.isRunning()

Expand Down Expand Up @@ -577,11 +600,14 @@ def closeEvent(self, e):
if ret == _qtw.QMessageBox.Cancel:
e.ignore()
elif ret == _qtw.QMessageBox.Close:
UserSettings.setRecentProjectJsonPath(self.editor.diagramPath)
e.accept()
elif ret == _qtw.QMessageBox.Save:
self.editor.save()
UserSettings.setRecentProjectJsonPath(self.editor.diagramPath)
e.accept()
else:
UserSettings.setRecentProjectJsonPath(self.editor.diagramPath)
e.accept()

def ensureSettingsExist(self):
Expand Down
45 changes: 35 additions & 10 deletions trnsysGUI/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import PyQt5.QtWidgets as _qtw

import trnsysGUI.common.cancelled as _ccl
from trnsysGUI.userSettings import UserSettings


@_dc.dataclass
Expand Down Expand Up @@ -56,17 +57,19 @@ def getProject() -> _ccl.MaybeCancelled[Project]:
class _CreateNewOrOpenExisting(_enum.Enum):
CREATE_NEW = _enum.auto()
OPEN_EXISTING = _enum.auto()
OPEN_RECENT = _enum.auto()


def _askUserWhetherToCreateNewProjectOrOpenExisting() -> _ccl.MaybeCancelled[_CreateNewOrOpenExisting]:
messageBox = _qtw.QMessageBox()
messageBox.setWindowTitle("Start a new or open an existing project")
messageBox.setText("Do you want to start a new project or open an existing one?")

recentButton = _qtw.QPushButton("Recent")
createButton = _qtw.QPushButton("New")
openButton = _qtw.QPushButton("Open")
messageBox.addButton(createButton, _qtw.QMessageBox.YesRole)
messageBox.addButton(openButton, _qtw.QMessageBox.NoRole)
messageBox.addButton(recentButton, _qtw.QMessageBox.NoRole)
messageBox.addButton(_qtw.QMessageBox.Cancel)
messageBox.setFocus()
messageBox.exec()
Expand All @@ -83,6 +86,9 @@ def _askUserWhetherToCreateNewProjectOrOpenExisting() -> _ccl.MaybeCancelled[_Cr
if clickedButton is openButton:
return _CreateNewOrOpenExisting.OPEN_EXISTING

if clickedButton is recentButton:
return _CreateNewOrOpenExisting.OPEN_RECENT

raise AssertionError("Unknown button was clicked.")


Expand All @@ -93,6 +99,9 @@ def _getProjectInternal(createOrOpenExisting: "_CreateNewOrOpenExisting") -> _cc
if createOrOpenExisting == _CreateNewOrOpenExisting.CREATE_NEW:
return getCreateProject()

if createOrOpenExisting == _CreateNewOrOpenExisting.OPEN_RECENT:
return loadRecentProject()

raise AssertionError(f"Unknown value for enum {_CreateNewOrOpenExisting}: {createOrOpenExisting}")


Expand Down Expand Up @@ -132,11 +141,8 @@ def getExistingEmptyDirectory(
def _isEmptyDirectory(path: _pl.Path) -> bool:
if not path.is_dir():
return False

containedFilesAndDirectories = list(path.iterdir())

isDirectoryEmpty = len(containedFilesAndDirectories) == 0

return isDirectoryEmpty


Expand All @@ -145,15 +151,37 @@ def getLoadOrMigrateProject() -> _ccl.MaybeCancelled[LoadProject | MigrateProjec
if not projectFolderPathString:
return _ccl.CANCELLED
jsonFilePath = _pl.Path(projectFolderPathString)

projectFolderPath = jsonFilePath.parent
return checkIfProjectEnviromentIsValid(projectFolderPath, jsonFilePath)


def loadRecentProject() -> _ccl.MaybeCancelled[LoadProject | MigrateProject]:
messageBox = _qtw.QMessageBox()
messageBox.setStandardButtons(_qtw.QMessageBox.Ok)
try:
recentProjectJsonPath = _pl.Path(UserSettings.getRecentProjectJsonPath())
if not recentProjectJsonPath.exists():
messageBox.setText("Recent project has moved or was deleted")
result = messageBox.exec()
if result == _qtw.QMessageBox.Ok:
return _ccl.CANCELLED
else:
return checkIfProjectEnviromentIsValid(recentProjectJsonPath.parent, recentProjectJsonPath)
except TypeError:
messageBox.setText("No recent project available")
result = messageBox.exec()
if result == _qtw.QMessageBox.Ok:
return _ccl.CANCELLED
return _ccl.CANCELLED


def checkIfProjectEnviromentIsValid(
projectFolderPath, jsonFilePath
) -> _ccl.MaybeCancelled[LoadProject | MigrateProject]:
containingFolderIsCalledSameAsJsonFile = projectFolderPath.name == jsonFilePath.stem
ddckFolder = projectFolderPath / "ddck"

if not containingFolderIsCalledSameAsJsonFile or not ddckFolder.is_dir():
oldJsonFilePath = jsonFilePath

messageBox = _qtw.QMessageBox()
messageBox.setText(
"The json you are opening does not have a proper project folder environment. "
Expand All @@ -164,12 +192,9 @@ def getLoadOrMigrateProject() -> _ccl.MaybeCancelled[LoadProject | MigrateProjec
result = messageBox.exec()
if result == _qtw.QMessageBox.Cancel:
return _ccl.CANCELLED

maybeCancelled = getExistingEmptyDirectory(startingDirectoryPath=projectFolderPath.parent)
if _ccl.isCancelled(maybeCancelled):
return _ccl.CANCELLED
newProjectFolderPath = _ccl.value(maybeCancelled)

return MigrateProject(oldJsonFilePath, newProjectFolderPath)

return LoadProject(jsonFilePath)
17 changes: 17 additions & 0 deletions trnsysGUI/userSettings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pathlib as _pl
from PyQt5.QtCore import QSettings # pylint: disable=invalid-name


class UserSettings:

_SETTINGS = QSettings("SPF", "pytrnsys")

@staticmethod
def setRecentProjectJsonPath(jsonFilePath: _pl.Path) -> None:
jsonFilePath = _pl.Path(jsonFilePath)
if jsonFilePath.exists():
UserSettings._SETTINGS.setValue("recentProject", jsonFilePath)

@staticmethod
def getRecentProjectJsonPath() -> _pl.Path:
return UserSettings._SETTINGS.value("recentProject")

0 comments on commit c288975

Please sign in to comment.