def on_ok(self):
     """ Tries to convert the current case to 2D mode while saving the 3D mode data. """
     try:
         self.stored_y_value = float(self.y2_pos_input.text())
     except ValueError:
         error_dialog(__("The Y position that was inserted is not valid."))
     self.accept()
Esempio n. 2
0
    def check_and_filter(self):
        """ Filters the executable removing those not matching the correct application.
            Returns whether or not all of them were correctly set. """
        execs_correct: bool = True
        execs_to_check = {
            "gencase": self.gencase,
            "dualsphysics": self.dsphysics,
            "partvtk": self.partvtk,
            "floatinginfo": self.floatinginfo,
            "computeforces": self.computeforces,
            "measuretool": self.measuretool,
            "isosurface": self.isosurface,
            "boundaryvtk": self.boundaryvtk,
            "flowtool": self.flowtool
        }

        bad_executables: list = list()

        for word, executable in execs_to_check.items():
            if not executable_contains_string(executable, word):
                debug("Executable {} does not contain the word {}".format(
                    executable, word))
                execs_correct = False
                bad_executables.append(executable)

        if not execs_correct:
            error_dialog(
                "One or more of the executables set on the configuration is not correct. Please see the details below.",
                "These executables do not correspond to their appropriate tool or don't have execution permissions:\n\n{}"
                .format(LINE_END.join(bad_executables)))

        self.persist()
        return execs_correct
        def on_dsph_sim_finished(exit_code):
            """ Simulation finish handler. Defines what happens when the process finishes."""

            # Reads output and completes the progress bar
            output = str(process.readAllStandardOutput().data(), encoding='utf-8')

            run_dialog.set_detail_text(str(output))
            run_dialog.run_complete()

            run_fs_watcher.removePath(Case.the().path + "/" + Case.the().name + "_out/")

            if exit_code == 0:
                # Simulation went correctly
                Case.the().info.is_simulation_done = True
                Case.the().info.needs_to_run_gencase = False
                self.simulation_complete.emit(True)
            else:
                # In case of an error
                Case.the().info.needs_to_run_gencase = True
                if "exception" in str(output).lower():
                    log("There was an error on the execution. Opening an error dialog for that.")
                    run_dialog.hide()
                    self.simulation_complete.emit(False)
                    error_dialog(__("An error occurred during execution. Make sure that parameters exist and are properly defined. "
                                    "You can also check your execution device (update the driver of your GPU). Read the details for more information."), str(output))
            save_case(Case.the().path, Case.the())
    def on_save(self):
        """ Link linearspring save button behaviour"""
        target_linearspring = self.case.chrono.get_link_linearspring_for_id(
            self.link_linearspring_id)

        target_linearspring.idbody1 = str(
            self.body_one_line_edit.currentText())
        target_linearspring.idbody2 = str(
            self.body_two_line_edit.currentText())
        target_linearspring.point_fb1 = [
            float(self.point_b1_x_line_edit.text()),
            float(self.point_b1_y_line_edit.text()),
            float(self.point_b1_z_line_edit.text())
        ]
        target_linearspring.point_fb2 = [
            float(self.point_b2_x_line_edit.text()),
            float(self.point_b2_y_line_edit.text()),
            float(self.point_b2_z_line_edit.text())
        ]
        target_linearspring.stiffness = float(self.stiffness_line_edit.text())
        target_linearspring.damping = float(self.damping_line_edit.text())
        target_linearspring.rest_length = float(self.rest_line_edit.text())
        target_linearspring.number_of_sections = int(
            self.vtk_nside_line_edit.text())
        target_linearspring.spring_radius = float(
            self.vtk_radius_line_edit.text())
        target_linearspring.revolution_length = float(
            self.vtk_length_line_edit.text())

        if target_linearspring.idbody1 and target_linearspring.idbody2:
            LinkLinearspringEdit.accept(self)
        else:
            error_dialog(
                "You need to select an option for each one of the bodies.")
Esempio n. 5
0
    def on_export_finished(exit_code):
        """ Closes and displays info/error about the process. """
        post_processing_widget.adapt_to_export_finished()
        export_dialog.accept()
        detailed_text = "The executed command line was: {} {}\n\n{}".format(
            case.executable_paths.partvtk, " ".join(executable_parameters),
            case.info.current_output)

        if not exit_code:
            info_dialog(info_text=__("PartVTK finished successfully"),
                        detailed_text=detailed_text)
        else:
            error_dialog(__(
                "There was an error on the post-processing. Show details to view the errors."
            ),
                         detailed_text=detailed_text)

        if options["open_paraview"]:
            subprocess.Popen([
                case.executable_paths.paraview,
                "--data={}\\{}\\{}_..{}".format(
                    case.get_out_folder_path(), options["file_name"],
                    options["file_name"], save_extension)
            ],
                             stdout=subprocess.PIPE)
    def on_ok(self):
        """ Saves damping zone data to the data structure. """
        self.case.get_damping_zone(self.object_key).enabled = self.enabled_checkbox.isChecked()
        self.case.get_damping_zone(self.object_key).overlimit = float(self.overlimit_input.text())
        self.case.get_damping_zone(self.object_key).redumax = float(self.redumax_input.text())
        damping_group = FreeCAD.ActiveDocument.getObject(self.object_key)
        damping_group.OutList[0].Start = (float(self.limitmin_input_x.text()) * DIVIDER,
                                          float(self.limitmin_input_y.text()) * DIVIDER,
                                          float(self.limitmin_input_z.text()) * DIVIDER)
        damping_group.OutList[0].End = (float(self.limitmax_input_x.text()) * DIVIDER,
                                        float(self.limitmax_input_y.text()) * DIVIDER,
                                        float(self.limitmax_input_z.text()) * DIVIDER)
        damping_group.OutList[1].Start = damping_group.OutList[0].End

        overlimit_vector = FreeCAD.Vector(*damping_group.OutList[0].End) - FreeCAD.Vector(*damping_group.OutList[0].Start)
        try:
            overlimit_vector.normalize()
        except FreeCAD.Base.FreeCADError:
            error_dialog(__("The vector between minimum and maximum limit must have length."))

        overlimit_vector = overlimit_vector * (self.case.get_damping_zone(self.object_key).overlimit * DIVIDER)
        overlimit_vector = overlimit_vector + FreeCAD.Vector(*damping_group.OutList[0].End)

        damping_group.OutList[1].End = (overlimit_vector.x, overlimit_vector.y, overlimit_vector.z)
        FreeCAD.ActiveDocument.recompute()
        self.accept()
Esempio n. 7
0
def load_case(load_path: str) -> "Case":
    """ Loads a case from the given folder and returns its Case data. """
    refocus_cwd()
    project_folder_path = path.dirname(load_path)
    freecad_document_file_path = path.abspath("{}/DSPH_Case.FCStd".format(project_folder_path))

    if not path.isfile(freecad_document_file_path):
        error_dialog(__("DSPH_Case.FCStd file could not be found. Please check if the project was moved or the file was renamed."))
        return None

    if document_count() and not prompt_close_all_documents():
        return None

    FreeCAD.open(project_folder_path + "/DSPH_Case.FCStd")

    with open(load_path, "rb") as load_picklefile:
        try:
            loaded_data = pickle.load(load_picklefile)
            if not loaded_data.version:
                warning_dialog(__("The case data you're trying to load is older than version 0.6 and cannot be loaded."))
                prompt_close_all_documents(prompt=False)
                return None
            if loaded_data.version < VERSION:
                warning_dialog(__("The case data you are loading is from a previous version ({}) of this software. They may be missing features or errors.").format(loaded_data.version))
            elif loaded_data.version > VERSION:
                warning_dialog(__("You're loading a case data from a future version ({}) of this software. You should upgrade DesignSPHysics as they may be errors using this file.").format(loaded_data.version))

            return loaded_data
        except AttributeError:
            error_dialog(__("There was an error opening the case. Case Data file seems to be corrupted."))
            return None
Esempio n. 8
0
    def on_save(self):
        """ Link pointline save button behaviour"""
        link_pointline = self.case.chrono.get_link_pointline_for_id(
            self.link_pointline_id)

        link_pointline.idbody1 = str(self.body_one_line_edit.currentText())
        link_pointline.slidingvector = [
            float(self.sliding_vector_x_line_edit.text()),
            float(self.sliding_vector_y_line_edit.text()),
            float(self.sliding_vector_z_line_edit.text())
        ]
        link_pointline.rotpoint = [
            float(self.rotpoint_x_line_edit.text()),
            float(self.rotpoint_y_line_edit.text()),
            float(self.rotpoint_z_line_edit.text())
        ]
        link_pointline.rotvector = [
            float(self.rotvector_x_line_edit.text()),
            float(self.rotvector_y_line_edit.text()),
            float(self.rotvector_z_line_edit.text())
        ]
        link_pointline.rotvector2 = [
            float(self.rotvector2_x_line_edit.text()),
            float(self.rotvector2_y_line_edit.text()),
            float(self.rotvector2_z_line_edit.text())
        ]
        link_pointline.stiffness = float(self.stiffness_line_edit.text())
        link_pointline.damping = float(self.damping_line_edit.text())

        if link_pointline.idbody1:
            LinkPointlineEdit.accept(self)
        else:
            error_dialog("You need to select an option for the body to use.")
Esempio n. 9
0
    def on_execute_gencase(self):
        """ Saves data into disk and uses GenCase to generate the case files."""
        self.on_save_case()
        if not Case.the().executable_paths.gencase:
            warning_dialog(__("GenCase executable is not set."))
            return

        gencase_full_path = path.abspath(Case.the().executable_paths.gencase)
        arguments = [
            "{path}/{name}_Def".format(path=Case.the().path,
                                       name=Case.the().name),
            "{path}/{name}_out/{name}".format(path=Case.the().path,
                                              name=Case.the().name),
            "-save:+all"
        ]
        cmd_string = "{} {}".format(gencase_full_path, " ".join(arguments))

        refocus_cwd()
        process = QtCore.QProcess(get_fc_main_window())
        process.setWorkingDirectory(Case.the().path)
        ensure_process_is_executable_or_fail(gencase_full_path)
        process.start(gencase_full_path, arguments)
        debug("Executing -> {}".format(cmd_string))
        process.waitForFinished()

        try:
            output = str(process.readAllStandardOutput().data(),
                         encoding='utf-8')
        except UnicodeDecodeError:
            output = str(process.readAllStandardOutput().data(),
                         encoding='latin1')

        if process.exitCode():
            Case.the().info.is_gencase_done = False
            error_dialog(
                __("Error executing GenCase. Did you add objects to the case?. Another reason could be memory issues. View details for more info."
                   ), output)
        else:
            try:
                total_particles_text = output[
                    output.index("Total particles: "):output.index(" (bound=")]
                total_particles = int(
                    total_particles_text[total_particles_text.index(": ") +
                                         2:])
                Case.the().info.particle_number = total_particles
                GencaseCompletedDialog(particle_count=total_particles,
                                       detail_text=output,
                                       cmd_string=cmd_string,
                                       parent=get_fc_main_window()).show()
                Case.the().info.is_gencase_done = True
                self.on_save_case()
                Case.the().info.needs_to_run_gencase = False
            except ValueError:
                print_exc()
                Case.the().info.is_gencase_done = False
                Case.the().info.needs_to_run_gencase = True

        # Refresh widget enable/disable status as GenCase finishes
        self.gencase_completed.emit(Case.the().info.is_gencase_done)
Esempio n. 10
0
    def on_mtool_export(self):
        """ Export button behaviour."""
        export_parameters = dict()
        export_parameters["save_mode"] = self.outformat_combobox.currentIndex()
        export_parameters["save_vars"] = "-all"
        if self.mtool_types_chk_all.isChecked():
            export_parameters["save_vars"] = "+all"
        else:
            if self.mtool_types_chk_vel.isChecked():
                export_parameters["save_vars"] += ",+vel"
            if self.mtool_types_chk_rhop.isChecked():
                export_parameters["save_vars"] += ",+rhop"
            if self.mtool_types_chk_press.isChecked():
                export_parameters["save_vars"] += ",+press"
            if self.mtool_types_chk_mass.isChecked():
                export_parameters["save_vars"] += ",+mass"
            if self.mtool_types_chk_vol.isChecked():
                export_parameters["save_vars"] += ",+vol"
            if self.mtool_types_chk_idp.isChecked():
                export_parameters["save_vars"] += ",+idp"
            if self.mtool_types_chk_ace.isChecked():
                export_parameters["save_vars"] += ",+ace"
            if self.mtool_types_chk_vor.isChecked():
                export_parameters["save_vars"] += ",+vor"
            if self.mtool_types_chk_kcorr.isChecked():
                export_parameters["save_vars"] += ",+kcorr"

        if export_parameters[
                "save_vars"] == "-all" and not self.mtool_calculate_elevation.isChecked(
                ):
            export_parameters["save_vars"] = "+all"

        export_parameters[
            "calculate_water_elevation"] = self.mtool_calculate_elevation.isChecked(
            )

        if self.mtool_file_name_text.text():
            export_parameters["filename"] = self.mtool_file_name_text.text()
        else:
            export_parameters["filename"] = "MeasurePart"

        if self.mtool_parameters_text.text():
            export_parameters[
                "additional_parameters"] = self.mtool_parameters_text.text()
        else:
            export_parameters["additional_parameters"] = ""

        if not Case.the().info.measuretool_points and not Case.the(
        ).info.measuretool_grid:
            error_dialog(
                __("No points or grid are defined to execute MeasureTool"),
                __("Please define either list of points or a grid of points to continue. MeasureTool won't be executed."
                   ))
        else:
            measuretool_export(export_parameters, Case.the(),
                               self.post_processing_widget)
            self.accept()
    def on_export_finished(exit_code):
        """ Closes and displays info/error about the process. """
        post_processing_widget.adapt_to_export_finished()
        export_dialog.accept()
        detailed_text = "The executed command line was: {} {}\n\n{}".format(case.executable_paths.flowtool, " ".join(executable_parameters), case.info.current_output)

        if not exit_code:
            info_dialog(info_text=__("FlowTool finished successfully"), detailed_text=detailed_text)
        else:
            error_dialog(__("There was an error on the post-processing. Show details to view the errors."), detailed_text=detailed_text)
 def on_load_button(self):
     """ Defines load case button behaviour. This is made so errors can be detected and handled. """
     try:
         self.on_load_case()
     except ImportError:
         error_dialog(
             __("There was an error loading the case"),
             __("The case you are trying to load has some data that DesignSPHysics could not load.\n\nDid you make the case in a previous version?"
                ))
         self.on_new_case(prompt=False)
Esempio n. 13
0
def check_compatibility():
    """ Ensures the current version of FreeCAD is compatible with the macro. Spawns an error dialog and throws exception to halt
        the execution if its not. """
    if not is_compatible_version():
        error_dialog(
            __("This FreeCAD version is not compatible. Please update FreeCAD to version {} or higher."
               ).format(FREECAD_MIN_VERSION))
        raise EnvironmentError(
            __("This FreeCAD version is not compatible. Please update FreeCAD to version {} or higher."
               ).format(FREECAD_MIN_VERSION))
    def on_save(self):
        """ Link Spheric save button behaviour"""
        link_spheric = self.case.chrono.get_link_spheric_for_id(self.link_spheric_id)

        link_spheric.idbody1 = str(self.body_one_line_edit.currentText())
        link_spheric.idbody2 = str(self.body_two_line_edit.currentText())
        link_spheric.rotpoint = [float(self.point_x_line_edit.text()), float(self.point_y_line_edit.text()), float(self.point_z_line_edit.text())]
        link_spheric.stiffness = float(self.stiffness_line_edit.text())
        link_spheric.damping = float(self.damping_line_edit.text())

        if link_spheric.idbody1:
            LinkSphericEdit.accept(self)
        else:
            error_dialog("You need to select an option for the body to use.")
Esempio n. 15
0
 def on_open_paraview_menu(self, action):
     """ Tries to open Paraview with the selected option. """
     try:
         subprocess.Popen([
             Case.the().executable_paths.paraview, "--data={}\\{}".format(
                 Case.the().path + "\\" + Case.the().name + "_out",
                 action.text())
         ],
                          stdout=subprocess.PIPE)
         self.accept()
     except FileNotFoundError:
         error_dialog(
             "There was an error executing paraview. Make sure the path for the paraview executable is set in the DesignSPHyisics configuration and that the executable is a correct paraview one."
         )
Esempio n. 16
0
    def browse(self, app_name, input_prop) -> None:
        """ Opens a file browser to check for the provided app name. """
        file_name, _ = QtGui.QFileDialog().getOpenFileName(self, __("Select {} path").format(app_name), Case.the().info.last_used_directory)
        Case.the().info.update_last_used_directory(file_name)

        self.ok_button.setFocus()

        if not file_name:
            return

        if executable_contains_string(file_name, app_name):
            input_prop.setText(file_name)
        else:
            error_dialog(__("Can't recognize {} in the selected executable.").format(app_name))
    def on_apply(self):
        """ Applies the currently introduced MLPiston2D configuration to the data structure. """
        self.temp_mlpiston2d.incz = float(self.incz_input.text())
        self.temp_mlpiston2d.smoothz = int(self.smooth_z.text())
        self.temp_mlpiston2d.smoothy = int(self.smooth_y.text())
        list_posy = self.veldata_posy_input.text().split(",")
        list_timedataini = self.veldata_timedataini_input.text().split(",")
        if len(list_posy) != len(list_timedataini) or len(
                self.temp_mlpiston2d.veldata) != len(list_posy) or len(
                    self.temp_mlpiston2d.veldata) != len(list_timedataini):
            error_dialog(
                __("Wrong number of Y positions or Time offsets. Introduce {} of them separated by commas"
                   ).format(len(self.temp_mlpiston2d.veldata)))
            return
        for index, _ in enumerate(self.temp_mlpiston2d.veldata):
            self.temp_mlpiston2d.veldata[index].posy = list_posy[index]
            self.temp_mlpiston2d.veldata[index].timedataini = list_timedataini[
                index]

        self.mlpiston2d = self.temp_mlpiston2d
        self.accept()
Esempio n. 18
0
    def geo_ok_clicked(self):
        """ Defines ok button behaviour"""
        for geo_scaling_edit in [
                self.geo_scaling_x_e, self.geo_scaling_y_e,
                self.geo_scaling_z_e
        ]:
            geo_scaling_edit.setText(geo_scaling_edit.text().replace(",", "."))
        try:
            import_geo(filename=str(self.geo_file_path.text()),
                       scale_x=float(self.geo_scaling_x_e.text()),
                       scale_y=float(self.geo_scaling_y_e.text()),
                       scale_z=float(self.geo_scaling_z_e.text()),
                       name=str(self.geo_objname_text.text()),
                       autofill=self.geo_autofill_chck.isChecked(),
                       case=Case.the())

            self.accept()
        except ValueError:
            error_dialog(
                __("There was an error. Are you sure you wrote correct float values in the sacaling factor?"
                   ))
Esempio n. 19
0
    def on_save(self):
        """ Link hinge save button behaviour"""
        link_hinge = self.case.chrono.get_link_hinge_for_id(self.link_hinge_id)
        link_hinge.idbody1 = str(self.body_one_line_edit.currentText())
        link_hinge.idbody2 = str(self.body_two_line_edit.currentText())
        link_hinge.rotpoint = [
            float(self.rotpoints_x_line_edit.text()),
            float(self.rotpoints_y_line_edit.text()),
            float(self.rotpoints_z_line_edit.text())
        ]
        link_hinge.rotvector = [
            float(self.rotvector_x_line_edit.text()),
            float(self.rotvector_y_line_edit.text()),
            float(self.rotvector_z_line_edit.text())
        ]
        link_hinge.stiffness = float(self.stiffness_line_edit.text())
        link_hinge.damping = float(self.damping_line_edit.text())

        if link_hinge.idbody1 and link_hinge.idbody2:
            LinkHingeEdit.accept(self)
        else:
            error_dialog(
                "You need to select an option for each one of the bodies.")
    def on_load_case(self):
        """Defines loading case mechanism. Load points to a dsphdata custom file, that stores all the relevant info.
           If FCStd file is not found the project is considered corrupt."""

        load_path, _ = QtGui.QFileDialog.getOpenFileName(
            self, __("Load Case"),
            Case.the().info.last_used_directory, "casedata.dsphdata")
        Case.the().info.update_last_used_directory(load_path)

        if load_path == "":
            return

        disk_data: Case = load_case(load_path)
        if not disk_data:
            return

        try:
            Case.update_from_disk(disk_data)
            self.update_dp.emit()
        except (EOFError, ValueError):
            error_dialog(
                __("There was an error importing the case  You probably need to set them again.\n\n"
                   "This could be caused due to file corruption, caused by operating system based line endings or ends-of-file, or other related aspects."
                   ))

        # User may have changed the name of the folder/project
        Case.the().path = path.dirname(load_path)
        Case.the().name = Case.the().path.split("/")[-1]

        # Adapt widget state to case info
        self.case_created.emit()
        self.gencase_completed.emit(Case.the().info.is_gencase_done)
        self.simulation_completed.emit(Case.the().info.is_simulation_done)
        self.need_refresh.emit()

        Case.the().executable_paths.check_and_filter()
        Case.the().info.update_last_used_directory(load_path)
    def on_save(self):
        """ Link pulley save button behaviour"""
        link_pulley = self.case.chrono.get_link_pulley_for_id(
            self.link_pulley_id)
        link_pulley.idbody1 = str(self.body_one_line_edit.currentText())
        link_pulley.idbody2 = str(self.body_two_line_edit.currentText())
        link_pulley.rotpoint = [
            float(self.rotpoints_x_line_edit.text()),
            float(self.rotpoints_y_line_edit.text()),
            float(self.rotpoints_z_line_edit.text())
        ]
        link_pulley.rotvector = [
            float(self.rotvector_x_line_edit.text()),
            float(self.rotvector_y_line_edit.text()),
            float(self.rotvector_z_line_edit.text())
        ]
        link_pulley.radius = float(self.radius_line_edit.text())
        link_pulley.radius2 = float(self.radius2_line_edit.text())

        if link_pulley.idbody1 and link_pulley.idbody2:
            LinkPulleyEdit.accept(self)
        else:
            error_dialog(
                "You need to select an option for each one of the bodies.")
Esempio n. 22
0
    def _on_configure_moordyn_parameters(self) -> None:
        """ Opens up the MoorDyn configuration parameters dialog. """
        new_selected_bodies: list = list()

        for row_num in range(0, self.floating_selection_table.rowCount()):
            target_widget: MooringsCompatibleFloatingWidget = self.floating_selection_table.cellWidget(
                row_num, 0)
            if target_widget.use_checkbox.isChecked():
                list_of_matching_bodies: list = list(
                    filter(lambda body: body.ref == target_widget.mkbound,
                           self.moordyn_parameters_data.bodies))
                new_body: MoorDynBody = list_of_matching_bodies[
                    0] if list_of_matching_bodies else MoorDynBody(
                        target_widget.mkbound)
                new_selected_bodies.append(new_body)

        self.moordyn_parameters_data.bodies = list(new_selected_bodies)
        if not self.moordyn_parameters_data.bodies:
            error_dialog(
                __("You must at least select one floating body to configure MoorDyn"
                   ))
            return

        MoorDynParametersDialog(self.moordyn_parameters_data)
Esempio n. 23
0
    def __init__(self, box_id, parent=None):
        super().__init__(parent=parent)

        self.box_id = box_id

        self.box_edit_layout = QtGui.QVBoxLayout()

        # Find the box for which the button was pressed
        target_box = None

        for box in Case.the().flowtool_boxes:
            if box.id == self.box_id:
                target_box = box

        # This should not happen but if no box is found with reference id, it spawns an error.
        if target_box is None:
            error_dialog("There was an error opening the box to edit")
            return

        self.box_edit_name_layout = QtGui.QHBoxLayout()
        self.box_edit_name_label = QtGui.QLabel(__("Box Name"))
        self.box_edit_name_input = QtGui.QLineEdit(target_box.name)
        self.box_edit_name_layout.addWidget(self.box_edit_name_label)
        self.box_edit_name_layout.addWidget(self.box_edit_name_input)

        self.box_edit_description = QtGui.QLabel(
            __("Using multiple boxes with the same name will produce only one volume to measure.\n"
               "Use that to create prisms and complex forms. "
               "All points are specified in meters."))
        self.box_edit_description.setAlignment(QtCore.Qt.AlignCenter)

        # Reference image
        self.box_edit_image = QtGui.QLabel()
        self.box_edit_image.setPixmap(
            get_icon("flowtool_template.jpg", return_only_path=True))
        self.box_edit_image.setAlignment(QtCore.Qt.AlignCenter)

        # Point coords inputs
        self.box_edit_points_layout = QtGui.QVBoxLayout()

        self.box_edit_point_a_layout = QtGui.QHBoxLayout()
        self.box_edit_point_a_label = QtGui.QLabel(__("Point A (X, Y, Z)"))
        self.box_edit_point_a_x = QtGui.QLineEdit(str(target_box.point1[0]))
        self.box_edit_point_a_y = QtGui.QLineEdit(str(target_box.point1[1]))
        self.box_edit_point_a_z = QtGui.QLineEdit(str(target_box.point1[2]))
        self.box_edit_point_a_layout.addWidget(self.box_edit_point_a_label)
        self.box_edit_point_a_layout.addWidget(self.box_edit_point_a_x)
        self.box_edit_point_a_layout.addWidget(self.box_edit_point_a_y)
        self.box_edit_point_a_layout.addWidget(self.box_edit_point_a_z)

        self.box_edit_point_b_layout = QtGui.QHBoxLayout()
        self.box_edit_point_b_label = QtGui.QLabel(__("Point B (X, Y, Z)"))
        self.box_edit_point_b_x = QtGui.QLineEdit(str(target_box.point2[0]))
        self.box_edit_point_b_y = QtGui.QLineEdit(str(target_box.point2[1]))
        self.box_edit_point_b_z = QtGui.QLineEdit(str(target_box.point2[2]))
        self.box_edit_point_b_layout.addWidget(self.box_edit_point_b_label)
        self.box_edit_point_b_layout.addWidget(self.box_edit_point_b_x)
        self.box_edit_point_b_layout.addWidget(self.box_edit_point_b_y)
        self.box_edit_point_b_layout.addWidget(self.box_edit_point_b_z)

        self.box_edit_point_c_layout = QtGui.QHBoxLayout()
        self.box_edit_point_c_label = QtGui.QLabel(__("Point C (X, Y, Z)"))
        self.box_edit_point_c_x = QtGui.QLineEdit(str(target_box.point3[0]))
        self.box_edit_point_c_y = QtGui.QLineEdit(str(target_box.point3[1]))
        self.box_edit_point_c_z = QtGui.QLineEdit(str(target_box.point3[2]))
        self.box_edit_point_c_layout.addWidget(self.box_edit_point_c_label)
        self.box_edit_point_c_layout.addWidget(self.box_edit_point_c_x)
        self.box_edit_point_c_layout.addWidget(self.box_edit_point_c_y)
        self.box_edit_point_c_layout.addWidget(self.box_edit_point_c_z)

        self.box_edit_point_d_layout = QtGui.QHBoxLayout()
        self.box_edit_point_d_label = QtGui.QLabel(__("Point D (X, Y, Z)"))
        self.box_edit_point_d_x = QtGui.QLineEdit(str(target_box.point4[0]))
        self.box_edit_point_d_y = QtGui.QLineEdit(str(target_box.point4[1]))
        self.box_edit_point_d_z = QtGui.QLineEdit(str(target_box.point4[2]))
        self.box_edit_point_d_layout.addWidget(self.box_edit_point_d_label)
        self.box_edit_point_d_layout.addWidget(self.box_edit_point_d_x)
        self.box_edit_point_d_layout.addWidget(self.box_edit_point_d_y)
        self.box_edit_point_d_layout.addWidget(self.box_edit_point_d_z)

        self.box_edit_point_e_layout = QtGui.QHBoxLayout()
        self.box_edit_point_e_label = QtGui.QLabel(__("Point E (X, Y, Z)"))
        self.box_edit_point_e_x = QtGui.QLineEdit(str(target_box.point5[0]))
        self.box_edit_point_e_y = QtGui.QLineEdit(str(target_box.point5[1]))
        self.box_edit_point_e_z = QtGui.QLineEdit(str(target_box.point5[2]))
        self.box_edit_point_e_layout.addWidget(self.box_edit_point_e_label)
        self.box_edit_point_e_layout.addWidget(self.box_edit_point_e_x)
        self.box_edit_point_e_layout.addWidget(self.box_edit_point_e_y)
        self.box_edit_point_e_layout.addWidget(self.box_edit_point_e_z)

        self.box_edit_point_f_layout = QtGui.QHBoxLayout()
        self.box_edit_point_f_label = QtGui.QLabel(__("Point F (X, Y, Z)"))
        self.box_edit_point_f_x = QtGui.QLineEdit(str(target_box.point6[0]))
        self.box_edit_point_f_y = QtGui.QLineEdit(str(target_box.point6[1]))
        self.box_edit_point_f_z = QtGui.QLineEdit(str(target_box.point6[2]))
        self.box_edit_point_f_layout.addWidget(self.box_edit_point_f_label)
        self.box_edit_point_f_layout.addWidget(self.box_edit_point_f_x)
        self.box_edit_point_f_layout.addWidget(self.box_edit_point_f_y)
        self.box_edit_point_f_layout.addWidget(self.box_edit_point_f_z)

        self.box_edit_point_g_layout = QtGui.QHBoxLayout()
        self.box_edit_point_g_label = QtGui.QLabel(__("Point G (X, Y, Z)"))
        self.box_edit_point_g_x = QtGui.QLineEdit(str(target_box.point7[0]))
        self.box_edit_point_g_y = QtGui.QLineEdit(str(target_box.point7[1]))
        self.box_edit_point_g_z = QtGui.QLineEdit(str(target_box.point7[2]))
        self.box_edit_point_g_layout.addWidget(self.box_edit_point_g_label)
        self.box_edit_point_g_layout.addWidget(self.box_edit_point_g_x)
        self.box_edit_point_g_layout.addWidget(self.box_edit_point_g_y)
        self.box_edit_point_g_layout.addWidget(self.box_edit_point_g_z)

        self.box_edit_point_h_layout = QtGui.QHBoxLayout()
        self.box_edit_point_h_label = QtGui.QLabel(__("Point H (X, Y, Z)"))
        self.box_edit_point_h_x = QtGui.QLineEdit(str(target_box.point8[0]))
        self.box_edit_point_h_y = QtGui.QLineEdit(str(target_box.point8[1]))
        self.box_edit_point_h_z = QtGui.QLineEdit(str(target_box.point8[2]))
        self.box_edit_point_h_layout.addWidget(self.box_edit_point_h_label)
        self.box_edit_point_h_layout.addWidget(self.box_edit_point_h_x)
        self.box_edit_point_h_layout.addWidget(self.box_edit_point_h_y)
        self.box_edit_point_h_layout.addWidget(self.box_edit_point_h_z)

        self.box_edit_points_layout.addLayout(self.box_edit_point_a_layout)
        self.box_edit_points_layout.addLayout(self.box_edit_point_b_layout)
        self.box_edit_points_layout.addLayout(self.box_edit_point_c_layout)
        self.box_edit_points_layout.addLayout(self.box_edit_point_d_layout)
        self.box_edit_points_layout.addLayout(self.box_edit_point_e_layout)
        self.box_edit_points_layout.addLayout(self.box_edit_point_f_layout)
        self.box_edit_points_layout.addLayout(self.box_edit_point_g_layout)
        self.box_edit_points_layout.addLayout(self.box_edit_point_h_layout)

        # Ok and cancel buttons
        self.box_edit_button_layout = QtGui.QHBoxLayout()
        self.box_edit_button_ok = QtGui.QPushButton(__("OK"))
        self.box_edit_button_cancel = QtGui.QPushButton(__("Cancel"))

        self.box_edit_button_layout.addStretch(1)
        self.box_edit_button_layout.addWidget(self.box_edit_button_ok)
        self.box_edit_button_layout.addWidget(self.box_edit_button_cancel)

        self.box_edit_layout.addLayout(self.box_edit_name_layout)
        self.box_edit_layout.addWidget(self.box_edit_description)
        self.box_edit_layout.addWidget(self.box_edit_image)
        self.box_edit_layout.addStretch(1)
        self.box_edit_layout.addLayout(self.box_edit_points_layout)
        self.box_edit_layout.addLayout(self.box_edit_button_layout)

        self.setLayout(self.box_edit_layout)

        self.box_edit_button_ok.clicked.connect(self.on_ok)
        self.box_edit_button_cancel.clicked.connect(self.on_cancel)

        self.exec_()
    def __init__(self, link_linearspring_id, bodies_widgets, parent=None):
        super().__init__(parent=parent)

        self.case = Case.the()
        self.link_linearspring_id = link_linearspring_id

        # Title
        self.setWindowTitle(__("Link linearspring configuration"))
        self.link_linearspring_edit_layout = QtGui.QVBoxLayout()

        # Find the link linearspring for which the button was pressed
        target_link_linearspring = None

        for link_linearspring in self.case.chrono.link_linearspring:
            if link_linearspring.id == self.link_linearspring_id:
                target_link_linearspring = link_linearspring

        # This should not happen but if no link linearspring is found with reference id, it spawns an error.
        if target_link_linearspring is None:
            error_dialog(
                "There was an error opnening the link linearspring to edit")
            return

        # Elements that interact
        self.body_layout = QtGui.QHBoxLayout()
        self.body_one_label = QtGui.QLabel(__("Body 1: "))
        self.body_one_line_edit = QtGui.QComboBox()
        self.body_one_line_edit.insertItems(
            0, [str(target_link_linearspring.idbody1)])
        for body in bodies_widgets:
            if body.object_check.isChecked() and body.object_name != str(
                    target_link_linearspring.idbody1):
                self.body_one_line_edit.insertItems(0, [body.object_name])
        self.body_two_label = QtGui.QLabel(__("Body 2: "))
        self.body_two_line_edit = QtGui.QComboBox()
        self.body_two_line_edit.insertItems(
            0, [str(target_link_linearspring.idbody2)])
        for body in bodies_widgets:
            if body.object_check.isChecked() and body.object_name != str(
                    target_link_linearspring.idbody2):
                self.body_two_line_edit.insertItems(0, [body.object_name])
        self.body_to_body_label = QtGui.QLabel(__("to"))

        self.body_layout.addWidget(self.body_one_label)
        self.body_layout.addWidget(self.body_one_line_edit)
        self.body_layout.addWidget(self.body_to_body_label)
        self.body_layout.addWidget(self.body_two_label)
        self.body_layout.addWidget(self.body_two_line_edit)
        self.body_layout.addStretch(1)

        self.link_linearspring_edit_layout.addLayout(self.body_layout)

        # Points where the elements interact in body 1
        self.points_b1_layout = QtGui.QHBoxLayout()
        self.points_b1_label = QtGui.QLabel(__("Points in body 1: "))
        self.point_b1_x_label = QtGui.QLabel(__("X"))
        self.point_b1_x_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.point_fb1[0]))
        self.point_b1_y_label = QtGui.QLabel(__("Y"))
        self.point_b1_y_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.point_fb1[1]))
        self.point_b1_z_label = QtGui.QLabel(__("Z"))
        self.point_b1_z_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.point_fb1[2]))

        self.points_b1_layout.addWidget(self.points_b1_label)
        self.points_b1_layout.addWidget(self.point_b1_x_label)
        self.points_b1_layout.addWidget(self.point_b1_x_line_edit)
        self.points_b1_layout.addWidget(self.point_b1_y_label)
        self.points_b1_layout.addWidget(self.point_b1_y_line_edit)
        self.points_b1_layout.addWidget(self.point_b1_z_label)
        self.points_b1_layout.addWidget(self.point_b1_z_line_edit)

        self.link_linearspring_edit_layout.addLayout(self.points_b1_layout)

        # Points where the elements interact in body 2
        self.points_b2_layout = QtGui.QHBoxLayout()
        self.points_b2_label = QtGui.QLabel(__("Points in body 2: "))
        self.point_b2_x_label = QtGui.QLabel(__("X"))
        self.point_b2_x_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.point_fb2[0]))
        self.point_b2_y_label = QtGui.QLabel(__("Y"))
        self.point_b2_y_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.point_fb2[1]))
        self.point_b2_z_label = QtGui.QLabel(__("Z"))
        self.point_b2_z_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.point_fb2[2]))

        self.points_b2_layout.addWidget(self.points_b2_label)
        self.points_b2_layout.addWidget(self.point_b2_x_label)
        self.points_b2_layout.addWidget(self.point_b2_x_line_edit)
        self.points_b2_layout.addWidget(self.point_b2_y_label)
        self.points_b2_layout.addWidget(self.point_b2_y_line_edit)
        self.points_b2_layout.addWidget(self.point_b2_z_label)
        self.points_b2_layout.addWidget(self.point_b2_z_line_edit)

        self.link_linearspring_edit_layout.addLayout(self.points_b2_layout)

        # Torsion options
        self.torsion_stiffness_layout = QtGui.QHBoxLayout()
        self.torsion_damping_layout = QtGui.QHBoxLayout()
        self.stiffness_label = QtGui.QLabel(__("Stiffness (N/m):"))
        self.stiffness_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.stiffness))
        self.damping_label = QtGui.QLabel(__("Damping (Ns/m):"))
        self.damping_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.damping))

        self.torsion_stiffness_layout.addWidget(self.stiffness_label)
        self.torsion_stiffness_layout.addWidget(self.stiffness_line_edit)
        self.torsion_damping_layout.addWidget(self.damping_label)
        self.torsion_damping_layout.addWidget(self.damping_line_edit)

        self.link_linearspring_edit_layout.addLayout(
            self.torsion_stiffness_layout)
        self.link_linearspring_edit_layout.addLayout(
            self.torsion_damping_layout)

        # Spring equilibrium length
        self.rest_layout = QtGui.QHBoxLayout()
        self.rest_label = QtGui.QLabel(__("Rest length (m):"))
        self.rest_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.rest_length))

        self.rest_layout.addWidget(self.rest_label)
        self.rest_layout.addWidget(self.rest_line_edit)

        self.link_linearspring_edit_layout.addLayout(self.rest_layout)

        # vtk
        self.visualization_options_groupbox = QtGui.QGroupBox(
            __("Visualization Options"))
        self.vtk_layout = QtGui.QHBoxLayout()
        self.vtk_nside_label = QtGui.QLabel(__("Number of sections: "))
        self.vtk_nside_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.number_of_sections))
        self.vtk_radius_label = QtGui.QLabel(__("Spring radius: "))
        self.vtk_radius_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.spring_radius))
        self.vtk_length_label = QtGui.QLabel(__("Length for revolution: "))
        self.vtk_length_line_edit = QtGui.QLineEdit(
            str(target_link_linearspring.revolution_length))

        self.vtk_layout.addWidget(self.vtk_nside_label)
        self.vtk_layout.addWidget(self.vtk_nside_line_edit)
        self.vtk_layout.addWidget(self.vtk_radius_label)
        self.vtk_layout.addWidget(self.vtk_radius_line_edit)
        self.vtk_layout.addWidget(self.vtk_length_label)
        self.vtk_layout.addWidget(self.vtk_length_line_edit)

        self.visualization_options_groupbox.setLayout(self.vtk_layout)
        self.link_linearspring_edit_layout.addWidget(
            self.visualization_options_groupbox)

        # Buttons
        self.ok_button = QtGui.QPushButton("Save")
        self.ok_button.clicked.connect(self.on_save)
        self.cancel_button = QtGui.QPushButton("Cancel")
        self.cancel_button.clicked.connect(self.on_cancel)
        self.button_layout = QtGui.QHBoxLayout()
        self.button_layout.addStretch(1)

        self.button_layout.addWidget(self.ok_button)
        self.button_layout.addWidget(self.cancel_button)

        self.link_linearspring_edit_layout.addLayout(self.button_layout)

        # Add the elements to the window
        self.setLayout(self.link_linearspring_edit_layout)
        self.exec_()
    def on_ex_simulate(self):
        """ Defines what happens on simulation button press.
            It shows the run window and starts a background process with dualsphysics running. Updates the window with useful info."""

        refocus_cwd()

        if Case.the().info.needs_to_run_gencase:
            # Warning window about save_case
            warning_dialog("You should run GenCase again. Otherwise, the obtained results may not be as expected")

        static_params_exe = [Case.the().get_out_xml_file_path(),
                             Case.the().get_out_folder_path(),
                             "-{device}".format(device=self.device_selector.currentText().lower()),
                             "-svres"]

        additional_parameters = list()
        if Case.the().info.run_additional_parameters:
            additional_parameters = Case.the().info.run_additional_parameters.split(" ")

        final_params_ex = static_params_exe + additional_parameters
        cmd_string = "{} {}".format(Case.the().executable_paths.dsphysics, " ".join(final_params_ex))

        run_dialog = RunDialog(case_name=Case.the().name, processor=self.device_selector.currentText(), number_of_particles=Case.the().info.particle_number, cmd_string=cmd_string, parent=get_fc_main_window())
        run_dialog.set_value(0)
        run_dialog.run_update(0, 0, None)
        Case.the().info.is_simulation_done = False

        run_fs_watcher = QtCore.QFileSystemWatcher()

        self.simulation_started.emit()

        # Cancel button handler
        def on_cancel():
            log(__("Stopping simulation"))
            if process:
                process.kill()
            run_dialog.hide_all()
            Case.the().info.is_simulation_done = True
            self.simulation_cancelled.emit()

        run_dialog.cancelled.connect(on_cancel)

        # Launch simulation and watch filesystem to monitor simulation
        filelist = [f for f in os.listdir(Case.the().path + "/" + Case.the().name + "_out/") if f.startswith("Part")]
        for f in filelist:
            os.remove(Case.the().path + "/" + Case.the().name + "_out/" + f)

        def on_dsph_sim_finished(exit_code):
            """ Simulation finish handler. Defines what happens when the process finishes."""

            # Reads output and completes the progress bar
            output = str(process.readAllStandardOutput().data(), encoding='utf-8')

            run_dialog.set_detail_text(str(output))
            run_dialog.run_complete()

            run_fs_watcher.removePath(Case.the().path + "/" + Case.the().name + "_out/")

            if exit_code == 0:
                # Simulation went correctly
                Case.the().info.is_simulation_done = True
                Case.the().info.needs_to_run_gencase = False
                self.simulation_complete.emit(True)
            else:
                # In case of an error
                Case.the().info.needs_to_run_gencase = True
                if "exception" in str(output).lower():
                    log("There was an error on the execution. Opening an error dialog for that.")
                    run_dialog.hide()
                    self.simulation_complete.emit(False)
                    error_dialog(__("An error occurred during execution. Make sure that parameters exist and are properly defined. "
                                    "You can also check your execution device (update the driver of your GPU). Read the details for more information."), str(output))
            save_case(Case.the().path, Case.the())

        # Launches a QProcess in background
        process = QtCore.QProcess(get_fc_main_window())
        process.finished.connect(on_dsph_sim_finished)

        process.start(Case.the().executable_paths.dsphysics, final_params_ex)

        def on_fs_change():
            """ Executed each time the filesystem changes. This updates the percentage of the simulation and its details."""
            run_file_data = ""
            with open(Case.the().path + "/" + Case.the().name + "_out/Run.out", "r") as run_file:
                run_file_data = run_file.readlines()

            # Fill details window
            run_dialog.set_detail_text("".join(run_file_data))

            # Set percentage scale based on timemax
            for l in run_file_data:
                if Case.the().execution_parameters.timemax == -1:
                    if "TimeMax=" in l:
                        Case.the().execution_parameters.timemax = float(l.split("=")[1])

            current_value: float = 0.0
            totalpartsout: int = 0
            last_estimated_time = None

            # Update execution metrics
            last_part_lines = list(filter(lambda x: "Part_" in x and "stored" not in x and "      " in x, run_file_data))
            if last_part_lines:
                current_value = (float(last_part_lines[-1].split(None)[1]) * float(100)) / float(Case.the().execution_parameters.timemax)
            else:
                current_value = None

            # Update particles out
            last_particles_out_lines = list(filter(lambda x: "(total: " in x and "Particles out:" in x, run_file_data))
            if last_particles_out_lines:
                totalpartsout = int(last_particles_out_lines[-1].split("(total: ")[1].split(")")[0])

            try:
                last_estimated_time = str(" ".join(last_part_lines[-1].split(None)[-2:]))
            except IndexError:
                last_estimated_time = None

            # Update run dialog
            run_dialog.run_update(current_value, totalpartsout, last_estimated_time)

        # Set filesystem watcher to the out directory.
        run_fs_watcher.addPath(Case.the().path + "/" + Case.the().name + "_out/")
        run_fs_watcher.directoryChanged.connect(on_fs_change)

        # Handle error on simulation start
        if process.state() == QtCore.QProcess.NotRunning:
            # Probably error happened.
            run_fs_watcher.removePath(Case.the().path + "/" + Case.the().name + "_out/")
            process = None
            error_dialog("Error on simulation start. Check that the DualSPHysics executable is correctly set.")
        else:
            run_dialog.show()
    def __init__(self, link_spheric_id, bodies_widgets, parent=None):
        super().__init__(parent=parent)

        self.case = Case.the()
        self.link_spheric_id = link_spheric_id

        # Title
        self.setWindowTitle(__("Link spheric configuration"))
        self.link_spheric_edit_layout = QtGui.QVBoxLayout()

        # Find the link spheric for which the button was pressed
        target_link_spheric = None

        for link_spheric in self.case.chrono.link_spheric:
            if link_spheric.id == self.link_spheric_id:
                target_link_spheric = link_spheric

        # This should not happen but if no link spheric is found with reference id, it spawns an error.
        if target_link_spheric is None:
            error_dialog("There was an error opnening the link spheric to edit")
            return

        # Elements that interact
        self.body_layout = QtGui.QHBoxLayout()
        self.body_one_label = QtGui.QLabel(__("Body 1: "))
        self.body_one_line_edit = QtGui.QComboBox()
        if str(target_link_spheric.idbody1) != "":
            self.body_one_line_edit.insertItems(0, ["", str(target_link_spheric.idbody1)])
            self.body_one_line_edit.setCurrentIndex(1)
        else:
            self.body_one_line_edit.insertItems(0, [str(target_link_spheric.idbody1)])
        for body in bodies_widgets:
            if body.object_check.isChecked() and body.object_name != str(target_link_spheric.idbody1):
                self.body_one_line_edit.insertItems(0, [body.object_name])
        self.body_two_label = QtGui.QLabel(__("Body 2: "))
        self.body_two_line_edit = QtGui.QComboBox()
        if str(target_link_spheric.idbody2) != "":
            self.body_two_line_edit.insertItems(0, ["", str(target_link_spheric.idbody2)])
            self.body_two_line_edit.setCurrentIndex(1)
        else:
            self.body_two_line_edit.insertItems(0, [str(target_link_spheric.idbody2)])
        for body in bodies_widgets:
            if body.object_check.isChecked() and body.object_name != str(target_link_spheric.idbody2):
                self.body_two_line_edit.insertItems(0, [body.object_name])
        self.body_to_body_label = QtGui.QLabel(__("to"))

        self.body_layout.addWidget(self.body_one_label)
        self.body_layout.addWidget(self.body_one_line_edit)
        self.body_layout.addWidget(self.body_to_body_label)
        self.body_layout.addWidget(self.body_two_label)
        self.body_layout.addWidget(self.body_two_line_edit)
        self.body_layout.addStretch(1)

        self.link_spheric_edit_layout.addLayout(self.body_layout)

        # Points where the elements interact
        self.points_layout = QtGui.QHBoxLayout()
        self.points_label = QtGui.QLabel(__("Points: "))
        self.point_x_label = QtGui.QLabel(__("X"))
        self.point_x_line_edit = QtGui.QLineEdit(str(target_link_spheric.rotpoint[0]))
        self.point_y_label = QtGui.QLabel(__("Y"))
        self.point_y_line_edit = QtGui.QLineEdit(str(target_link_spheric.rotpoint[1]))
        self.point_z_label = QtGui.QLabel(__("Z"))
        self.point_z_line_edit = QtGui.QLineEdit(str(target_link_spheric.rotpoint[2]))

        self.points_layout.addWidget(self.points_label)
        self.points_layout.addWidget(self.point_x_label)
        self.points_layout.addWidget(self.point_x_line_edit)
        self.points_layout.addWidget(self.point_y_label)
        self.points_layout.addWidget(self.point_y_line_edit)
        self.points_layout.addWidget(self.point_z_label)
        self.points_layout.addWidget(self.point_z_line_edit)

        self.link_spheric_edit_layout.addLayout(self.points_layout)

        # Torsion options
        self.torsion_stiffness_layout = QtGui.QHBoxLayout()
        self.torsion_damping_layout = QtGui.QHBoxLayout()
        self.stiffness_label = QtGui.QLabel(__("Stiffness (Nm/rad):"))
        self.stiffness_line_edit = QtGui.QLineEdit(str(target_link_spheric.stiffness))
        self.damping_label = QtGui.QLabel(__("Damping (Nms/rad):"))
        self.damping_line_edit = QtGui.QLineEdit(str(target_link_spheric.damping))

        self.torsion_stiffness_layout.addWidget(self.stiffness_label)
        self.torsion_stiffness_layout.addWidget(self.stiffness_line_edit)
        self.torsion_damping_layout.addWidget(self.damping_label)
        self.torsion_damping_layout.addWidget(self.damping_line_edit)

        self.link_spheric_edit_layout.addLayout(self.torsion_stiffness_layout)
        self.link_spheric_edit_layout.addLayout(self.torsion_damping_layout)

        # Buttons
        self.ok_button = QtGui.QPushButton("Save")
        self.ok_button.clicked.connect(self.on_save)
        self.cancel_button = QtGui.QPushButton("Cancel")
        self.cancel_button.clicked.connect(self.on_cancel)
        self.button_layout = QtGui.QHBoxLayout()
        self.button_layout.addStretch(1)

        self.button_layout.addWidget(self.ok_button)
        self.button_layout.addWidget(self.cancel_button)

        self.link_spheric_edit_layout.addLayout(self.button_layout)

        # Add the elements to the window
        self.setLayout(self.link_spheric_edit_layout)
        self.exec_()
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        self.main_layout = QtGui.QVBoxLayout()
        self.main_layout.setContentsMargins(0, 0, 0, 0)

        self.label_layout = QtGui.QHBoxLayout()
        self.first_row_layout = QtGui.QHBoxLayout()
        self.second_row_layout = QtGui.QHBoxLayout()
        self.third_row_layout = QtGui.QHBoxLayout()
        self.fourth_row_layout = QtGui.QHBoxLayout()

        self.casecontrols_label = QtGui.QLabel("<b>{}</b>".format(
            __("Pre-processing")))
        self.force_button = QtGui.QPushButton(__("Force Enable Panels"))
        self.force_button.setStyleSheet(
            "font-size: 8px; max-height: 10px; padding-bottom: 0; padding-top: 0; padding-left:2px; padding-right: 2px"
        )

        self.new_case_button = QtGui.QToolButton()
        self.new_case_button.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
        self.new_case_button.setToolButtonStyle(
            QtCore.Qt.ToolButtonTextBesideIcon)
        self.new_case_button.setText("  {}".format(__("New\n  Case")))
        self.new_case_button.setToolTip(
            __("Creates a new case. \nThe opened documents will be closed."))
        self.new_case_button.setIcon(
            QtGui.QIcon.fromTheme("document-new", get_icon("new.png")))
        self.new_case_button.setIconSize(QtCore.QSize(28, 28))

        self.new_case_menu = QtGui.QMenu()
        self.new_case_menu.addAction(
            QtGui.QIcon.fromTheme("document-new", get_icon("new.png")),
            __("New"))
        self.new_case_menu.addAction(
            QtGui.QIcon.fromTheme("document-new", get_icon("new.png")),
            __("Import FreeCAD Document"))

        self.new_case_button.setMenu(self.new_case_menu)
        self.new_case_menu.resize(60, 60)

        self.save_button = QtGui.QToolButton()
        self.save_button.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
        self.save_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
        self.save_button.setText("  {}".format(__("Save\n  Case")))
        self.save_button.setToolTip(__("Saves the case."))
        self.save_button.setIcon(
            QtGui.QIcon.fromTheme("document-save", get_icon("save.png")))
        self.save_button.setIconSize(QtCore.QSize(28, 28))
        self.save_menu = QtGui.QMenu()
        self.save_menu.addAction(
            QtGui.QIcon.fromTheme("document-save-as", get_icon("save.png")),
            __("Save as..."))
        self.save_button.setMenu(self.save_menu)

        self.load_button = QtGui.QToolButton()
        self.load_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
        self.load_button.setText("  {}".format(__("Load\n  Case")))
        self.load_button.setToolTip(
            __("Loads a case from disk. All the current documents\nwill be closed."
               ))
        self.load_button.setIcon(
            QtGui.QIcon.fromTheme("document-open", get_icon("load.png")))
        self.load_button.setIconSize(QtCore.QSize(28, 28))

        self.add_fillbox_button = QtGui.QPushButton(__("Add fillbox"))
        self.add_fillbox_button.setToolTip(
            __("Adds a FillBox. A FillBox is able to fill an empty space\nwithin limits of geometry and a maximum bounding\nbox placed by the user."
               ))
        self.add_fillbox_button.setIcon(QtGui.QIcon.fromTheme("list-add"))

        self.add_geometry_button = QtGui.QPushButton("Import GEO")
        self.add_geometry_button.setToolTip(
            __("Imports a GEO object with postprocessing. This way you can set the scale of the imported object."
               ))
        self.add_geometry_button.setIcon(QtGui.QIcon.fromTheme("list-add"))

        self.import_xml_button = QtGui.QPushButton(__("Import XML"))
        self.import_xml_button.setToolTip(
            __("Imports an already created XML case from disk."))

        self.case_summary_button = QtGui.QPushButton(__("Case summary"))
        self.case_summary_button.setToolTip(
            __("Shows a complete case summary with objects, configurations and settings in a brief view."
               ))
        self.case_summary_button.setIcon(
            QtGui.QIcon.fromTheme("document-properties"))

        self.toggle_2d_mode_button = QtGui.QPushButton(__("Change 3D/2D"))
        self.toggle_2d_mode_button.setToolTip(
            __("Changes the case mode between 2D and 3D mode, switching the Case Limits between a plane or a cube"
               ))
        self.toggle_2d_mode_button.setIcon(
            QtGui.QIcon.fromTheme("object-flip-horizontal"))

        self.special_button = QtGui.QPushButton(__("Special"))
        self.special_button.setToolTip(__("Special actions for the case."))
        self.special_button.setIcon(QtGui.QIcon.fromTheme("window-new"))

        self.gencase_button = QtGui.QPushButton(__("Run GenCase"))
        self.gencase_button.setStyleSheet("QPushButton {font-weight: bold; }")
        self.gencase_button.setToolTip(
            __("This pre-processing tool creates the initial state of the particles (position, velocity and density) and defines the different SPH parameters for the simulation."
               ))
        self.gencase_button.setIcon(get_icon("run_gencase.png"))
        self.gencase_button.setIconSize(QtCore.QSize(12, 12))

        self.force_button.clicked.connect(self.on_force_button)
        self.new_case_button.clicked.connect(lambda: self.on_new_case(True))
        self.save_button.clicked.connect(self.on_save_case)
        self.gencase_button.clicked.connect(self.on_execute_gencase)
        self.new_case_menu.triggered.connect(self.on_newdoc_menu)
        self.save_menu.triggered.connect(self.on_save_menu)
        self.load_button.clicked.connect(self.on_load_button)
        self.add_fillbox_button.clicked.connect(self.on_add_fillbox)
        self.add_geometry_button.clicked.connect(self.on_add_geo)
        self.import_xml_button.clicked.connect(lambda: error_dialog(
            "XML Import is not available in this version."))
        self.case_summary_button.clicked.connect(CaseSummary)
        self.toggle_2d_mode_button.clicked.connect(self.on_2d_toggle)
        self.special_button.clicked.connect(SpecialOptionsSelectorDialog)

        self.label_layout.addWidget(self.casecontrols_label)
        self.label_layout.addStretch(1)
        self.label_layout.addWidget(self.force_button)
        self.first_row_layout.addWidget(self.new_case_button)
        self.first_row_layout.addWidget(self.save_button)
        self.first_row_layout.addWidget(self.load_button)
        self.second_row_layout.addWidget(self.case_summary_button)
        self.second_row_layout.addWidget(self.toggle_2d_mode_button)
        self.third_row_layout.addWidget(self.add_fillbox_button)
        self.third_row_layout.addWidget(self.add_geometry_button)
        # self.third_row_layout.addWidget(self.import_xml_button)
        self.fourth_row_layout.addWidget(self.special_button)
        self.fourth_row_layout.addWidget(self.gencase_button)

        self.main_layout.addLayout(self.label_layout)
        self.main_layout.addLayout(self.first_row_layout)
        self.main_layout.addLayout(self.third_row_layout)
        self.main_layout.addLayout(self.second_row_layout)
        self.main_layout.addLayout(self.fourth_row_layout)

        self.setLayout(self.main_layout)
    def on_multilayeredmb_menu(self, action):
        """ Defines MLPiston menu behaviour"""
        # Get currently selected object
        try:
            selection = FreeCADGui.Selection.getSelection()[0]
        except IndexError:
            error_dialog(__("You must select an object"))
            return

        # Check if object is in the simulation
        if not Case.the().is_object_in_simulation(selection.Name):
            error_dialog(
                __("The selected object must be added to the simulation"))
            return

        # Check if it is fluid and warn the user.
        if Case.the().get_simulation_object(
                selection.Name).type == ObjectType.FLUID:
            error_dialog(
                __("You can't apply a piston movement to a fluid.\nPlease select a boundary and try again"
                   ))
            return

        # Get selection mk
        selection_obj = Case.the().get_simulation_object(selection.Name)
        selection_mk: int = selection_obj.obj_mk
        mk_properties: MKBasedProperties = Case.the().get_mk_based_properties(
            selection_obj.type, selection_mk)

        # Check that this mk has no other motions applied
        if mk_properties.has_movements():
            # MK has motions applied. Warn the user and delete them
            motion_delete_warning = ok_cancel_dialog(
                APP_NAME,
                __("This mk already has motions applied. Setting a Multi-layered piston will delete all of its movement. Are you sure?"
                   ))
            if motion_delete_warning == QtGui.QMessageBox.Cancel:
                return
            mk_properties.remove_all_movements()

        # 1D or 2D piston
        if __("1 Dimension") in action.text():
            if mk_properties.mlayerpiston and not isinstance(
                    mk_properties.mlayerpiston, MLPiston1D):
                overwrite_warn = ok_cancel_dialog(
                    APP_NAME,
                    __("You're about to overwrite a previous coupling movement for this mk. Are you sure?"
                       ))
                if overwrite_warn == QtGui.QMessageBox.Cancel:
                    return

            config_dialog = MLPiston1DConfigDialog(selection_mk,
                                                   mk_properties.mlayerpiston,
                                                   parent=get_fc_main_window())
            if config_dialog.result() == QtGui.QDialog.Accepted:
                warning_dialog(
                    __("All changes have been applied for mk = {}").format(
                        selection_mk))
            mk_properties.mlayerpiston = config_dialog.mlpiston1d

        if __("2 Dimensions") in action.text():
            # Check that there's no other multilayered piston for this mk
            if mk_properties.mlayerpiston and not isinstance(
                    mk_properties.mlayerpiston, MLPiston2D):
                overwrite_warn = ok_cancel_dialog(
                    APP_NAME,
                    __("You're about to overwrite a previous coupling movement for this mk. Are you sure?"
                       ))
                if overwrite_warn == QtGui.QMessageBox.Cancel:
                    return

            config_dialog = MLPiston2DConfigDialog(selection_mk,
                                                   mk_properties.mlayerpiston,
                                                   parent=get_fc_main_window())
            if config_dialog.result() == QtGui.QDialog.Accepted:
                warning_dialog(
                    __("All changes have been applied for mk = {}").format(
                        selection_mk))
            mk_properties.mlayerpiston = config_dialog.mlpiston2d

        self.accept()
Esempio n. 29
0
                # Probably already copied the file.
                pass
            except IOError:
                error("Unable to copy {} into {}".format(filename, save_name))

    # Dumps all the case data to an XML file.
    XMLExporter().save_to_disk(save_name, case)

    case.version = VERSION
    # Save data array on disk. It is saved as a binary file with Pickle.
    try:
        with open(save_name + "/casedata.dsphdata", "wb") as picklefile:
            pickle.dump(case, picklefile, PICKLE_PROTOCOL)
    except Exception:
        print_exc()
        error_dialog(__("There was a problem saving the DSPH information file (casedata.dsphdata)."))

    refocus_cwd()


def get_default_config_file():
    """ Gets the default-config.json from disk """
    current_script_folder = path.dirname(path.realpath(__file__))
    with open("{}/../default-config.json".format(current_script_folder)) as data_file:
        loaded_data = json.load(data_file)

    if "win" in platform:
        to_ret = loaded_data["windows"]
    elif "linux" in platform:
        to_ret = loaded_data["linux"]
    def __init__(self, link_pointline_id, bodies_widgets, parent=None):
        super().__init__(parent=parent)

        self.case = Case.the()
        self.link_pointline_id = link_pointline_id

        # Title
        self.setWindowTitle(__("Link pointline configuration"))
        self.link_pointline_edit_layout = QtGui.QVBoxLayout()

        # Find the link pointline for which the button was pressed
        target_link_pointline = None

        for link_pointline in self.case.chrono.link_pointline:
            if link_pointline.id == self.link_pointline_id:
                target_link_pointline = link_pointline

        # This should not happen but if no link pointline is found with reference id, it spawns an error.
        if target_link_pointline is None:
            error_dialog("There was an error opnening the link pointline to edit")
            return

        # Elements that interact
        self.body_layout = QtGui.QHBoxLayout()
        self.body_one_label = QtGui.QLabel(__("Body 1: "))
        self.body_one_line_edit = QtGui.QComboBox()
        if str(target_link_pointline.idbody1) != "":
            self.body_one_line_edit.insertItems(0, ["", str(target_link_pointline.idbody1)])
            self.body_one_line_edit.setCurrentIndex(1)
        else:
            self.body_one_line_edit.insertItems(0, [str(target_link_pointline.idbody1)])
        for body in bodies_widgets:
            if body.object_check.isChecked() and body.object_name != str(target_link_pointline.idbody1):
                self.body_one_line_edit.insertItems(0, [body.object_name])
        self.body_layout.addWidget(self.body_one_label)
        self.body_layout.addWidget(self.body_one_line_edit)
        self.body_layout.addStretch(1)

        self.link_pointline_edit_layout.addLayout(self.body_layout)

        # Vector direction for sliding axis
        self.sliding_vector_layout = QtGui.QHBoxLayout()
        self.sliding_vector_label = QtGui.QLabel(__("Sliding Vector: "))
        self.sliding_vector_x_label = QtGui.QLabel(__("X"))
        self.sliding_vector_x_line_edit = QtGui.QLineEdit(str(target_link_pointline.slidingvector[0]))
        self.sliding_vector_y_label = QtGui.QLabel(__("Y"))
        self.sliding_vector_y_line_edit = QtGui.QLineEdit(str(target_link_pointline.slidingvector[1]))
        self.sliding_vector_z_label = QtGui.QLabel(__("Z"))
        self.sliding_vector_z_line_edit = QtGui.QLineEdit(str(target_link_pointline.slidingvector[2]))

        self.sliding_vector_layout.addWidget(self.sliding_vector_label)
        self.sliding_vector_layout.addWidget(self.sliding_vector_x_label)
        self.sliding_vector_layout.addWidget(self.sliding_vector_x_line_edit)
        self.sliding_vector_layout.addWidget(self.sliding_vector_y_label)
        self.sliding_vector_layout.addWidget(self.sliding_vector_y_line_edit)
        self.sliding_vector_layout.addWidget(self.sliding_vector_z_label)
        self.sliding_vector_layout.addWidget(self.sliding_vector_z_line_edit)

        self.link_pointline_edit_layout.addLayout(self.sliding_vector_layout)

        # Point for rotation
        self.rotpoint_layout = QtGui.QHBoxLayout()
        self.rotpoint_label = QtGui.QLabel(__("Point for rotation: "))
        self.rotpoint_x_label = QtGui.QLabel(__("X"))
        self.rotpoint_x_line_edit = QtGui.QLineEdit(str(target_link_pointline.rotpoint[0]))
        self.rotpoint_y_label = QtGui.QLabel(__("Y"))
        self.rotpoint_y_line_edit = QtGui.QLineEdit(str(target_link_pointline.rotpoint[1]))
        self.rotpoint_z_label = QtGui.QLabel(__("Z"))
        self.rotpoint_z_line_edit = QtGui.QLineEdit(str(target_link_pointline.rotpoint[2]))

        self.rotpoint_layout.addWidget(self.rotpoint_label)
        self.rotpoint_layout.addWidget(self.rotpoint_x_label)
        self.rotpoint_layout.addWidget(self.rotpoint_x_line_edit)
        self.rotpoint_layout.addWidget(self.rotpoint_y_label)
        self.rotpoint_layout.addWidget(self.rotpoint_y_line_edit)
        self.rotpoint_layout.addWidget(self.rotpoint_z_label)
        self.rotpoint_layout.addWidget(self.rotpoint_z_line_edit)

        self.link_pointline_edit_layout.addLayout(self.rotpoint_layout)

        # Vector direction for rotation
        self.rotvector_layout = QtGui.QHBoxLayout()
        self.rotvector_label = QtGui.QLabel(__("Vector direction: "))
        self.rotvector_x_label = QtGui.QLabel(__("X"))
        self.rotvector_x_line_edit = QtGui.QLineEdit(str(target_link_pointline.rotvector[0]))
        self.rotvector_y_label = QtGui.QLabel(__("Y"))
        self.rotvector_y_line_edit = QtGui.QLineEdit(str(target_link_pointline.rotvector[1]))
        self.rotvector_z_label = QtGui.QLabel(__("Z"))
        self.rotvector_z_line_edit = QtGui.QLineEdit(str(target_link_pointline.rotvector[2]))

        self.rotvector_layout.addWidget(self.rotvector_label)
        self.rotvector_layout.addWidget(self.rotvector_x_label)
        self.rotvector_layout.addWidget(self.rotvector_x_line_edit)
        self.rotvector_layout.addWidget(self.rotvector_y_label)
        self.rotvector_layout.addWidget(self.rotvector_y_line_edit)
        self.rotvector_layout.addWidget(self.rotvector_z_label)
        self.rotvector_layout.addWidget(self.rotvector_z_line_edit)

        self.link_pointline_edit_layout.addLayout(self.rotvector_layout)

        # Second vector to avoid rotation
        self.rotvector2_layout = QtGui.QHBoxLayout()
        self.rotvector2_label = QtGui.QLabel(__("Second vector: "))
        self.rotvector2_x_label = QtGui.QLabel(__("X"))
        self.rotvector2_x_line_edit = QtGui.QLineEdit(str(target_link_pointline.rotvector2[0]))
        self.rotvector2_y_label = QtGui.QLabel(__("Y"))
        self.rotvector2_y_line_edit = QtGui.QLineEdit(str(target_link_pointline.rotvector2[1]))
        self.rotvector2_z_label = QtGui.QLabel(__("Z"))
        self.rotvector2_z_line_edit = QtGui.QLineEdit(str(target_link_pointline.rotvector2[2]))

        self.rotvector2_layout.addWidget(self.rotvector2_label)
        self.rotvector2_layout.addWidget(self.rotvector2_x_label)
        self.rotvector2_layout.addWidget(self.rotvector2_x_line_edit)
        self.rotvector2_layout.addWidget(self.rotvector2_y_label)
        self.rotvector2_layout.addWidget(self.rotvector2_y_line_edit)
        self.rotvector2_layout.addWidget(self.rotvector2_z_label)
        self.rotvector2_layout.addWidget(self.rotvector2_z_line_edit)

        self.link_pointline_edit_layout.addLayout(self.rotvector2_layout)

        # Torsion options
        self.torsion_stiffness_layout = QtGui.QHBoxLayout()
        self.torsion_damping_layout = QtGui.QHBoxLayout()
        self.stiffness_label = QtGui.QLabel(__("Stiffness"))
        self.stiffness_line_edit = QtGui.QLineEdit(str(target_link_pointline.stiffness))
        self.damping_label = QtGui.QLabel(__("Damping"))
        self.damping_line_edit = QtGui.QLineEdit(str(target_link_pointline.damping))

        self.torsion_stiffness_layout.addWidget(self.stiffness_label)
        self.torsion_stiffness_layout.addWidget(self.stiffness_line_edit)
        self.torsion_damping_layout.addWidget(self.damping_label)
        self.torsion_damping_layout.addWidget(self.damping_line_edit)

        self.link_pointline_edit_layout.addLayout(self.torsion_stiffness_layout)
        self.link_pointline_edit_layout.addLayout(self.torsion_damping_layout)

        # Buttons
        self.ok_button = QtGui.QPushButton("Save")
        self.ok_button.clicked.connect(self.on_save)
        self.cancel_button = QtGui.QPushButton("Cancel")
        self.cancel_button.clicked.connect(self.on_cancel)
        self.button_layout = QtGui.QHBoxLayout()
        self.button_layout.addStretch(1)

        self.button_layout.addWidget(self.ok_button)
        self.button_layout.addWidget(self.cancel_button)

        self.link_pointline_edit_layout.addLayout(self.button_layout)

        # Add the elements to the window
        self.setLayout(self.link_pointline_edit_layout)
        self.exec_()