class CodeTextEditor(QWidget): codeChanged = Signal() def __init__(self): super().__init__() self.textEdit = QTextEdit() self.textEdit.setTabStopDistance(20) self.textEdit.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap) self.textEdit.textChanged.connect(self.codeChanged.emit) self.textEdit.setAcceptRichText(False) layout = QHBoxLayout() self.setLayout(layout) layout.addWidget(self.textEdit) self._highlighter = PythonSyntaxHighlighter(self.textEdit.document()) def SetCode(self, code: str): self.textEdit.setPlainText(code) def Code(self): return self.textEdit.toPlainText()
class BuilderWidget(QWidget): def __init__(self, parent=None) -> None: super().__init__(parent) self.verticalLayout = QVBoxLayout(self) self.compileButton = QPushButton('Compile', self) self.compileButton.setMinimumSize(QSize(200, 50)) self.verticalLayout.addWidget(self.compileButton, 0, Qt.AlignHCenter) self.tidyButton = QPushButton('Tidy', self) self.verticalLayout.addWidget(self.tidyButton, 0, Qt.AlignHCenter) self.splitter = QSplitter(self) self.splitter.setOrientation(Qt.Vertical) self.widget = QWidget(self.splitter) self.widget.setObjectName(u"widget") self.verticalLayout2 = QVBoxLayout(self.widget) self.stdoutLabel = QLabel(self.widget) self.stdoutLabel.setText('stdout:') self.verticalLayout2.addWidget(self.stdoutLabel) self.stdoutText = QTextEdit(self.widget) self.stdoutText.setEnabled(False) self.stdoutText.setReadOnly(True) self.stdoutText.setPlainText("Output will appear here") self.verticalLayout2.addWidget(self.stdoutText) self.splitter.addWidget(self.widget) self.widget1 = QWidget(self.splitter) self.verticalLayout3 = QVBoxLayout(self.widget1) self.stderrLabel = QLabel(self.widget1) self.stderrLabel.setText('stderr:') self.verticalLayout3.addWidget(self.stderrLabel) self.stderrText = QTextEdit(self.widget1) self.stderrText.setEnabled(False) self.stderrText.setReadOnly(True) self.stderrText.setPlainText('Errors will appear here') self.verticalLayout3.addWidget(self.stderrText) self.splitter.addWidget(self.widget1) self.verticalLayout.addWidget(self.splitter) # Logic # Use QProcess to start a program and get its outputs https://stackoverflow.com/a/22110924 self.process = QProcess(self) self.process.readyReadStandardOutput.connect(self.readStdout) self.process.readyReadStandardError.connect(self.readStderr) self.process.started.connect(self.processStarted) self.process.finished.connect(self.processFinished) self.process.errorOccurred.connect(self.errorOccurred) self.compileButton.clicked.connect(self.doCompile) self.tidyButton.clicked.connect(self.doTidy) def doCompile(self): self.cleanupUI() self.process.setWorkingDirectory(settings.get_repo_location()) self.process.startCommand(settings.get_build_command()) def doTidy(self): self.cleanupUI() self.process.setWorkingDirectory(settings.get_repo_location()) self.process.startCommand(settings.get_tidy_command()) def cleanupUI(self): self.stdoutText.setEnabled(True) self.stderrText.setEnabled(True) self.stdoutText.setPlainText('') self.stderrText.setPlainText('') def readStdout(self): lines = self.process.readAllStandardOutput().data().decode( )[:-1].split('\n') for line in lines: if line == 'tmc.gba: FAILED': line = 'tmc.gba: <b style="color:red">FAILED</b>' elif line == 'tmc.gba: OK': line = 'tmc.gba: <b style="color:lime">OK</b>' self.stdoutText.append(line) def readStderr(self): lines = self.process.readAllStandardError().data().decode()[:-1].split( '\n') for line in lines: if 'error' in line.lower(): line = f'<span style="color:red">{line}</span>' elif 'warning' in line.lower(): line = f'<span style="color:orange">{line}</span>' self.stderrText.append(line) def processStarted(self): self.compileButton.setEnabled(False) self.tidyButton.setEnabled(False) def processFinished(self): self.compileButton.setEnabled(True) self.tidyButton.setEnabled(True) def errorOccurred(self): self.stderrText.insertPlainText(self.process.errorString())
class AboutWindow_Ui(QWidget): def __init__(self, persepolis_setting): super().__init__() self.persepolis_setting = persepolis_setting # add support for other languages locale = str(self.persepolis_setting.value('settings/locale')) QLocale.setDefault(QLocale(locale)) self.translator = QTranslator() if self.translator.load(':/translations/locales/ui_' + locale, 'ts'): QCoreApplication.installTranslator(self.translator) # set ui direction ui_direction = self.persepolis_setting.value('ui_direction') if ui_direction == 'rtl': self.setLayoutDirection(Qt.RightToLeft) elif ui_direction in 'ltr': self.setLayoutDirection(Qt.LeftToRight) icons = ':/' + \ str(self.persepolis_setting.value('settings/icons')) + '/' self.setMinimumSize(QSize(545, 375)) self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg'))) verticalLayout = QVBoxLayout(self) self.about_tabWidget = QTabWidget(self) # about tab self.about_tab = QWidget(self) about_tab_horizontalLayout = QHBoxLayout(self.about_tab) about_tab_verticalLayout = QVBoxLayout() # persepolis icon if qtsvg_available: persepolis_icon_verticalLayout = QVBoxLayout() self.persepolis_icon = QtSvgWidget.QSvgWidget(':/persepolis.svg') self.persepolis_icon.setFixedSize(QSize(64, 64)) persepolis_icon_verticalLayout.addWidget(self.persepolis_icon) persepolis_icon_verticalLayout.addStretch(1) about_tab_horizontalLayout.addLayout(persepolis_icon_verticalLayout) self.title_label = QLabel(self.about_tab) font = QFont() font.setBold(True) font.setWeight(QFont.Weight.Bold) self.title_label.setFont(font) self.title_label.setAlignment(Qt.AlignCenter) about_tab_verticalLayout.addWidget(self.title_label) self.version_label = QLabel(self.about_tab) self.version_label.setAlignment(Qt.AlignCenter) about_tab_verticalLayout.addWidget(self.version_label) self.site2_label = QLabel(self.about_tab) self.site2_label.setTextFormat(Qt.RichText) self.site2_label.setAlignment(Qt.AlignCenter) self.site2_label.setOpenExternalLinks(True) self.site2_label.setTextInteractionFlags( Qt.TextBrowserInteraction) about_tab_verticalLayout.addWidget(self.site2_label) self.telegram_label = QLabel(self.about_tab) self.telegram_label.setTextFormat(Qt.RichText) self.telegram_label.setAlignment(Qt.AlignCenter) self.telegram_label.setOpenExternalLinks(True) self.telegram_label.setTextInteractionFlags( Qt.TextBrowserInteraction) about_tab_verticalLayout.addWidget(self.telegram_label) self.twitter_label = QLabel(self.about_tab) self.twitter_label.setTextFormat(Qt.RichText) self.twitter_label.setAlignment(Qt.AlignCenter) self.twitter_label.setOpenExternalLinks(True) self.twitter_label.setTextInteractionFlags( Qt.TextBrowserInteraction) about_tab_verticalLayout.addWidget(self.twitter_label) about_tab_verticalLayout.addStretch(1) about_tab_horizontalLayout.addLayout(about_tab_verticalLayout) # developers_tab # developers self.developers_tab = QWidget(self) developers_verticalLayout = QVBoxLayout(self.developers_tab) self.developers_title_label = QLabel(self.developers_tab) font.setBold(True) font.setWeight(QFont.Weight.Bold) self.developers_title_label.setFont(font) self.developers_title_label.setAlignment(Qt.AlignCenter) developers_verticalLayout.addWidget(self.developers_title_label) self.name_label = QLabel(self.developers_tab) self.name_label.setAlignment(Qt.AlignCenter) developers_verticalLayout.addWidget(self.name_label) # contributors self.contributors_thank_label = QLabel(self.developers_tab) self.contributors_thank_label.setFont(font) self.contributors_thank_label.setAlignment(Qt.AlignCenter) developers_verticalLayout.addWidget(self.contributors_thank_label) self.contributors_link_label = QLabel(self.developers_tab) self.contributors_link_label.setTextFormat(Qt.RichText) self.contributors_link_label.setAlignment(Qt.AlignCenter) self.contributors_link_label.setOpenExternalLinks(True) self.contributors_link_label.setTextInteractionFlags( Qt.TextBrowserInteraction) developers_verticalLayout.addWidget(self.contributors_link_label) developers_verticalLayout.addStretch(1) # translators tab self.translators_tab = QWidget(self) translators_tab_verticalLayout = QVBoxLayout(self.translators_tab) # translators self.translators_textEdit = QTextEdit(self.translators_tab) self.translators_textEdit.setReadOnly(True) translators_tab_verticalLayout.addWidget(self.translators_textEdit) # License tab self.license_tab = QWidget(self) license_tab_verticalLayout = QVBoxLayout(self.license_tab) self.license_text = QTextEdit(self.license_tab) self.license_text.setReadOnly(True) license_tab_verticalLayout.addWidget(self.license_text) verticalLayout.addWidget(self.about_tabWidget) # buttons button_horizontalLayout = QHBoxLayout() button_horizontalLayout.addStretch(1) self.pushButton = QPushButton(self) self.pushButton.setIcon(QIcon(icons + 'ok')) self.pushButton.clicked.connect(self.close) button_horizontalLayout.addWidget(self.pushButton) verticalLayout.addLayout(button_horizontalLayout) self.setWindowTitle(QCoreApplication.translate("about_ui_tr", "About Persepolis")) # about_tab self.title_label.setText(QCoreApplication.translate("about_ui_tr", "Persepolis Download Manager")) self.version_label.setText(QCoreApplication.translate("about_ui_tr", "Version 3.2.0")) self.site2_label.setText(QCoreApplication.translate("about_ui_tr", "<a href=https://persepolisdm.github.io>https://persepolisdm.github.io</a>", "TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!")) self.telegram_label.setText(QCoreApplication.translate("about_ui_tr", "<a href=https://telegram.me/persepolisdm>https://telegram.me/persepolisdm</a>", "TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!")) self.twitter_label.setText(QCoreApplication.translate("about_ui_tr", "<a href=https://twitter.com/persepolisdm>https://twitter.com/persepolisdm</a>", "TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!")) # developers_tab self.developers_title_label.setText(QCoreApplication.translate('about_ui_tr', 'Developers:')) self.name_label.setText(QCoreApplication.translate("about_ui_tr", "\nAliReza AmirSamimi\nMohammadreza Abdollahzadeh\nSadegh Alirezaie\nMostafa Asadi\nMohammadAmin Vahedinia\nJafar Akhondali\nH.Rostami\nEhsan Titish", "TRANSLATORS NOTE: YOU REALLY DON'T NEED TO TRANSLATE THIS PART!")) self.contributors_thank_label.setText(QCoreApplication.translate('about_ui_tr', 'Special thanks to:')) self.contributors_link_label.setText( "<a href=https://github.com/persepolisdm/persepolis/graphs/contributors>our contributors</a>") # License self.license_text.setPlainText(""" This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. """) # tabs self.about_tabWidget.addTab(self.about_tab, QCoreApplication.translate("about_ui_tr", "About Persepolis")) self.about_tabWidget.addTab(self.developers_tab, QCoreApplication.translate("about_ui_tr", "Developers")) self.about_tabWidget.addTab(self.translators_tab, QCoreApplication.translate("about_ui_tr", "Translators")) self.about_tabWidget.addTab(self.license_tab, QCoreApplication.translate("about_ui_tr", "License")) # button self.pushButton.setText(QCoreApplication.translate("about_ui_tr", "OK"))
class Window(QDialog): def __init__(self, parent=None): super(Window, self).__init__(parent) self.iconGroupBox = QGroupBox() self.iconLabel = QLabel() self.iconComboBox = QComboBox() self.showIconCheckBox = QCheckBox() self.messageGroupBox = QGroupBox() self.typeLabel = QLabel() self.durationLabel = QLabel() self.durationWarningLabel = QLabel() self.titleLabel = QLabel() self.bodyLabel = QLabel() self.typeComboBox = QComboBox() self.durationSpinBox = QSpinBox() self.titleEdit = QLineEdit() self.bodyEdit = QTextEdit() self.showMessageButton = QPushButton() self.minimizeAction = QAction() self.maximizeAction = QAction() self.restoreAction = QAction() self.quitAction = QAction() self.trayIcon = QSystemTrayIcon() self.trayIconMenu = QMenu() self.createIconGroupBox() self.createMessageGroupBox() self.iconLabel.setMinimumWidth(self.durationLabel.sizeHint().width()) self.createActions() self.createTrayIcon() self.showMessageButton.clicked.connect(self.showMessage) self.showIconCheckBox.toggled.connect(self.trayIcon.setVisible) self.iconComboBox.currentIndexChanged.connect(self.setIcon) self.trayIcon.messageClicked.connect(self.messageClicked) self.trayIcon.activated.connect(self.iconActivated) self.mainLayout = QVBoxLayout() self.mainLayout.addWidget(self.iconGroupBox) self.mainLayout.addWidget(self.messageGroupBox) self.setLayout(self.mainLayout) self.iconComboBox.setCurrentIndex(1) self.trayIcon.show() self.setWindowTitle("Systray") self.resize(400, 300) def setVisible(self, visible): self.minimizeAction.setEnabled(visible) self.maximizeAction.setEnabled(not self.isMaximized()) self.restoreAction.setEnabled(self.isMaximized() or not visible) super().setVisible(visible) def closeEvent(self, event): if not event.spontaneous() or not self.isVisible(): return if self.trayIcon.isVisible(): QMessageBox.information( self, "Systray", "The program will keep running in the system tray. " "To terminate the program, choose <b>Quit</b> in the context " "menu of the system tray entry.") self.hide() event.ignore() @Slot(int) def setIcon(self, index): icon = self.iconComboBox.itemIcon(index) self.trayIcon.setIcon(icon) self.setWindowIcon(icon) self.trayIcon.setToolTip(self.iconComboBox.itemText(index)) @Slot(str) def iconActivated(self, reason): if reason == QSystemTrayIcon.Trigger: pass if reason == QSystemTrayIcon.DoubleClick: self.iconComboBox.setCurrentIndex( (self.iconComboBox.currentIndex() + 1) % self.iconComboBox.count()) if reason == QSystemTrayIcon.MiddleClick: self.showMessage() @Slot() def showMessage(self): self.showIconCheckBox.setChecked(True) selectedIcon = self.typeComboBox.itemData( self.typeComboBox.currentIndex()) msgIcon = QSystemTrayIcon.MessageIcon(selectedIcon) if selectedIcon == -1: # custom icon icon = QIcon( self.iconComboBox.itemIcon(self.iconComboBox.currentIndex())) self.trayIcon.showMessage( self.titleEdit.text(), self.bodyEdit.toPlainText(), icon, self.durationSpinBox.value() * 1000, ) else: self.trayIcon.showMessage( self.titleEdit.text(), self.bodyEdit.toPlainText(), msgIcon, self.durationSpinBox.value() * 1000, ) @Slot() def messageClicked(self): QMessageBox.information( None, "Systray", "Sorry, I already gave what help I could.\n" "Maybe you should try asking a human?") def createIconGroupBox(self): self.iconGroupBox = QGroupBox("Tray Icon") self.iconLabel = QLabel("Icon:") self.iconComboBox = QComboBox() self.iconComboBox.addItem(QIcon(":/images/bad.png"), "Bad") self.iconComboBox.addItem(QIcon(":/images/heart.png"), "Heart") self.iconComboBox.addItem(QIcon(":/images/trash.png"), "Trash") self.showIconCheckBox = QCheckBox("Show icon") self.showIconCheckBox.setChecked(True) iconLayout = QHBoxLayout() iconLayout.addWidget(self.iconLabel) iconLayout.addWidget(self.iconComboBox) iconLayout.addStretch() iconLayout.addWidget(self.showIconCheckBox) self.iconGroupBox.setLayout(iconLayout) def createMessageGroupBox(self): self.messageGroupBox = QGroupBox("Balloon Message") self.typeLabel = QLabel("Type:") self.typeComboBox = QComboBox() self.typeComboBox.addItem("None", QSystemTrayIcon.NoIcon) self.typeComboBox.addItem( self.style().standardIcon(QStyle.SP_MessageBoxInformation), "Information", QSystemTrayIcon.Information, ) self.typeComboBox.addItem( self.style().standardIcon(QStyle.SP_MessageBoxWarning), "Warning", QSystemTrayIcon.Warning, ) self.typeComboBox.addItem( self.style().standardIcon(QStyle.SP_MessageBoxCritical), "Critical", QSystemTrayIcon.Critical, ) self.typeComboBox.addItem(QIcon(), "Custom icon", -1) self.typeComboBox.setCurrentIndex(1) self.durationLabel = QLabel("Duration:") self.durationSpinBox = QSpinBox() self.durationSpinBox.setRange(5, 60) self.durationSpinBox.setSuffix(" s") self.durationSpinBox.setValue(15) self.durationWarningLabel = QLabel( "(some systems might ignore this hint)") self.durationWarningLabel.setIndent(10) self.titleLabel = QLabel("Title:") self.titleEdit = QLineEdit("Cannot connect to network") self.bodyLabel = QLabel("Body:") self.bodyEdit = QTextEdit() self.bodyEdit.setPlainText( "Don't believe me. Honestly, I don't have a clue." "\nClick this balloon for details.") self.showMessageButton = QPushButton("Show Message") self.showMessageButton.setDefault(True) messageLayout = QGridLayout() messageLayout.addWidget(self.typeLabel, 0, 0) messageLayout.addWidget(self.typeComboBox, 0, 1, 1, 2) messageLayout.addWidget(self.durationLabel, 1, 0) messageLayout.addWidget(self.durationSpinBox, 1, 1) messageLayout.addWidget(self.durationWarningLabel, 1, 2, 1, 3) messageLayout.addWidget(self.titleLabel, 2, 0) messageLayout.addWidget(self.titleEdit, 2, 1, 1, 4) messageLayout.addWidget(self.bodyLabel, 3, 0) messageLayout.addWidget(self.bodyEdit, 3, 1, 2, 4) messageLayout.addWidget(self.showMessageButton, 5, 4) messageLayout.setColumnStretch(3, 1) messageLayout.setRowStretch(4, 1) self.messageGroupBox.setLayout(messageLayout) def createActions(self): self.minimizeAction = QAction("Minimize", self) self.minimizeAction.triggered.connect(self.hide) self.maximizeAction = QAction("Maximize", self) self.maximizeAction.triggered.connect(self.showMaximized) self.restoreAction = QAction("Restore", self) self.restoreAction.triggered.connect(self.showNormal) self.quitAction = QAction("Quit", self) self.quitAction.triggered.connect(qApp.quit) def createTrayIcon(self): self.trayIconMenu = QMenu(self) self.trayIconMenu.addAction(self.minimizeAction) self.trayIconMenu.addAction(self.maximizeAction) self.trayIconMenu.addAction(self.restoreAction) self.trayIconMenu.addSeparator() self.trayIconMenu.addAction(self.quitAction) self.trayIcon = QSystemTrayIcon(self) self.trayIcon.setContextMenu(self.trayIconMenu)
class Window(QDialog): def __init__(self, parent=None): super(Window, self).__init__(parent) self.createTrayIcon() self.createProgramsList() self.createCodeEditPage() self.logsPage = QTextBrowser() self.documentation = QTextBrowser() self.tabWidget = QTabWidget() self.tabWidget.setIconSize(QSize(64, 64)) self.tabWidget.addTab(self.programsListPage, QIcon(":/images/Adventure-Map-icon.png"), "Programs") self.tabWidget.addTab(self.codeEditPage, QIcon(":/images/Sword-icon.png"), "Edit Program") self.tabWidget.addTab(self.logsPage, QIcon(":/images/Spell-Scroll-icon.png"), "Logs") self.tabWidget.addTab(self.documentation, QIcon(":/images/Spell-Book-icon.png"), "Documentation") self.mainLayout = QVBoxLayout() self.mainLayout.addWidget(self.tabWidget) self.setLayout(self.mainLayout) self.setWindowTitle(APP_NAME) self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.Dialog) self.resize(800, 600) self.systrayHintMsgShowed = False self.firstShow = True self.fromQuit = False def createProgramsList(self): self.programsListModel = QStandardItemModel(0, 1, self) self.programsList = QListView() self.programsList.setModel(self.programsListModel) self.programsListPage = QWidget() self.programsListLayout = QVBoxLayout() self.programsListButtons = QHBoxLayout() self.programsListButtonNew = QPushButton("New") self.programsListButtonDelete = QPushButton("Delete") self.programsListButtonEdit = QPushButton("Edit") self.programsListButtonSet = QPushButton("Set") self.programsListButtons.addWidget(self.programsListButtonNew) self.programsListButtons.addWidget(self.programsListButtonSet) self.programsListButtons.addWidget(self.programsListButtonEdit) self.programsListButtons.addWidget(self.programsListButtonDelete) self.programsListLayout.addLayout(self.programsListButtons) self.programsListLayout.addWidget(self.programsList) self.programsListPage.setLayout(self.programsListLayout) self.programsListButtonNew.clicked.connect(self.newProgram) self.programsListButtonEdit.clicked.connect(self.editProgram) self.programsListButtonDelete.clicked.connect(self.deleteProgram) self.programsListButtonSet.clicked.connect(self.setProgram) def createCodeEditPage(self): self.codeEditPage = QWidget() self.codeEditLayout = QVBoxLayout() self.codeEditNameBox = QHBoxLayout() self.codeEditNameBoxNameLabel = QLabel("Name:") self.codeEditNameBoxNameInput = QLineEdit() self.codeEditNameBoxSaveButton = QPushButton("Save") self.codeEditNameBoxCancelButton = QPushButton("Cancel") self.codeEditNameBox.addWidget(self.codeEditNameBoxNameLabel) self.codeEditNameBox.addWidget(self.codeEditNameBoxNameInput) self.codeEditNameBox.addWidget(self.codeEditNameBoxSaveButton) self.codeEditNameBox.addWidget(self.codeEditNameBoxCancelButton) self.codeEdit = QTextEdit() self.codeEditLayout.addLayout(self.codeEditNameBox) self.codeEditLayout.addWidget(self.codeEdit) self.codeEditPage.setLayout(self.codeEditLayout) self.codeEditLastCode = '' self.codeEditNameBoxSaveButton.clicked.connect(self.saveEditProgram) self.codeEditNameBoxCancelButton.clicked.connect(self.cancelEditProgram) def showEvent(self, event): super().showEvent(event) if self.firstShow: self.firstShow = False self.createWaitDialog() self.findKeyboard() def closeWaitDialog(self): time.sleep(1) self.waitDialog.close() @Slot() def newProgram(self): self.showNormal() self.tabWidget.setCurrentWidget(self.codeEditPage) self.codeEdit.setPlainText("") self.codeEditLastCode = '' self.codeEditNameBoxNameInput.setText("") @Slot() def editProgram(self): selected = self.programsList.selectedIndexes() if not selected: return selected = selected[0].data() loadProgram = LoadProgram(self.cmdSocket, selected) loadProgram.loaded.connect(self.programLoaded) loadProgram.start() self.showWaitDialog("Loading program ...") @Slot() def saveEditProgram(self): name = self.codeEditNameBoxNameInput.text() program = self.codeEdit.toPlainText() if not name: return editProgramWorker = EditProgram(self.cmdSocket, name, program) editProgramWorker.edited.connect(self.programSaved) editProgramWorker.start() self.showWaitDialog("Saving program ...") @Slot() def cancelEditProgram(self): self.codeEdit.setPlainText(self.codeEditLastCode) @Slot() def deleteProgram(self): selected = self.programsList.selectedIndexes() if not selected: return selected = selected[0].data() deleteWorker = DeleteProgram(self.cmdSocket, selected) deleteWorker.deleted.connect(self.programDeleted) deleteWorker.start() self.showWaitDialog("Deleting program ...") @Slot() def setProgram(self): selected = self.programsList.selectedIndexes() if not selected: return selected = selected[0].data() setWorker = SetProgram(self.cmdSocket, selected) setWorker.setDone.connect(self.programSet) setWorker.start() self.showWaitDialog("Setting program ...") @Slot(str, str) def programLoaded(self, name, program): self.closeWaitDialog() self.tabWidget.setCurrentWidget(self.codeEditPage) self.codeEdit.setPlainText(program) self.codeEditLastCode = program self.codeEditNameBoxNameInput.setText(name) @Slot(str) def programDeleted(self, name): self.updateProgramsList() @Slot(str) def programSet(self, name): self.updateProgramsList() @Slot(str) def programSaved(self, name): self.updateProgramsList() self.tabWidget.setCurrentWidget(self.programsListPage) def createWaitDialog(self): self.waitDialog = QDialog(self) self.waitDialogLayout = QHBoxLayout() self.waitDialogLabel = QLabel() self.waitDialogLayout.addWidget(self.waitDialogLabel) self.waitDialog.setLayout(self.waitDialogLayout) self.waitDialog.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint) def showWaitDialog(self, text='Please wait...'): self.waitDialogLabel.setText(text) self.waitDialog.exec_() def findKeyboard(self): find = ConnectKeyboard() find.connected.connect(self.keyboardConnected) find.start() self.showWaitDialog('Finding and connecting Fruit2Pi Keyboard ...') @Slot(BluetoothSocket) def keyboardConnected(self, socket): self.cmdSocket = socket self.updateProgramsList() def updateProgramsList(self): self.listProgram = ListProgram(self.cmdSocket) self.listProgram.listed.connect(self.programListUpdated) self.listProgram.start() @Slot(list, str) def programListUpdated(self, programs, current_program): print(programs) print(current_program) self.closeWaitDialog() self.programsListModel.clear() for p in programs: item = QStandardItem(p) if p == current_program: item.setForeground(QBrush(QColor(0, 0, 255, 127))) self.programsListModel.appendRow(item) def setVisible(self, visible): super().setVisible(visible) def closeEvent(self, event): if self.fromQuit: return if not event.spontaneous() or not self.isVisible(): return if not self.systrayHintMsgShowed: self.systrayHintMsgShowed = True icon = QIcon(":/images/yammi-banana-icon.png") self.trayIcon.showMessage(APP_NAME, "Running on background" "To quit, choose <b>Quit</b> in the icon menu", icon, 5000 ) self.hide() event.ignore() @Slot(str) def iconActivated(self, reason): print(reason) if reason == QSystemTrayIcon.Trigger: self.showNormal() if reason == QSystemTrayIcon.DoubleClick: self.showNormal() @Slot() def showProgramsPage(self): self.showNormal() self.tabWidget.setCurrentWidget(self.programsListPage) @Slot() def showLogsPage(self): self.showNormal() self.tabWidget.setCurrentWidget(self.logsPage) @Slot() def showDocumentation(self): self.showNormal() self.tabWidget.setCurrentWidget(self.documentation) @Slot() def quit(self): self.fromQuit = True qApp.quit() def createTrayIcon(self): self.showProgramsAction = QAction("Programs", self) self.showProgramsAction.triggered.connect(self.showProgramsPage) self.showNewProgramAction = QAction("New Program", self) self.showNewProgramAction.triggered.connect(self.newProgram) self.showSetProgramAction = QAction("Logs", self) self.showSetProgramAction.triggered.connect(self.showLogsPage) self.showDocumentationAction = QAction("Documentation", self) self.showDocumentationAction.triggered.connect(self.showDocumentation) self.quitAction = QAction("Quit", self) self.quitAction.triggered.connect(self.quit) self.trayIconMenu = QMenu(self) self.trayIconMenu.addAction(self.showProgramsAction) self.trayIconMenu.addAction(self.showSetProgramAction) self.trayIconMenu.addAction(self.showNewProgramAction) self.trayIconMenu.addAction(self.showDocumentationAction) self.trayIconMenu.addSeparator() self.trayIconMenu.addAction(self.quitAction) self.trayIcon = QSystemTrayIcon(self) self.trayIcon.setContextMenu(self.trayIconMenu) self.trayIcon.activated.connect(self.iconActivated) self.trayIcon.setIcon(QIcon(":/images/yammi-banana-icon.png")) self.trayIcon.show()