def load_example(self, is_import: bool = False) -> bool: """Load example to new project.""" # load example by expression example_name, ok = QInputDialog.getItem(self, "Examples", "Select an example to load:", all_examples(), 0, False) if not ok: return False if not is_import: self.reset() self.main_clear() if self.prefer.open_project_actions_option == 1: self.command_stack.beginMacro("Add mechanism") expr, inputs = example_list(example_name) self.parse_expression(expr) if not is_import: if self.prefer.open_project_actions_option == 1: self.command_stack.endMacro() self.command_stack.beginMacro("Add inputs data") # Import without inputs data self.load_inputs(inputs) if self.prefer.open_project_actions_option == 0: self.command_stack.clear() self.command_stack.setUndoLimit(self.prefer.undo_limit_option) elif self.prefer.open_project_actions_option == 1: self.command_stack.endMacro() self.set_file_name(example_name, is_example=True) self.project_saved() logger.info(f"Example \"{example_name}\" has been loaded.") return True
def console_connect(self) -> None: """Turn the OS command line (stdout) log to console.""" logger.info("Connect to GUI console.") XStream.stdout().message_written.connect(self.__append_to_console) self.console_connect_button.setEnabled(False) self.console_disconnect_button.setEnabled(True) logger.info("Connect to GUI console.")
def __task(self) -> Dict[str, Any]: """Get the algorithm result.""" t0 = process_time() a = algorithm(self.alg)( self.planar, self.settings, progress_fun=self.progress_update.emit, interrupt_fun=lambda: self.is_stop, ) expression = a.run() tf = a.history() time_spend = process_time() - t0 last_gen = tf[-1][0] mechanism = { 'algorithm': self.alg.value, 'time': time_spend, 'last_gen': last_gen, 'last_fitness': tf[-1][1], 'interrupted': str(last_gen) if self.is_stop else 'False', 'settings': self.settings, 'hardware_info': { 'os': f"{system()} {release()} {machine()}", 'cpu': processor(), }, 'time_fitness': tf, 'callback': self.planar.callback, } mechanism.update(self.mech) mechanism['expression'] = expression logger.info(f"cost time: {time_spend:.02f} [s]") return mechanism
def __path_dlg(self, item: QListWidgetItem) -> None: """View path data.""" name = item.text().split(":", maxsplit=1)[0] try: paths = self.__paths[name] except KeyError: return points_text = ", ".join(f"Point{i}" for i in range(len(paths))) if QMessageBox.question( self, "Path data", f"This path data including {points_text}.", (QMessageBox.Save | QMessageBox.Close), QMessageBox.Close ) != QMessageBox.Save: return file_name = self.output_to( "path data", ["Comma-Separated Values (*.csv)", "Text file (*.txt)"] ) if not file_name: return with open(file_name, 'w+', encoding='utf-8', newline='') as stream: w = writer(stream) for path in paths: for point in path: w.writerow(point) w.writerow(()) logger.info(f"Output path data: {file_name}")
def console_disconnect(self) -> None: """Turn the console log to OS command line (stdout).""" logger.info("Disconnect from GUI console.") XStream.back() self.console_connect_button.setEnabled(True) self.console_disconnect_button.setEnabled(False) logger.info("Disconnect from GUI console.")
def __close_work(self) -> None: """Close the thread.""" if not self.work.isRunning(): return self.stop_signal.emit() logger.info("The thread has been canceled.") self.work.wait()
def __algorithm(self) -> Dict[str, Any]: """Get the algorithm result.""" t0 = process_time() algorithm = ALGORITHM[self.algorithm]( self.planar, self.settings, progress_fun=self.progress_update.emit, interrupt_fun=lambda: self.is_stop, ) expression = algorithm.run() tf = algorithm.history() time_spend = process_time() - t0 info = cpu.info[0] my_cpu = info.get("model name", info.get('ProcessorNameString', '')) last_gen = tf[-1][0] mechanism = { 'algorithm': self.algorithm.value, 'time': time_spend, 'last_gen': last_gen, 'last_fitness': tf[-1][1], 'interrupted': str(last_gen) if self.is_stop else 'False', 'settings': self.settings, 'hardware_info': { 'os': f"{system()} {release()} {machine()}", 'cpu': my_cpu, }, 'time_fitness': tf, } mechanism.update(self.mech) mechanism['expression'] = expression logger.info(f"cost time: {time_spend:.02f} [s]") return mechanism
def save_reply_box(self, title: str, file_name: str) -> None: """Show message when successfully saved.""" size = size_format(QFileInfo(file_name).size()) QMessageBox.information( self, f"Initial Saved: {title}", f"Successfully saved:\n{file_name}\n" f"Size: {size}") logger.info(f"Saved: [\"{file_name}\"] ({size})")
def closeEvent(self, event: QCloseEvent) -> None: """Close event to avoid user close the window accidentally.""" if self.check_file_changed(): event.ignore() return if self.inputs_widget.inputs_play_shaft.isActive(): self.inputs_widget.inputs_play_shaft.stop() self.save_settings() XStream.back() logger.info("Exit") event.accept()
def load_data(self, file_name: str, data: _Data) -> None: """Load file method.""" self.main_clear() ver = data.get('pyslvs_ver', "") if ver: logger.info(f"Load data from version {ver}") del ver self.dlg = QProgressDialog("Loading project", "Cancel", 0, 7, self._parent) self.dlg.show() try: mechanism_data = self.__load_mech(data) storage_data = self.__load_storage(data) input_data = self.__load_input(data) paths = self.__load_path(data) collection_data = self.__load_collection(data) config_data = self.__load_config(data) algorithm_data = self.__load_algorithm(data) self.__load_background(data) except Exception as e: QMessageBox.warning(self._parent, "Load error", f"Exception:\n{e}") self.dlg.deleteLater() self.dlg = None return # File type option align (ignore previous one) self.prefer.file_type_option = data.get('file_type', 0) # Show overview dialog self.dlg.deleteLater() self.dlg = OverviewDialog( self._parent, QFileInfo(file_name).baseName(), mechanism_data, storage_data, input_data, paths, collection_data, config_data, algorithm_data, self.get_background_path() ) self.dlg.show() self.dlg.exec_() self.dlg.deleteLater() self.dlg = None
def main() -> None: """Startup function.""" global _app t0 = process_time() exit_code = 0 from sys import argv, exit from logging import shutdown from platform import system from pyslvs_ui.info import ARGUMENTS, logger if ARGUMENTS.cmd in {'gui', None}: from qtpy.QtCore import Qt, qInstallMessageHandler from qtpy.QtWidgets import QApplication, QSplashScreen from qtpy.QtGui import QPixmap _app = QApplication(argv) # Depress Qt warning qInstallMessageHandler(lambda _0, _1, _2: None) # Load QRC file from pyslvs_ui.icons_rc import qInitResources qInitResources() # Splash sp = QSplashScreen(QPixmap(":/icons/splash.png")) sp.showMessage(f"{__author__} {__copyright__}", Qt.AlignBottom | Qt.AlignRight) sp.show() # Force enable fusion style on macOS if system() == 'Darwin': ARGUMENTS.fusion = True if ARGUMENTS.fusion: _app.setStyle('fusion') # Main window from .main_window import MainWindow w = MainWindow.new() sp.finish(w) sp.deleteLater() logger.info(f"Startup with: {process_time() - t0:.02f}s") if not ARGUMENTS.debug_mode: w.console_connect() del sp, w exit_code = _app.exec_() elif ARGUMENTS.cmd == 'test': from importlib import import_module import_module('pyslvs_ui.main_window') logger.info("All module loaded successfully.") logger.info(f"Loaded with: {process_time() - t0:.02f}s") elif ARGUMENTS.cmd == 'extract': logger.info(f"Start CLI: {process_time() - t0:.02f}s") # TODO: CLI mode else: raise ValueError(f"unknown command: {ARGUMENTS.cmd}") shutdown() exit(exit_code)
def run(self) -> None: """Start the algorithm loop.""" for name, path in self.mech['target'].items(): logger.debug(f"- [P{name}] ({len(path)})") t0 = process_time() for self.loop in range(self.loop): logger.info(f"Algorithm [{self.loop + 1}]: {self.alg}") if self.is_stop: # Cancel the remaining tasks logger.info("Canceled.") continue self.result.emit(self.__task()) logger.info(f"total cost time: {process_time() - t0:.02f} [s]") self.finished.emit()
def __new_project(self) -> None: """Create (Clean) a new project.""" if self.check_file_changed(): return self.clear() logger.info("Created a new project.")
def __interrupt(self) -> None: """Interrupt the process.""" if self.work.isRunning(): self.stop_signal.emit() logger.info("The thread has been interrupted.")