def pasteStorage(self): """Add the storage data from string.""" expr, ok = QInputDialog.getMultiLineText(self, "Storage", "Please input expression:") if not ok: return try: # Put the expression into parser to see if it is legal. parse_params(expr) except Exception as e: print(e) QMessageBox.warning(self, "Loading failed", "Your expression is in an incorrect format.") return name, ok = QInputDialog.getText(self, "Storage", "Please input name tag:") if not ok: return name_list = [ self.mechanism_storage.item(i).text() for i in range(self.mechanism_storage.count()) ] i = 0 name = name or f"Prototype_{i}" while name in name_list: name = f"Prototype_{i}" i += 1 self.__add_storage(name, expr)
def on_mechanism_storage_paste_clicked(self): """Add the storage data from string.""" expr, ok = QInputDialog.getText(self, "Storage", "Please input expression:") if not ok: return try: #Put the expression into parser to see if it is legal. PMKS_parser.parse(expr) except: QMessageBox.warning(self, "Loading failed", "Your expression is in an incorrect format.") return name, ok = QInputDialog.getText(self, "Storage", "Please input name tag:") if not ok: return if not name: nameList = [ self.mechanism_storage.item(i).text() for i in range(self.mechanism_storage.count()) ] i = 0 while "Prototype_{}".format(i) in nameList: i += 1 name = "Prototype_{}".format(i) _addStorage(self, name, expr, clear=False)
def __save_atlas(self): """Saving all the atlas to image file. We should turn transparent background to white first. Then using QImage class to merge into one image. """ file_name = "" lateral = 0 if self.save_edges_auto.isChecked(): lateral, ok = QInputDialog.getInt(self, "Atlas", "The number of lateral:", 5, 1, 10) if not ok: return file_name = self.outputTo("Atlas image", qt_image_format) if file_name: reply = QMessageBox.question( self, "Type synthesis", "Do you want to Re-synthesis?", (QMessageBox.Yes | QMessageBox.YesToAll | QMessageBox.Cancel), QMessageBox.Yes) if reply == QMessageBox.Yes: self.__structure_synthesis() elif reply == QMessageBox.YesToAll: self.__structure_synthesis_all() count = self.structure_list.count() if not count: return if not lateral: lateral, ok = QInputDialog.getInt(self, "Atlas", "The number of lateral:", 5, 1, 10) if not ok: return if not file_name: file_name = self.outputTo("Atlas image", qt_image_format) if not file_name: return width = self.structure_list.iconSize().width() image_main = QImage( QSize(lateral * width if count > lateral else count * width, ((count // lateral) + bool(count % lateral)) * width), self.__atlas_image(0).format()) image_main.fill(QColor(Qt.white).rgb()) painter = QPainter(image_main) for row in range(count): image = self.__atlas_image(row) painter.drawImage( QPointF(row % lateral * width, row // lateral * width), image) painter.end() pixmap = QPixmap() pixmap.convertFromImage(image_main) pixmap.save(file_name, format=QFileInfo(file_name).suffix()) self.saveReplyBox("Atlas", file_name)
def __read_slvs(self, file_name: str): """Read slvs format. + Choose a group. + Read the entities of the group. """ parser = SlvsParser(file_name) if not parser.isValid(): QMessageBox.warning(self, "Format error", "The format is not support.") return groups = parser.getGroups() if not groups: QMessageBox.warning(self, "Format error", "The model file is empty.") return group, ok = QInputDialog.getItem( self, "Solvespace groups", "Choose a group:\n" "(Please know that the group must contain a sketch only.)", ["@".join(g) for g in groups], 0, False) if not ok: return self.clear() self.DatabaseWidget.reset() print(f"Read from group: {group}") self.parseExpression(parser.parse(group.split('@')[0]))
def on_save_atlas_clicked(self): """Save function as same as type synthesis widget.""" count = self.collection_list.count() if not count: return lateral, ok = QInputDialog.getInt(self, "Atlas", "The number of lateral:", 5, 1, 10) if not ok: return fileName = self.outputTo("Atlas image", Qt_images) if not fileName: return icon_size = self.collection_list.iconSize() width = icon_size.width() image_main = QImage( QSize(lateral * width if count > lateral else count * width, ((count // lateral) + bool(count % lateral)) * width), self.collection_list.item(0).icon().pixmap( icon_size).toImage().format()) image_main.fill(QColor(Qt.white).rgb()) painter = QPainter(image_main) for row in range(count): image = self.collection_list.item(row).icon().pixmap( icon_size).toImage() painter.drawImage( QPointF(row % lateral * width, row // lateral * width), image) painter.end() pixmap = QPixmap() pixmap.convertFromImage(image_main) pixmap.save(fileName, format=QFileInfo(fileName).suffix()) self.saveReplyBox("Atlas", fileName)
def on_action_Import_PMKS_server_triggered(self): """Load PMKS URL and turn it to expression.""" URL, ok = QInputDialog.getText(self, "PMKS URL input", "Please input link string:") if not ok: return if not URL: QMessageBox.warning(self, "Loading failed", "Your link is in an incorrect format.") return try: for s in URL.split('?')[-1].split('&'): if 'mech=' in s: expr = s.replace('mech=', '').split('|') break textList = [s for s in expr if s not in ('', " ", '\n')] expression = [] while textList: item = textList.pop(0).split(',')[:-1] for i, e in enumerate(reversed(item)): if e in ['R', 'P', 'RP']: t = -(i + 1) break links = item[:t] item = item[t:] expression.append("J[{}, P[{}], L[{}]]".format( "{}:{}".format(item[0], item[-1]) if item[0] != 'R' else 'R', ", ".join((item[1], item[2])), ", ".join(links))) expression = "M[{}]".format(", ".join(expression)) except: QMessageBox.warning(self, "Loading failed", "Your link is in an incorrect format.") else: self.parseExpression(expression)
def __save_atlas(self): """Save function as same as type synthesis widget.""" count = self.collection_list.count() if not count: return lateral, ok = QInputDialog.getInt(self, "Atlas", "The number of lateral:", 5, 1) if not ok: return file_name = self.output_to("Atlas image", qt_image_format) if not file_name: return icon_size = self.collection_list.iconSize() width = icon_size.width() image_main = QImage( QSize(lateral * width if count > lateral else count * width, ((count // lateral) + bool(count % lateral)) * width), self.collection_list.item(0).icon().pixmap( icon_size).toImage().format()) image_main.fill(Qt.transparent) painter = QPainter(image_main) for row in range(count): image = self.collection_list.item(row).icon().pixmap( icon_size).toImage() painter.drawImage( QPointF(row % lateral * width, row // lateral * width), image) painter.end() pixmap = QPixmap() pixmap.convertFromImage(image_main) pixmap.save(file_name) self.save_reply_box("Atlas", file_name)
def __rename(self): """Show up a string input to change the data name.""" row = self.collections_list.currentRow() if not row > -1: return name, ok = QInputDialog.getText( self, "Profile name", "Please enter the profile name:" ) if not ok: return if not name: QMessageBox.warning( self, "Profile name", "Can not use blank string to rename." ) return item = self.collections_list.item(row) self.collections[name] = self.collections.pop(item.text()) item.setText(name) self.unsave_func()
def __copy(self): """Ask a name to copy a data.""" row = self.collections_list.currentRow() if not row > -1: return name, ok = QInputDialog.getText( self, "Profile name", "Please enter a new profile name:" ) if not ok: return if not name: QMessageBox.warning( self, "Profile name", "Can not use blank string to rename." ) return name_old = self.collections_list.item(row).text() self.collections[name] = self.collections[name_old].copy() self.collections_list.addItem(name) self.unsave_func()
def customizeZoom(self): """Customize zoom value.""" value, ok = QInputDialog.getInt(self, "Zoom", "Enter a zoom value:", self.ZoomBar.minimum(), self.ZoomBar.value(), self.ZoomBar.maximum(), 10) if ok: self.ZoomBar.setValue(value)
def on_save_button_clicked(self): """Save the profile to database.""" if self.profile_name: name = self.profile_name ok = True else: name, ok = QInputDialog.getText(self, "Profile name", "Please enter the profile name:") if ok: i = 0 while (name not in self.collections) and (not name): name = "Structure_{}".format(i) self.collections[name] = self.get_currentMechanismParams() self.profile_name = name self.unsaveFunc()
def __import_pmks_url(self): """Load PMKS URL and turn it to expression.""" url, ok = QInputDialog.getText( self, "PMKS URL input", "Please input link string:" ) if not ok: return if not url: QMessageBox.warning( self, "Loading failed", "Your link is in an incorrect format." ) return try: for s in url.split('?')[-1].split('&'): if 'mech=' in s: expr = s.replace('mech=', '').split('|') break else: raise ValueError text_list = [s for s in expr if s not in ('', " ", '\n')] expr.clear() while text_list: item = text_list.pop(0).split(',')[:-1] for i, e in enumerate(reversed(item)): if e in {'R', 'P', 'RP'}: t = -(i + 1) break else: raise ValueError links = item[:t] item = item[t:] type_text = f"{item[0]}:{item[-1]}" if item[0] != 'R' else 'R' links_text = ", ".join(links) expr.append(f"J[{type_text}, P[{item[1]}, {item[2]}], L[{links_text}]]") expr = "M[" + ", ".join(expr) + "]" except (ValueError, IndexError): QMessageBox.warning( self, "Loading failed", "Your link is in an incorrect format." ) else: self.parse_expression(expr)
def __save(self): """Save the profile to database.""" if self.profile_name.text(): name = self.profile_name.text() ok = True else: name, ok = QInputDialog.getText(self, "Profile name", "Please enter the profile name:") if not ok: return i = 0 while (name not in self.collections) and (not name): name = f"Structure_{i}" self.collections[name] = self.__get_current_mechanism_params() self.profile_name.setText(name) self.unsave_func()
def on_record_start_toggled(self, toggled): """Save to file path data.""" if toggled: self.MainCanvas.recordStart(int(360 / self.record_interval.value())) return path = self.MainCanvas.getRecordPath() name, ok = QInputDialog.getText(self, "Recording completed!", "Please input name tag:") if (not name) or (name in self.pathData): i = 0 while "Record_{}".format(i) in self.pathData: i += 1 QMessageBox.information(self, "Record", "The name tag is being used or empty.") name = "Record_{}".format(i) self.addPath(name, path)
def on_save_button_clicked(self): """Save as new profile to collection widget.""" if not self.mech_params: return name, ok = QInputDialog.getText(self, "Profile name", "Please enter the profile name:") if not ok: return i = 0 while (name not in self.collections) and (not name): name = "Structure_{}".format(i) mech_params = deepcopy(self.mech_params) for key in ['Driver', 'Follower', 'Target']: for name in mech_params[key]: mech_params[key][name] = None self.collections[name] = mech_params self.unsaveFunc()
def __add_from_edges(self): """Add collection by input string.""" edges_str = "" while not edges_str: edges_str, ok = QInputDialog.getText( self, "Add by edges", "Please enter a connection expression:\n" "Example: [(0, 1), (1, 2), (2, 3), (3, 0)]") if not ok: return try: edges = eval(edges_str) if any(len(edge) != 2 for edge in edges): raise ValueError("wrong format") except (SyntaxError, ValueError) as error: QMessageBox.warning(self, str(error), f"Error: {error}") return else: self.add_collection(edges)
def loadExample(self, isImport=False) -> bool: """Load example to new workbook.""" if not self.checkSaved(): return False #load example by expression. example_name, ok = QInputDialog.getItem( self, "Examples", "Select a example to load:", sorted(k for k in example_list), 0, False) if not ok: return False if not isImport: self.reset() self.clearFunc() self.parseFunc(example_list[example_name]) self.fileName = QFileInfo(example_name) self.isSavedFunc() print("Example \"{}\" has been loaded.".format(example_name)) return True
def on_merge_btn_clicked(self): tmp = [] for i in range(self.tabWidget.count()): if i == self.tabWidget.currentIndex(): continue tmp.append(str(i) + ":" + self.tabWidget.tabText(i)) item, ok = QInputDialog.getItem(self, "Merge", "Select figure", tmp, 0, False) if not ok: return tabcunt = int(item.split(":")[0]) view = self.tabWidget.widget(self.tabWidget.currentIndex()) mer = self.tabWidget.widget(tabcunt) for seri in mer.m_chart.series(): spline = QSplineSeries() spline.append(seri.pointsVector()) view.m_chart.addSeries(spline) self.on_tabWidget_tabCloseRequested(tabcunt) mer.close()
def on_add_by_edges_button_clicked(self): """Add collection by input string.""" edgesSTR = "" while not edgesSTR: edgesSTR, ok = QInputDialog.getText( self, "Add by edges", "Please enter a connection expression:\n" + "Example: [(0, 1), (1, 2), (2, 3), (3, 0)]") if not ok: return try: edges = eval(edgesSTR) if any(len(edge) != 2 for edge in edges): raise SyntaxError("Wrong format") except Exception as e: QMessageBox.warning(self, str(e), "Error: {}".format(e)) return else: self.addCollection(edges)
def __spell_correction(self): """Refactor words.""" pos = self.positionFromLineIndex(*self.getCursorPosition()) start, end, words = self.__word_at_pos(pos) if not words: return # Camel case. word = words for m in re.finditer(r'[A-Za-z][a-z]+', words): if m.start() < pos - start < m.end(): word = m.group(0) break answer, ok = QInputDialog.getItem(self, "Spell correction", f"Refactor word: \"{word}\"", _spell.candidates(word)) if ok: self.__replace_all(words, words.replace(word, answer))
def __save_profile(self): """Save as new profile to collection widget.""" if not self.mech_params: return name, ok = QInputDialog.getText(self, "Profile name", "Please enter the profile name:") if not ok: return i = 0 while (not name) and (name not in self.collections): name = f"Structure_{i}" i += 1 mech_params = deepcopy(self.mech_params) for key in ('Placement', 'Target'): for mp in mech_params[key]: mech_params[key][mp] = None self.collections[name] = mech_params self.workbook_no_save()
def loadExample(self, is_import: bool = False) -> bool: """Load example to new workbook.""" if self.__check_file_changed(): return False # load example by expression. example_name, ok = QInputDialog.getItem(self, "Examples", "Select an example to load:", sorted(example_list), 0, False) if not ok: return False expr, inputs = example_list[example_name] if not is_import: self.reset() self.__clear_func() self.__parse_func(expr) if not is_import: # Import without input data. self.__load_inputs_func(inputs) self.file_name = QFileInfo(example_name) self.__workbook_saved() print(f"Example \"{example_name}\" has been loaded.") return True
def importMechanism(self, fileName: str): """Pick and import the latest mechanism from a branch.""" self.connectDatabase(fileName) commit_all = CommitModel.select().join(BranchModel) branch_all = BranchModel.select().order_by(BranchModel.name) if self.history_commit != None: self.connectDatabase(self.fileName.absoluteFilePath()) else: self.colseDatabase() branch_name, ok = QInputDialog.getItem( self, "Branch", "Select the latest commit in the branch to load.", [branch.name for branch in branch_all], 0, False) if not ok: return try: commit = (commit_all.where( BranchModel.name == branch_name).order_by( CommitModel.date).get()) except CommitModel.DoesNotExist: QMessageBox.warning(self, "Warning", "This file is a non-committed database.") else: self.importCommit(commit)
def __start_record(self, toggled: bool): """Save to file path data.""" if toggled: self.MainCanvas.record_start(int( self.dial_spinbox.maximum() / self.record_interval.value() )) return path = self.MainCanvas.get_record_path() name, ok = QInputDialog.getText( self, "Recording completed!", "Please input name tag:" ) i = 0 name = name or f"Record_{i}" while name in self.__path_data: name = f"Record_{i}" i += 1 QMessageBox.information( self, "Record", "The name tag is being used or empty." ) self.add_path(name, path)
def save(self, file_name: str, is_branch: bool = False): """Save database, append commit to new branch function.""" author_name = self.FileAuthor.text( ) or self.FileAuthor.placeholderText() branch_name = '' if is_branch else self.branch_current.text() commit_text = self.FileDescription.text() while not author_name: author_name, ok = QInputDialog.getText( self, "Author", "Please enter author's name:", QLineEdit.Normal, "Anonymous") if not ok: return while not branch_name.isidentifier(): branch_name, ok = QInputDialog.getText( self, "Branch", "Please enter a branch name:", QLineEdit.Normal, "master") if not ok: return while not commit_text: commit_text, ok = QInputDialog.getText(self, "Commit", "Please add a comment:", QLineEdit.Normal, "Update mechanism.") if not ok: return if (file_name != self.file_name.absoluteFilePath()) and isfile(file_name): os_remove(file_name) print("The original file has been overwritten.") self.__connect_database(file_name) is_error = False with _db.atomic(): if author_name in (user.name for user in UserModel.select()): author_model = (UserModel.select().where( UserModel.name == author_name).get()) else: author_model = UserModel(name=author_name) if branch_name in (branch.name for branch in BranchModel.select()): branch_model = (BranchModel.select().where( BranchModel.name == branch_name).get()) else: branch_model = BranchModel(name=branch_name) args = { 'author': author_model, 'description': commit_text, 'mechanism': _compress(self.__point_expr_func()), 'linkcolor': _compress(self.__link_expr_func()), 'storage': _compress(list(self.__storage_data_func())), 'pathdata': _compress(self.__path_data_func()), 'collectiondata': _compress(self.__collect_data_func()), 'triangledata': _compress(self.__triangle_data_func()), 'inputsdata': _compress( tuple((b, d) for b, d, a in self.__inputs_data_func())), 'algorithmdata': _compress(self.__algorithm_data_func()), 'branch': branch_model, } try: args['previous'] = (CommitModel.select().where( CommitModel.id == self.commit_current_id.value()).get()) except CommitModel.DoesNotExist: args['previous'] = None new_commit = CommitModel(**args) try: author_model.save() branch_model.save() new_commit.save() except Exception as e: print(str(e)) _db.rollback() is_error = True else: self.history_commit = CommitModel.select().order_by( CommitModel.id) if is_error: os_remove(file_name) print("The file was removed.") return self.read(file_name) print(f"Saving \"{file_name}\" successful.") size = QFileInfo(file_name).size() print("Size: " + (f"{size / 1024 / 1024:.02f} MB" if size / 1024 // 1024 else f"{size / 1024:.02f} KB"))
def save(self, fileName: str, isBranch=False): """Save database. + Append to new branch function. """ author_name = self.FileAuthor.text() if not author_name: author_name = self.FileAuthor.placeholderText() branch_name = '' if isBranch else self.branch_current.text() commit_text = self.FileDescription.text() while not author_name: author_name, ok = QInputDialog.getText( self, "Author", "Please enter author's name:", QLineEdit.Normal, "Anonymous") if not ok: return while not branch_name.isidentifier(): branch_name, ok = QInputDialog.getText( self, "Branch", "Please enter a branch name:", QLineEdit.Normal, "master") if not ok: return while not commit_text: commit_text, ok = QInputDialog.getText(self, "Commit", "Please add a comment:", QLineEdit.Normal, "Update mechanism.") if not ok: return if ((fileName != self.fileName.absoluteFilePath()) and os.path.isfile(fileName)): os.remove(fileName) print("The original file has been overwritten.") self.connectDatabase(fileName) isError = False with db.atomic(): if author_name in (user.name for user in UserModel.select()): author_model = (UserModel.select().where( UserModel.name == author_name).get()) else: author_model = UserModel(name=author_name) if branch_name in (branch.name for branch in BranchModel.select()): branch_model = (BranchModel.select().where( BranchModel.name == branch_name).get()) else: branch_model = BranchModel(name=branch_name) pointData = self.pointDataFunc() linkcolor = { vlink.name: vlink.colorSTR for vlink in self.linkDataFunc() } args = { 'author': author_model, 'description': commit_text, 'mechanism': compress("M[{}]".format(", ".join(vpoint.expr for vpoint in pointData))), 'linkcolor': compress(linkcolor), 'storage': compress(self.storageDataFunc()), 'pathdata': compress(self.pathDataFunc()), 'collectiondata': compress(self.CollectDataFunc()), 'triangledata': compress(self.TriangleDataFunc()), 'inputsdata': compress(self.InputsDataFunc()), 'algorithmdata': compress(self.AlgorithmDataFunc()), 'branch': branch_model } try: args['previous'] = (CommitModel.select().where( CommitModel.id == self.commit_current_id.value()).get()) except CommitModel.DoesNotExist: args['previous'] = None new_commit = CommitModel(**args) try: author_model.save() branch_model.save() new_commit.save() except Exception as e: print(str(e)) db.rollback() isError = True else: self.history_commit = (CommitModel.select().order_by( CommitModel.id)) if isError: os.remove(fileName) print("The file was removed.") return self.read(fileName) print("Saving \"{}\" successful.".format(fileName)) size = QFileInfo(fileName).size() print( "Size: {}".format("{} MB".format(round(size / 1024 / 1024, 2)) if size / 1024 // 1024 else "{} KB".format(round(size / 1024, 2))))