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.")
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)
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)
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.")
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))
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.")
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)
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")
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]
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
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()
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 = ""
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)
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))
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()
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()
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:
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