def pull_data(self, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = False): """Method to pull data from database""" table = self.name if verbose is True and t_log is None: t_log = TimeLogger() sql = "SELECT * FROM {tbl}" query = SQL(sql).format(tbl=Identifier(table)) if my_conn is None: my_conn = self.my_conn else: self.my_conn = my_conn my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] out_data = read_sql(query, con=conn, index_col='type_name') if verbose: t_log.new_event('Extracting records from Table: ' + table) return out_data
def available_templates(my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = False) -> TemplateIDs: """Function to pull available templates from ddtatbase""" if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] if verbose is True: print('Extracting available Templates') if verbose is True: t_log.new_event('Connecting to Templates on Database') cur = conn.cursor() try: cur.execute('SELECT id FROM template ORDER BY created_at') except DatabaseError as error: print("Couldn't retrieve templates", error) output = cur.fetchall() cur.close() template_ids = TemplateIDs([x[0] for x in output]) if verbose is True: t_log.new_event('Finished Extracting Data') return template_ids
def delete(self, id_tup: Tuple, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = False): """Method to Insert New Equation Records""" if my_conn is None: my_conn = self.my_conn else: self.my_conn = my_conn if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] cur = conn.cursor() sql: str = 'DELETE FROM {table} WHERE id IN ({values});' query = SQL(sql).format(values=SQL(', ').join(map(Literal, id_tup)), table=Identifier(self.name)) self.pull_data() if verbose is True: t_log.new_event("execute_values() done") try: cur.execute(query, id_tup) conn.commit() except DatabaseError as error: print("Error: %s" % error) conn.rollback() cur.close()
def update_insertion_order_for_selected(self, order: dict, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = False): """Populates insertion_order attribute""" self.pull_grouped_data() df = self.selected_data_df() join_table: str = self.table_name + '_' + self.parent_table_name if verbose is True and t_log is None: t_log = TimeLogger() if my_conn is None: my_conn = self.my_conn else: self.my_conn = my_conn my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) self.my_conn = my_conn conn = my_conn['conn'] sql = 'UPDATE {table} SET insertion_order = %s WHERE ({c_table_id}, {p_table_id}) = (%s, %s)' query = SQL(sql).format(table=Identifier(join_table), c_table_id=Identifier(self.id_name()), p_table_id=Identifier( self.parent_table_id_name())) cur = conn.cursor(cursor_factory=NamedTupleCursor) if verbose is True: t_log.new_event('Updating Insertion order for: ' + join_table) print(query.as_string(conn)) for eq_name, i in order.items(): p_id = self.selected_parent_id c_id = int(df.name[df.name == eq_name].index[0]) if verbose: print(cur.mogrify(query, (i, c_id, p_id))) try: cur.execute(query, (i, c_id, p_id)) except OperationalError as error: print(error) conn.commit() self.pull_grouped_data() if verbose is True: t_log.new_event('Finished Updating Insertion Order: ' + join_table)
def generic_new_record_db(table_name: str = None, data_df: Optional[DataFrame] = None, name: str = None, new_record=None, notes: str = None, created_by: str = None, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = None) -> DataFrame: """Insert New Record Into math_object""" if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] db_params = my_conn['db_params'] if new_record is None: new_record = {} next_id: int = generic_record_count(data_df) + 1 if name is None: name = "{aTable} {ID:d}".format(ID=next_id, aTable=table_name) if created_by is None: created_by = db_params['user'] new_record.update(name=name, notes=notes, created_by=created_by) query = SQL('INSERT INTO {table} ({fields}) VALUES ({values})' ).format(table=Identifier(table_name), fields=SQL(', ').join(map(Identifier, new_record.keys())), values=SQL(', ').join(map(Placeholder, new_record.keys()))) if verbose: print(query.as_string(conn)) cur = conn.cursor(cursor_factory=NamedTupleCursor) if verbose: t_log.new_event('Adding new record to Table: {aTable}'.format(aTable=table_name)) try: cur.execute(query, new_record) except OperationalError as error: print(error) # new_records = cur.fetchall() conn.commit() cur.close() updated_df = \ generic_pull_data(table_name=table_name, my_conn=my_conn, t_log=t_log, verbose=verbose) return updated_df
def delete_types(self, types, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = False): """Method to Insert New Equation Records""" if my_conn is None: my_conn = self.my_conn else: self.my_conn = my_conn if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] cur = conn.cursor() if verbose is True: t_log.new_event(type(types)) if isinstance(types, str): print('you are here') types = tuple([types]) sql: str = 'DELETE FROM {table} WHERE type_name IN ({values});' query = SQL(sql).format(values=SQL(', ').join(map(Literal, types)), table=Identifier(self.name)) if verbose is True: print(query.as_string(cur)) t_log.new_event('Values' + str(types)) t_log.new_event('Pulling Data for: ' + self.name) try: cur.execute(query, types) conn.commit() except DatabaseError as error: print("Error: %s" % error) conn.rollback() cur.close() self.reinitialize_types_df(my_conn=my_conn, t_log=t_log, verbose=verbose) if verbose is True: t_log.new_event("execute_values() done") cur.close()
def generic_disassociate_parent(parent_id: int = None, child_id: int = None, table_name: str = None, parent_table_name: str = None, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = False): """Associate the parent and child tables using parent id. Insertion_order and inserted_by are optional""" parent_key = parent_table_name + '_id' self_key = table_name + '_id' join_table = table_name + '_' + parent_table_name if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] sql = 'DELETE FROM {table} WHERE ({self_id}, {parent_id}) = (%s, %s)' query = SQL(sql).format(table=Identifier(join_table), self_id=Identifier(self_key), parent_id=Identifier(parent_key)) cur = conn.cursor(cursor_factory=NamedTupleCursor) if verbose is True: print(query.as_string(conn)) print(cur.mogrify(query, (child_id, parent_id))) t_log.new_event('Disassociating Tables: ' + join_table) try: cur.execute(query, (child_id, parent_id)) except OperationalError as error: print(error) conn.commit() data_df = \ generic_pull_grouped_data(table_name=table_name, parent_table_name=parent_table_name, my_conn=my_conn, t_log=t_log, verbose=verbose) if verbose is True: t_log.new_event('Finished disassociating: ' + join_table) return data_df
def generic_pull_grouped_data(table_name: str = None, parent_table_name: str = None, verbose: bool = False, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None) -> DataFrame: """Multi-index Extract DataFrame DB""" table_id_name: str = table_name + '_id' parent_id_name: str = parent_table_name + '_id' join_table: str = table_name + '_' + parent_table_name if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] sql = 'SELECT * FROM {join_table} RIGHT JOIN {table} USING({table_id})' query = SQL(sql).format(table=Identifier(table_name), join_table=Identifier(join_table), table_id=Identifier(table_id_name)) if verbose is True: t_log.new_event('Loading Database: ' + table_name) data_df = read_sql(query, con=conn, index_col=[parent_id_name, table_id_name]) # This was a good example of loading objects to file # data_df['latex'] = data_df['latex'].apply(loads) data_df['latex_obj'] = None for row in data_df.itertuples(): data_df.loc[row.Index, 'latex_obj'] = \ LatexData(my_conn=my_conn, latex=row.latex, template_id=row.template_id, image=row.image, compiled_at=row.compiled_at) data_df.sort_values([parent_id_name, 'insertion_order', 'created_at'], inplace=True) if verbose is True: t_log.new_event('Database Loaded: ' + table_name) return data_df
def other_parents(self, child_id: int = None, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = None): """Pulls list of other parents""" gd = self.grouped_data gd_inds = gd.index.dropna() if len(gd_inds) > 0: parent_df = gd.loc[(slice(None), child_id), :].droplevel(self.id_name()) pids = tuple(parent_df.index.to_list()) if verbose is True and t_log is None: t_log = TimeLogger() if my_conn is None: my_conn = self.my_conn else: self.my_conn = my_conn my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] sql = "SELECT * FROM {parent_table} WHERE {parent_id} IN %s;" query = SQL(sql).format( parent_table=Identifier(self.parent_table_name), parent_id=Identifier(self.parent_table_id_name())) if verbose is True: t_log.new_event('Loading Database: ' + self.parent_table_name) cur = conn.cursor(cursor_factory=NamedTupleCursor) cur.execute(query, (pids, )) records = cur.fetchall() if verbose is True: t_log.new_event('Database Loaded: ' + self.parent_table_name) else: if verbose is True: t_log.new_event('No Other Parents') records = [] return records
def new_record(self, new_record: TemplateRecordInput, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = False): """Method to Insert New Equation Records""" table_name = self.name if verbose is True and t_log is None: t_log = TimeLogger() if my_conn is None: my_conn = self.my_conn else: self.my_conn = my_conn my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] query = SQL('INSERT INTO {table} ({fields}) VALUES ({values})').format( table=Identifier(table_name), fields=SQL(', ').join(map(Identifier, new_record._fields)), values=SQL(', ').join(map(Placeholder, new_record._fields))) if verbose: t_log.new_event(query.as_string(conn)) cur = conn.cursor(cursor_factory=NamedTupleCursor) if verbose: t_log.new_event('Adding new record to Table: {aTable}'.format( aTable=table_name)) try: cur.execute(query, new_record._asdict()) except DatabaseError as error: print(error) conn.commit() cur.close() self.pull_data()
def insert(self, new_data, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = False): """Method to Insert New Equation Records""" if verbose is True and t_log is None: t_log = TimeLogger() if my_conn is None: my_conn = self.my_conn else: self.my_conn = my_conn my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] cur = conn.cursor() self.types_df = self.types_df.append(new_data) sql = 'INSERT INTO {table} (type_name) VALUES %s;' query = SQL(sql).format(table=Identifier(self.name)) tuples = [tuple([x]) for x in new_data.index] if verbose is True: print(query.as_string(cur)) print('Values', tuples) t_log.new_event('Loading: ' + self.name) try: execute_values(cur, query, tuples) conn.commit() except DatabaseError as error: print("Error: %s" % error) conn.rollback() cur.close() if verbose is True: t_log.new_event("execute_values() done") cur.close()
def template(my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, version: int = None, verbose: bool = False) -> NamedTupleCursor: """Function to pull the data for a specified template""" if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] cur = conn.cursor(cursor_factory=NamedTupleCursor) if version is None: if verbose: t_log.new_event('Extracting Latest Template from Database') cur.execute('SELECT * FROM template ORDER BY created_at DESC LIMIT 1') else: try: if verbose: t_log.new_event('Extracting Template with id: {} from Database'.format(version)) cur.execute('SELECT * FROM template WHERE ID=%s', (version,)) except DatabaseError as error: print("Couldn't retrieve that template.", error) print("Returning latest template.") cur.execute('SELECT * FROM template ORDER BY created_at DESC LIMIT 1') if verbose: t_log.new_event('Starting Template Extraction') the_template = cur.fetchone() cur.close() if verbose: t_log.new_event('Finished Template Extraction') return the_template
def generic_pull_data(table_name: str = None, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = None) -> DataFrame: """Multi-index Extract DataFrame DB""" if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] table_id_name: str = table_name + '_id' query = SQL('SELECT * FROM {table}').format(table=Identifier(table_name)) if verbose is True: t_log.new_event('Loading Equation Group Data') data_df = read_sql(query, con=conn, index_col=table_id_name) if verbose is True: t_log.new_event('Finished Equation Group Data') return data_df
def update(self, an_id: id = None, where_key: str = None, name: str = None, data=None, notes: str = None, modified_by: str = None, created_by: str = None, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None, verbose: bool = None): """Insert New Record Into grouped_physics_object""" if my_conn is None: my_conn = self.my_conn else: self.my_conn = my_conn if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] db_params = my_conn['db_params'] if where_key is None: where_key = self.id_name() if an_id is None: warn("No Record ID Specified", NoRecordIDError) else: if data is None: data = {} data.update(add_field('name', name)) data.update(add_field('notes', notes)) data.update(add_field('created_by', created_by)) # If there is no data, then skip. Of course one could still change modified by: if len(data) > 0 or modified_by is not None: # Always require a modified by and because one can change data without specifying a modifer, # this is necessary. We don't check it before the previous if, because we don't want to create # a modified_by if not data was set and no modified_by was set. if modified_by is None: modified_by = db_params['user'] data.update(modified_by=modified_by) fields = data.keys() sql = "UPDATE {table} SET {fields} WHERE {pkey} = {a_value}" if verbose: print('Data:\n', data) print('\nFields:\n', fields) query = SQL(sql).format( table=Identifier(self.table_name), fields=SQL(', ').join( Composed([Identifier(k), SQL(' = '), Placeholder(k)]) for k in fields ), pkey=Identifier(where_key), a_value=Placeholder('where_key') ) data.update(where_key=an_id) cur = conn.cursor(cursor_factory=NamedTupleCursor) if verbose: print(query.as_string(conn)) print(cur.mogrify(query, data)) try: cur.execute(query, data) except OperationalError as error: print(error) conn.commit() cur.close() self.pull_data()
def generic_associate_parent(parent_id: int = None, child_id: int = None, table_name: str = None, parent_table_name: str = None, insertion_order: int = None, inserted_by: str = None, new_record: dict = None, verbose: bool = False, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None): """Associate the parent and child tables using parent id. Insertion_order and inserted_by are optional""" parent_key = parent_table_name + '_id' self_key = table_name + '_id' join_table = table_name + '_' + parent_table_name if verbose is True and t_log is None: t_log = TimeLogger() my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] db_params = my_conn['db_params'] if new_record is None: new_record = {} if inserted_by is None: inserted_by = db_params['user'] new_record.update({ parent_key: parent_id, self_key: child_id }, insertion_order=insertion_order, inserted_by=inserted_by) sql = 'INSERT INTO {table} ({fields}) VALUES ({values})' keys = new_record.keys() query = SQL(sql).format(table=Identifier(join_table), fields=SQL(', ').join(map(Identifier, keys)), values=SQL(', ').join(map(Placeholder, keys))) cur = conn.cursor(cursor_factory=NamedTupleCursor) if verbose is True: t_log.new_event('Associating Tables: ' + join_table) try: cur.execute(query, new_record) except OperationalError as error: print(error) conn.commit() cur.close() data_df = \ generic_pull_grouped_data(table_name=table_name, parent_table_name=parent_table_name, my_conn=my_conn, t_log=t_log, verbose=verbose) if verbose is True: t_log.new_event('Finished Associating: ' + join_table) return data_df
def generic_new_record_db(parent_id: int = None, table_name: str = None, parent_table_name: str = None, data_df: Optional[DataFrame] = None, name: str = None, new_record=None, latex: LatexData = None, notes: str = None, dimensions: int = 1, insertion_order: int = None, created_by: str = None, unit_id: int = 1, verbose: bool = None, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None) -> DataFrame: """Insert New Record Into math_object""" if verbose is True and t_log is None: t_log = TimeLogger() if new_record is None: new_record = {} my_conn = my_connect(my_conn=my_conn, t_log=t_log, verbose=verbose) conn = my_conn['conn'] db_params = my_conn['db_params'] table_id = table_name + '_id' next_id: int = generic_last_equation_number(data_df) + 1 if name is None: name = "{aTable} {ID:d}".format(ID=next_id, aTable=table_name) if created_by is None: created_by = db_params['user'] if latex is None: latex = LatexData() new_record.update(name=name, notes=notes, dimensions=dimensions, unit_id=unit_id, type_name='Unassigned', latex=latex.latex, image=latex.image, compiled_at=latex.compiled_at, template_id=latex.template_id, created_by=created_by) query = SQL( 'INSERT INTO {table} ({fields}) VALUES ({values}) RETURNING *').format( table=Identifier(table_name), fields=SQL(', ').join(map(Identifier, new_record.keys())), values=SQL(', ').join(map(Placeholder, new_record.keys()))) if verbose: print(query.as_string(conn)) cur = conn.cursor(cursor_factory=NamedTupleCursor) if verbose: print('Adding new record to Table: {aTable}'.format(aTable=table_name)) try: cur.execute(query, new_record) except OperationalError as error: print(error) new_records = cur.fetchall() conn.commit() cur.close() updated_df: Optional[DataFrame] = None if parent_id is not None: for record in new_records: updated_df = generic_associate_parent( my_conn=my_conn, t_log=t_log, parent_id=parent_id, child_id=getattr(record, table_id), insertion_order=insertion_order, table_name=table_name, parent_table_name=parent_table_name, inserted_by=created_by, verbose=verbose) else: updated_df = \ generic_pull_grouped_data(table_name=table_name, parent_table_name=parent_table_name, my_conn=my_conn, t_log=t_log, verbose=verbose) return updated_df
def compile_pattern(pattern: str = 'm^3', keep: bool = True, temp_fname: str = "eq_db", version: int = None, a_template: str = None, verbose: bool = False, my_conn: Optional[dict] = None, t_log: Optional[TimeLogger] = None) -> bytes: """General Latex Compile Function""" if verbose: if t_log is None: t_log = TimeLogger() print('\tArguments:') pprint.PrettyPrinter(indent=12).pprint(locals()) if a_template is None: a_template_record = template(version=version, my_conn=my_conn, t_log=t_log, verbose=verbose) a_template = a_template_record.data this_path = Path.cwd() if this_path.name == 'CustomWidgets': os.chdir('../LaTeX') elif this_path.name == 'equation_database': os.chdir('LaTeX') else: warn('Unrecognized Directory') # preprocess pattern to make sure it conforms to latex processed_pattern = pattern.strip() text_file = open(temp_fname+'.tex', "w") text_file.write(a_template.replace('%__REPLACEMENT__TEXT', processed_pattern)) text_file.close() # try: if verbose: print("Operating System: ", os.name) t_log.new_event('Executing XeLaTeX:') shell = os.name == 'nt' try: p_1 = subprocess.run(['xelatex.exe', temp_fname + '.tex', '-interaction=batchmode'], shell=shell, capture_output=True, text=True, check=True) if verbose: pprint.PrettyPrinter(indent=8).pprint(p_1) except subprocess.CalledProcessError as error: print(error.output) try: if verbose: t_log.new_event('Converting to png') p_2 = subprocess.run(['convert.exe', '-density', '300', '-depth', '8', '-quality', '85', temp_fname + '.pdf', 'png32:'+temp_fname+'.png'], shell=shell, capture_output=True, text=True, check=True) if verbose: t_log.new_event('Finished converting png') pprint.PrettyPrinter(indent=8).pprint(p_2) except subprocess.CalledProcessError as error: t_log.new_event('Failed to make png:') print(error.output) if verbose: t_log.new_event('Pulling png data into python') with open(temp_fname + '.png', 'rb') as file: png_data: bytes = file.read() os.chdir(this_path) if keep is False: clean_files(temp_fname) return png_data
def __init__(self, *args, **kwargs): self.app = QApplication(sys.argv) super().__init__(*args, **kwargs) # Some good colors: # #afbcc6, #b9afc6, #afb0c6 self.title = "Equation Database" self.left = WINDOW_LEFT_START # self.left = 0 self.top = WINDOW_TOP_START self.height = WINDOW_HEIGHT self.width = int(self.height * golden_ratio) # region ToolBar self.toolbar = self.addToolBar('Save') self.toolbar.setIconSize(QSize(128, 128)) save_action = QAction(QIcon('Icons/save_button_256x256.png'), '&Save', self) save_action.setShortcut('Ctrl+S') save_action.setStatusTip('Save Equation Group') analyze_action = QAction(QIcon('Icons/analyze_cog_512x512.png'), '&Analyze', self) analyze_action.setShortcut('Alt+A') analyze_action.setStatusTip('Analyze Equation Group') new_eqn_action = QAction(QIcon('Icons/sigma_icon_256x256.png'), '&New Equation', self) new_eqn_action.setShortcut('Ctrl+N') new_eqn_action.setStatusTip('New Equation') new_eqn_group_action = QAction(QIcon('Icons/new_eq_group_1000x1000.png'), '&New Equation Group', self) new_eqn_group_action.setShortcut('Alt+N') new_eqn_group_action.setStatusTip('New Equation Group') new_eqn_group_action.triggered.connect(self.new_equation_group) eqn_group_info_action = QAction(QIcon('Icons/info_icon256x256.png'), '&Equation Group Information', self) eqn_group_info_action.setShortcut('Alt+I') eqn_group_info_action.setStatusTip('Equation Group Information') self.toolbar.addAction(save_action) self.toolbar.addAction(new_eqn_action) empty1 = QWidget(self.toolbar) ew: int = 50 # pylint: disable=invalid-name empty1.setFixedWidth(ew) empty2 = QWidget(self.toolbar) empty2.setFixedWidth(ew) self.toolbar.addWidget(empty1) self.toolbar.addSeparator() self.toolbar.addWidget(empty2) self.toolbar.addAction(new_eqn_group_action) self.toolbar.addAction(analyze_action) self.toolbar.addAction(eqn_group_info_action) # endregion t_log = TimeLogger() verbose = True my_conn = my_connect(t_log=t_log, verbose=verbose) self.my_conn = my_conn t_log.new_event("Start Gui Build: ") # region Equation Group - Left Frame # ----------------------------------------------------------------------------------------------------------- self.eq_group_gbox = QGroupBox("Equation Group") self.eq_group_gbox.setMinimumWidth(200) self.eq_group_v_layout = QVBoxLayout(self.eq_group_gbox) self.eq_group_v_layout.setSpacing(5) self.eq_group_cbox = QComboBox(self.eq_group_gbox) self.eq_group_cbox.activated.connect(self.populate_equation_listbox) self.eq_group_v_layout.addWidget(self.eq_group_cbox) self.analyze_frame = QFrame(self.eq_group_gbox) self.analyze_h_layout = QHBoxLayout(self.analyze_frame) self.analyze_h_layout.setContentsMargins(10, 0, 10, 15) size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.analyze_frame.setSizePolicy(size_policy) self.equation_filter_list = EDFilterListWidget(self.eq_group_gbox) self.equation_listbox = self.equation_filter_list.list # self.equation_listbox = QListWidget(self.eq_group_gbox) self.equation_listbox.setSelectionBehavior(QAbstractItemView.SelectItems) self.equation_listbox.setSelectionMode(QAbstractItemView.ExtendedSelection) self.equation_listbox.selectionModel().selectionChanged.connect(self.select_one_equation) self.equation_filter_list.add.connect(self.add_equation) self.equation_filter_list.remove.connect(self.remove_equation) self.eq_group_v_layout.addWidget(self.equation_filter_list) # endregion # region Equation Details - Right Frame # ----------------------------------------------------------------------------------------------------------- self.eq_details_gbox = QGroupBox("Equation Details") # Entire encapsulating Gbox self.eq_details_v_layout = QVBoxLayout(self.eq_details_gbox) # region Equation Header added to Equation Details # ********************************************************** self.eq_header_frame = QFrame() size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.eq_header_frame.setSizePolicy(size_policy) self.eq_header_g_layout = QGridLayout(self.eq_header_frame) self.eq_details_v_layout.addWidget(self.eq_header_frame) self.name_label = QLabel("Equation Name") self.name_l_edit = QLineEdit() self.eq_header_g_layout.addWidget(self.name_label, 0, 0) self.eq_header_g_layout.addWidget(self.name_l_edit, 0, 1) self.codefile_label = QLabel("Code File") self.codefile_l_edit = QLineEdit() self.eq_header_g_layout.addWidget(self.codefile_label, 1, 0) self.eq_header_g_layout.addWidget(self.codefile_l_edit, 1, 1) self.type_label = QLabel("Type") self.type_cbox = QComboBox() self.type_cbox.setMinimumWidth(700) self.eq_header_g_layout.addWidget(self.type_label, 0, 2) self.eq_header_g_layout.addWidget(self.type_cbox, 0, 3) self.associated_eq_groups_btn = EquationButton("Associated Eq Groups") self.eq_header_g_layout.addWidget(self.associated_eq_groups_btn, 1, 3) self.eq_header_g_layout.setAlignment(self.associated_eq_groups_btn, Qt.AlignLeft) self.details_btn = EquationButton("Other Details") self.eq_header_g_layout.addWidget(self.details_btn, 1, 3) self.eq_header_g_layout.setAlignment(self.details_btn, Qt.AlignRight) # endregion # region LaTeX added to Equation Details # ********************************************************** self.latex_gbox = QGroupBox("LaTeX") size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.latex_gbox.setSizePolicy(size_policy) self.latex_v_layout = QVBoxLayout(self.latex_gbox) # This would be great for when one wants to filter content based on what is being typed # self.latex_textbox.textChanged.connect(self.update_latex_image) self.latex_graphicbox = QGraphicsView(self.latex_gbox) self.scene = QGraphicsScene() self.latex_graphicbox.setScene(self.scene) # self.latex_graphicbox.setMinimumSize(QSize(907, 369)) self.latex_textbox = LaTexTextEdit(my_conn=my_conn, parent=self.latex_gbox, t_log=t_log, scene=self.scene, graphics_view=self.latex_graphicbox, verbose=verbose) self.latex_splitter = Customsplitter(Qt.Vertical) # Note Handle for a vert splitter is oriented Horizontally self.latex_splitter.addWidget(self.latex_textbox) self.latex_splitter.addWidget(self.latex_graphicbox) self.latex_v_layout.addWidget(self.latex_splitter) self.latex_btn_frame = QFrame() size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.latex_btn_frame.setSizePolicy(size_policy) self.latex_btn_h_layout = QHBoxLayout(self.latex_btn_frame) self.latex_btn_h_layout.setContentsMargins(0, 0, 1, 10) self.latex_template_btn = EquationButton("Template") self.latex_update_btn = EquationButton("Update") h_spacer = QSpacerItem(20, 40, QSizePolicy.MinimumExpanding, QSizePolicy.Expanding) self.latex_btn_h_layout.addWidget(self.latex_template_btn) self.latex_btn_h_layout.addItem(h_spacer) self.latex_btn_h_layout.addWidget(self.latex_update_btn) self.latex_v_layout.addWidget(self.latex_btn_frame) # endregion # region Variables Notes self.var_notes_frame = QFrame(self.eq_details_gbox) self.var_notes_v_layout = QVBoxLayout(self.var_notes_frame) # self.var_notes_frame.setLayout(self.var_notes_v_layout) self.variables_gbox = QGroupBox("Variables") self.variables_v_layout = QVBoxLayout(self.variables_gbox) self.variables_v_layout.setSpacing(5) # self.variables_gbox.setLayout(self.var_notes_v_layout) self.variables_tbl = QTableWidget(self.variables_gbox) self.variables_v_layout.addWidget(self.variables_tbl) self.var_add_btn = QPushButton("+") self.var_add_btn.setObjectName("add_rm_btn") ar_w = 50 self.var_add_btn.setFixedSize(QSize(ar_w, int(ar_w))) self.var_add_btn.clicked.connect(self.add_variable) self.var_rm_btn = QPushButton("-") self.var_rm_btn.setObjectName("add_rm_btn") self.var_rm_btn.clicked.connect(self.remove_variable) self.var_rm_btn.setFixedSize(QSize(ar_w, int(ar_w))) self.var_add_rm_frame = QFrame(self.variables_gbox) size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.var_add_rm_frame.setSizePolicy(size_policy) self.var_add_rm_h_layout = QHBoxLayout(self.var_add_rm_frame) self.var_add_rm_h_layout.setSpacing(2) h_spacer = QSpacerItem(20, 40, QSizePolicy.MinimumExpanding, QSizePolicy.Expanding) self.var_add_rm_h_layout.addItem(h_spacer) self.var_add_rm_h_layout.addWidget(self.var_add_btn) self.var_add_rm_h_layout.addWidget(self.var_rm_btn) self.variables_v_layout.addWidget(self.var_add_rm_frame) self.notes_gbox = QGroupBox("Notes") self.notes_v_layout = QVBoxLayout(self.notes_gbox) # self.notes_gbox.setLayout(self.notes_v_layout) self.notes_textbox = QTextEdit(self.notes_gbox) self.notes_v_layout.addWidget(self.notes_textbox) self.notes_btn_frame = QFrame() size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.notes_btn_frame.setSizePolicy(size_policy) self.notes_btn_h_layout = QHBoxLayout(self.notes_btn_frame) self.notes_btn_h_layout.setContentsMargins(0, 0, 1, 10) self.notes_update_btn = EquationButton("Update") h_spacer = QSpacerItem(20, 40, QSizePolicy.MinimumExpanding, QSizePolicy.Expanding) self.notes_btn_h_layout.addItem(h_spacer) self.notes_btn_h_layout.addWidget(self.notes_update_btn) self.notes_v_layout.addWidget(self.notes_btn_frame) self.var_notes_vsplt = Customsplitter(Qt.Vertical) self.var_notes_vsplt.addWidget(self.variables_gbox) self.var_notes_vsplt.addWidget(self.notes_gbox) self.var_notes_v_layout.addWidget(self.var_notes_vsplt) # endregion self.detail_v_splitter = Customsplitter() self.detail_v_splitter.addWidget(self.latex_gbox) self.detail_v_splitter.addWidget(self.var_notes_frame) self.detail_v_splitter.setSizes([int(self.width * 0.7 * 0.5), int(self.width * 0.7 * 0.5)]) self.eq_details_v_layout.addWidget(self.detail_v_splitter) # endregion # region Main Splitter splits the equation groups list view from the details view # ----------------------------------------------------------------------------------------------------------- self.main_splitter = Customsplitter() self.main_splitter.addWidget(self.eq_group_gbox) self.main_splitter.addWidget(self.eq_details_gbox) self.main_splitter.setSizes([int(self.width * 0.3), int(self.width * 0.7)]) # endregion # region Main Window Creation self.main_frame = QFrame() self.main_layout = QVBoxLayout(self.main_frame) self.main_layout.addWidget(self.main_splitter) self.setCentralWidget(self.main_frame) self.setGeometry(self.left, self.top, self.width, self.height) self.setWindowTitle(self.title) app_icon = QIcon("Icons/sigma_icon.png") self.setWindowIcon(app_icon) self.app.setStyle('Oxygen') # endregion # region Data members t_log.new_event("End GUI Build") self.state_data = dict() # t_log.new_event("Equation Group Load") self.eqn_grp = EquationGroup(my_conn=my_conn, t_log=t_log, verbose=verbose) self.eq = GroupedEquations(my_conn=my_conn, t_log=t_log, verbose=verbose) self.var = GroupedVariables(my_conn=my_conn, t_log=t_log, verbose=verbose) self.unit = Unit(my_conn=my_conn, t_log=t_log, verbose=verbose) self.eq_type = TypeTable(name='equation_type', my_conn=my_conn, t_log=t_log, verbose=verbose) self.var_type = TypeTable(name='variable_type', my_conn=my_conn, t_log=t_log, verbose=verbose) self.unit_type = TypeTable(name='unit_type', my_conn=my_conn, t_log=t_log, verbose=verbose) t_log.new_event("Data Finished Loading") self.eq_grp_id: int = 1 # Can envision it pulling user specified state information someday self.eqn_records_for_eqn_group = None # Gets Populated when equations are present self.eq_id: tuple = (1,) # Same comment as eq_grp_id self.var_records_for_eqns = None # Gets populated when eqn_group_gets selected self.selected_equation = None # Stores the selected equation self.latex_textbox.db_ref = self.eq self.equation_taken: bool = False t_log.new_event("Populating Boxes") self.refresh_eqn_group_combo_box() self.populate_equation_listbox() t_log.new_event("Populating Boxes") self.app.setStyleSheet(open('equation_db.css').read()) t_log.new_event("Finished Style Sheet") print() print('Total Time: ', t_log.total_time())
from equation_group_dialog import EquationGroupDialog from equation_dialog import EquationDialog from equations import GroupedEquations # , EquationRecord from variables import GroupedVariables, GroupedVariableRecord from variable_dialog import VariableDialog from CustomWidgets.filter_list_widget import EDFilterListWidget from unit import Unit from type_table import TypeTable from time_logging import TimeLogger WINDOW_LEFT_START = 300 WINDOW_TOP_START = 300 WINDOW_HEIGHT = 1500 if platform.system() == "Windows": outer_log = TimeLogger() outer_log.new_event('Starting Windows Stuff: ') displays = screeninfo.get_monitors() if len(displays) == 2: WINDOW_LEFT_START = 3200 WINDOW_TOP_START = 25 WINDOW_HEIGHT = 900 elif len(displays) == 3: my_mon = displays[2] WINDOW_LEFT_START = my_mon.x + int(my_mon.width / 20) WINDOW_TOP_START = 300 WINDOW_HEIGHT = 1500 # for item in obj: