class SetPolicyWidget(QWidget): Sg_view_changed = Signal() def __init__(self, model: SettingsModel, parent=None): super(SetPolicyWidget, self).__init__(parent) self._model = model self.setAccessibleName("InfoBox") self.titolo = QLabel("Politica di gestione conflitti") self.titolo.setAccessibleName('Title2') self.sottotitolo = QLabel("Cambia come vengono gestiti conflitti") self.sottotitolo.setAccessibleName('Sottotitolo') self.spaceLabel = QLabel(" ") self.client = QRadioButton( "Client: le modifiche in locale sovrascrivono quelle presenti nel server" ) self.manual = QRadioButton( "Manuale: verranno salvati entrambi i file, sarà l'utente a decidere cosa mantenere" ) self.Sl_model_changed() layout = QVBoxLayout() layout.addWidget(self.titolo) layout.addWidget(self.sottotitolo) layout.addWidget(self.spaceLabel) sub_layout = QVBoxLayout() sub_layout.addWidget(self.client) sub_layout.addWidget(self.manual) layout.addLayout(sub_layout) self.setLayout(layout) self.client.clicked.connect(self.Sl_client_checked) self.manual.clicked.connect(self.Sl_manual_checked) @Slot() def Sl_client_checked(self): if self.client.isChecked(): self.Sg_view_changed.emit() @Slot() def Sl_manual_checked(self): if self.manual.isChecked(): self.Sg_view_changed.emit() @Slot() def Sl_model_changed(self): if self._model.get_policy() == Policy.Manual: self.client.setChecked(False) self.manual.setChecked(True) else: self.client.setChecked(True) self.manual.setChecked(False)
class ReferenceDialog(QDialog): def __init__(self, parent): super().__init__(parent) self.setWindowTitle("Set reference") vbox = QVBoxLayout(self) grid = QGridLayout() self.average = QRadioButton("Average") self.channels = QRadioButton("Channel(s):") self.average.toggled.connect(self.toggle) self.channellist = QLineEdit() self.channellist.setEnabled(False) self.average.setChecked(True) grid.addWidget(self.average, 0, 0) grid.addWidget(self.channels, 1, 0) grid.addWidget(self.channellist, 1, 1) vbox.addLayout(grid) buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) vbox.addWidget(buttonbox) buttonbox.accepted.connect(self.accept) buttonbox.rejected.connect(self.reject) vbox.setSizeConstraint(QVBoxLayout.SetFixedSize) def toggle(self): if self.average.isChecked(): self.channellist.setEnabled(False) else: self.channellist.setEnabled(True)
class Importador(QWidget): """GUI class for the BGG -> Ludopedia importer""" enable_editables = Signal(bool) alternative_chosen = Signal(object) def __init__(self, parent=None): super().__init__(parent) self.thread = QThread() self.worker = None grid_layout = QGridLayout(self) login_group_box = self.create_login_group() data_group_box = self.create_data_group() self.enable_editables.connect(login_group_box.setEnabled) self.enable_editables.connect(data_group_box.setEnabled) self.import_button = QPushButton('Importar', self) self.import_button.setEnabled(False) self.enable_editables.connect(self.import_button.setEnabled) self.import_button.clicked.connect(self.enable_editables) self.import_button.clicked.connect(self.load_data) self.bgg_user_line_edit.textChanged.connect(self.enable_import) self.ludo_mail_line_edit.textChanged.connect(self.enable_import) self.ludo_pass_line_edit.textChanged.connect(self.enable_import) grid_layout.addWidget(login_group_box, 1, 1, 1, 2) grid_layout.addWidget(data_group_box, 2, 1, 1, 2) grid_layout.addWidget(self.import_button, 8, 2) self.log_widget = QTextEdit(self) self.log_widget.setReadOnly(True) grid_layout.addWidget(self.log_widget, 9, 1, 30, 2) def create_qlineedit(self, text): """Creates a label with the given text and an accompanying line edit""" line_edit = QLineEdit(self) line_edit_label = QLabel(text, line_edit) line_edit_label.setBuddy(line_edit) return (line_edit, line_edit_label) def create_login_group(self): """Create labels and line edits for providing BGG and ludopedia login information""" (self.bgg_user_line_edit, bgg_user_label) = self.create_qlineedit('Usuario BoardGameGeek:') (self.ludo_mail_line_edit, ludo_mail_label) = self.create_qlineedit('E-mail Ludopedia:') (self.ludo_pass_line_edit, ludo_pass_label) = self.create_qlineedit('Senha Ludopedia:') self.ludo_pass_line_edit.setEchoMode(QLineEdit.PasswordEchoOnEdit) group_box = QGroupBox('Login') grid_layout = QGridLayout(group_box) grid_layout.addWidget(bgg_user_label, 1, 1) grid_layout.addWidget(self.bgg_user_line_edit, 1, 2) grid_layout.addWidget(ludo_mail_label, 2, 1) grid_layout.addWidget(self.ludo_mail_line_edit, 2, 2) grid_layout.addWidget(ludo_pass_label, 3, 1) grid_layout.addWidget(self.ludo_pass_line_edit, 3, 2) group_box.setLayout(grid_layout) return group_box def create_data_group(self): """Creates group for holding specific choice data selection""" button_group = QButtonGroup(self) button_group.setExclusive(True) colecao_radio_button = QRadioButton('Coleção') self.partidas_radio_button = QRadioButton('Partidas') colecao_radio_button.setChecked(True) button_group.addButton(colecao_radio_button) button_group.addButton(self.partidas_radio_button) (self.min_date_picker, min_date_label) = create_date_picker('À Partir de:', self) (self.max_date_picker, max_date_label) = create_date_picker('Até:', self) self.min_date_picker.dateChanged.connect( self.max_date_picker.setMinimumDate) colecao_radio_button.toggled.connect(self.min_date_picker.setDisabled) colecao_radio_button.toggled.connect(self.max_date_picker.setDisabled) self.map_users_button = QPushButton( 'Ver mapa de usuarios BGG -> Ludopedia', self) self.map_users_button.setEnabled(False) self.map_users_button.clicked.connect(self.user_map) colecao_radio_button.toggled.connect(self.map_users_button.setDisabled) group_box = QGroupBox('Dados') grid_layout = QGridLayout(group_box) grid_layout.addWidget(colecao_radio_button, 1, 1) grid_layout.addWidget(self.partidas_radio_button, 1, 2) grid_layout.addWidget(min_date_label, 2, 1) grid_layout.addWidget(self.min_date_picker, 2, 2) grid_layout.addWidget(max_date_label, 3, 1) grid_layout.addWidget(self.max_date_picker, 3, 2) grid_layout.addWidget(self.map_users_button, 4, 1, 1, 2) group_box.setLayout(grid_layout) return group_box def enable_import(self): """Slot to toggle state of the import button""" self.import_button.setDisabled(not self.bgg_user_line_edit.text() or not self.ludo_mail_line_edit.text() or not self.ludo_pass_line_edit.text()) def log_text(self, message_type, text): """Logs the given text to the QPlainTextWidget""" current_time = QTime.currentTime().toString() if message_type == MessageType.ERROR: self.log_widget.insertHtml( f'[{current_time}] {ERROR_HTML}{text}<br>') elif message_type == MessageType.GENERIC: self.log_widget.insertHtml(f'[{current_time}] {text}<br>') elif message_type == MessageType.DEBUG and ENABLE_DEBUG: self.log_widget.insertHtml( f'[{current_time}] {DEBUG_HTML}{text}<br>') self.log_widget.moveCursor(QTextCursor.End) if ENABLE_DEBUG: print(text) def disconnect_thread(self): """Disconnect the started signal from the thread""" self.thread.started.disconnect() def configure_thread(self, worker): """Does basic thread startup and cleanup configuration""" worker.finished.connect(self.thread.quit) worker.moveToThread(self.thread) self.thread.started.connect(worker.run) worker.message.connect(self.log_text) worker.finished.connect(self.disconnect_thread) worker.exit_on_error.connect(self.thread.quit) worker.exit_on_error.connect(lambda: self.enable_editables.emit(True)) def load_data(self): """Load data from bgg""" try: (session, ludo_user_id) = self.login_ludopedia() bgg_user = self.bgg_user_line_edit.text() if self.partidas_radio_button.isChecked(): current_date = format_qdate(QDate.currentDate()) min_date = parse_date( format_qdate(self.min_date_picker.date()), current_date) max_date = parse_date( format_qdate(self.max_date_picker.date()), min_date) self.worker = BGGPlayFetcher(bgg_user, min_date, max_date) self.configure_thread(self.worker) self.worker.finished.connect(lambda plays: self.post_plays( session, plays, bgg_user, ludo_user_id)) else: self.worker = BGGColectionFetcher(bgg_user) self.configure_thread(self.worker) self.worker.finished.connect( lambda bgg_collection: self.import_collection( session, bgg_collection)) self.thread.start() except InputError: self.enable_editables.emit(True) def show_play_table(self, plays): """Shows a table with all the plays to be imported, allowing user to select some to skip""" tree_model = PlayTableModel(plays) table_widget = QTableView() table_widget.setModel(tree_model) table_widget.verticalHeader().setVisible(False) table_view_header = table_widget.horizontalHeader() table_view_header.setStretchLastSection(True) for column in range(tree_model.columnCount()): column_size = tree_model.data(tree_model.index(0, column), PlayTableModel.SIZE_ROLE) table_view_header.resizeSection(column, column_size) table_widget_dialog = QDialog(self) table_widget_dialog.setModal(True) grid_layout = QGridLayout(table_widget_dialog) grid_layout.addWidget(table_widget, 1, 1) table_widget_dialog.resize(800, 600) table_widget_dialog.exec_() skipped_plays = tree_model.get_skipped_plays() return [play for play in plays if play.id not in skipped_plays] def post_plays(self, session, plays, bgg_user, ludo_user_id): """Receives plays from the Play Fetched thread and start the Ludopedia Logger""" user_map = self.get_bgg_to_ludo_users() if bgg_user not in user_map: user_map[bgg_user] = ludo_user_id selected_plays = self.show_play_table(plays) self.worker = LudopediaPlayLogger(session, selected_plays, bgg_user, user_map) self.worker.request_search.connect( self.request_search_and_show_alternatives, Qt.BlockingQueuedConnection) self.worker.request_alternative.connect(self.request_alternative, Qt.BlockingQueuedConnection) self.alternative_chosen.connect(self.worker.receive_alternative, Qt.DirectConnection) self.configure_thread(self.worker) self.worker.finished.connect(lambda: self.enable_editables.emit(True)) self.thread.start() def user_map(self): """Slot to show user map from bgg to ludopedia""" user_map_dialog = QDialog(self) user_map_dialog.setModal(True) bgg_to_ludo = self.get_bgg_to_ludo_users() user_list = [f'{key} -> {value}' for key, value in bgg_to_ludo.items()] list_widget = QListWidget(user_map_dialog) list_widget.addItems(user_list) list_widget.setResizeMode(QListView.Adjust) list_widget.sortItems() grid_layout = QGridLayout(user_map_dialog) grid_layout.addWidget(list_widget, 1, 1) user_map_dialog.resize(400, 400) user_map_dialog.show() def login_ludopedia(self): """Logins into Ludopedia manually and returns the session and user_id""" self.log_text(MessageType.GENERIC, 'Obtendo dados do Ludopedia') payload = { 'email': self.ludo_mail_line_edit.text(), 'pass': self.ludo_pass_line_edit.text() } session = requests.Session() session_request = session.post(LUDOPEDIA_LOGIN_URL, data=payload) if 'senha incorretos' in session_request.text: self.log_text( MessageType.ERROR, 'Não foi possível logar na Ludopedia com as informações fornecidas' ) raise InputError user_re = re.search(r'id_usuario=(\d+)', session_request.text) user_id = user_re.group(1) if user_re else None return (session, user_id) def import_collection(self, session, collection): """Imports a given collection into Ludopedia""" self.worker = LudopediaCollectionLogger(session, collection) self.configure_thread(self.worker) self.worker.finished.connect(lambda: self.enable_editables.emit(True)) self.thread.start() def show_alternatives_dialog(self, bgg_play, data): """Show alternative games to use as the game to log a play""" alternatives_dialog = QInputDialog(self) alternatives_list = [ f'{item["nm_jogo"]} ({item["ano_publicacao"]})' for item in data ] alternatives_dialog.setComboBoxItems(alternatives_list) alternatives_dialog.setOption(QInputDialog.UseListViewForComboBoxItems) game_str = f'{bgg_play.game_name} ({bgg_play.year_published})' alternatives_dialog.setLabelText( f'Escolha uma alternativa para o jogo "{game_str}"') if alternatives_dialog.exec_(): selected_index = alternatives_list.index( alternatives_dialog.textValue()) return data[selected_index] return None def request_search_and_show_alternatives(self, session, bgg_play): """Request a new string to use for game search and then show results to be picked""" new_search_dialog = QInputDialog(self) game_str = f'{bgg_play.game_name} ({bgg_play.year_published})' new_search_dialog.setLabelText( f'Jogo "{game_str}" não encontrado\nBuscar por:') new_search_dialog.setInputMode(QInputDialog.TextInput) if new_search_dialog.exec_(): data = search_ludopedia_games(session, new_search_dialog.textValue()) data = self.show_alternatives_dialog(bgg_play, data) self.alternative_chosen.emit(data) def request_alternative(self, bgg_play, data): """Request an alternative from user and emit choice""" alternative = self.show_alternatives_dialog(bgg_play, data) self.alternative_chosen.emit(alternative) def get_bgg_to_ludo_users(self): """Reads usuarios.txt file to map a bgg user to its corresponding ludopedia one""" try: parser = ConfigParser() with open("usuarios.txt") as lines: lines = chain(("[top]", ), lines) parser.read_file(lines) bgg_to_ludo_user = dict(parser['top']) bgg_to_ludo_user_id = dict() for bgg_user, ludo_user in bgg_to_ludo_user.items(): if is_invalid_bgg_user(bgg_user): self.log_text( MessageType.ERROR, f'Usuário do BGG "{bgg_user}" inválido' f' no mapa de usuários') continue if ludo_user.isdigit(): bgg_to_ludo_user_id[bgg_user] = ludo_user self.log_text( MessageType.DEBUG, f'Usuário do BGG "{bgg_user}" já mapeado' f' ao id ludopedia: {ludo_user}') else: ludo_user_id = get_ludo_user_id(ludo_user) if ludo_user_id: self.log_text(MessageType.DEBUG, f'{ludo_user_id} para {ludo_user}') bgg_to_ludo_user_id[bgg_user] = ludo_user_id else: self.log_text( MessageType.ERROR, f'Falha ao buscar id de usuario da' f' ludopedia para "{ludo_user}"') return bgg_to_ludo_user_id except FileNotFoundError: self.log_error( MessageType.ERROR, 'Não foi possível encontrar o arquivo "usuarios.txt') return {}
class Maker(QWidget): def __init__(self, parent=None): super(Maker, self).__init__(parent) self.setWindowTitle("Project Maker") self.userFilepath = QLineEdit() self.userFilepath.setPlaceholderText("Your filepath here...") self.projName = QLineEdit() self.projName.setPlaceholderText("Your project name here...") self.makeButton = QPushButton("Create Project") self.fileSearchButton = QPushButton("...") self.fileSearchButton.setToolTip( "Search for a directory for your project") self.goProj = QRadioButton("Go Project") self.goProj.setToolTip("You will still need a go.mod file") self.pyProj = QRadioButton("Python Project") self.versionControlFiles = QCheckBox( "Create README.md and .gitignore?") self.versionControlFiles.setToolTip( "Creates the files used in online version control, such as Github") self.pyProj.setChecked(True) self.versionControlFiles.setChecked(True) projSelect = QGroupBox("Project Selection") projectOptions = QVBoxLayout() projectOptions.addWidget(self.pyProj) projectOptions.addWidget(self.goProj) projectOptions.addWidget(self.versionControlFiles) projectOptions.stretch(1) projSelect.setLayout(projectOptions) searchLayout = QHBoxLayout() searchLayout.addWidget(self.userFilepath) searchLayout.addWidget(self.fileSearchButton) searchLayout.stretch(1) layout = QVBoxLayout() layout.addLayout(searchLayout) layout.addWidget(self.projName) layout.addWidget(self.makeButton) layout.addWidget(self.fileSearchButton) layout.addWidget(projSelect) self.setLayout(layout) self.makeButton.clicked.connect(self.createFiles) self.fileSearchButton.clicked.connect(self.onClickFileSearch) @Slot() def onClickFileSearch(self): fileSearch = QFileDialog.getExistingDirectory(self, "Select a Directory...", "C:/Users") self.userFilepath.setText(fileSearch) @Slot() def createFiles(self): p = Path(f"{self.userFilepath.text()}/{self.projName.text()}") try: p.mkdir() except FileExistsError as exc: msgbox = QMessageBox() msgbox.setText(f"{exc}") msgbox.exec() else: os.chdir(f"{self.userFilepath.text()}\\{self.projName.text()}") if self.pyProj.isChecked(): fileType = "py" elif self.goProj.isChecked(): fileType = "go" with open(f"{self.projName.text()}.{fileType}", "w") as f: f.write(f"# Created on {date.today()}") if self.versionControlFiles.isChecked(): open("README.md", "a").close() open(".gitignore", "a").close()
class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) # Variaveis self.separador = ";" # Separador padrao de colunas em um arquivo txt ou csv self.selected = np.array([1, 24, 48, 96]).astype('timedelta64[h]') # selecionados ao iniciar o programa, modificavel. self.fileformat = '' # Reservado para o formato do arquivo a ser aberto. Pode ser .xlsx ou .odf. ou .csv e assim vai. # facilita o acesso a variavel. self.timedeltastr = ("1 Hora","2 Horas", "3 Horas", "4 Horas","12 Horas", "24 Horas", "48 Horas", "72 horas", "96 horas", "30 Dias") self.timedeltas = np.array([1, 2, 3, 4, 12, 24, 48, 72, 96, 24*30]).astype('timedelta64[h]') self.linktimedelta = dict([(self.timedeltas[x], self.timedeltastr[x]) for x in range(len(self.timedeltastr))]) self.datastring = ["DD/MM/AAAA",'AAAA/MM/DD', "AAAA-MM-DD", "DD-MM-AAAA"] self.dataformat = ["%d/%m/%Y", "%Y/%m/%d", "%Y-%m-%d", "%d-%m-%Y"] self.linkdata = dict([(self.datastring[x], self.dataformat[x]) for x in range(len(self.dataformat))]) self.timestring = ["hh:mm", "hh:mm:ss", "hh:mm:ss.ms"] self.timeformat = ["%H:%M", "%H:%M:%S", "%H:%M:%S.%f"] self.linktime = dict([(self.timestring[x], self.timeformat[x]) for x in range(len(self.timeformat))]) #Janela Principal widget = QWidget() self.setCentralWidget(widget) # Inicializa os Widgets self.folder = QLineEdit("Salvar Como...") self.path = QLineEdit("Abrir arquivo...") # buttonOpen = QPushButton('Abrir') buttonSave = QPushButton("Destino") Processar = QPushButton('Executar') Ajuda = QPushButton('Informações') # groupBox2 = QGroupBox("Delimitador") self.delimitador1 = QRadioButton("Ponto-Vírgula") self.delimitador2 = QRadioButton("Vírgula") self.delimitador3 = QRadioButton("Ponto") self.delimitador4 = QRadioButton("Tabulação") # checkGroup = QGroupBox("Mais opções") text3 = QPushButton("Configurações") text2 = QLabel("Formato da Data") text1 = QLabel("Formato da Hora") self.FormatoTime = QComboBox() self.FormatoTime.addItems(self.timestring) self.FormatoData = QComboBox() self.FormatoData.addItems(self.datastring) # text = QLabel("Por favor, selecione na tabela abaixo as colunas a utilizar:") self.ignore = QRadioButton("Possui Cabeçalho") # True se estiver selecionado, False caso nao # self.Tabela = QTableWidget(15,15) self.startTable() # Layouts MainLayout = QVBoxLayout() Gridlayout = QGridLayout() Gridlayout.addWidget(self.path, 0, 0) Gridlayout.addWidget(self.folder, 1, 0) Gridlayout.addWidget(buttonOpen, 0, 1) Gridlayout.addWidget(buttonSave, 1, 1) Gridlayout.addWidget(Processar, 0, 3) Gridlayout.addWidget(Ajuda, 1, 3) Gridlayout.setColumnStretch(0, 2) Gridlayout.setColumnStretch(3, 1) Gridlayout.setColumnMinimumWidth(2, 20) SecondLayout = QHBoxLayout() SecondLayout.addWidget(groupBox2) SecondLayout.addSpacing(40) SecondLayout.addWidget(checkGroup) # SepLayout = QVBoxLayout() SepLayout.addWidget(self.delimitador1) SepLayout.addWidget(self.delimitador2) SepLayout.addWidget(self.delimitador3) SepLayout.addWidget(self.delimitador4) # OptionsLayout = QVBoxLayout() OptionsLayout.addWidget(text3) OptionsLayout.addWidget(text2) OptionsLayout.addWidget(self.FormatoData) OptionsLayout.addWidget(text1) OptionsLayout.addWidget(self.FormatoTime) ThirdLayout = QVBoxLayout() ThirdLayout.addWidget(self.ignore) ThirdLayout.addWidget(text) MainLayout.addLayout(Gridlayout) MainLayout.addLayout(SecondLayout) MainLayout.addLayout(ThirdLayout) MainLayout.addWidget(self.Tabela) # Coloca o Layout principal na Janela widget.setLayout(MainLayout) # Comandos dos Widgets e edicoes. groupBox2.setLayout(SepLayout) self.delimitador1.setChecked(True) self.folder.setReadOnly(True) self.path.setReadOnly(True) checkGroup.setLayout(OptionsLayout) buttonOpen.clicked.connect(self.searchFile) buttonSave.clicked.connect(self.getNewFile) self.delimitador1.clicked.connect(self.updateDelimiter) self.delimitador2.clicked.connect(self.updateDelimiter) self.delimitador3.clicked.connect(self.updateDelimiter) self.delimitador4.clicked.connect(self.updateDelimiter) Ajuda.clicked.connect(self.help) Processar.clicked.connect(self.taskStart) text3.clicked.connect(self.openSubWindow) # Propriedades da janela principal height = 480 width = 640 myappid = 'GePlu.release1_0.0' # arbitrary string ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid) self.setWindowIcon(QIcon(r'images\icon6.ico')) self.setFixedSize(width, height) self.setWindowTitle("GePlu") def openSubWindow(self): dialog = MyDialog(self) dialog.show() dialog.exec_() def taskStart(self): ''' Inicia a execucao do programa, se houver algum erro durante o processo notifica o usuario e deixa a funcao imediatamente''' if self.folder.isModified() and self.path.isModified(): # o usuario entrou com os enderecos? start = time.time() # Conhece do que se trata cada coluna na tabela e armazena essa informacao. header = {} for col in range(15): header[self.Tabela.cellWidget(0, col).currentText()] = col boolean = 0 if self.ignore.isChecked() else None # Le o arquivo e retorna um dataframe de strings df_master = utils.read_file(self, header = boolean) df_master = dt.data_filter(self, df_master, header) df_master = dt.convert_dtype(self, df_master) # Computa os acumulados para cada intervalo de tempo (key). for key in self.selected: array = dt.compute(df_master.index.to_numpy(), df_master['Observado'].to_numpy(), key) df_master[self.linktimedelta[key]] = pd.Series(array, df_master.index) # salva o arquivo final. utils.save_file(self, df_master) # Fim do processo end = time.time() # Notifica o usuario QMessageBox.information(self, "Notificação", "Tarefa realizada com sucesso!\nTempo de execução: {} s.".format(round(end-start, 2))) # Reseta a tabela e os endereço do arquivo aberto e onde salvar, na janela principal. self.resetProgram() else: QMessageBox.warning(self, "Notificação", "Houve um erro no arquivo ou diretório especificado.\nPor favor, selecione um caminho válido.") def help(self): x = 'Caso tenha alguma dúvida, abra o documento em PDF presente\nna pasta do programa ou entre em contato.\n\nGeplu\n1.0.0' msgBox = QMessageBox.information(self, "Informação", x) def resetProgram(self): self.Tabela.clearContents() self.startTable() self.folder.setText("Salvar Como...") self.path.setText("Selecionar o arquivo...") self.folder.setModified(False) self.folder.setModified(False) def updateDelimiter(self): separadores = {"Ponto-Vírgula": ';', "Vírgula":",", "Ponto":".", "Tabulação":"\t"} for x in [self.delimitador1, self.delimitador3, self.delimitador2, self.delimitador4]: if x.isChecked(): self.separador = separadores[x.text()] break if self.path.isModified(): self.updateTable() def startTable(self): for col in range(self.Tabela.columnCount()): combo = QComboBox() combo.addItems(["Selecionar","Data & Hora","Prec. Observada","Data","Hora","Nível do Rio"]) self.Tabela.setCellWidget(0, col, combo) def updateTable(self): # Guarda a primeira linha n_col = self.Tabela.columnCount() textos = [0]*n_col for col in range(n_col): textos[col] = self.Tabela.cellWidget(0, col).currentText() self.Tabela.clearContents() self.startTable() for col in range(n_col): self.Tabela.cellWidget(0, col).setCurrentText(textos[col]) # Mostra na tabela as primeiras 14 linhas do arquivo que o usuario deseja abrir/utilizar. data_df = utils.read_file(self, 14).to_numpy() for row in range(data_df.shape[0]): for col in range(data_df.shape[1]): self.Tabela.setItem(row+1, col, QTableWidgetItem(data_df[row][col])) def searchFile(self): address, x = QFileDialog.getOpenFileName(self, "Selecione um arquivo", filter = "Text files (*.txt *.csv *.xlsx)" ) if len(address) > 0: self.path.setText(address) self.path.setModified(True) self.fileformat = address[address.index('.'):] self.updateTable() def getNewFile(self): address, x = QFileDialog.getSaveFileName(self, "Salvar como", filter = "Text files (*.csv);; Text files (*.txt);; Planilha do Microsoft Excel (*.xlsx)" ) if len(address) > 0: self.folder.setText(address) self.folder.setModified(True)