def on_change(self):
     """ Reacts to any change, sanitizing it and firing a signal with the appropriate data object. """
     self._sanitize_input()
     try:
         self.changed.emit(self.index, self.construct_motion_object())
     except ValueError:
         debug("Introduced an invalid value for a float number.")
예제 #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_change(self):
     """ Reacts to changes on the widget, sanitizes the input and fires an event with the resulting object. """
     self._sanitize_input()
     try:
         self.changed.emit(0, self.construct_motion_object())
     except ValueError:
         debug("Introduced an invalid value for a float number.")
 def on_change(self):
     """ Reacts to data changing and sanitizes the input data. """
     self._sanitize_input()
     try:
         self.changed.emit(self.index, self.construct_motion_object())
     except ValueError:
         debug("Introduced an invalid value for a float number.")
    def __init__(self, executable_paths: ExecutablePaths):
        super().__init__()
        self._executable_paths = executable_paths

        self.setWindowTitle(__("DualSPHysics Suite Feature Report"))

        self.root_layout = QtGui.QVBoxLayout()

        self.report_text = QtGui.QTextEdit()
        self.report_text.setReadOnly(True)

        self.button_layout = QtGui.QHBoxLayout()
        self.ok_button = QtGui.QPushButton(__("OK"))

        self.button_layout.addStretch(1)
        self.button_layout.addWidget(self.ok_button)

        self.root_layout.addWidget(self.report_text)
        self.root_layout.addLayout(self.button_layout)

        self.fill_report()

        self.setLayout(self.root_layout)
        self.setMinimumWidth(self.MIN_WIDTH)
        self.setMinimumHeight(self.MIN_HEIGHT)

        self.ok_button.clicked.connect(self.on_ok)

        debug("Executable paths are: ")
        debug(executable_paths)
예제 #6
0
    def on_mkgroup_change(self, value):
        """ Defines what happens when MKGroup is changed. """
        new_value: int = value
        old_value: int = self.last_mk_value

        # First we do what the user want
        Case.the().get_simulation_object(
            FreeCADGui.Selection.getSelection()[0].Name).obj_mk = new_value
        self.last_mk_value = new_value

        # Then we check that it is sensible
        orphan_mkbasedproperties: list = Case.the(
        ).get_orphan_mkbasedproperties()
        if orphan_mkbasedproperties:
            response = ok_cancel_dialog(
                __("Changing MK value"),
                __("By doing this you will loose all MK configuration for the previous MK: {}. Are you sure you want to do this?"
                   ).format(old_value))
            if response == QtGui.QMessageBox.Ok:
                debug(
                    "Changing from mk {} to {} caused orphan mkbasedproperties. Deleting..."
                    .format(old_value, new_value))
                Case.the().delete_orphan_mkbasedproperties()
            else:
                self.mkgroup_prop.setValue(old_value)
예제 #7
0
 def on_change(self):
     """ Reacts to any input changes, sanitizes it and fires a signal with the corresponding data object. """
     self._sanitize_input()
     try:
         self.changed.emit(self.index, self.construct_motion_object())
     except ValueError:
         debug("Introduced an invalid value for a float number.")
예제 #8
0
 def shift_object_up_in_order(self, index) -> None:
     """ Moves an object up in the order. """
     corrected_index = index + 1
     if 2 <= corrected_index < len(self.objects):
         debug("Object has right condition to shift up")
         self.objects.insert(corrected_index - 1,
                             self.objects.pop(corrected_index))
예제 #9
0
 def on_change(self):
     """ Reacts to a change and emits an object construction signal. """
     self._sanitize_input()
     try:
         self.changed.emit(self.index, self.construct_motion_object())
     except ValueError:
         debug("Introduced an invalid value for a float number.")
 def on_change(self):
     """ Reacts to any change on the widget, sanitizes the input and fires a signal with the corresponding motion object """
     self._sanitize_input()
     try:
         self.changed.emit(0, self.construct_motion_object())
     except ValueError:
         debug("Introduced an invalid value for a number.")
예제 #11
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)
예제 #12
0
 def __getattr__(self, attr):
     if attr == "frdrawmode":
         debug(
             "frdrawmode property in simulation object <{}> nonexistent: Creating one"
             .format(self.name))
         self.frdrawmode: bool = False
         return self.frdrawmode
     raise AttributeError()
 def on_change(self):
     """ Reacts to input change, sanitizing it and firing a signal with the correspondent data object. """
     self._sanitize_input()
     self._awas_enabled_handler()
     try:
         self.changed.emit(0, self.construct_motion_object())
     except ValueError:
         debug("Introduced an invalid value for a float number.")
 def on_change(self):
     """ Reacts to any input change sanitizing it and firing a signal with the appropriate data object. """
     if not self.time_input.text():
         self.time_input.setText("0")
     self.time_input.setText(self.time_input.text().replace(",", "."))
     try:
         self.changed.emit(self.index, self.construct_motion_object())
     except ValueError:
         debug("Introduced an invalid value for a float number")
예제 #15
0
 def get_mk_based_properties(self, obj_type: ObjectType, mknumber: int) -> MKBasedProperties:
     """ Returns the properties set for a given MK number of a given type """
     if obj_type == ObjectType.BOUND:
         mknumber += MKFLUID_LIMIT
     if not self.has_mk_properties(mknumber):
         debug("Creating MKBasedProperties on demand for realmk: {}".format(mknumber))
         self.mkbasedproperties[mknumber] = MKBasedProperties(mk=mknumber)
     debug("Returning MKBasedProperties object for realmk: {}".format(mknumber))
     return self.mkbasedproperties[mknumber]
예제 #16
0
def delete_existing_docks():
    """ Searches for existing docks related to DesignSPHysics destroys them. """
    for previous_dock in [
            get_fc_main_window().findChild(QtGui.QDockWidget,
                                           MAIN_WIDGET_INTERNAL_NAME),
            get_fc_main_window().findChild(QtGui.QDockWidget,
                                           PROP_WIDGET_INTERNAL_NAME)
    ]:
        if previous_dock:
            debug("Removing previous {} dock".format(APP_NAME))
            previous_dock.setParent(None)
            previous_dock = None
예제 #17
0
 def __getattr__(self, attr):
     if attr == "refilling":
         debug(
             "refilling property in InletOutletZone <{}> nonexistent: Creating one"
             .format(self.id))
         self.refilling: InletOutletRefillingMode = InletOutletRefillingMode.SIMPLE_FULL
         return self.refilling
     if attr == "inputtreatment":
         debug(
             "inputtreatment property in InletOutletZone <{}> nonexistent: Creating one"
             .format(self.id))
         self.inputtreatment: InletOutletInputTreatment = InletOutletInputTreatment.NO_CHANGES
         return self.inputtreatment
     raise AttributeError()
예제 #18
0
def on_tree_item_selection_change(properties_widget, designsphysics_dock):
    """ Refreshes relevant parts of DesignsPHysics under an important change event. """
    debug("Syncronizing FreeCAD data structures with DesignSPHysics")
    selection = FreeCADGui.Selection.getSelection()
    properties_widget.set_add_button_enabled(True)

    if selection:
        if len(selection) > 1:
            # Multiple objects selected
            properties_widget.configure_to_add_multiple_selection()
        else:
            # One object selected
            if selection[0].Name == "Case_Limits" or "_internal_" in selection[
                    0].Name:
                properties_widget.configure_to_no_selection()
            elif Case.the().is_damping_bound_to_object(selection[0].Name):
                properties_widget.configure_to_damping_selection()
            elif Case.the().is_object_in_simulation(selection[0].Name):
                # Show properties on table
                properties_widget.configure_to_regular_selection()
                properties_widget.adapt_to_simulation_object(
                    Case.the().get_simulation_object(selection[0].Name),
                    selection[0])
            else:
                if not selection[0].InList:
                    # Show button to add to simulation
                    properties_widget.configure_to_add_single_selection()
                else:
                    properties_widget.configure_to_incompatible_object()
    else:
        properties_widget.configure_to_no_selection()

    # Delete invalid or already deleted (in FreeCAD) objects
    for object_name in Case.the().get_all_simulation_object_names():
        fc_object = get_fc_object(object_name)
        if not fc_object or fc_object.InList:
            Case.the().remove_object(object_name)

    for damping_to_delete in list(
            filter(lambda x: not get_fc_object(x),
                   Case.the().damping_zones)):
        Case.the().remove_damping_zone(damping_to_delete)

    # Update dsph objects list
    designsphysics_dock.refresh_object_list()
    properties_widget.fit_size()
    def _on_add_new_line(self):
        used_line_ids = list(
            map(lambda line: line.line_id, self.stored_configuration.lines))
        debug("Line ids currently in use: {}".format(used_line_ids))
        for i in range(
                0, 999):  # Note: I hope no one tries to create more lines...
            if i not in used_line_ids:
                break
        debug("Found this appropriate int for a new line id: {}".format(i))

        new_line: MoorDynLine = MoorDynLine(i)
        self.stored_configuration.lines.append(new_line)
        self.lines_table.setRowCount(self.lines_table.rowCount() + 1)
        widget: MoorDynLineWidget = MoorDynLineWidget(
            new_line.line_id,
            self.lines_table.rowCount() - 1)
        widget.configure_clicked.connect(
            lambda line_id=None: self._on_configure_line(line_id))
        widget.delete_clicked.connect(
            lambda line_id=None: self._on_delete_line(line_id))
        self.lines_table.setCellWidget(self.lines_table.rowCount() - 1, 0,
                                       widget)
    def update_to_save(self):
        """ Check all the conditions before save """

        # Clean the chrono object list
        self.case.chrono.objects = list()

        # Checks the chrono objects and options for save
        for elem in self.chrono_object_options_widgets:
            if not elem.object_check.isChecked():
                continue
            chrono_object = ChronoObject()
            chrono_object.id = elem.key
            chrono_object.name = elem.object_name
            chrono_object.mkbound = elem.object_mk
            chrono_object.modelnormal_enabled = elem.geometry_check.isChecked()
            chrono_object.modelnormal_type = {0: ChronoModelNormalType.ORIGINAL, 1: ChronoModelNormalType.INVERT, 2: ChronoModelNormalType.TWOFACE}[elem.modelnormal_input.currentIndex()]
            chrono_object.floating_type = elem.is_floating
            self.case.chrono.objects.append(chrono_object)

        # Checks the csv interval option for save
        if self.csv_intervals_checkbox.isChecked():
            self.case.chrono.csv_intervals.enabled = True
            try:
                self.case.chrono.csv_intervals.value = float(self.csv_intervals_line_edit.text())
            except ValueError:
                self.case.chrono.csv_intervals.enabled = False
                self.case.chrono.csv_intervals.value = ""
                debug("Introduced an invalid value for a float number.")
        else:
            self.case.chrono.csv_intervals.enabled = False
            self.case.chrono.csv_intervals.value = ""

        # Checks the scale scheme option for save
        if self.scale_scheme_checkbox.isChecked():
            self.case.chrono.scale_scheme.enabled = True
            try:
                self.case.chrono.scale_scheme.value = float(self.scale_scheme_line_edit.text())
            except ValueError:
                self.case.chrono.scale_scheme.enabled = False
                self.case.chrono.scale_scheme.value = ""
                debug("Introduced an invalid value for a float number.")
        else:
            self.case.chrono.scale_scheme.enabled = False
            self.case.chrono.scale_scheme.value = ""

        # Checks the collisiondp option for save
        if self.collisiondp_checkbox.isChecked():
            self.case.chrono.collisiondp.enabled = True
            try:
                self.case.chrono.collisiondp.value = float(self.collisiondp_line_edit.text())
            except ValueError:
                self.case.chrono.collisiondp.enabled = False
                self.case.chrono.collisiondp.value = ""
                debug("Introduced an invalid value for a float number.")
        else:
            self.case.chrono.collisiondp.enabled = False
            self.case.chrono.collisiondp.value = ""
예제 #21
0
 def merge_old_object(old, new):
     """ Merges an old object with the current version. """
     # FIXME: Add support for dicts,lists,tuples...
     for attr, value in new.__dict__.items():
         debug("Evaluating attr {} from the new object of type {}, for the old object of type {}".format(attr, type(new), type(old)))
         if not hasattr(old, attr):
             debug("Old object didn't have that attribute. Just updating it and going forward")
             setattr(old, attr, value)
             continue
         if hasattr(value, "__dict__") and hasattr(old, attr):
             # FIXME: old.attr may not have __dict__...
             debug("The attr {} is an object, and the old object has it. Exploring...".format(attr))
             Case.merge_old_object(getattr(old, attr), value)
             continue
    def _on_delete_line(self, line_id):
        debug("Deleting line {}".format(line_id))
        debug("Lines before: {}".format(self.stored_configuration.lines))
        self.stored_configuration.lines = list(
            filter(lambda line: line.line_id != line_id,
                   self.stored_configuration.lines))
        debug("Lines after: {}".format(self.stored_configuration.lines))

        index_to_delete: int = 0
        for i in range(0, self.lines_table.rowCount()):
            if self.lines_table.cellWidget(i, 0).line_id == line_id:
                index_to_delete = i
                break

        self.lines_table.removeRow(index_to_delete)

        for index in range(0, self.lines_table.rowCount()):
            target_widget: MoorDynLineWidget = self.lines_table.cellWidget(
                index, 0)
            target_widget.row = index
            self.lines_table.setCellWidget(index, 0, target_widget)
예제 #23
0
    def adapt_to_simulation_object(self, sim_object: SimulationObject,
                                   fc_object):
        """ Adapts the contents of the property widget to the specifications of the simulation object passed as a parameter. """

        self.mkgroup_prop.setValue(sim_object.obj_mk)
        self.last_mk_value = int(self.mkgroup_prop.value())

        self.autofill_prop.setChecked(bool(sim_object.autofill))
        self.frdrawmode_prop.setChecked(bool(sim_object.frdrawmode))

        debug(
            "Object {} supports changing type? {}. Its type is {} with mk {}".
            format(sim_object.name, sim_object.supports_changing_type(),
                   sim_object.type, sim_object.obj_mk))

        # Object Type selector adaptation
        if sim_object.supports_changing_type():
            debug(
                "Changing objtype_prop to {} in PropertiesDockWidget.adapt_to_simulation_object"
                .format("Fluid" if sim_object.type ==
                        ObjectType.FLUID else "Bound"))
            self.objtype_prop.setEnabled(True)
            self.objtype_prop.setCurrentIndex(0 if sim_object.type ==
                                              ObjectType.FLUID else 1)
            self.set_mkgroup_range(sim_object.type)
            self.set_mkgroup_text("{} <a href='{}'>?</a>".format(
                __("MKFluid" if sim_object.type ==
                   ObjectType.FLUID else "MKBound"), HelpURL.BASIC_CONCEPTS))
        else:
            # Everything else
            debug(
                "Changing objtype_prop to {} in PropertiesDockWidget.adapt_to_simulation_object"
                .format("Fluid" if sim_object.type ==
                        ObjectType.FLUID else "Bound"))
            self.set_mkgroup_range(ObjectType.BOUND)
            self.objtype_prop.setCurrentIndex(1)
            self.objtype_prop.setEnabled(False)

        # Object Fillmode selector adaptation
        self.fillmode_prop.setEnabled(False)
        if sim_object.supports_changing_fillmode():
            self.fillmode_prop.setEnabled(True)
            self.fillmode_prop.setCurrentIndex({
                ObjectFillMode.FULL: 0,
                ObjectFillMode.SOLID: 1,
                ObjectFillMode.FACE: 2,
                ObjectFillMode.WIRE: 3
            }[sim_object.fillmode])
        else:
            # Object not supported. Put Solid if it's a fillbox or face if not
            self.fillmode_prop.setCurrentIndex(1 if fc_object.TypeId ==
                                               FreeCADObjectType.FOLDER else 2)

        # Object Float State button adaptation
        if sim_object.supports_floating():
            self.floatstate_prop.setEnabled(
                sim_object.type != ObjectType.FLUID)

        # Object Initials button adaptation
        self.initials_prop.setEnabled(sim_object.type == ObjectType.FLUID)

        # Object Motion button adaptation
        if sim_object.supports_motion():
            self.motion_prop.setEnabled(sim_object.type != ObjectType.FLUID)

        # Object Material button adaptation
        self.material_prop.setEnabled(sim_object.type == ObjectType.BOUND)

        # Is an external object that supports autofill
        self.autofill_prop.setEnabled(sim_object.autofill is not None)

        # Is an object that supports frdrawmode
        self.frdrawmode_prop.setEnabled(
            fc_object.TypeId in (FreeCADObjectType.BOX,
                                 FreeCADObjectType.CYLINDER,
                                 FreeCADObjectType.SPHERE))
예제 #24
0
    def execute_bathymetry_tool(self):
        """ Executes bathymetry tool and returns the output path of the generated file. """

        export_process = QtCore.QProcess(get_fc_main_window())
        temp_dir = gettempdir()
        working_dialog = WorkingDialog(self)

        def on_export_finished():
            temp_bathymetry_file_path = "{}/output.stl".format(temp_dir)
            import_geo(filename=str(temp_bathymetry_file_path),
                       scale_x=1.0,
                       scale_y=1.0,
                       scale_z=1.0,
                       name=str(self.geo_objname_text.text()),
                       autofill=self.geo_autofill_chck.isChecked(),
                       case=Case.the())
            working_dialog.accept()

        executable_parameters = [
            "-loadpos",
            str(self.geo_file_path.text()),
            "-move:{}:{}:{}".format(self.bath_move_x_e.text(),
                                    self.bath_move_y_e.text(),
                                    self.bath_move_z_e.text()),
            "-rotate:{}:{}:{}".format(self.bath_rotate_x_e.text(),
                                      self.bath_rotate_y_e.text(),
                                      self.bath_rotate_z_e.text()),
            "-scale:{}:{}:{}".format(self.bath_scale_x_e.text(),
                                     self.bath_scale_y_e.text(),
                                     self.bath_scale_z_e.text())
        ]

        if self.bath_selection_enabled_chk.isChecked():
            executable_parameters.append("-selposmin:{}:{}".format(
                self.bath_selection_point_x_e.text(),
                self.bath_selection_point_y_e.text()))
            executable_parameters.append("-selsize:{}:{}".format(
                self.bath_selection_size_x_e.text(),
                self.bath_selection_size_y_e.text()))

        executable_parameters.append("-gdp:{}".format(
            self.bath_grid_dp_x_e.text()))

        if self.bath_initdomain_enabled_chk.isChecked():
            executable_parameters.append("-gposmin:{}:{}".format(
                self.bath_initdomain_point_x_e.text(),
                self.bath_initdomain_point_y_e.text()))
            executable_parameters.append("-gsize:{}:{}".format(
                self.bath_initdomain_size_x_e.text(),
                self.bath_initdomain_size_y_e.text()))

        if self.bath_xmin_check.isChecked():
            executable_parameters.append("-gexpandxmin:{}:{}:{}:{}".format(
                self.bath_xmin_size_e.text(), self.bath_xmin_z_e.text(),
                self.bath_xmin_size2_e.text(), self.bath_xmin_z2_e.text()))

        if self.bath_xmax_check.isChecked():
            executable_parameters.append("-gexpandxmax:{}:{}:{}:{}".format(
                self.bath_xmax_size_e.text(), self.bath_xmax_z_e.text(),
                self.bath_xmax_size2_e.text(), self.bath_xmax_z2_e.text()))

        if self.bath_ymin_check.isChecked():
            executable_parameters.append("-gexpandymin:{}:{}:{}:{}".format(
                self.bath_ymin_size_e.text(), self.bath_ymin_z_e.text(),
                self.bath_ymin_size2_e.text(), self.bath_ymin_z2_e.text()))

        if self.bath_ymax_check.isChecked():
            executable_parameters.append("-gexpandymax:{}:{}:{}:{}".format(
                self.bath_ymax_size_e.text(), self.bath_ymax_z_e.text(),
                self.bath_ymax_size2_e.text(), self.bath_ymax_z2_e.text()))

        if self.bath_periodicx_enabled_chk.isChecked():
            executable_parameters.append("-gperix:{}:{}".format(
                self.bath_periodicx_rampwidth_x_e.text(),
                self.bath_periodicx_flatwidth_x_e.text()))

        if self.bath_periodicy_enabled_chk.isChecked():
            executable_parameters.append("-gperiy:{}:{}".format(
                self.bath_periodicy_rampwidth_x_e.text(),
                self.bath_periodicy_flatwidth_x_e.text()))

        if self.bath_finalmove_enabled_chk.isChecked():
            executable_parameters.append("-gmove:{}:{}:{}".format(
                self.bath_finalmove_x_e.text(), self.bath_finalmove_y_e.text(),
                self.bath_finalmove_z_e.text()))

        executable_parameters.append("-savegrid:stl:mm")
        executable_parameters.append("{}/output.stl".format(temp_dir))

        self.save_default_data()

        export_process.finished.connect(on_export_finished)
        ensure_process_is_executable_or_fail(
            Case.the().executable_paths.bathymetrytool)
        debug("Executing: {} {}".format(
            Case.the().executable_paths.bathymetrytool,
            " ".join(executable_parameters)))
        export_process.start(Case.the().executable_paths.bathymetrytool,
                             executable_parameters)
        working_dialog.exec()
예제 #25
0
 def zone_edit(self, io_id):
     """ Calls a window for edit zones """
     debug("Trying to open a zone edit for zone UUID {}".format(io_id))
     InletZoneEdit(io_id, parent=get_fc_main_window())
     self.refresh_zones()
예제 #26
0
    if not path.exists("{}/{}_out".format(save_name, project_name)):
        makedirs("{}/{}_out".format(save_name, project_name))

    # Export all complex objects to STL
    for obj in case.get_all_complex_objects():
        Mesh.export([get_fc_object(obj.name)], "{}/{}.stl".format(save_name, obj.name))

    # FIXME: Too many branches

    # Copy files from movements and change its paths to be inside the project.
    for _, mkproperties in case.mkbasedproperties.items():
        for movement in mkproperties.movements:
            if isinstance(movement, SpecialMovement):
                if isinstance(movement.generator, (FileGen, RotationFileGen)):
                    filename = movement.generator.filename
                    debug("Copying {} to {}".format(filename, save_name))

                    # Change directory to de case one, so if file path is already relative it copies it to the
                    # out folder
                    chdir(save_name)

                    try:
                        # Copy to project root
                        shutil.copy2(filename, save_name)
                    except shutil.Error:
                        # Probably already copied the file.
                        pass
                    except IOError:
                        error("Unable to copy {} into {}".format(filename, save_name))

                    try:
예제 #27
0
def boot():
    """ Boots the application. """
    print_license()
    check_compatibility()

    try:
        master_branch_version = str(
            urlopen(GITHUB_MASTER_CONSTANTS_URL).read()).split(
                "VERSION = \"")[-1].split("\"")[0]
        if VERSION < master_branch_version and NOTIFY_ON_OUTDATED_VERSION:
            info_dialog(
                __("Your version of DesignSPHyiscs is outdated. Please go to the Addon Manager and update it. New versions include bug fixes, new features and new DualSPHysics executables, among other things."
                   ),
                __("The version you're using is {} while the version that you can update to is {}"
                   ).format(VERSION, master_branch_version))
    except URLError:
        log("No network connection or Git repo is down. Skipping version check."
            )

    if document_count() > 0:
        success = prompt_close_all_documents()
        if not success:
            debug(
                "User chose not to close the currently opened documents. Aborting startup"
            )
            quit()

    # Tries to delete docks created by a previous execution of DesignSPHysics
    delete_existing_docks()

    designsphysics_dock = DesignSPHysicsDock(get_fc_main_window())
    properties_widget = PropertiesDockWidget(parent=get_fc_main_window())

    get_fc_main_window().addDockWidget(QtCore.Qt.RightDockWidgetArea,
                                       designsphysics_dock)
    get_fc_main_window().addDockWidget(QtCore.Qt.LeftDockWidgetArea,
                                       properties_widget)

    # Subscribe the FreeCAD Objects tree to the item selection change function.
    # This helps FreeCAD notify DesignSPHysics for the deleted and changed objects to get updated correctly.
    fc_object_tree: QtGui.QTreeWidget = get_fc_main_window().findChildren(
        QtGui.QSplitter)[0].findChildren(QtGui.QTreeWidget)[0]
    fc_object_tree.itemSelectionChanged.connect(
        lambda p=properties_widget, d=designsphysics_dock:
        on_tree_item_selection_change(p, d))
    debug(
        "Subscribing selection change monitor handler to freecad object tree item changed."
    )

    properties_widget.need_refresh.connect(
        lambda p=properties_widget, d=designsphysics_dock:
        on_tree_item_selection_change(p, d))
    designsphysics_dock.need_refresh.connect(
        lambda p=properties_widget, d=designsphysics_dock:
        on_tree_item_selection_change(p, d))

    # Launch a monitor thread that ensures some things are not changed.
    monitor_thread = threading.Thread(
        target=lambda p=properties_widget, d=designsphysics_dock:
        selection_monitor(p, d))
    monitor_thread.start()

    FreeCADGui.activateWorkbench(DEFAULT_WORKBENCH)
    log(__("Initialization finished for {} v{}").format(APP_NAME, VERSION))
    def on_mgrid_change(self, _, column):
        """ Defines what happens when a field changes on the table"""
        if column > 8:
            return
        for self.mgrid_row in range(0, self.mgrid_table.rowCount()):
            try:
                self.current_grid = [
                    float(self.mgrid_table.item(self.mgrid_row, 0).text()),
                    float(self.mgrid_table.item(self.mgrid_row, 1).text()),
                    float(self.mgrid_table.item(self.mgrid_row, 2).text()),
                    float(self.mgrid_table.item(self.mgrid_row, 3).text()),
                    float(self.mgrid_table.item(self.mgrid_row, 4).text()),
                    float(self.mgrid_table.item(self.mgrid_row, 5).text()),
                    int(self.mgrid_table.item(self.mgrid_row, 6).text()),
                    int(self.mgrid_table.item(self.mgrid_row, 7).text()),
                    int(self.mgrid_table.item(self.mgrid_row, 8).text())
                ]

                debug(self.current_grid)

                # Make the operations to calculate final points
                self.mgrid_table.setItem(self.mgrid_row, 9, QtGui.QTableWidgetItem(str(
                    float(self.current_grid[0]) +
                    float(self.current_grid[6] - 1) *
                    float(self.current_grid[3])
                )))
                self.mgrid_table.setItem(self.mgrid_row, 10, QtGui.QTableWidgetItem(str(
                    float(self.current_grid[1]) +
                    float(self.current_grid[7] - 1) *
                    float(self.current_grid[4])
                )))
                self.mgrid_table.setItem(self.mgrid_row, 11, QtGui.QTableWidgetItem(str(
                    float(self.current_grid[2]) +
                    float(self.current_grid[8] - 1) *
                    float(self.current_grid[5])
                )))

                if self.current_grid[6] == 0:
                    self.mgrid_table.setItem(self.mgrid_row, 9, QtGui.QTableWidgetItem(str(
                        "0"
                    )))
                if self.current_grid[7] == 0:
                    self.mgrid_table.setItem(self.mgrid_row, 10, QtGui.QTableWidgetItem(str(
                        "0"
                    )))
                if self.current_grid[8] == 0:
                    self.mgrid_table.setItem(self.mgrid_row, 11, QtGui.QTableWidgetItem(str(
                        "0"
                    )))

                self.mgrid_table.item(self.mgrid_row, 9).setBackground(QtGui.QColor(210, 255, 255))
                self.mgrid_table.item(self.mgrid_row, 10).setBackground(QtGui.QColor(210, 255, 255))
                self.mgrid_table.item(self.mgrid_row, 11).setBackground(QtGui.QColor(210, 255, 255))
                # Those should not be used
                self.mgrid_table.item(self.mgrid_row, 9).setFlags(
                    QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
                self.mgrid_table.item(self.mgrid_row, 10).setFlags(
                    QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
                self.mgrid_table.item(self.mgrid_row, 11).setFlags(
                    QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            except (ValueError, AttributeError):
                pass