def statusbar_setup(self): stat = QStatusBar() self.setStatusBar(stat) label1 = QLabel() label1.setText("Label 1") label1.show() stat.addWidget(label1, 1)
def __init__(self, parent=None): super(FlowSolvingPopup, self).__init__(parent) layout = QBoxLayout(QBoxLayout.TopToBottom) layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) self._solverWidget = FlowSolverWidget() self._solverWidget.finished.connect(self._solverFinished) layout.addWidget(self._solverWidget) status = QStatusBar() status.setSizeGripEnabled(False) self._againButton = QPushButton("next") self._againButton.setVisible(False) self._againButton.clicked.connect(self._againClicked) status.addPermanentWidget(self._againButton) self._abortButton = QPushButton("close") self._abortButton.clicked.connect(self._abortClicked) status.addPermanentWidget(self._abortButton) self._messageLabel = QLabel("ready") status.addWidget(self._messageLabel) layout.addWidget(status) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self._timer = QTimer() self._timer.timeout.connect(self._timerTick)
class StatusDemo(QMainWindow): def __init__(self): super(StatusDemo, self).__init__() self.initUi() def initUi(self): bar = self.menuBar() file = bar.addMenu("File") file.addAction("show") file.addAction("add") file.addAction("remove") file.triggered[QAction].connect(self.processTrigger) self.setCentralWidget(QTextEdit()) self.statusBar = QStatusBar() self.b = QPushButton("click here") self.setWindowTitle("QStatusBar Example") self.setStatusBar(self.statusBar) self.show() def processTrigger(self, q): if (q.text() == "show"): self.statusBar.showMessage(q.text() + " is clicked", 2000) if q.text() == "add": self.statusBar.addWidget(self.b) if q.text() == "remove": self.statusBar.removeWidget(self.b) self.statusBar.show()
class Window(QMainWindow): def __init__(self): super().__init__() self.wid = Widget() self.setCentralWidget(self.wid) self.updateButton = QPushButton('refresh', self) self.updateButton.clicked.connect(self.refresh) self.l = QLabel() self.l.setText("hello world") self.sb = QStatusBar() self.sb.addWidget(self.l) self.sb.addWidget(self.updateButton) self.setStatusBar(self.sb) self.sb.show() def refresh(self): self.l.setText("Threads: " + str(self.wid.getThreads())) self.wid.list.clear() self.wid.BackupList() def closeEvent(self, event): if self.wid.BM is None: print("No Backup Manager loaded") else: self.wid.BM.close() print("Closing Backup Manager")
def initUI(self): self.setGeometry(300, 300, 300, 300) self.setWindowTitle('Diag Tool') statusBar = QStatusBar(self) self.targetInfo = QLabel(self) self.connectionStatus = QLabel(self) statusBar.addWidget(self.targetInfo, 0) statusBar.addWidget(self.connectionStatus, 1) self.setStatusBar(statusBar) self.streamDisp = QLabel(self) self.streamDisp.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) layout = QGridLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.streamDisp, 0, 0, 0, 4) self.setCentralWidget(QWidget(self)) self.centralWidget().setLayout(layout) self.menuTarget = self.menuBar().addMenu('Target') self.menuTargetConnect = QAction('Connect', self) self.menuTargetConnect.triggered.connect(self.onMenuTargetConnect) self.menuTargetSettings = QAction('Settings', self) self.menuTargetSettings.triggered.connect(self.onMenuTargetSettings) self.menuTarget.addAction(self.menuTargetConnect) self.menuTarget.addAction(self.menuTargetSettings)
class Browser(QWidget): def __init__(self): super(Browser, self).__init__() self.setWindowTitle("Navegador PyConAr 2016") vbox = QVBoxLayout(self) # Contenedor principal hbox = QHBoxLayout() # Contenedor horizontal # Widgets btn_atras = QPushButton(QIcon.fromTheme("back"), '') btn_adelante = QPushButton(QIcon.fromTheme("forward"), '') btn_ok = QPushButton(QIcon.fromTheme("find"), '') btn_parar = QPushButton(QIcon.fromTheme("cancel"), '') btn_reload = QPushButton(QIcon.fromTheme("reload"), '') self.url = QLineEdit() self.url.setPlaceholderText("Ingresa una página web o busca en Google") # Agrego los widgets hbox.addWidget(btn_atras) hbox.addWidget(btn_adelante) hbox.addWidget(btn_parar) hbox.addWidget(btn_reload) hbox.addWidget(self.url) hbox.addWidget(btn_ok) # Agrego el contenedor horizontal al vertical vbox.addLayout(hbox) # Componente web self.web = QWebView() vbox.addWidget(self.web) # Creo una barra de estado self.estado = QStatusBar() self.estado.hide() # Creo una barra de progreso y la agrego a la barra de estado self.prog = QProgressBar() self.estado.addWidget(self.prog, 1) self.estado.addWidget(QLabel("Cargando...")) vbox.addWidget(self.estado) # Conexiones btn_atras.clicked.connect(self.web.back) btn_adelante.clicked.connect(self.web.forward) btn_parar.clicked.connect(self.web.stop) btn_reload.clicked.connect(self.web.reload) btn_ok.clicked.connect(self._cargar_pagina) self.web.loadProgress.connect(self.prog.setValue) self.web.loadFinished.connect(self._carga_terminada) self.url.returnPressed.connect(self._cargar_pagina) def _carga_terminada(self): self.estado.hide() self.url.setText(self.web.url().toString()) def _cargar_pagina(self): if not self.estado.isVisible(): self.estado.show() text = self.url.text() if text.find('.') != -1 and not text.startswith('http://'): url = 'http://' + text else: url = 'http://google.com/search?q=' + text.replace(' ', '+') self.web.load(QUrl(url))
def _make_widget(self): from PyQt5.QtWidgets import QStatusBar, QSizePolicy, QLabel sb = QStatusBar() sb.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) sb._primary_status_label = QLabel() sb._secondary_status_label = QLabel() sb.addWidget(sb._primary_status_label) sb.addPermanentWidget(sb._secondary_status_label) return sb
class Status(): def __init__(self, app): self.statusBarMessage = QLabel() self.statusBarMessage.setText('No file open') self.statusBar = QStatusBar() self.statusBar.addWidget(self.statusBarMessage) app.setStatusBar(self.statusBar) def setText(self, text): self.statusBarMessage.setText(text)
def _make_widget(self): from PyQt5.QtWidgets import QStatusBar, QSizePolicy, QWidget sb = QStatusBar() sb.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) from PyQt5.QtGui import QWindow, QSurface self._window = pw = QWindow() pw.exposeEvent = self._expose_event pw.resizeEvent = self._resize_event pw.keyPressEvent = self.session.ui.forward_keystroke pwidget = QWidget.createWindowContainer(pw, sb) pw.setSurfaceType(QSurface.OpenGLSurface) sb.addWidget(pwidget, stretch = 1) return sb
class StatusBar: def __init__(self, *args): self.main_window_in_class = args[0] self.contain() def contain(self): self.status_bar = QStatusBar(self.main_window_in_class) self.main_window_in_class.setStatusBar(self.status_bar) version = QLabel(self.main_window_in_class) version.setText(" v. 1.0.1") self.status_bar.addWidget(version)
def _createStatusBar(self): status = QStatusBar() status.addWidget(QPushButton('By Hourly')) status.addWidget(QPushButton('By Gross')) status.addWidget(QPushButton('By Net')) status.addWidget(QPushButton('By Salary')) self.setStatusBar(status)
def _createStatusBar(self): status_bar = QStatusBar() def addLink(link, text): label = QLabel('<a href="' + link + '">' + text + "</a>") label.setOpenExternalLinks(True) status_bar.addWidget(label) addLink(link="https://twitter.com/terramyst1", text="by terramyst, ") addLink(link="https://github.com/amosborne/puyo-trainer", text="github.") status_bar.addWidget( QLabel("(keyboard usage: arrow keys, x, z, spacebar)")) self.setStatusBar(status_bar)
class GlobalSettingsWindow(QMainWindow): def __init__(self): super().__init__() # self.setStyle(ProxyStyle()) self.vertical_tabs = TabWidget() self.status_bar = QStatusBar() self.reset_button = QPushButton('Reset') self.init_ui() self.show() def init_ui(self) -> None: self.setStyleSheet(get_color_scheme()) self.setWindowTitle('Settings') user_w, user_h = get_user_resolution() w = int(user_w / 3) h = int(user_h * 4 / 9) self.resize(w, h) self.setCentralWidget(self.vertical_tabs) self.reset_button.clicked.connect(self.on_reset) status_bar_content_widget = QWidget() status_bar_content_layout = QGridLayout(status_bar_content_widget) status_bar_content_layout.addWidget( QLabel( "Changes are auto saved; some will only be effective upon next start" ), 0, 0, 1, 1, Qt.AlignVCenter | Qt.AlignLeft) status_bar_content_layout.addWidget(self.reset_button, 0, 1, 1, 1, Qt.AlignVCenter | Qt.AlignRight) self.status_bar.addWidget(status_bar_content_widget, 1) self.status_bar.setSizeGripEnabled(False) self.setStatusBar(self.status_bar) self.setLayout(QVBoxLayout()) def on_reset(self) -> None: if self.vertical_tabs.currentIndex() == 0: self.vertical_tabs.ui_settings.on_reset() elif self.vertical_tabs.currentIndex() == 1: self.vertical_tabs.game_settings.on_reset() elif self.vertical_tabs.currentIndex() == 2: self.vertical_tabs.tabs_settings.on_reset() else: pass
class Mwindow(QMainWindow): appname = "主程序" def __init__(self): super(Mwindow, self).__init__() self.central_widget = QWidget() self.sta_bar = QStatusBar() self.mainUI() def mainUI(self): self.setWindowTitle("ana SYS") self.resize(800, 600) self.setCentralWidget(self.central_widget) box_0 = QHBoxLayout() left_frame = QWidget() left_frame.setObjectName("left_frame") left_frame.setFocusPolicy(Qt.StrongFocus) left_frame.setStyleSheet( "background-color:rgba(255,255,255,255);border-color:red;border-width:1px;border-style:solid;" ) l_box = QFormLayout() lab_0 = QLabel("a") lab_1 = QLabel("b") lab_2 = QLabel("c") l_box.addRow(lab_0) l_box.addRow(lab_1) l_box.addRow(lab_2) left_frame.setLayout(l_box) right_frame = QWidget() right_frame.setObjectName("right_frame") right_frame.setFocusPolicy(Qt.StrongFocus) right_frame.setStyleSheet( "background-color:rgba(255,255,255,255);border-color:red;border-width:1px;border-style:solid;" ) box_0.addWidget(left_frame) box_0.addWidget(right_frame) self.central_widget.setLayout(box_0) self.setstatus_bar() def setstatus_bar(self): self.sta_bar.addWidget(QLabel("程序运行中")) self.setStatusBar(self.sta_bar)
class ufTreeMgrWindow(QMainWindow): """ """ def __init__(self,parent=None): super(ufTreeMgrWindow,self).__init__(parent) Context.EDIT_TREE = EDIT_TREE self.statusBar = QStatusBar() self.msgLine = QLabel() self.statusBar.addWidget(self.msgLine) self.cubeFile = 'danacube.json' self.tree = TreeMgr(editAsTree(self.cubeFile), EDIT_TREE, TOP_LEVEL_ELEMS, Context, msgLine=self.msgLine) self.setCentralWidget(self.tree) self.setStatusBar(self.statusBar) def closeEvent(self,event): self.close() def close(self): self.saveFile() return True def saveFile(self): if self.saveDialog(): definiciones = load_cubo(self.cubeFile) definiciones['user functions'] = tree2dict(self.tree.model().invisibleRootItem(),isDictFromDef) dump_config(definiciones, self.cubeFile,total=True,secure=False) def saveDialog(self): if (QMessageBox.question(self, "Salvar", "Desea salvar los cambios del fichero de configuracion {}?".format(self.cubeFile), QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes): return True else: return False
class M_window(QMainWindow): appname = "ANA SYS" def __init__(self): super(M_window, self).__init__() self.central_widget = QWidget() self.sta_bar = QStatusBar() self.left_frame = Left_Frame_0() self.right_frame = Right_Frame_0() self.rside_frame = Rside_Frame_0() self.mainUI() def mainUI(self): self.setWindowTitle(M_window.appname) self.resize(900, 600) self.setWindowIcon(QIcon("./source/icon/mianwin5050.svg")) self.setCentralWidget(self.central_widget) box_0 = QHBoxLayout() box_0.setContentsMargins(0, 0, 0, 0) box_0.addWidget(self.left_frame) box_0.addWidget(self.right_frame) box_0.addWidget(self.rside_frame) self.central_widget.setLayout(box_0) self.setstatus_bar() self.left_frame.s.item_0.update_.connect(self.fun) self.left_frame.s.item_1.update_.connect(self.fun) self.left_frame.s.item_2.update_.connect(self.fun) def fun(self, str_): print(str_) self.right_frame.lab.setText(str_) def setstatus_bar(self): self.sta_bar.addWidget(QLabel("程序运行中 ")) self.setStatusBar(self.sta_bar)
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) bar = self.menuBar() game_menu = bar.addMenu("Game") game_menu.addAction("save") game_menu.addAction("add") #game_menu.triggered[QAction].connect( self.gameMenuTrigger ) self.setStyleSheet("background-color: white") self.statusBar = QStatusBar() turnButton = QPushButton() self.statusBar.addWidget(turnButton) self.setWindowTitle("Halma") self.setStatusBar(self.statusBar) self.statusChangedEvent() def statusChangedEvent(self): self.statusBar.showMessage(halma.getStatusMessage()) def setCenterWidget(self, widget): self.setCentralWidget(widget)
def build_ui(self): # build a main GUI window self.main_window = QMainWindow() self.main_window.setWindowTitle('Analysis tool') self.main_window.show() self.canvas = pg.ScatterPlotWidget() # add a label to the main window splitter = QSplitter(self.main_window) splitter.addWidget(self.canvas) self.main_window.setCentralWidget(splitter) # add a toolbar with an action button to the main window action = QAction('Open result file', self) action.triggered.connect(self.openFile) toolbar = QToolBar() toolbar.addAction(action) self.main_window.addToolBar(toolbar) # self.main_window.addToolBar(Qt.BottomToolBarArea, # NavigationToolbar(self.canvas, self.main_window)) # add a status bar to the main window self.status_openfile = QLabel("No file open.") self.status_data = QLabel("") status_bar = QStatusBar() status_bar.addWidget(self.status_openfile, 1) status_bar.addWidget(self.status_data, 0) self.main_window.setStatusBar(status_bar) self.result = None self.index = 0 self.plotdata = [[], [], []] self.currentData = [[], [], []] self.installEventFilter(self)
def __buildUI(self): ##构造界面 self.resize(600, 450) self.setWindowTitle("Demo8_5, View/Scene/Item关系和坐标变换") font = self.font() font.setPointSize(11) self.setFont(font) centralWidget = QWidget(self) #中间工作区组件 vLayoutMain = QVBoxLayout(centralWidget) #垂直布局 groupBox = QGroupBox(centralWidget) #显示两个Label的groupBox vLayoutGroup = QVBoxLayout(groupBox) self.__labViewSize = QLabel(groupBox) self.__labViewSize.setText("view坐标,左上角(0,0),宽度=,长度=") vLayoutGroup.addWidget(self.__labViewSize) self.__labSceneRect = QLabel(groupBox) self.__labSceneRect.setText("view.sceneRect=()") vLayoutGroup.addWidget(self.__labSceneRect) vLayoutMain.addWidget(groupBox) #主布局添加groupBox self.view = QmyGraphicsView(centralWidget) #绘图视图 self.view.setCursor(Qt.CrossCursor) self.view.setMouseTracking(True) ## self.view.setDragMode(QGraphicsView.RubberBandDrag) vLayoutMain.addWidget(self.view) #添加到主布局 self.setCentralWidget(centralWidget) #设置工作区中间组件 statusBar = QStatusBar(self) #状态栏 self.setStatusBar(statusBar) self.__labViewCord = QLabel("View 坐标:") self.__labViewCord.setMinimumWidth(150) statusBar.addWidget(self.__labViewCord) self.__labSceneCord = QLabel("Scene 坐标:") self.__labSceneCord.setMinimumWidth(150) statusBar.addWidget(self.__labSceneCord) self.__labItemCord = QLabel("Item 坐标:") self.__labItemCord.setMinimumWidth(150) statusBar.addWidget(self.__labItemCord)
class MainWindow(QMainWindow): def __init__(self, conn, parent=None): super(MainWindow, self).__init__(parent) """ Connection object as attribute. """ self.conn = conn self.conn.synced.connect(self._conn_synced) self.conn.unsynced.connect(self._conn_unsynced) """ Dictionary of objects available to the window and widgets""" self.objects = {} self.objects['ut'] = UniversalTime(self.conn) self.objects['vessels'] = Vessels(self.conn) """ Populating menu bar. """ bar = self.menuBar() remote_menu = bar.addMenu("Remote") vessels_menu = VesselsMenu(self, self.objects['vessels'], bar) """ Populating Remote menu. """ def remote_action(q): if q.text() == "Connection to kRPC server": connection_window = ConnectionWindow(conn) connection_window.show() remote_menu.addAction("Connection to kRPC server") remote_menu.triggered[QAction].connect(remote_action) """ Populating status bar. """ self.status_conn = StatusLabel("Not connected.") self.status_ut = StatusLabel("UT not synchronized.") self.status_bar = QStatusBar() self.status_bar.addWidget(self.status_conn) self.status_bar.addWidget(self.status_ut) self.objects['ut'].updated.connect(self._ut_updated) self.setStatusBar(self.status_bar) """ Define window layout. """ self.setWindowTitle("Krocs") self.mdi = QMdiArea() self.setCentralWidget(self.mdi) """ Catch main window close event to close application. """ def closeEvent(self, event): QCoreApplication.instance().quit() def _conn_synced(self): """ Updating view if new connection. """ self.status_conn.setText("Connected to %s." % self.conn.addr) self.status_conn.setValid() def _conn_unsynced(self): """ Updating view if closed connection. """ self.status_conn.setText("Not connected.") self.status_conn.setCritical() self.status_ut.setText("UT: Not synchronized.") self.status_ut.setCritical() def _ut_updated(self): """ Update view if UT changed. """ self.status_ut.setText( "UT: Y%02d/D%03d %d:%02d:%02d" % (int(self.objects['ut'].value) // 9203328, ((int(self.objects['ut'].value) // 21600000) % 42608) // 1000, (int(self.objects['ut'].value) // 3600) % 6, (int(self.objects['ut'].value) // 60) % 60, int(self.objects['ut'].value) % 60)) self.status_ut.setValid()
class Controller(): '''Todas funções e ações comuns para todos os usuários estão nesta classe''' def __init__(self, parent): self.parent = parent self.setStatusBar() def setStatusBar(self): '''Substitui a statuBar inicial pelo nome do usuário e data atual''' self.status_bar = QStatusBar(self.parent)#Cria uma nova statusBar self.parent.setStatusBar(self.status_bar)#Define a nova statusBar como padrão #Adiciona o texto do lado esquerdo da statusBar self.status_bar.addWidget(QLabel(str(self.parent.usuario.descricao))) self.status_bar.addWidget(QLabel("-")) self.status_bar.addWidget(QLabel(self.parent.usuario.nome)) self.status_bar.addWidget(QLabel(self.parent.usuario.sobrenome)) #Adiciona o texto do lado direito da statusBar self.status_bar.addPermanentWidget(QLabel(date.today().strftime('%d/%m/%Y'))) def deconectar(self): '''Desconecta o usuário atual, redireciona o sistema para a tela de login''' del self.parent.usuario#Excluir a instancia da classe usuario, para ser instanciada uma nova classe em um futuro login self.parent.startInterfaceLogin()#Carrega a tela de Login self.parent.menu.setMenusPrincipal()#Configura o Menu da Tela Inicial del self.parent.mdi_area #Deleta o MDIArea para inicialização do centralWidget da tela de login def showTrocaSenha(self): '''Altera o widget central para o formulario de troca de senha''' self.sub_troca_senha = TrocaSenha(self) self.parent.mdi_area.addSubWindow(self.sub_troca_senha) self.sub_troca_senha.show() def trocarSenha(self): '''Altera a senha do usuário''' senha_antiga = self.sub_troca_senha.edit_senha_antiga.text()#Recebe o valor digitado senha_nova = self.sub_troca_senha.edit_senha_nova.text()#Recebe o valor digitado confirma_nova = self.sub_troca_senha.edit_confirma_nova.text()#Recebe o valor digitado if(senha_nova == confirma_nova):#Compara o valor das novas senhas if(senha_antiga == self.parent.usuario.password):#compara a senha antiga self.parent.usuario.password = senha_nova#troca a senha na instancia do objeto if(self.parent.usuario.alteraSenha()):#aciona o metodo do objeto para trocar a senha no banco self.sub_troca_senha.showMessageSucesso()#caso a troca do banco retorne com sucesso exibe a menssagem de sucesso self.parent.mdi_area.removeSubWindow(self.sub_troca_senha)#remove a subwindow da tela del self.sub_troca_senha#deleta a instancia da subwindow else:#Caso a senha antiga estiver errada self.sub_troca_senha.showMessageErro() else:#Caso a senha digitade esteja errada self.sub_troca_senha.showMessageErro() def showRelatorioSimples(self): '''Exibe um relatorio simples no central widget determinado nos parametros Usado para tela home do gerente e estoquista Informações do relatorio: -Quantidade em Estoque -Produtos vencidos -Produtos que vencem em 30 dias -Produtos que vencem em 60 dias ''' self.parent.conteudo_central.addWidget(self.home_gerente) self.parent.conteudo_central.setCurrentWidget(self.home_gerente) def formataCpf(self, cpf): '''Retorna o CPF formatado(somente Numeros) parametros: cpf - Não formatado ex: 111.222.333-44 retorno: cpf - Formatado ex: 11122233344''' cpf_formatado = "" for digito in str(cpf): if digito.isdigit(): cpf_formatado += str(digito) return cpf_formatado
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): monospacedFont = QFontDatabase.systemFont(QFontDatabase.FixedFont) bottombox = QHBoxLayout() self.serialPortEdit = QLineEdit() self.serialPortEdit.setPlaceholderText("Enter full path to the serial port") self.serialPortEdit.returnPressed.connect(self.on_serialportedit_enter_pressed) self.serialPortEdit.setFont(monospacedFont) self.baudrateComboBox = QComboBox() self.std_baudrates = [50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200] self.baudrateComboBox.addItems(map(lambda x: str(x), self.std_baudrates)) self.baudrateComboBox.setPlaceholderText("Select Baud rate") self.baudrateComboBox.setCurrentIndex(-1) self.connectBtn = QPushButton("Connect") self.connectBtn.clicked.connect(self.on_connect_btn_clicked) self.disconnectBtn = QPushButton("Disconnect") self.disconnectBtn.clicked.connect(self.on_disconnect_btn_clicked) self.disconnectBtn.setEnabled(False) bottombox.addWidget(self.serialPortEdit) bottombox.addWidget(self.baudrateComboBox) bottombox.addWidget(self.connectBtn) bottombox.addWidget(self.disconnectBtn) mainvbox = QVBoxLayout() self.serialOutputEdit = QPlainTextEdit() self.serialOutputEdit.setReadOnly(True) self.serialOutputEdit.setFont(monospacedFont) self.serialInputEdit = QLineEdit() self.serialInputEdit.setPlaceholderText("Enter your data you want to send to the port") self.serialInputEdit.setEnabled(False) self.serialInputEdit.setFont(monospacedFont) mainvbox.addWidget(self.serialOutputEdit) mainvbox.addWidget(self.serialInputEdit) mainvbox.addLayout(bottombox) centralWidget = QWidget(self) centralWidget.setLayout(mainvbox) self.setCentralWidget(centralWidget) self.statusBar = QStatusBar() connectedImage = QImage.fromData(base64.b64decode(connectedImagebase64), "PNG") disonnectedImage = QImage.fromData(base64.b64decode(disconnectedImagebase64), "PNG") self.connectedImagePixMap = QPixmap.fromImage(connectedImage) self.disconnectedImagePixMap = QPixmap.fromImage(disonnectedImage) self.connectionStatusLabelIcon = QLabel() self.connectionStatusLabelIcon.setPixmap(self.disconnectedImagePixMap) self.connectionStatusLabelText = QLabel("Disconnected") self.statusBar.addWidget(self.connectionStatusLabelIcon) self.statusBar.addWidget(self.connectionStatusLabelText) self.timerPushButton = QPushButton("Enable Timer") self.timerPushButton.setCheckable(True) self.timerPushButton.toggled.connect(self.on_timerPushButton_toggled) self.timerWindowDoubleSpinBox = QDoubleSpinBox() self.timerWindowDoubleSpinBox.setMinimum(0) self.timerWindowDoubleSpinBox.setMaximum(10) self.timerWindowDoubleSpinBox.setDecimals(1) self.timerWindowDoubleSpinBox.setValue(1) self.timerWindowDoubleSpinBox.setSuffix(" s") self.clearConsolePushButton = QPushButton("Clear console") self.clearConsolePushButton.clicked.connect(self.on_clearConsolePushButton_clicked) self.filterStringCheckBox = QCheckBox("Enable Filter") self.filterStringCheckBox.stateChanged.connect(self.on_filterStringCheckBox_stateChanged) self.filterEnabled = False self.filterString = "" self.filterStringEdit = QLineEdit() self.filterStringEdit.setPlaceholderText("Filter String") self.filterStringEdit.setFont(monospacedFont) self.filterStringEdit.textEdited.connect(self.on_filterStringEdit_textEdited) self.statusBar.addPermanentWidget(self.filterStringCheckBox) self.statusBar.addPermanentWidget(self.filterStringEdit) self.statusBar.addPermanentWidget(self.clearConsolePushButton) self.statusBar.addPermanentWidget(self.timerPushButton) self.statusBar.addPermanentWidget(self.timerWindowDoubleSpinBox) self.statusBar.layout().setContentsMargins(8, 0, 0, 0) self.setStatusBar(self.statusBar) self.setGeometry(300, 300, 800, 495) self.setWindowTitle('Attify Serial Console') self.show() def on_filterStringEdit_textEdited(self, text): if self.filterStringCheckBox.isChecked(): self.filterString = text def on_filterStringCheckBox_stateChanged(self, state): if self.filterStringCheckBox.isChecked(): self.filterString = self.filterStringEdit.text().strip() self.filterEnabled = True else: self.filterEnabled = False def on_clearConsolePushButton_clicked(self): self.serialOutputEdit.clear() def on_timerPushButton_toggled(self, checked): self.timerWindowDoubleSpinBox.setEnabled(not checked) if checked: Timer.currentTimerWindow = self.timerWindowDoubleSpinBox.value() else: Timer.currentTimerWindow = -1 def closeEvent(self,event): try: self.readMonitorQ.quit() except: pass try: self.serialReader.stop() except: pass try: self.serialWriter.stop() except: pass try: self.serial_port.close() except: pass event.accept() def on_serialportedit_enter_pressed(self): self.on_connect_btn_clicked() def on_serialinput_enter_pressed(self): cmd = str(self.serialInputEdit.text()).strip() if len(cmd) > 0: self.serialOutputEdit.appendPlainText('>> ' + cmd) cmd = (cmd + '\r\n').encode() if Timer.currentTimerWindow != -1: Timer.lastSerialInputTime = time.time() self.write_Q.put(cmd) self.serialInputEdit.clear() def on_connect_btn_clicked(self): serial_port_txt = self.serialPortEdit.text() if len(serial_port_txt) > 0: index = self.baudrateComboBox.currentIndex() if index == -1: error_dialog = QErrorMessage(self) error_dialog.setModal(True) error_dialog.showMessage("Please select a baud rate") else: baud_rate = self.std_baudrates[index] try: self.serial_port = serial.Serial(serial_port_txt, timeout=1, baudrate=baud_rate) except Exception as ex: error_dialog = QErrorMessage(self) error_dialog.setModal(True) error_dialog.showMessage(str(ex)) else: self.connectBtn.setEnabled(False) self.disconnectBtn.setEnabled(True) self.serialInputEdit.setEnabled(True) self.connectionStatusLabelText.setText("Connected") self.connectionStatusLabelIcon.setPixmap(self.connectedImagePixMap) self.baudrateComboBox.setEnabled(False) self.start_reader() self.start_writer() def write_to_Serial_Output_Edit(self, data): cleaned_text = strip_ansi(data.decode('ascii')).strip() if (self.filterEnabled and self.filterString not in cleaned_text) or not self.filterEnabled: self.serialOutputEdit.appendPlainText(cleaned_text) def start_reader(self): self.read_Q = queue.Queue() self.serialReader = SerialReader(self.serial_port, self.read_Q) self.serialReader.start_threaded() self.readMonitorQ = MonitorQ(self.read_Q) self.readMonitorQ.dataAvailable.connect(self.write_to_Serial_Output_Edit) self.readMonitorQ.start() def start_writer(self): self.write_Q = queue.Queue() self.serialWriter = SerialWriter(self.serial_port, self.write_Q) self.serialWriter.start_threaded() self.serialInputEdit.returnPressed.connect(self.on_serialinput_enter_pressed) def on_disconnect_btn_clicked(self): self.connectBtn.setEnabled(True) self.disconnectBtn.setEnabled(False) self.serialInputEdit.setEnabled(False) self.connectionStatusLabelText.setText("Disconnected") self.connectionStatusLabelIcon.setPixmap(self.disconnectedImagePixMap) self.serialInputEdit.returnPressed.disconnect(self.on_serialinput_enter_pressed) self.baudrateComboBox.setEnabled(True) self.readMonitorQ.quit() self.serialReader.stop() self.serialWriter.stop() self.serial_port.close()
class View(QWidget): # Send data to port send_data = pyqtSignal(object) # Chage baudrate baudrate_changed = pyqtSignal(object) # Change end of line eol_changed = pyqtSignal(object) # Change port port_changed = pyqtSignal(object) # Pause model pause_m = pyqtSignal(object) # Continue model start_m = pyqtSignal(object) def __init__(self): QWidget.__init__(self) self.queue = None self.end_cmd = None self.autoscroll = False self.msg_sent = False self.timer = QTimer() self.timer.timeout.connect(self.update_gui) self.timer.start(100) self.__initUI() def __initUI(self): vbox = QVBoxLayout(self) # vbox.setSpacing(0) vbox.setContentsMargins(3, 3, 3, 3) # Add window's menu bar self.menubar = QMenuBar() file_menu = self.menubar.addMenu('File') file_menu.addAction('Save', self.save_to_file) vbox.addWidget(self.menubar) # Command box cmd_hbox = QHBoxLayout() self.cmd_edit = QLineEdit() cmd_hbox.addWidget(self.cmd_edit) cmd_btn = QPushButton('Send') cmd_btn.clicked.connect(self.emit_send_data) cmd_hbox.addWidget(cmd_btn) cmd_btn = QPushButton('Start') cmd_btn.clicked.connect(self.start_m.emit) cmd_hbox.addWidget(cmd_btn) cmd_btn = QPushButton('Stop') cmd_btn.clicked.connect(self.pause_m.emit) cmd_hbox.addWidget(cmd_btn) vbox.addLayout(cmd_hbox) # Editors pair box editor_hbox = QHBoxLayout() # Text edit area self.editer = QPlainTextEdit() self.editer.scrollContentsBy = self.ModScrollContentsBy editor_hbox.addWidget(self.editer) # HEX edit area self.editor_hex = QPlainTextEdit() self.editor_hex.scrollContentsBy = self.ModScrollContentsBy editor_hbox.addWidget(self.editor_hex) vbox.addLayout(editor_hbox) # Settings area stng_hbox = QHBoxLayout() # - Autoscroll chk_btn = QCheckBox('Autoscroll') chk_btn.stateChanged.connect(self.set_autoscroll) stng_hbox.addWidget(chk_btn) cmd_btn = QPushButton('Clear') cmd_btn.clicked.connect(self.editer.clear) cmd_btn.clicked.connect(self.editor_hex.clear) stng_hbox.addWidget(cmd_btn) stng_hbox.addStretch(1) # - Ending of line self.eol_menu = QComboBox() self.eol_menu.addItem('No line ending') self.eol_menu.addItem('Newline') self.eol_menu.addItem('Carriage return') self.eol_menu.addItem('Both NL + CR') self.eol_menu.setCurrentIndex(0) self.eol_menu.currentIndexChanged.connect(self.emit_eol_changed) stng_hbox.addWidget(self.eol_menu) # - Baudrate select self.br_menu = QComboBox() self.br_menu.addItem('300 baud') self.br_menu.addItem('1200 baud') self.br_menu.addItem('2400 baud') self.br_menu.addItem('4800 baud') self.br_menu.addItem('9600 baud') self.br_menu.addItem('19200 baud') self.br_menu.addItem('38400 baud') self.br_menu.addItem('57600 baud') self.br_menu.addItem('115200 baud') self.br_menu.addItem('230400 baud') self.br_menu.addItem('460800 baud') self.br_menu.currentIndexChanged.connect(self.emit_br_changed) # Set default baudrate 9600 self.br_menu.setCurrentIndex(4) stng_hbox.addWidget(self.br_menu) vbox.addLayout(stng_hbox) # Port editing form port_hbox = QHBoxLayout() port_lbl = QLabel('Port: ') port_hbox.addWidget(port_lbl) self.port_edit = QLineEdit() self.port_edit.editingFinished.connect(self.changePort) port_hbox.addWidget(self.port_edit) vbox.addLayout(port_hbox) # Status Bar self.status_bar = QStatusBar() self.status_label = QLabel() self.status_label.setAlignment(Qt.AlignRight) self.status_bar.addWidget(self.status_label, 1) vbox.addWidget(self.status_bar) self.setLayout(vbox) def show_error(self, value): msg = QMessageBox(QMessageBox.NoIcon, 'Error occured.', value, QMessageBox.Ok) msg.exec() #============================================================================== # Get, set #============================================================================== def set_queue(self, queue): self.queue = queue def set_end_cmd(self, end_cmd): self.end_cmd = end_cmd def set_autoscroll(self, value): self.autoscroll = value def set_port(self, value): self.port_edit.insert(value) def get_cmd(self): return self.cmd_edit.text() def set_eol(self, value): self.eol_menu.setCurrentIndex(value) def update_status_bar(self, data_set): ''' Update GUI status bar. Args: data_set: Dictionary with port configurations: port, baudrate, number of bits, parity, number of stop bits. ''' string = '{} {}-{}-{}'.format(data_set['baudrate'], data_set['num_of_bits'], data_set['parity'], data_set['num_of_stop']) self.status_label.setText(string) def update_gui(self): self.process_incoming() self.update() def appendText(self, data): # pos = QPoint(self.editer.textCursor().position(), 0) # self.editer.moveCursor(QTextCursor.End) # self.editer.insertPlainText(text) self.editer.appendPlainText(data[0]) # self.editer.cursorForPosition(pos) self.editor_hex.appendHtml(data[1]) def process_incoming(self): while self.queue.qsize(): try: msg = self.queue.get(0) # Check contents of message and do what it says # As a test, we simply print it # print(bytes(msg, 'ASCII'), end='') # self.editer.appendPlainText(msg) self.appendText(msg) if self.autoscroll: self.editer.ensureCursorVisible() self.editor_hex.ensureCursorVisible() self.scroll_down() except Queue.empty: pass def scroll_down(self): for editor in [self.editer, self.editor_hex]: sb = editor.verticalScrollBar() sb.setValue(sb.maximum()) editor.moveCursor(QTextCursor.End) def changePort(self): if not self.msg_sent: self.msg_sent = True self.emit_port_changed() else: self.msg_sent = False return None #============================================================================== # Utils #============================================================================== def save_to_file(self): _file = QFileDialog.getSaveFileName() if _file[0]: with open(_file[0], 'w+') as fn: fn.write(self.editer.toPlainText()) #============================================================================== # Signals #============================================================================== def emit_send_data(self): self.send_data.emit(self.get_cmd()) self.cmd_edit.clear() def emit_br_changed(self, value): baudrate = self.br_menu.itemText(value)[:-5] self.baudrate_changed.emit(baudrate) def emit_eol_changed(self, value): self.eol_changed.emit(value) def emit_port_changed(self): self.port_edit.clearFocus() self.port_changed.emit(self.port_edit.text()) #============================================================================== # Events #============================================================================== def ModScrollContentsBy(self, dx, dy): # print('as: {}. dx: {}. dy: {}.'.format(self.autoscroll, dx, dy)) for editor in [self.editer, self.editor_hex]: if self.autoscroll: editor.ensureCursorVisible() else: QPlainTextEdit.scrollContentsBy(editor, dx, dy) def closeEvent(self, event): self.end_cmd() QWidget.closeEvent(self, event) print('exit')
class ChessClaimView(QMainWindow): """ The main window of the application. Attributes: rowCount(int): The number of the row the TreeView Table has. iconsSize(int): The recommended size of the icons. mac_notification: Notification for macOS win_notification: Notification for windows OS """ def __init__(self): super().__init__() self.resize(720, 275) self.iconsSize = 16 self.setWindowTitle('Chess Claim Tool') self.center() self.rowCount = 0 if (platform.system() == "Darwin"): from MacNotification import Notification self.mac_notification = Notification() elif (platform.system() == "Windows"): from win10toast import ToastNotifier self.win_notification = ToastNotifier() 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 set_GUI(self): """ Initialize GUI components. """ # Create the Menu self.livePgnOption = QAction('Live PGN',self) self.livePgnOption.setCheckable(True) aboutAction = QAction('About',self) menubar = self.menuBar() optionsMenu = menubar.addMenu('&Options') optionsMenu.addAction(self.livePgnOption) aboutMenu = menubar.addMenu('&Help') aboutMenu.addAction(aboutAction) aboutAction.triggered.connect(self.slots.on_about_clicked) # Create the Claims Table (TreeView) self.claimsTable = QTreeView() self.claimsTable.setFocusPolicy(Qt.NoFocus) self.claimsTable.setEditTriggers(QAbstractItemView.NoEditTriggers) self.claimsTable.header().setDefaultAlignment(Qt.AlignCenter) self.claimsTable.setSortingEnabled(True) self.claimsTable.doubleClicked.connect(self.open_game) # Create the Claims Model self.claimsTableModel = QStandardItemModel() labels = ["#","Timestamp","Type","Board","Players","Move"] self.claimsTableModel.setHorizontalHeaderLabels(labels) self.claimsTable.setModel(self.claimsTableModel) # Create the Scan & Stop Button Box self.buttonBox = ButtonBox(self) # Create the Sources Button sourcesButton = QPushButton("Add Sources") sourcesButton.setObjectName("sources") sourcesButton.clicked.connect(self.slots.on_sourcesButton_clicked) # Create the Status Bar self.pixmapCheck = QPixmap(resource_path("check_icon.png")) self.pixmapError = QPixmap(resource_path("error_icon.png")) self.sourceLabel = QLabel() self.sourceLabel.setObjectName("source-label") self.sourceImage = QLabel() self.sourceImage.setObjectName("source-image") self.downloadLabel = QLabel() self.downloadLabel.setObjectName("download-label") self.downloadImage = QLabel() self.downloadImage.setObjectName("download-image") self.scanningLabel = QLabel() self.scanningLabel.setObjectName("scanning") self.spinnerLabel = QLabel() self.spinnerLabel.setVisible(False) self.spinnerLabel.setObjectName("spinner") self.spinner = QMovie(resource_path("spinner.gif")) self.spinner.setScaledSize(QSize(self.iconsSize, self.iconsSize)) self.spinnerLabel.setMovie(self.spinner) self.spinner.start() self.statusBar = QStatusBar() self.statusBar.setSizeGripEnabled(False) self.statusBar.addWidget(self.sourceLabel) self.statusBar.addWidget(self.sourceImage) self.statusBar.addWidget(self.downloadLabel) self.statusBar.addWidget(self.downloadImage) self.statusBar.addWidget(self.scanningLabel) self.statusBar.addWidget(self.spinnerLabel) self.statusBar.addPermanentWidget(sourcesButton) self.statusBar.setContentsMargins(10,5,9,5) # Container Layout for the Central Widget containerLayout = QVBoxLayout() containerLayout.setSpacing(0) containerLayout.addWidget(self.claimsTable) containerLayout.addWidget(self.buttonBox) # Central Widget containerWidget = QWidget() containerWidget.setLayout(containerLayout) self.setCentralWidget(containerWidget) self.setStatusBar(self.statusBar) def open_game(self): """ TODO: Double click should open a window to replay the game.""" pass def resize_claimsTable(self): """ Resize the table (if needed) after the insertion of a new element""" for index in range(0,6): self.claimsTable.resizeColumnToContents(index) def set_slots(self, slots): """ Connect the Slots """ self.slots = slots def add_to_table(self,type,bo_number,players,move): """ Add new row to the claimsTable Args: type: The type of the draw (3 Fold Repetition, 5 Fold Repetition, 50 Moves Rule, 75 Moves Rule). bo_number: The number of the boards, if this information is available. players: The name of the players. move: With which move the draw is valid. """ # Before insertion, remove rows as descripted in the remove_rows function self.remove_rows(type,players) timestamp = str(datetime.now().strftime('%H:%M:%S')) row = [] items = [str(self.rowCount+1),timestamp,type,bo_number,players,move] """ Convert each item(str) to QStandardItem, make the necessary stylistic additions and append it to row.""" for index in range(len(items)): standardItem = QStandardItem(items[index]) standardItem.setTextAlignment(Qt.AlignCenter) if(index == 2): font = standardItem.font() font.setBold(True) standardItem.setFont(font) if (items[index] == "5 Fold Repetition" or items[index] == "75 Moves Rule"): standardItem.setData(QColor(255,0,0), Qt.ForegroundRole) row.append(standardItem) self.claimsTableModel.appendRow(row) self.rowCount = self.rowCount+1 # After the insertion resize the table self.resize_claimsTable() # Always the last row(the bottom of the table) should be visible. self.claimsTable.scrollToBottom() #Send Notification self.notify(type,players,move) def notify(self,type,players,move): """ Send notification depending on the OS. Args: type: The type of the draw (3 Fold Repetition, 5 Fold Repetition, 50 Moves Rule, 75 Moves Rule). players: The names of the players. move: With which move the draw is valid. """ if (platform.system() == "Darwin"): self.mac_notification.clearNotifications() self.mac_notification.notify(type,players,move) elif(platform.system() == "Windows"): self.win_notification.show_toast(type, players+"\n"+move, icon_path=resource_path("logo.ico"), duration=5, threaded=True) def remove_from_table(self,index): """ Remove element from the claimsTable. Args: index: The index of the row we want to remove. First row has index=0. """ self.claimsTableModel.removeRow(index) def remove_rows(self,type,players): """ Removes a existing row from the Claims Table when same players made the same type of draw with a new move - or they made 5 Fold Repetition over the 3 Fold or 75 Moves Rule over 50 moves Rule. Args: type: The type of the draw (3 Fold Repetition, 5 Fold Repetition, 50 Moves Rule, 75 Moves Rule). players: The names of the players. """ for index in range(self.rowCount): try: modelType = self.claimsTableModel.item(index,2).text() modelPlayers = self.claimsTableModel.item(index,4).text() except AttributeError: modelType = "" modelPlayers = "" if (modelType == type and modelPlayers == players): self.remove_from_table(index) self.rowCount = self.rowCount - 1 break elif (type == "5 Fold Repetition" and modelType == "3 Fold Repetition" and modelPlayers == players) : self.remove_from_table(index) self.rowCount = self.rowCount - 1 break elif (type == "75 Moves Rule" and modelType == "50 Moves Rule" and modelPlayers == players): self.remove_from_table(index) self.rowCount = self.rowCount - 1 break def clear_table(self): """ Clear all the elements off the Claims Table and resets the rowCount. """ for index in range(self.rowCount): self.claimsTableModel.removeRow(0) self.rowCount = 0 def set_sources_status(self,status,validSources=None): """ Adds the sourcess in the statusBar. Args: status(str): The status of the validity of the sources. "ok": At least one source is valid. "error": None of the sources are valid. validSources(list): The list of valid sources, if there is any. This list is used here to display the ToolTip. """ self.sourceLabel.setText("Sources:") # Set the ToolTip if there are sources. try: text = "" for index in range(len(validSources)): if (index == len(validSources) - 1): number = str(index+1) text = text+number+") "+validSources[index].get_value() else: number = str(index+1) text = text+number+") "+validSources[index].get_value()+"\n" self.sourceLabel.setToolTip(text) except TypeError: pass if (status == "ok"): self.sourceImage.setPixmap(self.pixmapCheck.scaled(self.iconsSize,self.iconsSize,transformMode=Qt.SmoothTransformation)) else: self.sourceImage.setPixmap(self.pixmapError.scaled(self.iconsSize,self.iconsSize,transformMode=Qt.SmoothTransformation)) def set_download_status(self,status): """ Adds download status in the statusBar. Args: status(str): The status of the download(s). "ok": The download of the sources is successful. "error": The download of the sources failed. "stop": The download process stopped. """ timestamp = str(datetime.now().strftime('%H:%M:%S')) self.downloadLabel.setText(timestamp+" Download:") if (status == "ok"): self.downloadImage.setPixmap(self.pixmapCheck.scaled(self.iconsSize,self.iconsSize,transformMode=Qt.SmoothTransformation)) elif (status == "error"): self.downloadImage.setPixmap(self.pixmapError.scaled(self.iconsSize,self.iconsSize,transformMode=Qt.SmoothTransformation)) elif (status == "stop"): self.downloadImage.clear() self.downloadLabel.clear() def set_scan_status(self,status): """ Adds the scan status in the statusBar. Args: status(str): The status of the scan process. "active": The scan process is active. "error": The scan process waits for a new file. "stop": The scan process stopped. """ if (status == "wait"): self.scanningLabel.setText("Scan: Waiting") self.spinnerLabel.setVisible(False) elif (status == "active"): self.scanningLabel.setText("Scanning...") self.spinnerLabel.setVisible(True) elif (status == "stop"): self.scanningLabel.clear() self.spinnerLabel.setVisible(False) def change_scanButton_text(self,status): """ Changes the text of the scanButton depending on the status of the application. Args: status(str): The status of the scan process. "active": The scan process is active. "wait": The scan process is being terminated "stop": The scan process stopped. """ if (status == "active"): self.buttonBox.scanButton.setText("Scanning PGN...") elif (status == "stop"): self.buttonBox.scanButton.setText("Start Scan") elif(status == "wait"): self.buttonBox.scanButton.setText("Please Wait") def enable_buttons(self): self.buttonBox.scanButton.setEnabled(True) self.buttonBox.stopButton.setEnabled(True) def disable_buttons(self): self.buttonBox.scanButton.setEnabled(False) self.buttonBox.stopButton.setEnabled(False) def enable_statusBar(self): """ Show download and scan status messages - if they were previously hidden (by disable_statusBar) - from the statusBar.""" self.downloadLabel.setVisible(True) self.scanningLabel.setVisible(True) self.downloadImage.setVisible(True) def disable_statusBar(self): """ Hide download and scan status messages from the statusBar. """ self.downloadLabel.setVisible(False) self.downloadImage.setVisible(False) self.scanningLabel.setVisible(False) self.spinnerLabel.setVisible(False) def closeEvent(self,event): """ Reimplement the close button If the program is actively scanning a pgn a warning dialog shall be raised in order to make sure that the user didn't clicked the close Button accidentally. Args: event: The exit QEvent. """ try: if (self.slots.scanWorker.isRunning): exitDialog = QMessageBox() exitDialog.setWindowTitle("Warning") exitDialog.setText("Scanning in Progress") exitDialog.setInformativeText("Do you want to quit?") exitDialog.setIcon(exitDialog.Warning) exitDialog.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel) exitDialog.setDefaultButton(QMessageBox.Cancel) replay = exitDialog.exec() if replay == QMessageBox.Yes: event.accept() else: event.ignore() except: event.accept() def load_warning(self): """ Displays a Warning Dialog. trigger: User clicked the "Start Scanning" Button without any valid pgn source. """ warningDialog = QMessageBox() warningDialog.setIcon(warningDialog.Warning) warningDialog.setWindowTitle("Warning") warningDialog.setText("PGN File(s) Not Found") warningDialog.setInformativeText("Please enter at least one valid PGN source.") warningDialog.exec() def load_about_dialog(self): """ Displays the About Dialog.""" self.aboutDialog = AboutDialog() self.aboutDialog.set_GUI() self.aboutDialog.show()
class MainWin(QMainWindow): def __init__(self): super(MainWin, self).__init__() self.settings = QSettings("RadioBOB", "settings") self.setStyleSheet(mystylesheet(self)) self.radioNames = [] self.radiolist = [] self.channels = [] self.imagelist = [] self.radiofile = "" self.radioStations = "" self.rec_name = "" self.rec_url = "" self.old_meta = "" self.notificationsEnabled = True self.headerlogo = QIcon( os.path.join(os.path.dirname(sys.argv[0]), "headerlogo.png")) self.setContentsMargins(5, 0, 5, 0) self.wg = QWidget() self.er_label = QLabel("Image") self.er_label.setPixmap(self.headerlogo.pixmap(QSize(300, 140))) self.er_label.setScaledContents(False) self.er_label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.layout = QVBoxLayout() ### combo box self.urlCombo = QComboBox() self.er_label.setAlignment(Qt.AlignCenter) self.layout.addWidget(self.er_label, 0, Qt.AlignCenter) self.layout1 = QHBoxLayout() self.layout1.setContentsMargins(50, 0, 50, 0) self.tIcon = QIcon( os.path.join(os.path.dirname(sys.argv[0]), "logo.png")) self.playIcon = QIcon( os.path.join(os.path.dirname(sys.argv[0]), "media-playback-start.svg")) self.stopIcon = QIcon( os.path.join(os.path.dirname(sys.argv[0]), "media-playback-stop.svg")) self.recordIcon = QIcon( os.path.join(os.path.dirname(sys.argv[0]), "media-record.svg")) self.hideIcon = QIcon( os.path.join(os.path.dirname(sys.argv[0]), "hide.png")) self.outfile = QStandardPaths.standardLocations( QStandardPaths.TempLocation)[0] + "/er_tmp.mp3" self.recording_enabled = False self.is_recording = False spc1 = QSpacerItem(6, 10, QSizePolicy.Expanding, QSizePolicy.Maximum) self.play_btn = QPushButton("", self) self.play_btn.setFixedWidth(btnwidth) self.play_btn.setIcon(self.playIcon) self.layout1.addWidget(self.play_btn) self.stop_btn = QPushButton("", self) self.stop_btn.setFixedWidth(btnwidth) self.stop_btn.setIcon(self.stopIcon) self.layout1.addWidget(self.stop_btn) ### record self.rec_btn = QPushButton("", self) self.rec_btn.setFixedWidth(btnwidth) self.rec_btn.setIcon(self.recordIcon) self.rec_btn.clicked.connect(self.recordRadio) self.rec_btn.setToolTip("Aufnehmen") self.layout1.addWidget(self.rec_btn) ### stop record self.stoprec_btn = QPushButton("", self) self.stoprec_btn.setFixedWidth(btnwidth) self.stoprec_btn.setIcon(self.stopIcon) self.stoprec_btn.clicked.connect(self.stop_recording) self.stoprec_btn.setToolTip("Aufnahme stoppen") self.layout1.addWidget(self.stoprec_btn) ### Hauptfenster verbergen self.hide_btn = QPushButton("", self) self.hide_btn.setFixedWidth(btnwidth) self.hide_btn.setToolTip("Fenster ins Tray minimieren") self.hide_btn.setIcon(self.hideIcon) self.hide_btn.clicked.connect(self.showMain) self.layout1.addWidget(self.hide_btn) self.level_sld = QSlider(self) self.level_sld.setFixedWidth(310) self.level_sld.setToolTip("Lautstärkeregler") self.level_sld.setTickPosition(1) self.level_sld.setOrientation(Qt.Horizontal) self.level_sld.setValue(65) self.level_lbl = QLabel(self) self.level_lbl.setAlignment(Qt.AlignHCenter) self.level_lbl.setText("Lautstärke 65") self.layout.addItem(spc1) self.layout.addWidget(self.level_sld, Qt.AlignCenter) self.layout.addWidget(self.level_lbl, Qt.AlignCenter) self.layout.addItem(spc1) self.layout.addLayout(self.layout1) self.player = RadioPlayer(self) self.player.metaDataChanged.connect(self.metaDataChanged) self.player.error.connect(self.handleError) self.play_btn.clicked.connect(self.playRadioStation) self.stop_btn.clicked.connect(self.stop_preview) self.level_sld.valueChanged.connect(self.set_sound_level) self.urlCombo.currentIndexChanged.connect(self.url_changed) self.current_station = "" self.process = QProcess() self.process.started.connect(self.getPID) self.wg.setLayout(self.layout) self.setCentralWidget(self.wg) self.stoprec_btn.setVisible(False) self.readStations() self.createStatusBar() self.setAcceptDrops(True) self.setWindowTitle("Radio BOB") self.setWindowIcon(self.tIcon) self.stationActs = [] self.layout.addItem(spc1) self.setFixedSize(340, 360) self.move(30, 30) # Init tray icon trayIcon = QIcon(self.tIcon) self.trayIcon = QSystemTrayIcon() self.trayIcon.setIcon(self.headerlogo) self.trayIcon.show() self.trayIcon.activated.connect(self.showMainfromTray) self.geo = self.geometry() self.showWinAction = QAction(QIcon.fromTheme("view-restore"), "Hauptfenster anzeigen", triggered=self.showMain) self.notifAction = QAction(QIcon.fromTheme("dialog-information"), "Tray Meldungen ausschalten", triggered=self.toggleNotif) self.togglePlayerAction = QAction("Wiedergabe stoppen", triggered=self.togglePlay) self.togglePlayerAction.setIcon(QIcon.fromTheme("media-playback-stop")) self.recordAction = QAction(QIcon.fromTheme("media-record"), "Aufnahme starten", triggered=self.recordRadio) self.stopRecordAction = QAction(QIcon.fromTheme("media-playback-stop"), "Aufnahme stoppen", triggered=self.stop_recording) self.findExecutable() self.readSettings() self.makeTrayMenu() self.createWindowMenu() if QSystemTrayIcon.isSystemTrayAvailable(): print("System Tray Icon verfügbar") else: print("System Tray Icon nicht verfügbar") if self.player.state() == QMediaPlayer.StoppedState: self.togglePlayerAction.setText("Wiedergabe starten") self.togglePlayerAction.setIcon( QIcon.fromTheme("media-playback-start")) elif self.player.state() == QMediaPlayer.PlayingState: self.togglePlayerAction.setText("Wiedergabe stoppen") self.togglePlayerAction.setIcon( QIcon.fromTheme("media-playback-stop")) def showTrayMessage(self, title, message, icon, timeout=4000): self.trayIcon.showMessage(title, message, icon, timeout) def handleError(self): print(f"Fehler: {self.player.errorString()}") self.showTrayMessage(f"Error:\n{self.player.errorString()}", self.tIcon, 3000) self.statusLabel.setText(f"Fehler:\n{self.player.errorString()}") def togglePlay(self): if self.togglePlayerAction.text() == "Wiedergabe stoppen": self.stop_preview() self.togglePlayerAction.setText("Wiedergabe starten") self.togglePlayerAction.setIcon( QIcon.fromTheme("media-playback-start")) else: self.playRadioStation() self.togglePlayerAction.setText("Aufnahme stoppen") self.togglePlayerAction.setIcon( QIcon.fromTheme("media-playback-stop")) def createWindowMenu(self): self.tb = self.addToolBar("Menu") self.tb_menu = QMenu() self.tb.setIconSize(QSize(44, 20)) ##### submenus from categories ########## b = self.radioStations.splitlines() for x in reversed(range(len(b))): line = b[x] if line == "": print(f"empty line {x} removed") del (b[x]) i = 0 for x in range(0, len(b)): line = b[x] menu_line = line.split(",") ch = menu_line[0] data = menu_line[1] if len(menu_line) > 2: image = menu_line[2] self.tb_menu.addAction(self.stationActs[i]) i += 1 #################################### toolButton = QToolButton() toolButton.setIcon(self.headerlogo) toolButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) toolButton.setText(" Stationen") toolButton.setFixedWidth(120) toolButton.setMenu(self.tb_menu) toolButton.setPopupMode(QToolButton.InstantPopup) self.tb.addWidget(toolButton) empty = QWidget() self.tb.addWidget(empty) self.tb.setContextMenuPolicy(Qt.PreventContextMenu) self.tb.setMovable(False) self.tb.setAllowedAreas(Qt.TopToolBarArea) def makeTrayMenu(self): self.stationActs = [] self.tray_menu = QMenu() self.tray_menu.addAction(self.togglePlayerAction) ##### submenus from categories ########## b = self.radioStations.splitlines() for x in reversed(range(len(b))): line = b[x] if line == "": print(f"empty line {x} removed") del (b[x]) i = 0 for x in range(0, len(b)): line = b[x] menu_line = line.split(",") ch = menu_line[0] data = menu_line[1] if len(menu_line) > 2: image = menu_line[2] self.stationActs.append( QAction(self.tIcon, ch, triggered=self.openTrayStation)) self.stationActs[i].setData(str(i)) self.tray_menu.addAction(self.stationActs[i]) i += 1 #################################### self.tray_menu.addSeparator() if not self.is_recording: if not self.urlCombo.currentText().startswith("--"): self.tray_menu.addAction(self.recordAction) self.recordAction.setText( f"starte Aufnahme von {self.urlCombo.currentText()}") if self.is_recording: self.tray_menu.addAction(self.stopRecordAction) self.tray_menu.addSeparator() self.tray_menu.addAction(self.showWinAction) self.tray_menu.addSeparator() self.tray_menu.addAction(self.notifAction) self.tray_menu.addSeparator() exitAction = self.tray_menu.addAction( QIcon.fromTheme("application-exit"), "Beenden") exitAction.triggered.connect(self.exitApp) self.trayIcon.setContextMenu(self.tray_menu) def showMain(self): if self.isVisible() == False: self.showWinAction.setText("Hauptfenster verbergen") self.setVisible(True) elif self.isVisible() == True: self.showWinAction.setText("Hauptfenster anzeigen") self.setVisible(False) def showMainfromTray(self): buttons = qApp.mouseButtons() if buttons == Qt.LeftButton: if self.isVisible() == False: self.showWinAction.setText("Hauptfenster verbergen") self.setVisible(True) elif self.isVisible() == True: self.showWinAction.setText("Hauptfenster anzeigen") self.setVisible(False) def toggleNotif(self): if self.notifAction.text() == "Tray Meldungen ausschalten": self.notifAction.setText("Tray Meldungen einschalten") self.notificationsEnabled = False elif self.notifAction.text() == "Tray Meldungen einschalten": self.notifAction.setText("Tray Meldungen ausschalten") self.notificationsEnabled = True print(f"Notifications {self.notificationsEnabled}") self.metaDataChanged() def openTrayStation(self): action = self.sender() if action: ind = action.data() name = action.text() self.urlCombo.setCurrentIndex(self.urlCombo.findText(name)) print(f"swith to Station: {ind} - {self.urlCombo.currentText()}") def exitApp(self): self.close() QApplication.quit() def message(self, message): QMessageBox.information(None, 'Meldung', message) def closeEvent(self, e): self.writeSettings() print("schreibe Konfiguratinsdatei ...\nbis bald, keep on rocking...") QApplication.quit() def readSettings(self): print("lese Konfiguratinsdatei ...") if self.settings.contains("pos"): pos = self.settings.value("pos", QPoint(200, 200)) self.move(pos) else: self.move(0, 26) if self.settings.contains("lastChannel"): lch = self.settings.value("lastChannel") self.urlCombo.setCurrentIndex(self.urlCombo.findText(lch)) if self.settings.contains("notifications"): self.notificationsEnabled = self.settings.value("notifications") if self.settings.value("notifications") == "false": self.notificationsEnabled = False self.notifAction.setText("Tray Meldungen einschalten") else: self.notifAction.setText("Tray Meldungen ausschalten") self.notificationsEnabled = True if self.settings.contains("windowstate"): print(self.settings.value("windowstate")) if self.settings.value("windowstate") == "Hauptfenster anzeigen": self.show() self.showWinAction.setText("Hauptfenster verbergen") else: self.hide() self.showWinAction.setText("Hauptfenster anzeigen") if self.settings.contains("volume"): vol = self.settings.value("volume") print(f"set volume to {vol}") self.level_sld.setValue(int(vol)) def writeSettings(self): self.settings.setValue("pos", self.pos()) self.settings.setValue("index", self.urlCombo.currentIndex()) self.settings.setValue("lastChannel", self.urlCombo.currentText()) self.settings.setValue("notifications", self.notificationsEnabled) if self.isVisible(): self.settings.setValue("windowstate", "Hauptfenster anzeigen") else: self.settings.setValue("windowstate", "Hauptfenster verbergen") self.settings.setValue("volume", self.level_sld.value()) self.settings.sync() def readStations(self): self.urlCombo.clear() self.radiolist = [] self.channels = [] self.imagelist = [] dir = os.path.dirname(sys.argv[0]) self.radiofile = os.path.join(dir, "bob.txt") with open(self.radiofile, 'r') as f: self.radioStations = f.read() f.close() newlist = [list(x) for x in self.radioStations.splitlines()] for lines in self.radioStations.splitlines(): mLine = lines.split(",") if not mLine[0].startswith("--"): self.urlCombo.addItem(self.tIcon, mLine[0], Qt.UserRole - 1) self.radiolist.append(mLine[1]) def findExecutable(self): wget = QStandardPaths.findExecutable("wget") if wget != "": print(f"found wget at {wget} *** recording available") self.statusLabel.setText("Aufnahmen möglich") self.showTrayMessage("Hinweis", "wget gefunden\nAufnahmen möglich", self.tIcon) self.recording_enabled = True else: self.showTrayMessage( "Hinweis", "wget icht gefunden\nkeine Aufnahmen möglich", self.tIcon) print("wget icht gefunden\nkeine Aufnahmen möglich") self.recording_enabled = False def remove_last_line_from_string(self, s): return s[:s.rfind('\n')] def createStatusBar(self): self.statusLabel = QLabel("Info") self.statusLabel.setWordWrap(True) self.statusLabel.setAlignment(Qt.AlignCenter) #self.statusLabel.setStyleSheet("color:#73d216;") self.statusBar = QStatusBar() self.statusBar.setSizeGripEnabled(False) self.setStatusBar(self.statusBar) self.statusLabel.setText("Willkommen bei Radio BOB") self.statusBar.addWidget(self.statusLabel, 1) pixmap = QIcon(self.headerlogo) self.home_label = QPushButton() self.home_label.setIconSize(QSize(52, 26)) self.home_label.setFixedSize(60, 32) self.home_label.setToolTip("Radio BOB Homepage besuchen") self.home_label.setIcon(self.headerlogo) self.home_label.clicked.connect(self.showHomepage) self.statusBar.addPermanentWidget(self.home_label) def showHomepage(self): url = QUrl('https://radiobob.de') QDesktopServices.openUrl(url) def metaDataChanged(self): if self.player.isMetaDataAvailable(): trackInfo = (self.player.metaData("Title")) if trackInfo is None: self.statusLabel.setText( f"playing {self.urlCombo.currentText()}") new_trackInfo = "" new_trackInfo = str(trackInfo) #print(new_trackInfo) if not new_trackInfo == "None" and " - " in new_trackInfo: self.statusLabel.setText( f"{new_trackInfo.split(' - ')[0]}\n{new_trackInfo.split(' - ')[1]}" ) else: self.statusLabel.setText( f" playing {self.urlCombo.currentText()}") mt = new_trackInfo if not mt == "None" and " - " in mt: if self.notificationsEnabled: if not mt == self.old_meta: print(mt) self.showTrayMessage( "Radio BOB", f"{mt.split(' - ')[0]}\n{mt.split(' - ')[1]}", self.tIcon) self.old_meta = mt self.trayIcon.setToolTip(mt) else: self.trayIcon.setToolTip(mt) self.old_meta = mt else: self.statusLabel.setText(f"playing {self.urlCombo}") def url_changed(self): if self.urlCombo.currentIndex() < self.urlCombo.count() - 1: if not self.urlCombo.currentText().startswith("--"): ind = self.urlCombo.currentIndex() url = self.radiolist[ind] self.current_station = url self.player.stop() self.rec_btn.setVisible(True) self.stop_btn.setVisible(True) self.play_btn.setVisible(True) name = self.urlCombo.currentText() print(f"playing {name} from {url}") self.playRadioStation() if self.togglePlayerAction.text() == "Wiedergabe stoppen": self.togglePlayerAction.setText("Wiedergabe starten") self.togglePlayerAction.setIcon( QIcon.fromTheme("media-playback-start")) else: self.togglePlayerAction.setText("Wiedergabe stoppen") self.togglePlayerAction.setIcon( QIcon.fromTheme("media-playback-stop")) else: self.rec_btn.setVisible(False) self.stop_btn.setVisible(False) self.play_btn.setVisible(False) def playRadioStation(self): if self.player.is_on_pause: self.set_running_player() self.player.start() self.stop_btn.setFocus() self.togglePlayerAction.setText("Aufnahme stoppen") self.togglePlayerAction.setIcon( QIcon.fromTheme("media-playback-stop")) if not self.current_station: return self.player.set_media(self.current_station) self.set_running_player() self.player.start() if self.is_recording: self.recordAction.setText(f"stoppe Aufnahme von {self.rec_name}") self.recordAction.setIcon(QIcon.fromTheme("media-playback-stop")) else: self.recordAction.setText( f"starte Aufnahme von {self.urlCombo.currentText()}") self.recordAction.setIcon(QIcon.fromTheme("media-record")) self.statusLabel.setText(f"playing {self.urlCombo.currentText()}") self.setWindowTitle(self.urlCombo.currentText()) def set_running_player(self): self.play_btn.setEnabled(False) self.stop_btn.setEnabled(True) self.rec_btn.setEnabled(True) def stop_preview(self): self.player.finish() self.play_btn.setEnabled(True) self.stop_btn.setEnabled(False) self.rec_btn.setEnabled(False) self.statusLabel.setText("stopped") self.togglePlayerAction.setText("Wiedergabe starten") self.togglePlayerAction.setIcon( QIcon.fromTheme("media-playback-start")) def set_sound_level(self, level): self.player.set_sound_level(level) self.level_lbl.setText("Lautstärke " + str(level)) self.player.setVolume(level) def update_volume_slider(self, level): self.level_lbl.setText("Lautstärke " + str(level)) self.level_sld.blockSignals(True) self.level_sld.setValue(value) self.level_lbl.setText("Lautstärke " + str(level)) self.level_sld.blockSignals(False) def recordRadio(self): if not self.is_recording: self.deleteOutFile() self.rec_url = self.current_station self.rec_name = self.urlCombo.currentText() cmd = ("wget -q " + self.rec_url + " -O " + self.outfile) print(cmd) self.is_recording = True self.process.startDetached(cmd) self.recordAction.setText(f"stoppe Aufnahme von {self.rec_name}") self.recordAction.setIcon(QIcon.fromTheme("media-playback-stop")) self.rec_btn.setVisible(False) self.stoprec_btn.setVisible(True) else: self.stop_recording() def stop_recording(self): if self.is_recording: self.process.close() print("stoppe Aufnahme") self.is_recording = False QProcess.execute("killall wget") self.saveRecord() self.stoprec_btn.setVisible(False) self.rec_btn.setVisible(True) self.recordAction.setText( f"starte Aufnahme von {self.urlCombo.currentText()}") self.recordAction.setIcon(QIcon.fromTheme("media-record")) else: self.showTrayMessage("Hinweis", "keine Aufnahme gestartet", self.tIcon) def saveRecord(self): if not self.is_recording: print("saving Audio") musicfolder = QStandardPaths.standardLocations( QStandardPaths.MusicLocation)[0] recname = self.rec_name.replace("-", " ").replace(" - ", " ") + ".mp3" infile = QFile(self.outfile) savefile, _ = QFileDialog.getSaveFileName( None, "Speichern als...", f'{musicfolder}/{recname}', "Audio (*.mp3)") if (savefile != ""): if QFile(savefile).exists: QFile(savefile).remove() print(f"saving {savefile}") if not infile.copy(savefile): QMessageBox.warning( self, "Fehler", f"File {savefile} {infile.errorString()}") print(f"Prozess-State: {str(self.process.state())}") if QFile(self.outfile).exists: print(f"{self.outfile} existiert") QFile(self.outfile).remove() def deleteOutFile(self): if QFile(self.outfile).exists: print(f"delete file {self.outfile}") if QFile(self.outfile).remove: print(f"{self.outfile} deleted") else: print(f"{self.outfile} not deleted") def getPID(self): print(f"{self.process.pid()} {self.process.processId()}")
class SearchFilm(QMainWindow, Ui_MainWindow): def __init__(self): super(SearchFilm, self).__init__() self.setupUi(self) self.setWindowTitle(u'找电影') self.setFixedSize(991, 700) # 窗口居中显示 # desktop = QtWidgets.QApplication.desktop() # x = (desktop.width() - self.width()) // 2 # y = (desktop.height() - self.height()) // 2 # self.move(x, y) # self.buttonBack.setStyleSheet("QPushButton{border-image: url(img/back_16px.png)}") self.buttonBack.setIcon(QIcon('img/back_16px.png')) # self.buttonDownload.setStyleSheet("QPushButton{border-image: url(img/download_16px.png)}") self.buttonDownload.setIcon(QIcon('img/download_16px.png')) # self.buttonZoomOut.setStyleSheet("QPushButton{border-image: url(img/zoom_out_16px.png)}") self.buttonZoomOut.setIcon(QIcon('img/zoom_out_16px.png')) # self.buttonZoomIn.setStyleSheet("QPushButton{border-image: url(img/zoom_in_16px.png)}") self.buttonZoomIn.setIcon(QIcon('img/zoom_in_16px.png')) self.settingsMenu = self.menuBar().addMenu(u'设置') self.helpMenu = self.menuBar().addMenu(u'帮助') self.statusbar = QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.lableNetStatus = QLabel() self.lableNetStatus.setText(u"网络状态: ") self.statusbar.addWidget(self.lableNetStatus) self.permanent = QLabel() self.permanent.setText("<a href=\"http://www.415.net\">bt之家</a>") self.permanent.setOpenExternalLinks(True) # 设置可以打开网站链接 self.statusbar.addPermanentWidget(self.permanent) self.checkNetwork() self.buttonSearchMain.clicked.connect(self.search) self.buttonSearch.clicked.connect(self.getSearchResult) self.listWidget.itemClicked.connect(self.itemClicked) self.buttonBack.clicked.connect(self.backToIndex1) self.buttonOpenUrl.clicked.connect(self.openUrl) self.buttonZoomIn.clicked.connect(self.zoom_in_func) self.buttonZoomOut.clicked.connect(self.zoom_out_func) self.buttonDownload.clicked.connect(self.downloadBT) def showDialog(self): self.dialog = QDialog() self.dialog.setWindowFlags(Qt.FramelessWindowHint) # 无边框 # 设置显示位置在主窗口中央,大小100*100 rect = self.frameGeometry() x = rect.x() + rect.width() // 2 - 50 y = rect.y() + rect.height() // 2 - 50 self.dialog.setGeometry(x, y, 100, 100) #dialog.setAttribute(Qt.WA_TranslucentBackground) label = QLabel(self.dialog) #label.setText("pic") gif = QMovie('img/loading.gif') label.setMovie(gif) gif.start() # 设置窗口的属性为ApplicationModal模态,用户只有关闭弹窗后,才能关闭主界面 self.dialog.setWindowModality(Qt.ApplicationModal) self.dialog.exec_() def search(self): filmName = self.lineEditFilmNameMain.text() if filmName == '': QMessageBox.information(self, u'提示', u'请在搜索框内填写电影名', QMessageBox.Yes) else: self.stackedWidgetMain.setCurrentIndex(1) self.lineEditFilmName.setText(filmName) self.searchFilmThread = SearchFilmThread(filmName) self.searchFilmThread._signal.connect(self.addItems) self.searchFilmThread.start() self.showDialog() def getSearchResult(self): filmName = self.lineEditFilmName.text() if filmName == '': QMessageBox.information(self, u'提示', u'请在搜索框内填写电影名', QMessageBox.Yes) else: self.listWidget.clear() self.stackedWidget.setCurrentIndex(0) self.searchFilmThread = SearchFilmThread(filmName) self.searchFilmThread._signal.connect(self.addItems) self.searchFilmThread.start() self.showDialog() def itemClicked(self, item): # 清理之前显示的内容 info = "<!DOCTYPE html>\n<html>\n</head>\n</html>\n" self.browser.setHtml(info) self.browser.clearFocus() self.stackedWidget.setCurrentIndex(1) url = self.searchResult[item.text()] self.getFilmInfoThread = GetFilmInfoThread(url) self.getFilmInfoThread._signal.connect(self.showFilmInfo) self.getFilmInfoThread.start() self.showDialog() def backToIndex1(self): self.stackedWidget.setCurrentIndex(0) # 清理之前显示的内容 info = "<!DOCTYPE html>\n<html>\n</head>\n</html>\n" self.browser.setHtml(info) self.browser.clearFocus() def addItems(self, filmList): self.listWidget.clear() self.searchResult = filmList for film in filmList: self.listWidget.addItem(''.join(film)) self.dialog.close() def showFilmInfo(self, info): self.browser.setHtml(info[0]) self.browser.setZoomFactor(0.7) self.fileName = info[1] self.labelFileName.setText(self.fileName) self.downloadUrl = info[2] self.dialog.close() def openUrl(self): webbrowser.open_new_tab("www.415.net") def zoom_in_func(self): self.browser.setZoomFactor(self.browser.zoomFactor() + 0.1) def zoom_out_func(self): self.browser.setZoomFactor(self.browser.zoomFactor() - 0.1) def downloadBT(self): self.downloadThread = DownloadThread(self.fileName, self.downloadUrl) self.downloadThread._signal.connect(self.updateDownloadStatus) self.downloadThread.start() def updateDownloadStatus(self, status): if status: QMessageBox.information(self, u'下载提示', u'下载完成', QMessageBox.Yes) else: QMessageBox.information(self, u'下载提示', u'下载失败!', QMessageBox.Yes) def checkNetwork(self): self.checkNetworkThread = CheckNetworkThread() self.checkNetworkThread._signal.connect(self.updateNetStatus) self.checkNetworkThread.start() def updateNetStatus(self, status): if status: self.lableNetStatus.setText(u"网络状态: 已连接") else: self.lableNetStatus.setText(u"网络状态: 已断开") def closeEvent(self, event): """ 对MainWindow的函数closeEvent进行重构 退出软件时结束所有进程 """ reply = QMessageBox.question(self, u'关闭提示', "是否要退出程序?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() os._exit(0) else: event.ignore()
class mainWindow(QMainWindow): def __init__(self,obj): super().__init__() self.setObjectName('Window1') self.obj=obj self.set=0 self.initUI() def initUI(self): self.resize(850,500) self.setWindowTitle('Moodly 1.0 Beta - Configure') self.setWindowIcon(QIcon(':/Assets/moodly.gif')) self.setFixedSize(830,500) self.center() self.sysTray=QWidget() self.tray = SystemTrayIcon(QIcon(':/Assets/moodly.gif'),self.sysTray) self.tray.show() self.tray.trigger.connect(self.showApp) self.tray.qtrigger.connect(self.closeApp) self.tray.uptrigger.connect(self.updateNow) self.setWidget() self.show() def setWidget(self): if self.obj.configured==0: self.setCentralWidget(configureWidget(self)) elif self.obj.configured==1: self.setCentralWidget(setupWidget(self)) elif self.obj.configured==2: self.setStyleSheet('''#Window1{background-color: light gray;}''') self.setWindowTitle('Moodly 1.0 Beta') self.setMenuBar() self.tabWidget = tabWidget(self) self.setCentralWidget(self.tabWidget) self.tray.updateAction.setEnabled(True) self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.statusBar.hide() self.statusLbl1 = QLabel() self.statusLbl2 = QLabel() self.statusLbl2.setAlignment(QtCore.Qt.AlignRight) self.statusBar.addWidget(self.statusLbl1) self.statusBar.addWidget(self.statusLbl2,QtCore.Qt.AlignRight) self.updateTimer() self.notifTimer() self.i_thread = {} self.nt=0 def showApp(self): if self.isMinimized(): self.showNormal() self.show() self.activateWindow() def closeApp(self): self.tray.hide() qApp.quit() def showStatus(self,msg,id_): if id_ == 0: self.statusLbl1.setText(msg) else: self.statusLbl2.setText(msg) self.statusBar.show() def hideStatus(self,id_): if id_==0: self.statusLbl1.setText('') else: self.statusLbl2.setText('') if self.statusLbl1.text() == '' and self.statusLbl2.text()=='': self.statusBar.hide() def updateTimer(self): self.current_timer = QTimer() delay = int(re.findall(r'\d+', self.obj.upIntval)[0]) delay = delay*60*60*1000 self.current_timer.timeout.connect(self.updater) self.current_timer.setSingleShot(True) if self.set==0: self.updater() else: self.current_timer.start(delay) def notifTimer(self): if self.obj.nIntval=="Turn Off": self.notifier = False else: delay = int(re.findall(r'\d+', self.obj.nIntval)[0])*60*60 self.timer1 = QTimer() self.timer1.timeout.connect(partial(self.quickNotify)) self.timer1.setSingleShot(True) self.timer1.start(10*60*1000) self.notifier= True def quickNotify(self): if self.obj.n !=0 and self.obj.updating==False: str_ = str(self.obj.n) self.tray.display_notify("Moodly","You have %s unread notifications"%str_,1) self.notifTimer() def quickStatus(self,i): if self.obj.updating==False: if i==0: self.showStatus('Next Update Scheduled at %s'%str(self.obj.scheduled)) self.timer2 = QTimer() self.timer2.timeout.connect(partial(self.quickStatus,1)) self.timer2.setSingleShot(True) self.timer2.start(6000) elif i==1: delay = int(re.findall(r'\d+', self.obj.upIntval)[0])*60*60 self.showStatus('Last Update Scheduled at %s'%str(self.obj.scheduled-datetime.timedelta(0,delay))+'Failed') self.timer2 = QTimer() self.timer2.timeout.connect(partial(self.quickStatus,2)) self.timer2.setSingleShot(True) self.timer2.start(6000) else: self.showStatus('Last Successful Update ') self.timer2 = QTimer() self.timer2.timeout.connect(self.hideStatus) self.timer2.setSingleShot(True) self.timer2.start(6000) self.statusTimer() def updater(self): self.obj.updating = True self.showStatus('Updating Moodly.....',0) self.thread=updateThread(self.obj) self.thread.finished.connect(self.downloader) self.thread.start() def downloader(self): if int(self.obj.dwnld)==1: self.showStatus('Downloading Files.....',0) self.dthread=downloadThread(self.obj) self.dthread.finished.connect(self.tabUpdater) self.dthread.start() else: self.tabUpdater() def closeEvent(self, event): self.hide() event.ignore() self.tray.display_notify('Moodly','Moodly running in notification tray.',1) def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def setMenuBar(self): exitAction = QAction(QIcon(':/Assets/close.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.triggered.connect(self.closeApp) self.alreadyOpen = 0 configAction = QAction(QIcon(':/Assets/setting.png'), '&Configure', self) configAction.triggered.connect(self.changeConfig) configAction.setShortcut('Ctrl+Shift+C') updateAction = QAction(QIcon(':/Assets/sync.png'), '&Update Now', self) updateAction.triggered.connect(self.updateNow) updateAction.setShortcut('Ctrl+U') menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(configAction) fileMenu.addAction(updateAction) fileMenu.addAction(exitAction) def updateNow(self): if self.obj.updating==False: self.current_timer.stop() self.current_timer.deleteLater() self.updater() else: reply = QMessageBox.information(self,'Moodly',"An update is already in progress. ", QMessageBox.Ok) if reply == QMessageBox.Ok: pass def changeConfig(self): if self.alreadyOpen is 0: self.tab = reConfigureWidget(self.tabWidget) self.tabWidget.addTab(self.tab,QIcon(':/Assets/setting.png'),'Configure') self.tabWidget.setTabToolTip(self.tabWidget.indexOf(self.tab),'Configure') self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(self.tab)) self.alreadyOpen=1 else: self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(self.tab)) def verify(self): self.obj.saveConfig(1) self.thread=WorkThread(self.obj) self.thread.finished.connect(self.notify) self.thread.start() self.set=1 self.setWidget() def notify(self): self.setWidget() self.tray.display_notify("Moodly",self.obj.status_msg[0],self.obj.status_msg[1]) def tabUpdater(self): self.set=1 self.tabWidget.tab1.updater() self.tabWidget.tab2.updater() for tab in self.tabWidget.tab: tab.updater() self.obj.updating = False self.c_timer = QTimer() self.c_timer.timeout.connect(partial(self.hideStatus,0)) self.c_timer.setSingleShot(True) self.showStatus('Update Completed',0) self.c_timer.start(5000) self.tray.display_notify("Moodly",self.obj.status_msg[0],self.obj.status_msg[1]) self.updateTimer() def itemsWriter(self,fileName,id1,id2): nt=self.getIndex() self.i_thread[nt] = itemsWriterThread(fileName,id1,id2,nt,self.obj) self.i_thread[nt].finished.connect(partial(self.del_i_thread,self.i_thread[nt].id3)) self.i_thread[nt].start() def del_i_thread(self,id3): self.i_thread[id3]=0 def getIndex(self): if self.nt==0: return self.nt else: for i in range(0,self.nt): if self.i_thread[i]==0: return i self.nt+=1 return self.nt def configWriter(self,text1,text2,combo1,combo2,text3,path_): self.sid3=self.showStatus('Configuring...',1) self.c_thread = configWriterThread(self.obj,text1,text2,combo1,combo2,text3,path_) self.c_thread.finished.connect(self.reConfigModify) self.c_thread.start() def reConfigModify(self): if self.alreadyOpen==1: self.tab.status_label.setText(self.obj.config_status) self.tray.display_notify("Moodly",self.obj.status_msg[0],self.obj.status_msg[1]) self.re_timer = QTimer() self.re_timer.timeout.connect(partial(self.hideStatus,1)) self.re_timer.setSingleShot(True) self.showStatus(self.obj.config_status,1) self.re_timer.start(5000) self.tabWidget.updating = False if self.obj.intValChanged ==0: self.current_timer.stop() self.current_timer.deleteLater() self.updateTimer() self.obj.intValChanged = -1 elif self.obj.intValChanged ==1: if self.notifier == True: self.timer1.stop() self.timer1.deleteLater() self.notifTimer() self.obj.intValChanged = -1 elif self.obj.intValChanged ==2: self.current_timer.stop() self.current_timer.deleteLater() self.updateTimer() if self.notifier == True: self.timer1.stop() self.timer1.deleteLater() self.notifTimer() self.obj.intValChanged = -1
class BatchTrackingDialog(QDialog): """Dialog for batch processing videos.""" def __init__(self, root_folder, parent=None): super(BatchTrackingDialog, self).__init__(parent) self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) self.setWindowTitle('Batch Processing Wizard') app_icon = QIcon(QPixmap(os.path.join(DIR, '..', 'icons', 'logo.png'))) self.setWindowIcon(app_icon) self.step_number = 0 self.video_settings = [] self.root_folder = root_folder self.layout = QGridLayout() # move all steps into a stacked layout. # this allows each layout to be shown individually, # while providing a container for all layouts. self.widgets = QStackedWidget() file_widget = StackedStepWidget(0, BatchFileSelector(self.root_folder, 0)) arena_widget = StackedStepWidget(1, BatchArenaSpecifier(1)) try: arena_widget.settings_widget.background_frame_ix.connect( self.update_progress_bar) except RuntimeError: print('Error while trying to connect the arena widget' + 'to the update_progress_bar fxn.') female_widget = StackedStepWidget(2, BatchFemaleSpecifier(2)) tight_threshold_widget = StackedStepWidget( 3, BatchTightThresholdSpecifier(3)) tight_threshold_widget.settings_widget.image_calc_progress.connect( self.update_progress_bar) loose_threshold_widget = StackedStepWidget( 4, BatchLooseThresholdSpecifier(4)) loose_threshold_widget.settings_widget.image_calc_progress.connect( self.update_progress_bar) tracking_widget = StackedStepWidget(5, BatchTrackingWidget(5)) tracking_widget.settings_widget.tracking_progress.connect( self.update_progress_bar) self.widgets.addWidget(file_widget) self.widgets.addWidget(arena_widget) self.widgets.addWidget(female_widget) self.widgets.addWidget(tight_threshold_widget) self.widgets.addWidget(loose_threshold_widget) self.widgets.addWidget(tracking_widget) # connect all widget signals to this class's update_settings # function. self.connect_widget_signals() self.layout.addWidget(self.widgets, 0, 0, 6, 6) # setup the next and previous buttons self.next_button = QPushButton('Next') self.next_button.setEnabled(False) previous_button = QPushButton('Previous') self.next_button.clicked.connect(self.step_forward) previous_button.clicked.connect(self.step_backward) self.layout.addWidget(previous_button, 6, 0, 1, 1) self.layout.addWidget(self.next_button, 6, 5, 1, 1) # setup the status bar interface self.set_status() self.layout.addWidget(self.status, 7, 0, 1, 6) self.setLayout(self.layout) self.resize(1000, 600) def connect_widget_signals(self): """Connects all widgets in the StackedLayout to self.update_settings.""" for i in xrange(self.widgets.count() + 1): # this call returns 0 if widget at index is not present. if self.widgets.widget(i): self.widgets.widget( i).settings_widget.all_settings_valid.connect( self.update_settings) def set_status(self): """Sets interface for status bar at bottom of dialog window.""" self.status = QStatusBar() self.status.setSizeGripEnabled(True) self.process_label = QLabel('Process') self.process_label.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.progress_bar = QProgressBar() self.status.addWidget(self.process_label) self.status.addPermanentWidget(self.progress_bar) def _step(self): """Updates layout currently being displayed in StackedLayout.""" self.widgets.setCurrentIndex(self.step_number) if self.widgets.currentWidget().settings_widget.check_settings_valid(): self.next_button.setEnabled(True) def step_forward(self): """Moves the StackedLayout forward by one index.""" if self.step_number < self.widgets.count() - 1: self.step_number += 1 self._step() def step_backward(self): """Moves the StackedLayout backward by one index.""" if self.step_number > 0: self.step_number -= 1 self._step() @pyqtSlot(bool, int, list) def update_settings(self, is_set, widget_ix, settings_list): """This function updates all of the video settings. It is a slot for the BatchSettingsWidget.all_settings_valid signal, and not only sets the video_settings of this class (TrackingDialog), but updates all of the settings in each of the widgets in the StackedLayout. """ if is_set: self.next_button.setEnabled(True) self.video_settings = settings_list for i in xrange(self.widgets.count() + 1): if self.widgets.widget(i): self.widgets.widget(i).settings_widget.update_settings( settings_list) else: self.next_button.setEnabled(False) @pyqtSlot(int, str) def update_progress_bar(self, progress, description): """Updates the progress bar based on actions happening in widgets within the StackedLayout.""" self.process_label.setText('Process -- {}'.format(description)) self.progress_bar.setValue(progress)
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 500) icon = QIcon() icon.addPixmap(QPixmap("favicon.png"), QIcon.Normal, QIcon.Off) MainWindow.setWindowIcon(icon) self.centralwidget = QWidget(MainWindow) self.statusbar = QStatusBar(MainWindow) self.statusBarText = QLabel() self.statusBarText.setAlignment(QtCore.Qt.AlignRight) self.statusbar.addWidget(self.statusBarText, 1) MainWindow.setStatusBar(self.statusbar) self.textEdit = QTextEdit(self.centralwidget) self.textEdit.setGeometry(QRect(190, 0, 611, 501)) self.gridLayoutWidget = QWidget(self.centralwidget) self.gridLayoutWidget.setGeometry(QRect(10, 10, 171, 151)) self.gridLayout = QGridLayout(self.gridLayoutWidget) self.gridLayout.setContentsMargins(0, 0, 0, 0) self.radioButton_3 = QRadioButton(self.gridLayoutWidget) self.radioButton = QRadioButton(self.gridLayoutWidget) self.radioButton_2 = QRadioButton(self.gridLayoutWidget) self.radioButton_2.setChecked(True) self.radioButtonGroup = QButtonGroup() self.radioButtonGroup.addButton(self.radioButton) self.radioButtonGroup.addButton(self.radioButton_2) self.radioButtonGroup.addButton(self.radioButton_3) self.radioButton.toggled.connect( lambda e, textEdit=self.textEdit, button=self. radioButton, statusBar=self.statusBarText: setFontType( textEdit, button, statusBar)) self.radioButton_2.toggled.connect( lambda e, textEdit=self.textEdit, button=self. radioButton_2, statusBar=self.statusBarText: setFontType( textEdit, button, statusBar)) self.radioButton_3.toggled.connect( lambda e, textEdit=self.textEdit, button=self. radioButton_3, statusBar=self.statusBarText: setFontType( textEdit, button, statusBar)) self.gridLayout.addWidget(self.radioButton_2, 3, 0, 1, 1) self.gridLayout.addWidget(self.radioButton, 2, 0, 1, 1) self.gridLayout.addWidget(self.radioButton_3, 1, 0, 1, 1) self.comboBox = QComboBox(self.gridLayoutWidget) self.fontSizeList = [ '8', '9', '10', '11', '12', '14', '16', '18', '20', '22', '24', '26', '28', '36', '48', '72' ] self.comboBox.addItems(self.fontSizeList) self.comboBox.setCurrentIndex(4) self.comboBox.currentTextChanged.connect( lambda fontSize, textEdit=self.textEdit, statusBar=self. statusBarText: setFontSize(textEdit, fontSize, statusBar)) self.textEdit.setFont(QFont('Times New Roman', 12)) self.gridLayout.addWidget(self.comboBox, 0, 0, 1, 1) self.gridLayoutWidget_2 = QWidget(self.centralwidget) self.gridLayoutWidget_2.setGeometry(QRect(9, 200, 171, 135)) self.gridLayoutWidget_2.setFixedWidth(171) self.gridLayoutWidget_2.setFixedHeight(135) self.gridLayout_2 = QGridLayout(self.gridLayoutWidget_2) self.gridLayout_2.setContentsMargins(0, 0, 0, 0) self.pushButtonGroup = QButtonGroup() self.pushButton_3 = QPushButton(self.gridLayoutWidget_2) self.pushButton_3.setStyleSheet( "QPushButton {\n" " background-color: rgb(255, 241, 60);\n" "}") self.pushButton_3.setText("") self.pushButton_3.setCheckable(True) self.pushButton_3.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_3, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_3) self.gridLayout_2.addWidget(self.pushButton_3, 2, 0, 1, 1) self.pushButton_16 = QPushButton(self.gridLayoutWidget_2) self.pushButton_16.setStyleSheet( "QPushButton {\n" " background-color: rgb(107, 144, 186);\n" "}") self.pushButton_16.setText("") self.pushButton_16.setCheckable(True) self.pushButton_16.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_16, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_16) self.gridLayout_2.addWidget(self.pushButton_16, 3, 3, 1, 1) self.pushButton_2 = QPushButton(self.gridLayoutWidget_2) self.pushButton_2.setStyleSheet( "QPushButton {\n" " background-color: rgb(255, 255, 255);\n" "}") self.pushButton_2.setText("") self.pushButton_2.setCheckable(True) self.pushButton_2.setChecked(True) self.pushButton_2.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_2, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_2) self.gridLayout_2.addWidget(self.pushButton_2, 1, 0, 1, 1) self.pushButton_6 = QPushButton(self.gridLayoutWidget_2) self.pushButton_6.setStyleSheet( "QPushButton {\n" " background-color: rgb(126, 126, 126);\n" "}") self.pushButton_6.setText("") self.pushButton_6.setCheckable(True) self.pushButton_6.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_6, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_6) self.gridLayout_2.addWidget(self.pushButton_6, 0, 1, 1, 1) self.pushButton_10 = QPushButton(self.gridLayoutWidget_2) self.pushButton_10.setStyleSheet( "QPushButton {\n" " background-color: rgb(188, 121, 90);\n" "}") self.pushButton_10.setText("") self.pushButton_10.setCheckable(True) self.pushButton_10.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_10, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_10) self.gridLayout_2.addWidget(self.pushButton_10, 1, 2, 1, 1) self.pushButton = QPushButton(self.gridLayoutWidget_2) self.pushButton.setStyleSheet("QPushButton {\n" " background-color: black;\n" "}") self.pushButton.setText("") self.pushButton.setCheckable(True) self.pushButton.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton) self.gridLayout_2.addWidget(self.pushButton, 0, 0, 1, 1) self.pushButton_7 = QPushButton(self.gridLayoutWidget_2) self.pushButton_7.setStyleSheet( "QPushButton {\n" " background-color: rgb(0, 175, 82);\n" "}") self.pushButton_7.setText("") self.pushButton_7.setCheckable(True) self.pushButton_7.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_7, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_7) self.gridLayout_2.addWidget(self.pushButton_7, 2, 1, 1, 1) self.pushButton_11 = QPushButton(self.gridLayoutWidget_2) self.pushButton_11.setStyleSheet( "QPushButton {\n" " background-color: rgb(0, 160, 228);\n" "}") self.pushButton_11.setText("") self.pushButton_11.setCheckable(True) self.pushButton_11.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_11, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_11) self.gridLayout_2.addWidget(self.pushButton_11, 2, 2, 1, 1) self.pushButton_4 = QPushButton(self.gridLayoutWidget_2) self.pushButton_4.setStyleSheet( "QPushButton {\n" " background-color: rgb(239, 227, 177);\n" "}") self.pushButton_4.setText("") self.pushButton_4.setCheckable(True) self.pushButton_4.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_4, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_4) self.gridLayout_2.addWidget(self.pushButton_4, 3, 0, 1, 1) self.pushButton_12 = QPushButton(self.gridLayoutWidget_2) self.pushButton_12.setStyleSheet( "QPushButton {\n" " background-color: rgb(143, 215, 232);\n" "}") self.pushButton_12.setText("") self.pushButton_12.setCheckable(True) self.pushButton_12.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_12, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_12) self.gridLayout_2.addWidget(self.pushButton_12, 3, 2, 1, 1) self.pushButton_14 = QPushButton(self.gridLayoutWidget_2) self.pushButton_14.setStyleSheet( "QPushButton {\n" " background-color: rgb(255, 172, 199);\n" "}") self.pushButton_14.setText("") self.pushButton_14.setCheckable(True) self.pushButton_14.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_14, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_14) self.gridLayout_2.addWidget(self.pushButton_14, 1, 3, 1, 1) self.pushButton_15 = QPushButton(self.gridLayoutWidget_2) self.pushButton_15.setStyleSheet( "QPushButton {\n" " background-color: rgb(63, 72, 198);\n" "}") self.pushButton_15.setText("") self.pushButton_15.setCheckable(True) self.pushButton_15.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_15, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_15) self.gridLayout_2.addWidget(self.pushButton_15, 2, 3, 1, 1) self.pushButton_5 = QPushButton(self.gridLayoutWidget_2) self.pushButton_5.setStyleSheet( "QPushButton {\n" " background-color: rgb(193, 193, 193);\n" "}") self.pushButton_5.setText("") self.pushButton_5.setCheckable(True) self.pushButton_5.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_5, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_5) self.gridLayout_2.addWidget(self.pushButton_5, 1, 1, 1, 1) self.pushButton_9 = QPushButton(self.gridLayoutWidget_2) self.pushButton_9.setStyleSheet( "QPushButton {\n" " background-color: rgb(140, 9, 31);\n" "}") self.pushButton_9.setText("") self.pushButton_9.setCheckable(True) self.pushButton_9.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_9, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_9) self.gridLayout_2.addWidget(self.pushButton_9, 0, 2, 1, 1) self.pushButton_8 = QPushButton(self.gridLayoutWidget_2) self.pushButton_8.setStyleSheet( "QPushButton {\n" " background-color: rgb(174, 229, 61);\n" "}") self.pushButton_8.setText("") self.pushButton_8.setCheckable(True) self.pushButton_8.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_8, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_8) self.gridLayout_2.addWidget(self.pushButton_8, 3, 1, 1, 1) self.pushButton_17 = QPushButton(self.gridLayoutWidget_2) self.pushButton_17.setStyleSheet( "QPushButton {\n" " background-color: rgb(255, 126, 58);\n" "}") self.pushButton_17.setText("") self.pushButton_17.setCheckable(True) self.pushButton_17.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_17, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_17) self.gridLayout_2.addWidget(self.pushButton_17, 0, 4, 1, 1) self.pushButton_18 = QPushButton(self.gridLayoutWidget_2) self.pushButton_18.setStyleSheet( "QPushButton {\n" " background-color: rgb(255, 200, 56);\n" "}") self.pushButton_18.setText("") self.pushButton_18.setCheckable(True) self.pushButton_18.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_18, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_18) self.gridLayout_2.addWidget(self.pushButton_18, 1, 4, 1, 1) self.pushButton_19 = QPushButton(self.gridLayoutWidget_2) self.pushButton_19.setStyleSheet( "QPushButton {\n" " background-color: rgb(166, 74, 160);\n" "}") self.pushButton_19.setText("") self.pushButton_19.setCheckable(True) self.pushButton_19.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_19, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_19) self.gridLayout_2.addWidget(self.pushButton_19, 2, 4, 1, 1) self.pushButton_20 = QPushButton(self.gridLayoutWidget_2) self.pushButton_20.setStyleSheet( "QPushButton {\n" " background-color: rgb(199, 189, 228);\n" "}") self.pushButton_20.setText("") self.pushButton_20.setCheckable(True) self.pushButton_20.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_20, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_20) self.gridLayout_2.addWidget(self.pushButton_20, 3, 4, 1, 1) self.pushButton_13 = QPushButton(self.gridLayoutWidget_2) self.pushButton_13.setStyleSheet( "QPushButton {\n" " background-color: rgb(246, 36, 49);\n" "}") self.pushButton_13.setText("") self.pushButton_13.setCheckable(True) self.pushButton_13.toggled.connect( lambda e, textEdit=self.textEdit, button=self.pushButton_13, statusBar=self.statusBarText: setBackgroundColor( textEdit, button, statusBar)) self.pushButtonGroup.addButton(self.pushButton_13) self.gridLayout_2.addWidget(self.pushButton_13, 0, 3, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setGeometry(QRect(0, 0, 800, 26)) self.menuPlik = QMenu(self.menubar) self.menuEdycj = QMenu(self.menubar) MainWindow.setMenuBar(self.menubar) self.toolBar = QToolBar(MainWindow) self.toolBar.setMovable(False) MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.actionNowy = QAction(MainWindow) self.actionNowy.triggered.connect( lambda: handleNewFile(self.textEdit, self.statusBarText)) self.actionOtworz = QAction(MainWindow) self.actionOtworz.triggered.connect( lambda: handleOpenFile(self.textEdit, self.statusBarText)) self.actionZapisz = QAction(MainWindow) self.actionZapisz.triggered.connect( lambda: handleSaveFile(self.textEdit, self.statusBarText)) self.actionZapisz_jako = QAction(MainWindow) self.actionZapisz_jako.triggered.connect( lambda: handleSaveFileAs(self.textEdit, self.statusBarText)) self.actionZakoncz = QAction(MainWindow) self.actionZakoncz.triggered.connect(lambda: sys.exit()) self.actionWytnij = QAction(MainWindow) self.actionWytnij.triggered.connect( lambda: handleCut(self.textEdit, self.statusBarText)) self.actionKopiuj = QAction(MainWindow) self.actionKopiuj.triggered.connect( lambda: handleCopy(self.textEdit, self.statusBarText)) self.actionWklej = QAction(MainWindow) self.actionWklej.triggered.connect( lambda: handlePaste(self.textEdit, self.statusBarText)) self.actionZazancz_wszystko = QAction(MainWindow) self.actionZazancz_wszystko.triggered.connect( lambda: handleSelectAll(self.textEdit, self.statusBarText)) self.actionNew_File = QAction(MainWindow) icon1 = QIcon() icon1.addPixmap(QPixmap("file.png"), QIcon.Normal, QIcon.Off) self.actionNew_File.setIcon(icon1) self.actionNew_File.triggered.connect( lambda: handleNewFile(self.textEdit, self.statusBarText)) self.actionOpen_File = QAction(MainWindow) self.actionOpen_File.triggered.connect( lambda: handleOpenFile(self.textEdit, self.statusBarText)) icon2 = QIcon() icon2.addPixmap(QPixmap("browse.png"), QIcon.Normal, QIcon.Off) self.actionOpen_File.setIcon(icon2) self.actionSave_File = QAction(MainWindow) icon3 = QIcon() icon3.addPixmap(QPixmap("save.png"), QIcon.Normal, QIcon.Off) self.actionSave_File.setIcon(icon3) self.actionSave_File.triggered.connect( lambda: handleSaveFile(self.textEdit, self.statusBarText)) self.actionUndo = QAction(MainWindow) self.actionUndo.triggered.connect( lambda: handleUndo(self.textEdit, self.statusBarText)) icon4 = QIcon() icon4.addPixmap(QPixmap("undo.png"), QIcon.Normal, QIcon.Off) self.actionUndo.setIcon(icon4) self.actionRedo = QAction(MainWindow) icon5 = QIcon() icon5.addPixmap(QPixmap("redo.png"), QIcon.Normal, QIcon.Off) self.actionRedo.setIcon(icon5) self.actionRedo.triggered.connect( lambda: handleRedo(self.textEdit, self.statusBarText)) self.actionCut = QAction(MainWindow) icon6 = QIcon() icon6.addPixmap(QPixmap("cut.png"), QIcon.Normal, QIcon.Off) self.actionCut.setIcon(icon6) self.actionCut.triggered.connect( lambda: handleCut(self.textEdit, self.statusBarText)) self.actionCopy = QAction(MainWindow) icon7 = QIcon() icon7.addPixmap(QPixmap("copy.png"), QIcon.Normal, QIcon.Off) self.actionCopy.setIcon(icon7) self.actionCopy.triggered.connect( lambda: handleCopy(self.textEdit, self.statusBarText)) self.actionPaste = QAction(MainWindow) self.actionPaste.triggered.connect( lambda: handlePaste(self.textEdit, self.statusBarText)) icon8 = QIcon() icon8.addPixmap(QPixmap("paste.png"), QIcon.Normal, QIcon.Off) self.actionPaste.setIcon(icon8) self.menuPlik.addAction(self.actionNowy) self.menuPlik.addAction(self.actionOtworz) self.menuPlik.addAction(self.actionZapisz) self.menuPlik.addAction(self.actionZapisz_jako) self.menuPlik.addAction(self.actionZakoncz) self.menuEdycj.addAction(self.actionWytnij) self.menuEdycj.addAction(self.actionKopiuj) self.menuEdycj.addAction(self.actionWklej) self.menuEdycj.addAction(self.actionZazancz_wszystko) self.menubar.addAction(self.menuPlik.menuAction()) self.menubar.addAction(self.menuEdycj.menuAction()) self.toolBar.addAction(self.actionNew_File) self.toolBar.addAction(self.actionOpen_File) self.toolBar.addAction(self.actionSave_File) self.toolBar.addSeparator() self.toolBar.addAction(self.actionUndo) self.toolBar.addAction(self.actionRedo) self.toolBar.addSeparator() self.toolBar.addAction(self.actionCut) self.toolBar.addAction(self.actionCopy) self.toolBar.addAction(self.actionPaste) self.leftPaneWidget = QWidget() self.vBox = QVBoxLayout() self.vBox.addWidget(self.comboBox) self.vBox.addWidget(self.radioButton) self.vBox.addWidget(self.radioButton_2) self.vBox.addWidget(self.radioButton_3) self.vBox.addWidget(self.gridLayoutWidget_2) self.leftPaneWidget.setLayout(self.vBox) self.hBox = QHBoxLayout() self.hBox.addWidget(self.leftPaneWidget) self.hBox.addWidget(self.textEdit) self.centralwidget.setLayout(self.hBox) self.setObjectTitles(MainWindow) QMetaObject.connectSlotsByName(MainWindow) def setObjectTitles(self, MainWindow): MainWindow.setWindowTitle("Notatnik") self.radioButton_3.setText("Courier New") self.radioButton.setText("Arial") self.radioButton_2.setText("Times New Roman") self.menuPlik.setTitle("Plik") self.menuEdycj.setTitle("Edycja") self.toolBar.setWindowTitle("toolBar") self.actionNowy.setText("Nowy") self.actionNowy.setShortcut("Ctrl+N") self.actionOtworz.setText("Otwórz") self.actionOtworz.setShortcut("Ctrl+O") self.actionZapisz.setText("Zapisz") self.actionZapisz.setShortcut("Ctrl+S") self.actionZapisz_jako.setText("Zapisz jako") self.actionZapisz_jako.setShortcut("Ctrl+Shift+S") self.actionZakoncz.setText("Zakończ") self.actionWytnij.setText("Wytnij") self.actionWytnij.setShortcut("Ctrl+X") self.actionKopiuj.setText("Kopiuj") self.actionKopiuj.setShortcut("Ctrl+C") self.actionWklej.setText("Wklej") self.actionWklej.setShortcut("Ctrl+V") self.actionZazancz_wszystko.setText("Zaznacz wszystko") self.actionZazancz_wszystko.setShortcut("Ctrl+A") self.actionNew_File.setText("New File") self.actionNew_File.setToolTip("New File") self.actionNew_File.setShortcut("Ctrl+N") self.actionOpen_File.setText("Open File") self.actionOpen_File.setToolTip("Open File") self.actionOpen_File.setShortcut("Ctrl+O") self.actionSave_File.setText("Save File") self.actionSave_File.setToolTip("Save File") self.actionSave_File.setShortcut("Ctrl+S") self.actionUndo.setText("Undo") self.actionUndo.setToolTip("Undo Action") self.actionUndo.setShortcut("Ctrl+Z") self.actionRedo.setText("Redo") self.actionRedo.setToolTip("Redo Action") self.actionRedo.setShortcut("Ctrl+Shift+Z") self.actionCut.setText("Cut") self.actionCut.setToolTip("Cut Selection") self.actionCut.setShortcut("Ctrl+X") self.actionCopy.setText("Copy") self.actionCopy.setToolTip("Copy Selection") self.actionCopy.setShortcut("Ctrl+C") self.actionPaste.setText("Paste") self.actionPaste.setToolTip("Paste Text") self.actionPaste.setShortcut("Ctrl+V")
class Main(QMainWindow): def __init__(self, app, palette, editor, parent=None): super().__init__(parent) self.editor = editor # Current config chosen (can be one of 3 config<N>.json) self.onStart(choiceIndex) # Initializing config options self.status = QStatusBar( self ) # Status bar for displaying useful info like update found etc # Initializing the main widget where text is displayed self.tab = Tabs(self.cleanOpen, app, palette, self) # self.tabsOpen = [] self.pic_opened = False # This is used to open pictures but right now that feature is disabled self.dialog = MessageBox( self ) # Handles dialogs, for now it only creates the create new project dialog self.setWindowIcon(QIcon("resources/Python-logo-notext.svg_.png") ) # Setting the window icon self.setWindowTitle("Hydra") # Setting the window title self.status_font = QFont( editor["statusBarFont"], editor["statusBarFontSize"]) # Status bar font self.os = platform.system() self.tab.tabs.currentChanged.connect( self.fileNameChange ) # To change the title of the window when tab changes self.search = DocumentSearch( ) # To find documents in the whole system, also not quite working today # Initializing QActions that can be triggered from a QMenu or via keyboard shortcuts self.openterm() self.openterminal() # self.split2Tabs() self.new() self.newProject() self.findDocument() self.openProjectF() self.open() self.save() self.saveAs() self.exit() self.thread = UpdateThread( ) # Update checking runs on its own thread to prevent main GUI from blocking self.thread.start() # Data retrieved from the update thread gets processed check_updates self.thread.textSignal.connect(self.check_updates) # Attributes to manage opening directories and such self.dir_opened = False self._dir = None self.update_progress = QProgressBar() self.update_progress.setMaximumWidth(225) self.update_progress.setStyleSheet(self.update_progress.styleSheet()) self.setCentralWidget(self.tab) # QMainWindow's central widget self.files = None # Tracking the current file that is open self.dead_code_thread = DeadCodeCheker() # This checks for dead code self.dead_code_thread.infoSignal.connect(self.write_dead_code_info) self.stack = [] # Used for tracking when to check for dead code self.tab_to_write_to = None self.tagInfo = StatusLabel(text="", font=self.status_font) self.initUI() # Main UI def write_dead_code_info(self, text): self.tab.events.info_bar.setText(text) def check_updates(self, text): """ A function to check for updates and ask the user if they want to update or not """ self.update_label = QLabel() self.update_label.setFont( QFont(self.editor["generalFont"], self.editor["generalFontSize"])) self.update_label.setFont(self.status_font) self.update_label.setText(text) self.status.addWidget(self.update_label) if text != "An update is available, would you like to update?": pass else: self.button = QPushButton("Update") self.button.setFont( QFont(self.editor["generalFont"], self.editor["generalFontSize"])) self.status.addWidget(self.button) self.button.clicked.connect(self.update_Hydra) def update_Hydra(self): """ This function gets used when the user wants to update Hydra This function is not finished so it doesn't do any updating """ self.update_label.setText("Updating...") self.status.removeWidget(self.button) self.status.addWidget(self.update_progress) for i in range(101): self.update_progress.setValue(i) QTest.qWait(random.randint(50, 75)) # make_decision(True) def fileNameChange(self): try: currentFileName = self.tab.tabs.currentWidget().baseName self.setWindowTitle("Hydra ~ " + str(currentFileName)) except AttributeError: self.setWindowTitle("Hydra ~ ") def onStart(self, index): try: editor = configs[index]["editor"] if editor["windowStaysOnTop"] is True: self.setWindowFlags(Qt.WindowStaysOnTopHint) else: pass except Exception as err: pass # log exception self.font = QFont() self.font.setFamily(self.editor["editorFont"]) self.font.setPointSize(self.editor["editorFontSize"]) self.tabSize = self.editor["TabWidth"] def initUI(self): self.setStatusBar(self.status) # Initializing the status bar self.font.setFixedPitch(True) menuFont = QFont() menuFont.setFamily(self.editor["menuFont"]) menuFont.setPointSize(self.editor["menuFontSize"]) menu = self.menuBar() menu.setFont(menuFont) # Creating the file menu fileMenu = menu.addMenu("File") # Adding options to the file menu # self.setStatusBar(self.status) fileMenu.addAction(self.newAct) fileMenu.addAction(self.newProjectAct) fileMenu.addAction(self.openAct) fileMenu.addAction(self.openProjectAct) fileMenu.addAction(self.saveAct) fileMenu.addAction(self.saveAsAct) fileMenu.addSeparator() fileMenu.addAction(self.exitAct) toolMenu = menu.addMenu("Tools") toolMenu.addAction(self.openTermAct) toolMenu.addAction(self.openTerminalAct) # toolMenu.addAction(self.split2TabsAct) searchDoc = menu.addMenu("Find document") searchDoc.addAction(self.findDocumentAct) self.showMaximized() def open(self): self.openAct = QAction("Open...", self) self.openAct.setShortcut("Ctrl+O") self.openAct.setStatusTip("Open a file") self.openAct.triggered.connect(self.openFileFromMenu) def closeEvent(self, QCloseEvent): os._exit(42) # This makes sure every thread gets killed def new(self): self.newAct = QAction("New") self.newAct.setShortcut("Ctrl+N") self.newAct.setStatusTip("Create a new file") self.newAct.triggered.connect(self.newFile) def newProject(self): self.newProjectAct = QAction("New project") self.newProjectAct.setShortcut("Ctrl+Shift+N") self.newProjectAct.setStatusTip("Create a new project") self.newProjectAct.triggered.connect(self.newProjectFolder) def openProjectF(self): self.openProjectAct = QAction("Open project") self.openProjectAct.setShortcut("Ctrl+Shift+O") self.openProjectAct.setStatusTip("Open a project") self.openProjectAct.triggered.connect(self.openProject) def split2Tabs(self): self.split2TabsAct = QAction("Split the first 2 tabs") self.split2TabsAct.setShortcut("Ctrl+Alt+S") self.split2TabsAct.setStatusTip("Splits the first 2 tabs into one tab") self.split2TabsAct.triggered.connect(self.tab.split) def switchTabs(self): if self.tab.tabs.count() - 1 == self.tab.tabs.currentIndex(): self.tab.tabs.setCurrentIndex(0) else: self.tab.tabs.setCurrentIndex(self.tab.tabs.currentIndex() + 1) def save(self): self.saveAct = QAction("Save") self.saveAct.setShortcut("Ctrl+S") self.saveAct.setStatusTip("Save a file") self.saveAct.triggered.connect(self.saveFile) def openterm(self): self.openTermAct = QAction("Run", self) self.openTermAct.setShortcut("Shift+F10") self.openTermAct.setStatusTip("Run your code") self.openTermAct.triggered.connect(self.execute_file) def openterminal(self): self.openTerminalAct = QAction("Terminal", self) self.openTerminalAct.setShortcut("Ctrl+T") self.openTerminalAct.setStatusTip("Open a terminal") self.openTerminalAct.triggered.connect(self.realterminal) def saveAs(self): self.saveAsAct = QAction("Save As...") self.saveAsAct.setShortcut("Ctrl+Shift+S") self.saveAsAct.setStatusTip("Save a file as") self.saveAsAct.triggered.connect(self.saveFileAs) def findDocument(self): self.findDocumentAct = QAction("Find document") self.findDocumentAct.setShortcut("Ctrl+Shift+F") self.findDocumentAct.setStatusTip("Find a document") self.findDocumentAct.triggered.connect(self.temp) def temp(self): pass def findDocumentFunc(self): self.search.run() def exit(self): self.exitAct = QAction("Quit", self) self.exitAct.setShortcut("Ctrl+Q") self.exitAct.setStatusTip("Exit application") self.exitAct.triggered.connect(self.lets_exit) def lets_exit(self): # self.saveFile() qApp.quit() def openFileFromMenu(self): options = QFileDialog.Options() filenames, _ = QFileDialog.getOpenFileNames( self, "Open a file", "", "All Files (*);;Python Files (*.py);;Text Files (*.txt)", options=options, ) if filenames: # If file is selected, we can open it filename = filenames[0] if filename[-3:] in ["gif", "png", "jpg", "bmp" ] or filename[-4:] in ["jpeg"]: self.pic_opened = True self.cleanOpen(filename, self.pic_opened) def openBrowser(self): widget = Browser("https://duckduckgo.com") word = "" index = self.tab.tabs.addTab(widget, "Info about: " + str(word)) self.tab.tabs.setCurrentIndex(index) def cleanOpen(self, filename, pic_opened=False, searchCommand=None): basename = os.path.basename(filename) if os.path.isdir(filename): return if pic_opened: tab = Image(filename, basename) else: tab = Content("", filename, basename, self, False, searchCommand) for index, tab_name in enumerate(self.tab.tabCounter): if ( tab_name == basename ): # If we already have a file open and we're trying to open the same file, then do nothing if searchCommand: print(searchCommand, " search ocmmand") tab.searchFor(searchCommand) return tab.start_opening() # TODO: Only works for NON image files right now label = QLabel("Loading...") label.setAlignment(Qt.AlignCenter) index_to_remove = self.tab.tabs.addTab(label, "") # lmao it works tab.readyToShow.connect( lambda state: self.addTab(state, tab, basename, index_to_remove)) update_previous_file(filename) def addTab(self, state, tab, basename, index_to_remove): """ Removes given tab and adds a new tab and makes it active """ self.tab.tabs.removeTab(index_to_remove) index = self.tab.tabs.addTab(tab, basename) self.tab.tabs.setCurrentIndex(index) self.tab.tabCounter.append(basename) # Not in use def openFile(self, filename): try: for index, tabName in enumerate(self.tab.tabCounter): with open(filename, "r+") as file_o: print("first open") if filename[-3:] in ["gif", "png", "jpg", "bmp" ] or filename[-4:] in ["jpeg"]: self.pic_opened = True else: self.pic_opened = False try: text = file_o.read() except UnicodeDecodeError as E: text = str(E) basename = os.path.basename(filename) if not self.pic_opened: tab = Content(text, filename, basename, self) tab.saved = True tab.modified = False else: tab = Image(filename, basename) if tabName == tab.baseName: self.tab.tabs.removeTab(index) self.tab.tabCounter.remove(tab.baseName) try: with open(filename, "r+") as file_o: try: if self.pic_opened is not True: text = file_o.read() else: text = None except (FileNotFoundError, UnicodeDecodeError, AttributeError) as E: text = str(E) except FileNotFoundError: with open(filename, "w+") as newFileCreated: print("third open") text = newFileCreated.read() basename = os.path.basename(filename) if self.pic_opened is True: tab = Image(filename, basename) else: tab = Content(text, filename, basename, self) # Creating a tab object *IMPORTANT* tab.saved = True tab.modified = False self.tab.tabCounter.append(tab.baseName) dirPath = os.path.dirname(filename) self.files = filename # self.tabsOpen.append(self.files) index = self.tab.tabs.addTab( tab, tab.baseName ) # This is the index which we will use to set the current self.tab.tabs.setTabToolTip(index, str(tab.fileName)) if ( not self.dir_opened ): # If a project isn't opened then we open a directory everytime we open a file self.tab.directory.openDirectory(dirPath) self.tab.showDirectory() else: pass self.tab.setLayout(self.tab.layout) # Finally we set the layout update_previous_file(filename) self.tab.tabs.setCurrentIndex( index) # Setting the index so we could find the current widget self.currentTab = self.tab.tabs.currentWidget() if self.pic_opened is not True: self.currentTab.editor.setFont(self.font) # Setting the font self.currentTab.editor.setFocus( ) # Setting focus to the tab after we open it self.pic_opened = False except ( IsADirectoryError, AttributeError, UnboundLocalError, PermissionError, ) as E: print(E, " on line 346 in the file main.py") def newFile(self): text = "" if self._dir: base_file_name = "Untitled_file_" + str(random.randint( 1, 100)) + ".py" fileName = str(self._dir) + "/" + base_file_name else: base_file_name = "Untitled_file_" + str(random.randint( 1, 100)) + ".py" current = os.getcwd() fileName = current + "/" + base_file_name self.pyFileOpened = True # Creates a new blank file file = Content(text, fileName, base_file_name, self) self.tab.splitterH.addWidget( self.tab.tabs ) # Adding tabs, now the directory tree will be on the left self.tab.tabCounter.append(file.fileName) self.tab.setLayout(self.tab.layout) # Finally we set the layout index = self.tab.tabs.addTab( file, file.baseName ) # addTab method returns an index for the tab that was added self.tab.tabs.setTabToolTip(index, str(file.fileName)) self.tab.tabs.setCurrentIndex( index) # Setting focus to the new tab that we created widget = self.tab.tabs.currentWidget() def newProjectFolder(self): self.dialog = NewProject(self) self.dialog.show() def openProject(self): self._dir = QFileDialog.getExistingDirectory(None, "Select a folder:", "", QFileDialog.ShowDirsOnly) self.tab.directory.openDirectory(self._dir) self.dir_opened = True # Generating tags file self.generateTagFile(self._dir) self.tab.showDirectory() def generateTagFile(self, directoryLocation: str) -> bool: location = shutil.which("ctags") appDir = os.getcwd() if location is None: print( "Please download universal ctags from the website https://github.com/universal-ctags/ctags" ) return False else: os.chdir(directoryLocation) generateProcess = QProcess(self) command = [location, "-R"] generateProcess.start(" ".join(command)) self.tagInfo.setText("Generating tags file...") self.status.addWidget(self.tagInfo, Qt.AlignRight) generateProcess.finished.connect( lambda: self.afterTagGeneration(appDir)) def afterTagGeneration(self, appDir: str) -> None: os.chdir(appDir) print(os.getcwd()) self.status.removeWidget(self.tagInfo) def parseTagFile(self): pass def openProjectWithPath(self, path): self.tab.directory.openDirectory(path) self.dir_opened = True self._dir = path self.tab.showDirectory() def saveFile(self): self.stack.append(1) try: active_tab = self.tab.tabs.currentWidget() if self.tab.tabs.count(): # If a file is already opened # self.save_thread.add_args(active_tab) # self.save_thread.start() active_tab.start_saving() active_tab.saved = True # active_tab.start_from = os.path.getsize(active_tab.fileName) # self.dead_code_thread.add_args(active_tab.editor.toPlainText()) # self.dead_code_thread.start() # TODO: THrow this analyzer into a code analyzer if len(self.stack) > 5: self.dead_code_thread.add_args( active_tab.editor.toPlainText()) self.dead_code_thread.start( ) # TODO: THrow this analyzer into a code analyzer self.stack = [] active_tab.modified = False """f if active_tab.fileName.endswith(".py"): active_tab.editor.updateAutoComplete(active_tab.fileName) """ else: options = QFileDialog.Options() name = QFileDialog.getSaveFileName( self, "Save File", "", "All Files (*);;Python Files (*.py);;Text Files (*.txt)", options=options, ) fileName = name[0] with open(fileName, "w+") as saveFile: active_tab.saved = True active_tab.modified = False # self.tabsOpen.append(fileName) saveFile.write(active_tab.editor.toPlainText()) self.tab.events.look_for_dead_code( active_tab.editor.toPlainText()) saveFile.close() """ if fileName.endswith(".py"): active_tab.editor.updateAutoComplete(active_tab.fileName) """ self.setWindowTitle("Hydra ~ " + str(active_tab.baseName) + " [SAVED]") active_tab.tokenize_file() except Exception as E: print(E, " on line 403 in the file main.py") def choose_python(self): return sys.executable def saveFileAs(self): try: active_tab = self.tab.tabs.currentWidget() if active_tab is not None: active_index = self.tab.tabs.currentIndex() options = QFileDialog.Options() name = QFileDialog.getSaveFileName( self, "Save File", "", "All Files (*);;Python Files (*.py);;Text Files (*.txt)", options=options, ) fileName = name[0] with open(fileName, "w+") as saveFile: active_tab.saved = True active_tab.modified = False # self.tabsOpen.append(fileName) try: baseName = os.path.basename(fileName) except AttributeError: print("All tabs closed") saveFile.write(active_tab.editor.toPlainText()) text = active_tab.editor.toPlainText() newTab = Content(str(text), fileName, baseName, self) newTab.ready = True self.tab.tabs.removeTab( active_index ) # When user changes the tab name we make sure we delete the old one index = self.tab.tabs.addTab( newTab, newTab.baseName) # And add the new one! self.tab.tabs.setTabToolTip(index, str(newTab.fileName)) self.tab.tabs.setCurrentIndex(index) newActiveTab = self.tab.tabs.currentWidget() newActiveTab.editor.setFont(self.font) newActiveTab.editor.setFocus() saveFile.close() self.setWindowTitle("Hydra ~ " + str(active_tab.baseName) + " [SAVED]") else: print("No file opened") except FileNotFoundError: print("File dialog closed") def realterminal(self): """ Checking if the file executing widget already exists in the splitter layout: If it does exist, then we're going to replace the widget with the terminal widget, if it doesn't exist then just add the terminal widget to the layout and expand the splitter. """ if self.tab.splitterV.indexOf(self.tab.Console) == 1: self.tab.splitterV.replaceWidget( self.tab.splitterV.indexOf(self.tab.Console), self.tab.terminal) self.tab.splitterV.setSizes([400, 10]) else: self.tab.showConsole() def open_documentation(self, data, word): """ Opens documentation for a built in function """ data = data.replace("|", "") index = self.tab.tabs.addTab( Content( data, os.getcwd() + "/" + str(word) + ".doc", str(word) + ".doc", self, True, ), str(word), ) self.tab.tabs.setCurrentIndex(index) def execute_file(self): """ Checking if the terminal widget already exists in the splitter layout: If it does exist, then we're going to replace it, if it doesn't then we're just gonna add our file executer to the layout, expand the splitter and run the file. Then check if the file executer already exists, but is called again to run the file again """ active_tab = self.tab.tabs.currentWidget() python_command = self.choose_python() if self.tab.splitterV.indexOf(self.tab.terminal) == 1: self.tab.splitterV.replaceWidget( self.tab.splitterV.indexOf(self.tab.terminal), self.tab.Console) self.tab.Console.run( "{} ".format(python_command) + active_tab.fileName, active_tab.fileName) self.tab.splitterV.setSizes([400, 10]) elif self.tab.splitterV.indexOf(self.tab.Console) == 1: self.tab.Console.run( "{} ".format(python_command) + active_tab.fileName, active_tab.fileName) self.tab.splitterV.setSizes([400, 10]) else: self.tab.showFileExecuter() self.tab.Console.run( "{} ".format(python_command) + active_tab.fileName, active_tab.fileName) self.tab.splitterV.setSizes([400, 10]) def jumpToDef(self, tagList: list): print(tagList) tagInfo = tagList[0] fileName = tagList[1] searchCommand = tagList[2] self.cleanOpen(fileName, False, searchCommand)
class GUI(QMainWindow): FRAME_WIDTH = 700 FRAME_HEIGHT = 600 FRAME_BORDER = 20 def __init__(self, config_man: ConfigManager, updater: Updater): super(GUI, self).__init__() self._config_man = config_man self._updater = updater self._subreddit_list = QListWidget() self._subreddit_text_field = QLineEdit() self._subreddit_add_btn = QPushButton() self._subreddit_del_btn = QPushButton() self._filter_text_field = QLineEdit() self._filter_add_btn = QPushButton() self._filter_del_btn = QPushButton() self._filt_rb_include = QRadioButton("Include") self._filt_rb_exclude = QRadioButton("Exclude") self._filter_phrase_list = QListWidget() self._sound_checkbox = CheckBox("Sound", self._sound_notify) self._popup_checkbox = CheckBox("Popup", self._popup_notify) self._notification_checkboxes = [self._sound_checkbox, self._popup_checkbox] self._update_button = QPushButton("Update") self._notification_sound = QSound(self._config_man.properties['notification_sound_path']) self._thread_list = QListWidget() self._status_bar = QStatusBar() self._last_updated_label = QLabel() self._refresh_rate_select = QComboBox() self._popup = None self._init_properties() self._init_layout() self._init_bindings() def _init_layout(self): self.setBaseSize(self.FRAME_WIDTH, self.FRAME_HEIGHT) self.setGeometry(QRect(100, 100, self.FRAME_WIDTH, self.FRAME_HEIGHT)) self._subreddit_list.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) self._subreddit_text_field.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self._subreddit_add_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self._subreddit_del_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self._filter_text_field.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self._filter_add_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self._filter_del_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self._filt_rb_include.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self._filt_rb_exclude.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self._filter_phrase_list.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) for checkbox in self._notification_checkboxes: checkbox.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self._refresh_rate_select.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self._update_button.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) subreddit_box = QHBoxLayout() subreddit_box.addWidget(self._subreddit_text_field) subreddit_box.addWidget(self._subreddit_add_btn) subreddit_box.addWidget(self._subreddit_del_btn) filter_box = QHBoxLayout() filter_box.addWidget(self._filter_text_field) filter_box.addWidget(self._filter_add_btn) filter_box.addWidget(self._filter_del_btn) refresh_rate_box = QHBoxLayout() label = QLabel("Refresh rate") label.setFixedSize(70, 20) refresh_rate_box.addWidget(label) refresh_rate_box.addWidget(self._refresh_rate_select) refresh_rate_box.addSpacing(5) label = QLabel("mins") label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) refresh_rate_box.addWidget(label) option_box = QVBoxLayout() label = QLabel("Subreddits") label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) option_box.addWidget(label) option_box.addWidget(self._subreddit_list) option_box.addItem(subreddit_box) option_box.addSpacing(self.FRAME_BORDER) label = QLabel("Filter phrases") label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) option_box.addWidget(label) option_box.addWidget(self._filter_phrase_list) option_box.addItem(filter_box) option_box.addWidget(self._filt_rb_include) option_box.addWidget(self._filt_rb_exclude) option_box.addSpacing(self.FRAME_BORDER) for checkbox in self._notification_checkboxes: option_box.addWidget(checkbox) option_box.addSpacing(self.FRAME_BORDER) option_box.addItem(refresh_rate_box) option_box.addSpacing(self.FRAME_BORDER) option_box.addWidget(self._update_button) self._thread_list.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self._thread_list.setIconSize(QSize(200, 200)) self._thread_list.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) self._subreddit_list.setSelectionMode(QAbstractItemView.ExtendedSelection) self._filter_phrase_list.setSelectionMode(QAbstractItemView.ExtendedSelection) self._thread_list.setSelectionMode(QAbstractItemView.NoSelection) hbox = QHBoxLayout() hbox.addItem(option_box) hbox.addWidget(self._thread_list) main = QWidget() main.setLayout(hbox) self.setCentralWidget(main) self.setStatusBar(self._status_bar) self._status_bar.addWidget(self._last_updated_label) def _init_bindings(self): self._updater.updater_task.update.connect(self.update_reddit_posts) self._update_button.clicked.connect(self.update_reddit_posts) self._subreddit_text_field.returnPressed.connect(self._add_subreddit) self._filter_add_btn.pressed.connect(self._add_filter_phrase) self._filter_text_field.returnPressed.connect(self._add_filter_phrase) self._filter_del_btn.pressed.connect(self._del_filter_phrase) self._subreddit_add_btn.clicked.connect(self._add_subreddit) self._subreddit_del_btn.clicked.connect(self._del_subreddit) self._sound_checkbox.stateChanged.connect(lambda state: self._config_man.set('sound_notify', state)) self._popup_checkbox.stateChanged.connect(lambda state: self._config_man.set('popup_notify', state)) self._filt_rb_include.toggled.connect(self._change_filter_mode) self._filt_rb_exclude.toggled.connect(self._change_filter_mode) self._refresh_rate_select.currentIndexChanged.connect(lambda rate: self._updater.set_refresh_rate((rate+1)*60)) def _init_properties(self): for sub in self._config_man.properties['subreddits']: self._subreddit_list.addItem(QListWidgetItem(sub.lower())) for phrase in self._config_man.properties['filter_phrases']: self._filter_phrase_list.addItem(QListWidgetItem(phrase)) if self._config_man.properties['filter_mode'] == 'exclude': self._filt_rb_exclude.setChecked(True) else: self._filt_rb_include.setChecked(True) checked = True if self._config_man.properties['sound_notify'] == 2 else False self._sound_checkbox.setChecked(checked) checked = True if self._config_man.properties['popup_notify'] == 2 else False self._popup_checkbox.setChecked(checked) self._last_updated_label.setText("last updated: " + time.strftime("%d/%m/%y %I:%M%p", time.localtime(self._config_man.properties['last_updated']))) self._subreddit_add_btn.setIcon(QIcon("../resources/add_button.png")) self._subreddit_del_btn.setIcon(QIcon("../resources/del_button.png")) self._filter_add_btn.setIcon(QIcon("../resources/add_button.png")) self._filter_del_btn.setIcon(QIcon("../resources/del_button.png")) for i in range(1, 61): self._refresh_rate_select.addItem(str(i)) self._refresh_rate_select.setCurrentText(str(self._config_man.properties['refresh_rate']//60)) def update_reddit_posts(self): try: new_threads = self._updater.update() for thread in new_threads: item = ThreadItem(thread) self._thread_list.addItem(item.stub) self._thread_list.setItemWidget(item.stub, item.delegate) self._thread_list.scrollToBottom() if len(new_threads) != 0: for checkbox in self._notification_checkboxes: checkbox.execute_if_checked() self._last_updated_label.setText("last updated: " + time.strftime("%d/%m/%y %I:%M%p", time.localtime())) except UpdaterException: pass def _add_subreddit(self): entry = self._subreddit_text_field.text().lower().replace(" ", "") if not self._config_man.properties['subreddits'].__contains__(entry) and entry != "": self._subreddit_list.addItem(QListWidgetItem(entry)) self._config_man.properties['subreddits'].append(entry) self._subreddit_text_field.clear() def _add_filter_phrase(self): entry = self._filter_text_field.text().lower() if not self._config_man.properties['filter_phrases'].__contains__(entry) and entry != "": self._filter_phrase_list.addItem(QListWidgetItem(entry)) self._config_man.properties['filter_phrases'].append(entry) self._filter_text_field.clear() def _del_subreddit(self): items = self._subreddit_list.selectedItems() for item in items: row = self._subreddit_list.row(item) self._subreddit_list.takeItem(row) try: self._config_man.properties['subreddits'].remove(item.text()) except ValueError: pass def _del_filter_phrase(self): items = self._filter_phrase_list.selectedItems() for item in items: row = self._filter_phrase_list.row(item) self._filter_phrase_list.takeItem(row) try: self._config_man.properties['filter_phrases'].remove(item.text()) except ValueError: pass def closeEvent(self, a0): self._config_man.save() def _sound_notify(self): if self._config_man.properties['notification_sound_path'] == "": winsound.MessageBeep() else: self._notification_sound.play() def _popup_notify(self): self._popup = QMessageBox(QMessageBox.NoIcon, "Reddit Monitor", "") self._popup.show() self._popup.setWindowState(self._popup.windowState() & ~Qt.WindowMinimized | Qt.WindowActive) self._popup.activateWindow() def _change_filter_mode(self): if self._filt_rb_exclude.isChecked(): self._config_man.set('filter_mode', 'exclude') else: self._config_man.set('filter_mode', 'include')