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 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 __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 on_importXLSX_clicked(self): """Paste path data from a Excel file.""" fileName = self.inputFrom( "Excel file", ["Microsoft Office Excel (*.xlsx *.xlsm *.xltx *.xltm)"] ) if not fileName: return wb = openpyxl.load_workbook(fileName) ws = wb.get_sheet_by_name(wb.get_sheet_names()[0]) data = [] #Keep finding until there is no value. i = 1 while True: x = ws.cell(row=i, column=1).value y = ws.cell(row=i, column=2).value if x == None or y == None: break try: data.append((round(float(x), 4), round(float(y), 4))) except: QMessageBox.warning(self, "File error", "Wrong format.\n" + "The datasheet seems to including non-digital cell." ) break i += 1 for x, y in data: self.add_point(x, y)
def __add_from_files(self): """Append atlas by text files.""" file_names = self.input_from("Edges data", ["Text File (*.txt)"], multiple=True) if not file_names: return read_data = [] for file_name in file_names: with open(file_name, 'r', encoding='utf-8') as f: for line in f: read_data.append(line) collections = [] for edges in read_data: try: collections.append(Graph(eval(edges))) except (SyntaxError, TypeError): QMessageBox.warning(self, "Wrong format", "Please check the edges text format.") return if not collections: return self.collections += collections self.__reload_atlas()
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 __import_xlsx(self): """Paste path data from a Excel file.""" file_name = self.input_from( "Excel file", ["Microsoft Office Excel (*.xlsx *.xlsm *.xltx *.xltm)"]) if not file_name: return wb = load_workbook(file_name) ws = wb.get_sheet_by_name(wb.get_sheet_names()[0]) data = [] # Keep finding until there is no value. i = 1 while True: x = ws.cell(row=i, column=1).value y = ws.cell(row=i, column=2).value if None in {x, y}: break try: data.append((round(float(x), 4), round(float(y), 4))) except (IndexError, AttributeError): QMessageBox.warning( self, "File error", "Wrong format.\n" "The data sheet seems to including non-digital cell.") break i += 1 for x, y in data: self.add_point(x, y)
def refresh_proj(self, node: Optional[QTreeWidgetItem] = None): """Re-parse the file node.""" if node is None: node = self.tree_main.currentItem() if not node.text(1): QMessageBox.warning(self, "No path", "Can only refresh from valid path.") return self.__delete_node_data(node) node.takeChildren() parse(node, self.data) self.tree_main.setCurrentItem(node) _expand_recursive(node) code = int(node.text(2)) self.text_editor.setText(self.data[code]) self.data.set_saved(code, True) self.__add_macros() # File keeper if self.keeper is not None: self.keeper.stop() self.keeper = FileKeeper(LOADED_FILES, self) self.keeper.file_changed.connect(self.file_changed_warning) self.keeper.start()
def on_Edges_to_altas_clicked(self): """Turn the text files into a atlas image. This opreation will load all edges to list widget first. """ fileNames = self.inputFrom( "Edges data", ["Text File (*.txt)"], multiple=True ) if not fileNames: return read_data = [] for fileName in fileNames: with open(fileName, 'r') as f: read_data += f.read().split('\n') answer = [] for edges in read_data: try: answer.append(Graph(eval(edges))) except: QMessageBox.warning(self, "Wrong format", "Please check the edges text format." ) return if not answer: return self.answer = answer self.on_reload_atlas_clicked() check_status = self.save_edges_auto.isChecked() self.save_edges_auto.setChecked(False) self.on_save_atlas_clicked() self.save_edges_auto.setChecked(check_status)
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 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 parse_expression(self, expr: str): """Parse expression.""" try: args_list = parse_params(expr) except LarkError: QMessageBox.warning( self, "Loading failed", f"Your expression is in an incorrect format." ) else: for args in args_list: links = args[0].split(',') link_names = { vlink.name for vlink in self.entities_link.data() } for link_name in links: # If link name not exist. if link_name not in link_names: self.add_link(link_name, 'Blue') row_count = self.entities_point.rowCount() self.command_stack.beginMacro(f"Add {{Point{row_count}}}") self.command_stack.push(AddTable(self.entities_point)) self.command_stack.push(EditPointTable( row_count, self.entities_point, self.entities_link, args )) self.command_stack.endMacro()
def loadCommitID(self, id: int): """Check the id is correct.""" try: commit = self.history_commit.where(CommitModel.id == id).get() except CommitModel.DoesNotExist: QMessageBox.warning(self, "Warning", "Commit ID is not exist.") except AttributeError: QMessageBox.warning(self, "Warning", "Nothing submitted.") else: self.loadCommit(commit)
def add_collection(self, edges: Sequence[Tuple[int, int]]): """Add collection by in put edges.""" graph = Graph(edges) error = self.__is_valid_graph(graph) if error: QMessageBox.warning(self, "Add Collection Error", f"Error: {error}") return self.collections.append(graph) self.unsaveFunc() self.__reload_atlas()
def refresh_proj(self): """Re-parse the file node.""" node = self.tree_main.currentItem() if not node.text(1): QMessageBox.warning( self, "No path", "Can only refresh from valid path." ) parse(node, self.data) self.tree_main.setCurrentItem(node) self.text_editor.setText(self.data[int(node.text(2))])
def __readPathFromCSV(self, data: List[str]): """Trun STR to FLOAT then add them to current target path.""" try: data = [(round(float(data[i]), 4), round(float(data[i + 1]), 4)) for i in range(0, len(data), 2)] except: QMessageBox.warning( self, "File error", "Wrong format.\nIt should be look like this:" + "\n0.0,0.0[\\n]" * 3) else: for e in data: self.addPoint(e[0], e[1])
def __from_canvas(self): """Get a collection data from current mechanism.""" try: collection = self.getCollection() except ValueError as e: QMessageBox.warning(self, "Mechanism not support.", str(e)) else: num = 0 name = f"mechanism{num}" while name in self.collections: name = f"mechanism{num}" num += 1 self.collections[name] = collection.copy() self.collections_list.addItem(name)
def __read_path_from_csv(self, raw_data: List[str]): """Turn string to float then add them to current target path.""" try: data = [(round(float(raw_data[i]), 4), round(float(raw_data[i + 1]), 4)) for i in range(0, len(raw_data), 2)] except (IndexError, ValueError): QMessageBox.warning( self, "File error", "Wrong format.\nIt should be look like this:" + ("\n0.0,0.0[\\n]" * 3)) else: for x, y in data: self.add_point(x, y)
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 file_changed_warning(self, path: str, node: QTreeWidgetItem): """Triggered when file changed.""" if QMessageBox.warning(self, "File Changed", f"File {path} has changed.\nReload the file?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: self.refresh_proj(node)
def __drawAtlas(self, i: int, G: Graph) -> bool: """Draw atlas and return True if done.""" item = QListWidgetItem("No. {}".format(i + 1)) try: item.setIcon( graph(G, self.Topologic_result.iconSize().width(), self.engine, self.graph_link_as_node.isChecked())) except EngineError as e: QMessageBox.warning( self, str(e), "Please install and make sure Graphviz is working.") return False else: item.setToolTip(str(G.edges)) self.Topologic_result.addItem(item) return True
def __accepted(self): """Use the file path to export the project.""" qdir = QDir(_get_name(self.path_edit, ispath=True)) if self.newfolder_option.isChecked(): new_folder = self.filename_edit.placeholderText() if (not qdir.mkdir(new_folder)) and self.warn_radio.isChecked(): self.exist_warning(new_folder, folder=True) return qdir.cd(new_folder) try: ok = self.do(qdir) except PermissionError as error: QMessageBox.warning(self, "Permission error", str(error)) else: if ok: self.accept()
def read(self, file_name: str): """Load database commit.""" self.__connect_database(file_name) history_commit = CommitModel.select().order_by(CommitModel.id) commit_count = len(history_commit) if not commit_count: QMessageBox.warning(self, "Warning", "This file is a non-committed database.") return self.__clear_func() self.reset() self.history_commit = history_commit for commit in self.history_commit: self.__add_commit(commit) print(f"{commit_count} commit(s) was find in database.") self.__load_commit(self.history_commit.order_by(-CommitModel.id).get()) self.file_name = QFileInfo(file_name) self.__workbook_saved()
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 read(self, fileName: str): """Load database commit.""" self.connectDatabase(fileName) history_commit = CommitModel.select().order_by(CommitModel.id) commit_count = len(history_commit) if not commit_count: QMessageBox.warning(self, "Warning", "This file is a non-committed database.") return self.clearFunc() self.reset() self.history_commit = history_commit for commit in self.history_commit: self.addCommit(commit) print("{} commit(s) was find in database.".format(commit_count)) self.loadCommit(self.history_commit.order_by(-CommitModel.id).get()) self.fileName = QFileInfo(fileName) self.isSavedFunc()
def addCollection(self, edges: Tuple[Tuple[int, int]]): """Add collection by in put edges.""" G = Graph(edges) try: if not edges: raise TestError("is empty graph.") for n in G.nodes: if len(list(G.neighbors(n))) < 2: raise TestError("is not close chain") for H in self.collections: if is_isomorphic(G, H): raise TestError("is isomorphic") except TestError as e: QMessageBox.warning(self, "Add Collection Error", "Error: {}".format(e)) return self.collections.append(G) self.unsaveFunc() self.on_reload_atlas_clicked()
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 __delete_branch(self): """Delete all commits in the branch.""" if not self.BranchList.currentRow() > -1: return branch_name = self.BranchList.currentItem().text() if branch_name == self.branch_current.text(): QMessageBox.warning(self, "Warning", "Cannot delete current branch.") return file_name = self.file_name.absoluteFilePath() # Connect on database to remove all the commit in this branch. with _db.atomic(): CommitModel.delete().where( CommitModel.branch.in_(BranchModel.select().where( BranchModel.name == branch_name))).execute() BranchModel.delete().where( BranchModel.name == branch_name).execute() _db.close() print(f"Branch {branch_name} was deleted.") # Reload database. self.read(file_name)
def on_branch_delete_clicked(self): """Delete all commits in the branch.""" if not self.BranchList.currentRow() > -1: return branch_name = self.BranchList.currentItem().text() if branch_name != self.branch_current.text(): fileName = self.fileName.absoluteFilePath() #Connect on database to remove all the commit in this branch. with db.atomic(): branch_quary = (BranchModel.select().where( BranchModel.name == branch_name)) (CommitModel.delete().where( CommitModel.branch.in_(branch_quary)).execute()) (BranchModel.delete().where( BranchModel.name == branch_name).execute()) db.close() print("Branch {} was deleted.".format(branch_name)) #Reload database. self.read(fileName) else: QMessageBox.warning(self, "Warning", "Cannot delete current branch.")
def on_add_by_files_button_clicked(self): """Append atlas by text files.""" fileNames = self.inputFrom("Edges data", ["Text File (*.txt)"], multiple=True) if not fileNames: return read_data = [] for fileName in fileNames: with open(fileName, 'r') as f: read_data += f.read().split('\n') collections = [] for edges in read_data: try: collections.append(Graph(eval(edges))) except: QMessageBox.warning(self, "Wrong format", "Please check the edges text format.") return if not collections: return self.collections += collections self.on_reload_atlas_clicked()