Skip to content
Open
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: 0 additions & 1 deletion .github/workflows/build_installer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ jobs:
run: |
conda init bash
conda activate rascal2
conda install conda-forge::expat==2.7.3
if [ ${{ matrix.platform }} == "macos-14" ]; then
ARCH="arm64"
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Users/runner/hostedtoolcache/MATLAB/2023.2.999/arm64/MATLAB.app/bin/maca64
Expand Down
1 change: 1 addition & 0 deletions environment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ dependencies:
- python=3.10
- pip
- llvm-openmp
- expat=2.7.3
- pip:
- -r requirements.txt
- -r requirements-dev.txt
2 changes: 1 addition & 1 deletion packaging/linux/build_installer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ echo ""
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O "$TMP_DIR/miniconda.sh"
bash ./miniconda.sh -b -p ./miniconda
./miniconda/bin/conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main --channel https://repo.anaconda.com/pkgs/r
./miniconda/bin/conda create -n rascal_builder -y python=3.10
./miniconda/bin/conda create -n rascal_builder -y python=3.10 expat=2.7.3

echo ""
echo "Downloading Dependencies"
Expand Down
51 changes: 51 additions & 0 deletions rascal2/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import logging
import multiprocessing
import re
from contextlib import suppress

from PyQt6 import QtWidgets

from rascal2.config import MatlabHelper, handle_scaling, setup_logging
from rascal2.paths import IMAGES_PATH, STATIC_PATH
from rascal2.ui.view import MainWindowView


def ui_execute(splash):
"""Create main window and executes GUI event loop.

Returns
-------
exit code : int
QApplication exit code
"""
handle_scaling()
QtWidgets.QApplication.setStyle("Fusion")
app = QtWidgets.QApplication.instance()
with suppress(FileNotFoundError), open(STATIC_PATH / "style.css") as stylesheet:
palette = app.palette()
replacements = {
"@Path": IMAGES_PATH.as_posix(),
"@Window": palette.window().color().name(),
"@Highlight": palette.highlight().color().name(),
"@Midlight": palette.midlight().color().name(),
"@Text": palette.text().color().name(),
}
style = re.sub("|".join(replacements), lambda x: replacements[x.group(0)], stylesheet.read())
app.setStyleSheet(style)

window = MainWindowView()
window.show()
splash.finish(window)

return app.exec()


def start_app(splash):
"""Start RasCAL app."""
multiprocessing.set_start_method("spawn", force=True)
setup_logging()
matlab_helper = MatlabHelper()
exit_code = ui_execute(splash)
matlab_helper.close_event.set()
logging.shutdown()
return exit_code
38 changes: 1 addition & 37 deletions rascal2/config.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,12 @@
import logging
import os

os.environ["DELAY_MATLAB_START"] = "1"
import multiprocessing as mp
import pathlib
import platform
import site
import sys

from rascal2.paths import MATLAB_ARCH_FILE
from rascal2.settings import Settings, get_global_settings

if getattr(sys, "frozen", False):
# we are running in a bundle
SOURCE_PATH = pathlib.Path(sys.executable).parent.parent
SITE_PATH = SOURCE_PATH / "bin/_internal"
if pathlib.Path(SOURCE_PATH / "MacOS").is_dir():
SOURCE_PATH = SOURCE_PATH / "Resources"
SITE_PATH = SOURCE_PATH
EXAMPLES_PATH = SOURCE_PATH / "examples"
else:
SOURCE_PATH = pathlib.Path(__file__).parent
SITE_PATH = site.getsitepackages()[-1]
EXAMPLES_PATH = SOURCE_PATH.parent / "examples"

STATIC_PATH = SOURCE_PATH / "static"
IMAGES_PATH = STATIC_PATH / "images"
MATLAB_ARCH_FILE = pathlib.Path(SITE_PATH) / "matlab/engine/_arch.txt"
EXAMPLES_TEMP_PATH = pathlib.Path(get_global_settings().fileName()).parent / "examples"
LOGGER = logging.getLogger("rascal2")
SETTINGS = Settings()

Expand All @@ -39,22 +19,6 @@ def handle_scaling():
windll.user32.SetProcessDPIAware()


def path_for(filename: str):
"""Get full path for the given image file.

Parameters
----------
filename : str
basename and extension of image.

Returns
-------
full path : str
full path of the image.
"""
return (IMAGES_PATH / filename).as_posix()


def log_uncaught_exceptions(exc_type, exc_value, exc_traceback):
"""Qt slots swallows exceptions but this ensures exceptions are logged."""
logging.critical("An unhandled exception occurred!", exc_info=(exc_type, exc_value, exc_traceback))
Expand Down
3 changes: 2 additions & 1 deletion rascal2/dialogs/about_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

import rascal2
import rascal2.widgets
from rascal2.config import MatlabHelper, path_for
from rascal2.config import MatlabHelper
from rascal2.paths import path_for
from rascal2.settings import get_global_settings


Expand Down
3 changes: 2 additions & 1 deletion rascal2/dialogs/custom_file_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
from PyQt6 import Qsci, QtGui, QtWidgets
from ratapi.utils.enums import Languages

from rascal2.config import EXAMPLES_PATH, LOGGER, SETTINGS, MatlabHelper
from rascal2.config import LOGGER, SETTINGS, MatlabHelper
from rascal2.core.enums import CustomFileType
from rascal2.paths import EXAMPLES_PATH

MATLAB_MODEL_TEMPLATE = """function [output, sub_rough] = {0}{1}
% RasCAL-2 Layer Model Custom File.
Expand Down
3 changes: 2 additions & 1 deletion rascal2/dialogs/settings_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

from PyQt6 import QtCore, QtWidgets

from rascal2.config import LOGGER, MATLAB_ARCH_FILE, SETTINGS, MatlabHelper
from rascal2.config import LOGGER, SETTINGS, MatlabHelper
from rascal2.paths import MATLAB_ARCH_FILE
from rascal2.settings import SettingsGroups
from rascal2.widgets.inputs import get_validated_input

Expand Down
3 changes: 2 additions & 1 deletion rascal2/dialogs/startup_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

from PyQt6 import QtCore, QtWidgets

from rascal2.config import EXAMPLES_PATH, LOGGER
from rascal2.config import LOGGER
from rascal2.core.worker import Worker
from rascal2.paths import EXAMPLES_PATH
from rascal2.settings import update_recent_projects

# global variable for required project files
Expand Down
85 changes: 41 additions & 44 deletions rascal2/main.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,51 @@
import logging
import multiprocessing
import re
import os
import sys
from contextlib import suppress

from PyQt6 import QtGui, QtWidgets

from rascal2.config import IMAGES_PATH, STATIC_PATH, MatlabHelper, handle_scaling, path_for, setup_logging
from rascal2.ui.view import MainWindowView


def ui_execute():
"""Create main window and executes GUI event loop.

Returns
-------
exit code : int
QApplication exit code
"""
handle_scaling()
QtWidgets.QApplication.setStyle("Fusion")
app = QtWidgets.QApplication(sys.argv[:1])
app.setWindowIcon(QtGui.QIcon(path_for("logo.png")))
with suppress(FileNotFoundError), open(STATIC_PATH / "style.css") as stylesheet:
palette = app.palette()
replacements = {
"@Path": IMAGES_PATH.as_posix(),
"@Window": palette.window().color().name(),
"@Highlight": palette.highlight().color().name(),
"@Midlight": palette.midlight().color().name(),
"@Text": palette.text().color().name(),
}
style = re.sub("|".join(replacements), lambda x: replacements[x.group(0)], stylesheet.read())
app.setStyleSheet(style)

window = MainWindowView()
window.show()
return app.exec()

from PyQt6.QtCore import Qt, QThread
from PyQt6.QtGui import QIcon, QPixmap
from PyQt6.QtWidgets import QApplication, QSplashScreen

from rascal2.paths import path_for


class SplashScreen(QSplashScreen):
"""Create splash screen widget."""

def __init__(self, *args):
super().__init__(*args)
self.painted = False

def paintEvent(self, event):
super().paintEvent(event)
self.painted = True


def main():
"""Entry point function for starting RasCAL."""
multiprocessing.freeze_support()
multiprocessing.set_start_method("spawn", force=True)
setup_logging()
matlab_helper = MatlabHelper()
exit_code = ui_execute()
matlab_helper.close_event.set()
logging.shutdown()
sys.exit(exit_code)

app = QApplication([])
app.setWindowIcon(QIcon(path_for("logo.png")))

splash = SplashScreen(QPixmap(path_for("splash.png")), Qt.WindowType.WindowStaysOnTopHint)
splash.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
splash.show()
splash.raise_()
splash.activateWindow()
app.processEvents()
for _ in range(100):
if splash.painted:
break
# wait for splash to paint on linux
QThread.usleep(100)
app.processEvents()
app.processEvents()

os.environ["DELAY_MATLAB_START"] = "1"
from rascal2.app import start_app

sys.exit(start_app(splash))


if __name__ == "__main__":
Expand Down
39 changes: 39 additions & 0 deletions rascal2/paths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import site
import sys
from pathlib import Path

from rascal2.settings import get_global_settings

if getattr(sys, "frozen", False):
# we are running in a bundle
SOURCE_PATH = Path(sys.executable).parent.parent
SITE_PATH = SOURCE_PATH / "bin/_internal"
if Path(SOURCE_PATH / "MacOS").is_dir():
SOURCE_PATH = SOURCE_PATH / "Resources"
SITE_PATH = SOURCE_PATH
EXAMPLES_PATH = SOURCE_PATH / "examples"
else:
SOURCE_PATH = Path(__file__).parent
SITE_PATH = site.getsitepackages()[-1]
EXAMPLES_PATH = SOURCE_PATH.parent / "examples"

STATIC_PATH = SOURCE_PATH / "static"
IMAGES_PATH = STATIC_PATH / "images"
MATLAB_ARCH_FILE = Path(SITE_PATH) / "matlab/engine/_arch.txt"
EXAMPLES_TEMP_PATH = Path(get_global_settings().fileName()).parent / "examples"


def path_for(filename: str):
"""Get full path for the given image file.

Parameters
----------
filename : str
basename and extension of image.

Returns
-------
full path : str
full path of the image.
"""
return (IMAGES_PATH / filename).as_posix()
Binary file modified rascal2/static/images/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added rascal2/static/images/splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion rascal2/ui/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import ratapi.outputs
from PyQt6 import QtCore

from rascal2.config import EXAMPLES_PATH, EXAMPLES_TEMP_PATH
from rascal2.paths import EXAMPLES_PATH, EXAMPLES_TEMP_PATH


def copy_example_project(load_path):
Expand Down
3 changes: 2 additions & 1 deletion rascal2/ui/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

from PyQt6 import QtCore, QtGui, QtWidgets

from rascal2.config import EXAMPLES_PATH, EXAMPLES_TEMP_PATH, SETTINGS, path_for
from rascal2.config import SETTINGS
from rascal2.core.enums import UnsavedReply
from rascal2.dialogs.about_dialog import AboutDialog
from rascal2.dialogs.settings_dialog import SettingsDialog
from rascal2.dialogs.startup_dialog import PROJECT_FILES, LoadDialog, LoadR1Dialog, NewProjectDialog, StartupDialog
from rascal2.paths import EXAMPLES_PATH, EXAMPLES_TEMP_PATH, path_for
from rascal2.settings import MDIGeometries, get_global_settings
from rascal2.widgets import ControlsWidget, PlotWidget, TerminalWidget
from rascal2.widgets.project import ProjectWidget
Expand Down
2 changes: 1 addition & 1 deletion rascal2/widgets/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pydantic.fields import FieldInfo
from PyQt6 import QtCore, QtGui, QtWidgets

from rascal2.config import path_for
from rascal2.paths import path_for


def get_validated_input(field_info: FieldInfo, parent=None) -> QtWidgets.QWidget:
Expand Down
3 changes: 2 additions & 1 deletion rascal2/widgets/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT
from PyQt6 import QtCore, QtGui, QtWidgets

from rascal2.config import SETTINGS, path_for
from rascal2.config import SETTINGS
from rascal2.paths import path_for
from rascal2.widgets.inputs import MultiSelectComboBox, ProgressButton


Expand Down
3 changes: 2 additions & 1 deletion rascal2/widgets/project/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
from PyQt6 import QtCore, QtGui, QtWidgets
from ratapi.utils.enums import BackgroundActions, LayerModels

from rascal2.config import SETTINGS, path_for
from rascal2.config import SETTINGS
from rascal2.core.readers import readers
from rascal2.paths import path_for
from rascal2.widgets.delegates import ProjectFieldDelegate
from rascal2.widgets.inputs import RangeWidget

Expand Down
2 changes: 1 addition & 1 deletion rascal2/widgets/project/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ratapi.utils.custom_errors import custom_pydantic_validation_error
from ratapi.utils.enums import Calculations, Geometries, LayerModels

from rascal2.config import path_for
from rascal2.paths import path_for
from rascal2.widgets.project.lists import ContrastWidget, DataWidget
from rascal2.widgets.project.slider_view import SliderViewWidget
from rascal2.widgets.project.tables import (
Expand Down
3 changes: 2 additions & 1 deletion rascal2/widgets/project/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
from ratapi.utils.enums import Calculations, Languages, Procedures, TypeOptions

import rascal2.widgets.delegates as delegates
from rascal2.config import LOGGER, SETTINGS, path_for
from rascal2.config import LOGGER, SETTINGS
from rascal2.core.enums import CustomFileType
from rascal2.dialogs.custom_file_editor import create_new_file, edit_file
from rascal2.paths import path_for


class ClassListTableModel(QtCore.QAbstractTableModel):
Expand Down
2 changes: 1 addition & 1 deletion rascal2/widgets/startup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from PyQt6 import QtCore, QtGui, QtWidgets

from rascal2.config import path_for
from rascal2.dialogs.startup_dialog import LoadDialog, LoadR1Dialog, NewProjectDialog
from rascal2.paths import path_for


class StartUpWidget(QtWidgets.QWidget):
Expand Down
Loading