def fillTableWidget(self, qtable: QTableWidget, df: pd.DataFrame = None): # TODO: Hacerla gfeneral {self.fromTime} {self.toTime} recibiendo el widget # Limpiar contenidos de tabla headerList = tuple(df.columns.values) qtable.clearContents() qtable.setColumnCount(len(headerList)) qtable.setHorizontalHeaderLabels(headerList) # self.qtable.horizontalHeader().setStretchLastSection(True) qtable.horizontalHeader( ).setSectionResizeMode(QHeaderView.Stretch) rowCount = 0 for row in df.itertuples(): # Sets the number of rows in this table's model to rows. If this is less than rowCount(), # the data in the unwanted rows is discarded. qtable.setRowCount(rowCount+1) for i, columnName in enumerate(headerList): # val = QTableWidgetItem(row._asdict()[str(columnName)]) val = QTableWidgetItem(str(row._asdict()[columnName])) qtable.setItem(rowCount, i, val) rowCount += 1
class ListaUnidades(BaseSubWindow): def __init__(self, parent=None): super().__init__("Unidades cadastrados no sistema") self.parent = parent self.setTable() self.setLayoutTable() #super().setMinimumWidth(1050) super().setMinimumHeight(500) def setTable(self): '''Cria os Widgets da tabela''' self.unidades = self.parent.unidade.getUnidades( ) #Pega as unidades salvas no sistema self.table = QTableWidget( len(self.unidades), 3 ) #Cria a tabela com a quantidade de linhas conforme os unidades e 11 colunas header_label = """Ação-Sigla-Descrição""" #Lista usada para formar os titulos da tabela self.table.setHorizontalHeaderLabels(header_label.split( '-')) #Interpreta a lista de titulos e seta os titulos da tabela self.setValuesTable() #Coloca os valores na tabela self.table.resizeColumnsToContents( ) #As colunas ficam com a largura do tamanho do conteudo self.table.setEditTriggers( QAbstractItemView.NoEditTriggers) #Bloqueia o edit nos itens def setLayoutTable(self): '''Posiciona os Widgets da tabela''' self.conteudo = QWidget() self.layout_group = QVBoxLayout() self.layout_group.addWidget(self.table) self.conteudo.setLayout(self.layout_group) self.setWidget(self.conteudo) def setValuesTable(self): '''Preenche a tabela usando dois laços de repetição(um para linhas e outro para colunas)''' linha = 0 coluna = 1 for unidade in self.unidades: #Separa as linhas dos unidades self.table.setCellWidget( linha, 0, ButtonGroup(self, unidade[0], linha) ) #Coloca os botões na celula e passa o id do unidade for item in unidade[ 1:]: #Separa cada coluna da linha(da segunda coluna em diante) self.table.setItem(linha, coluna, QTableWidgetItem(str(item))) coluna += 1 coluna = 1 linha += 1 def updateTable(self): '''Atualiza as linhas da tabela''' self.unidades = self.parent.unidade.getProdutos( ) #Pega os unidades salvos no sistema self.table.clearContents() if (len(self.unidades) > self.table.rowCount()): self.table.insertRow( int(len(self.unidades) - self.table.rowCount())) elif (len(self.unidades) < self.table.rowCount()): self.table.removeRow( int(self.table.rowCount() - len(self.unidades))) self.setValuesTable()
def out(self, header_titles: list, cursor, table: QTableWidget = None, callback=None): if not table: table: QTableWidget = self._docWindow.table table.clearContents() table.setColumnCount(len(header_titles)) table.setHorizontalHeaderLabels(header_titles) row = cursor.fetchone() table.setRowCount(0) table.resizeColumnsToContents() if not row: QueryMessage(399) return elif row[0] == 0 and callback is not None: callback() elif len(row) == 1: QueryMessage(row[0]) else: row_count = 0 while row: table.setRowCount(row_count + 1) for x in range(len(header_titles)): if str(row[x]) == 'True' or str(row[x]) == 'False': table.setItem( row_count, x, QTableWidgetItem("Да" if row[7] else "Нет")) elif str(row[x]) == 'None': table.setItem(row_count, x, QTableWidgetItem("-")) else: table.setItem(row_count, x, QTableWidgetItem(str(row[x]))) row_count += 1 row = cursor.fetchone() table.resizeColumnsToContents() if table == self._docWindow.table: self.selected_row = -1 self.selected_column = -1 self._docWindow.desc_table.clearContents() self._docWindow.desc_table.setRowCount(0)
class MainApp(QWidget): """ Coordinate transform program for relocating samples in different coordinate systems Developer: Reto Trappitsch Version: 2.1.1 Date: May 29, 2020 """ def __init__(self): # version number: self.version = '2.1.1' self.version_date = 'May 29, 2020' # run in debug mode? self.rundebug = False # round digits self.rounddig = 3 # which calculation mode to start in (Nittler or Admon - labels of radiobuttons) self.calcmode = 'Nittler' # initialize the thing super().__init__() self.title = 'Coordinate Transformation' self.left = 50 self.top = 80 self.width = 900 # this is used for geometry but then also for tableheight. tableheight dominates! self.height = 845 # default for header, columns self.default_header_rows = 1 self.default_name_column = 1 self.default_x_column = 2 self.default_y_column = 3 # my clipboard self.clipboard = QApplication.clipboard() self.setup_keyboard_shortcuts() # initialize the UI self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) # define outermost v layout outervlayout = QVBoxLayout() # some top row buttons and layout toprowbutthlayout = QHBoxLayout() # open buttons openfile_butt = QPushButton('Open file') openfile_butt.clicked.connect(self.openfile) openfile_butt.setToolTip( 'Load coordinates from a file. Please make sure you specify\n' 'how many header rows the file has and where your x, y, and\n' 'fiducial data is.' 'Files that can be read are: comma separated (*.csv), tab\n' 'separated (*.txt), or excel files.') toprowbutthlayout.addWidget(openfile_butt) # save button toprowbutthlayout.addStretch() savecsv_butt = QPushButton('Save csv') savecsv_butt.clicked.connect(lambda: self.savefile('csv')) savecsv_butt.setToolTip( 'Save the current table, as is displayed, into a csv file. This file can also be\n' 'imported later with the \'Open csv\' button.') toprowbutthlayout.addWidget(savecsv_butt) savetxt_butt = QPushButton('Save txt') savetxt_butt.clicked.connect(lambda: self.savefile('txt')) savecsv_butt.setToolTip( 'Save the current table, as is displayed, into a txt file. This file can also be\n' 'imported later with the \'Open txt\' button.') toprowbutthlayout.addWidget(savetxt_butt) # add radiobuttons for method toprowbutthlayout.addStretch() mnit_radio = QRadioButton('Nittler') mnit_radio.setToolTip( 'Method from Larry Nittler\' PhD thesis, App. E. Only shift and rotation are \n' 'considered. Strech not possible. Linear regression through all reference points\n' 'is calculated, so mechanical slack, etc., is regressed out over time.' ) madm_radio = QRadioButton('Admon') madm_radio.setToolTip( 'Method from Admon et al. (2015). See \'Help\' for full reference. Only three\n' 'fiducial marks are considered for coordinate transformation, however, the stretch\n' 'of coordinate systems is included as well.') if self.calcmode == 'Nittler': mnit_radio.setChecked(True) else: madm_radio.setChecked(True) # connect buttons to the subroutine mnit_radio.toggled.connect(lambda: self.set_calcmode(mnit_radio)) mnit_radio.toggled.connect(lambda: self.set_calcmode(madm_radio)) # add to layout toprowbutthlayout.addWidget(mnit_radio) toprowbutthlayout.addWidget(madm_radio) # add test, help, quit toprowbutthlayout.addStretch() if self.rundebug: test_butt = QPushButton('Test') test_butt.clicked.connect(self.test) toprowbutthlayout.addWidget(test_butt) help_butt = QPushButton('Help') help_butt.clicked.connect(self.help) help_butt.setToolTip('Display a brief help message.') toprowbutthlayout.addWidget(help_butt) quit_butt = QPushButton('Quit') quit_butt.clicked.connect(self.close) quit_butt.setToolTip('Close the program') toprowbutthlayout.addWidget(quit_butt) # add buttons to layout outervlayout.addLayout(toprowbutthlayout) # outervlayout.addStretch() # set a second row with options, QSpinBoxes mostly secondrow = QHBoxLayout() header_label = QLabel('header rows:') self.header_spinbox = QSpinBox(self, minimum=0, maximum=1000) self.header_spinbox.setAlignment(Qt.AlignRight) self.header_spinbox.setValue(self.default_header_rows) self.header_spinbox.setToolTip( 'Select how many rows should be skipped\n' 'at the beginning of file. These are the\n' 'header rows.') namecol_label = QLabel('name col:') self.namecol_spinbox = QSpinBox(self, minimum=0, maximum=1000) self.namecol_spinbox.setAlignment(Qt.AlignRight) self.namecol_spinbox.setValue(self.default_name_column) self.namecol_spinbox.setToolTip('Which column contains the name\n' 'of the location? Select 0 for None.') xcol_label = QLabel('x col:') self.xcol_spinbox = QSpinBox(self, minimum=0, maximum=1000) self.xcol_spinbox.setAlignment(Qt.AlignRight) self.xcol_spinbox.setValue(self.default_x_column) self.xcol_spinbox.setToolTip('Which column contains the x coordinate\n' 'of the location? Select 0 for None.') ycol_label = QLabel('y col:') self.ycol_spinbox = QSpinBox(self, minimum=0, maximum=1000) self.ycol_spinbox.setAlignment(Qt.AlignRight) self.ycol_spinbox.setValue(self.default_y_column) self.ycol_spinbox.setToolTip('Which column contains the y coordinate\n' 'of the location? Select 0 for None.') fid_xcol_label = QLabel('ref x col:') self.fid_xcol_spinbox = QSpinBox(self, minimum=0, maximum=1000) self.fid_xcol_spinbox.setAlignment(Qt.AlignRight) self.fid_xcol_spinbox.setValue(self.default_x_column + 2) self.fid_xcol_spinbox.setToolTip( 'Which column contains the x reference coordinate\n' 'of the location? Select 0 for None.') fid_ycol_label = QLabel('ref y col:') self.fid_ycol_spinbox = QSpinBox(self, minimum=0, maximum=1000) self.fid_ycol_spinbox.setAlignment(Qt.AlignRight) self.fid_ycol_spinbox.setValue(self.default_y_column + 2) self.fid_xcol_spinbox.setToolTip( 'Which column contains the y reference coordinate\n' 'of the location? Select 0 for None.') secondrow.addWidget(header_label) secondrow.addWidget(self.header_spinbox) secondrow.addStretch() secondrow.addWidget(namecol_label) secondrow.addWidget(self.namecol_spinbox) secondrow.addStretch() secondrow.addWidget(xcol_label) secondrow.addWidget(self.xcol_spinbox) secondrow.addStretch() secondrow.addWidget(ycol_label) secondrow.addWidget(self.ycol_spinbox) secondrow.addStretch() secondrow.addWidget(fid_xcol_label) secondrow.addWidget(self.fid_xcol_spinbox) secondrow.addStretch() secondrow.addWidget(fid_ycol_label) secondrow.addWidget(self.fid_ycol_spinbox) secondrow.addStretch() # add to outer layout outervlayout.addLayout(secondrow) # make the table self.datatable = QTableWidget() self.datatable.setRowCount(23) self.datatable.setColumnCount(7) # implement mouse button self.datatable.setContextMenuPolicy(Qt.CustomContextMenu) self.datatable.customContextMenuRequested.connect(self.context_menu) # set headers headers = [ QTableWidgetItem('Name'), QTableWidgetItem('x'), QTableWidgetItem('y'), QTableWidgetItem('x_ref'), QTableWidgetItem('y_ref'), QTableWidgetItem('x_calc'), QTableWidgetItem('y_calc') ] for it in range(len(headers)): self.datatable.setHorizontalHeaderItem(it, headers[it]) # set up clipboard for table self.clip = QGuiApplication.clipboard() # add table to widget outervlayout.addWidget(self.datatable) # bottom button row bottrowbutthlayout = QHBoxLayout() # add Row addrow_butt = QPushButton('+ Row') addrow_butt.clicked.connect(self.addrow) addrow_butt.setToolTip( 'Add an empty row to the data table. You can then manually enter new values into this\n' 'empty row.') bottrowbutthlayout.addWidget(addrow_butt) # clear table clear_butt = QPushButton('Clear all') clear_butt.clicked.connect(self.cleartable) clear_butt.setToolTip( 'Clear all data in the table. A confirmation will be required, but after that, there\n' 'is no undoing this action. Make sure you have the data, assuming you need it, saved.' ) bottrowbutthlayout.addWidget(clear_butt) bottrowbutthlayout.addStretch() # information on Fit self.infolbl = QLabel('') bottrowbutthlayout.addWidget(self.infolbl) bottrowbutthlayout.addStretch() # calculate button calc_butt = QPushButton('Calculate') calc_butt.clicked.connect(self.calculate) calc_butt.setToolTip( 'Calculate the regression. An \'Average distance error\' will be provided. This is a\n' 'number that is good to compare from fit to fit. If weird, non-numeric values show up\n' 'make sure that you have entered proper numbers.') bottrowbutthlayout.addWidget(calc_butt) # add to outer layout # outervlayout.addStretch() outervlayout.addLayout(bottrowbutthlayout) # set layout to app self.setLayout(outervlayout) # show the UI self.show() def setup_keyboard_shortcuts(self): # Keyboard shortcuts copy_shortcut = QShortcut(QKeySequence("Ctrl+C"), self) copy_shortcut.activated.connect(self.copy) paste_shortcut = QShortcut(QKeySequence("Ctrl+V"), self) paste_shortcut.activated.connect(self.paste) open_shortcut = QShortcut(QKeySequence("Ctrl+O"), self) open_shortcut.activated.connect(self.openfile) del_shortcut = QShortcut(QKeySequence("Del"), self) del_shortcut.activated.connect(self.delete) def context_menu(self, position): menu = QMenu() copyAction = menu.addAction("Copy") pasteAction = menu.addAction("Paste") delAction = menu.addAction("Delete") action = menu.exec_(self.datatable.mapToGlobal(position)) if action == copyAction: self.copy() elif action == pasteAction: self.paste() elif action == delAction: self.delete() def set_calcmode(self, rb): if rb.isChecked(): self.calcmode = rb.text() if self.rundebug: print(self.calcmode) def openfile(self): # file dialog options = QFileDialog.Options() # options |= QFileDialog.DontUseNativeDialog filename, _ = QFileDialog.getOpenFileName( self, 'QFileDialog.getOpenFileName()', '', 'Supported Files (*.csv *.txt *.xls *.xlsx);;All Files (*)', options=options) if filename == '': return sep = filename[-4:len(filename)] headerrows = int(self.header_spinbox.value()) namecol = int(self.namecol_spinbox.value()) xdatcol = int(self.xcol_spinbox.value()) ydatcol = int(self.ycol_spinbox.value()) xfidcol = int(self.fid_xcol_spinbox.value()) yfidcol = int(self.fid_ycol_spinbox.value()) # columns to use usecol = [] if namecol > 0: usecol.append(namecol - 1) usecol.append(xdatcol - 1) usecol.append(ydatcol - 1) usecol.append(xfidcol - 1) usecol.append(yfidcol - 1) datain = None # csv and txt read in: try: if sep == '.csv': datain = pd.read_csv(filename, header=None, skiprows=headerrows, usecols=usecol)[usecol] # separator: elif sep == '.txt': datain = pd.read_csv(filename, delimiter='\t', header=None, skiprows=headerrows, usecols=usecol)[usecol] elif sep == '.xls' or sep == 'xlsx': datain = pd.read_excel(filename, header=None, skiprows=headerrows, usecols=usecol)[usecol] except KeyError or ValueError: self.show_data_error() return # first set the length of the table to be the length of the data self.datatable.setRowCount(0) # name column present namecolpresent = False if namecol > 0: namecolpresent = True # now add data rows for it in range(datain.shape[0]): row = [] if not namecolpresent: row.append('') for jt in range(datain.shape[1]): row.append(datain.iloc[it, jt]) # add the row to the table self.addTableRow(row) # adjust table size self.datatable.resizeColumnsToContents() def show_data_error(self): QMessageBox.warning( self, 'Requested data not found', 'Could not find the data you requested. Please ensure' 'that the data exists in the respective columns.') def addTableRow(self, row_data): row = self.datatable.rowCount() self.datatable.setRowCount(row + 1) col = 0 for item in row_data: itemstr = str(item) if itemstr == 'nan': itemstr = '' cell = QTableWidgetItem(itemstr) self.datatable.setItem(row, col, cell) col += 1 def savefile(self, sep): # get file name from dialog if sep == 'txt': filename, _ = QFileDialog.getSaveFileName( self, 'Save File As', '', 'Text Files (*.txt);;All Files (*)') else: filename, _ = QFileDialog.getSaveFileName( self, 'Save File As', '', 'Comma Separated Files (*.csv);;All Files (*)') # if filename is empty if filename is '': return # open the file f = open(filename, 'w') # separator if sep == 'csv': ss = ',' else: ss = '\t' # write header f.writelines('Name' + ss + 'x_old' + ss + 'y_old' + ss + 'x_ref' + ss + 'y_ref' + ss + 'x_calc' + ss + 'y_calc' + '\n') # write the data out for it in range(self.datatable.rowCount()): for jt in range(7): if self.datatable.item(it, jt) is not None: savestring = self.datatable.item( it, jt).text().strip().rstrip().replace('\n', '').replace( '\r', '') f.writelines(savestring) # separator if not last if jt < 6: f.writelines(ss) f.writelines('\n') # flush and close f.flush() f.close() def test(self): print(self.calcmode) def help(self): msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle('Help') msgBox.setInformativeText( 'Help is implemented with tooltips, hover over the buttons in question\n' 'and you should receive some information.\n\n' 'Routines:\n' 'Nittler: (PhD Thesis Larry Nittler, Appendix F)\n' 'Linear regression to as many reference points that are given. Only \n' 'Rotation and shift are included in this method. No stretch of the data.\n' 'Make sure that the reference systems are in the same unit system!\n\n' 'Admon: (Admon et al. (2005) Microsc. Microanal. 11, 354–362)\n' 'Only three fiducial marks can be selected, however, stretch of the\n' 'coordinate system is also calculated. Ideal when switching between\n' 'different units from one coordinate system to the next.\n\n' 'Author: Reto Trappitsch\n' 'Version: ' + self.version + '\n' 'Date: ' + self.version_date + '\n\n') msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec() def calculate(self): # admon or nittler if self.calcmode == 'Nittler': self.calculate_nittler() else: self.calculate_admon() def calculate_admon(self): # stop editing self.datatable.setCurrentItem(None) # fake z coordinate zcoord = 1. # initialize data input array as nan tabold = np.full((self.datatable.rowCount(), 3), np.nan) tabref = np.full((self.datatable.rowCount(), 2), np.nan) for it in range(self.datatable.rowCount()): # append data if self.datatable.item(it, 1) is not None and self.datatable.item( it, 2) is not None: try: if self.datatable.item( it, 1).text() is not '' and self.datatable.item( it, 2).text() is not '': tabold[it][0] = float( self.datatable.item(it, 1).text()) tabold[it][1] = float( self.datatable.item(it, 2).text()) tabold[it][2] = zcoord except ValueError: QMessageBox.warning( self, 'Table error', 'There is an error in your data table. Please make sure ' 'all numbers are floats.') return except AttributeError: QMessageBox.warning( self, 'Table error', 'There is an error in the data table. Did you finish all ' 'editing?') # append reference if self.datatable.item(it, 3) is not None and self.datatable.item( it, 4) is not None: try: if self.datatable.item( it, 3).text() is not '' and self.datatable.item( it, 4).text() is not '': tabref[it][0] = float( self.datatable.item(it, 3).text()) tabref[it][1] = float( self.datatable.item(it, 4).text()) except ValueError: QMessageBox.warning( self, 'Table error', 'There is an error in your data table. Please fix.') return except AttributeError: QMessageBox.warning( self, 'Table error', 'There is an error in the data table. Did you finish all ' 'editing?') # make sure at least two reference points are given # now find crefold and crefnew for calculation of parameters crefold = [] crefnew = [] for it in range(len(tabold)): if not np.isnan(tabold[it][0]) and not np.isnan(tabref[it][0]): crefold.append([tabold[it][0], tabold[it][1], zcoord]) # artificially add a z coordinate crefnew.append([tabref[it][0], tabref[it][1], zcoord]) # artificially add a z coordinate if len(crefnew) < 3: QMessageBox.warning( self, 'Reference error', 'Need three reference points to transform into the ' 'new coordinates.') return if len(crefnew) > 3: QMessageBox.information( self, 'Too many reference points', 'Only the first three reference values are ' 'taken for the transformation.') # transform to np.arrays, only take the first three entries crefold = np.array(crefold[0:3]) crefnew = np.array(crefnew[0:3]) crefoldt = np.array(crefold).transpose() crefnewt = np.array(crefnew).transpose() tabnew = np.zeros((len(tabold), 2)) for it in range(len(tabold)): tmpnew = np.matmul(crefnewt, np.matmul(np.linalg.inv(crefoldt), tabold[it])) tabnew[it][0] = np.round(tmpnew[0], self.rounddig) tabnew[it][1] = np.round(tmpnew[1], self.rounddig) # write the calc and the new into the table for it in range(len(tabold)): self.datatable.setItem(it, 5, QTableWidgetItem(str(tabnew[it][0]))) self.datatable.setItem(it, 6, QTableWidgetItem(str(tabnew[it][1]))) # resize columns to contents self.datatable.resizeColumnsToContents() def calculate_nittler(self): # stop editing self.datatable.setCurrentItem(None) # initialize data input array as nan tabold = np.full((self.datatable.rowCount(), 2), np.nan) tabref = np.full((self.datatable.rowCount(), 2), np.nan) for it in range(self.datatable.rowCount()): # append data if self.datatable.item(it, 1) is not None and self.datatable.item( it, 2) is not None: try: if self.datatable.item( it, 1).text() is not '' and self.datatable.item( it, 2).text() is not '': tabold[it][0] = float( self.datatable.item(it, 1).text()) tabold[it][1] = float( self.datatable.item(it, 2).text()) except ValueError: QMessageBox.warning( self, 'Table error', 'There is an error in your data table. Please make sure all ' 'numbers are floats.') return except AttributeError: QMessageBox.warning( self, 'Table error', 'There is an error in the data table. Did you finish all ' 'editing?') # append reference if self.datatable.item(it, 3) is not None and self.datatable.item( it, 4) is not None: try: if self.datatable.item( it, 3).text() is not '' and self.datatable.item( it, 4).text() is not '': tabref[it][0] = float( self.datatable.item(it, 3).text()) tabref[it][1] = float( self.datatable.item(it, 4).text()) except ValueError: QMessageBox.warning( self, 'Table error', 'There is an error in your data table. Please fix.') return except AttributeError: QMessageBox.warning( self, 'Table error', 'There is an error in the data table. Did you finish all ' 'editing?') # make sure at least two reference points are given # now find crefold and crefnew for calculation of parameters crefold = [] crefnew = [] for it in range(len(tabold)): if not np.isnan(tabold[it][0]) and not np.isnan(tabref[it][0]): crefold.append([tabold[it][0], tabold[it][1]]) crefnew.append([tabref[it][0], tabref[it][1]]) if len(crefnew) < 2: QMessageBox.warning( self, 'Reference error', 'Need at least two reference points to transform into the ' 'new coordinates.') return # transform to np.arrays crefold = np.array(crefold) crefnew = np.array(crefnew) # now calculate what i need to calculate with all the reference values, all variables start with var vara = 0. varb = 0. varc = 0. vard = float(len(crefold)) vare = 0. varf = 0. varg = 0. varh = 0. # run the sums for it in range(len(crefold)): vara += (crefold[it][0]**2. + crefold[it][1]**2.) varb += crefold[it][0] varc += crefold[it][1] vare += (crefold[it][0] * crefnew[it][0] + crefold[it][1] * crefnew[it][1]) varf += (crefold[it][1] * crefnew[it][0] - crefold[it][0] * crefnew[it][1]) varg += crefnew[it][0] varh += crefnew[it][1] # calculate parameters params = (1. / (varb**2. + varc**2 - vara * vard)) * np.array([ -vard * vare + varb * varg + varc * varh, -vard * varf + varc * varg - varb * varh, varb * vare + varc * varf - vara * varg, varc * vare - varb * varf - vara * varh ]) tabnew = np.zeros((len(tabold), 2)) for it in range(len(tabnew)): if not np.isnan(tabold[it][0]): tabnew[it][0] = np.round( tabold[it][0] * params[0] + tabold[it][1] * params[1] + params[2], self.rounddig) tabnew[it][1] = np.round( -tabold[it][0] * params[1] + tabold[it][1] * params[0] + params[3], self.rounddig) # calculate the reference crefcalc = [] for it in range(len(crefold)): crefcalc.append([ crefold[it][0] * params[0] + crefold[it][1] * params[1] + params[2], -crefold[it][0] * params[1] + crefold[it][1] * params[0] + params[3] ]) # calculate shortest distance dsane = 0. for it in range(len(crefnew)): # add the delta between the points in the actual points dsane += np.sqrt((crefcalc[it][0] - crefnew[it][0])**2. + (crefcalc[it][1] - crefnew[it][1])**2.) # now divide by total number of points to get average deviation dsane /= len(crefnew) # set text in info label self.infolbl.setText('Average distance error: ' + str(np.round(dsane, self.rounddig))) # write the calc and the new into the table for it in range(len(tabold)): self.datatable.setItem(it, 5, QTableWidgetItem(str(tabnew[it][0]))) self.datatable.setItem(it, 6, QTableWidgetItem(str(tabnew[it][1]))) # resize columns to contents self.datatable.resizeColumnsToContents() def addrow(self): self.datatable.insertRow(self.datatable.rowCount()) # def keyPressEvent(self, event): # """ # Implement copy, paste # """ # if type(event) == QKeyEvent: # if event.key() == Qt.Key_Space: # print('spacer') # def copy(self): inds = [] for idx in self.datatable.selectedIndexes(): inds.append([idx.row(), idx.column()]) # now start string to copy str2cpy = '' try: oldrow = inds[0][0] except IndexError: # nothing selected, then just do nothing return for it in range(len(inds)): # easier handling row = inds[it][0] col = inds[it][1] datfield = self.datatable.item(row, col) # check if the first if it == 0: if datfield is None: str2cpy = '' else: str2cpy = datfield.text() else: # add separator if oldrow == row: str2cpy += '\t' else: str2cpy += '\n' # now add the entry if datfield is None: str2cpy += '' else: str2cpy += datfield.text() # set new row oldrow = row # now copy the string to the clipboard self.clipboard.clear() self.clipboard.setText(str2cpy) def paste(self): # get the current index try: tmp = self.datatable.selectedIndexes()[0] except IndexError: # nothing selected QMessageBox.warning(self, 'Selection error', 'Select a cell where to paste into') return currind = [tmp.row(), tmp.column()] # read in clipboard datain = self.clipboard.text().split('\n') # check for empty input if datain is '': QMessageBox.warning(self, 'Paste error', 'Nothing in clipboard to paste.') return data = [] for line in datain: data.append(line.replace('\r', '').split()) # check if outside of range in horizontal if currind[1] + len(data[0]) > 7: QMessageBox.warning( self, 'Paste error', 'Too many columns in clipboard to fit. Wrong selection where to ' 'paste into?') return # add rows in the end until we have enough to paste into while currind[0] + len(data) > self.datatable.rowCount(): self.datatable.insertRow(self.datatable.rowCount()) # now fill the cells with the pasted stuff for row in range(len(data)): for col in range(len(data[row])): self.datatable.setItem(row + currind[0], col + currind[1], QTableWidgetItem(data[row][col])) def delete(self): # get the current index inds = [] try: for idx in self.datatable.selectedIndexes(): inds.append([idx.row(), idx.column()]) except IndexError: # nothing selected return # selected indeces print(inds) # now fill the cells with the pasted stuff for row, col in inds: self.datatable.setItem(row, col, QTableWidgetItem('')) def cleartable(self): # clear the table msgbox = QMessageBox.question( self, 'Clear table?', 'Are you sure you want to clear the table?', QMessageBox.Yes, QMessageBox.No) if msgbox == QMessageBox.Yes: self.datatable.clearContents() self.datatable.setRowCount(23)
class DisplayLayout(QDialog): def __init__(self, main, object): QDialog.__init__(self) self.main = main self.tmp = main.tmpDirectory self.object = object self.folderpath = "" self.layoutList = [] self.closed = False self.setWindowTitle('Layout') self.setWindowFlags(Qt.Window) self.resize(650, 500) self.setMinimumSize(QSize(0, 500)) self.setMaximumSize(QSize(16777215, 500)) horizontalLayout = QHBoxLayout(self) formLayout = QFormLayout() formLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) formLayout.setFormAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop) addLabel = QLabel(self) addLabel.setMinimumSize(QSize(23, 23)) addLabel.setMaximumSize(QSize(23, 23)) addLabel.setPixmap(QPixmap(self.main.pluginDirectory+"/icons/addLayout.png")) removeLabel = QLabel(self) removeLabel.setMinimumSize(QSize(23, 23)) removeLabel.setMaximumSize(QSize(23, 23)) removeLabel.setPixmap(QPixmap(self.main.pluginDirectory+"/icons/removeLayout.png")) addLayout = QHBoxLayout() addLayout.setSizeConstraint(QLayout.SetFixedSize) addLayout.addWidget(addLabel) addLayout.addWidget(removeLabel) formLayout.setLayout(0, QFormLayout.LabelRole, addLayout) self.layoutFoldersList = QTableWidget(0, 1, self) self.layoutFoldersList.setMinimumSize(QSize(300, 400)) self.layoutFoldersList.setColumnWidth(0, 300) self.layoutFoldersList.setHorizontalHeaderLabels(["Layout-Ordner"]) self.layoutFoldersList.setEditTriggers(QAbstractItemView.NoEditTriggers) self.layoutFoldersList.setSelectionMode(QAbstractItemView.SingleSelection) self.layoutsList = QTableWidget(0, 1, self) self.layoutsList.setMinimumSize(QSize(300, 400)) self.layoutsList.setColumnWidth(0, 300) self.layoutsList.setHorizontalHeaderLabels(["Layouts"]) self.layoutsList.setSelectionMode(QAbstractItemView.SingleSelection) self.layoutsList.setEditTriggers(QAbstractItemView.NoEditTriggers) layoutLayout = QHBoxLayout() layoutLayout.setSizeConstraint(QLayout.SetMaximumSize) layoutLayout.addWidget(self.layoutFoldersList) layoutLayout.addWidget(self.layoutsList) formLayout.setLayout(1, QFormLayout.SpanningRole, layoutLayout) buttonBox = QDialogButtonBox(self) buttonBox.setStandardButtons(QDialogButtonBox.Close|QDialogButtonBox.Apply) formLayout.setWidget(2, QFormLayout.FieldRole, buttonBox) horizontalLayout.addLayout(formLayout) buttonBox.button(QDialogButtonBox.Apply).clicked.connect(self.showLayout) buttonBox.button(QDialogButtonBox.Close).clicked.connect(self.cancel) self.layoutFoldersList.itemClicked.connect(self.getLayouts) addLabel.mouseReleaseEvent = self.newFolder removeLabel.mouseReleaseEvent = self.delFolder self.layoutFoldersList.keyPressEvent = self.keyPress for layout in self.main.config.options('Layouts'): l = self.main.config.get('Layouts', layout) self.layoutList.append(layout) self.layoutFoldersList.setRowCount(self.layoutFoldersList.rowCount()+1) self.layoutFoldersList.setItem(self.layoutFoldersList.rowCount()-1, 0, QTableWidgetItem(l)) #self.exec_() self.show() def show(self): super(DisplayLayout, self).show() self.closed = False def closeEvent(self, evnt): super(DisplayLayout, self).closeEvent(evnt) self.closed = True def showLayout(self): QApplication.setOverrideCursor(Qt.WaitCursor) selected = self.layoutsList.selectedItems() if not len(self.folderpath) or not len(selected): return now = datetime.datetime.now() a = str(now.year) + str(now.strftime('%m')) + str(now.strftime('%d')) GeODin = win32com.client.Dispatch("GeODin.GeODinApplication") info = GeODin.LicenceInfo.split('\r\n') #dongle = [t for t in info if 'dongle' in t.lower()] #print info if not len(info) or not len(info): return #print "Licence Info: ", info licence = info[1].split(': ')[1] m = hashlib.md5.new() m.update(a+'-'+licence) new_hash = m.hexdigest() #layout = self.folderpath + '\\' + str(selected[0].text()) layout = self.folderpath + '\\' + selected[0].text() database = self.object.parent.parent invid = self.object.invid image = 41 #image = 12 Params = "[Params]\n" exe = "EXECUTE=ProducePortalImage\n" Layout = "LAYOUT=" pagenumber = "\nPageNumber=20\n" scale = "Scale=0\n" version = "VersionName=\n" ArcGeODin = "ArcGeODin=" dbName = "\n[Database]\n" name = "Name=" username = "******" password = "******" objects = "[Objects]\n" objectID = "ObjectID1=" Image = "\n[Image]\n" imageType = "ImageType=" resolution = "\nResolution=3000" params = Params + exe + Layout + layout + pagenumber + scale + version + ArcGeODin + new_hash + dbName + name + str(database) + username + password + objects + objectID + invid + Image + imageType + str(image) + resolution pic = GeODin.ProduceData(params) if GeODin.ExceptionValue != 0: print("Error ID: "+ str(GeODin.ExceptionValue)) print("Error Message: "+GeODin.ExceptionMsg.encode('utf-8')) f = open(self.tmp + "\\out.pdf", 'wb') f.write("<!DOCTYPE html><html><head><meta charset='utf-8'/></head><body>\r\n" + pic[0].replace("\r\n","</br>").encode('utf-8')+"\r\n</body></html>") f.close() GeODin = None self.layoutDialog = ImageLayout(self.tmp + "/out.pdf", selected[0].text()) def cancel(self): self.closed = True self.accept() #self.main = None #self.object = None #self.layoutFoldersList = None #self.accept() def newFolder(self, event): # get path for GeODin data path_data = str(self.main.config.get('Options', 'programdata')) # get layout directory directory = QFileDialog.getExistingDirectory(self, "Select Directory", path_data) #print type(directory) #print directory # directory = directory.encode('utf-8') # if layout directory has been specified if directory: i=0 # map over layout folders self.layoutFoldersList.setRowCount(self.layoutFoldersList.rowCount() + 1) self.layoutFoldersList.setItem(self.layoutFoldersList.rowCount()-1, 0, QTableWidgetItem(directory)) # write layout folder to config file while self.main.config.has_option('Layouts','L' + str(i)): i =1 self.main.config.set('Layouts', 'L'+str(i), directory) self.main.saveConfig() # append layouts to tableview self.layoutList.append('L' + str(i)) def delFolder(self, event): # delete layout folder from list selected = self.layoutFoldersList.selectedItems() if selected: for s in reversed(selected): pos = self.layoutFoldersList.row(s) self.main.config.remove_option('Layouts', self.layoutList[pos]) self.main.saveConfig() self.layoutList.pop(pos) self.layoutFoldersList.removeRow(pos) def reloadLayouts(self): selected = self.layoutFoldersList.selectedItems() if selected: self.getLayouts(selected[0]) def getLayouts(self, item): path = item.text() self.folderpath = path layouts = [ l for l in os.listdir(path) if os.path.isfile(os.path.join(path,l)) and l.lower().endswith(".glo")] self.layoutsList.clearContents() self.layoutsList.setRowCount(0) if layouts: for l in layouts: self.layoutsList.setRowCount(self.layoutsList.rowCount()+1) self.layoutsList.setItem(self.layoutsList.rowCount()-1, 0, QTableWidgetItem(l)) def keyPress(self, event): pass
class Labels(QWidget): """ Attributes ---------- chan_name : list of str list of all the labels (with the user-defined changes) """ def __init__(self, parent): super().__init__() self.parent = parent self.filename = None self.chan_name = None # None when dataset is not loaded self.create() def create(self): self.idx_load = QPushButton('Load') self.idx_load.clicked.connect(self.load_labels) self.idx_load.setToolTip('Load file with a list of channels (separated by , or ; or tabs or spaces).') self.idx_save = QPushButton('Save') self.idx_save.clicked.connect(self.save_labels) self.idx_save.setEnabled(False) # cancel is equal to setting labels to what they were self.idx_cancel = QPushButton('Cancel') self.idx_cancel.clicked.connect(self.update) self.idx_apply = QPushButton('Apply') self.idx_apply.clicked.connect(self.apply) self.idx_apply.setToolTip('Changes will take effect. This will reset the channel groups and traces.') layout_0 = QHBoxLayout() layout_0.addWidget(self.idx_load) layout_0.addWidget(self.idx_save) layout_1 = QHBoxLayout() layout_1.addWidget(self.idx_cancel) layout_1.addWidget(self.idx_apply) self.table = QTableWidget() self.table.horizontalHeader().setStretchLastSection(True) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setColumnCount(2) self.table.setHorizontalHeaderLabels(['Current Labels', 'New Labels']) self.table.cellChanged.connect(self.check_labels) layout = QVBoxLayout() layout.addLayout(layout_0) layout.addWidget(self.table) layout.addLayout(layout_1) self.setLayout(layout) self.setEnabled(False) def update(self, checked=False, labels=None, custom_labels=None): """Use this function when we make changes to the list of labels or when we load a new dataset. Parameters ---------- checked : bool argument from clicked.connect labels : list of str list of labels in the dataset (default) custom_labels : list of str list of labels from a file """ if labels is not None: self.setEnabled(True) self.chan_name = labels self.table.blockSignals(True) self.table.clearContents() self.table.setRowCount(len(self.chan_name)) for i, label in enumerate(self.chan_name): old_label = QTableWidgetItem(label) old_label.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) if custom_labels is not None and i < len(custom_labels) and custom_labels[i]: # it's not empty string or None label_txt = custom_labels[i] else: label_txt = label new_label = QTableWidgetItem(label_txt) self.table.setItem(i, 0, old_label) self.table.setItem(i, 1, new_label) self.table.blockSignals(False) def check_labels(self): # read new labels first labels = self._read_labels() # disable apply, if there are duplicates if len(labels) == len(set(labels)): self.idx_apply.setEnabled(True) else: self.idx_apply.setEnabled(False) # mark duplicates in red self.table.blockSignals(True) for i, label in enumerate(labels): if labels.count(label) > 1: self.table.item(i, 1).setBackground(QColor('red')) else: self.table.item(i, 1).setBackground(QColor('white')) self.table.blockSignals(False) def load_labels(self, checked=False, test_name=None): if self.filename is not None: filename = self.filename elif self.parent.info.filename is not None: filename = Path(self.parent.info.filename) else: filename = None if test_name: filename = test_name else: filename, _ = QFileDialog.getOpenFileName(self, 'Open Labels', str(filename.parent), 'Comma-separated values (*.csv);; Text file (*.txt);; All Files(*.*)') if filename == '': return self.filename = Path(filename) with self.filename.open() as f: text = f.read() labels = split(', |,|; |;|\t|\n| ', text) labels = [label.strip() for label in labels] self.update(custom_labels=labels) def save_labels(self): """Save labels modified by the user. TODO ---- Save labels modified by the user """ pass def apply(self): self.chan_name = self._read_labels() self.parent.info.dataset.header['chan_name'] = self.chan_name self.parent.channels.reset() self.parent.channels.update() self.parent.traces.reset() def reset(self): self.table.blockSignals(True) self.table.clearContents() self.table.blockSignals(False) self.setEnabled(False) def _read_labels(self): labels = [] for i in range(self.table.rowCount()): labels.append(self.table.item(i, 1).text()) return labels
class MyMainWindow(QWidget): type = False type_sig = pyqtSignal(bool) def __init__(self): super().__init__() self.row = 0 self.col = 10 self.initUI() self.link() self.js = '/home/pi/pyqt/mp3/js.mp3' self.hs = '/home/pi/pyqt/mp3/hs.mp3' self.tx = '/home/pi/pyqt/mp3/tx.mp3' def initUI(self): # self.setupUi(self) # self.player = QMediaPlayer() # self.player.setVolume(100) bgHbox = QHBoxLayout() bgrid = QGridLayout() bgrid.setSpacing(10) leftVbox = QVBoxLayout() idHbox = QHBoxLayout() idLabel = QLabel("学号:") self.idLabelval = QLabel("20151110048") idHbox.addWidget(idLabel) idHbox.addWidget(self.idLabelval) nameHbox = QHBoxLayout() nameLable = QLabel("姓名:") self.nameLableval = QLabel("三胖") nameHbox.addWidget(nameLable) nameHbox.addWidget(self.nameLableval) classHbox = QHBoxLayout() classLabel = QLabel("班级:") self.classLabelval = QLabel("物联网1502 ") classHbox.addWidget(classLabel) classHbox.addWidget(self.classLabelval) self.retbtn = QPushButton("退出") self.retbtn.clicked.connect(self.ret) # self.insertbtn = QPushButton("插入") # self.insertbtn.clicked.connect(self.insertClick) line = QFrame() line.setFrameShape(QFrame.VLine) line.setFrameShadow(QFrame.Sunken) rightVbox = QVBoxLayout() self.table = QTableWidget() self.table.setColumnCount(self.col) self.table.setRowCount(100) self.table.setHorizontalHeaderLabels( ['图书名', '图书ID', '归还时间', '', '', '', '', '', '', '']) for i in range(self.col): self.table.setColumnWidth(i, 150) rightVbox.addWidget(self.table) # self.printBrowser = QTextBrowser() # rightVbox.addWidget(self.printBrowser) leftVbox.addStretch(20) leftVbox.addLayout(idHbox) leftVbox.addStretch(1) leftVbox.addLayout(nameHbox) leftVbox.addStretch(1) leftVbox.addLayout(classHbox) leftVbox.addStretch(1) leftVbox.addWidget(self.retbtn) # leftVbox.addWidget(self.insertbtn) leftVbox.addStretch(20) bgHbox.addLayout(leftVbox) bgHbox.addWidget(line) bgHbox.addLayout(rightVbox) self.setLayout(bgHbox) self.setWindowTitle("Main") self.setGeometry(300, 300, 1000, 1000 * 0.618) self.setWindowIcon(QIcon('/home/enheng/Pictures/Icon/music.png')) self.center() def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) # def insertClick(self, item): # self.addItem(["这是书名", "这是ID"]) # 载入Main窗口 def ok(self, type, id): self.type = type self.type_sig.emit(type) if type: self.setWindowTitle("借阅信息") else: self.setWindowTitle("归还信息") self.player.setMedia(QUrl.fromLocalFile(self.tx)) self.player.play() self.idLabelval.setText(id) ret = self.dbcmd( "select Name, Class from stu where Id = '{0}'".format(id)) # print(ret) if len(ret) != 0: self.nameLableval.setText(ret[0][0]) self.classLabelval.setText(ret[0][1] + " ") self.show() # 连接数据库 def link(self): try: self.db = pymysql.connect('localhost', 'enheng', '123456', 'sorting', charset='utf8') except pymysql.err.Error: print("db Link error") self.close() else: self.cursor = self.db.cursor() self.c = comm(self.db, self.cursor) self.type_sig.connect(self.c.settype) self.c.book_sig.connect(self.addItem) self.c.start() # 数据库查询 def dbcmd(self, cmd): try: self.cursor.execute(cmd) self.db.commit() return self.cursor.fetchall() except: self.db.rollback() print("db Select error") # 添加数据项 def addItem(self, v): j = 0 for i in range(len(v)): item = QTableWidgetItem(v[i]) self.table.setItem(self.row, j, item) j += 1 item = QTableWidgetItem( time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))) self.table.setItem(self.row, j, item) self.row += 1 if self.type: self.player.setMedia(QUrl.fromLocalFile(self.js)) else: self.player.setMedia(QUrl.fromLocalFile(self.hs)) self.player.play() # 退出时 def ret(self): self.table.clearContents() self.row = 0 self.hide() def closeEvent(self, a0: QtGui.QCloseEvent): if hasattr(self, 'db'): self.c.quit() self.cursor.close() self.db.close()
class SettingsDialog(QDialog): """ The dialog allowing an user to configure the plugin. It has multiple tabs used to group the settings by category (general, network, etc.). """ def __init__(self, plugin): super(SettingsDialog, self).__init__() self._plugin = plugin # General setup of the dialog self._plugin.logger.debug("Showing settings dialog") self.setWindowTitle("Settings") icon_path = self._plugin.plugin_resource("settings.png") self.setWindowIcon(QIcon(icon_path)) self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint) window_widget = QWidget(self) window_layout = QVBoxLayout(window_widget) tabs = QTabWidget(window_widget) window_layout.addWidget(tabs) # "General Settings" tab tab = QWidget(tabs) layout = QFormLayout(tab) layout.setFormAlignment(Qt.AlignVCenter) tabs.addTab(tab, "General Settings") user_widget = QWidget(tab) user_layout = QHBoxLayout(user_widget) layout.addRow(user_widget) # User color self._color_button = QPushButton("") self._color_button.setFixedSize(50, 30) def color_button_activated(_): self._set_color(qt_color=QColorDialog.getColor().rgb()) self._color = self._plugin.config["user"]["color"] self._set_color(ida_color=self._color) self._color_button.clicked.connect(color_button_activated) user_layout.addWidget(self._color_button) # User name self._name_line_edit = QLineEdit() name = self._plugin.config["user"]["name"] self._name_line_edit.setText(name) user_layout.addWidget(self._name_line_edit) text = "Disable all user cursors" self._disable_all_cursors_checkbox = QCheckBox(text) layout.addRow(self._disable_all_cursors_checkbox) navbar_checked = not self._plugin.config["cursors"]["navbar"] funcs_checked = not self._plugin.config["cursors"]["funcs"] disasm_checked = not self._plugin.config["cursors"]["disasm"] all_checked = navbar_checked and funcs_checked and disasm_checked self._disable_all_cursors_checkbox.setChecked(all_checked) def state_changed(state): enabled = state == Qt.Unchecked self._disable_navbar_cursors_checkbox.setChecked(not enabled) self._disable_navbar_cursors_checkbox.setEnabled(enabled) self._disable_funcs_cursors_checkbox.setChecked(not enabled) self._disable_funcs_cursors_checkbox.setEnabled(enabled) self._disable_disasm_cursors_checkbox.setChecked(not enabled) self._disable_disasm_cursors_checkbox.setEnabled(enabled) self._disable_all_cursors_checkbox.stateChanged.connect(state_changed) style_sheet = """QCheckBox{ margin-left: 20px; }""" text = "Disable navigation bar user cursors" self._disable_navbar_cursors_checkbox = QCheckBox(text) layout.addRow(self._disable_navbar_cursors_checkbox) self._disable_navbar_cursors_checkbox.setChecked(navbar_checked) self._disable_navbar_cursors_checkbox.setEnabled(not all_checked) self._disable_navbar_cursors_checkbox.setStyleSheet(style_sheet) text = "Disable functions window user cursors" self._disable_funcs_cursors_checkbox = QCheckBox(text) layout.addRow(self._disable_funcs_cursors_checkbox) self._disable_funcs_cursors_checkbox.setChecked(funcs_checked) self._disable_funcs_cursors_checkbox.setEnabled(not all_checked) self._disable_funcs_cursors_checkbox.setStyleSheet(style_sheet) text = "Disable disassembly view user cursors" self._disable_disasm_cursors_checkbox = QCheckBox(text) layout.addRow(self._disable_disasm_cursors_checkbox) self._disable_disasm_cursors_checkbox.setChecked(disasm_checked) self._disable_disasm_cursors_checkbox.setEnabled(not all_checked) self._disable_disasm_cursors_checkbox.setStyleSheet(style_sheet) text = "Allow other users to send notifications" self._notifications_checkbox = QCheckBox(text) layout.addRow(self._notifications_checkbox) checked = self._plugin.config["user"]["notifications"] self._notifications_checkbox.setChecked(checked) # Log level debug_level_label = QLabel("Logging level: ") self._debug_level_combo_box = QComboBox() self._debug_level_combo_box.addItem("CRITICAL", logging.CRITICAL) self._debug_level_combo_box.addItem("ERROR", logging.ERROR) self._debug_level_combo_box.addItem("WARNING", logging.WARNING) self._debug_level_combo_box.addItem("INFO", logging.INFO) self._debug_level_combo_box.addItem("DEBUG", logging.DEBUG) self._debug_level_combo_box.addItem("TRACE", logging.TRACE) level = self._plugin.config["level"] index = self._debug_level_combo_box.findData(level) self._debug_level_combo_box.setCurrentIndex(index) layout.addRow(debug_level_label, self._debug_level_combo_box) # "Network Settings" tab tab = QWidget(tabs) layout = QVBoxLayout(tab) tab.setLayout(layout) tabs.addTab(tab, "Network Settings") top_widget = QWidget(tab) layout.addWidget(top_widget) top_layout = QHBoxLayout(top_widget) self._servers = list(self._plugin.config["servers"]) self._servers_table = QTableWidget(len(self._servers), 3, self) top_layout.addWidget(self._servers_table) for i, server in enumerate(self._servers): # Server host and port item = QTableWidgetItem("%s:%d" % (server["host"], server["port"])) item.setData(Qt.UserRole, server) item.setFlags(item.flags() & ~Qt.ItemIsEditable) # XXX - This prevented editing a server entry for your current # server because the row cannot be selected properly with # SingleSelection option selected #if self._plugin.network.server == server: # item.setFlags((item.flags() & ~Qt.ItemIsSelectable)) self._servers_table.setItem(i, 0, item) # Server has SSL enabled? ssl_checkbox = QTableWidgetItem() state = Qt.Unchecked if server["no_ssl"] else Qt.Checked ssl_checkbox.setCheckState(state) ssl_checkbox.setFlags((ssl_checkbox.flags() & ~Qt.ItemIsEditable)) ssl_checkbox.setFlags( (ssl_checkbox.flags() & ~Qt.ItemIsUserCheckable)) self._servers_table.setItem(i, 1, ssl_checkbox) # Auto-connect enabled? auto_checkbox = QTableWidgetItem() state = Qt.Unchecked if not server["auto_connect"] else Qt.Checked auto_checkbox.setCheckState(state) auto_checkbox.setFlags( (auto_checkbox.flags() & ~Qt.ItemIsEditable)) auto_checkbox.setFlags( (auto_checkbox.flags() & ~Qt.ItemIsUserCheckable)) self._servers_table.setItem(i, 2, auto_checkbox) self._servers_table.setHorizontalHeaderLabels( ("Servers", "SSL", "Auto")) horizontal_header = self._servers_table.horizontalHeader() horizontal_header.setSectionsClickable(False) horizontal_header.setSectionResizeMode(0, QHeaderView.Stretch) horizontal_header.setSectionResizeMode(1, QHeaderView.ResizeToContents) horizontal_header.setSectionResizeMode(2, QHeaderView.ResizeToContents) self._servers_table.verticalHeader().setVisible(False) self._servers_table.setSelectionBehavior(QTableWidget.SelectRows) self._servers_table.setSelectionMode(QTableWidget.SingleSelection) self._servers_table.itemClicked.connect(self._server_clicked) self._servers_table.itemDoubleClicked.connect( self._server_double_clicked) self._servers_table.setMaximumHeight(100) buttons_widget = QWidget(top_widget) buttons_layout = QVBoxLayout(buttons_widget) top_layout.addWidget(buttons_widget) # Add server button self._add_button = QPushButton("Add Server") self._add_button.clicked.connect(self._add_button_clicked) buttons_layout.addWidget(self._add_button) # Edit server button self._edit_button = QPushButton("Edit Server") self._edit_button.setEnabled(False) self._edit_button.clicked.connect(self._edit_button_clicked) buttons_layout.addWidget(self._edit_button) # Delete server button self._delete_button = QPushButton("Delete Server") self._delete_button.setEnabled(False) self._delete_button.clicked.connect(self._delete_button_clicked) buttons_layout.addWidget(self._delete_button) bottom_widget = QWidget(tab) bottom_layout = QFormLayout(bottom_widget) layout.addWidget(bottom_widget) # TCP Keep-Alive settings keep_cnt_label = QLabel("Keep-Alive Count: ") self._keep_cnt_spin_box = QSpinBox(bottom_widget) self._keep_cnt_spin_box.setRange(0, 86400) self._keep_cnt_spin_box.setValue(self._plugin.config["keep"]["cnt"]) self._keep_cnt_spin_box.setSuffix(" packets") bottom_layout.addRow(keep_cnt_label, self._keep_cnt_spin_box) keep_intvl_label = QLabel("Keep-Alive Interval: ") self._keep_intvl_spin_box = QSpinBox(bottom_widget) self._keep_intvl_spin_box.setRange(0, 86400) self._keep_intvl_spin_box.setValue( self._plugin.config["keep"]["intvl"]) self._keep_intvl_spin_box.setSuffix(" seconds") bottom_layout.addRow(keep_intvl_label, self._keep_intvl_spin_box) keep_idle_label = QLabel("Keep-Alive Idle: ") self._keep_idle_spin_box = QSpinBox(bottom_widget) self._keep_idle_spin_box.setRange(0, 86400) self._keep_idle_spin_box.setValue(self._plugin.config["keep"]["idle"]) self._keep_idle_spin_box.setSuffix(" seconds") bottom_layout.addRow(keep_idle_label, self._keep_idle_spin_box) # Buttons commons to all tabs actions_widget = QWidget(self) actions_layout = QHBoxLayout(actions_widget) # Cancel = do not save the changes and close the dialog def cancel(_): self.reject() cancel_button = QPushButton("Cancel") cancel_button.clicked.connect(cancel) actions_layout.addWidget(cancel_button) # Reset = reset all settings from all tabs to default values reset_button = QPushButton("Reset") reset_button.clicked.connect(self._reset) actions_layout.addWidget(reset_button) # Save = save the changes and close the dialog def save(_): self._commit() self.accept() save_button = QPushButton("Save") save_button.clicked.connect(save) actions_layout.addWidget(save_button) window_layout.addWidget(actions_widget) # Do not allow the user to resize the dialog self.setFixedSize(window_widget.sizeHint().width(), window_widget.sizeHint().height()) def _set_color(self, ida_color=None, qt_color=None): """Sets the color of the user color button.""" # IDA represents colors as 0xBBGGRR if ida_color is not None: r = ida_color & 255 g = (ida_color >> 8) & 255 b = (ida_color >> 16) & 255 # Qt represents colors as 0xRRGGBB if qt_color is not None: r = (qt_color >> 16) & 255 g = (qt_color >> 8) & 255 b = qt_color & 255 ida_color = r | g << 8 | b << 16 qt_color = r << 16 | g << 8 | b # Set the stylesheet of the button css = "QPushButton {background-color: #%06x; color: #%06x;}" self._color_button.setStyleSheet(css % (qt_color, qt_color)) self._color = ida_color def _server_clicked(self, _): self._edit_button.setEnabled(True) self._delete_button.setEnabled(True) def _server_double_clicked(self, _): item = self._servers_table.selectedItems()[0] server = item.data(Qt.UserRole) # If not the current server, connect to it if (not self._plugin.network.connected or self._plugin.network.server != server): self._plugin.network.stop_server() self._plugin.network.connect(server) self.accept() def _add_button_clicked(self, _): dialog = ServerInfoDialog(self._plugin, "Add server") dialog.accepted.connect(partial(self._add_dialog_accepted, dialog)) dialog.exec_() def _edit_button_clicked(self, _): selected = self._servers_table.selectedItems() if len(selected) == 0: self._plugin.logger.warning("No server selected") return item = selected[0] server = item.data(Qt.UserRole) dialog = ServerInfoDialog(self._plugin, "Edit server", server) dialog.accepted.connect(partial(self._edit_dialog_accepted, dialog)) dialog.exec_() def _delete_button_clicked(self, _): item = self._servers_table.selectedItems()[0] server = item.data(Qt.UserRole) self._servers.remove(server) self._plugin.save_config() self._servers_table.removeRow(item.row()) self.update() def _add_dialog_accepted(self, dialog): """Called when the dialog to add a server is accepted.""" server = dialog.get_result() self._servers.append(server) row_count = self._servers_table.rowCount() self._servers_table.insertRow(row_count) new_server = QTableWidgetItem("%s:%d" % (server["host"], server["port"])) new_server.setData(Qt.UserRole, server) new_server.setFlags(new_server.flags() & ~Qt.ItemIsEditable) self._servers_table.setItem(row_count, 0, new_server) new_checkbox = QTableWidgetItem() state = Qt.Unchecked if server["no_ssl"] else Qt.Checked new_checkbox.setCheckState(state) new_checkbox.setFlags((new_checkbox.flags() & ~Qt.ItemIsEditable)) new_checkbox.setFlags(new_checkbox.flags() & ~Qt.ItemIsUserCheckable) self._servers_table.setItem(row_count, 1, new_checkbox) self.update() def _edit_dialog_accepted(self, dialog): """Called when the dialog to edit a server is accepted.""" server = dialog.get_result() item = self._servers_table.selectedItems()[0] self._servers[item.row()] = server item.setText("%s:%d" % (server["host"], server["port"])) item.setData(Qt.UserRole, server) item.setFlags(item.flags() & ~Qt.ItemIsEditable) checkbox = self._servers_table.item(item.row(), 1) state = Qt.Unchecked if server["no_ssl"] else Qt.Checked checkbox.setCheckState(state) self.update() def _reset(self, _): """Resets all the form elements to their default value.""" config = self._plugin.default_config() self._name_line_edit.setText(config["user"]["name"]) self._set_color(ida_color=config["user"]["color"]) navbar_checked = not config["cursors"]["navbar"] funcs_checked = not config["cursors"]["funcs"] disasm_checked = not config["cursors"]["disasm"] all_checked = navbar_checked and funcs_checked and disasm_checked self._disable_all_cursors_checkbox.setChecked(all_checked) self._disable_navbar_cursors_checkbox.setChecked(navbar_checked) self._disable_navbar_cursors_checkbox.setEnabled(not all_checked) self._disable_funcs_cursors_checkbox.setChecked(funcs_checked) self._disable_funcs_cursors_checkbox.setEnabled(not all_checked) self._disable_disasm_cursors_checkbox.setChecked(disasm_checked) self._disable_disasm_cursors_checkbox.setEnabled(not all_checked) checked = config["user"]["notifications"] self._notifications_checkbox.setChecked(checked) index = self._debug_level_combo_box.findData(config["level"]) self._debug_level_combo_box.setCurrentIndex(index) del self._servers[:] self._servers_table.clearContents() self._keep_cnt_spin_box.setValue(config["keep"]["cnt"]) self._keep_intvl_spin_box.setValue(config["keep"]["intvl"]) self._keep_idle_spin_box.setValue(config["keep"]["idle"]) def _commit(self): """Commits all the changes made to the form elements.""" name = self._name_line_edit.text() if self._plugin.config["user"]["name"] != name: old_name = self._plugin.config["user"]["name"] self._plugin.network.send_packet(UpdateUserName(old_name, name)) self._plugin.config["user"]["name"] = name if self._plugin.config["user"]["color"] != self._color: name = self._plugin.config["user"]["name"] old_color = self._plugin.config["user"]["color"] packet = UpdateUserColor(name, old_color, self._color) self._plugin.network.send_packet(packet) self._plugin.config["user"]["color"] = self._color self._plugin.interface.widget.refresh() all_ = self._disable_all_cursors_checkbox.isChecked() checked = self._disable_navbar_cursors_checkbox.isChecked() self._plugin.config["cursors"]["navbar"] = not all_ and not checked checked = self._disable_funcs_cursors_checkbox.isChecked() self._plugin.config["cursors"]["funcs"] = not all_ and not checked checked = self._disable_disasm_cursors_checkbox.isChecked() self._plugin.config["cursors"]["disasm"] = not all_ and not checked checked = self._notifications_checkbox.isChecked() self._plugin.config["user"]["notifications"] = checked index = self._debug_level_combo_box.currentIndex() level = self._debug_level_combo_box.itemData(index) self._plugin.logger.setLevel(level) self._plugin.config["level"] = level self._plugin.config["servers"] = self._servers cnt = self._keep_cnt_spin_box.value() self._plugin.config["keep"]["cnt"] = cnt intvl = self._keep_intvl_spin_box.value() self._plugin.config["keep"]["intvl"] = intvl idle = self._keep_idle_spin_box.value() self._plugin.config["keep"]["idle"] = idle if self._plugin.network.client: self._plugin.network.client.set_keep_alive(cnt, intvl, idle) self._plugin.save_config()
class SecondTab(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): grid = QGridLayout() grid.addWidget(self.create_choice_groupbox(), 0, 0) grid.addWidget(self.create_view_groupbox(), 0, 1) self.setLayout(grid) # Groupbox: 주문결제내역 def create_choice_groupbox(self): gbox = QGroupBox() gbox.setTitle('주문결제내역') vbox = QVBoxLayout() # widget btn_update = QPushButton('새로고침', self) btn_update.clicked.connect(self.set_item_in_order_history_table) vbox.addWidget(btn_update) self.order_history_table = QTableWidget() self.create_order_history_table() vbox.addWidget(self.order_history_table) gbox.setLayout(vbox) return gbox # Groupbox: 조회 def create_view_groupbox(self): gbox = QGroupBox() gbox.setTitle('조회') vbox = QVBoxLayout() # widget self.order_details_table = QTableWidget() self.create_order_details_table() vbox.addWidget(self.order_details_table) gbox.setLayout(vbox) return gbox # Table Widget: 조회할 주문 선택 def create_order_history_table(self): self.order_history_table.setColumnCount(len(rec.summary_cols_list)) self.order_history_table.setHorizontalHeaderLabels( rec.summary_cols_list) self.order_history_table.setEditTriggers( QAbstractItemView.NoEditTriggers) self.order_history_table.setSelectionBehavior( QAbstractItemView.SelectRows) # Table Widget: 상세조회 def create_order_details_table(self): self.order_details_table.setColumnCount(len(rec.details_cols_list)) self.order_details_table.setHorizontalHeaderLabels( rec.details_cols_list) self.order_details_table.setRowCount(4) self.order_details_table.setEditTriggers( QAbstractItemView.NoEditTriggers) def set_item_in_order_history_table(self): self.order_history_table.clearContents() self.order_history_table.setRowCount(rec.summary_ws.max_row - 1) order_history_list = [] for row in rec.summary_ws.iter_rows(min_row=2, values_only=True): order_history_list.append(row) for i in range(rec.summary_ws.max_row - 1): self.order_history_table.setItem( i, 0, QTableWidgetItem(order_history_list[i][0])) self.order_history_table.setItem( i, 1, QTableWidgetItem(str(order_history_list[i][1]))) # Signal self.order_history_table.cellClicked.connect( self.set_item_in_order_details_table) @pyqtSlot(int, int) def set_item_in_order_details_table(self, row_int, col): self.order_details_table.clearContents() order_datetime_list = [] order_details_list = [] for row in rec.details_ws.iter_rows(min_row=2, values_only=True): order_datetime_list.append(row[0]) order_details_list.append(row) order_datetime = rec.summary_ws['A'][row_int + 1].value order_index = order_datetime_list.index(order_datetime) order_count = order_datetime_list.count(order_datetime) self.order_details_table.setRowCount(order_count) order_details_2_list = order_details_list[order_index:order_index + order_count] for i in range(order_count): self.order_details_table.setItem( i, 0, QTableWidgetItem(order_details_2_list[i][0])) self.order_details_table.setItem( i, 1, QTableWidgetItem(order_details_2_list[i][1])) self.order_details_table.setItem( i, 2, QTableWidgetItem(str(order_details_2_list[i][2]))) self.order_details_table.setItem( i, 3, QTableWidgetItem(str(order_details_2_list[i][3]))) self.order_details_table.setItem( i, 4, QTableWidgetItem(str(order_details_2_list[i][4]))) self.order_details_table.setItem( i, 5, QTableWidgetItem(order_details_2_list[i][5]))
class Viewer(QMainWindow): """The main window for the application.""" def __init__(self, stats, mode, difficulties, theme): """Initializes basic information about the Viewer class.""" super().__init__() ### Initialize parameters passed from smtracker.py self.stats = stats # XML tree self.mode = mode # Gamemode self.difficulties = difficulties # Tracked difficulties ### Initialize interface options self.icons_enabled = True # Icons ### Create an empty table if self.stats is not None: song_count = len(self.stats.find("SongScores")) self.table = QTableWidget(song_count, len(self.difficulties) + 2) else: self.table = QTableWidget(0, len(self.difficulties) + 2) # Set some basic table attributes self.table.setIconSize(QSize(32, 32)) self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table.setSelectionMode(QAbstractItemView.NoSelection) table_header = ["Group", "Title"] table_header.extend(self.difficulties) # Sets the header cells for head in table_header: where = table_header.index(head) headeritem = QTableWidgetItem() headeritem.setText(head) self.table.setHorizontalHeaderItem(where, headeritem) self.theme = theme self.init_ui() def init_table(self): """Generates a table with the song scores.""" # Prepare table for inserting items self.table.clearContents() self.table.setSortingEnabled(False) # Current table row current_row = 0 for song in self.stats.find("SongScores"): # Current table row current_column = 0 # Get the song's group and title # location[0] should always be "Songs" location = song.attrib['Dir'].split('/') # Create group cell group = QTableWidgetItem(location[1]) self.table.setItem(current_row, current_column, group) current_column = current_column + 1 # Create title cell title = QTableWidgetItem(location[2]) self.table.setItem(current_row, current_column, title) current_column = current_column + 1 # step_counter will be used for traversing the scores in a song step_counter = 0 for diff in self.difficulties: try: if (song[step_counter].attrib['Difficulty'] == diff and song[step_counter].attrib['StepsType'] == self.mode): try: grade = smformat.highscore_grade(song[step_counter], self.theme) percent = float(parse.highscore_stat(song[step_counter], "PercentDP")) * 100 if self.theme == "sm5" and self.icons_enabled is True: cell = QTableWidgetItem('{:.2f}%'.format(percent)) cell.setIcon(QIcon(smtracker.__path__[0] + '/images/' + grade + '.png')) else: cell = QTableWidgetItem('{} ({:.2f}%)'.format(grade, percent)) # Get the timings for our song timings = parse.highscore_timings(song[step_counter]) # TODO: Figure out if there's a cleaner way of # doing this tooltip = """Marvelous: {} Perfect: {} Great: {} Good: {} Boo: {} Miss: {} ----- Modifiers: {} ----- SN2 Score: {} DDRA Score: {} IIDX EX Score: {}""".format(timings['W1'], timings['W2'], timings['W3'], timings['W4'], timings['W5'], timings['Miss'], parse.highscore_stat(song[step_counter], "Modifiers"), parse.calculate_score_supernova2(song[step_counter]), parse.calculate_score_ddra(song[step_counter]), parse.calculate_score_iidx(song[step_counter])) cell.setToolTip(tooltip) self.table.setItem(current_row, current_column, cell) # This exception is reached if a Song was played, but # has no score (AutoPlay, PlayerAutoPlay) except AttributeError: cell = QTableWidgetItem() self.table.setItem(current_row, current_column, cell) step_counter = step_counter + 1 # If there are no scores for the current difficulty, # add an empty cell instead else: cell = QTableWidgetItem() self.table.setItem(current_row, current_column, cell) # This exception is reached if we already reached the last # score on a song (using step_counter) except IndexError: cell = QTableWidgetItem() self.table.setItem(current_row, current_column, cell) current_column = current_column + 1 current_row = current_row + 1 # Final table adjustments self.table.resizeColumnsToContents() self.table.setSortingEnabled(True) self.table.sortByColumn(0, Qt.AscendingOrder) def combobox_activated(self, combobox): """Sets the current game mode and regenerates the table.""" self.mode = combobox.currentText() self.init_table() def themebox_activated(self, combobox): """Sets the current grading system and regenerates the table.""" self.theme = combobox.currentText() self.init_table() def about_box(self): """Shows an about box with information about smtracker.""" text = ("<p>{desc} (version {vers})</p>" "<p>Released under the terms of the <a href=\"http://www.gnu.org" "/licenses/gpl-3.0.html\">GNU General Public License" ", version 3 or later</a></p>" "<p>Icons provided by <a href=\"http://stepmania.com\">" "StepMania</a> under the <a href=\"https://github.com/stepmania" "/stepmania/blob/master/Docs/Licenses.txt\">MIT license</a></p>" "<p><a href=\"{url}\">{url}</a></p>").format( desc=smtracker.__description__, vers=smtracker.__version__, url=smtracker.__url__) QMessageBox.information(self, "About smtracker", text) def export_html(self): """Saves an HTML report using QFileDialog to set a location.""" filetuple = QFileDialog.getSaveFileName(self, "Save HTML report as", None, "HTML file (*.html)") if filetuple[0]: if filetuple[0].endswith(".html"): filename = filetuple[0] else: filename = filetuple[0] + ".html" html.save(self.stats, self.mode, self.difficulties, self.theme, filename) def set_statusbar(self): """Resets the application statusbar.""" displayname = parse.get_profile_name(self.stats) lastplayed = parse.get_last_played(self.stats) status = 'Profile: {} // Last played: {}'.format(displayname, lastplayed) self.setStatusTip(status) def set_stats(self, stats): """Sets a new Stats.xml file and regenerates the UI.""" self.stats = stats self.table.setRowCount(len(self.stats.find("SongScores"))) self.init_table() self.set_statusbar() def open_file(self): """Opens a QFileDialog to set a new Stats.xml file.""" filetuple = QFileDialog.getOpenFileName(self, "Select Stats.xml file " "to open", None, "StepMania stats " "files (*.xml)") if filetuple[0]: tempstats = etree.parse(filetuple[0]).getroot() if tempstats.find("SongScores") is None: QMessageBox.critical(self, "Error parsing file", "The selected " "file is not a valid StepMania Stats.xml " "file.") else: self.set_stats(tempstats) def toggle_icons(self, state): """Sets icons_enabled and regenerates the table.""" self.icons_enabled = state self.init_table() def init_menubar(self): """Generates the main window menu bar.""" # Creates the actions for the main menu ### 'File' menu exit_action = QAction('E&xit', self) exit_action.setShortcut('Ctrl+Q') exit_action.setStatusTip('Exit smtracker') exit_action.triggered.connect(qApp.exit) export_action = QAction('&Export...', self) export_action.setShortcut('Ctrl+E') export_action.setStatusTip('Export table as HTML file') export_action.triggered.connect(self.export_html) open_action = QAction('&Open...', self) open_action.setShortcut('Ctrl+O') open_action.setStatusTip('Open a Stats.xml file') open_action.triggered.connect(self.open_file) ### 'Options' menu icons_action = QAction('Enable &icons', self) icons_action.setCheckable(True) icons_action.setChecked(self.icons_enabled) icons_action.triggered.connect(lambda: self.toggle_icons(icons_action.isChecked())) ### 'About' menu about_action = QAction('&About smtracker...', self) about_action.triggered.connect(self.about_box) qt_action = QAction('About &Qt...', self) qt_action.triggered.connect(QApplication.aboutQt) # Creates the menu bar and starts adding items to it menubar = self.menuBar() file_menu = menubar.addMenu('&File') file_menu.addAction(open_action) # Create the profile submenu and add the machine profile item profile_menu = file_menu.addMenu('Open &profile') mp_action = profile_menu.addAction('Machine Profile') # Define the location for profiles profile_folder, mp_folder = parse.get_profile_location() # Check if the machine profile exists if os.path.isfile(mp_folder + "Stats.xml") is True: no_mp = False mp_action.setStatusTip('Open this machine\'s profile') machine_profile = etree.parse(mp_folder + "Stats.xml").getroot() mp_action.triggered.connect(lambda: self.set_stats(machine_profile)) else: no_mp = True mp_action.setEnabled(False) # Check if there's any local profiles if os.path.isdir(profile_folder) is True: no_lp = False profile_menu.addSeparator() for profile in os.listdir(profile_folder): tempstats = etree.parse(profile_folder + profile + "/Stats.xml").getroot() tempname = parse.get_profile_name(tempstats) action = profile_menu.addAction(tempname) function = functools.partial(self.set_stats, tempstats) action.triggered.connect(function) else: no_lp = True # If there are no profiles at all, disable profile menu if no_mp is True and no_lp is True: profile_menu.setEnabled(False) # Add the rest of the actions to the menubar file_menu.addAction(export_action) file_menu.addAction(exit_action) options_menu = menubar.addMenu('&Options') options_menu.addAction(icons_action) about_menu = menubar.addMenu('&About') about_menu.addAction(about_action) about_menu.addAction(qt_action) def init_ui(self): """Initializes the user interface.""" modes = ("dance-single", "dance-double", "pump-single", "pump-double", "pump-halfdouble", "bm-single7", "bm-double7") themes = ("sm5", "itg", "supernova2", "ddra", "iidx") # Combobox for game modes combobox = QComboBox() combobox.addItems(modes) combobox.setCurrentText(self.mode) combolabel = QLabel("Game mode:") combobox.activated.connect(lambda: self.combobox_activated(combobox)) themebox = QComboBox() themebox.addItems(themes) themebox.setCurrentText(self.theme) themelabel = QLabel("Grading system:") themebox.activated.connect(lambda: self.themebox_activated(themebox)) self.init_menubar() if self.stats is not None: self.init_table() hbox = QHBoxLayout() hbox.addWidget(combolabel) hbox.addWidget(combobox, 1) hbox.addWidget(themelabel) hbox.addWidget(themebox, 1) vbox = QVBoxLayout() vbox.addLayout(hbox) vbox.addWidget(self.table) container = QWidget() container.setLayout(vbox) self.setCentralWidget(container) self.statusBar() if self.stats is not None: self.set_statusbar() else: self.setStatusTip("No Stats.xml file loaded") self.setWindowTitle('smtracker - StepMania Score Tracker') self.resize(1200, 700) self.show()
class MetadataWidget(QWidget): def __init__(self, mainWindow): # exécuter le constructeur de la classe de base : QWidget.__init__(self, mainWindow) '''Le constructeur de la classe MetadataWidget reçoit une référence sur l'application principale, affectée à l'attribut 'mw'. Cette référence est utile pour accéder aux différents onglets de l'appli- cation et les données associées (listes, dictionnaires...).''' self.mw = mainWindow # Le tableau des noms de fichiers et des paramètres usinages déduits # des noms : self.table = QTableWidget(self) self.__listMateriaux = [] # materiaux trouvés dans les noms fichiers # Le bouton pour lancer le scan du répertoire choisi: self.btn_scanFiles = QPushButton("Scan Fichiers", self) # Les widgets pour choisir et afficher le répertoire à scanner : self.labelUsinage = QLabel("Dossier usinage", self) self.dossierUsinage = QLineEdit(self.mw.usinage_dir, self) self.choisirDossierU = QPushButton("...", self) # La liste des fichiers *.txt de perçage/tournage trouvés dans le # répertoire renvoyé par 'dossierUsin' : self.listeFichiers = [] # connecter le clic des widgets aux méthodes de la classe : self.ConnectWidgetsToMethods() @property def listMateriaux(self) : return self.__listMateriaux.copy() def set_listMateriaux(self,new_list) : self.__listMateriaux = new_list @property def dossierUsin(self): '''Le répertoire dans lequel sont cherchés les fichiers de mesure *.txt''' return self.dossierUsinage.text() @dossierUsin.setter def dossierUsin(self, dir_name): self.dossierUsinage.setText(dir_name) def ChoixDossier(self, currDir, operation): '''Lance un navigateur pour choisir l\'emplacement du dossier contenant les fichiers d'acquisition *.txt.''' mess = 'Choix du dossier <usinage> ' + operation dir_name = QFileDialog.getExistingDirectory(None, mess, currDir) if dir_name != '' : # un répertoire valide a été choisi : self.dossierUsin = dir_name # MAJ du label self.ClearTable() # effacer le tableau def ListerTxt(self, dossierU): '''Affecte à l'attribut 'listeFichiers' la liste triée des fichiers *.txt contenus dans le répertoire dossierU passé en argument.''' #################################################################### ######## <Méthode ListerTxt à écrire> ############################## #################################################################### #################################################################### def ResizeTableColums(self): '''Met à jour la largeur des colonnes du tableau des fichiers en fonction des contenus des colonnes.''' for c in range(self.table.columnCount()): self.table.resizeColumnToContents(c) def ClearTable(self): '''Efface les données du tableau des fichiers.''' self.table.clearContents() def ListerFichiers(self): '''Scanne le répertoire choisi pour trouver les fichiers *.txt, efface le tableau et le remplit avec les nouvelles informations obtenues avec les noms des fichiers.''' self.ClearTable() self.ListerTxt(self.dossierUsin) self.RemplirTable() self.ResizeTableColums() def ConnectWidgetsToMethods(self): '''Connecte les actions des widgets (QPushButton, QTableWidget...) aux méthodes appropriées.''' mess = 'Liste les fichiers *.txt de perçage' mess += 'contenus dans le dossier choisi.' self.btn_scanFiles.setToolTip(mess) self.btn_scanFiles.clicked.connect(self.ListerFichiers) mess = 'Lance un navigateur pour choisir l\'emplacement du dossier' mess += ' de travail.' self.choisirDossierU.setToolTip(mess) self.choisirDossierU.clicked.connect(self.ChoixDossier) self.table.setSortingEnabled(True)
class TournamentOrganizerWidget(QWidget): def __init__(self, parent): super(TournamentOrganizerWidget, self).__init__(parent) self.parent = parent # Default Players (for quick testing) player_names = [ 'Frodo', 'Sam', 'Merry', 'Pippin', 'Gandalf', 'Aragorn', 'Legolas', 'Gimli', 'Boromir' ] # for name in player_names: # to.add_player(name, None) self.sort_order = 'by_name' view.notifier.observers.append(self) self.header_label = QLabel('Players') self.header_widget = QWidget(self) header_layout = QBoxLayout(QBoxLayout.LeftToRight) header_layout.addWidget(self.header_label) self.header_widget.setLayout(header_layout) self.sort_by_name_btn = QPushButton('Sort by Name', self) self.sort_by_name_btn.clicked.connect(self.sort_by_name) self.sort_by_rank_btn = QPushButton('Sort by Rank', self) self.sort_by_rank_btn.clicked.connect(self.sort_by_rank) self.sort_btns_widget = QWidget(self) sort_btns_layout = QBoxLayout(QBoxLayout.LeftToRight) sort_btns_layout.addWidget(self.sort_by_name_btn) sort_btns_layout.addSpacing(10) sort_btns_layout.addWidget(self.sort_by_rank_btn) self.sort_btns_widget.setLayout(sort_btns_layout) self.player_list = QTableWidget(style.style_loader.TABLE_INITIAL_LENGTH, 2, self) self.player_list.setHorizontalHeaderLabels(['Name', 'Record']) self.player_list.setFixedHeight(300) self.player_list.setFixedWidth(400) self.player_list.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.player_list.verticalHeader().setSectionResizeMode(QHeaderView.Fixed) self.player_list.horizontalHeader().setVisible(True) self.player_list_widget = QWidget(self) player_list_layout = QBoxLayout(QBoxLayout.LeftToRight) player_list_layout.addWidget(self.player_list) self.player_list_widget.setLayout(player_list_layout) self.add_player_btn = QPushButton('Add Player', self) self.add_player_btn.clicked.connect(self.parent.show_add_player_widget) self.remove_player_btn = QPushButton('Remove Player', self) self.remove_player_btn.clicked.connect(self.parent.show_remove_player_widget) self.player_btns_widget = QWidget(self) player_btn_layout = QBoxLayout(QBoxLayout.LeftToRight) player_btn_layout.addWidget(self.add_player_btn) player_btn_layout.addSpacing(10) player_btn_layout.addWidget(self.remove_player_btn) self.player_btns_widget.setLayout(player_btn_layout) self.error = None layout = QFormLayout() layout.addRow(self.header_widget) layout.addRow(self.sort_btns_widget) layout.addRow(self.player_list_widget) layout.addRow(self.player_btns_widget) self.setLayout(layout) self.update() def update(self): self.player_list.clearContents() players = [to.players[player] for player in to.sorted_players(self.sort_order)] index = 0 for player in players: if index == self.player_list.rowCount(): self.player_list.insertRow(index) name_item = QTableWidgetItem(player.name) name_item.setFlags(name_item.flags() & ~Qt.ItemIsEditable) self.player_list.setItem(index, 0, name_item) record_item = QTableWidgetItem(player.record_str()) record_item.setFlags(record_item.flags() & ~Qt.ItemIsEditable) self.player_list.setItem(index, 1, record_item) index += 1 self.player_list.show() def sort_by_name(self): self.sort_order = 'by_name' self.update() def sort_by_rank(self): self.sort_order = 'by_rank' self.update() def player_added(self, player, user): try: to.add_player(player, user) except TournamentException as ex: self.error = ErrorMessage(str(ex), '') self.error.setStyleSheet(style.style_loader.stylesheet) self.error.show() self.update() def player_removed(self, player): try: to.remove_player(player) except TournamentException as ex: self.error = ErrorMessage(str(ex), '') self.error.setStyleSheet(style.style_loader.stylesheet) self.error.show() self.update() def report_result(self, player, record, win_or_draw): pass def result_reported(self): self.update() def pairings_created(self): self.update() def reset(self): self.update()
class HyperLprWindow(QMainWindow): start_init_signal = pyqtSignal() def __init__(self): super().__init__() self.initUI() def initUI(self): self.statusBar().showMessage('Ready') self.left_action = QAction('上一个', self) self.left_action.setShortcut(QKeySequence.MoveToPreviousChar) self.left_action.triggered.connect(self.analyze_last_one_image) self.right_action = QAction('下一个', self) self.right_action.setShortcut(QKeySequence.MoveToNextChar) self.right_action.triggered.connect(self.analyze_next_one_image) self.rename_image_action = QAction('保存e2e文件名', self) self.rename_image_action.setShortcut(QKeySequence.MoveToPreviousLine) self.rename_image_action.triggered.connect(self.rename_current_image_with_info) self.statusBar() menubar = self.menuBar() fileMenu = menubar.addMenu('&Function') fileMenu.addAction(self.left_action) fileMenu.addAction(self.right_action) fileMenu.addAction(self.rename_image_action) self.image_window_view = HyperLprImageView() table_widget_header_labels = [ "文件名", "分割识别", "置信度", "颜色", "E2E识别", "E2E置信度"] self.hyperlpr_tableview = QTableWidget( 0, len(table_widget_header_labels)) self.hyperlpr_tableview.setHorizontalHeaderLabels( table_widget_header_labels) self.hyperlpr_tableview.setSelectionBehavior( QAbstractItemView.SelectItems) self.hyperlpr_tableview.setSelectionMode( QAbstractItemView.SingleSelection) self.hyperlpr_tableview.setEditTriggers( QAbstractItemView.NoEditTriggers) self.hyperlpr_tableview.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) self.hyperlpr_tableview.setEditTriggers( QAbstractItemView.NoEditTriggers) self.hyperlpr_tableview.cellClicked.connect( self.recognize_one_license_plate) self.left_button = QPushButton("<") self.left_button.setFixedWidth(60) self.right_button = QPushButton(">") self.right_button.setFixedWidth(60) self.left_button.setEnabled(False) self.right_button.setEnabled(False) self.left_button.clicked.connect(self.analyze_last_one_image) self.right_button.clicked.connect(self.analyze_next_one_image) left_right_layout = QHBoxLayout() left_right_layout.addStretch() left_right_layout.addWidget(self.left_button) left_right_layout.addStretch() left_right_layout.addWidget(self.right_button) left_right_layout.addStretch() self.location_label = QLabel("车牌目录", self) self.location_text = QLineEdit(self) self.location_text.setEnabled(False) #self.location_text.setFixedWidth(300) self.location_button = QPushButton("...") self.location_button.clicked.connect(self.select_new_dir) self.location_layout = QHBoxLayout() self.location_layout.addWidget(self.location_label) self.location_layout.addWidget(self.location_text) self.location_layout.addWidget(self.location_button) self.location_layout.addStretch() self.check_box = QCheckBox("与文件名比较车牌") self.check_box.setChecked(True) self.update_file_path_button = QPushButton('批量识别') self.update_file_path_button.clicked.connect( self.batch_recognize_all_images) self.update_file_path_layout = QHBoxLayout() self.update_file_path_layout.addWidget(self.check_box) self.update_file_path_layout.addWidget(self.update_file_path_button) self.update_file_path_layout.addStretch() self.save_as_e2e_filename_button = QPushButton("保存e2e文件名") self.save_as_e2e_filename_button.setEnabled(False) self.save_as_e2e_filename_button.clicked.connect(self.rename_current_image_with_info) self.save_layout = QHBoxLayout() self.save_layout.addWidget(self.save_as_e2e_filename_button) self.save_layout.addStretch() self.top_layout = QVBoxLayout() self.top_layout.addLayout(left_right_layout) self.top_layout.addLayout(self.location_layout) self.top_layout.addLayout(self.update_file_path_layout) self.top_layout.addLayout(self.save_layout) function_groupbox = QGroupBox("功能区") function_groupbox.setLayout(self.top_layout) license_plate_image_label = QLabel("车牌图") self.license_plate_widget = QLabel("") block_image_label = QLabel("分割图") self.block_plate_widget = QLabel("") filename_label = QLabel("文件名:") self.filename_edit = QLineEdit() segmentation_recognition_label = QLabel("分割识别:") self.segmentation_recognition_edit = QLineEdit() self.segmentation_recognition_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.segmentation_recognition_edit.setStyleSheet("color:red") confidence_label = QLabel("分割识别\n置信度") self.confidence_edit = QLineEdit() #self.confidence_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.confidence_edit.setStyleSheet("color:red") plate_color_label = QLabel("车牌颜色") self.plate_color_edit = QLineEdit() self.plate_color_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.plate_color_edit.setStyleSheet("color:red") e2e_recognization_label = QLabel("e2e识别:") self.e2e_recognization_edit = QLineEdit() self.e2e_recognization_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.e2e_recognization_edit.setStyleSheet("color:red") e2e_confidence_label = QLabel("e2e置信度") self.e2e_confidence_edit = QLineEdit() #self.e2e_confidence_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.e2e_confidence_edit.setStyleSheet("color:red") info_gridlayout = QGridLayout() line_index = 0 info_gridlayout.addWidget(filename_label, line_index, 0) info_gridlayout.addWidget(self.filename_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget(license_plate_image_label, line_index, 0) info_gridlayout.addWidget(self.license_plate_widget, line_index, 1) line_index += 1 info_gridlayout.addWidget(e2e_recognization_label, line_index, 0) info_gridlayout.addWidget(self.e2e_recognization_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget( segmentation_recognition_label, line_index, 0) info_gridlayout.addWidget( self.segmentation_recognition_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget(plate_color_label, line_index, 0) info_gridlayout.addWidget(self.plate_color_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget(block_image_label, line_index, 0) info_gridlayout.addWidget(self.block_plate_widget, line_index, 1) line_index += 1 info_gridlayout.addWidget(confidence_label, line_index, 0) info_gridlayout.addWidget(self.confidence_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget(e2e_confidence_label, line_index, 0) info_gridlayout.addWidget(self.e2e_confidence_edit, line_index, 1) info_widget = QGroupBox("分割识别&e2e") info_widget.setLayout(info_gridlayout) right_splitter = QSplitter(Qt.Vertical) right_splitter.addWidget(self.hyperlpr_tableview) right_splitter.addWidget(function_groupbox) right_splitter.addWidget(info_widget) right_splitter.setStretchFactor(0, 2) right_splitter.setStretchFactor(2, 1) main_splitter = QSplitter(Qt.Horizontal) main_splitter.addWidget(self.image_window_view) main_splitter.addWidget(right_splitter) main_splitter.setStretchFactor(0, 1) self.image_filename_list = [] self.hyperlpr_dir_path = "" self.segmentation_recognition_correct_number = 0 self.color_correct_number = 0 self.e2e_recognization_correct_number = 0 self.current_row = 0 self.batch_recognization_thread = LicenseRecognizationThread() self.batch_recognization_thread.recognization_done_signal.connect( self.recognization_done_slot) self.batch_recognization_thread.start() self.start_init_signal.connect(self.read_path_and_show_one_image) self.setCentralWidget(main_splitter) self.setWindowTitle("HyperLPR车牌识别软件v1.0") self.start_init_signal.emit() def read_path_and_show_one_image(self): hyperlpr_dir_info_filepath = QDir.homePath() + "/hyperlpr_dir_file" if os.path.exists(hyperlpr_dir_info_filepath): with open(hyperlpr_dir_info_filepath, 'r') as f: self.hyperlpr_dir_path = f.read() if len(self.hyperlpr_dir_path) > 0: self.reset_info_gui() if len(self.image_filename_list) > 0: self.recognize_and_show_one_image(self.image_filename_list[0], 0) def select_new_dir(self): self.hyperlpr_dir_path = QFileDialog.getExistingDirectory( self, "读取文件夹", QDir.currentPath()) if len(self.hyperlpr_dir_path) > 0: hyperlpr_dir_info_filepath = QDir.homePath() + "/hyperlpr_dir_file" with open(hyperlpr_dir_info_filepath, 'w') as f: f.write(self.hyperlpr_dir_path) self.reset_info_gui() def rename_current_image_with_info(self): if len(self.hyperlpr_dir_path) > 0: target_dir_path = self.hyperlpr_dir_path + "/result" if not os.path.exists(target_dir_path): os.makedirs(target_dir_path) if len(self.plate_color_edit.text())>0 and len(self.e2e_recognization_edit.text())>0: orign_path = os.path.join(self.hyperlpr_dir_path, self.filename_edit.text()) target_path = os.path.join(target_dir_path,self.plate_color_edit.text()+"-"+self.e2e_recognization_edit.text()+".jpg") shutil.copyfile(orign_path, target_path) def reset_info_gui(self): self.location_text.setText(self.hyperlpr_dir_path) self.scan_files_with_new_dir(self.hyperlpr_dir_path) self.fill_table_with_new_info() def scan_files_with_new_dir(self, path): name_list = os.listdir(path) # 列出文件夹下所有的目录与文件 self.image_filename_list.clear() for i in range(0, len(name_list)): if name_list[i].endswith( ".jpg") or name_list[i].endswith(".png"): self.image_filename_list.append(name_list[i]) def fill_table_with_new_info(self): self.hyperlpr_tableview.clearContents() row_count = self.hyperlpr_tableview.rowCount() for i in range(row_count, -1, -1): self.hyperlpr_tableview.removeRow(i) for i in range(0, len(self.image_filename_list)): row = self.hyperlpr_tableview.rowCount() self.hyperlpr_tableview.insertRow(row) item0 = QTableWidgetItem() item0.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 0, item0) self.hyperlpr_tableview.item( row, 0).setText( self.image_filename_list[i]) item1 = QTableWidgetItem() item1.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 1, item1) item2 = QTableWidgetItem() item2.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 2, item2) item3 = QTableWidgetItem() item3.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 3, item3) item4 = QTableWidgetItem() item4.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 4, item4) item5 = QTableWidgetItem() item5.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 5, item5) if len(self.image_filename_list) > 0: self.left_button.setEnabled(True) self.right_button.setEnabled(True) self.save_as_e2e_filename_button.setEnabled(True) def analyze_last_one_image(self): if self.current_row > 0: self.recognize_one_license_plate(self.current_row-1, 0) def analyze_next_one_image(self): if self.current_row < (len(self.image_filename_list)-1): self.recognize_one_license_plate(self.current_row + 1, 0) def recognize_one_license_plate(self, row, col): if col == 0 and row < len(self.image_filename_list): self.current_row = row self.recognize_and_show_one_image( self.image_filename_list[row], row) def recognize_and_show_one_image(self, image_filename_text, row): if image_filename_text.endswith(".jpg"): print(image_filename_text) path = os.path.join(self.hyperlpr_dir_path, image_filename_text) image = cv2.imdecode(np.fromfile(path, dtype=np.uint8), -1) image, res_set = SimpleRecognizePlateWithGui(image) img = QImage( image.data, image.shape[1], image.shape[0], image.shape[1] * image.shape[2], QImage.Format_RGB888) self.image_window_view.resetPixmap(img.rgbSwapped()) self.image_window_view.resetRectText(res_set) if len(res_set) > 0: curr_rect = res_set[0][2] image_crop = image[int(curr_rect[1]):int( curr_rect[1] + curr_rect[3]), int(curr_rect[0]):int(curr_rect[0] + curr_rect[2])] curr_plate = cv2.resize(image_crop, (204, 108)) plate_img = QImage( curr_plate.data, curr_plate.shape[1], curr_plate.shape[0], curr_plate.shape[1] * curr_plate.shape[2], QImage.Format_RGB888) self.license_plate_widget.setPixmap( QPixmap.fromImage(plate_img.rgbSwapped())) # print(res_set[0][6]) block_crop = image[0:24, 0:(24 * int(res_set[0][6]))] curr_block = cv2.resize( block_crop, (24 * int(res_set[0][6]), 24)) block_image = QImage( curr_block.data, curr_block.shape[1], curr_block.shape[0], curr_block.shape[1] * curr_block.shape[2], QImage.Format_RGB888) self.block_plate_widget.setPixmap( QPixmap.fromImage(block_image.rgbSwapped())) self.segmentation_recognition_edit.setText(res_set[0][0]) if res_set[0][0] in image_filename_text: self.segmentation_recognition_edit.setStyleSheet("color:black") else: self.segmentation_recognition_edit.setStyleSheet("color:red") self.filename_edit.setText(image_filename_text) self.confidence_edit.setText("%.3f" % (float(res_set[0][1]))) self.plate_color_edit.setText(res_set[0][3]) if res_set[0][3] in image_filename_text: self.plate_color_edit.setStyleSheet("color:black") else: self.plate_color_edit.setStyleSheet("color:red") self.e2e_recognization_edit.setText(res_set[0][4]) if res_set[0][4] in image_filename_text: self.e2e_recognization_edit.setStyleSheet("color:black") else: self.e2e_recognization_edit.setStyleSheet("color:red") self.e2e_confidence_edit.setText( "%.3f" % (float(res_set[0][5]))) else: self.license_plate_widget.clear() self.block_plate_widget.clear() self.segmentation_recognition_edit.setText("") self.filename_edit.setText(image_filename_text) self.confidence_edit.setText("") self.plate_color_edit.setText("") self.e2e_recognization_edit.setText("") self.e2e_confidence_edit.setText("") self.fill_table_widget_with_res_info(res_set, row) def batch_recognize_all_images(self): self.segmentation_recognition_correct_number = 0 self.color_correct_number = 0 self.e2e_recognization_correct_number = 0 self.batch_recognization_thread.set_parameter( self.image_filename_list, self.hyperlpr_dir_path) def recognization_done_slot(self, result_list): row = result_list[0] res_set = result_list[1] self.fill_table_widget_with_res_info(res_set, row) if row == len(self.image_filename_list) - 1: total_number = len(self.image_filename_list) row_count = self.hyperlpr_tableview.rowCount() if row_count > total_number: self.hyperlpr_tableview.removeRow(total_number) self.hyperlpr_tableview.insertRow(total_number) item0 = QTableWidgetItem() item0.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 0, item0) self.hyperlpr_tableview.item( total_number, 0).setText( "统计结果") item1 = QTableWidgetItem() item1.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 1, item1) self.hyperlpr_tableview.item( total_number, 1).setText( "{0} / {1} = {2: .3f}".format( self.segmentation_recognition_correct_number, total_number, self.segmentation_recognition_correct_number / total_number)) item2 = QTableWidgetItem() item2.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 2, item2) item3 = QTableWidgetItem() item3.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 3, item3) self.hyperlpr_tableview.item( total_number, 3).setText( "{0} / {1} = {2: .3f}".format(self.e2e_recognization_correct_number, total_number, self.e2e_recognization_correct_number / total_number)) item4 = QTableWidgetItem() item4.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 4, item4) self.hyperlpr_tableview.item( total_number, 4).setText( "{0} / {1} = {2: .3f}".format(self.color_correct_number, total_number, self.color_correct_number / total_number)) item5 = QTableWidgetItem() item5.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 5, item5) def fill_table_widget_with_res_info(self, res_set, row): image_filename_text = self.image_filename_list[row] if len(res_set) > 0: self.hyperlpr_tableview.item(row, 1).setText(res_set[0][0]) if res_set[0][0] in image_filename_text: self.hyperlpr_tableview.item( row, 1).setForeground( QBrush( QColor( 0, 0, 255))) self.segmentation_recognition_correct_number += 1 else: self.hyperlpr_tableview.item( row, 1).setForeground( QBrush( QColor( 255, 0, 0))) self.hyperlpr_tableview.item( row, 2).setText( "%.3f" % (float( res_set[0][1]))) self.hyperlpr_tableview.item(row, 3).setText(res_set[0][3]) if res_set[0][3] in image_filename_text: self.hyperlpr_tableview.item( row, 3).setForeground( QBrush( QColor( 0, 0, 255))) self.color_correct_number += 1 else: self.hyperlpr_tableview.item( row, 3).setForeground( QBrush( QColor( 255, 0, 0))) self.hyperlpr_tableview.item(row, 4).setText(res_set[0][4]) if res_set[0][4] in image_filename_text: self.hyperlpr_tableview.item( row, 4).setForeground( QBrush( QColor( 0, 0, 255))) self.e2e_recognization_correct_number += 1 else: self.hyperlpr_tableview.item( row, 4).setForeground( QBrush( QColor( 255, 0, 0))) self.hyperlpr_tableview.item( row, 5).setText( "%.3f" % (float( res_set[0][5])))
class Labels(QWidget): """ Attributes ---------- chan_name : list of str list of all the labels (with the user-defined changes) """ def __init__(self, parent): super().__init__() self.parent = parent self.filename = None self.chan_name = None # None when dataset is not loaded self.create() def create(self): self.idx_load = QPushButton('Load') self.idx_load.clicked.connect(self.load_labels) self.idx_load.setToolTip('Load file with a list of channels (separated by , or ; or tabs or spaces).') self.idx_save = QPushButton('Save') self.idx_save.clicked.connect(self.save_labels) self.idx_save.setEnabled(False) # cancel is equal to setting labels to what they were self.idx_cancel = QPushButton('Cancel') self.idx_cancel.clicked.connect(self.update) self.idx_apply = QPushButton('Apply') self.idx_apply.clicked.connect(self.apply) self.idx_apply.setToolTip('Changes will take effect. This will reset the channel groups and traces.') layout_0 = QHBoxLayout() layout_0.addWidget(self.idx_load) layout_0.addWidget(self.idx_save) layout_1 = QHBoxLayout() layout_1.addWidget(self.idx_cancel) layout_1.addWidget(self.idx_apply) self.table = QTableWidget() self.table.horizontalHeader().setStretchLastSection(True) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setColumnCount(2) self.table.setHorizontalHeaderLabels(['Current Labels', 'New Labels']) self.table.cellChanged.connect(self.check_labels) layout = QVBoxLayout() layout.addLayout(layout_0) layout.addWidget(self.table) layout.addLayout(layout_1) self.setLayout(layout) self.setEnabled(False) def update(self, checked=False, labels=None, custom_labels=None): """Use this function when we make changes to the list of labels or when we load a new dataset. Parameters ---------- checked : bool argument from clicked.connect labels : list of str list of labels in the dataset (default) custom_labels : list of str list of labels from a file """ if labels is not None: self.setEnabled(True) self.chan_name = labels self.table.blockSignals(True) self.table.clearContents() self.table.setRowCount(len(self.chan_name)) for i, label in enumerate(self.chan_name): old_label = QTableWidgetItem(label) old_label.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) if custom_labels is not None and i < len(custom_labels) and custom_labels[i]: # it's not empty string or None label_txt = custom_labels[i] else: label_txt = label new_label = QTableWidgetItem(label_txt) self.table.setItem(i, 0, old_label) self.table.setItem(i, 1, new_label) self.table.blockSignals(False) def check_labels(self): # read new labels first labels = self._read_labels() # disable apply, if there are duplicates if len(labels) == len(set(labels)): self.idx_apply.setEnabled(True) else: self.idx_apply.setEnabled(False) # mark duplicates in red self.table.blockSignals(True) for i, label in enumerate(labels): if labels.count(label) > 1: self.table.item(i, 1).setBackground(QColor('red')) else: self.table.item(i, 1).setBackground(QColor('white')) self.table.blockSignals(False) def load_labels(self, checked=False, test_name=None): if self.filename is not None: filename = self.filename elif self.parent.info.filename is not None: filename = Path(self.parent.info.filename) else: filename = None if test_name: filename = test_name else: filename, _ = QFileDialog.getOpenFileName(self, 'Open Labels', str(filename.parent), 'Comma-separated values (*.csv);; Text file (*.txt);; All Files(*.*)') if filename == '': return self.filename = Path(filename) with self.filename.open() as f: text = f.read() labels = split(', |,|; |;|\t|\n| ',text) labels = [label.strip() for label in labels] self.update(custom_labels=labels) def save_labels(self): """Save labels modified by the user. TODO ---- Save labels modified by the user """ pass def apply(self): self.chan_name = self._read_labels() self.parent.info.dataset.header['chan_name'] = self.chan_name self.parent.channels.reset() self.parent.traces.reset() def reset(self): self.table.blockSignals(True) self.table.clearContents() self.table.blockSignals(False) self.setEnabled(False) def _read_labels(self): labels = [] for i in range(self.table.rowCount()): labels.append(self.table.item(i, 1).text()) return labels
class PairingsWidget(QWidget): def __init__(self, parent): super(PairingsWidget, self).__init__(parent) self.parent = parent view.notifier.observers.append(self) self.header_label = QLabel('Pairings') self.header_widget = QWidget(self) header_layout = QBoxLayout(QBoxLayout.TopToBottom) header_layout.addWidget(self.header_label) self.header_widget.setLayout(header_layout) self.pairings_list = QTableWidget(style.style_loader.TABLE_INITIAL_LENGTH, 2, self) self.pairings_list.setFixedHeight(300) self.pairings_list.setFixedWidth(400) self.pairings_list.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.pairings_list.verticalHeader().setSectionResizeMode(QHeaderView.Fixed) self.pairings_list_widget = QWidget(self) pairings_list_layout = QBoxLayout(QBoxLayout.LeftToRight) pairings_list_layout.addWidget(self.pairings_list) self.pairings_list_widget.setLayout(pairings_list_layout) self.report_btn = QPushButton('Report Results', self) self.report_btn.clicked.connect(parent.show_report_result_widget) self.report_btn_widget = QWidget(self) report_btn_layout = QBoxLayout(QBoxLayout.LeftToRight) report_btn_layout.addWidget(self.report_btn) self.report_btn_widget.setLayout(report_btn_layout) layout = QFormLayout() layout.addRow(self.header_widget) layout.addRow(self.pairings_list_widget) layout.addRow(self.report_btn_widget) self.setLayout(layout) self.update() def update(self): self.pairings_list.clearContents() index = 0 for p1, p2 in to.pairings.items(): if index == self.pairings_list.rowCount(): self.pairings_list.insertRow(index) p1_item = QTableWidgetItem(p1) p1_item.setFlags(p1_item.flags() & ~Qt.ItemIsEditable) self.pairings_list.setItem(index, 0, p1_item) if p2 == None: p2_str = '--BYE--' else: p2_str = p2 p2_item = QTableWidgetItem(p2_str) p2_item.setFlags(p2_item.flags() & ~Qt.ItemIsEditable) self.pairings_list.setItem(index, 1, p2_item) index += 1 self.pairings_list.show() def player_added(self, player, user): pass def player_removed(self, player): pass def pairings_created(self): self.update() self.parent.show() def report_result(self, player, record, win_loss_draw): try: if win_loss_draw == 'win': to.record_win(player, record) elif win_loss_draw == 'loss': to.record_loss(player, record) elif win_loss_draw == 'draw': to.record_draw(player, record) view.notifier.result_reported() except TournamentException as ex: self.error = ErrorMessage(str(ex), '') self.error.setStyleSheet(style.style_loader.stylesheet) self.error.show() def result_reported(self): self.update() self.parent.show() def reset(self): self.update() self.parent.show()
class ModeTabWidget(QWidget): """ This class describes the placement of widgets in the Mode 1 tab """ def __init__(self, globalData): super().__init__() self.tVec = [] self.kVec = [] self.globalData = globalData #self.layout = QHBoxLayout(self) layout = QGridLayout(self) layout.setColumnStretch(1, 2) layout.setColumnStretch(2, 2) self.tableWidget = QTableWidget() self.tableWidget.setRowCount(4) self.tableWidget.setColumnCount(2) self.tableWidget.setHorizontalHeaderLabels(['Dummy','Dummy']) self.tableWidget.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) layout.addWidget(self.tableWidget,1,1) self.buttonPanel = QVBoxLayout() self.buttonPanel.addWidget(self.addDataButtons()) #self.buttonPanel.addWidget(self.addExternalDataButtons()) self.buttonPanel.addWidget(self.addComputationButtons()) layout.addLayout(self.buttonPanel,1,2) def addExternalDataButtons(self): buttonGroupBox = QGroupBox("Import/Export data", self) buttonLayout = QVBoxLayout() buttons = [] self.importDataButton = QPushButton('Import Data') self.importDataButton.setToolTip('Imports failure data') self.importDataButton.clicked.connect(self.importData) buttons.append(self.importDataButton) self.saveDataButton = QPushButton('Save Data') self.saveDataButton.setToolTip('Saves data in the table failure data') self.saveDataButton.clicked.connect(self.saveData) buttons.append(self.saveDataButton) for button in buttons: buttonLayout.addWidget(button) #buttonLayout.setAlignment(button, Qt.AlignTop) buttonLayout.addStretch(1) buttonGroupBox.setLayout(buttonLayout) return buttonGroupBox def addComputationButtons(self): buttonGroupBox = QGroupBox("Computation", self) buttonLayout = QVBoxLayout() buttons = [] self.computeButton = QPushButton('Compute') self.computeButton.setToolTip('Starts the computation') self.computeButton.clicked.connect(self.compute) buttons.append(self.computeButton) for button in buttons: buttonLayout.addWidget(button) buttonLayout.addStretch(1) buttonGroupBox.setLayout(buttonLayout) return buttonGroupBox def addDataButtons(self): buttonGroupBox = QGroupBox("Data Manipulation", self) buttonLayout = QVBoxLayout() buttons = [] self.addRowButton = QPushButton('Add Row') self.addRowButton.setToolTip('Adds a row to the end of the table') self.addRowButton.clicked.connect(self.addRow) buttons.append(self.addRowButton) self.insertRowButton = QPushButton('Insert Row') self.insertRowButton.setToolTip('Inserts Row above the selected row') self.insertRowButton.clicked.connect(self.insertRow) buttons.append(self.insertRowButton) self.deleteRowsButton = QPushButton('Delete Row') self.deleteRowsButton.setToolTip('Deletes selected row') self.deleteRowsButton.clicked.connect(self.deleteRows) buttons.append(self.deleteRowsButton) self.clearRowsButton = QPushButton('Clear All') self.clearRowsButton.setToolTip('Clears all rows') self.clearRowsButton.clicked.connect(self.clearRows) buttons.append(self.clearRowsButton) for button in buttons: buttonLayout.addWidget(button) #buttonLayout.setAlignment(button, Qt.AlignTop) buttonLayout.addStretch(1) buttonGroupBox.setLayout(buttonLayout) return buttonGroupBox def compute(self): """ This function is run when the compute button is clicked #Verify data and start computation """ print("Compute!") data = self.getTableData() def saveAndDisplayResults(self, weibull): print("Save and display results") def importData(self): fileName = QFileDialog.getOpenFileName(self, 'Open File','.') data = utils.import_data(fileName) self.setGlobalData(data) self.populateTable(data) def setGlobalData(self, data): print("Please override this function to set the global data for the particular mode") self.globalData.input[self.modex] = data def clearRows(self): d = QDialog() buttons = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) buttons.accepted.connect(d.accept) buttons.rejected.connect(d.reject) msgLabel = QLabel("Warning: Data from all rows will be cleared. This cannot be undone. Proceed?") d.layout = QVBoxLayout(d) d.layout.addWidget(msgLabel) d.layout.addWidget(buttons) d.setWindowTitle("Clear All Rows") if d.exec_() == QDialog.Accepted: self.tableWidget.clearContents() def deleteRows(self): self.tableWidget.removeRow(self.tableWidget.currentRow()) self.tableChanged(0, 0) def addRow(self): self.tableWidget.insertRow(self.tableWidget.rowCount()) self.tableChanged(0, 0) def insertRow(self): self.tableWidget.insertRow(self.tableWidget.currentRow()) self.tableChanged(0, 0) def saveData(self): fileName = QFileDialog.getSaveFileName(self, 'Save Data', '.', initialFilter='*.csv') data = self.getTableData() if fileName: utils.export_data(data, fileName) def getTableData(self): data = [] for i in range(self.tableWidget.rowCount()): try: if self.tableWidget.item(i,0) != None: data.append((self.tableWidget.item(i,0).text(), float(self.tableWidget.item(i,1).text()))) except: print("Unexpected error:", sys.exc_info()[0]) raise print(data) return data
class VentanaAreas(QtWidgets.QDialog): def __init__(self, pluginDFS, parent=iface.mainWindow()): super(VentanaAreas, self).__init__(parent) #self.parent = iface.mainWindow() self.contenedor = QVBoxLayout() self.setLayout(self.contenedor) self.tablaAreas = QTableWidget() self.tablaAreas.setColumnCount(1) self.pluginDFS = pluginDFS self.contenedor.addWidget(self.tablaAreas) #self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) estilo = """ QWidget{ background : rgb(250,238,224) } QPushButton{ background : rgb(174, 116, 0); color : rgb(255, 255, 255); border-radius : 4px; } QPushButton::hover{ background : rgb(104, 69, 13); color : rgb(255, 255, 255); border-radius : 2px; } QTableWidget{ background : rgb(255,255,255); } """ self.setStyleSheet(estilo) #---------------------------------------------------------------- def mostrarAreas(self): self.limpiarTabla() rango = len(self.pluginDFS.geomsAreas) - 1 for x in range(0, rango): self.tablaAreas.insertRow(x) area = "%.2f" % self.pluginDFS.geomsAreas[x].area() string = str(area) + ' m2' item = QtWidgets.QTableWidgetItem(string) self.tablaAreas.setItem( x, 0, item) #self.capaActual.getFeatures().attributes()[x]) item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) color = self.pluginDFS.listaColores[x] self.tablaAreas.item(x, 0).setBackground(color) header = self.tablaAreas.horizontalHeader() header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents) self.tablaAreas.setHorizontalHeaderItem( 0, QTableWidgetItem('Area (Metros cuadrados)')) self.show() #-------------------------------------------------------- def limpiarTabla(self): self.tablaAreas.clearContents() self.tablaAreas.setRowCount(0) for row in range(0, self.tablaAreas.rowCount()): self.tablaAreas.removeRow(row) #--------------------------------------------------- def closeEvent(self, evnt): self.pluginDFS.quitarAreas()
class BarcodeTable(QGroupBox): """ GUI component. Displays a list of barcodes for the currently selected puck. """ def __init__(self, options): super(BarcodeTable, self).__init__() self._options = options self.setTitle("Plate Barcodes") self.setMaximumWidth(160) self.setMinimumWidth(260) self._init_ui() self.clear() def _init_ui(self): # Plate being displayed self._plate_lbl = QLabel() # Create barcode table - lists all the barcodes in a record self._table = QTableWidget() self._table.setMinimumWidth(70) self._table.setMinimumHeight(600) self._table.setColumnCount(1) self._table.setRowCount(10) self._table.setHorizontalHeaderLabels(['Barcode']) self._table.setMinimumWidth(200) # Clipboard button - copy the selected barcodes to the clipboard self._btn_clipboard = QPushButton('Copy To Clipboard') self._btn_clipboard.setToolTip( 'Copy barcodes for the selected record to the clipboard') self._btn_clipboard.resize(self._btn_clipboard.sizeHint()) self._btn_clipboard.clicked.connect(self.copy_to_clipboard) hbox = QHBoxLayout() hbox.setSpacing(10) hbox.addWidget(self._btn_clipboard) hbox.addStretch(1) vbox = QVBoxLayout() vbox.addWidget(self._plate_lbl) vbox.addWidget(self._table) vbox.addLayout(hbox) self.setLayout(vbox) def populate(self, holder_barcode, barcodes): """ Called when a new row is selected on the record table. """ self._holder_barcode = holder_barcode self._barcodes = barcodes[:] self._update_state() def clear(self): self._holder_barcode = None self._barcodes = [] self._update_state() def _update_state(self): self._populate_table() self._update_button_state() self._update_plate_label() def _populate_table(self): """Displays all of the barcodes from the selected record in the barcode table. By default, valid barcodes are highlighted green, invalid barcodes are highlighted red, and empty slots are grey. """ self._table.clearContents() self._table.setRowCount(len(self._barcodes)) for index, barcode in enumerate(self._barcodes): if barcode == NOT_FOUND_SLOT_SYMBOL: cell_color = self._options.col_bad() elif barcode == EMPTY_SLOT_SYMBOL: cell_color = self._options.col_empty() else: cell_color = self._options.col_ok() cell_color.a = 192 # Set table item barcode = QTableWidgetItem(barcode) barcode.setBackground(cell_color.to_qt()) barcode.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self._table.setItem(index, 0, barcode) def _update_button_state(self): self._btn_clipboard.setEnabled(self._has_barcodes()) def copy_to_clipboard(self): """ Called when the copy to clipboard button is pressed. Copies the list/s of barcodes for the currently selected records to the clipboard so that the user can paste it elsewhere. """ if self._holder_barcode is None: self._holder_barcode = NOT_FOUND_SLOT_SYMBOL clipboard_barcodes = [self._holder_barcode] + self._barcodes[:] for i, barcode in enumerate(clipboard_barcodes): if barcode in [NOT_FOUND_SLOT_SYMBOL, EMPTY_SLOT_SYMBOL]: clipboard_barcodes[i] = "" sep = os.linesep if clipboard_barcodes: import pyperclip pyperclip.copy(sep.join(clipboard_barcodes)) def _update_plate_label(self): barcode_holder = str(self._holder_barcode) text = "Plate : " + barcode_holder if self._has_barcodes( ) else "Plate:" myFont = QtGui.QFont() myFont.setBold(True) self._plate_lbl.setFont(myFont) self._plate_lbl.setText(text) def _has_barcodes(self): return self._barcodes is not None and len(self._barcodes) > 0
class UserManagerWidget(QWidget): def __init__(self, parent): super(UserManagerWidget, self).__init__(parent) self.parent = parent self.sort_order = 'by_name' view.notifier.observers.append(self) self.header_label = QLabel('Users') self.header_widget = QWidget(self) header_layout = QBoxLayout(QBoxLayout.LeftToRight) header_layout.addWidget(self.header_label) self.header_widget.setLayout(header_layout) self.sort_by_name_btn = QPushButton('Sort by Name', self) self.sort_by_name_btn.clicked.connect(self.sort_by_name) self.sort_by_rank_btn = QPushButton('Sort by Rank', self) self.sort_by_rank_btn.clicked.connect(self.sort_by_rank) self.sort_btns_widget = QWidget(self) sort_btns_layout = QBoxLayout(QBoxLayout.LeftToRight) sort_btns_layout.addWidget(self.sort_by_name_btn) sort_btns_layout.addSpacing(10) sort_btns_layout.addWidget(self.sort_by_rank_btn) self.sort_btns_widget.setLayout(sort_btns_layout) self.user_list = QTableWidget(style.style_loader.TABLE_INITIAL_LENGTH, 3, self) self.user_list.setFixedHeight(300) self.user_list.setFixedWidth(400) self.user_list.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.user_list.verticalHeader().setSectionResizeMode(QHeaderView.Fixed) self.user_list_widget = QWidget(self) user_list_layout = QBoxLayout(QBoxLayout.LeftToRight) user_list_layout.addWidget(self.user_list) self.user_list_widget.setLayout(user_list_layout) self.add_player_btn = QPushButton('Add User', self) self.add_player_btn.clicked.connect(self.parent.show_add_user_widget) self.remove_player_btn = QPushButton('Remove User', self) self.remove_player_btn.clicked.connect(self.parent.show_remove_user_widget) self.player_btns_widget = QWidget(self) player_btn_layout = QBoxLayout(QBoxLayout.LeftToRight) player_btn_layout.addWidget(self.add_player_btn) player_btn_layout.addSpacing(10) player_btn_layout.addWidget(self.remove_player_btn) self.player_btns_widget.setLayout(player_btn_layout) self.error = None layout = QFormLayout() layout.addRow(self.header_widget) layout.addRow(self.sort_btns_widget) layout.addRow(self.user_list_widget) layout.addRow(self.player_btns_widget) self.setLayout(layout) self.update() def update(self): self.user_list.clearContents() # TODO: get the most recent user list users = um.users() index = 0 for user in users: if index == self.user_list.rowCount(): self.user_list.insertRow(index) name_item = QTableWidgetItem(user.name) name_item.setFlags(name_item.flags() & ~Qt.ItemIsEditable) self.user_list.setItem(index, 0, name_item) id_item = QTableWidgetItem(str(user.id)) id_item.setFlags(id_item.flags() & ~Qt.ItemIsEditable) self.user_list.setItem(index, 1, id_item) record_item = QTableWidgetItem(user.record_str()) record_item.setFlags(record_item.flags() & ~Qt.ItemIsEditable) self.user_list.setItem(index, 2, record_item) index += 1 self.user_list.show() def sort_by_name(self): self.sort_order = 'by_name' self.update() def sort_by_rank(self): self.sort_order = 'by_rank' self.update() def player_added(self, player, user): self.update() def player_removed(self, player): self.update() def report_result(self, player, record, win_or_draw): pass def result_reported(self): self.update() def pairings_created(self): self.update() def reset(self): self.update()
class ObjectSelector(QWidget): def __init__(self, *args): super().__init__(*args) # Set size & position. screen = QtWidgets.QDesktopWidget().screenGeometry(0) self.resize(int(screen.width() * 0.7), int(screen.height() * 0.7)) self.move(int(screen.width() * 0.15), int(screen.height() * 0.15)) # Set window type. flags = QtCore.Qt.WindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint) self.setWindowFlags(flags) self.layout = QVBoxLayout() self.layout.setContentsMargins(50, 50, 50, 50) self.omnibox = QHBoxLayout() self.omnibox.setContentsMargins(20, 20, 20, 20) self.omnitext = QLineEdit() self.omnitext.setStyleSheet( "QLineEdit { font-size: 20px; padding: 12px; border: none; border-radius: 10px; }" ) self.omnitext.setFrame(False) # Doesn't seem to do anything' self.omnitext.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False) self.omnitext.setPlaceholderText("Search ...") self.omnitext.setClearButtonEnabled(True) self.omnitext.setTextMargins(20, 20, 20, 20) self.omnibox.addWidget(self.omnitext) self.layout.addLayout(self.omnibox) # Here I'm going to start with the list of objects from # the history service. This will need to be completely # rejigged in future. # So, a table ... date/time, event, type, details of object. # # The object details will be the tricky bit: objects don't # have to have a name or anything. Perhaps it'd be good for # the type implementation to have a method to get a description # of the object in a type-specific way? self.object_table = QTableWidget(10, 4, self) self.object_table.setHorizontalHeaderLabels( ("Date / Time", "Type", "Event", "Object")) self.object_table.verticalHeader().setVisible(False) self.object_table.setContentsMargins(20, 20, 20, 20) for r in range(10): for c in (0, 1, 2, 3): item = QTableWidgetItem() item.setText( ["datetime", "type", "event", "description of object"][c]) self.object_table.setItem(r, c, item) self.layout.addWidget(self.object_table) self.setLayout(self.layout) self.hide() self.history = History.api() return def show(self): # FIXME: needs a lot more work here ... # Populate history list self.object_table.clearContents() now = datetime.utcnow() history = self.history.get_events(now, 100, True) r = 0 for event in history: for c in range(4): item = QTableWidgetItem() item.setText([event[0], "type", event[2], event[1]][c]) self.object_table.setItem(r, c, item) r += 1 super().show() return def hide(self): super().hide() return def toggle_visibility(self): """Show if hidden; hide if shown""" if self.isVisible(): self.hide() else: self.show() return
class LabelAssistDialog(QDialog): """ A simple UI for showing bookmarks and navigating to them. FIXME: For now, this window is tied to a particular lane. If your project has more than one lane, then each one will have it's own bookmark window, which is kinda dumb. """ def __init__(self, parent, topLevelOperatorView): super(LabelAssistDialog, self).__init__(parent) # Create thread router to populate table on main thread self.threadRouter = ThreadRouter(self) # Set object classification operator view self.topLevelOperatorView = topLevelOperatorView self.setWindowTitle("Label Assist") self.setMinimumWidth(500) self.setMinimumHeight(700) layout = QGridLayout() layout.setContentsMargins(10, 10, 10, 10) # Show variable importance table rows = 0 columns = 4 self.table = QTableWidget(rows, columns) self.table.setHorizontalHeaderLabels(['Frame', 'Max Area', 'Min Area', 'Labels']) self.table.verticalHeader().setVisible(False) # Select full row on-click and call capture double click self.table.setSelectionBehavior(QTableView.SelectRows); self.table.doubleClicked.connect(self._captureDoubleClick) layout.addWidget(self.table, 1, 0, 3, 2) # Create progress bar self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(0) self.progressBar.hide() layout.addWidget(self.progressBar, 4, 0, 1, 2) # Create button to populate table self.computeButton = QPushButton('Compute object info') self.computeButton.clicked.connect(self._triggerTableUpdate) layout.addWidget(self.computeButton, 5, 0) # Create close button closeButton = QPushButton('Close') closeButton.clicked.connect(self.close) layout.addWidget(closeButton, 5, 1) # Set dialog layout self.setLayout(layout) def _triggerTableUpdate(self): # Check that object area is included in selected features featureNames = self.topLevelOperatorView.SelectedFeatures.value if 'Standard Object Features' not in featureNames or 'Count' not in featureNames['Standard Object Features']: box = QMessageBox(QMessageBox.Warning, 'Warning', 'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"', QMessageBox.NoButton, self) box.show() return # Clear table self.table.clearContents() self.table.setRowCount(0) self.table.setSortingEnabled(False) self.progressBar.show() self.computeButton.setEnabled(False) def compute_features_for_frame(tIndex, t, features): # Compute features and labels (called in parallel from request pool) roi = [slice(None) for i in range(len(self.topLevelOperatorView.LabelImages.meta.shape))] roi[tIndex] = slice(t, t+1) roi = tuple(roi) frame = self.topLevelOperatorView.SegmentationImages(roi).wait() frame = frame.squeeze().astype(numpy.uint32, copy=False) # Dirty trick: We don't care what we're passing here for the 'image' parameter, # but vigra insists that we pass *something*, so we'll cast the label image as float32. features[t] = vigra.analysis.extractRegionFeatures(frame.view(numpy.float32), frame, ['Count'], ignoreLabel=0) tIndex = self.topLevelOperatorView.SegmentationImages.meta.axistags.index('t') tMax = self.topLevelOperatorView.SegmentationImages.meta.shape[tIndex] features = {} labels = {} def compute_all_features(): # Compute features in parallel pool = RequestPool() for t in range(tMax): pool.add( Request( partial(compute_features_for_frame, tIndex, t, features) ) ) pool.wait() # Compute labels labels = self.topLevelOperatorView.LabelInputs([]).wait() req = Request(compute_all_features) req.notify_finished( partial(self._populateTable, features, labels) ) req.submit() @threadRouted def _populateTable(self, features, labels, *args): self.progressBar.hide() self.computeButton.setEnabled(True) for time, feature in features.items(): # Insert row rowNum = self.table.rowCount() self.table.insertRow(self.table.rowCount()) # Get max and min object areas areas = feature['Count']#objectFeatures['Standard Object Features']['Count'] maxObjArea = numpy.max(areas[numpy.nonzero(areas)]) minObjArea = numpy.min(areas[numpy.nonzero(areas)]) # Get number of labeled objects labelNum = numpy.count_nonzero(labels[time]) # Load fram number item = QTableWidgetItem(str(time)) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 0, item) # Load max object areas item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(maxObjArea))) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 1, item) # Load min object areas item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(minObjArea))) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 2, item) # Load label numbers item = QTableWidgetItemWithFloatSorting(str("{: .01f}".format(labelNum))) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 3, item) # Resize column size to fit dialog size self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) # Sort by max object area self.table.setSortingEnabled(True) self.table.sortByColumn(1, Qt.DescendingOrder) def _captureDoubleClick(self): # Navigate to selected frame index = self.table.selectedIndexes()[0] frameStr = self.table.model().data(index).toString() if frameStr: frameNum = int(frameStr) self.parent().editor.posModel.time = frameNum
class iCareNewQueryWidget(QWidget): def __init__(self): super(QWidget, self).__init__() self._setup_widget() def _setup_widget(self): self.query = QTextEdit(self) self.label1 = QLabel("Query:") self.label2 = QLabel("Output:") self.submit1 = QPushButton("Execute Query") self.submit1.clicked.connect(self.run_query) self.export1 = QPushButton("Export Data") self.export1.clicked.connect(self.export_data) self.table1 = QTableWidget() # set layouts self.layout = QGridLayout(self) self.layout.setColumnStretch(0, 3) # add widgets self.layout.addWidget(self.label1, 0, 0) self.layout.addWidget(self.query, 1, 0) self.layout.addWidget(self.submit1, 1, 1) self.layout.addWidget(self.label2, 2, 0) self.layout.addWidget(self.table1, 3, 0) self.layout.addWidget(self.export1, 3, 1) self.setLayout(self.layout) @pyqtSlot() def run_query(self): query = self.query.toPlainText() if (len(query) == 0): prompt_error("Please enter a query") return try: dict_values = database.execute_query_result(query) if (dict_values): self.populateTable(dict_values) gui_helper.prompt_information("query executed successfully") except Exception as e: gui_helper.prompt_error(str(e)) def populateTable(self, column_values): self.table1.clearContents() self.table1.setColumnCount(len(column_values)) for key in column_values: self.table1.setRowCount(len(column_values[key])) break for i, key in enumerate(column_values): self.table1.setHorizontalHeaderItem(i, QTableWidgetItem(key)) col_vals = column_values[key] for j, val in enumerate(col_vals): self.table1.setItem(j, i, QTableWidgetItem(str(val))) @pyqtSlot() def export_data(self): query_text = self.query.toPlainText() if (len(query_text) == 0): prompt_error("Please enter a query") return try: conn = database.get_db_connection() dataframe = query.manual_sql_query(conn, query_text) dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) if dialog.exec_(): filepaths = dialog.selectedFiles() self.file_save(filepaths[0], dataframe) except Exception as e: gui_helper.prompt_error(str(e)) @pyqtSlot() def file_save(self, file_path, dataframe): if (exportFile.exportCSV(file_path, dataframe)): gui_helper.prompt_information("File has been succesfully saved!") else: gui_helper.prompt_error("Failed to save file")
class HyperLprWindow(QMainWindow): start_init_signal = pyqtSignal() def __init__(self): super().__init__() self.initUI() def initUI(self): self.statusBar().showMessage('Ready') self.image_window_view = HyperLprImageView() table_widget_header_labels = [ "文件名", "分割识别", "置信度", "颜色", "E2E识别", "E2E置信度" ] self.hyperlpr_tableview = QTableWidget(0, len(table_widget_header_labels)) self.hyperlpr_tableview.setHorizontalHeaderLabels( table_widget_header_labels) self.hyperlpr_tableview.setSelectionBehavior( QAbstractItemView.SelectItems) self.hyperlpr_tableview.setSelectionMode( QAbstractItemView.SingleSelection) self.hyperlpr_tableview.setEditTriggers( QAbstractItemView.NoEditTriggers) self.hyperlpr_tableview.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) self.hyperlpr_tableview.setEditTriggers( QAbstractItemView.NoEditTriggers) self.hyperlpr_tableview.cellClicked.connect( self.recognize_one_license_plate) self.location_label = QLabel("车牌目录", self) self.location_text = QLineEdit(self) self.location_text.setEnabled(False) self.location_text.setFixedWidth(300) self.location_button = QPushButton("...") self.location_button.clicked.connect(self.select_new_dir) self.location_layout = QHBoxLayout() self.location_layout.addWidget(self.location_label) self.location_layout.addWidget(self.location_text) self.location_layout.addWidget(self.location_button) self.location_layout.addStretch() self.check_box = QCheckBox("与文件名比较车牌") self.check_box.setChecked(True) self.update_file_path_button = QPushButton('批量识别') self.update_file_path_button.clicked.connect( self.batch_recognize_all_images) self.update_file_path_layout = QHBoxLayout() self.update_file_path_layout.addWidget(self.check_box) self.update_file_path_layout.addWidget(self.update_file_path_button) self.update_file_path_layout.addStretch() self.bottom_layout = QVBoxLayout() self.bottom_layout.addLayout(self.location_layout) self.bottom_layout.addLayout(self.update_file_path_layout) bottom_widget = QWidget() bottom_widget.setLayout(self.bottom_layout) license_plate_iamge_label = QLabel("车牌图") self.license_plate_widget = QLabel("") block_image_label = QLabel("分割图") self.block_plate_widget = QLabel("") filename_label = QLabel("文件名:") self.filename_edit = QLineEdit() segmentation_recognition_label = QLabel("分割识别:") self.segmentation_recognition_edit = QLineEdit() self.segmentation_recognition_edit.setFont(QFont("黑体", 24, QFont.Bold)) self.segmentation_recognition_edit.setStyleSheet("color:red") confidence_label = QLabel("置信度") self.confidence_edit = QLineEdit() self.confidence_edit.setFont(QFont("黑体", 24, QFont.Bold)) self.confidence_edit.setStyleSheet("color:red") plate_color_label = QLabel("车牌颜色") self.plate_color_edit = QLineEdit() self.plate_color_edit.setFont(QFont("黑体", 24, QFont.Bold)) self.plate_color_edit.setStyleSheet("color:red") e2e_recognization_label = QLabel("e2e识别:") self.e2e_recognization_edit = QLineEdit() self.e2e_recognization_edit.setFont(QFont("黑体", 24, QFont.Bold)) self.e2e_recognization_edit.setStyleSheet("color:red") e2e_confidence_label = QLabel("e2e置信度") self.e2e_confidence_edit = QLineEdit() self.e2e_confidence_edit.setFont(QFont("黑体", 24, QFont.Bold)) self.e2e_confidence_edit.setStyleSheet("color:red") info_gridlayout = QGridLayout() info_gridlayout.addWidget(filename_label, 0, 0) info_gridlayout.addWidget(self.filename_edit, 0, 1) info_gridlayout.addWidget(license_plate_iamge_label, 1, 0) info_gridlayout.addWidget(self.license_plate_widget, 1, 1) info_gridlayout.addWidget(block_image_label, 2, 0) info_gridlayout.addWidget(self.block_plate_widget, 2, 1) info_gridlayout.addWidget(segmentation_recognition_label, 3, 0) info_gridlayout.addWidget(self.segmentation_recognition_edit, 3, 1) info_gridlayout.addWidget(confidence_label, 4, 0) info_gridlayout.addWidget(self.confidence_edit, 4, 1) info_gridlayout.addWidget(plate_color_label, 5, 0) info_gridlayout.addWidget(self.plate_color_edit, 5, 1) info_gridlayout.addWidget(e2e_recognization_label, 6, 0) info_gridlayout.addWidget(self.e2e_recognization_edit, 6, 1) info_gridlayout.addWidget(e2e_confidence_label, 7, 0) info_gridlayout.addWidget(self.e2e_confidence_edit, 7, 1) info_widget = QWidget() info_widget.setLayout(info_gridlayout) right_splitter = QSplitter(Qt.Vertical) right_splitter.addWidget(bottom_widget) right_splitter.addWidget(self.hyperlpr_tableview) right_splitter.addWidget(info_widget) right_splitter.setStretchFactor(1, 3) right_splitter.setStretchFactor(2, 2) main_splitter = QSplitter(Qt.Horizontal) main_splitter.addWidget(self.image_window_view) main_splitter.addWidget(right_splitter) main_splitter.setStretchFactor(0, 1) self.image_filename_list = [] self.hyperlpr_dir_path = "" self.segmentation_recognition_correct_number = 0 self.color_correct_number = 0 self.e2e_recognization_correct_number = 0 self.batch_recognization_thread = LicenseRecognizationThread() self.batch_recognization_thread.recognization_done_signal.connect( self.recognization_done_slot) self.batch_recognization_thread.start() self.start_init_signal.connect(self.read_path_and_show_one_image) self.setCentralWidget(main_splitter) self.setWindowTitle("HyperLPR车牌识别软件v1.0") self.start_init_signal.emit() def read_path_and_show_one_image(self): hyperlpr_dir_info_filepath = QDir.homePath() + "/hyperlpr_dir_file" if os.path.exists(hyperlpr_dir_info_filepath): with open(hyperlpr_dir_info_filepath, 'r') as f: self.hyperlpr_dir_path = f.read() if len(self.hyperlpr_dir_path) > 0: self.reset_info_gui() if len(self.image_filename_list) > 0: self.recognize_and_show_one_image(self.image_filename_list[0], 0) def select_new_dir(self): self.hyperlpr_dir_path = QFileDialog.getExistingDirectory( self, "读取文件夹", QDir.currentPath()) if len(self.hyperlpr_dir_path) > 0: hyperlpr_dir_info_filepath = QDir.homePath() + "/hyperlpr_dir_file" with open(hyperlpr_dir_info_filepath, 'w') as f: f.write(self.hyperlpr_dir_path) self.reset_info_gui() def reset_info_gui(self): self.location_text.setText(self.hyperlpr_dir_path) self.scan_files_with_new_dir(self.hyperlpr_dir_path) self.fill_table_with_new_info() def scan_files_with_new_dir(self, path): name_list = os.listdir(path) # 列出文件夹下所有的目录与文件 self.image_filename_list.clear() for i in range(0, len(name_list)): if name_list[i].endswith(".jpg") or name_list[i].endswith(".png"): self.image_filename_list.append(name_list[i]) def fill_table_with_new_info(self): self.hyperlpr_tableview.clearContents() row_count = self.hyperlpr_tableview.rowCount() for i in range(row_count, -1, -1): self.hyperlpr_tableview.removeRow(i) for i in range(0, len(self.image_filename_list)): row = self.hyperlpr_tableview.rowCount() self.hyperlpr_tableview.insertRow(row) item0 = QTableWidgetItem() item0.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 0, item0) self.hyperlpr_tableview.item(row, 0).setText( self.image_filename_list[i]) item1 = QTableWidgetItem() item1.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 1, item1) item2 = QTableWidgetItem() item2.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 2, item2) item3 = QTableWidgetItem() item3.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 3, item3) item4 = QTableWidgetItem() item4.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 4, item4) item5 = QTableWidgetItem() item5.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(row, 5, item5) def recognize_one_license_plate(self, row, col): if col == 0 and row < len(self.image_filename_list): self.recognize_and_show_one_image(self.image_filename_list[row], row) def recognize_and_show_one_image(self, image_filename_text, row): if image_filename_text.endswith(".jpg"): path = os.path.join(self.hyperlpr_dir_path, image_filename_text) image = cv2.imdecode(np.fromfile(path, dtype=np.uint8), -1) image, res_set = SimpleRecognizePlateWithGui(image) img = QImage(image.data, image.shape[1], image.shape[0], image.shape[1] * image.shape[2], QImage.Format_RGB888) self.image_window_view.resetPixmap(img.rgbSwapped()) self.image_window_view.resetRectText(res_set) if len(res_set) > 0: curr_rect = res_set[0][2] image_crop = image[int(curr_rect[1]):int(curr_rect[1] + curr_rect[3]), int(curr_rect[0]):int(curr_rect[0] + curr_rect[2])] curr_plate = cv2.resize(image_crop, (136, 72)) plate_img = QImage(curr_plate.data, curr_plate.shape[1], curr_plate.shape[0], curr_plate.shape[1] * curr_plate.shape[2], QImage.Format_RGB888) self.license_plate_widget.setPixmap( QPixmap.fromImage(plate_img.rgbSwapped())) # print(res_set[0][6]) block_crop = image[0:24, 0:(24 * int(res_set[0][6]))] curr_block = cv2.resize(block_crop, (24 * int(res_set[0][6]), 24)) block_image = QImage(curr_block.data, curr_block.shape[1], curr_block.shape[0], curr_block.shape[1] * curr_block.shape[2], QImage.Format_RGB888) self.block_plate_widget.setPixmap( QPixmap.fromImage(block_image.rgbSwapped())) self.segmentation_recognition_edit.setText(res_set[0][0]) self.filename_edit.setText(image_filename_text) self.confidence_edit.setText("%.3f" % (float(res_set[0][1]))) self.plate_color_edit.setText(res_set[0][3]) self.e2e_recognization_edit.setText(res_set[0][4]) self.e2e_confidence_edit.setText("%.3f" % (float(res_set[0][5]))) else: self.license_plate_widget.clear() self.block_plate_widget.clear() self.segmentation_recognition_edit.setText("") self.filename_edit.setText("") self.confidence_edit.setText("") self.plate_color_edit.setText("") self.e2e_recognization_edit.setText("") self.e2e_confidence_edit.setText("") self.fill_table_widget_with_res_info(res_set, row) def batch_recognize_all_images(self): self.segmentation_recognition_correct_number = 0 self.color_correct_number = 0 self.e2e_recognization_correct_number = 0 self.batch_recognization_thread.set_parameter(self.image_filename_list, self.hyperlpr_dir_path) def recognization_done_slot(self, result_list): row = result_list[0] res_set = result_list[1] self.fill_table_widget_with_res_info(res_set, row) if row == len(self.image_filename_list) - 1: total_number = len(self.image_filename_list) row_count = self.hyperlpr_tableview.rowCount() if row_count > total_number: self.hyperlpr_tableview.removeRow(total_number) self.hyperlpr_tableview.insertRow(total_number) item0 = QTableWidgetItem() item0.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 0, item0) self.hyperlpr_tableview.item(total_number, 0).setText("统计结果") item1 = QTableWidgetItem() item1.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 1, item1) self.hyperlpr_tableview.item(total_number, 1).setText( "{0} / {1} = {2: .3f}".format( self.segmentation_recognition_correct_number, total_number, self.segmentation_recognition_correct_number / total_number)) item2 = QTableWidgetItem() item2.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 2, item2) item3 = QTableWidgetItem() item3.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 3, item3) self.hyperlpr_tableview.item(total_number, 3).setText( "{0} / {1} = {2: .3f}".format( self.e2e_recognization_correct_number, total_number, self.e2e_recognization_correct_number / total_number)) item4 = QTableWidgetItem() item4.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 4, item4) self.hyperlpr_tableview.item(total_number, 4).setText( "{0} / {1} = {2: .3f}".format( self.color_correct_number, total_number, self.color_correct_number / total_number)) item5 = QTableWidgetItem() item5.setTextAlignment(Qt.AlignCenter) self.hyperlpr_tableview.setItem(total_number, 5, item5) def fill_table_widget_with_res_info(self, res_set, row): image_filename_text = self.image_filename_list[row] if len(res_set) > 0: self.hyperlpr_tableview.item(row, 1).setText(res_set[0][0]) if res_set[0][0] in image_filename_text: self.hyperlpr_tableview.item(row, 1).setForeground( QBrush(QColor(0, 0, 255))) self.segmentation_recognition_correct_number += 1 else: self.hyperlpr_tableview.item(row, 1).setForeground( QBrush(QColor(255, 0, 0))) self.hyperlpr_tableview.item(row, 2).setText( "%.3f" % (float(res_set[0][1]))) self.hyperlpr_tableview.item(row, 3).setText(res_set[0][3]) if res_set[0][3] in image_filename_text: self.hyperlpr_tableview.item(row, 3).setForeground( QBrush(QColor(0, 0, 255))) self.color_correct_number += 1 else: self.hyperlpr_tableview.item(row, 3).setForeground( QBrush(QColor(255, 0, 0))) self.hyperlpr_tableview.item(row, 4).setText(res_set[0][4]) if res_set[0][4] in image_filename_text: self.hyperlpr_tableview.item(row, 4).setForeground( QBrush(QColor(0, 0, 255))) self.e2e_recognization_correct_number += 1 else: self.hyperlpr_tableview.item(row, 4).setForeground( QBrush(QColor(255, 0, 0))) self.hyperlpr_tableview.item(row, 5).setText( "%.3f" % (float(res_set[0][5])))
class Table(QMainWindow): def __init__(self, parent): super().__init__(parent) self.db = DB() self.initUI() def initUI(self): in_class = "tables" self.sidebar = sidebar.Sidebar(self) self.sidebar.window.connect(self.getvalue) self.addDockWidget(Qt.LeftDockWidgetArea, self.sidebar) header = AppName(in_class) footer = Footer() add_and_search = AddSearchFrame(in_class) add_and_search.add_button.clicked.connect( lambda: self.add_tables(in_class)) add_and_search.search_button.clicked.connect( lambda: self.search_tables(add_and_search.search_box)) self.table = QTableWidget() self.table.setColumnCount(4) # self.table.setStyleSheet("border: none") # self.table.setStyleSheet( # "background-color: rgb(255, 255, 255);\n" # 'font: 10pt "MS Shell Dlg 2";\n' # "color: rgb(30, 45, 66);" # ) # self.table.setHorizontalHeaderItem(0, QTableWidgetItem("ID")) self.table.setHorizontalHeaderItem(0, QTableWidgetItem("Table Name")) self.table.setHorizontalHeaderItem(1, QTableWidgetItem("Covers")) self.table.setHorizontalHeaderItem(2, QTableWidgetItem("Edit")) self.table.setHorizontalHeaderItem(3, QTableWidgetItem("Delete")) # self.table.insertRow(self.table.rowCount()) # # self.table.setItem(self.table.rowCount() - 1, 0, QTableWidgetItem("ID1")) # self.table.setItem(self.table.rowCount() - 1, 1, QTableWidgetItem("Name1")) # self.table.setItem(self.table.rowCount() - 1, 2, QTableWidgetItem("Job1")) # self.table.setItem(self.table.rowCount() - 1, 3, QTableWidgetItem("Joining Date1")) # self.table.setItem(self.table.rowCount() - 1, 4, QTableWidgetItem("Salary1")) # self.table.setItem(self.table.rowCount() - 1, 5, QTableWidgetItem("Bonus1")) # self.table.setItem(self.table.rowCount() - 1, 6, QTableWidgetItem("Total Salary1")) # self.table.setItem(self.table.rowCount() - 1, 7, QTableWidgetItem("Edit1")) # self.table.setItem(self.table.rowCount() - 1, 8, QTableWidgetItem("Delete1")) data = self.load_tables_data() print(data) for x in data: print(x) self.populate_table(data) layout = QVBoxLayout() layout.addWidget(header) layout.addWidget(add_and_search) layout.addWidget(self.table) # layout.addStretch() layout.addWidget(footer) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) centralWidget = QWidget() centralWidget.setLayout(layout) self.setCentralWidget(centralWidget) self.setContentsMargins(0, 0, 0, 0) # self.resize(800, 600) self.setWindowTitle("Login") self.resize(1160, 605) self.show() self.center() def center(self): '''centers the window on the screen''' screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def getvalue(self, value): print(value) print(type(value)) if value == 1: self.hide() view = sidebar.Dashboard(self) elif value == 2: self.hide() view = sidebar.Employee(self) elif value == 3: pass elif value == 4: self.hide() view = sidebar.Reservations(self) elif value == 5: self.hide() view = sidebar.Category(self) elif value == 6: self.hide() view = sidebar.Settings(self) elif value == 7: self.hide() view = sidebar.Orders(self) elif value == 8: self.hide() view = sidebar.Menu(self) elif value == 9: self.hide() view = sidebar.Bill(self) def load_tables_data(self): query = "SELECT id, table_number, covers FROM tables;" result = self.db.fetch(query) return result ''' This function is called after an employee has been added and returns only the last row. ''' def add_update_tables_data(self): query = "SELECT id, table_number, covers FROM tables " \ "order by id desc limit 1;" result = self.db.fetch(query) return result def edit_tables(self): emp_row = self.table.indexAt(self.sender().pos()) id = int( self.table.cellWidget(emp_row.row(), emp_row.column()).objectName()) print(emp_row.row()) print(id) print(type(id)) ''' Get the data from the database for that user. ''' data = self.get_data(id) print("Data") print(data) # print(type(data[4])) view = AddTableDetails(self, "update", data[0]) view.tablenotextbox.setText(data[1]) view.covertextbox.setText(str(data[2])) view.closing.connect(self.editupdate_emp) def editupdate_emp(self, check): print("I am here") print(check) self.table.clearContents() self.table.setRowCount(0) data = self.load_tables_data() self.populate_table(data) # self.table.resizeColumnsToContents() def get_data(self, id): query = "SELECT id, table_number, covers FROM tables " \ "where id=%s" values = (id, ) result = self.db.fetch(query, values) for (id, table_number, covers) in result: id = id table_number = table_number covers = covers return [id, table_number, covers] def delete_tables(self): emp_row = self.table.indexAt(self.sender().pos()) # print(emp_row.row()) # print(emp_row.column()) # print(self.table.cellWidget(emp_row.row(), emp_row.column()).objectName()) id = int( self.table.cellWidget(emp_row.row(), emp_row.column()).objectName()) # print(id) # print(emp_row.child(emp_row.row(), emp_row.column())) query = "DELETE FROM tables WHERE id=%s" values = (id, ) try: result = self.db.execute(query, values) except: pass self.table.clearContents() self.table.setRowCount(0) data = self.load_tables_data() self.populate_table(data) def add_tables(self, where): if where == "tables": print("Category Button Clicked from tables") view = AddTableDetails(self, "add") view.closing.connect(self.update_tables) elif where == "stocks": print("Stock Button Clicked") def search_tables(self, search_obj): search = search_obj.text() search_obj.setText("") print("Search") if search != "": query = "SELECT * FROM tables WHERE table_number like %s" values = ("%" + search + "%", ) else: query = "SELECT * FROM tables" values = () self.table.clearContents() self.table.setRowCount(0) data = self.db.fetch(query, values) self.populate_table(data) ''' Repopulates the employee table with the updated data. ''' def update_tables(self, check): print("I am here") print(check) data = self.add_update_tables_data() self.populate_table(data) ''' This function populates the employee table with data. ''' def populate_table(self, data): for (id, table_number, covers) in data: self.table.insertRow(self.table.rowCount()) self.table.setItem(self.table.rowCount() - 1, 0, QTableWidgetItem(str(table_number))) self.table.setItem(self.table.rowCount() - 1, 1, QTableWidgetItem(str(covers))) edit = QPushButton(self.table) edit.setObjectName(str(id)) edit.setStyleSheet("background-color: rgb(50,205,50);") edit.setText("Edit") edit.adjustSize() edit.clicked.connect(self.edit_tables) self.table.setCellWidget(self.table.rowCount() - 1, 2, edit) delete = QPushButton(self.table) delete.setObjectName(str(id)) delete.setStyleSheet("background-color: #d63447;") delete.setText("Delete") delete.adjustSize() delete.clicked.connect(self.delete_tables) # delete.mousePressEvent = functools.partial(self.delete_emp, source_object=delete) self.table.setCellWidget(self.table.rowCount() - 1, 3, delete)
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.icon_path = 'resources\\warframe.ico' self.app_title = 'Warframe Prime Helper' self.company_name = 'Warframe Tools' self.settings = QSettings(self.company_name, self.app_title) self.setWindowTitle(self.app_title) self.market_api = None self.image_label = None self.image_label2 = None self.warframe_height = 1080 self.warframe_width = 1920 self.table = None self.mission_table = None self.slider_names = None self.sliders = None self.slider_labels = None self.slider_default_values = None self.slider_orig_values = None self.slider_values = None self.is_slider_max_set = False #self.plat_check_box = QCheckBox("Prefer platinum") #self.plat_check_box.setChecked(True) self.update_prices_button = None self.update_ducats_button = None self.update_prices_progress = None self.update_ducats_progress = None self.last_updated_prices_value = None self.last_updated_ducats_value = None self.num_parts_value = None self.latest_item_value = None self.move_to_top_check_box = None self.pause_button = None self.is_paused = False self.hide_crop_check_box = None self.hide_filter_check_box = None self.hide_fissure_check_box = None self.relics = None self.hide_relics = {} self.hidden_relics = set() self.hide_missions = {} self.hidden_missions = set() self.hide_missions_box = None self.mission_names = None self.crop_img = None self.filter_img = None self.dialog = None self.layout = None self.filled_rows = 0 self.max = -1 self.max_row = -1 self.ocr = None self.old_screenshot_shape = 0 self.old_filtered_shape = 0 self.missions = [] self.num_primes = 100 self.api = None self.prices_progress_lock = Lock() self.ducats_progress_lock = Lock() self.ducats_thread = None self.prices_thread = None self.timer = None self.init_image_labels() self.init_tables() self.init_sliders() self.init_dialog() self.set_layout() self.init_timer() self.show() #measured correct values self.setFixedSize(978, 617) def init_timer(self): self.timer = QTimer() self.timer.timeout.connect(self.update_mission_table_time) self.timer.start(1000) def init_image_labels(self): self.image_label = QLabel() image = QPixmap('temp\\crop_27.bmp') self.image_label.setPixmap(image) self.image_label2 = QLabel() self.image_label2.setPixmap(image) def set_layout(self): settings_button_box = self.make_settings_button_box() self.init_imgs() bot_box = self.make_bot_box() self.layout = QVBoxLayout() self.layout.setAlignment(Qt.AlignTop) self.layout.addSpacing(-12) self.layout.addLayout(settings_button_box) self.layout.addWidget(self.crop_img) self.layout.addWidget(self.filter_img) self.layout.addWidget(bot_box) self.setLayout(self.layout) def make_settings_button_box(self): settings_button = QPushButton() # Gear icon is from: https://iconscout.com/icon/gear-222 style_sheet = """ QPushButton { qproperty-icon: url(" "); qproperty-iconSize: 15px 15px; border-image: url("resources/Gear.svg"); background-color: rgba(255, 255, 255, 0); } QPushButton:hover { border-image: url("resources/SelectedGear.svg"); }""" settings_button.setStyleSheet(style_sheet) #settings_button.setStyleSheet("background-color: rgba(0, 0, 0, 255); font-size: 23px;") settings_button.clicked.connect(self.show_preferences) settings_button.setFixedWidth(30) settings_button.setFixedHeight(30) settings_button_hb = QHBoxLayout() settings_button_hb.setAlignment(Qt.AlignRight) settings_button_hb.addWidget(settings_button) settings_button_hb.addSpacing(-11) return settings_button_hb def make_bot_box(self): bot_layout = QHBoxLayout() bot_layout.addWidget(self.table) bot_layout.addWidget(self.mission_table) bot_box = QGroupBox() bot_box.setLayout(bot_layout) bot_box.setFixedHeight(287) return bot_box def init_dialog(self): crop_box = self.make_crop_box() filter_box = self.make_filter_box() other_box = self.make_other_box() settings_layout_1 = QVBoxLayout() settings_layout_1.addWidget(crop_box) settings_layout_1.addWidget(filter_box) settings_layout_1.addWidget(other_box) update_box = self.make_update_box() rate_box = self.make_rate_box() settings_layout_2 = QVBoxLayout() settings_layout_2.addWidget(update_box) settings_layout_2.addWidget(rate_box) hide_box = self.make_hide_box() hide_relics_box = self.make_hide_relics_box() button_box = self.make_button_box() settings_layout_3 = QVBoxLayout() settings_layout_3.addWidget(hide_box) settings_layout_3.addWidget(hide_relics_box) hide_missions_box = self.make_hide_missions_box() settings_layout_4 = QVBoxLayout() settings_layout_4.addWidget(hide_missions_box) settings_layout_4.addWidget(button_box) settings_layout = QHBoxLayout() settings_layout.addLayout(settings_layout_1) settings_layout.addLayout(settings_layout_2) settings_layout.addLayout(settings_layout_3) settings_layout.addLayout(settings_layout_4) self.dialog = QDialog() self.dialog.setWindowTitle("Preferences") self.dialog.setWindowModality(Qt.ApplicationModal) self.dialog.setLayout(settings_layout) def make_button_box(self): button_box = QDialogButtonBox() button_box.setOrientation(Qt.Horizontal) button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) button_box.accepted.connect(self.save_settings) button_box.rejected.connect(self.load_settings) return button_box def load_settings(self): self.settings.sync() slider_orig_values = {'x': 521, 'y': 400, 'w': 908, 'h': 70, 'v1': 197, 'v2': 180, 'd': 4, 'Screencap (hz)': 1, 'Fissure (s)': 30, 'API Threads': 4} self.slider_default_values = {} slider_default_max = {'x': self.warframe_width/2, 'y': self.warframe_height/2, 'w': self.warframe_width, 'h': self.warframe_height, 'v1': 255, 'v2': 255, 'd': 40} for slider_name in self.slider_names: self.slider_default_values[slider_name] = self.settings.value(slider_name,defaultValue=slider_orig_values[slider_name]) if len(slider_name) <= 2: max_val = self.settings.value("{}_max".format(slider_name), defaultValue=slider_default_max[slider_name], type=int) self.sliders[slider_name].setMaximum(max_val) self.sliders[slider_name].setValue(self.slider_default_values[slider_name]) prices = self.settings.value("last_updated_prices_value", defaultValue="Never", type=str) ducats = self.settings.value("last_updated_ducats_value", defaultValue="Never", type=str) num_parts = self.settings.value("num_parts_value", defaultValue=350, type=int) latest_item = self.settings.value("latest_item_value", defaultValue="", type=str) self.last_updated_prices_value.setText(prices) self.last_updated_ducats_value.setText(ducats) self.num_parts_value.setNum(num_parts) self.latest_item_value.setText(latest_item) for relic in self.relics: checked = self.settings.value("hide_{}".format(relic), defaultValue=False,type=bool) self.hide_relics[relic].setChecked(checked) if checked: self.set_hidden_relic(relic) for mission in self.mission_names: checked = self.settings.value("hide_{}".format(mission), defaultValue=False, type=bool) self.hide_missions[mission].setChecked(checked) if checked: self.set_hidden_mission(mission) if self.settings.value("toggle_fissure_table", defaultValue=False, type=bool): self.hide_fissure_check_box.setChecked(True) self.toggle_fissure_table() if self.settings.value("toggle_move_to_top", defaultValue=False, type=bool): self.move_to_top_check_box.setChecked(True) self.toggle_move_to_top() if self.settings.value("toggle_cropped_img", defaultValue=False, type=bool): self.hide_crop_check_box.setChecked(True) self.toggle_cropped_img() if self.settings.value("toggle_filtered_img", defaultValue=False, type=bool): self.hide_filter_check_box.setChecked(True) self.toggle_filtered_img() self.dialog.close() def save_settings(self): for slider_name in self.slider_names: self.settings.setValue(slider_name, self.sliders[slider_name].value()) for relic in self.relics: self.settings.setValue("hide_{}".format(relic), self.hide_relics[relic].isChecked()) for mission in self.mission_names: self.settings.setValue("hide_{}".format(mission), self.hide_missions[mission].isChecked()) self.settings.setValue("toggle_fissure_table", self.hide_fissure_check_box.isChecked()) self.settings.setValue("toggle_move_to_top", self.move_to_top_check_box.isChecked()) self.settings.setValue("toggle_cropped_img", self.hide_crop_check_box.isChecked()) self.settings.setValue("toggle_filtered_img", self.hide_filter_check_box.isChecked()) self.dialog.close() self.settings.sync() def init_imgs(self): self.crop_img = QGroupBox("Crop") crop_img_layout = QVBoxLayout() crop_img_layout.addWidget(self.image_label) self.crop_img.setLayout(crop_img_layout) self.filter_img = QGroupBox("Filtered") filter_img_layout = QVBoxLayout() filter_img_layout.addWidget(self.image_label2) self.filter_img.setLayout(filter_img_layout) def make_hide_missions_box(self, missions=None): if self.hide_missions_box is None: self.hide_missions_box = QGroupBox("Hide Missions") if missions is not None: hide_missions_layout = QGridLayout() hide_missions_layout.setColumnStretch(2, 2) hide_missions_layout.setAlignment(Qt.AlignTop) hide_missions_layout.setContentsMargins(0, 0, 0, 0) skip_missions = ["MT_SECTOR", "MT_PVP", "MT_LANDSCAPE", "MT_EVACUATION", "MT_ASSASSINATION", "MT_ARENA"] seen_missions = set() i = 0 for mission in missions: mission_name = missions[mission]['value'] if mission_name == "Extermination": mission_name = "Exterminate" if mission not in skip_missions and mission_name not in seen_missions: self.hide_missions[mission_name] = QCheckBox(mission_name) self.hide_missions[mission_name].setChecked(False) self.hide_missions[mission_name].stateChanged.connect(partial(self.set_hidden_mission, mission_name)) hide_missions_layout.addWidget(self.hide_missions[mission_name], int(i/2), i % 2) i += 1 seen_missions.add(mission_name) self.hide_missions_box.setLayout(hide_missions_layout) self.mission_names = list(seen_missions) self.load_settings() return self.hide_missions_box def set_hidden_mission(self, mission): if self.hide_missions[mission].isChecked(): self.hidden_missions.add(mission) else: self.hidden_missions.remove(mission) self.update_mission_table_hidden() def make_hide_relics_box(self): hide_relics_layout = QVBoxLayout() hide_relics_layout.setAlignment(Qt.AlignTop) hide_relics_layout.setContentsMargins(0, 0, 0, 0) self.relics = ["Axi", "Neo", "Meso", "Lith", "Requiem"] for relic in self.relics: self.hide_relics[relic] = QCheckBox(relic) self.hide_relics[relic].setChecked(False) self.hide_relics[relic].stateChanged.connect(partial(self.set_hidden_relic, relic)) hide_relics_layout.addWidget(self.hide_relics[relic]) hide_relics_box = QGroupBox("Hide Relics") hide_relics_box.setLayout(hide_relics_layout) return hide_relics_box def make_hide_box(self): hide_layout = QVBoxLayout() hide_layout.setAlignment(Qt.AlignTop) hide_layout.setContentsMargins(0, 0, 0, 0) self.hide_crop_check_box = QCheckBox("Hide Crop") self.hide_crop_check_box.setChecked(False) self.hide_crop_check_box.stateChanged.connect(self.toggle_cropped_img) hide_layout.addWidget(self.hide_crop_check_box) self.hide_filter_check_box = QCheckBox("Hide Filtered") self.hide_filter_check_box.setChecked(False) self.hide_filter_check_box.stateChanged.connect(self.toggle_filtered_img) hide_layout.addWidget(self.hide_filter_check_box) self.hide_fissure_check_box = QCheckBox("Hide Fissure Table") self.hide_fissure_check_box.setChecked(False) self.hide_fissure_check_box.stateChanged.connect(self.toggle_fissure_table) hide_layout.addWidget(self.hide_fissure_check_box) hide_box = QGroupBox("Hide UI") hide_box.setLayout(hide_layout) return hide_box def make_rate_box(self): rate_grid = QGridLayout() rate_grid.setColumnStretch(3, 3) rate_grid.setContentsMargins(0, 0, 0, 0) for i in range(3): slider_name = self.slider_names[i + 7] rate_grid.addWidget(self.slider_labels[slider_name], i, 0) rate_grid.addWidget(self.slider_values[slider_name], i, 1) rate_grid.addWidget(self.sliders[slider_name], i, 2) rate_box = QGroupBox("Rates") rate_box.setLayout(rate_grid) return rate_box def make_other_box(self): self.move_to_top_check_box = QCheckBox("Bring to front") self.move_to_top_check_box.setChecked(True) self.move_to_top_check_box.stateChanged.connect(self.toggle_move_to_top) self.pause_button = QPushButton("Pause") self.pause_button.clicked.connect(self.toggle_button) self.is_paused = False other_layout = QVBoxLayout() other_layout.setAlignment(Qt.AlignTop) other_layout.setContentsMargins(0, 0, 0, 0) other_layout.addWidget(self.move_to_top_check_box) other_layout.addWidget(self.pause_button) other_box = QGroupBox("Other") other_box.setLayout(other_layout) return other_box def make_filter_box(self): filter_grid = QGridLayout() filter_grid.setColumnStretch(3, 3) filter_grid.setAlignment(Qt.AlignTop) filter_grid.setContentsMargins(0, 0, 0, 0) for i in range(3): slider_name = self.slider_names[i + 4] filter_grid.addWidget(self.slider_labels[slider_name], i, 0) filter_grid.addWidget(self.slider_values[slider_name], i, 1) filter_grid.addWidget(self.sliders[slider_name], i, 2) filter_box = QGroupBox("Filter Parameters") filter_box.setLayout(filter_grid) return filter_box def make_crop_box(self): crop_grid = QGridLayout() crop_grid.setColumnStretch(3, 4) crop_grid.setAlignment(Qt.AlignTop) crop_grid.setContentsMargins(0, 0, 0, 0) for i in range(4): slider_name = self.slider_names[i] crop_grid.addWidget(self.slider_labels[slider_name], i, 0) crop_grid.addWidget(self.slider_values[slider_name], i, 1) crop_grid.addWidget(self.sliders[slider_name], i, 2) crop_box = QGroupBox("Crop Parameters") crop_box.setLayout(crop_grid) return crop_box def make_update_box(self): update_layout = QGridLayout() update_layout.setColumnStretch(4, 2) update_layout.setAlignment(Qt.AlignTop) update_layout.setContentsMargins(0, 0, 0, 0) self.update_prices_button = QPushButton("Update Prices") self.update_prices_button.clicked.connect(self.update_prices) self.update_prices_progress = QProgressBar() self.update_prices_progress.setFixedWidth(110) self.update_prices_progress.setRange(0, 100) update_layout.addWidget(self.update_prices_button, 0, 0) update_layout.addWidget(self.update_prices_progress, 0, 1) self.update_ducats_button = QPushButton("Update Ducats") self.update_ducats_button.clicked.connect(self.update_ducats) self.update_ducats_progress = QProgressBar() self.update_ducats_progress.setFixedWidth(110) self.update_ducats_progress.setRange(0, 100) update_layout.addWidget(self.update_ducats_button, 1, 0) update_layout.addWidget(self.update_ducats_progress, 1, 1) last_updated_prices_label = QLabel("Prices Updated") prices = self.settings.value("last_updated_prices_value", defaultValue="Never", type=str) ducats = self.settings.value("last_updated_ducats_value", defaultValue="Never", type=str) num_parts = self.settings.value("num_parts_value", defaultValue=350, type=str) latest_item = self.settings.value("latest_item_value", defaultValue="", type=str) self.last_updated_prices_value = QLabel(prices) self.last_updated_ducats_value = QLabel(ducats) self.num_parts_value = QLabel(num_parts) self.latest_item_value = QLabel(latest_item) update_layout.addWidget(last_updated_prices_label, 2, 0) update_layout.addWidget(self.last_updated_prices_value, 2, 1) last_updated_ducats_label = QLabel("Ducats Updated") update_layout.addWidget(last_updated_ducats_label, 3, 0) update_layout.addWidget(self.last_updated_ducats_value, 3, 1) num_parts_label = QLabel("Prime Parts") update_layout.addWidget(num_parts_label, 4, 0) update_layout.addWidget(self.num_parts_value, 4, 1) latest_item_label = QLabel("Latest Prime") update_layout.addWidget(latest_item_label, 5, 0) update_layout.addWidget(self.latest_item_value, 5, 1) update_box = QGroupBox("Updates") update_box.setLayout(update_layout) return update_box def init_sliders(self): self.slider_names = ['x', 'y', 'w', 'h', 'v1', 'v2', 'd', 'Screencap (hz)', 'Fissure (s)', 'API Threads'] self.sliders = {x: QSlider(Qt.Horizontal) for x in self.slider_names} self.slider_labels = {x: QLabel(x) for x in self.slider_names} self.slider_default_values = {} self.slider_orig_values = {'x': 521, 'y': 400, 'w': 908, 'h': 70, 'v1': 197, 'v2': 180, 'd': 4, 'Screencap (hz)': 1, 'Fissure (s)': 30, 'API Threads': 4} for slider_name in self.slider_names: self.slider_default_values[slider_name] = self.settings.value(slider_name, defaultValue=self.slider_orig_values[slider_name]) self.slider_values = {x: QLabel(str(self.slider_default_values[x])) for x in self.slider_names} self.slider_values['Screencap (hz)'].setNum(self.slider_default_values['Screencap (hz)']/4) self.slider_values['d'].setNum(self.slider_default_values['d'] / 4) self.slider_labels['d'].setText('\u0394') self.sliders['x'].setMaximum(int(self.warframe_width / 2)) self.sliders['y'].setMaximum(int(self.warframe_height / 2)) self.sliders['w'].setMaximum(self.warframe_width) self.sliders['h'].setMaximum(self.warframe_height) self.sliders['v1'].setMaximum(255) self.sliders['v2'].setMaximum(255) self.sliders['d'].setMaximum(40) self.sliders['Screencap (hz)'].setMaximum(20) self.sliders['Screencap (hz)'].setMinimum(1) self.sliders['Fissure (s)'].setMaximum(60) self.sliders['Fissure (s)'].setMinimum(10) self.sliders['API Threads'].setMaximum(10) self.sliders['API Threads'].setMinimum(2) for slider_name in self.slider_names: if len(slider_name) <= 2: self.sliders[slider_name].setMinimum(0) self.sliders[slider_name].setSingleStep(1) self.slider_values[slider_name].setFixedWidth(35) self.sliders[slider_name].setValue(self.slider_default_values[slider_name]) def init_tables(self): self.table = QTableWidget(7, 3) self.table.setHorizontalHeaderLabels(['Prime Part', 'Plat', 'Ducats']) self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) header = self.table.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.Stretch) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) self.mission_table = QTableWidget(30, 4) self.mission_table.setHorizontalHeaderLabels(['Relic', 'Mission', 'Type', 'Time Left']) self.mission_table.setEditTriggers(QAbstractItemView.NoEditTriggers) mission_header = self.mission_table.horizontalHeader() for i in range(4): mission_header.setSectionResizeMode(i, QHeaderView.Interactive) mission_header.resizeSection(0, 55) mission_header.resizeSection(1, 150) mission_header.resizeSection(2, 90) mission_header.resizeSection(3, 60) self.mission_table.setFixedWidth(405) def update_prices(self): self.prices_thread = threading.Thread(name="prices_thread", target=self.market_api.update_prices) self.prices_thread.start() self.update_prices_button.setEnabled(False) self.update_ducats_button.setEnabled(False) def update_ducats(self): self.ducats_thread = threading.Thread(name="ducats_thread", target=self.market_api.update_ducats) self.ducats_thread.start() self.update_prices_button.setEnabled(False) self.update_ducats_button.setEnabled(False) def update_primes_info(self, num, latest): self.num_parts_value.setNum(num) self.latest_item_value.setText(latest) self.update_prices_progress.setMaximum(num) self.update_ducats_progress.setMaximum(num) self.num_primes = num def get_datetime(self): return datetime.now().strftime("%b %d %Y %H:%M:%S") def update_ducats_time(self): self.last_updated_ducats_value.setText(self.get_datetime()) self.ducats_progress_lock.acquire() self.update_ducats_progress.setValue(self.num_primes) self.ducats_progress_lock.release() self.settings.setValue("last_updated_ducats_value", self.last_updated_ducats_value.text()) self.settings.setValue("num_parts_value", self.num_parts_value.text()) self.settings.setValue("latest_item_value", self.latest_item_value.text()) def update_prices_time(self): self.last_updated_prices_value.setText(self.get_datetime()) self.prices_progress_lock.acquire() self.update_prices_progress.setValue(self.num_primes) self.prices_progress_lock.release() self.settings.setValue("last_updated_prices_value", self.last_updated_prices_value.text()) self.settings.setValue("num_parts_value", self.num_parts_value.text()) self.settings.setValue("latest_item_value", self.latest_item_value.text()) def set_update_prices_progress(self, val): if self.prices_progress_lock.acquire(): self.update_prices_progress.setValue(val) self.prices_progress_lock.release() def set_update_ducats_progress(self, val): if self.ducats_progress_lock.acquire(): self.update_ducats_progress.setValue(val) self.ducats_progress_lock.release() def finished_update_progress(self): self.update_prices_button.setEnabled(True) self.update_ducats_button.setEnabled(True) def show_preferences(self): self.dialog.exec_() self.load_settings() def toggle_fissure_table(self): if self.hide_fissure_check_box.isChecked(): self.mission_table.hide() else: self.mission_table.show() self.setFixedSize(self.layout.sizeHint()) def toggle_move_to_top(self): self.ocr.set_move_to_top(self.move_to_top_check_box.isChecked()) def toggle_cropped_img(self): if self.hide_crop_check_box.isChecked(): self.crop_img.hide() else: self.crop_img.show() self.setFixedSize(self.layout.sizeHint()) def toggle_filtered_img(self): if self.hide_filter_check_box.isChecked(): self.filter_img.hide() else: self.filter_img.show() self.setFixedSize(self.layout.sizeHint()) #print("{}h,{}w".format(self.frameGeometry().height(),self.frameGeometry().width())) def set_sliders_range(self, x, y): max_values = {'x': int(x/2), 'y': int(y/2), 'w':x, 'h':y} for slider_name in max_values: self.sliders[slider_name].setMaximum(max_values[slider_name]) self.sliders[slider_name].setValue(self.slider_default_values[slider_name]) self.settings.setValue("{}_max", max_values[slider_name]) def toggle_button(self): self.is_paused = not self.is_paused if self.is_paused: self.pause_button.setText("Resume") else: self.pause_button.setText("Pause") if self.ocr is not None: if self.is_paused: self.ocr.save_screenshot() self.ocr.skip_screenshot = True else: self.ocr.skip_screenshot = False def clear_table(self): self.table.clearSelection() self.table.clearContents() self.filled_rows = 0 #self.table.setRowCount(self.filled_rows) def is_plat_preferred(self): return self.plat_check_box.isChecked() def insert_table_row(self, row): for i in range(3): self.table.setItem(self.filled_rows, i, QTableWidgetItem(str(row[i]))) self.filled_rows = self.filled_rows + 1 #self.table.setRowCount(self.filled_rows) def update_mission_table(self, missions): self.missions = list(missions) cur_time = time.time() for i in range(len(missions)): for j in range(3): self.mission_table.setItem(i, j, QTableWidgetItem(str(self.missions[i][j]))) self.mission_table.setItem(i, 3, QTableWidgetItem(self.get_duration_str(self.missions[i][3]-cur_time))) if self.missions[i][0] in self.hidden_relics: self.mission_table.setRowHidden(i, True) if self.missions[i][2] in self.hidden_missions: self.mission_table.setRowHidden(i, True) else: self.mission_table.setRowHidden(i, False) self.mission_table.setRowCount(len(self.missions)-1) def update_mission_table_time(self): cur_time = time.time() needs_update = False for i in range(len(self.missions)): self.mission_table.setItem(i, 3, QTableWidgetItem(self.get_duration_str(self.missions[i][3]-cur_time))) if self.missions[i][3]-cur_time < 0: needs_update = True if needs_update: self.api.filter_expired_missions() def update_mission_table_hidden(self): for i in range(len(self.missions)): if self.missions[i][0] in self.hidden_relics: self.mission_table.setRowHidden(i, True) elif self.missions[i][2] in self.hidden_missions: self.mission_table.setRowHidden(i, True) else: self.mission_table.setRowHidden(i, False) def get_duration_str(self, duration): m, s = divmod(int(duration), 60) h, m = divmod(m, 60) return '{:d}:{:02d}:{:02d}'.format(h, m, s) def set_ocr_connection(self, ocr): for slider_name in self.slider_names: self.sliders[slider_name].valueChanged.connect(partial(self.set_ocr_crop, ocr, slider_name)) self.ocr = ocr self.market_api = MarketReader(ocr=self.ocr, gui=self) def set_api(self, wf_api): self.api = wf_api self.make_hide_missions_box(self.api.mission_types) def set_hidden_relic(self, relic): if self.hide_relics[relic].isChecked(): self.hidden_relics.add(relic) else: self.hidden_relics.remove(relic) self.update_mission_table_hidden() def set_ocr_crop(self, ocr, dim, val): if dim == 'Screencap (hz)' or dim == 'd': val = val / 4 self.slider_values[dim].setNum(val) if val < 0 or val > 100000 or val is None: return if dim == 'x': ocr.set_x_offset(val) if dim == 'y': ocr.set_y_offset(val) if dim == 'w': ocr.set_w(val) if dim == 'h': ocr.set_h(val) if dim == 'v1': ocr.set_v1(val) if dim == 'v2': ocr.set_v2(val) if dim == 'd': self.ocr.set_diff_threshold(val/4) if dim == 'Screencap (hz)': ocr.set_interval(1/val) if dim == 'Fissure (s)': self.api.set_rate(val) if dim == 'API Threads': self.market_api.set_num_threads(val) #def select_max(self): # # TODO doesnt work # self.table.clearSelection() # self.table.selectRow(self.max_row) def update_filtered(self, filtered): filtered_shape = None if not self.hide_filter_check_box.isChecked(): filtered_shape = filtered.shape h, w = filtered.shape bytes_per_line = w filtered_pix = QPixmap(QImage(filtered, w, h, bytes_per_line, QImage.Format_Grayscale8)) filtered_pix = filtered_pix.scaled(908, 70, Qt.KeepAspectRatio) self.image_label2.setPixmap(filtered_pix) #self.update_window_size(None, filtered_shape) def update_screenshot(self, screenshot): screenshot_shape = None if not self.hide_crop_check_box.isChecked(): screenshot_shape = screenshot.shape h, w, ch = screenshot.shape bytes_per_line = ch * w screenshot_pix = QPixmap(QImage(screenshot, w, h, bytes_per_line, QImage.Format_RGB888)) screenshot_pix = screenshot_pix.scaled(908, 70, Qt.KeepAspectRatio) self.image_label.setPixmap(screenshot_pix) #self.update_window_size(screenshot_shape, None) def update_window_size(self, screenshot_shape, filtered_shape): should_update = False if screenshot_shape is not None and screenshot_shape == self.old_screenshot_shape: self.old_screenshot_shape = screenshot_shape should_update = True if filtered_shape is not None and filtered_shape == self.old_filtered_shape: self.old_filtered_shape = filtered_shape should_update = True if should_update: self.setFixedSize(self.layout.sizeHint()) def __exit__(self): self.market_api.exit_now = True self.ocr.exit_now = True
class Ui_MainWindow(object): def setupUi(self, MainWindow): self.conn = pymysql.connect(host='localhost', port=3306, user='******', password='', db='') self.cur = self.conn.cursor() self.sqlString = "select * from student where " MainWindow.setObjectName('MainWindow') MainWindow.resize(760, 440) MainWindow.setFixedSize(MainWindow.width(), MainWindow.height()) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName('centralwidget') self.frame = QFrame(self.centralwidget) self.frame.setGeometry(QtCore.QRect(10, 10, 491, 121)) self.frame.setFrameShape(QFrame.StyledPanel) self.frame.setFrameShadow(QFrame.Raised) self.frame.setObjectName('frame') self.check_sid = QCheckBox(self.frame) self.check_sid.setGeometry(QtCore.QRect(20, 10, 71, 16)) self.check_sid.setObjectName('check_sid') # self.check_sage = QCheckBox(self.frame) # self.check_sage.setGeometry(QtCore.QRect(20, 70, 71, 16)) # self.check_sage.setObjectName("check_Sage") self.check_sname = QCheckBox(self.frame) self.check_sname.setGeometry(QtCore.QRect(20, 40, 71, 16)) self.check_sname.setObjectName('check_sname') self.check_sgender = QCheckBox(self.frame) self.check_sgender.setGeometry(QtCore.QRect(20, 100, 71, 16)) self.check_sgender.setObjectName('check_sgender') self.sid = QLineEdit(self.frame) self.sid.setGeometry(QtCore.QRect(90, 10, 113, 16)) self.sid.setObjectName('sid') self.sname = QLineEdit(self.frame) self.sname.setGeometry(QtCore.QRect(90, 40, 113, 16)) self.sname.setObjectName("sname") # self.first_sage = QLineEdit(self.frame) # self.first_sage.setGeometry(QtCore.QRect(90, 70, 41, 16)) # self.first_sage.setObjectName("first_sage") self.sgender = QLineEdit(self.frame) self.sgender.setGeometry(QtCore.QRect(90, 100, 113, 16)) self.sgender.setObjectName("sgender") self.label = QLabel(self.frame) self.label.setGeometry(QtCore.QRect(140, 70, 16, 16)) self.label.setObjectName('label') self.check_sdept = QCheckBox(self.frame) self.check_sdept.setGeometry(QtCore.QRect(270, 40, 71, 16)) self.check_sdept.setObjectName("check_sdept") self.sdept = QLineEdit(self.frame) self.sdept.setGeometry(QtCore.QRect(340, 40, 113, 16)) self.sdept.setObjectName("sdept") self.sclass = QLineEdit(self.frame) self.sclass.setGeometry(QtCore.QRect(340, 10, 113, 16)) self.sclass.setObjectName("sclass") self.check_sclass = QCheckBox(self.frame) self.check_sclass.setGeometry(QtCore.QRect(270, 10, 71, 16)) self.check_sclass.setObjectName("check_sclass") self.find = QPushButton(self.frame) self.find.setGeometry(QtCore.QRect(380, 100, 75, 21)) self.find.setObjectName('find') self.find.clicked.connect(self.find_btn) self.sql_out = QTextBrowser(self.centralwidget) self.sql_out.setGeometry(QtCore.QRect(10, 140, 740, 61)) self.sql_out.setObjectName('sql_out') self.result_out = QTableWidget(self.centralwidget) self.result_out.setEditTriggers(QAbstractItemView.NoEditTriggers) self.result_out.setGeometry(QtCore.QRect(10, 210, 740, 171)) self.result_out.setObjectName('result_out') self.result_out.setColumnCount(5) self.result_out.setRowCount(5) self.result_out.resizeColumnsToContents() self.result_out.resizeRowsToContents() item = QTableWidgetItem() self.result_out.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() self.result_out.setHorizontalHeaderItem(1, item) item = QTableWidgetItem() self.result_out.setHorizontalHeaderItem(2, item) item = QTableWidgetItem() self.result_out.setHorizontalHeaderItem(3, item) item = QTableWidgetItem() self.result_out.setHorizontalHeaderItem(4, item) self.result_out.horizontalHeader().setDefaultSectionSize(100) self.result_out.horizontalHeader().setMinimumSectionSize(25) self.result_out.verticalHeader().setDefaultSectionSize(30) self.pushButton_2 = QPushButton(self.centralwidget) self.pushButton_2.setGeometry(QtCore.QRect(675, 390, 75, 21)) self.pushButton_2.setObjectName("pushButton_2") self.pushButton_2.clicked.connect(self.p2_clicked) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 509, 23)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def p2_clicked(self): self.pyqt_clicked1.emit() def find_btn(self): self.pyqt_clicked2.emit() def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) self.check_sid.setText(_translate("MainWindow", "学号", None)) # self.check_Sage.setText(_translate("MainWindow", "年龄自", None)) self.check_sname.setText(_translate("MainWindow", "姓名", None)) self.check_sgender.setText(_translate("MainWindow", "性别", None)) # self.label.setText(_translate("MainWindow", "到", None)) self.check_sdept.setText(_translate("MainWindow", "方向", None)) self.check_sclass.setText(_translate("MainWindow", "班级", None)) self.find.setText(_translate("MainWindow", "查询", None)) self.sql_out.setText(self.sqlString) item = self.result_out.horizontalHeaderItem(0) item.setText(_translate("MainWindow", "学号", None)) item = self.result_out.horizontalHeaderItem(1) item.setText(_translate("MainWindow", "姓名", None)) item = self.result_out.horizontalHeaderItem(2) item.setText(_translate("MainWindow", "性别", None)) item = self.result_out.horizontalHeaderItem(3) item.setText(_translate("MainWindow", "班级", None)) item = self.result_out.horizontalHeaderItem(4) item.setText(_translate("MainWindow", "专业方向", None)) self.pushButton_2.setText(_translate("MainWindow", "退出", None)) def mousePressEvent(self, event): print(">_<") def buttonTest(self): temp_sqlstring = self.sqlString is_first = True if self.check_sid.isChecked(): mystr = self.sid.text() if is_first: is_first = False if mystr.find("%") == -1: temp_sqlstring += "sid='" + self.sid.text() + "'" else: temp_sqlstring += "sid like'" + self.sid.text() + "'" else: if mystr.find("%") == -1: temp_sqlstring += " and sid = '" + self.sid.text() + "'" else: temp_sqlstring += " and sid like '" + self.sid.text() + "'" if self.check_sname.isChecked(): if is_first: mystr = self.sname.text() is_first = False if mystr.find("%") == -1: temp_sqlstring += "sname = '" + self.sname.text() + "'" else: temp_sqlstring += "sname like '" + self.sname.text() + "'" else: if mystr.find("%") == -1: temp_sqlstring += " and sname = '" + self.sname.text( ) + "'" else: temp_sqlstring += " and sname like '" + self.sname.text( ) + "'" if self.check_sgender.isChecked(): if is_first: is_first = False temp_sqlstring += "sgender = '" + self.sgender.text() + "'" else: temp_sqlstring += " and sgender = '" + self.sgender.text( ) + "'" if self.check_sclass.isChecked(): if is_first: mystr = self.sclass.text() is_first = False if mystr.find("%") == -1: temp_sqlstring += "sclass = '" + self.sclass.text() + "'" else: temp_sqlstring += "sclass like '" + self.sclass.text( ) + "'" else: if mystr.find("%") == -1: temp_sqlstring += " and sclass = '" + self.sclass.text( ) + "'" else: temp_sqlstring += " and sclass like '" + self.sclass.text( ) + "'" if self.check_sdept.isChecked(): if is_first: mystr = self.sdept.text() is_first = False if mystr.find("%") == -1: temp_sqlstring += "sdept = '" + self.sdept.text() + "'" else: temp_sqlstring += "sdept like '" + self.sdept.text() + "'" else: if mystr.find("%") == -1: temp_sqlstring += " and sdept = '" + self.sdept.text( ) + "'" else: temp_sqlstring += " and sdept like '" + self.sdept.text( ) + "'" self.result_out.clearContents() if not (is_first): print(temp_sqlstring) self.cur.execute(temp_sqlstring) k = 0 for i in self.cur: print("------------", i) w = 0 for j in i: if type(j) == int: newItem = QTableWidgetItem(str(j)) else: newItem = QTableWidgetItem(j) self.result_out.setItem(k, w, newItem) w += 1 k += 1 self.sql_out.setText("") self.sql_out.append(temp_sqlstring) print("find button pressed") def buttonExit(self): self.conn.commit() self.cur.close() self.conn.close() self.close() def keyPressEvent(self, e): if e.key() == QtCore.Qt.key_Escape: self.buttonExit()
class CrawlWindow(QWidget): def __init__(self): super(CrawlWindow, self).__init__() self.resize(1000, 600) self.setWindowTitle('关键词新闻搜索') self.setWindowIcon(QIcon(':reson/4.jpg')) # 初始化搜索文本框 self.movie_name = QLineEdit(self) # 初始化渠道下拉框 self.source_combobox = QComboBox(self) # 初始化一键搜索按钮 self.start_btn = QPushButton(self) # 初始化开始爬取按钮 self.get_btn = QPushButton(self) # 初始化一键分析按钮 self.word_cloud = QPushButton(self) # 初始化另存下拉框 self.save_combobox = QComboBox(self) # 初始化表格控件 self.table = QTableWidget(self) # 初始化输出文本框 self.log_browser = QTextBrowser(self) # 初始化进度条 self.progressbar = QProgressBar(self) # 初始化水平布局 self.h_layout = QHBoxLayout() # 初始化垂直布局 self.v_layout = QVBoxLayout() # 实例化词云程序 self.cloud = Cloud() # 实例化启动程序 self.crawl_thread = CrawlThread() # 初始化数据库 self.db = None # 初始化音频播放 self.btn_sound = QSound(':reson/btn.wav', self) self.finish_sound = QSound(':reson/finish.wav', self) # 实例化 self.movie_init() self.source_init() self.btn_init() self.combobox_init() self.table_init() self.word_cloud_init() self.log_init() self.progressbar_init() self.layout_init() self.crawl_init() # self.db_connect() def movie_init(self): """搜索文本框默认配置""" # 设置文本框尺寸 self.movie_name.setFixedSize(200, 25) # 设置默认文本 self.movie_name.setPlaceholderText("请输入关键词,不超过十个中文") # 限制10个中文字符 self.movie_name.setMaxLength(10) def source_init(self): """搜索渠道下拉框配置""" save_list = ['搜索渠道选择', '新华网', '新浪新闻', '百度新闻'] self.source_combobox.addItems(save_list) # 设置标签状态为可用 self.source_combobox.setEnabled(True) # 当下拉索引发生改变时发射信号触发绑定的事件 # self.source_combobox.currentTextChanged.connect(self.combobox_slot) def btn_init(self): self.start_btn.setText('一键搜索') self.get_btn.setText('开始爬取') self.get_btn.setEnabled(False) self.start_btn.clicked.connect(lambda: self.btn_slot(self.start_btn)) self.get_btn.clicked.connect(lambda: self.btn_slot(self.get_btn)) # TODO def word_cloud_init(self): """一键分析配置""" self.word_cloud.setText('一键分析') self.word_cloud.setEnabled(False) self.word_cloud.clicked.connect(self.word_cloud_slot) def combobox_init(self): """另存为下拉框配置""" save_list = ['另存为', 'MySQL', 'csv', 'txt', 'json'] self.save_combobox.addItems(save_list) # 设置标签状态为不可用 self.save_combobox.setEnabled(False) # 当下拉索引发生改变时发射信号触发绑定的事件 self.save_combobox.currentTextChanged.connect(self.combobox_slot) # 1 def table_init(self): self.table.setColumnCount(5) self.table.setHorizontalHeaderLabels(['新闻链接', '新闻摘要', '评论信息', '渠道来源', '发布日期']) self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) def log_init(self): """输出文本框配置""" # 设置盒子尺寸 self.log_browser.setMaximumHeight(150) def progressbar_init(self): """进度条""" self.progressbar.setRange(0, 10) self.progressbar.setValue(0) def layout_init(self): """页面布局""" self.h_layout.addWidget(self.movie_name) self.h_layout.addWidget(self.source_combobox) self.h_layout.addWidget(self.start_btn) self.h_layout.addWidget(self.get_btn) self.h_layout.addWidget(self.word_cloud) self.h_layout.addWidget(self.save_combobox) self.v_layout.addWidget(self.table) self.v_layout.addWidget(self.log_browser) self.v_layout.addWidget(self.progressbar) self.v_layout.addLayout(self.h_layout) self.setLayout(self.v_layout) def crawl_init(self): self.crawl_thread.total_nums.connect(self.total_nums_slot) self.crawl_thread.finished_signal.connect(self.finish_slot) self.crawl_thread.log_signal.connect(self.set_log_slot) self.crawl_thread.result_signal.connect(self.set_table_slot) def btn_slot(self, btn): self.btn_sound.play() # 点击一键搜索 if btn == self.start_btn: # 判断是否输入关键词 if self.movie_name.text(): self.log_browser.clear() self.log_browser.append('<font color="red">一键搜索</font>') self.log_browser.append('<font color="red">搜索中...</font>') self.table.clearContents() self.table.setRowCount(0) self.get_btn.setEnabled(True) self.save_combobox.setEnabled(False) self.crawl_thread.render(self.movie_name, self.source_combobox) self.crawl_thread.start() else: self.log_browser.append('<font color="red">请输入搜索关键词!</font>') if btn == self.get_btn: self.log_browser.append('<font color="red">开始爬取</font>') self.get_btn.setEnabled(False) self.start_btn.setEnabled(True) self.word_cloud.setEnabled(True) self.save_combobox.setEnabled(True) self.run() def word_cloud_slot(self): self.cloud.run() def total_nums_slot(self, total_nums): """搜索到新闻数""" total_nums = '本次搜索总找到新闻:{}条'.format(total_nums) self.log_browser.append(total_nums) def finish_slot(self): self.start_btn.setEnabled(True) self.get_btn.setEnabled(False) self.save_combobox.setEnabled(True) def set_log_slot(self, new_log): self.log_browser.append(new_log) def set_table_slot(self, img, summary, name, star, time): row = self.table.rowCount() self.table.insertRow(row) self.table.setItem(row, 0, QTableWidgetItem(img)) self.table.setItem(row, 1, QTableWidgetItem(summary)) self.table.setItem(row, 2, QTableWidgetItem(name)) self.table.setItem(row, 3, QTableWidgetItem(star)) self.table.setItem(row, 4, QTableWidgetItem(time)) def combobox_slot(self, text): if text == 'MySQL': # self.save_to_MySQL() pass elif text == 'csv': self.save_to_csv() elif text == 'txt': self.save_to_txt() elif text == 'json': self.save_to_json() # def db_connect(self): # """ # SQL配置 # db = QtSql.QSqlDatabase.addDatabase('QMYSQL') # db.setHostName('主机名') # db.setDatabaseName('数据库名') # db.setUserName('用户名') # db.setPassword('密码') # db.setPort(3306) # 端口号 # db.open() # 判断是否连接数据库成功 返回布尔值 # """ # # 创建数据库连接并打开 # self.db = QSqlDatabase.addDatabase('QMYSQL') # self.db.setHostName('localhost') # self.db.setDatabaseName('news') # self.db.setUserName('root') # self.db.setPassword('raspberry') # if not self.db.open(): # QMessageBox.critical(self, 'Database Connection', self.db.lastError().text()) def closeEvent(self, QCloseEvent): self.db.close() # def save_to_MySQL(self): # query = QSqlQuery() # # # query.exec_("CREATE TABLE IF NOT EXISTS movie " # # "(img VARCHAR(100), name VARCHAR(50), star VARCHAR(100)," # # " time VARCHAR(50), score VARCHAR(5))") # # for row in range(self.table.rowCount()): # word = self.movie_name.text() # img = self.table.item(row, 0).text() # name = self.table.item(row, 1).text() # star = self.table.item(row, 2).text() # time = self.table.item(row, 3).text() # query.prepare("INSERT INTO words (keyword,new_url,new_tag,new_summary,source) " # "VALUES (?, ?, ?, ?, ?)") # # sql = 'insert into words(keyword,new_url,new_tag,new_summary,source) VALUES ' \ # # '(%(keyword)s,%(url)s,%(tag)s,%(summary)s,%(source)s)' # # query.bindValue(0, word) # # query.bindValue(1, img) # # query.bindValue(2, name) # # query.bindValue(3, star) # # query.bindValue(4, time) # query.addBindValue(word) # query.addBindValue(img) # query.addBindValue(name) # query.addBindValue(star) # query.addBindValue(time) # # query.exec_() # # QMessageBox.information(self, '保存到MySQL', '保存成功!', QMessageBox.Ok) def save_to_csv(self): """保存为scv文件""" content = [] for row in range(self.table.rowCount()): img = self.table.item(row, 0).text() summary = self.table.item(row, 1).text() name = self.table.item(row, 2).text() star = self.table.item(row, 3).text() time = self.table.item(row, 4).text() content.append([img, summary, name, star, time]) with open('./关键词搜索.csv', 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(['新闻链接', '新闻摘要', '渠道来源', '发布日期', '新闻摘要']) writer.writerows(content) QMessageBox.information(self, '保存到csv', '保存成功!', QMessageBox.Ok) def save_to_txt(self): """保存为txt""" content = '' for row in range(self.table.rowCount()): img = '新闻链接:{}\n'.format(self.table.item(row, 0).text()) summary = '新闻摘要:{}\n'.format(self.table.item(row, 1).text()) name = '渠道来源:{}\n'.format(self.table.item(row, 2).text()) star = '发布日期:{}\n'.format(self.table.item(row, 3).text()) time = '新闻摘要:{}\n'.format(self.table.item(row, 4).text()) content += img + summary + name + star + time + '\n' with open('./关键词搜索新闻.txt', 'w', encoding='utf-8') as f: f.write(content) QMessageBox.information(self, '保存到txt', '保存成功!', QMessageBox.Ok) def save_to_json(self): """保存为json文件""" content = [] for row in range(self.table.rowCount()): img = self.table.item(row, 0).text() summary = self.table.item(row, 1).text() name = self.table.item(row, 2).text() star = self.table.item(row, 3).text() time = self.table.item(row, 4).text() content.append( { '新闻链接': img, '新闻摘要': summary, '渠道来源': name, '评论内容': star, '发布日期': time, } ) with open('./关键词搜索新闻.json', 'w', encoding='utf-8') as f: json.dump(content, f, ensure_ascii=False) QMessageBox.information(self, '保存到json', '保存成功!', QMessageBox.Ok) def run(self): """根据url爬取数据""" for row in range(self.table.rowCount()): new_url = self.table.item(row, 0).text() self.log_browser.append('开始爬取:{}'.format(new_url)) self.progressbar.setValue(row + 1) if self.progressbar.value() == 10: self.finish_sound.play() self.log_browser.append('<font color="red">全部爬取完毕!</font>')
class AdminWindow(QWidget): def __init__(self): super().__init__() self.table = QTableWidget(self) # 添加表格对象 self.database = Database('./data.db') self.check_list = [] # 保存所有的选择框 self.show_password_flag = False # 是否显示原密码 self.select_all_flag = False # 是否选择全部 self.main_window = None self.set_ui() def set_main_window(self, widget): self.main_window = widget def set_ui(self): self.setWindowTitle("Management page") self.setFixedSize(1200, 900) # 配合图片大小设定的值 self.font = QFont("Consolas") self.setFont(self.font) self.setWindowIcon(QIcon("./IMG/python-logo.png")) # 设置图标 self.add_table() # 添加数据表格 self.get_all_user() # add table 之后才有show self.add_line_edit() # 添加输入框 self.add_label() # 添加标签 self.add_button() # 添加按钮并绑定事件 # 添加数据表格 def add_table(self): self.table.setFixedWidth(1020) # 设置宽度 self.table.setFixedHeight(600) # 设置高度 self.table.move(10, 30) # 设置显示的位置 self.table.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) # 自动填充 self.table.horizontalHeader().setFont(self.font) # 设置一下字体 # self.table.setSelectionMode(QAbstractItemView.SingleSelection) # 只能单选 self.table.setSelectionBehavior(QAbstractItemView.SelectRows) # 只能选择整行 self.table.setColumnCount(4) # 设置列数 self.table.setHorizontalHeaderLabels( ["Choice", "username", "password", 'created_time']) # 设置首行 self.table.setEditTriggers( QAbstractItemView.NoEditTriggers) # 表格中的内容设置为无法修改 self.table.verticalHeader().hide() # 把序号隐藏 self.table.setSortingEnabled(False) # 自动排序 # 获取所有的用户信息 def get_all_user(self): data = self.database.read_table( ) # 从数据库中获取用户信息,用户信息以 username, password, created_time 形式返回 for user in data: self.add_row(user[0], user[1], user[2]) # 在表格上添加一行新的内容 def add_row(self, username, password, created_time): row = self.table.rowCount() # 表格的行数 self.table.setRowCount(row + 1) # 添加一行表格 self.table.setItem(row, 1, QTableWidgetItem(str(username))) # 将用户信息插入到表格中 self.table.setItem(row, 2, QTableWidgetItem(str(password))) self.table.setItem(row, 3, QTableWidgetItem(str(created_time))) # 设置复选框 widget = QWidget() check = QCheckBox() self.check_list.append(check) # 添加到复选框列表中 check_lay = QHBoxLayout() check_lay.addWidget(check) check_lay.setAlignment(Qt.AlignCenter) widget.setLayout(check_lay) self.table.setCellWidget(row, 0, widget) def add_line_edit(self): self.username_edit = QLineEdit(self) self.username_edit.setFixedSize(240, 40) self.username_edit.move(760, 700) self.username_edit.setPlaceholderText('username') self.password_edit = QLineEdit(self) self.password_edit.setFixedSize(240, 40) self.password_edit.move(760, 760) self.password_edit.setPlaceholderText('password') self.password_edit.setEchoMode(QLineEdit.Password) # 更新密码的输入框 self.update_username_edit = QLineEdit(self) self.update_username_edit.setFixedSize(240, 40) self.update_username_edit.move(160, 700) self.update_username_edit.setPlaceholderText('username') self.update_password_edit = QLineEdit(self) self.update_password_edit.setFixedSize(240, 40) self.update_password_edit.move(160, 760) self.update_password_edit.setPlaceholderText('new password') def show_password(self): if self.show_password_flag: # 如果是真,隐藏密码 self.password_edit.setEchoMode(QLineEdit.Password) self.show_password_flag = False self.show_password_button.setText('Show') else: # 否则显示密码 self.password_edit.setEchoMode(QLineEdit.Normal) self.show_password_flag = True self.show_password_button.setText("Hide") # 添加界面上的标签控件 def add_label(self): self.username_label = QLabel(self) self.username_label.setFixedSize(160, 40) self.username_label.move(640, 700) self.username_label.setText('username') self.password_label = QLabel(self) self.password_label.setFixedSize(160, 40) self.password_label.move(640, 760) self.password_label.setText('password') # 更新密码的标签 self.update_username_label = QLabel(self) self.update_username_label.setFixedSize(160, 40) self.update_username_label.move(40, 700) self.update_username_label.setText('username') self.update_password_label = QLabel(self) self.update_password_label.setFixedSize(160, 40) self.update_password_label.move(40, 760) self.update_password_label.setText('password') # 添加界面上的按钮控件 def add_button(self): # 创建按钮对象 self.delete_button = QPushButton(self) self.update_button = QPushButton(self) self.add_button_ = QPushButton(self) self.show_password_button = QPushButton(self) self.clear_button = QPushButton(self) self.select_all_button = QPushButton(self) self.refresh_button = QPushButton(self) self.main_window_button = QPushButton(self) # 设置按钮上的文本 self.delete_button.setText("Delete") self.update_button.setText("Update") self.add_button_.setText("Add") self.show_password_button.setText("Show") self.clear_button.setText("Clear") self.select_all_button.setText("Select All") self.refresh_button.setText("Refresh") self.main_window_button.setText("Main window") # 在按钮上设置提示信息 self.delete_button.setToolTip( "Delete the selected user, you can choose multiple users") self.clear_button.setToolTip( "Clear all the users, including the super user, but the super user will be " "created later by default") self.select_all_button.setToolTip( "Select all the users, including the super user") self.show_password_button.setToolTip("Show or hide the password") self.add_button_.setToolTip( "Add a new user with the username and password in the input box") self.update_button.setToolTip( "Update the password with the chosen username") self.refresh_button.setToolTip("Click here to refresh the table") self.main_window_button.setToolTip( "Click here and you will go to the user interface") # 控制位置 self.delete_button.move(1040, 340) self.select_all_button.move(1040, 280) self.clear_button.move(1040, 400) self.refresh_button.move(1040, 460) self.update_button.move(430, 700) self.add_button_.move(1020, 700) self.show_password_button.move(1020, 750) self.main_window_button.move(500, 820) # 绑定事件 self.delete_button.clicked.connect(self.delete_user) self.select_all_button.clicked.connect(self.select_all) self.clear_button.clicked.connect(self.clear) self.show_password_button.clicked.connect(self.show_password) self.add_button_.clicked.connect(self.add_user) self.update_button.clicked.connect(self.update_password) self.refresh_button.clicked.connect(self.refresh) self.main_window_button.clicked.connect(self.show_main_window) self.main_window_button.setFixedSize(200, 40) def show_main_window(self): self.main_window.show() def delete_user(self): choose_list = [] for i in self.check_list: if i.isChecked(): username = self.table.item(self.check_list.index(i), 1).text() if username == 'admin': answer = QMessageBox.critical( self, 'Error', 'You are going to delete the super user, but it will be created later with the default password', QMessageBox.Yes | QMessageBox.Cancel, QMessageBox.Cancel) if answer == QMessageBox.Yes: choose_list.append(i) if answer == QMessageBox.Cancel: return else: choose_list.append(i) for i in choose_list: username = self.table.item(self.check_list.index(i), 1).text() self.database.delete_table_by_username(username) self.table.removeRow(self.check_list.index(i)) self.check_list.remove(i) self.database.create_table() # 选择是否选择全部 def select_all(self): try: if not self.select_all_flag: for check in self.check_list: check.setCheckState(2) # 设置为选择状态 self.select_all_button.setText("Unselect") self.select_all_flag = True else: for check in self.check_list: check.setCheckState(0) # 设置为未选状态 self.select_all_button.setText("Select All") self.select_all_flag = False except: # 该错误是由于没有复选框引起 pass # 一行一行的添加数据 def add_user(self): username = self.username_edit.text() password = self.password_edit.text() if all((username, password)): flag = self.database.insert_table(username, password) if flag: QMessageBox.critical( self, 'Error', 'Already exists the username {}, please use another username' .format(username)) else: self.add_row(username, password, self.database.get_time()) self.username_edit.setText('') # 清空输入的用户信息 self.password_edit.setText('') else: QMessageBox.critical(self, 'Error', "Please fill in the blanks") # 清空所有的数据,包括数据库和表格中的数据 def clear(self): self.table.clearContents() # 清空表格的内容 self.table.setRowCount(0) # 将表格的行数重置为0 self.database.clear() # 清空数据库数据 # 更新密码 def update_password(self): username = self.update_username_edit.text() password = self.update_password_edit.text() if len(password) >= 6: self.database.update_table(username, password) self.change_table(username, password) self.update_password_edit.setText('') self.update_username_edit.setText('') else: QMessageBox.information(self, 'Error', 'Password is too short, at least 6 words', QMessageBox.Yes, QMessageBox.Yes) # 更新表格 def change_table(self, username, password): find_flag = False for row in range(self.table.rowCount()): username_find = self.table.item(row, 1).text() if username_find == username: self.table.item(row, 2).setText(password) find_flag = True break if not find_flag: # 如果没有找到对应的用户名 QMessageBox.information( self, 'prompt', 'Can not find the username {}'.format(username)) # 重新加载数据库并显示 def refresh(self): self.table.clearContents() self.check_list.clear() self.table.setRowCount(0) self.database.create_table() self.get_all_user()
class WidgetGallery(QDialog): def __init__(self, parent=None): super(WidgetGallery, self).__init__(parent) self.resize(1000, 750) self.fileName = None self.ppfile = None self.abafile = None self.syncfile = None self.segfile = None self.poifile = None self.key = None self.ppdata = 0.0 self.output = np.array([]) self.counter = 0 self.initUI() def initUI(self): self.setWindowIcon(QIcon('srail.jpg')) self.originalPalette = QApplication.palette() styleComboBox = QComboBox() styleComboBox.addItems(QStyleFactory.keys()) styleLabel = QLabel("&Style:") styleLabel.setBuddy(styleComboBox) self.useStylePaletteCheckBox = QCheckBox( "&Use style's standard palette") self.useStylePaletteCheckBox.setChecked(True) disableWidgetsCheckBox = QCheckBox("&Disable widgets") self.createTopLeftGroupBox() self.createTopRightGroupBox() self.createBottomLeftTabWidget(self.output) self.createBottomRightGroupBox() # self.createProgressBar() styleComboBox.activated[str].connect(self.changeStyle) self.useStylePaletteCheckBox.toggled.connect(self.changePalette) disableWidgetsCheckBox.toggled.connect( self.topLeftGroupBox.setDisabled) disableWidgetsCheckBox.toggled.connect( self.topRightGroupBox.setDisabled) disableWidgetsCheckBox.toggled.connect( self.bottomLeftTabWidget.setDisabled) disableWidgetsCheckBox.toggled.connect( self.bottomRightGroupBox.setDisabled) topLayout = QHBoxLayout() topLayout.addWidget(styleLabel) topLayout.addWidget(styleComboBox) topLayout.addStretch(0) topLayout.addWidget(self.useStylePaletteCheckBox) topLayout.addWidget(disableWidgetsCheckBox) mainLayout = QGridLayout() mainLayout.addLayout(topLayout, 0, 0, 1, 2) mainLayout.addWidget(self.topLeftGroupBox, 1, 0) mainLayout.addWidget(self.topRightGroupBox, 1, 1) mainLayout.addWidget(self.bottomLeftTabWidget, 2, 0) mainLayout.addWidget(self.bottomRightGroupBox, 2, 1) # mainLayout.addWidget(self.progressBar, 3, 0, 1, 2) mainLayout.setRowStretch(1, 1) mainLayout.setRowStretch(2, 1) mainLayout.setColumnStretch(0, 1) mainLayout.setColumnStretch(1, 1) self.setLayout(mainLayout) self.setWindowTitle("RAIL CONDITION MONITORING SYSTEM") self.changeStyle('Fusion') self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint) def changeStyle(self, styleName): QApplication.setStyle(QStyleFactory.create(styleName)) self.changePalette() def changePalette(self): if (self.useStylePaletteCheckBox.isChecked()): QApplication.setPalette(QApplication.style().standardPalette()) else: QApplication.setPalette(self.originalPalette) def advanceProgressBar(self): curVal = self.progressBar.value() maxVal = self.progressBar.maximum() self.progressBar.setValue(curVal + (maxVal - curVal) / 100) def createTopLeftGroupBox(self): self.topLeftGroupBox = QGroupBox("Pre-processing") radioButton1 = QRadioButton("Radio button 1") loadabaButton = QPushButton("Browse") loadsyncButton = QPushButton("Browse") loadsegButton = QPushButton("Browse") loadpoiButton = QPushButton("Browse") radioButton1.setChecked(True) checkBox = QCheckBox("Tri-state check box") checkBox.setTristate(True) checkBox.setCheckState(Qt.PartiallyChecked) loadabaButton.clicked.connect(self.browse_aba) loadsyncButton.clicked.connect(self.browse_sync) loadsegButton.clicked.connect(self.browse_seg) loadpoiButton.clicked.connect(self.browse_poi) self.abaEdit = QLineEdit() self.abaEdit.setText("ABA file") self.abaEdit.setReadOnly(True) self.syncEdit = QLineEdit() self.syncEdit.setReadOnly(True) self.syncEdit.setText("SYNC file") self.segEdit = QLineEdit() self.segEdit.setText("SEG file") self.segEdit.setReadOnly(True) self.poiEdit = QLineEdit() self.poiEdit.setText("POI file") self.poiEdit.setReadOnly(True) self.pprocessButton = QPushButton("Start") self.pprocessButton.setStyleSheet("height: 15px;width: 24px;") self.pprocessButton.clicked.connect(self.processing) self.pprocessButton.setToolTip('Click to start pre-processing') self.savefileButton = QPushButton("Save") self.savefileButton.setStyleSheet("height: 15px;width: 24px;") self.savefileButton.clicked.connect(self.save_pdata) self.savefileButton.setToolTip("Click to save the results") self.savefileButton.setVisible(False) layout = QFormLayout() layout.addRow(loadabaButton, self.abaEdit) layout.addRow(loadsyncButton, self.syncEdit) layout.addRow(loadsegButton, self.segEdit) layout.addRow(loadpoiButton, self.poiEdit) layout.addWidget(self.pprocessButton) layout.addWidget(self.savefileButton) self.topLeftGroupBox.setLayout(layout) def createTopRightGroupBox(self): self.topRightGroupBox = QGroupBox("Anomaly detection") loadpfileButton = QPushButton("Browse") loadpfileButton.clicked.connect(self.browse_file) self.processedEdit = QLineEdit() self.processedEdit.setText("Pre-processed file") self.processedEdit.setReadOnly(True) loadsegButton = QPushButton("Browse") loadsegButton.clicked.connect(self.browse_seg1) self.segEdit1 = QLineEdit() self.segEdit1.setText("SEG file") self.segEdit1.setReadOnly(True) self.fqbox = QComboBox() self.fqbox.addItems([ 'RMS', 'Kurtosis', 'Crest factor', 'Impulse factor', 'Skewness', 'Peak-to-peak', 'All' ]) self.fqbox.currentIndexChanged.connect(self.selection_change) self.swinqbox = QComboBox() self.swinqbox.addItems([ '500', '1000', '1500', '2000', '2500', '3000', '3500', '4000', '5000', '500' ]) self.swinqbox.currentIndexChanged.connect(self.selection_change) swinsbox = QSpinBox() swinsbox.stepBy(1000) swinsbox.setMinimum(1000) swinsbox.setMaximum(6000) self.detectanomButton = QPushButton("Start") self.detectanomButton.setStyleSheet("height: 15px;width: 24px;") self.detectanomButton.clicked.connect(self.detect_anomalies) self.detectanomButton.setToolTip("Click to start anomaly detection") self.saveButton = QPushButton("Save") self.saveButton.setStyleSheet("height: 15px;width: 24px;") self.saveButton.clicked.connect(self.save_results) self.saveButton.setToolTip("Click to save the results") self.saveButton.setVisible(False) layout = QFormLayout() layout.addRow(loadpfileButton, self.processedEdit) layout.addRow(loadsegButton, self.segEdit1) layout.addRow(QLabel("No. of features:"), self.fqbox) layout.addRow(QLabel("Sliding window:"), self.swinqbox) layout.addWidget(self.detectanomButton) layout.addWidget(self.saveButton) self.topRightGroupBox.setLayout(layout) def createBottomLeftTabWidget(self, output): self.bottomLeftTabWidget = QTabWidget() self.bottomLeftTabWidget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Ignored) tab1 = QWidget() self.tableWidget = QTableWidget(100, 3) self.tableWidget.setHorizontalHeaderLabels( ['Position(km)', 'Counter', 'Severity']) tab1hbox = QHBoxLayout() tab1hbox.setContentsMargins(3, 3, 3, 3) tab1hbox.addWidget(self.tableWidget) tab1.setLayout(tab1hbox) tab2 = QWidget() textEdit = QTextEdit() textEdit.isReadOnly() textEdit.setPlainText( "Train axle-box acceleration data\n" "has been used to find incipient defects\n" "rail defects.\n\n" "Blue color in results represents incipient ABA anomaly.\n" "Yellow color in results represents intermediate ABA anomaly.\n" "Red color in results represents severe ABA anomaly.\n") tab2hbox = QHBoxLayout() tab2hbox.setContentsMargins(5, 5, 5, 5) tab2hbox.addWidget(textEdit) tab2.setLayout(tab2hbox) self.bottomLeftTabWidget.addTab(tab1, "&Results") self.bottomLeftTabWidget.addTab(tab2, "Description") def createBottomRightGroupBox(self): self.bottomRightGroupBox = QGroupBox("Model parameters") self.bottomRightGroupBox.setCheckable(True) self.bottomRightGroupBox.setChecked(True) self.tbox = QComboBox() self.tbox.addItems(['25', '50', '100', '150', '200', '250']) self.tbox.currentIndexChanged.connect(self.selection_change) self.ispinBox = QSpinBox(self.bottomRightGroupBox) self.ispinBox.setValue(0) self.ispinBox.setMinimum(0) self.ispinBox.setMaximum(15) self.ispinBox.valueChanged.connect(self.selection_change) self.stbox = QComboBox() self.stbox.addItems(['16', '32', '64', '128', '256', '512']) self.stbox.currentIndexChanged.connect(self.selection_change) slider = QSlider(Qt.Horizontal, self.bottomRightGroupBox) slider.setValue(40) slider.show() layout = QGridLayout() layout.addWidget(QLabel("Impurity ratio (%):"), 0, 0, 1, 3) layout.addWidget(self.ispinBox, 0, 1, 1, 3) layout.addWidget(QLabel("Sub-sampling size:"), 1, 0, 1, 3) layout.addWidget(self.stbox, 1, 1, 1, 3) layout.addWidget(QLabel("No. of trees:"), 2, 0, 1, 3) layout.addWidget(self.tbox, 2, 1, 1, 3) layout.addWidget(slider, 3, 0, 1, 4) # layout.setRowStretch(5, 1) self.bottomRightGroupBox.setLayout(layout) def createProgressBar(self): self.progressBar = QProgressBar() self.progressBar.setRange(0, 10000) self.progressBar.setValue(0) timer = QTimer(self) timer.timeout.connect(self.advanceProgressBar) timer.start(1000) # ///////////////////// System functions ///////////////////////// def openFileNameDialog(self, type=None): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName( self, "QFileDialog.getOpenFileName()", "", "All Files (*);;Python Files (*.py)", options=options) if fileName: if self.type == 'anomaly' and not str(fileName).endswith('.h5'): msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("File Error") msg.setInformativeText( 'Please select the file with .h5 format!') msg.setWindowTitle("Error") msg.exec_() elif self.type != 'anomaly' and not str(fileName).endswith('.csv'): if self.type == 'aba' and not str(fileName).endswith('.h5'): msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("File Error") msg.setInformativeText( 'Please select the file with .h5 format!') msg.setWindowTitle("Error") msg.exec_() elif self.type != 'aba': msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("File Error") msg.setInformativeText( 'Please select the file with .csv format!') msg.setWindowTitle("Error") msg.exec_() if self.type == 'anomaly': print(fileName) self.ppfile = fileName self.processedEdit.setText(str(fileName)) elif self.type == 'aba': print(fileName) self.abafile = fileName self.abaEdit.setText(str(fileName)) # self.tableWidget.setItem(0, 1, QTableWidgetItem(str(123))) # self.close() elif self.type == 'sync': print(fileName) self.syncfile = fileName self.syncEdit.setText(str(fileName)) elif self.type == 'poi': print(fileName) self.poifile = fileName self.poiEdit.setText(str(fileName)) elif self.type == 'seg': print(fileName) self.segfile = fileName self.segEdit.setText(str(fileName)) elif self.type == 'seg1': print(fileName) self.segfile = fileName self.segEdit1.setText(str(fileName)) def openFileNamesDialog(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog files, _ = QFileDialog.getOpenFileNames( self, "QFileDialog.getOpenFileNames()", "", "All Files (*);;Python Files (*.py)", options=options) if files: print(files) self.close() def saveFileDialog(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getSaveFileName( self, "QFileDialog.getSaveFileName()", "", "All Files (*); MS Excel Files (*.csv); ; hdf5 (*.h5)", options=options) if fileName: print(fileName) self.savefile = fileName def selection_change(self): self.feature = self.fqbox.currentText() print(self.feature) self.swin = int(self.swinqbox.currentText()) self.impurity = float(self.ispinBox.value() / 100) print(self.impurity) self.sssize = int(self.stbox.currentText()) self.trees = int(self.tbox.currentText()) def processing(self): if self.abafile and self.syncfile and self.segfile and self.poifile: self.ppdata = pre_processing(self.abafile, self.syncfile, self.segfile, self.poifile, None) self.savefileButton.setVisible(True) self.pprocessButton.setVisible(False) self.abaEdit.setText("ABA file") self.syncEdit.setText("SYNC file") self.segEdit.setText("SEG file") self.poiEdit.setText("POI file") else: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("File Error") msg.setInformativeText('Please load all the required files...') msg.setWindowTitle("File missing!") msg.exec_() def detect_anomalies(self): if self.ppfile == None: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("File Error") msg.setInformativeText('Please load the pre-processed file!') msg.setWindowTitle("Error") msg.exec_() else: obj = RailDefects(1) self.output = obj.anomaly_detection(self.ppfile, self.segfile, self.feature, self.swin, self.sssize, self.impurity) loc = self.output[0, 0] cnt = self.output[0, 1] sev = self.output[0, 2] print("First Anomaly: ", loc, cnt, sev) # self.output = np.array([[2], [3], [5]]) self.saveButton.setVisible(True) self.detectanomButton.setVisible(False) self.processedEdit.setText("Pre-processed file") self.segEdit.setText("SEG file") # Populate the table if len(self.output) > 0: for i in range(75): for j in range(3): val = self.output[i, j] print("Value:", val) self.tableWidget.setItem(i, j, QTableWidgetItem(str(val))) if j == 2: if self.output[i, 2] <= 0.4: self.tableWidget.item(i, 2).setBackground( QColor(Qt.blue)) elif self.output[i, 2] > 0.4 and self.output[ i, 2] <= 0.75: self.tableWidget.item(i, 2).setBackground( QColor(Qt.yellow)) else: self.tableWidget.item(i, 2).setBackground( QColor(Qt.red)) def browse_aba(self): self.type = 'aba' self.openFileNameDialog(self.type) def browse_sync(self): self.type = 'sync' self.openFileNameDialog(self.type) def browse_poi(self): self.type = 'poi' self.openFileNameDialog(self.type) def browse_seg(self): self.type = 'seg' self.openFileNameDialog(self.type) def browse_seg1(self): self.type = 'seg1' self.openFileNameDialog(self.type) def browse_file(self): self.type = 'anomaly' self.openFileNameDialog(self.type) def save_results(self): self.key = None self.saveFileDialog() with open(self.savefile + '.csv', 'w', newline='') as file: try: writer = csv.writer(file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) writer.writerow(['positions', 'counters', 'severity']) for pos, cnt, sev in self.output: writer.writerow([pos, cnt, sev]) finally: file.close() self.detectanomButton.setVisible(True) self.saveButton.setVisible(False) self.tableWidget.clearContents() def save_pdata(self): self.key = 'processed' self.saveFileDialog() self.ppdata.to_hdf(self.savefile + '.h5', key='processed', mode='w') self.pprocessButton.setVisible(True) self.savefileButton.setVisible(False)
class LocationItemDlg(QDialog): def __init__(self, item=None, position=None, scene=None, parent=None): super(QDialog, self).__init__(parent) self.parentForm = parent self.item = item self.position = position self.scene = scene self.ediEquation = QTextEdit() self.ediEquation.setAcceptRichText(True) self.ediEquation.setTabChangesFocus(True) lblEquation = QLabel("Equations:") lblEquation.setBuddy(self.ediEquation) self.txtLocationName = QLineEdit() lblLocationName = QLabel("LocationName:") lblLocationName.setBuddy(self.txtLocationName) self.isNameAbove = QCheckBox() lblIsNameAbove = QLabel("IsNameAbove") lblIsNameAbove.setBuddy(self.isNameAbove) self.isInitial = QCheckBox() lblIsInitial = QLabel("IsInitial") lblIsInitial.setBuddy(self.isInitial) self.isEnd = QCheckBox() lblIsEnd = QLabel("IsEnd") lblIsEnd.setBuddy(self.isEnd) self.txtInvariant = QLineEdit() lblInvariant = QLabel("Invariant:") lblInvariant.setBuddy(self.txtInvariant) self.figEquation = Figure(figsize=(3, 1)) self.canvEquation = FigureCanvas(self.figEquation) lblCanvEquation = QLabel("Format(Equations):") lblCanvEquation.setBuddy(self.canvEquation) self.ediSymEquation = QTextEdit() self.ediSymEquation.setAcceptRichText(True) self.ediSymEquation.setTabChangesFocus(False) lblSymEquation = QLabel("Sympy(Equations):") lblSymEquation.setBuddy(self.ediSymEquation) self.txtCheckPointSeq = QLineEdit() lblCheckPointSeq = QLabel("CheckPoint Seq:") lblCheckPointSeq.setBuddy(self.txtCheckPointSeq) self.cmbVariableName = QComboBox() self.dicVariableList = [ key for key in parent.dicVariable.keys() if parent.dicVariable[key].isConstant == False ] self.cmbVariableName.addItems(self.dicVariableList) lblVariableName = QLabel("variableName:") lblVariableName.setBuddy(self.cmbVariableName) self.txtValue = QLineEdit() lblValue = QLabel("Value:") lblValue.setBuddy(self.txtValue) btnAddCheckPoint = QPushButton("&Save CheckPoint") btnAddCheckPoint.clicked.connect(self.SaveCheckPoint) btnRemoveCheckPoint = QPushButton("&Remove CheckPoint") btnRemoveCheckPoint.clicked.connect(self.RemoveCheckPoint) #self.EdgeWidget.resizeColumnsToContents() self.VariablesWidget = QTableWidget() # setup table widget self.VariablesWidget.itemDoubleClicked.connect( self.VariablesWidgetDoubleClicked) self.VariablesWidget.setColumnCount(3) self.VariablesWidget.setHorizontalHeaderLabels( ['Seq', 'Variable', 'Value']) #self.figInvariant = Figure(figsize=(5, 0.4)) #self.canvInvariant = FigureCanvas(self.figInvariant) #lblCanvInvariant = QLabel("&Format(Invariant):") #lblCanvInvariant.setBuddy(self.canvInvariant) btnDelete = QPushButton("Delete Location") btnDelete.clicked.connect(self.delete) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) #self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) self.isNameAbove.setChecked(True) if self.item is not None: self.ediEquation.setPlainText("\n".join(self.item.equation)) self.txtLocationName.setText(self.item.boxName) self.isInitial.setChecked(self.item.isInitial) self.isEnd.setChecked(self.item.isEnd) self.isNameAbove.setChecked(self.item.isNameAbove) self.txtInvariant.setText(self.item.invariant) self.SetVariableWdigetAll(self.item.checkPoints) layout = QGridLayout() layout.addWidget(lblEquation, 0, 0) layout.addWidget(self.ediEquation, 1, 0, 1, 8) layout.addWidget(lblLocationName, 2, 0) layout.addWidget(self.txtLocationName, 2, 1, 1, 2) layout.addWidget(lblIsNameAbove, 2, 3) layout.addWidget(self.isNameAbove, 2, 4, 1, 2) layout.addWidget(lblIsInitial, 3, 0) layout.addWidget(self.isInitial, 3, 1) layout.addWidget(lblIsEnd, 3, 2) layout.addWidget(self.isEnd, 3, 3) layout.addWidget(lblInvariant, 4, 0) layout.addWidget(self.txtInvariant, 4, 1, 1, 7) layout.addWidget(lblCanvEquation, 5, 0) layout.addWidget(self.canvEquation, 6, 0, 3, 8) layout.addWidget(lblSymEquation, 10, 0) layout.addWidget(self.ediSymEquation, 11, 0, 1, 8) #layout.addWidget(lblCanvInvariant, 10, 0) #layout.addWidget(self.canvInvariant, 10,1, 1, 5) layout.addWidget(self.buttonBox, 12, 0, 1, 6) layout.addWidget(btnDelete, 12, 7) self.setLayout(layout) layout.addWidget(lblCheckPointSeq, 13, 0) layout.addWidget(self.txtCheckPointSeq, 13, 1) layout.addWidget(lblVariableName, 13, 2) layout.addWidget(self.cmbVariableName, 13, 3) layout.addWidget(lblValue, 13, 4) layout.addWidget(self.txtValue, 13, 5) layout.addWidget(btnAddCheckPoint, 13, 6) layout.addWidget(btnRemoveCheckPoint, 13, 7) layout.addWidget(self.VariablesWidget, 14, 0, 1, 8) self.VariablesWidget.setSelectionMode( QAbstractItemView.SingleSelection) #self.VariablesWidget.setSelectionBehavior(QAbstractItemView.SelectRows) self.VariablesWidget.setSelectionBehavior( QAbstractItemView.SelectItems) self.VariablesWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) self.ediEquation.textChanged.connect(self.updateUi) self.txtInvariant.textChanged.connect(self.updateUi) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.resize(900, 1000) #self.buttonBox.button(QDialogButtonBox.Reset).clicked.connect(self.apply) self.setWindowTitle( "{0} Location Item".format("Add" if self.item is None else "Edit")) self.updateUi() def delete(self): self.parentForm.deleteText(self.item) self.parentForm.setDirty() QDialog.accept(self) def updateUi(self): self.apply() def SetVariableWdigetAll(self, checkPoints): self.VariablesWidget.clearContents() self.VariablesWidget.setRowCount(0) for strSeq in sorted(checkPoints.keys()): #for key in sorted(mydict.iterkeys()): self.AddCheckPoint(checkPoints[strSeq]) def SaveCheckPoint(self): if not self.txtCheckPointSeq.text(): QMessageBox.question( self, "CheckPoint Seq Is None", "Fail to Save,Please input a CheckPoint Seq!", QMessageBox.Ok) return if not self.cmbVariableName.currentText(): QMessageBox.question( self, "CheckPoint variable Name Is None", "Fail to Save,Please select a variable name!", QMessageBox.Ok) return if not self.txtValue.text(): QMessageBox.question( self, "CheckPoint Value Is None", "Fail to Save,Please input a CheckPoint Value!", QMessageBox.Ok) return checkPoint = { "boxName": self.txtCheckPointSeq.text(), "VariableName": self.cmbVariableName.currentText(), "Value": self.txtValue.text() } self.UpdateCheckPoint(checkPoint) def AddCheckPoint(self, checkPoint): rowCount = self.VariablesWidget.rowCount() row_index = self.VariablesWidget.rowCount() self.VariablesWidget.insertRow(row_index) row_index = row_index self.VariablesWidget.setItem( row_index, 0, QTableWidgetItem(checkPoint["boxName"], 0)) self.VariablesWidget.setItem( row_index, 1, QTableWidgetItem(checkPoint["VariableName"], 0)) self.VariablesWidget.setItem(row_index, 2, QTableWidgetItem(checkPoint["Value"], 0)) def UpdateCheckPoint(self, checkPoint): rowCount = self.VariablesWidget.rowCount() for row_index in range(rowCount): if self.VariablesWidget.item(row_index, 0).text() == checkPoint["boxName"]: self.VariablesWidget.setItem( row_index, 1, QTableWidgetItem(checkPoint["VariableName"], 0)) self.VariablesWidget.setItem( row_index, 2, QTableWidgetItem(checkPoint["Value"], 0)) #ui->tableWidget->resizeRowToContents(curRow) return self.AddCheckPoint(checkPoint) def RemoveCheckPoint(self): if not self.txtCheckPointSeq.text(): QMessageBox.question( self, "CheckPoint Seq Is None", "Fail to Remove,Please input a CheckPoint Seq!", QMessageBox.Ok) return rowCount = self.VariablesWidget.rowCount() for row_index in range(rowCount): if self.VariablesWidget.item(row_index, 0).text() == checkPoint["boxName"]: VariablesWidget.removeRow(row_index) return def GetCheckPoints(self): rowCount = self.VariablesWidget.rowCount() checkPoints = {} for row_index in range(rowCount): strCheckPointSeq = self.VariablesWidget.item(row_index, 0).text() if strCheckPointSeq: checkPoints[strCheckPointSeq] = { "boxName": strCheckPointSeq, "VariableName": self.VariablesWidget.item(row_index, 1).text(), "Value": self.VariablesWidget.item(row_index, 2).text() } return checkPoints def VariablesWidgetDoubleClicked(self, item): self.txtCheckPointSeq.setText( self.VariablesWidget.item(item.row(), 0).text()) self.cmbVariableName.setCurrentIndex( self.dicVariableList.index( self.VariablesWidget.item(item.row(), 1).text())) self.txtValue.setText(self.VariablesWidget.item(item.row(), 2).text()) def accept(self): iEditLine = self.ediEquation.document().lineCount() equation = [ self.ediEquation.document().findBlockByLineNumber(i).text() for i in range(iEditLine) ] tmpLocationName = self.txtLocationName.text() if (tmpLocationName == ""): QMessageBox.question( self, "Please Input Location Name", "Fail to Accept,Please Input a Name for the Location!", QMessageBox.Ok) return if self.item is None: if (tmpLocationName in self.parentForm.dicText.keys()): QMessageBox.question( self, "Location Name Exists", "Fail to Accept,Please Change a Name for the Location due to there is already a location named " + tmpLocationName + "!", QMessageBox.Ok) return self.item = LocationItem("", equation, self.txtInvariant.text(), self.position, self.isInitial.isChecked(), self.isEnd.isChecked(), self.isNameAbove.isChecked(), {}, self.scene, self.parentForm) if (self.item.boxName == ""): self.item.boxName = self.txtLocationName.text() else: if (self.item.boxName != self.txtLocationName.text()): if (tmpLocationName in self.parentForm.dicText.keys()): QMessageBox.question( self, "Location Name Exists", "Fail to Accept,Please Change a Name for the Location due to there is already a location named " + tmpLocationName + "!", QMessageBox.Ok) return self.parentForm.dicText.pop(self.item.boxName) self.item.boxName = self.txtLocationName.text() self.parentForm.dicText[self.item.boxName] = self.item self.item.equation = equation self.item.invariant = self.txtInvariant.text() self.item.isInitial = self.isInitial.isChecked() self.item.isEnd = self.isEnd.isChecked() self.item.isNameAbove = self.isNameAbove.isChecked() self.item.checkPoints = self.GetCheckPoints() self.item.update() self.parentForm.setDirty() QDialog.accept(self) def apply(self): #formula = #r'$x=\frac{3}{100}$' iEditLine = self.ediEquation.document().lineCount() iHeight = 1 if (iEditLine > 4): iHeight = 0.2 * (iEditLine - 4) + 1 self.figEquation.set_size_inches(5, iHeight) self.figEquation.clf() SympyLines = [] try: for i in range(iEditLine): strData = self.ediEquation.document().findBlockByLineNumber( i).text() try: #if True: if '=' in strData: strLeftEquation, strRightEquation = FormatParseLatex.formatParseLatex4Design( strData) SympyLines.append('='.join( [strLeftEquation, strRightEquation])) self.figEquation.text(0.1, iHeight - 0.2 * (i + 1), strData, fontsize=10) except Exception as e: #else: SympyLines.append(strData + "Error:" + str(e)) print(str(e)) except: print("Unexpected error:", sys.exc_info()[0]) self.ediSymEquation.setPlainText("\n".join(SympyLines)) self.canvEquation.draw() except: print("")
class LabelAssistDialog(QDialog): """ A simple UI for showing bookmarks and navigating to them. FIXME: For now, this window is tied to a particular lane. If your project has more than one lane, then each one will have it's own bookmark window, which is kinda dumb. """ def __init__(self, parent, topLevelOperatorView): super(LabelAssistDialog, self).__init__(parent) # Create thread router to populate table on main thread self.threadRouter = ThreadRouter(self) # Set object classification operator view self.topLevelOperatorView = topLevelOperatorView self.setWindowTitle("Label Assist") self.setMinimumWidth(500) self.setMinimumHeight(700) layout = QGridLayout() layout.setContentsMargins(10, 10, 10, 10) # Show variable importance table rows = 0 columns = 4 self.table = QTableWidget(rows, columns) self.table.setHorizontalHeaderLabels( ['Frame', 'Max Area', 'Min Area', 'Labels']) self.table.verticalHeader().setVisible(False) # Select full row on-click and call capture double click self.table.setSelectionBehavior(QTableView.SelectRows) self.table.doubleClicked.connect(self._captureDoubleClick) layout.addWidget(self.table, 1, 0, 3, 2) # Create progress bar self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(0) self.progressBar.hide() layout.addWidget(self.progressBar, 4, 0, 1, 2) # Create button to populate table self.computeButton = QPushButton('Compute object info') self.computeButton.clicked.connect(self._triggerTableUpdate) layout.addWidget(self.computeButton, 5, 0) # Create close button closeButton = QPushButton('Close') closeButton.clicked.connect(self.close) layout.addWidget(closeButton, 5, 1) # Set dialog layout self.setLayout(layout) def _triggerTableUpdate(self): # Check that object area is included in selected features featureNames = self.topLevelOperatorView.SelectedFeatures.value if 'Standard Object Features' not in featureNames or 'Count' not in featureNames[ 'Standard Object Features']: box = QMessageBox( QMessageBox.Warning, 'Warning', 'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"', QMessageBox.NoButton, self) box.show() return # Clear table self.table.clearContents() self.table.setRowCount(0) self.table.setSortingEnabled(False) self.progressBar.show() self.computeButton.setEnabled(False) def compute_features_for_frame(tIndex, t, features): # Compute features and labels (called in parallel from request pool) roi = [ slice(None) for i in range( len(self.topLevelOperatorView.LabelImages.meta.shape)) ] roi[tIndex] = slice(t, t + 1) roi = tuple(roi) frame = self.topLevelOperatorView.SegmentationImages(roi).wait() frame = frame.squeeze().astype(numpy.uint32, copy=False) # Dirty trick: We don't care what we're passing here for the 'image' parameter, # but vigra insists that we pass *something*, so we'll cast the label image as float32. features[t] = vigra.analysis.extractRegionFeatures( frame.view(numpy.float32), frame, ['Count'], ignoreLabel=0) tIndex = self.topLevelOperatorView.SegmentationImages.meta.axistags.index( 't') tMax = self.topLevelOperatorView.SegmentationImages.meta.shape[tIndex] features = {} labels = {} def compute_all_features(): # Compute features in parallel pool = RequestPool() for t in range(tMax): pool.add( Request( partial(compute_features_for_frame, tIndex, t, features))) pool.wait() # Compute labels labels = self.topLevelOperatorView.LabelInputs([]).wait() req = Request(compute_all_features) req.notify_finished(partial(self._populateTable, features, labels)) req.submit() @threadRouted def _populateTable(self, features, labels, *args): self.progressBar.hide() self.computeButton.setEnabled(True) for time, feature in features.items(): # Insert row rowNum = self.table.rowCount() self.table.insertRow(self.table.rowCount()) # Get max and min object areas areas = feature[ 'Count'] #objectFeatures['Standard Object Features']['Count'] maxObjArea = numpy.max(areas[numpy.nonzero(areas)]) minObjArea = numpy.min(areas[numpy.nonzero(areas)]) # Get number of labeled objects labelNum = numpy.count_nonzero(labels[time]) # Load fram number item = QTableWidgetItem(str(time)) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 0, item) # Load max object areas item = QTableWidgetItemWithFloatSorting( str("{: .02f}".format(maxObjArea))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 1, item) # Load min object areas item = QTableWidgetItemWithFloatSorting( str("{: .02f}".format(minObjArea))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 2, item) # Load label numbers item = QTableWidgetItemWithFloatSorting( str("{: .01f}".format(labelNum))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 3, item) # Resize column size to fit dialog size self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) # Sort by max object area self.table.setSortingEnabled(True) self.table.sortByColumn(1, Qt.DescendingOrder) def _captureDoubleClick(self): # Navigate to selected frame index = self.table.selectedIndexes()[0] frameStr = self.table.model().data(index).toString() if frameStr: frameNum = int(frameStr) self.parent().editor.posModel.time = frameNum
class ExTags(QDialog): """A dialog that shows you the tags in a file In addition, any attached cover art is shown.""" rowChanged = pyqtSignal(object, name='rowChanged') extendedtags = pyqtSignal(dict, name='extendedtags') def __init__(self, parent=None, row=None, files=None, preview_mode=False, artwork=True, status=None): if status is None: status = {'cover_pattern': 'folder'} self.status = status QDialog.__init__(self, parent) winsettings('extendedtags', self) self.get_fieldlist = [] self.previewMode = preview_mode add = QColor.fromRgb(255, 255, 0) edit = QColor.fromRgb(0, 255, 0) remove = QColor.fromRgb(255, 0, 0) self._colors = {ADD: QBrush(add), EDIT: QBrush(edit), REMOVE: QBrush(remove)} self.table = QTableWidget(0, 2, self) self.table.setVerticalHeader(VerticalHeader()) self.table.verticalHeader().setVisible(False) self.table.setSortingEnabled(True) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setHorizontalHeaderLabels([ translate('Extended Tags', 'Field'), translate('Extended Tags', 'Value')]) header = self.table.horizontalHeader() header.setVisible(True) header.setSortIndicatorShown(True) header.setStretchLastSection(True) header.setSortIndicator(0, Qt.AscendingOrder) self.piclabel = PicWidget(buttons=True) self.piclabel.imageChanged.connect( self._imageChanged) if not isinstance(self.piclabel.removepic, QAction): self.piclabel.removepic.clicked.connect( self.removePic) else: self.piclabel.removepic.triggered.connect(self.removePic) if row and row >= 0 and files: buttons = MoveButtons(files, row) buttons.indexChanged.connect(self._prevnext) buttons.setVisible(True) else: buttons = MoveButtons([], row) buttons.setVisible(False) self._files = files self.okcancel = OKCancel() self.okcancel.insertWidget(0, buttons) self._reset = QToolButton() self._reset.setToolTip(translate('Extended Tags', 'Resets the selected fields to their original value.')) self._reset.setIcon(get_icon('edit-undo', ':/undo.png')) self._reset.clicked.connect(self.resetFields) self.listbuttons = ListButtons() self.listbuttons.layout().addWidget(self._reset) self.listbuttons.moveupButton.hide() self.listbuttons.movedownButton.hide() listframe = QFrame() listframe.setFrameStyle(QFrame.Box) hbox = QHBoxLayout() hbox.addWidget(self.table, 1) hbox.addLayout(self.listbuttons, 0) listframe.setLayout(hbox) layout = QVBoxLayout() if artwork: imageframe = QFrame() imageframe.setFrameStyle(QFrame.Box) vbox = QVBoxLayout() vbox.setContentsMargins(0, 0, 0, 0) vbox.addWidget(self.piclabel) vbox.addStretch() vbox.addStrut(0) imageframe.setLayout(vbox) hbox = QHBoxLayout() hbox.addWidget(listframe, 1) hbox.addSpacing(4) hbox.addWidget(imageframe) hbox.addStrut(1) layout.addLayout(hbox) else: layout.addWidget(listframe) layout.addLayout(self.okcancel) self.setLayout(layout) self.okcancel.cancel.connect(self.closeMe) self.table.itemDoubleClicked.connect(self.editField) self.table.itemSelectionChanged.connect(self._checkListBox) self.okcancel.ok.connect(self.okClicked) self.listbuttons.edit.connect(self.editField) self.listbuttons.addButton.clicked.connect(self.addField) self.listbuttons.removeButton.clicked.connect(self.removeField) self.listbuttons.duplicate.connect(self.duplicate) self.setMinimumSize(450, 350) self.canceled = False self.filechanged = False if row and row >= 0 and files: self._prevnext(row) else: self.loadFiles(files) def addField(self): win = EditField(parent=self, field_list=self.get_fieldlist) win.setModal(True) win.show() win.donewithmyshit.connect(self.editFieldBuddy) def _checkListBox(self): if self.table.rowCount() <= 0: self.table.setEnabled(False) self.listbuttons.editButton.setEnabled(False) self.listbuttons.removeButton.setEnabled(False) self.listbuttons.duplicateButton.setEnabled(False) self._reset.setEnabled(False) else: self.table.setEnabled(True) self._reset.setEnabled(True) if len(self.table.selectedIndexes()) / 2 > 1: self.listbuttons.editButton.setEnabled(False) self.listbuttons.duplicateButton.setEnabled(False) else: self.listbuttons.editButton.setEnabled(True) self.listbuttons.removeButton.setEnabled(True) self.listbuttons.duplicateButton.setEnabled(True) self.table.resizeColumnToContents(0) def closeEvent(self, event): self.piclabel.close() QDialog.closeEvent(self, event) def closeMe(self): self.canceled = True self.close() def _deletePressed(self, item): if self.table.deletePressed: self.table.deletePressed = False self.removeField() def duplicate(self): self.editField(True) def editField(self, duplicate=False): """Opens a dialog to edit the currently selected Field. If duplicate is True the Edit Field dialog will be populated with the currently selected field's values. The new field'll then be added to the field list.""" row = self.table.currentRow() if row != -1: prevtag = self.get_field(row) if duplicate is True: win = EditField(prevtag, self, self.get_fieldlist, edit=False) else: win = EditField(prevtag, self, self.get_fieldlist) win.setModal(True) win.show() # Have to check for truth, because this method is # called by the doubleclicked signal. if duplicate is True: buddy = partial(self.editFieldBuddy, duplicate=True) else: buddy = self.editFieldBuddy win.donewithmyshit.connect(buddy) def editFieldBuddy(self, tag, value, prevtag=None, duplicate=False): rowcount = self.table.rowCount() if prevtag is not None: if duplicate: row = rowcount self._settag(rowcount, tag, value, ADD, self.previewMode, True) else: if tag == prevtag[0]: row = self.table.currentRow() self._settag(row, tag, value, EDIT, self.previewMode, True) if row + 1 < rowcount: self.table.selectRow(row + 1) else: cur_item = self.table.item(self.table.currentRow(), 0) self.resetFields([cur_item]) self.table.setCurrentItem(cur_item, QItemSelectionModel.ClearAndSelect) self.table.selectRow(self.table.row(cur_item)) self.removeField() valitem = self._settag(rowcount, tag, value, ADD, self.previewMode, True) cur_item.linked = [valitem] else: self._settag(rowcount, tag, value, ADD, self.previewMode, True) self._checkListBox() self.filechanged = True self.table.clearSelection() def get_field(self, row, status=None): getitem = self.table.item item = getitem(row, 0) tag = str(item.text()) try: value = str(getitem(row, 1).text()) except AttributeError: value = str(self.table.cellWidget(row, 1).currentText()) if status: return (tag, value, item.status) else: return (tag, value) def _imageChanged(self): self.filechanged = True def loadSettings(self): cparser = PuddleConfig() self.get_fieldlist = gettaglist() get = lambda k, v: cparser.get('extendedtags', k, v, True) add = QColor.fromRgb(*get('add', [255, 255, 0])) edit = QColor.fromRgb(*get('edit', [0, 255, 0])) remove = QColor.fromRgb(*get('remove', [255, 0, 0])) self._colors = {ADD: QBrush(add), EDIT: QBrush(edit), REMOVE: QBrush(remove)} item = self.table.item for row in range(self.table.rowCount()): field_item = self.get_item(row, 0) field_item.statusColors = self._colors field_item.status = field_item.status val_item = self.get_item(row, 1) val_item.statusColors = self._colors val_item.status = val_item.status def listtotag(self): get_field = self.get_field tags = {} lowered = {} listitems = [get_field(row, True) for row in range(self.table.rowCount())] for field, val, status in listitems: if status != REMOVE: if val == KEEP: continue l_field = field.lower() if l_field in lowered: tags[lowered[l_field]].append(val) else: lowered[l_field] = field tags[field] = [z.strip() for z in val.split('\\') if z.strip()] else: if field.lower() not in lowered: tags[field] = [] lowered[field.lower()] = field return tags def loadFiles(self, audios): if self.filechanged: self.save() self.filechanged = False self.table.clearContents() self.table.setRowCount(0) self.piclabel.lastfilename = audios[0].filepath self.piclabel.setEnabled(False) self.piclabel.setImages(None) if len(audios) == 1: audio = audios[0] self.setWindowTitle(audios[0].filepath) self._loadsingle(audio) else: self.setWindowTitle( translate('Extended Tags', 'Different files.')) from .tagmodel import status k = status['table'].model().taginfo[0] common, numvalues, imagetags = commontags(audios) images = common['__image'] del (common['__image']) previews = set(audios[0].preview) italics = set(audios[0].equal_fields()) self.piclabel.currentFile = audios[0] self.piclabel.filePattern = self.status['cover_pattern'] for audio in audios[1:]: previews = previews.intersection(audio.preview) italics = italics.intersection(audio.equal_fields()) row = 0 for field, values in common.items(): if field in italics: preview = UNCHANGED # field in italics => field in previews. elif field in previews: preview = BOLD else: preview = UNCHANGED if numvalues[field] != len(audios): self._settag(row, field, values, multi=True) row += 1 else: if isinstance(values, str): self._settag(row, field, values, None, preview) row += 1 else: for v in values: self._settag(row, field, v, None, preview) row += 1 self.piclabel.setImageTags(imagetags) if images: self.piclabel.setEnabled(True) self.piclabel.setImages(images) else: self.piclabel.setImages(None) self.piclabel.setEnabled(True) if images == 0: self.piclabel.context = 'Cover Varies' self.piclabel.removepic.setEnabled(True) self._checkListBox() def _loadsingle(self, tags): items = [] d = tags.usertags.copy() italics = tags.equal_fields() self.piclabel.currentFile = tags self.piclabel.filePattern = self.status['cover_pattern'] for key, val in sorted(d.items()): if key in italics: preview = UNCHANGED elif key in tags.preview: preview = BOLD else: preview = UNCHANGED if isinstance(val, str): items.append([key, val, None, preview]) else: [items.append([key, z, None, preview]) for z in val] [self._settag(i, *item) for i, item in enumerate(items)] self.piclabel.lastfilename = tags.filepath if not tags.library: self.piclabel.setImageTags(tags.IMAGETAGS) if tags.IMAGETAGS: if '__image' in tags.preview: images = tags.preview['__image'] else: images = tags.images self.piclabel.setEnabled(True) if images: self.piclabel.setImages(deepcopy(images)) else: self.piclabel.setImages(None) self._checkListBox() self.setWindowTitle(tags[PATH]) def okClicked(self): self.save() self.close() def _prevnext(self, row): if self.filechanged: self.save() self.loadFiles([self._files[row]]) self.rowChanged.emit(row) def get_item(self, row, column=None): if column is None: # Assume QModelIndex passed column = row.column() row = row.row() item = self.table.item(row, column) if item is None: item = self.table.cellWidget(row, column) return item def removeField(self): tb = self.table tb.setSortingEnabled(False) to_remove = {} rows = [] for index in self.table.selectedIndexes(): row = index.row() item = self.get_item(index) if item.status == ADD: to_remove[row] = item rows.append(row) item.status = REMOVE item.status = REMOVE [tb.removeRow(tb.row(z)) for z in to_remove.values()] tb.setSortingEnabled(True) self.filechanged = True self._checkListBox() if rows: row = max(rows) self.table.clearSelection() if row + 1 < self.table.rowCount(): self.table.selectRow(row + 1) def resetFields(self, items=None): box = self.table to_remove = {} # Stores row: item values so that only one item # gets removed per row. max_row = -1 for index in box.selectedIndexes(): row = index.row() item = self.table.item(row, index.column()) if item is None: item = self.table.cellWidget(row, index.column()) for i in item.linked: try: to_remove[box.row(i)] = i except RuntimeError: pass item.reset() if row > max_row: max_row = row if item.status == REMOVE: to_remove[row] = item self.table.clearSelection() if max_row != -1 and max_row + 1 < self.table.rowCount(): self.table.selectRow(max_row + 1) for item in to_remove.values(): self.table.removeRow(self.table.row(item)) self._checkListBox() def removePic(self): if self.piclabel.context == 'Cover Varies': self.piclabel.context = 'No Images' self.piclabel.removepic.setEnabled(False) if not isinstance(self.piclabel.removepic, QAction): self.piclabel.removepic.clicked.disconnect( self.removePic) else: self.piclabel.removepic.triggered.disconnect(self.removePic) self.piclabel.setImages(None) def save(self): if not self.filechanged: table = self.table for row in range(table.rowCount()): combo = table.cellWidget(row, 1) if combo is not None and combo.currentIndex() != 0: self.filechanged = True break if not self.filechanged: return tags = self.listtotag() if self.piclabel.context != 'Cover Varies': if not self.piclabel.images: tags['__image'] = [] else: tags["__image"] = self.piclabel.images newtags = [z for z in tags if z not in self.get_fieldlist] if newtags and newtags != ['__image']: settaglist(newtags + self.get_fieldlist) self.extendedtags.emit(tags) def _settag(self, row, field, value, status=None, preview=False, check=False, multi=False): tb = self.table tb.setSortingEnabled(False) if row >= tb.rowCount(): tb.insertRow(row) field_item = StatusWidgetItem(field, status, self._colors, preview) tb.setItem(row, 0, field_item) if not multi and (len(value) == 1 or isinstance(value, str)): valitem = StatusWidgetItem(to_string(value), status, self._colors, preview) tb.setItem(row, 1, valitem) else: valitem = StatusWidgetCombo(value, status, self._colors, preview) tb.setCellWidget(row, 1, valitem) else: field_item = tb.item(row, 0) field_item.setText(field) field_item.status = status val_item = self.get_item(row, 1) val_item.setText(value) val_item.status = status if check: lowered_tag = field.lower() for row in range(tb.rowCount()): item = tb.item(row, 0) text = str(item.text()) if text != field and text.lower() == lowered_tag: item.setText(field) if item.status not in [ADD, REMOVE]: item.status = EDIT try: tb.item(row, 1).status = EDIT except AttributeError: tb.cellWidget(row, 1).status = EDIT tb.setSortingEnabled(True) return field_item
class tableWidget(QDialog): def __init__(self, parent=None): super(tableWidget, self).__init__(parent) self.setWindowTitle("QTableWidget en PyQt5 por: ANDRES NIÑO") self.setWindowIcon(QIcon("Qt.png")) self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint | Qt.MSWindowsFixedSizeDialogHint) self.setFixedSize(740, 348) self.initUI() def initUI(self): # ================== WIDGET QTableWidget ================== self.tabla = QTableWidget(self) # Deshabilitar edición self.tabla.setEditTriggers(QAbstractItemView.NoEditTriggers) # Deshabilitar el comportamiento de arrastrar y soltar self.tabla.setDragDropOverwriteMode(False) # Seleccionar toda la fila self.tabla.setSelectionBehavior(QAbstractItemView.SelectRows) # Seleccionar una fila a la vez self.tabla.setSelectionMode(QAbstractItemView.SingleSelection) # Especifica dónde deben aparecer los puntos suspensivos "..." cuando se muestran # textos que no encajan self.tabla.setTextElideMode(Qt.ElideRight)# Qt.ElideNone # Establecer el ajuste de palabras del texto self.tabla.setWordWrap(False) # Deshabilitar clasificación self.tabla.setSortingEnabled(False) # Establecer el número de columnas self.tabla.setColumnCount(6) # Establecer el número de filas self.tabla.setRowCount(0) # Alineación del texto del encabezado self.tabla.horizontalHeader().setDefaultAlignment(Qt.AlignHCenter|Qt.AlignVCenter| Qt.AlignCenter) # Deshabilitar resaltado del texto del encabezado al seleccionar una fila self.tabla.horizontalHeader().setHighlightSections(False) # Hacer que la última sección visible del encabezado ocupa todo el espacio disponible self.tabla.horizontalHeader().setStretchLastSection(True) # Ocultar encabezado vertical self.tabla.verticalHeader().setVisible(False) # Dibujar el fondo usando colores alternados self.tabla.setAlternatingRowColors(True) # Establecer altura de las filas self.tabla.verticalHeader().setDefaultSectionSize(20) # self.tabla.verticalHeader().setHighlightSections(True) nombreColumnas = ("Id","Nombre", "Apellido", "Sexo", "Fecha de nacimiento", "País") # Establecer las etiquetas de encabezado horizontal usando etiquetas self.tabla.setHorizontalHeaderLabels(nombreColumnas) # Menú contextual self.tabla.setContextMenuPolicy(Qt.CustomContextMenu) self.tabla.customContextMenuRequested.connect(self.menuContextual) # Establecer ancho de las columnas for indice, ancho in enumerate((80, 120, 120, 110, 150), start=0): self.tabla.setColumnWidth(indice, ancho) self.tabla.resize(700, 240) self.tabla.move(20, 56) # =================== WIDGETS QPUSHBUTTON ================== botonMostrarDatos = QPushButton("Mostrar datos", self) botonMostrarDatos.setFixedWidth(140) botonMostrarDatos.move(20, 20) menu = QMenu() for indice, columna in enumerate(nombreColumnas, start=0): accion = QAction(columna, menu) accion.setCheckable(True) accion.setChecked(True) accion.setData(indice) menu.addAction(accion) botonMostrarOcultar = QPushButton("Motrar/ocultar columnas", self) botonMostrarOcultar.setFixedWidth(180) botonMostrarOcultar.setMenu(menu) botonMostrarOcultar.move(170, 20) botonEliminarFila = QPushButton("Eliminar fila", self) botonEliminarFila.setFixedWidth(100) botonEliminarFila.move(530, 20) botonLimpiar = QPushButton("Limpiar", self) botonLimpiar.setFixedWidth(80) botonLimpiar.move(640, 20) botonCerrar = QPushButton("Cerrar", self) botonCerrar.setFixedWidth(80) botonCerrar.move(640, 306) # ======================== EVENTOS ========================= botonMostrarDatos.clicked.connect(self.datosTabla) botonEliminarFila.clicked.connect(self.eliminarFila) botonLimpiar.clicked.connect(self.limpiarTabla) botonCerrar.clicked.connect(self.close) self.tabla.itemDoubleClicked.connect(self.Suscribete) menu.triggered.connect(self.mostrarOcultar) # ======================= FUNCIONES ============================ def Suscribete(self, celda): QMessageBox.warning(self, "Suscribirse", "Hola, l@ invito a que se suscriba al " "canal.\nPor cierto hiciste doble clic sobre esta " "celda: {}. ".format(celda.text()), QMessageBox.Ok) def datosTabla(self): datos = [("1", "Andres", "Niño", "Masculino", "06/12/2019", "Colombia"), ("2", "Donald", "Trump", "Masculino", "06/12/1950", "Estados Unidos"), ("3", "María Fernanda", "Espinosa", "Femenino", "06/10/1980", "Ecuador"), ("4", "Alberto", "Canosa", "Masculino", "04/05/1876", "España"), ("5", "Virtud", "Pontes", "Femenino", "23/18/1965", "España"), ("6", "Elon", "Musk", "Masculino", "06/12/1960", "Estados Unidos"), ("7", "Richard", "Branson", "Masculino", "14/12/1956", "Reino Unido"), ("8", "Gabriel", "Garcia Marquez", "Masculino", "19/11/1948", "Colombia"), ("9", "Valentina", "Tereshkova", "Femenino", "06/03/1937", "Rusia"), ("10", "Artur", "Fischer", "Masculino", "31/12/1919", "Alemania"), ("11", "Grace", "Murray Hopper", "Femenino", "09/12/1906", "Estados Unidos"), ("12", "Guido van", "Rossum", "Masculino", "31/01/1956", "Países Bajos")] self.tabla.clearContents() row = 0 for endian in datos: self.tabla.setRowCount(row + 1) idDato = QTableWidgetItem(endian[0]) idDato.setTextAlignment(4) self.tabla.setItem(row, 0, idDato) self.tabla.setItem(row, 1, QTableWidgetItem(endian[1])) self.tabla.setItem(row, 2, QTableWidgetItem(endian[2])) self.tabla.setItem(row, 3, QTableWidgetItem(endian[3])) self.tabla.setItem(row, 4, QTableWidgetItem(endian[4])) self.tabla.setItem(row, 5, QTableWidgetItem(endian[5])) row += 1 def mostrarOcultar(self, accion): columna = accion.data() if accion.isChecked(): self.tabla.setColumnHidden(columna, False) else: self.tabla.setColumnHidden(columna, True) def eliminarFila(self): filaSeleccionada = self.tabla.selectedItems() if filaSeleccionada: fila = filaSeleccionada[0].row() self.tabla.removeRow(fila) self.tabla.clearSelection() else: QMessageBox.critical(self, "Eliminar fila", "Seleccione una fila. ", QMessageBox.Ok) def limpiarTabla(self): self.tabla.clearContents() self.tabla.setRowCount(0) def menuContextual(self, posicion): indices = self.tabla.selectedIndexes() if indices: menu = QMenu() itemsGrupo = QActionGroup(self) itemsGrupo.setExclusive(True) menu.addAction(QAction("Copiar todo", itemsGrupo)) columnas = [self.tabla.horizontalHeaderItem(columna).text() for columna in range(self.tabla.columnCount()) if not self.tabla.isColumnHidden(columna)] copiarIndividual = menu.addMenu("Copiar individual") for indice, item in enumerate(columnas, start=0): accion = QAction(item, itemsGrupo) accion.setData(indice) copiarIndividual.addAction(accion) itemsGrupo.triggered.connect(self.copiarTableWidgetItem) menu.exec_(self.tabla.viewport().mapToGlobal(posicion)) def copiarTableWidgetItem(self, accion): filaSeleccionada = [dato.text() for dato in self.tabla.selectedItems()] if accion.text() == "Copiar todo": filaSeleccionada = tuple(filaSeleccionada) else: filaSeleccionada = filaSeleccionada[accion.data()] print(filaSeleccionada) return
class Menu(QMainWindow): def __init__(self, parent): super().__init__(parent) self.db = DB() self.initUI() def initUI(self): in_class = "menu" self.sidebar = sidebar.Sidebar(self) self.sidebar.window.connect(self.getvalue) self.addDockWidget(Qt.LeftDockWidgetArea, self.sidebar) header = AppName(in_class) footer = Footer() add_and_search = AddSearchFrame(in_class) add_and_search.add_button.clicked.connect(lambda: self.add_menu(in_class)) add_and_search.search_button.clicked.connect( lambda: self.search_menu(add_and_search.search_box)) self.table = QTableWidget() self.table.setColumnCount(5) # self.table.setStyleSheet("border: none") # self.table.setStyleSheet( # "background-color: rgb(255, 255, 255);\n" # 'font: 10pt "MS Shell Dlg 2";\n' # "color: rgb(30, 45, 66);" # ) # self.table.setHorizontalHeaderItem(0, QTableWidgetItem("ID")) self.table.setHorizontalHeaderItem(0, QTableWidgetItem("Food")) self.table.setHorizontalHeaderItem(1, QTableWidgetItem("Category")) self.table.setHorizontalHeaderItem(2, QTableWidgetItem("Price")) # self.table.setHorizontalHeaderItem(3, QTableWidgetItem("Bonus")) # self.table.setHorizontalHeaderItem(3, QTableWidgetItem("Joining Date")) # self.table.setHorizontalHeaderItem(6, QTableWidgetItem("Total Salary")) self.table.setHorizontalHeaderItem(3, QTableWidgetItem("Edit")) self.table.setHorizontalHeaderItem(4, QTableWidgetItem("Delete")) data = self.load_menu_data() print(data) for x in data: print(x) self.populate_table(data) self.table.resizeColumnsToContents() layout = QVBoxLayout() layout.addWidget(header) layout.addWidget(add_and_search) layout.addWidget(self.table) # layout.addStretch() layout.addWidget(footer) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) centralWidget = QWidget() centralWidget.setLayout(layout) self.setCentralWidget(centralWidget) self.setContentsMargins(0, 0, 0, 0) # self.resize(800, 600) self.setWindowTitle("Employee") self.resize(1160, 605) self.show() self.center() def center(self): '''centers the window on the screen''' screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def getvalue(self, value): print(value) print(type(value)) if value == 1: self.hide() view = sidebar.Dashboard(self) elif value == 2: self.hide() view = sidebar.Employee(self) elif value == 3: self.hide() view = sidebar.Table(self) elif value == 4: self.hide() view = sidebar.Reservations(self) elif value == 5: pass elif value == 6: self.hide() view = sidebar.Settings(self) elif value == 7: self.hide() view = sidebar.Orders(self) elif value == 8: self.hide() view = sidebar.Menu(self) elif value == 9: self.hide() view = sidebar.Bill(self) def load_menu_data(self): query = "SELECT food_name, price, category_name FROM menu " \ "join category on menu.category_id = category.id order by category_name" result = self.db.fetch(query) return result ''' This function is called after an employee has been added and returns only the last row. ''' def add_update_menu_data(self): query = "SELECT food_name, price, category_name FROM menu " \ "join category on menu.category_id = category.id " \ "order by id desc limit 1;" result = self.db.fetch(query) return result def edit_menu(self): emp_row = self.table.indexAt(self.sender().pos()) id = self.table.cellWidget(emp_row.row(), emp_row.column()).objectName() print(emp_row.row()) print(id) print(type(id)) ''' Get the data from the database for that user. ''' data = self.get_data(id) print("Data") print(data) # print(type(data[4])) view = AddMenuDetails(self, "update", data[0]) view.nametextbox.setText(data[0]) view.pricetextbox.setText(str(data[1])) category = self.get_category(data[2]) view.category_list.setCurrentText(category) view.closing.connect(self.editupdate_emp) def get_category(self, category): query = "SELECT category_name FROM category " \ "where id=%s" values = (category,) result = self.db.fetch(query, values) for (category) in result: category = category[0] return category def editupdate_emp(self, check): print("I am here") print(check) self.table.clearContents() self.table.setRowCount(0) data = self.load_menu_data() self.populate_table(data) self.table.resizeColumnsToContents() # self.table.resizeColumnsToContents() def get_data(self, id): query = "SELECT food_name, price, category_id FROM menu " \ "where food_name=%s" values = (id,) result = self.db.fetch(query, values) for (food_name, price, category) in result: food_name = food_name price = price category = category return [food_name, price, category] def delete_menu(self): emp_row = self.table.indexAt(self.sender().pos()) # print(emp_row.row()) # print(emp_row.column()) # print(self.table.cellWidget(emp_row.row(), emp_row.column()).objectName()) id = self.table.cellWidget(emp_row.row(), emp_row.column()).objectName() # print(id) # print(emp_row.child(emp_row.row(), emp_row.column())) query = "DELETE FROM menu WHERE food_name=%s" values = (id,) result = self.db.execute(query, values) self.table.clearContents() self.table.setRowCount(0) data = self.load_menu_data() self.populate_table(data) def add_menu(self, where): if where == "menu": print("Employee Button Clicked from Menu") view = AddMenuDetails(self, "add") view.closing.connect(self.update_menu) elif where == "stocks": print("Stock Button Clicked") def search_menu(self, search_obj): search = search_obj.text() search_obj.setText("") print("Search") if search != "": query = "SELECT * FROM menu WHERE food_name like %s" values = ("%" + search + "%",) else: query = "SELECT * FROM menu" values = () self.table.clearContents() self.table.setRowCount(0) data = self.db.fetch(query, values) self.populate_table(data) ''' Repopulates the employee table with the updated data. ''' def update_menu(self, check): print("I am here") print(check) self.table.clearContents() self.table.setRowCount(0) data = self.load_menu_data() self.populate_table(data) ''' This function populates the employee table with data. ''' def populate_table(self, data): for (food_name, price, category_name) in data: self.table.insertRow(self.table.rowCount()) self.table.setItem(self.table.rowCount() - 1, 0, QTableWidgetItem(str(food_name))) self.table.setItem(self.table.rowCount() - 1, 1, QTableWidgetItem(str(category_name))) self.table.setItem(self.table.rowCount() - 1, 2, QTableWidgetItem(str(price))) # self.table.setItem(self.table.rowCount() - 1, 3, QTableWidgetItem(str(bonus))) # self.table.setItem(self.table.rowCount() - 1, 3, QTableWidgetItem(str(joining_date.strftime("%d-%m-%Y")))) edit = QPushButton(self.table) edit.setObjectName(str(food_name)) edit.setStyleSheet("background-color: rgb(50,205,50);") edit.setText("Edit") edit.adjustSize() edit.clicked.connect(self.edit_menu) self.table.setCellWidget(self.table.rowCount() - 1, 3, edit) delete = QPushButton(self.table) delete.setObjectName(str(food_name)) delete.setStyleSheet("background-color: #d63447;") delete.setText("Delete") delete.adjustSize() delete.clicked.connect(self.delete_menu) # delete.mousePressEvent = functools.partial(self.delete_menu, source_object=delete) self.table.setCellWidget(self.table.rowCount() - 1, 4, delete)
class Query_Form(QDialog): #自定义creat_view类继承了QDialog类 def __init__(self, parent=None): #不是QWidget对象但继承了QObject对象要用parent super(Query_Form, self).__init__(parent) #调用QDialog类中_init_变量. 初始化构造函数 #设置界面大小、名称、背景 self.resize(1000, 800) self.setWindowTitle('Database') self.setStyleSheet("background-image:url(tubiao_meitu.jpg)") #窗体属性 self.setWindowFlags(Qt.Widget) #连接数据库 # db = pymysql.connect("localhost", "root", "root", "mrp",charset='utf8') db = pymysql.connect( host='127.0.0.1', port=3308, user='******', password='******', db='mrp', charset='utf8', ) #获取游标、数据 cur = db.cursor() cur.execute("SELECT * FROM 技术要求") data = cur.fetchall() #接收全部的返回结果行 #数据列字段名 tup:数组 #description:种类 col_lst = [tup[0] for tup in cur.description] #数据的大小 row = len(data) #获得data的行数 vol = len(data[0]) #获得data的卷数.第一行的数量(列数) #插入表格 self.MyTable = QTableWidget(row, vol) #row行,vol列的表格 font = QtGui.QFont('微软雅黑', 10) #设置字体、表头 self.MyTable.horizontalHeader().setFont(font) #设置行表头字体 self.MyTable.setHorizontalHeaderLabels(col_lst) #设置标题 #设置竖直方向表头不可见 self.MyTable.verticalHeader().setVisible(False) self.MyTable.setFrameShape(QFrame.NoFrame) #设置表格颜色 # self.MyTable.horizontalHeader().setStyleSheet('QHeaderView::section{background:skyblue}') #构建表格插入数据 for i in range(row): #i到row-1的数量 for j in range(vol): temp_data = data[i][j] # 临时记录,不能直接插入表格 data1 = QTableWidgetItem(str(temp_data)) # 转换后可插入表格 self.MyTable.setItem(i, j, data1) #编辑按钮 self.qle = QLineEdit() buttonBox = QDialogButtonBox() #增删查改四个按钮 addButton = buttonBox.addButton("&增加", QDialogButtonBox.ActionRole) okButton = buttonBox.addButton("&确定", QDialogButtonBox.ActionRole) deleteButton = buttonBox.addButton("&DELETE", QDialogButtonBox.ActionRole) inquireButton = buttonBox.addButton("&查询", QDialogButtonBox.ActionRole) #设置按钮内字体样式 addButton.setFont(font) okButton.setFont(font) deleteButton.setFont(font) inquireButton.setFont(font) #垂直布局 layout = QVBoxLayout() layout.addWidget(self.qle) layout.addWidget(buttonBox) layout.addWidget(self.MyTable) self.setLayout(layout) addButton.clicked.connect(partial(self.add_data, cur, db)) #绑定插入按钮的点击事件 okButton.clicked.connect(partial(self.up_data, cur, db, col_lst)) #更新实现 deleteButton.clicked.connect(partial(self.del_data, cur, db)) #删除实现 inquireButton.clicked.connect(partial(self.inq_data, db)) #查询实现 #partialial传递db #插入空表格 def add_data(self, cur, db): #获取行数 row = self.MyTable.rowCount() #在末尾插入一空行 self.MyTable.insertRow(row) #插入数据 def up_data(self, cur, db, col_lst): row_1 = self.MyTable.rowCount() #表格行数 value_lst = [] #建值列表 for i in range(len(col_lst)): #从i到字段数量的循环 if (len(self.MyTable.item(row_1 - 1, i).text()) == 0): value_lst.append(None) else: value_lst.append(self.MyTable.item(row_1 - 1, i).text()) tup_va_lst = [] #创建数组列表 for cl, va in zip(col_lst, value_lst): tup_va_lst.append((cl, va)) #插入语句 cur.execute( "INSERT INTO 技术要求 VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)", value_lst) #db.commit() 学习这里是否要这句,原代码没有 #删除 def del_data(self, cur, db): #是否删除的对话框 reply = QMessageBox.question(self, 'Message', '你确定要删除数据吗 ?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: #当前行 row_2 = self.MyTable.currentRow() del_d = self.MyTable.item(row_2, 0).text() #在数据库删除数据 # cur.execute("DELETE FROM 技术要求 WHERE ID = '"+del_d+"'") try: #2018-11-21添加 # 执行SQL语句 cur.execute("DELETE FROM 技术要求 WHERE ID = '" + del_d + "'") # 提交到数据库执行 db.commit() except: # 发生错误时回滚 db.rollback() # 关闭数据库连接 db.close() #删除表格 self.MyTable.removeRow(row_2) #查询 def inq_data(self, db): txt = self.qle.text() #模糊查询 if len(txt) != 0: cur = db.cursor() cur.execute( "SELECT * FROM 技术要求 WHERE ID LIKE '%" + txt + "%'" ) # CONCAT('f_id','f_area','f_place','f_AQI','f_AQItype','f_PM25per1h'),concat(concat('%','#txt'),'%') data_x = cur.fetchall() self.MyTable.clearContents() row_4 = len(data_x) vol_1 = len(cur.description) #查询到的更新带表格当中 for i_x in range(row_4): for j_y in range(vol_1): temp_data_1 = data_x[i_x][j_y] # 临时记录,不能直接插入表格 data_1 = QTableWidgetItem(str(temp_data_1)) # 转换后可插入表格 self.MyTable.setItem(i_x, j_y, data_1) #空输入返回原先数据表格 else: self.MyTable.clearContents() cur.execute("SELECT * FROM 技术要求") data_y = cur.fetchall() row_5 = len(data_y) vol_1 = len(cur.description) for i_x_1 in range(row_5): for j_y_1 in range(vol_1): temp_data_2 = data_y[i_x_1][j_y_1] # 临时记录,不能直接插入表格 data_2 = QTableWidgetItem(str(temp_data_2)) # 转换后可插入表格 self.MyTable.setItem(i_x_1, j_y_1, data_2)
class SearchPage(QWidget): def __init__(self, parent): super(QWidget, self).__init__(parent) self.searchMode = 0 self.initDBConnection() self.initUI() def initUI(self): layout = QVBoxLayout(self) functionLayout = QHBoxLayout() functionLayout.setAlignment(Qt.AlignLeft) functionLayout.setSpacing(2) self.searchButton = QPushButton() self.searchButton.setText("Search") self.searchButton.setStyleSheet("QPushButton {max-width: 80px;}") functionLayout.addWidget(self.searchButton) functionLayout.addSpacing(10) matchExpressionLabel = QLabel("Match Expression: ") functionLayout.addWidget(matchExpressionLabel) matchExpressionEdit = QLineEdit() matchExpressionEdit.setStyleSheet( "QLineEdit {max-width: 450px;min-width: 300px;}") matchExpressionEdit.setPlaceholderText( "Eg: (1 & (2 | 3)), Default: (1) or (1 & 2) or ... ") functionLayout.addWidget(matchExpressionEdit) functionLayout.addSpacing(10) caseMatchCheckBox = QCheckBox() caseMatchLabel = QLabel("Match Case") functionLayout.addWidget(caseMatchCheckBox) functionLayout.addSpacing(6) functionLayout.addWidget(caseMatchLabel) functionLayout.addStretch() layout.addLayout(functionLayout) self.mygroupbox = QGroupBox() self.myform = QFormLayout() self.myform.setVerticalSpacing(0) self.myform.setHorizontalSpacing(2) self.labelList = [] self.fieldComboList = [] self.filterComboList = [] self.inputboxList = [] self.plusbuttonlist = [] self.minusbuttonlist = [] relationComboList = [] self.sublayoutList = [] for i in range(3): self.createSearchFilter(i) # self.myform.addRow(self.sublayoutList[i]) #self.mygroupbox.setLayout(self.myform) self.updateSearchFilterForm() scroll = QScrollArea() scroll.setWidget(self.mygroupbox) scroll.setWidgetResizable(True) scroll.setFixedHeight(140) layout.addWidget(scroll) self.mainTable = QTableWidget( 100, 8, self) # create 100x8 table rowNum, colNum self.mainTable.setHorizontalHeaderLabels( ('Year', 'Title', 'Published In', 'Authors', 'Type', 'Added', 'Labels', 'RefID')) self.mainTable.setColumnWidth(0, 60) # Year self.mainTable.setColumnWidth(1, 240) # Title self.mainTable.setColumnWidth(2, 240) # Published In self.mainTable.setColumnWidth(3, 240) # Authors self.mainTable.setColumnWidth(4, 120) # Type self.mainTable.setColumnWidth(5, 120) # Added Date self.mainTable.setColumnWidth(6, 240) # Labels self.mainTable.setColumnWidth(7, 120) # RefAbsID # Table settings self.mainTable.setEditTriggers(QAbstractItemView.NoEditTriggers) self.mainTable.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) self.mainTable.setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.mainTable.setSelectionBehavior(QAbstractItemView.SelectRows) # Connect sorting signal self.mainTable.setSortingEnabled(True) self.mainTable.horizontalHeader().sortIndicatorChanged.connect( self.sortingTable) layout.addWidget(self.mainTable) layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) # Add tabs to widget #self.layout.addWidget(self.scrollArea) #self.setLayout(self.layout) self.appearance = True # Initialize internal signal and slot self.initSignalsSlots() def createSearchFilter(self, ind): self.labelList.insert(ind, QLabel('Key: ' + str(ind + 1))) fieldCombo = QComboBox() fieldChoiceList = [ 'Title', 'Year', 'Published In', 'Author', 'Keywords' ] fieldCombo.addItems(fieldChoiceList) if ind < 3: fieldCombo.setCurrentIndex(ind) else: fieldCombo.setCurrentIndex(0) self.fieldComboList.insert(ind, fieldCombo) filterCombo = QComboBox() filterChoiceList = ['Contains', 'Is'] filterCombo.addItems(filterChoiceList) self.filterComboList.insert(ind, filterCombo) self.inputboxList.insert(ind, QLineEdit()) tempPlusButton = QPushButton() tempPlusButton.setText("+") tempPlusButton.setStyleSheet("QPushButton {background-color: gray; border-color: beige; border-width: 1px;" \ "border-radius: 1px; font: bold 14px; padding: 6px;}") self.plusbuttonlist.insert(ind, tempPlusButton) tempMinusButton = QPushButton() tempMinusButton.setText("-") tempMinusButton.setStyleSheet("QPushButton {background-color: gray; border-color: beige; border-width: 1px;" \ "border-radius: 1px; font: bold 14px; padding: 6px;}") self.minusbuttonlist.insert(ind, tempMinusButton) # Signal and Slot self.plusbuttonlist[ind].clicked.connect( partial(self.onPlusButtonClicked, ind)) self.minusbuttonlist[ind].clicked.connect( partial(self.onMinusButtonClicked, ind)) tempSubLayput = QHBoxLayout() tempSubLayput.addWidget(self.labelList[ind]) tempSubLayput.addWidget(self.fieldComboList[ind]) tempSubLayput.addWidget(self.filterComboList[ind]) tempSubLayput.addWidget(self.inputboxList[ind]) tempSubLayput.addWidget(self.plusbuttonlist[ind]) tempSubLayput.addWidget(self.minusbuttonlist[ind]) self.sublayoutList.insert(ind, tempSubLayput) self.myform.insertRow(ind, self.sublayoutList[ind]) def removeSearchFilter(self, ind): self.labelList.pop(ind) self.fieldComboList.pop(ind) self.filterComboList.pop(ind) self.inputboxList.pop(ind) self.plusbuttonlist.pop(ind) self.minusbuttonlist.pop(ind) self.sublayoutList.pop(ind) self.myform.removeRow(ind) def initSignalsSlots(self): self.searchButton.clicked.connect(self.onSearchButtonClicked) def sortingTable(self, colIndex, order): #print("Column:" + str(colIndex)) if order == Qt.AscendingOrder: pass elif order == Qt.DescendingOrder: pass def initDBConnection(self): database = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Data.db") refs = [] try: self.conn = createConnectionToDB(database) except: buttonReply = QMessageBox.critical( self, 'Alert', "Initialize Info Tab: Database is missing.", QMessageBox.Ok, QMessageBox.Ok) def onPlusButtonClicked(self, buttonId): self.createSearchFilter(buttonId + 1) self.updateSearchFilterForm() def onMinusButtonClicked(self, buttonId): if (buttonId == 0) and (len(self.sublayoutList) == 1): buttonReply = QMessageBox.critical(self, 'Alert', "You need me.", QMessageBox.Ok, QMessageBox.Ok) else: self.removeSearchFilter(buttonId) self.updateSearchFilterForm() def updateSearchFilterForm(self): for i in range(len(self.sublayoutList)): self.labelList[i].setText('Key: ' + str(i + 1)) self.plusbuttonlist[i].clicked.disconnect() self.minusbuttonlist[i].clicked.disconnect() self.plusbuttonlist[i].clicked.connect( partial(self.onPlusButtonClicked, i)) self.minusbuttonlist[i].clicked.connect( partial(self.onMinusButtonClicked, i)) self.mygroupbox.setLayout(self.myform) def onSearchButtonClicked(self): searchTarget = [] for i in range(len(self.inputboxList)): tempStr = self.inputboxList[i].text() if len(tempStr) > 0: searchTarget.append( [self.fieldComboList[i].currentText(), tempStr]) if len(searchTarget) > 0: formattedSearchTarget = self.parseSearchTarget(searchTarget) self.switchSearchMode(formattedSearchTarget) def parseSearchTarget(self, searchTarget): # fieldChoiceList = ['Title', 'Year', 'Published In', 'Author', 'Keywords'] formattedSearchTarget = [] if len(searchTarget) > 0: for tarItem in searchTarget: if tarItem[0] == 'Published In': formattedSearchTarget.append(['PubIn', tarItem[1]]) else: formattedSearchTarget.append(tarItem) return formattedSearchTarget def switchSearchMode(self, searchTarget): # Local search, online search, mix search if self.searchMode == 0: self.databaseSearch(searchTarget) elif self.searchMode == 1: self.mixSearch(searchTarget) else: self.onlineSearch(searchTarget) def databaseSearch(self, searchTarget): foundRefItems = [] foundRefItems = searchRefInDB(self.conn, searchTarget) self.setRefsTable(foundRefItems) def onlineSearch(self, searchTarget): ''' 0: Local Database 1: "Mixed Search", 2: "Google Scholar", 3: "PubMed", 4: "IEEE Xplore", 5: "Science Direct", 6: "arXiv", 7: "Sci-Hub", 8: "More..." ''' foundRefItems = [] if self.searchMode == 2: pass elif self.searchMode == 3: pass elif self.searchMode == 4: pass elif self.searchMode == 5: pass elif self.searchMode == 6: pass elif self.searchMode == 7: pass else: pass self.setRefsTable(foundRefItems) def mixSearch(self, searchTarget): foundRefItems = [] self.setRefsTable(foundRefItems) def setRefsTable(self, refs): # Clean old contents self.mainTable.clearContents() # Must disable sorting table first, otherwise error will occur self.mainTable.setSortingEnabled(False) for rowInd in range(len(refs)): self.mainTable.setItem(rowInd, 0, QTableWidgetItem(str( refs[rowInd]['Year']))) # Year self.mainTable.setItem(rowInd, 1, QTableWidgetItem( refs[rowInd]['Title'])) # Title self.mainTable.setItem(rowInd, 2, QTableWidgetItem( refs[rowInd]['PubIn'])) # PubIn self.mainTable.setItem(rowInd, 3, QTableWidgetItem( refs[rowInd]['Author'])) # Authors self.mainTable.setItem(rowInd, 4, QTableWidgetItem( refs[rowInd]['MType'])) # Type self.mainTable.setItem(rowInd, 5, QTableWidgetItem(refs[rowInd]['AddedTime']) ) # Add Date, change to real field later self.mainTable.setItem(rowInd, 6, QTableWidgetItem( refs[rowInd]['Labels'])) # Labels self.mainTable.setItem( rowInd, 7, QTableWidgetItem(str( refs[rowInd]['RefAbsID']).zfill(10))) # RefAbsID # Enable sorting again. self.mainTable.setSortingEnabled(True)
class FirstTab(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): grid = QGridLayout() grid.addWidget(self.create_order_groupbox(), 0, 0) grid.addWidget(self.create_menu_groupbox(), 0, 1) self.setLayout(grid) # Groupbox: 주문현황 def create_order_groupbox(self): gbox = QGroupBox() gbox.setTitle('주문현황') hbox = QHBoxLayout() vbox = QVBoxLayout() # widget self.cart_table = QTableWidget() self.create_cart_table() vbox.addWidget(self.cart_table) vbox.addLayout(hbox) btn_print_bill = QPushButton('영수증출력', self) btn_cancel_all = QPushButton('전체취소', self) btn_pay_in_cash = QPushButton('현금결제', self) btn_pay_in_card = QPushButton('카드결제', self) # Signal btn_print_bill.clicked.connect(self.print_bill_of_recent_order) btn_cancel_all.clicked.connect(self.cancel_all_in_cart) btn_pay_in_cash.clicked.connect(self.pay_in_cash) btn_pay_in_card.clicked.connect(self.pay_in_credit_card) hbox.addWidget(btn_print_bill) hbox.addWidget(btn_cancel_all) hbox.addWidget(btn_pay_in_cash) hbox.addWidget(btn_pay_in_card) gbox.setLayout(vbox) return gbox # Groupbox: 메뉴선택 def create_menu_groupbox(self): gbox = QGroupBox() gbox.setTitle('메뉴선택') vbox = QVBoxLayout() # widget btns_menu = [] for i in range(len(menu_excel['메뉴명'])): btns_menu.append(QPushButton()) btns_menu[i].setText(menu_excel['메뉴명'][i] + '\n' + str(menu_excel['가격'][i]) + '원') vbox.addWidget(btns_menu[i]) # Signal btns_menu[i].clicked.connect( lambda arg, idx=i: self.add_menu_in_cart(menu_excel['메뉴명'][idx] )) gbox.setLayout(vbox) return gbox # Table Widget: 카트 def create_cart_table(self): header_list = ['메뉴', '수량', '감소', '증가', '직접입력', '단가', '금액', '취소'] self.cart_table.setColumnCount(len(header_list)) self.cart_table.setRowCount(len(menu_excel['메뉴명']) + 1) self.cart_table.setHorizontalHeaderLabels(header_list) self.cart_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.cart_table.setItem(4, 0, QTableWidgetItem('Total')) self.cart_table.setItem(4, 1, QTableWidgetItem(str(cal.return_total_qty()))) self.cart_table.setItem( 4, 6, QTableWidgetItem(str(cal.return_total_amount()))) # Slot @pyqtSlot() def set_item_in_cart_table(self): self.cart_table.clearContents() self.cart_table.setItem(4, 0, QTableWidgetItem('Total')) self.cart_table.setItem(4, 1, QTableWidgetItem(str(cal.return_total_qty()))) self.cart_table.setItem( 4, 6, QTableWidgetItem(str(cal.return_total_amount()))) btns_minus = [] btns_add = [] btns_input = [] btns_cancel = [] row_int = 0 if len(cal.cart_list) != 0: for i in range(len(cal.cart_list)): if cal.cart_list[i] not in cal.cart_list[:i]: btns_minus.append(QPushButton('-', self)) btns_add.append(QPushButton('+', self)) btns_input.append(QPushButton('수량입력', self)) btns_cancel.append(QPushButton('x', self)) self.cart_table.setItem(row_int, 0, QTableWidgetItem(cal.cart_list[i])) self.cart_table.setItem( row_int, 1, QTableWidgetItem( str(cal.return_menu_qty(cal.cart_list[i])))) self.cart_table.setItem( row_int, 5, QTableWidgetItem( str(cal.return_menu_cost(cal.cart_list[i])))) self.cart_table.setItem( row_int, 6, QTableWidgetItem( str(cal.return_menu_amount(cal.cart_list[i])))) self.cart_table.setCellWidget(row_int, 2, btns_minus[row_int]) self.cart_table.setCellWidget(row_int, 3, btns_add[row_int]) self.cart_table.setCellWidget(row_int, 4, btns_input[row_int]) self.cart_table.setCellWidget(row_int, 7, btns_cancel[row_int]) # Signal btns_minus[row_int].clicked.connect( lambda: self.minus_menu_in_cart(cal.cart_list[i])) btns_add[row_int].clicked.connect( lambda: self.add_menu_in_cart(cal.cart_list[i])) btns_input[row_int].clicked.connect( lambda: self.input_menu_in_cart(cal.cart_list[i])) btns_cancel[row_int].clicked.connect( lambda: self.cancel_menu_in_cart(cal.cart_list[i])) row_int += 1 @pyqtSlot(str) def add_menu_in_cart(self, menu_str): cal.add_qty(menu_str) self.set_item_in_cart_table() @pyqtSlot(str) def minus_menu_in_cart(self, menu_str): cal.minus_qty(menu_str) self.set_item_in_cart_table() @pyqtSlot(str) def input_menu_in_cart(self, menu_str): input_int, ok = QInputDialog.getInt(self, '수량 직접입력', menu_str + '의 수량을 입력하세요.', min=0) if ok: cal.input_qty(menu_str, input_int) self.set_item_in_cart_table() @pyqtSlot(str) def cancel_menu_in_cart(self, menu_str): cal.cancel_qty(menu_str) self.set_item_in_cart_table() @pyqtSlot() def cancel_all_in_cart(self): cal.cancel_all_qty() self.set_item_in_cart_table() @pyqtSlot() def print_bill_of_recent_order(self): msg = QMessageBox.information(self, '영수증출력', str(rec.receipt_df), QMessageBox.Ok, QMessageBox.Ok) @pyqtSlot() def pay_in_cash(self): if len(cal.cart_list) == 0: self.warn_pay_zero() else: cash, ok = QInputDialog.getInt(self, '현금결제', '결제할 금액: ' + \ str(cal.return_total_amount()) + '원' + '\n' + \ '받은 금액을 입력하세요.', min=cal.return_total_amount()) if ok: reply = QMessageBox.question(self, '현금결제: 거스름돈', '결제할 금액: ' + str(cal.return_total_amount()) + '원' + '\n' + \ '받은 금액: ' + str(cash) + '원' + '\n' + \ '거스름돈: ' + str(cash - cal.return_total_amount()) + '원' + '\n' + \ '이대로 결제합니까?', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: self.complete_payment('현금') @pyqtSlot() def pay_in_credit_card(self): if len(cal.cart_list) == 0: self.warn_pay_zero() else: reply = QMessageBox.question( self, '카드결제', '결제할 금액: ' + str(cal.return_total_amount()) + '원' + '\n' + '카드로 결제합니까?', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: self.complete_payment('카드') @pyqtSlot() def warn_pay_zero(self): msg = QMessageBox.information(self, '결제금액 경고', '결제금액은 0원일 수 없습니다.', QMessageBox.Ok, QMessageBox.Ok) @pyqtSlot(str) def complete_payment(self, payment_method_str): rec.receive_order(payment_method_str) msg = QMessageBox.information( self, '결제완료', '결제수단: ' + payment_method_str + '\n' + '결제가 완료되었습니다.', QMessageBox.Ok, QMessageBox.Ok) self.set_item_in_cart_table()
class MMWindow(QMainWindow): """Main Window class.""" def __init__(self): """Class initializer.""" super(MMWindow, self).__init__() # App data structures # Create the Media list object self.media_list = MediaList() # Variables for calculating total progress self.time_jump = 0.0 self.partial_time = 0.0 self.total_time = 0.0 self.total_duration = 0.0 # App interface setup # Window size self.resize(680, 576) # Set window title self.setWindowTitle('VideoMorph' + ' ' + VERSION) # Define and set app icon icon = QIcon() icon.addPixmap(QPixmap(':/logo/images/videomorph.png')) self.setWindowIcon(icon) # Define app central widget self.central_widget = QWidget(self) # Difine layouts self.vl = QVBoxLayout(self.central_widget) self.hl = QHBoxLayout() self.vl1 = QVBoxLayout() self.vl2 = QVBoxLayout() # Define groups self.group_settings() self.fix_layout() self.group_tasks_list() self.group_output_directory() self.group_progress() # Create the toolbar self.create_toolbar() # Add layouts self.hl.addLayout(self.vl2) self.vl.addLayout(self.hl) # Set central widget self.setCentralWidget(self.central_widget) # Create actions self.create_actions() # Populate PROFILES combo box self.populate_profiles() # Default conversion library self.conversion_lib = CONV_LIB.ffmpeg # Read app settings self.read_app_settings() # Create the converter according to the user selection of # conversion library self.converter = Converter(media_list=self.media_list, conversion_lib=self.conversion_lib) self.converter.process.setProcessChannelMode(QProcess.MergedChannels) self.converter.process.readyRead.connect(self._read_encoding_output) self.converter.process.finished.connect(self.finish_file_encoding) # Disable presets and profiles combo boxes self.cb_presets.setEnabled(False) self.cb_profiles.setEnabled(False) # Create app main menu bar self.create_main_menu() # Create app status bar self.create_status_bar() # Set tool buttons style self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) def group_settings(self): """Settings group.""" gb_settings = QGroupBox(self.central_widget) gb_settings.setTitle(self.tr('Conversion Presets')) size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth( gb_settings.sizePolicy().hasHeightForWidth()) gb_settings.setSizePolicy(size_policy) hl = QHBoxLayout(gb_settings) vl = QVBoxLayout() hl1 = QHBoxLayout() label = QLabel(self.tr('Convert to:')) hl1.addWidget(label) spacer_item = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) hl1.addItem(spacer_item) vl.addLayout(hl1) self.cb_profiles = QComboBox( gb_settings, statusTip=self.tr('Select the desired video format')) self.cb_profiles.setMinimumSize(QSize(200, 0)) vl.addWidget(self.cb_profiles) hl2 = QHBoxLayout() label = QLabel(self.tr('Target Quality:')) hl2.addWidget(label) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) hl2.addItem(spacerItem1) vl.addLayout(hl2) self.cb_presets = QComboBox( gb_settings, statusTip=self.tr('Select the desired video quality')) self.cb_presets.setMinimumSize(QSize(200, 0)) self.cb_profiles.currentIndexChanged.connect(partial( self.populate_presets, self.cb_presets)) self.cb_presets.activated.connect(self.update_media_files_status) vl.addWidget(self.cb_presets) hl.addLayout(vl) self.vl1.addWidget(gb_settings) def fix_layout(self): """Fix widgets layout.""" spacer_item = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.vl1.addItem(spacer_item) self.hl.addLayout(self.vl1) def group_tasks_list(self): """Define the Tasks Group arrangement.""" gb_tasks = QGroupBox(self.central_widget) gb_tasks.setTitle(self.tr('List of Conversion Tasks')) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(gb_tasks.sizePolicy().hasHeightForWidth()) gb_tasks.setSizePolicy(sizePolicy) hl = QHBoxLayout(gb_tasks) self.tb_tasks = QTableWidget(gb_tasks) self.tb_tasks.setColumnCount(4) self.tb_tasks.setRowCount(0) self.tb_tasks.setSelectionMode(QAbstractItemView.SingleSelection) self.tb_tasks.setSelectionBehavior(QAbstractItemView.SelectRows) self.tb_tasks.horizontalHeader().setSectionResizeMode( 0, QHeaderView.Stretch) self.tb_tasks.setHorizontalHeaderLabels( [self.tr('File Name'), self.tr('Duration'), self.tr('Target Quality'), self.tr('Progress')]) self.tb_tasks.cellClicked.connect(self._enable_remove_file_action) # Create a combo box for Target quality self.tb_tasks.setItemDelegate(TargetQualityDelegate(parent=self)) hl.addWidget(self.tb_tasks) self.vl2.addWidget(gb_tasks) self.tb_tasks.doubleClicked.connect(self.update_edit_triggers) def update_edit_triggers(self): if (int(self.tb_tasks.currentColumn()) == QUALITY and not self.converter.is_running): self.tb_tasks.setEditTriggers(QAbstractItemView.AllEditTriggers) else: self.tb_tasks.setEditTriggers(QAbstractItemView.NoEditTriggers) def group_output_directory(self): """Define the output directory Group arrangement.""" gb_output = QGroupBox(self.central_widget) gb_output.setTitle(self.tr('Output Directory')) vl = QVBoxLayout(gb_output) vl1 = QVBoxLayout() hl = QHBoxLayout() self.le_output = QLineEdit( str(QDir.homePath()), statusTip=self.tr('Choose Output Directory')) self.le_output.setReadOnly(True) hl.addWidget(self.le_output) self.tb_output = QToolButton( gb_output, statusTip=self.tr('Choose Output Directory')) self.tb_output.setText('...') self.tb_output.clicked.connect(self.output_directory) hl.addWidget(self.tb_output) vl1.addLayout(hl) vl.addLayout(vl1) self.vl2.addWidget(gb_output) def group_progress(self): """Define the Progress Group arrangement.""" gb_progress = QGroupBox(self.central_widget) gb_progress.setTitle(self.tr('Progress')) vl = QVBoxLayout(gb_progress) label_progress = QLabel(gb_progress) label_progress.setText(self.tr('Operation Progress')) vl.addWidget(label_progress) self.pb_progress = QProgressBar(gb_progress) self.pb_progress.setProperty('value', 0) vl.addWidget(self.pb_progress) label_total_progress = QLabel(gb_progress) label_total_progress.setText(self.tr('Total Progress')) vl.addWidget(label_total_progress) self.pb_total_progress = QProgressBar(gb_progress) self.pb_total_progress.setProperty('value', 0) vl.addWidget(self.pb_total_progress) self.vl2.addWidget(gb_progress) def read_app_settings(self): """Read the app settings.""" settings = QSettings(QDir.homePath() + '/.videomorph/config.ini', QSettings.IniFormat) pos = settings.value("pos", QPoint(600, 200), type=QPoint) size = settings.value("size", QSize(1096, 510), type=QSize) self.resize(size) self.move(pos) if 'profile' and 'preset' in settings.allKeys(): prof = settings.value('profile') pres = settings.value('preset') self.cb_profiles.setCurrentIndex(int(prof)) self.cb_presets.setCurrentIndex(int(pres)) if 'output_dir' in settings.allKeys(): self.le_output.setText(str(settings.value('output_dir'))) if 'conversion_lib' in settings.allKeys(): self.conversion_lib = settings.value('conversion_lib') def write_app_settings(self): """Write app settings on exit.""" settings = QSettings(QDir.homePath() + '/.videomorph/config.ini', QSettings.IniFormat) settings.setValue("pos", self.pos()) settings.setValue("size", self.size()) settings.setValue("profile", self.cb_profiles.currentIndex()) settings.setValue("preset", self.cb_presets.currentIndex()) settings.setValue("output_dir", self.le_output.text()) settings.setValue('conversion_lib', self.conversion_lib) def closeEvent(self, event): """Things to todo on close.""" # Disconnect the finished signal self.converter.process.finished.disconnect(self.finish_file_encoding) # Close communication and kill the encoding process if self.converter.is_running: self.converter.process.close() self.converter.process.kill() # Save settings self.write_app_settings() event.accept() def check_conversion_lib(self): """Check if ffmpeg or/and avconv are installed on the system.""" if which(CONV_LIB.ffmpeg) or which(CONV_LIB.avconv): return True else: msg_box = QMessageBox( QMessageBox.Critical, self.tr('Error!'), self.tr('ffmpeg or avconv libraries not found in your system'), QMessageBox.NoButton, self) msg_box.addButton("&Ok", QMessageBox.AcceptRole) if msg_box.exec_() == QMessageBox.AcceptRole: qApp.closeAllWindows() return False def create_actions(self): """Create the actions and connect them to the tool bar buttons.""" self.add_media_file_action = QAction( # Remove this line to use costume icons self.style().standardIcon(QStyle.SP_DialogOpenButton), self.tr('&Open'), self, shortcut="Ctrl+O", enabled=True, statusTip=self.tr('Add video files to the ' 'list of conversion tasks'), triggered=self.add_media) # Uncomment this line to use costume icons # self.add_media_file_action.setIcon(QIcon(':/icons/images/abrir.png')) self.clear_media_list_action = QAction( # Remove this line to use costume icons self.style().standardIcon(QStyle.SP_TrashIcon), self.tr('Clear &List'), self, shortcut="Ctrl+Del", enabled=False, statusTip=self.tr('Clear the Media List'), triggered=self.clear_media_list) # Uncomment this line to use costume icons # self.clear_media_list_action.setIcon(QIcon(':/icons/images/limpiar.png')) self.remove_media_file_action = QAction( # Remove this line to use costume icons self.style().standardIcon(QStyle.SP_BrowserStop), self.tr('&Remove File'), self, shortcut="Del", enabled=False, statusTip=self.tr('Remove Video Files from the List'), triggered=self.remove_media_file) # Uncomment this line to use costume icons # self.remove_media_file_action.setIcon(QIcon(':/icons/images/eliminar.png')) self.convert_action = QAction( # Remove this line to use costume icons self.style().standardIcon(QStyle.SP_MediaPlay), self.tr('&Convert'), self, shortcut="Ctrl+R", enabled=False, statusTip=self.tr('Start Conversion Process'), triggered=self.start_encoding) # Uncomment this line to use costume icons # self.convert_action.setIcon(QIcon(':/icons/images/convertir.png')) self.stop_action = QAction( # Remove this line to use costume icons self.style().standardIcon(QStyle.SP_MediaStop), self.tr('&Stop'), self, shortcut="Ctrl+P", enabled=False, statusTip=self.tr('Stop Video File Conversion'), triggered=self.stop_file_encoding) # Uncomment this line to use costume icons # self.stop_action.setIcon(QIcon(':/icons/images/parar.png')) self.about_action = QAction( # Remove this line to use costume icons self.style().standardIcon(QStyle.SP_MessageBoxInformation), self.tr('&About'), self, shortcut="Ctrl+H", enabled=True, statusTip=self.tr('About VideoMorph {v}'.format(v=VERSION)), triggered=self.about) # Uncomment this line to use costume icons # self.about_action.setIcon(QIcon(':/icons/images/parar.png')) self.exit_action = QAction( self.style().standardIcon(QStyle.SP_DialogCloseButton), self.tr('E&xit'), self, shortcut="Ctrl+Q", enabled=True, statusTip=self.tr('Exit VideoMorph {v}'.format(v=VERSION)), triggered=self.close) self.settings_action = QAction( self.style().standardIcon(QStyle.SP_FileDialogDetailedView), self.tr('&Settings...'), self, shortcut="Ctrl+S", enabled=True, statusTip=self.tr('Open VideoMorph {v} Settings Dialog'.format( v=VERSION)), triggered=self.settings) # Add actions to the tool bar self.tool_bar.addAction(self.add_media_file_action) self.tool_bar.addSeparator() self.tool_bar.addAction(self.clear_media_list_action) self.tool_bar.addAction(self.remove_media_file_action) self.tool_bar.addSeparator() self.tool_bar.addAction(self.convert_action) self.tool_bar.addAction(self.stop_action) self.tool_bar.addSeparator() self.tool_bar.addAction(self.settings_action) def create_main_menu(self): self.file_menu = self.menuBar().addMenu(self.tr('&File')) self.file_menu.addAction(self.add_media_file_action) self.file_menu.addSeparator() self.file_menu.addAction(self.settings_action) self.file_menu.addSeparator() self.file_menu.addAction(self.exit_action) self.edit_menu = self.menuBar().addMenu(self.tr('&Edit')) self.edit_menu.addAction(self.clear_media_list_action) self.edit_menu.addAction(self.remove_media_file_action) self.convert_menu = self.menuBar().addMenu(self.tr('&Conversion')) self.convert_menu.addAction(self.convert_action) self.convert_menu.addAction(self.stop_action) self.hel_menu = self.menuBar().addMenu(self.tr('&Help')) self.hel_menu.addAction(self.about_action) def create_toolbar(self): """Create and add_file a tool bar to the interface.""" self.tool_bar = QToolBar(self) self.addToolBar(Qt.TopToolBarArea, self.tool_bar) def create_status_bar(self): self.statusBar().showMessage(self.tr('Ready')) def about(self): a = AboutVM(parent=self) a.exec_() def settings(self): s = SettingsDialog(parent=self) if self.conversion_lib == CONV_LIB.ffmpeg: s.radio_btn_ffmpeg.setChecked(True) elif self.conversion_lib == CONV_LIB.avconv: s.radio_btn_avconv.setChecked(True) if not which(CONV_LIB.ffmpeg): s.radio_btn_ffmpeg.setEnabled(False) elif not which(CONV_LIB.avconv): s.radio_btn_avconv.setEnabled(False) if s.exec_(): if s.radio_btn_ffmpeg.isChecked(): self.conversion_lib = CONV_LIB.ffmpeg self.converter.conversion_lib = self.conversion_lib elif s.radio_btn_avconv.isChecked(): self.conversion_lib = CONV_LIB.avconv self.converter.conversion_lib = self.conversion_lib def get_prober(self): if self.conversion_lib == CONV_LIB.ffmpeg: return 'ffprobe' elif self.conversion_lib == CONV_LIB.avconv: return 'avprobe' def populate_profiles(self): """Populate profiles combo box.""" self.cb_profiles.addItems(PROFILES.keys()) def populate_presets(self, cb_presets): """Populate presets combo box.""" profile = self.cb_profiles.currentText() cb_presets.clear() for preset in PROFILES[profile].presets: cb_presets.addItem(preset) self.update_media_files_status() def output_directory(self): """Choose output directory.""" options = QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly directory = QFileDialog.getExistingDirectory( self, self.tr('Choose Output Directory'), QDir.homePath(), options=options) if directory: self.le_output.setText(directory) def add_media(self): """Add media files to the list of conversion tasks.""" # Dialog title title = self.tr('Select Files') # Media filters v_filter = (self.tr('Video files') + '(*.mkv *.ogg *.mp4 *.mpg *.dat ' '*.f4v *.flv *.wv *.3gp *.avi *.webm ' '*.wmv *.mov *.vob *.ogv *.ts)') # Select media files and store their path media_paths, _ = QFileDialog.getOpenFileNames(self, title, QDir.homePath(), v_filter) # If no file is selected then return if not media_paths: return # Count rows in the tasks table rows = self.tb_tasks.rowCount() # This rewind the encoding list if the encoding process is not running if not self.converter.is_running: self.media_list.running_index = -1 # Add selected medias to the table and to MediaList using threads to # minimize delay threads = [] for media_path in media_paths: t = MediaFileThread( media_path=media_path, target_quality=str(self.cb_presets.currentText()), prober=self.get_prober()) t.start() threads.append(t) for t in threads: t.join() for thread in threads: try: self.media_list.add_file(thread.media_file) self.tb_tasks.setRowCount(rows + 1) except FileAddedError: del thread.media_file continue # Test if the file was added to the list # (0 duration files are not added) if thread.media_file in self.media_list: item = QTableWidgetItem() item.setText(thread.media_file.get_name(with_extension=True)) self.tb_tasks.setItem(rows, NAME, item) item = QTableWidgetItem() file_duration = str( write_time(thread.media_file.info.format_duration)) item.setText(file_duration) self.tb_tasks.setItem(rows, DURATION, item) item = QTableWidgetItem() item.setText(str(self.cb_presets.currentText())) self.tb_tasks.setItem(rows, QUALITY, item) item = QTableWidgetItem() item.setText(self.tr('To convert')) self.tb_tasks.setItem(rows, PROGRESS, item) # Next table row rows += 1 # After adding files to the list, recalculate the list duration self.total_duration = self.media_list.duration # Update tool buttons so you can convert, or add_file, or clear... self.update_interface(stop=False, remove=False) def remove_media_file(self): """Remove selected media file from the list.""" item = self.tb_tasks.currentItem().row() if item is not None: # Delete file from table self.tb_tasks.removeRow(item) # If all files are deleted... update the interface if not self.tb_tasks.rowCount(): self.update_interface(convert=False, clear=False, remove=False, stop=False, presets=False, profiles=False) # Remove file from MediaList self.media_list.delete_file(file_index=item) self.total_duration = self.media_list.duration def clear_media_list(self): """Clear media conversion list with user confirmation.""" msg_box = QMessageBox( QMessageBox.Warning, self.tr('Warning!'), self.tr('Clear all tasks?'), QMessageBox.NoButton, self) msg_box.addButton(self.tr("&Yes"), QMessageBox.AcceptRole) msg_box.addButton(self.tr("&No"), QMessageBox.RejectRole) if msg_box.exec_() == QMessageBox.AcceptRole: # If use says YES clear table of conversion tasks self.tb_tasks.clearContents() self.tb_tasks.setRowCount(0) # Clear MediaList.medias so it does not contain any element self.media_list.clear() # Update buttons so user cannot convert, clear, or stop if there # is no file in the list self.update_interface(convert=False, clear=False, remove=False, stop=False, presets=False, profiles=False) def start_encoding(self): """Start the encoding process.""" # Update tool buttons state self.update_interface(presets=False, profiles=False, convert=False, clear=False, remove=False, output_dir=False, settings=False) # Increment the the MediaList index self.media_list.running_index += 1 running_media = self.media_list.get_running_file() if (not running_media.status == STATUS.done and not running_media.status == STATUS.stopped): self.converter.start_encoding( cmd=self.media_list.get_running_file().get_conversion_cmd( output_dir=self.le_output.text())) else: self.end_encoding_process() def stop_file_encoding(self): """Stop file encoding process and continue with the list.""" # Set MediaFile.status attribute self.media_list.get_running_file().status = STATUS.stopped # Update the list duration and partial time for total progress bar self.total_duration = self.media_list.duration self.time_jump = 0.0 self.partial_time = 0.0 self.total_time = 0.0 # Terminate the file encoding self.converter.stop_encoding() def finish_file_encoding(self): """Finish the file encoding process.""" if not self.media_list.get_running_file().status == STATUS.stopped: # Close and kill the converter process self.converter.process.close() # Check if the process finished OK if self.converter.process.exitStatus() == QProcess.NormalExit: # When finished a file conversion... self.tb_tasks.item(self.media_list.running_index, 3).setText( self.tr('Done!')) self.media_list.get_running_file().status = STATUS.done self.pb_progress.setProperty("value", 0) # Attempt to end the conversion process self.end_encoding_process() else: # If the process was stopped if not self.converter.is_running: self.tb_tasks.item(self.media_list.running_index, 3).setText( self.tr('Stopped!')) # Attempt to end the conversion process self.end_encoding_process() def end_encoding_process(self): # Test if encoding process is finished if self.converter.encoding_done: msg_box = QMessageBox( QMessageBox.Information, self.tr('Finished!'), self.tr('Encoding process successfully finished!'), QMessageBox.Ok, self) msg_box.show() self.statusBar().showMessage(self.tr('Ready')) # Reset all progress related variables self.pb_progress.setProperty("value", 0) self.pb_total_progress.setProperty("value", 0) self.time_jump = 0.0 self.partial_time = 0.0 self.total_time = 0.0 self.total_duration = self.media_list.duration # Reset the running_index self.media_list.running_index = -1 # Update tool buttons self.update_interface(convert=False, stop=False, remove=False) else: self.start_encoding() def _read_encoding_output(self): """Read the encoding output from the self.converter stdout.""" time_pattern = re.compile(r'time=([0-9.:]+) ') ret = str(self.converter.process.readAll()) time = time_pattern.findall(ret) if time: # Convert time to seconds if ':' in time[0]: time_in_secs = 0 for part in time[0].split(':'): time_in_secs = 60 * time_in_secs + float(part) else: time_in_secs = float(time[0]) # Calculate operation progress percent op_time = self.media_list.get_running_file().info.format_duration operation_progress = int(time_in_secs / float(op_time) * 100) # Update the table and the operation progress bar self.pb_progress.setProperty("value", operation_progress) self.tb_tasks.item(self.media_list.running_index, 3).setText( str(operation_progress) + "%") # Calculate total time if self.partial_time > time_in_secs: self.time_jump += self.partial_time self.total_time = self.time_jump + time_in_secs self.partial_time = time_in_secs else: self.total_time = self.time_jump + time_in_secs self.partial_time = time_in_secs # Calculate total progress percent total_progress = int(self.total_time / float(self.total_duration) * 100) # Update the total progress bar self.pb_total_progress.setProperty("value", total_progress) self.statusBar().showMessage( self.tr('Converting: {m}\t\t\t ' 'Operation remaining time: {rt}\t\t\t ' 'Total remaining time: {trt}').format( m=self.media_list.get_running_file().get_name(True), rt=write_time(float(op_time) - time_in_secs), trt=write_time( self.total_duration - self.total_time))) # TODO: Review this and setEditorData for repeated code def update_media_files_status(self): """Update target Quality.""" # Current item item = self.tb_tasks.currentItem() if item is not None: # Update target_quality in table self.tb_tasks.item(item.row(), QUALITY).setText( str(self.cb_presets.currentText())) # Update file target_quality self.media_list.get_file(item.row()).target_quality = str( self.cb_presets.currentText()) # Update table Progress field if file is: Done or Stopped if (self.media_list.get_file_status(item.row()) == STATUS.done or self.media_list.get_file_status( item.row()) == STATUS.stopped): self.tb_tasks.item(item.row(), PROGRESS).setText( self.tr('To convert')) # Update file Done or Stopped status self.media_list.set_file_status(file_index=item.row(), status=STATUS.todo) # Update total duration of the new tasks list self.total_duration = self.media_list.duration # Update the interface self.update_interface(clear=False, stop=False, remove=False) else: if self.tb_tasks.rowCount(): for i in range(self.tb_tasks.rowCount()): self.tb_tasks.item(i, QUALITY).setText( str(self.cb_presets.currentText())) if (self.media_list.get_file_status(i) == STATUS.done or self.media_list.get_file_status( i) == STATUS.stopped): self.tb_tasks.item(i, PROGRESS).setText( self.tr('To convert')) self.media_list.get_file(i).target_quality = str( self.cb_presets.currentText()) self.update_interface(clear=False, stop=False, remove=False) self._set_media_status() self.total_duration = self.media_list.duration def _set_media_status(self): """Update media files state of conversion.""" for media_ in self.media_list: media_.status = STATUS.todo self.media_list.running_index = -1 def update_interface(self, add=True, convert=True, clear=True, remove=True, stop=True, presets=True, profiles=True, output_dir=True, settings=True): self.add_media_file_action.setEnabled(add) self.convert_action.setEnabled(convert) self.clear_media_list_action.setEnabled(clear) self.remove_media_file_action.setEnabled(remove) self.stop_action.setEnabled(stop) self.cb_presets.setEnabled(presets) self.cb_profiles.setEnabled(profiles) self.tb_output.setEnabled(output_dir) self.tb_tasks.setCurrentItem(None) self.settings_action.setEnabled(settings) def _enable_remove_file_action(self): if not self.converter.is_running: self.remove_media_file_action.setEnabled(True)