class DownloadComponent(QGroupBox): reportFormatChanged = Signal(ReportWriter) saveCompleted = Signal(bool) def __init__(self): super().__init__() self._report_writer = None self._report_writer_thread = ReportWriterThread() self._report_writer_thread.completed.connect(self._saveCompleted) self._progress_message = ProgressMessageBox(self.parentWidget(), "Export des données en cours...", "Export des données en cours...", 0, 0) self._report_types = { "summary": {"name": "Résumé", "description": "Le résumé inclu les statistiques générales sur les images analysées"}, "full": {"name": "Complet", "description": "Le rapport complet inclu les statistiques détaillées sur les images analysées"}, "annotations": {"name": "Annotations", "description": "Converti les résultats de l'analyse en annotation utilisable pour l'entrainement"} } self._report_formats = { "summary": { "PDF": {"type": "Document PDF", "extension": "*.pdf"}, "Texte": {"type": "Fichier texte", "extension": "*.txt"} }, "full": { "CSV": {"type": "Fichier CSV", "extension": "*.csv"}, "JSON": {"type": "Fichier JSON", "extension": "*.json"}, "XML": {"type": "Fichier XML", "extension": "*.xml"}, }, "annotations": { "Annotations YOLOv4": {"type": "Fichier zip", "extension": "*.zip"} } } self._default_report_type = "summary" self.setTitle("Paramètres") self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) self._form_layout = QFormLayout() self._form_layout.setHorizontalSpacing(20) self._form_layout.setVerticalSpacing(14) self._report_type_cbox = QComboBox() for report_type, v in self._report_types.items(): self._report_type_cbox.addItem(v["name"], report_type) self._form_layout.addRow("Type de rapport :", self._report_type_cbox) self._info_text = QLabel(self._report_types[self._default_report_type]["description"]) self._info_text.setObjectName("info") self._form_layout.addRow(self._info_text) self._report_format_cbox = QComboBox() for format, data in self._report_formats[self._default_report_type].items(): self._report_format_cbox.addItem(format, data) self._form_layout.addRow("Format du rapport :", self._report_format_cbox) self._detection_shape_cbox = QComboBox() self._detection_shape_cbox.addItem("Rectangle", "rectangle") self._detection_shape_cbox.addItem("Cercle", "circle") self._detection_shape_cbox.hide() self._separator_cbox = QComboBox() self._separator_cbox.addItem("Point virgule", ";") self._separator_cbox.addItem("Virgule", ",") self._separator_cbox.hide() self._nb_keeped_spinbox = QSpinBox(self) self._nb_keeped_spinbox.setRange(1, 1) self._nb_keeped_spinbox.hide() download_button = StylizedButton("Télécharger", "blue") download_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) button_layout = QHBoxLayout() button_layout.setAlignment(Qt.AlignRight) button_layout.addWidget(download_button) main_layout = QVBoxLayout(self) main_layout.addLayout(self._form_layout) main_layout.addStretch(1) main_layout.addLayout(button_layout) # Signals download_button.clicked.connect(self._exportReport) self._report_type_cbox.currentIndexChanged.connect(self._reportTypeChanged) self._report_format_cbox.currentTextChanged.connect(self._reportFormatChanged) self._detection_shape_cbox.currentIndexChanged.connect(self._reportParamsChanged) self._separator_cbox.currentIndexChanged.connect(self._reportParamsChanged) def reset(self, analysis: Analysis): self._analysis = analysis self._report_type_cbox.setCurrentIndex(0) self._report_format_cbox.setCurrentIndex(0) self._nb_keeped_spinbox.setMaximum(analysis.imagesWithDetections()) self._nb_keeped_spinbox.setValue(min(100, analysis.imagesWithDetections())) self._loadWriter() def _loadWriter(self): format_text = self._report_format_cbox.currentText() if format_text == "PDF": self._report_writer = PDFReportWriter(self._analysis) elif format_text == "Texte": self._report_writer = TextReportWriter(self._analysis) elif format_text == "CSV": self._report_writer = CSVReportWriter(self._analysis, self._separator_cbox.currentData(), self._detection_shape_cbox.currentData()) elif format_text == "JSON": self._report_writer = JSONReportWriter(self._analysis, shape=self._detection_shape_cbox.currentData()) elif format_text == "XML": self._report_writer = XMLReportWriter(self._analysis, shape=self._detection_shape_cbox.currentData()) elif format_text == "Annotations YOLOv4": self._report_writer = Yolov4AnnotationsWriter(self._analysis) self.reportFormatChanged.emit(self._report_writer) @Slot(int) def _reportTypeChanged(self, index: int): report_type = self._report_type_cbox.currentData() self._info_text.setText(self._report_types[report_type]["description"]) self._report_format_cbox.clear() for format, data in self._report_formats[report_type].items(): self._report_format_cbox.addItem(format, data) if report_type == "summary": self._showDetectionShape(False) self._showSeparator(False) self._showKeepedNumber(False) elif report_type == "full": self._showDetectionShape(True) self._showKeepedNumber(False) elif report_type == "annotations": self._showDetectionShape(False) self._showSeparator(False) self._showKeepedNumber(True) @Slot(str) def _reportFormatChanged(self, format: str): if format == "CSV": self._showSeparator(True) else: # JSON & XSML self._showSeparator(False) self._loadWriter() def _showDetectionShape(self, show: bool): self._showRow("Détection :", self._detection_shape_cbox, show) def _showSeparator(self, show: bool): self._showRow("Séparateur :", self._separator_cbox, show) def _showKeepedNumber(self, show: bool): self._showRow("Images à exporter :", self._nb_keeped_spinbox, show) def _showRow(self, label: str, widget: QWidget, show: bool): if show and not widget.isVisible(): widget.show() self._form_layout.addRow(label, widget) elif not show and widget.isVisible(): label = self._form_layout.labelForField(widget) widget.hide() label.hide() self._form_layout.removeWidget(widget) self._form_layout.removeWidget(label) del label @Slot(int) def _reportParamsChanged(self, index: int): self._loadWriter() @Slot() def _exportReport(self): report_type = self._report_type_cbox.currentData() if report_type == "annotations": self._report_writer.setKeep(self._nb_keeped_spinbox.value()) error = self._report_writer.checkErrors() if error: QMessageBox.warning(self.parentWidget(), "Impossible de générer le rapport", error) return filename = self._analysis.parameters().name() report_format = self._report_format_cbox.currentData() path = QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation) + "/" + filename filter = "Fichier %s (%s)" % (report_format["type"], report_format["extension"]) result = QFileDialog.getSaveFileName(self, "Enregistrer le fichier", path, filter) filepath = result[0] if filepath == '': return self._report_writer_thread.start(self._report_writer, filepath) self._progress_message.exec_() @Slot() def _saveCompleted(self, success: bool): if self._progress_message: self._progress_message.close() self.saveCompleted.emit(success)
class _RemoveNanEditor(AbsOperationEditor): _baseText = { 0: 'Remove with more than: <b>{}</b> nan', 1: 'Remove with more than: <b>{}%</b> nan' } def __init__(self, mode: str, parent: QWidget = None): """ Builds the editor :param mode: one of 'col' or 'row' :param parent: a parent widget """ self.__mode: str = mode super().__init__(parent) def editorBody(self) -> QWidget: self.__group = QButtonGroup() self.__group.setExclusive(True) lab = QLabel('Choose how to remove:') self.__group.addButton(QRadioButton('By number'), id=0) self.__group.addButton(QRadioButton('By percentage'), id=1) self.__currId = None self.__summaryLabel = QLabel() self.__slider = QSlider(Qt.Horizontal, self) self.__slider.setMinimum(0) self.__slider.setTracking(True) self.__slider.setSingleStep(1) self.__numBox = QSpinBox() self.__numBox.setMinimum(0) self.__numBox.setMaximum(10000000) radioLayout = QHBoxLayout() radioLayout.addWidget(self.__group.button(0)) radioLayout.addWidget(self.__group.button(1)) self.__bodyLayout = QVBoxLayout() self.__bodyLayout.addWidget(lab) self.__bodyLayout.addLayout(radioLayout) self.__bodyLayout.addSpacing(20) self.__bodyLayout.addWidget(QLabel('Move the slider to set removal parameter:')) self.__bodyLayout.addSpacing(10) self.__bodyLayout.addWidget(self.__slider if self.__mode == 'row' else self.__numBox) self.__bodyLayout.addWidget(self.__summaryLabel) self.__group.buttonClicked[int].connect(self._toggleMode) # Both are connected, only one is shown self.__slider.valueChanged.connect(self._onValueChanged) self.__numBox.valueChanged[int].connect(self._onValueChanged) # Set a default button and label text self.__group.button(0).click() self.__summaryLabel.setText(self._baseText[0].format(self.__slider.minimum())) body = QWidget() body.setLayout(self.__bodyLayout) return body @Slot(int) def _toggleMode(self, bid: int) -> None: # NOTE: could be refactored if bid == self.__currId: return self.__currId = bid if bid == 0: if not (self.inputShapes and self.inputShapes[0]) and self.__mode == 'row': self.__slider.setDisabled(True) self._onValueChanged(self.__slider.value()) elif not self.__slider.isEnabled(): self.__slider.setEnabled(True) else: if self.__mode == 'row': self.__slider.setMaximum(self.inputShapes[0].nColumns) self._onValueChanged(self.__slider.value()) else: self.__bodyLayout.replaceWidget(self.__slider, self.__numBox) self.__slider.hide() self.__numBox.show() self._onValueChanged(self.__numBox.value()) else: if self.__mode == 'row': if not self.__slider.isEnabled(): self.__slider.setEnabled(True) else: self.__bodyLayout.replaceWidget(self.__numBox, self.__slider) self.__numBox.hide() self.__slider.show() self._onValueChanged(self.__slider.value()) self.__slider.setMaximum(100) @Slot(int) def _onValueChanged(self, value: int): self.__summaryLabel.setText(self._baseText[self.__currId].format(value)) def getOptions(self) -> Iterable: if self.__group.checkedId() == 0: # By number return None, self.__slider.value() if self.__mode == 'row' else self.__numBox.value() else: # By perc return self.__slider.value() / 100, None def setOptions(self, percentage: float, number: int) -> None: if percentage is not None: self.__group.button(1).click() self.__slider.setValue(percentage * 100) elif number is not None: self.__group.button(0).click() self.__slider.setValue(number) if self.__mode == 'row' else self.__numBox.setValue(number) else: # Both None self.__slider.setValue(0) self.__numBox.setValue(0) def refresh(self) -> None: if self.__mode == 'row' and self.__group.checkedId() == 0: self.__slider.setMaximum(self.inputShapes[0].nColumns) self.__slider.setEnabled(True)
class Bucket(QWidget): IMG_EMPTY = QIcon("img/Empty_bucket.svg") IMG_FULL = QIcon("img/Full_bucket.svg") IMG_HALF = QIcon("img/Half_full_bucket.svg") selected = Signal(object) removed = Signal(object) def __init__(self, capacity, init, goal): super().__init__() self.capacity = capacity self.init = init self.current = init self.goal = goal self.editable = False self.btn = QPushButton() self.btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.btn.clicked.connect(self.select) self.layout = QVBoxLayout() self.layout.addWidget(self.btn) self.btn_remove = QPushButton("X") self.btn_remove.clicked.connect(self.remove) self.layout.addWidget(self.btn_remove) self.edit_capacity = QSpinBox() self.edit_capacity.setPrefix("Capacity ") self.edit_capacity.setSuffix(" L") self.edit_capacity.valueChanged.connect(self.change_capacity) self.layout.addWidget(self.edit_capacity) self.edit_capacity.hide() self.edit_init = QSpinBox() self.edit_init.setPrefix("Init ") self.edit_init.setSuffix(" L") self.edit_init.valueChanged.connect(self.change_init) self.layout.addWidget(self.edit_init) self.edit_init.hide() self.edit_goal = QSpinBox() self.edit_goal.setPrefix("Goal ") self.edit_goal.setSuffix(" L") self.edit_goal.valueChanged.connect(self.change_goal) self.layout.addWidget(self.edit_goal) self.edit_goal.hide() self.update() self.setLayout(self.layout) def switch_editable(self): self.editable = not self.editable if self.editable: self.edit_capacity.show() self.edit_init.show() self.edit_goal.show() self.btn.setEnabled(False) else: self.edit_capacity.hide() self.edit_init.hide() self.edit_goal.hide() self.btn.setEnabled(True) def change_capacity(self, capacity): self.capacity = capacity self.update() def change_init(self, init): self.init = init self.current = init self.update() def change_goal(self, goal): self.goal = goal self.update() def reset(self): self.current = self.init self.update() def remove(self): self.removed.emit(self) def select(self): self.selected.emit(self) def update(self): self.update_spin() self.update_image() self.update_text() def update_spin(self): self.edit_capacity.setValue(self.capacity) self.edit_capacity.setMinimum(self.init) self.edit_init.setValue(self.init) self.edit_init.setMaximum(self.capacity) self.edit_goal.setValue(self.goal) self.edit_goal.setMaximum(self.capacity) def update_text(self): self.btn.setText(f"{self.current} ({self.goal}) / {self.capacity} L") def update_image(self): if self.current == 0: self.btn.setIcon(self.IMG_EMPTY) elif self.current == self.capacity: self.btn.setIcon(self.IMG_FULL) else: self.btn.setIcon(self.IMG_HALF) def emptying(self, bucket): value = min([self.current, bucket.capacity - bucket.current]) self.current -= value self.update() bucket.current += value bucket.update() def full(self): return self.capacity == self.current def good(self): return self.goal == self.current def changed_color(self, actived=False, color=Qt.blue): pal = QPushButton().palette() # self.btn if actived: pal.setColor(QPalette.Button, QColor(color)) elif self.good(): pal.setColor(QPalette.Button, QColor(Qt.green)) self.btn.setPalette(pal)
class application(QTabWidget): bot = 0 def __init__(self, parent=None): super(application, self).__init__(parent) self.bot = None self.db = sqlite3.connect('database') # tabs self.tab1 = QWidget() self.tab2 = QWidget() self.tab3 = QWidget() self.tab4 = QWidget() self.tab5 = QWidget() self.resize(640, 400) self.addTab(self.tab1, "Tab 1") self.addTab(self.tab2, "Tab 2") self.addTab(self.tab3, "Tab 3") self.addTab(self.tab4, "Tab 4") self.addTab(self.tab5, "Tab 5") # tab set keys self.h_box_key = QHBoxLayout() self.change_key_b = QPushButton("Edit keys") self.edit_1 = QLineEdit() self.edit_2 = QLineEdit() self.edit_3 = QLineEdit() self.edit_4 = QLineEdit() self.result = QLabel() self.set_button = QPushButton("Set keys") self.handle_info = QLabel() self.follower_info = QLabel() self.ready_lab = QLabel() # tab follow self.box_label = QLabel("Link to tweet") self.combo_label = QLabel("Mode") self.spin_label = QLabel("Limit before sleep") self.prog_bar = QProgressBar() self.combo_box = QComboBox() self.h_box = QHBoxLayout() self.spin_box = QSpinBox() self.link_box = QLineEdit() self.link_result = QLabel() self.follow_button = QPushButton("Follow Retweeters") self.cancel_button = QPushButton("Cancel") self.logger = QPlainTextEdit() self.h_box2 = QHBoxLayout() self.max_box = QSpinBox() self.max_label = QLabel("Max follows before stop") # tab unfollow self.unfollow_button = QPushButton("Unfollow Auto followers") self.unf_logger = QPlainTextEdit() self.unfollow_res = QLabel() self.prog_bar_unf = QProgressBar() self.unfollow_cancel = QPushButton("Cancel") self.unf_confirm = QMessageBox() # tab help self.help_box = QPlainTextEdit() self.help_label = QLabel( "<a href='http://Optumsense.com/'>http://Optumsense.com/</a>") #tab schedule self.tweet_box = QPlainTextEdit() self.date_time = QDateTimeEdit(QDateTime.currentDateTime()) self.schedule_but = QPushButton("Schedule Tweet") self.schedule_info = QLabel() self.schedule_table = QTableView() # threads self.follow_thread = None self.unfollow_thread = None self.schedule_thread = None # tabs self.tab1UI() self.tab2UI() self.tab3UI() self.tab4UI() self.tab5UI() self.setWindowTitle("Optumize") self.setWindowIcon(QtGui.QIcon('assets/oo.png')) # db cursor = self.db.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS keys(one TEXT, two TEXT, three TEXT, four TEXT)''' ) self.db.commit() def tab1UI(self): layout = QFormLayout() layout.addRow(self.h_box) self.h_box.addWidget(self.combo_label) self.combo_label.setAlignment(Qt.AlignRight) self.h_box.addWidget(self.combo_box) self.combo_box.addItem("Follow Retweeters") self.combo_box.addItem("Follow Followers") self.combo_box.currentIndexChanged.connect(self.selection_change) self.h_box.addWidget(self.spin_label) self.spin_label.setAlignment(Qt.AlignRight) self.h_box.addWidget(self.spin_box) self.spin_box.setMinimum(1) self.spin_box.setValue(30) layout.addRow(self.box_label, self.link_box) self.link_result.setAlignment(Qt.AlignCenter) layout.addRow(self.link_result) layout.addRow(self.follow_button) self.follow_button.clicked.connect(self.follow_ret) layout.addRow(self.cancel_button) self.cancel_button.clicked.connect(self.cancel_onclick) layout.addRow(self.h_box2) self.h_box2.addWidget(self.max_label) self.h_box2.addWidget(self.max_box) self.max_box.setFixedWidth(100) self.max_label.setAlignment(Qt.AlignRight) self.max_box.setMaximum(1000000) self.max_box.setValue(100) self.max_label.hide() self.max_box.hide() layout.addRow(self.logger) self.logger.setReadOnly(True) layout.addRow(self.prog_bar) self.prog_bar.setAlignment(Qt.AlignCenter) self.setTabText(0, "Follow") self.setTabIcon(0, QtGui.QIcon('assets/check_mark.png')) self.tab1.setLayout(layout) def selection_change(self, i): if i == 0: self.box_label.setText("Link to tweet") self.follow_button.setText("Follow Retweeters") self.link_result.setText("") self.max_label.hide() self.max_box.hide() self.follow_button.clicked.connect(self.follow_ret) else: self.box_label.setText("Handle of user") self.follow_button.setText("Follow Followers") self.link_result.setText("") self.max_label.show() self.max_box.show() self.max_label.setText("Max follows before stop") self.follow_button.clicked.connect(self.follow_fol) def cancel_onclick(self): if self.follow_thread is None: pass elif self.follow_thread.isRunning(): self.prog_bar.setValue(0) self.logger.appendPlainText("Cancelled script") self.follow_thread.terminate() self.follow_thread = None def follow_ret(self): self.prog_bar.setValue(0) self.follow_button.setEnabled(False) self.link_result.setText("") self.logger.clear() limit = self.spin_box.value() if self.bot is None: self.link_result.setText( "<font color='red'>Configure access keys in set keys tab</font>" ) return if self.follow_thread is not None: return link = self.link_box.text() id_tweet = link.split("/")[-1] try: tweet = self.bot.api.get_status(id_tweet) self.logger.appendPlainText( f"following retweeters from link: {link}...") self.follow_thread = FollowThread(self.bot, id_tweet, limit, 1, 0) self.follow_thread.start() self.connect(self.follow_thread, SIGNAL("finished()"), self.done) self.connect(self.follow_thread, SIGNAL("setup_prog(QString)"), self.setup_prog) self.connect(self.follow_thread, SIGNAL("post_follow(QString)"), self.post_follow) except tweepy.error.TweepError: self.follow_button.setEnabled(True) self.link_result.setText( "<font color='red'>Could not find tweet</font>") def setup_prog(self, msg): self.prog_bar.setMaximum(int(msg)) def follow_fol(self): self.prog_bar.setValue(0) self.follow_button.setEnabled(False) self.link_result.setText("") self.logger.clear() limit = self.spin_box.value() if self.bot is None: self.link_result.setText( "<font color='red'>Configure access keys in set keys tab</font>" ) return if self.follow_thread is not None: return handle = self.link_box.text() if handle == '': self.link_result.setText( "<font color='red'>Enter a handle above</font>") return elif handle[0] == '@': id_user = handle[1:] else: id_user = handle try: man = self.bot.api.get_user(id_user) self.logger.appendPlainText( f"following followers of {man.screen_name}...") self.logger.appendPlainText(f"Collecting") self.follow_thread = FollowThread(self.bot, id_user, limit, 2, self.max_box.value()) self.follow_thread.start() self.connect(self.follow_thread, SIGNAL("finished()"), self.done) self.connect(self.follow_thread, SIGNAL("setup_prog(QString)"), self.setup_prog) self.connect(self.follow_thread, SIGNAL("post_follow(QString)"), self.post_follow) except tweepy.error.TweepError: self.follow_button.setEnabled(True) self.link_result.setText( "<font color='red'>Could not find user</font>") def post_follow(self, message): if message == "bad": self.logger.appendPlainText( "Rate limit exceeded... sleeping for cooldown") else: self.logger.appendPlainText(message) self.prog_bar.setValue(self.prog_bar.value() + 1) def done(self): self.follow_thread = None self.follow_button.setEnabled(True) def tab2UI(self): layout = QFormLayout() layout.addRow(self.unfollow_button) layout.addRow(self.unfollow_cancel) layout.addRow(self.unfollow_res) self.unfollow_res.setAlignment(Qt.AlignCenter) self.unfollow_button.clicked.connect(self.unfollow_fol) self.unfollow_cancel.clicked.connect(self.unfollow_can) layout.addWidget(self.unf_logger) self.unf_logger.setReadOnly(True) layout.addRow(self.prog_bar_unf) self.prog_bar_unf.setAlignment(Qt.AlignCenter) self.setTabText(1, "Unfollow") self.setTabIcon(1, QtGui.QIcon('assets/cross.png')) self.tab2.setLayout(layout) def unfollow_fol(self): self.unfollow_button.setEnabled(False) self.unfollow_thread = UnfollowThread(self.bot) self.unfollow_thread.start() self.connect(self.unfollow_thread, SIGNAL("post_unfol(QString)"), self.post_unfol) self.connect(self.unfollow_thread, SIGNAL("finished()"), self.done_unf) def done_unf(self): self.unfollow_thread = None self.unf_logger.appendPlainText("Done") self.unfollow_button.setEnabled(True) def post_unfol(self, msg): if msg == "bad": self.unf_logger.appendPlainText( "rate limit exceeded, resting for 15 minutes") else: self.unf_logger.appendPlainText(f"Unfollowing {msg}") def unfollow_can(self): if self.unfollow_thread is None: pass elif self.unfollow_thread.isRunning(): self.unf_logger.appendPlainText("Cancelled script") self.unfollow_thread.terminate() self.unfollow_thread = None def tab3UI(self): layout = QFormLayout() layout.addWidget(self.tweet_box) self.tweet_box.setMaximumHeight(150) self.tweet_box.setPlaceholderText("Tweet contents") layout.addRow(self.date_time) self.date_time.setCalendarPopup(True) layout.addRow(self.schedule_info) layout.addRow(self.schedule_but) self.schedule_but.clicked.connect(self.schedule_tweet) layout.addWidget(self.schedule_table) self.setTabText(2, "Schedule Tweet") self.setTabIcon(2, QtGui.QIcon('assets/calendar.png')) self.tab3.setLayout(layout) def schedule_tweet(self): tweet_contents = self.tweet_box.toPlainText() if (len(tweet_contents) == 0): print("length of tweet is 0") self.schedule_info.setText("length of tweet is 0") return elif (len(tweet_contents) >= 280): self.schedule_info.setText("Tweet char limit exceeded") return if self.bot is None: self.schedule_info.setText( "<font color='red'>Configure access keys in set keys tab</font>" ) return datetime = self.date_time.text() try: print("done") self.schedule_thread.start() self.schedule_thread.add_tweet(tweet_contents, datetime) except: self.follow_button.setEnabled(True) self.link_result.setText( "<font color='red'>Could not find user</font>") def done_schedule(self): print("done scheduler") def tab4UI(self): layout = QFormLayout() layout.addRow("API key", self.edit_1) layout.addRow("API key secret", self.edit_2) layout.addRow("Auth token", self.edit_3) layout.addRow("Auth token secret", self.edit_4) self.set_button.clicked.connect(self.set_keys) l = self.read_file() if l is not None: if len(l) == 4: self.edit_1.setText(l[0]) self.edit_2.setText(l[1]) self.edit_3.setText(l[2]) self.edit_4.setText(l[3]) self.set_keys() layout.addRow(self.result) self.result.setAlignment(Qt.AlignCenter) layout.addRow(self.h_box_key) self.h_box_key.addWidget(self.change_key_b) self.h_box_key.addWidget(self.set_button) self.change_key_b.clicked.connect(self.change_keys) layout.addRow(self.handle_info) self.handle_info.setAlignment(Qt.AlignCenter) layout.addRow(self.follower_info) self.follower_info.setAlignment(Qt.AlignCenter) layout.addRow(self.ready_lab) self.ready_lab.setAlignment(Qt.AlignCenter) self.setTabText(3, "Settings") self.setTabIcon(3, QtGui.QIcon('assets/settings.png')) self.tab4.setLayout(layout) def change_keys(self): self.set_button.setEnabled(True) def set_keys(self): self.set_button.setEnabled(False) self.result.setText("") one = self.edit_1.text() two = self.edit_2.text() three = self.edit_3.text() four = self.edit_4.text() try: self.bot = apiconnector.ApiConnector(one, two, three, four) me = self.bot.add_keys(one, two, three, four) self.handle_info.setText("Handle: @" + me.screen_name) self.follower_info.setText("Followers: " + str(me.followers_count)) self.ready_lab.setText("<font color='green'>Ready!</font>") cursor = self.db.cursor() cursor.execute('DELETE FROM keys;', ) cursor.execute( '''INSERT INTO keys(one, two, three, four) VALUES(?,?,?,?)''', (one, two, three, four)) self.db.commit() self.schedule_thread = ScheduleThread(self.bot) except: print("Could not authenticate you") self.result.setText( "<font color='red'>Could not authenticate you</font>") def read_file(self): result = [] try: cursor = self.db.cursor() cursor.execute('''SELECT one, two, three, four FROM keys''') all_rows = cursor.fetchall() for row in all_rows: result.append(row[0]) result.append(row[1]) result.append(row[2]) result.append(row[3]) return result except: return None def tab5UI(self): layout = QFormLayout() layout.addRow("Website", self.help_label) self.help_label.setOpenExternalLinks(True) self.setTabText(4, "Help") self.setTabIcon(4, QtGui.QIcon('assets/help.png')) self.tab5.setLayout(layout)