class MyApp(QMainWindow): def __init__(self): super().__init__() self._initUI() def _initUI(self): self.setContentsMargins(10, 10, 10, 10) self.statusBar = QStatusBar(self) self.setStatusBar(self.statusBar) self.statusBar.showMessage("5초뒤 없어짐", 5000) group_box = QGroupBox('상태바') btn1 = QPushButton('상태바 보이기', self) btn2 = QPushButton('상태바 감추기', self) btn3 = QPushButton('상태바 텍스트 가져오기', self) btn4 = QPushButton('상태바 텍스트 변경하기', self) btn1.clicked.connect(self.onMyStatusBarShow) btn2.clicked.connect(self.onMyStatusBarHide) btn3.clicked.connect(self.onMyStatusBarGetText) btn4.clicked.connect(self.onMyStatusBarChangeText) v_box = QVBoxLayout() v_box.addWidget(btn1) v_box.addWidget(btn2) v_box.addWidget(btn3) v_box.addWidget(btn4) group_box.setLayout(v_box) self.setCentralWidget(group_box) self.setWindowTitle('Status Bar') self.setGeometry(300, 300, 300, 200) self.show() def onMyStatusBarShow(self): self.statusBar.showMessage('Ready') def onMyStatusBarHide(self): self.statusBar.clearMessage() def onMyStatusBarGetText(self): getMessage = self.statusBar.currentMessage() print(getMessage) def onMyStatusBarChangeText(self): self.statusBar.showMessage("change")
class LibraryApp(QMainWindow): def __init__(self, parent=None): super(LibraryApp, self).__init__(parent, flags=Qt.Window) self.authorization_service = None self.setWindowTitle('Library app') self.setCentralWidget(QStackedWidget()) self.centralWidget().addWidget(LoginWidget(self)) self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) desktop = QDesktopWidget() screen_center = desktop.screenGeometry().center() self.adjust_geometry(screen_center) def request_login(self, username, password): self.status_bar.clearMessage() self.status_bar.showMessage('Logging in') self.centralWidget().widget(0).blockSignals(True) self.authorization_service = AuthorizationService(self) self.authorization_service.login(username, password) @pyqtSlot(str) def login(self, user_type): self.centralWidget().widget(0).clear() if len(user_type) == 0: self.centralWidget().widget(0).blockSignals(False) self.centralWidget().widget(0).clear() self.status_bar.showMessage('Invalid username or password') return center = self.geometry().center() if user_type == 'A': self.centralWidget().addWidget(AdminWidget(self)) else: self.centralWidget().addWidget(UserWidget(self)) self.centralWidget().setCurrentIndex(1) self.adjust_geometry(center) self.status_bar.clearMessage() def request_logout(self): self.status_bar.showMessage('Logging out') self.authorization_service.logout() @pyqtSlot() def logout(self): center = self.geometry().center() self.centralWidget().widget(0).blockSignals(False) self.centralWidget().removeWidget(self.centralWidget().widget(1)) self.adjust_geometry(center) self.authorization_service = None self.status_bar.clearMessage() def adjust_geometry(self, center): self.adjustSize() width = self.geometry().width() height = self.geometry().height() geometry = QRect(center.x() - width / 2, center.y() - height / 2, width, height) self.setGeometry(geometry)
class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__() self.setWindowTitle('Sign PDF GUI') self.author = kwargs['author'] self.version = kwargs['version'] self.cliApp = kwargs['cliApp'] self.title = 'Sign PDF GUI' cliAppBasename = os.path.splitext(self.cliApp)[0] scriptDir = os.path.dirname(os.path.realpath(__file__)) iconPath = os.path.sep.join([scriptDir, 'icon', cliAppBasename]) self.setWindowIcon(QIcon(iconPath)) self.listPdf = [] # List of pdfs self.listImage = [] # List of images if 'pdflist' in kwargs.keys() and len(kwargs['pdflist']) > 0: n = len(kwargs['pdflist']) for i in range(0, n): self.listPdf.append(os.path.realpath(kwargs['pdflist'][i])) self.left = 10 self.top = 10 self.width = 700 self.height = 480 self.setGeometry(self.left, self.top, self.width, self.height) self.btnWidth = 100 self.btnHeight = 30 self.selectAllWidth = 70 widget = QWidget() self.setCentralWidget(widget) self.vbox = QVBoxLayout() widget.setLayout(self.vbox) multiple = False threshold = 0.9 mask = "254,255,254,255,254,255" self.otherConfigs = { 'multiple': multiple, 'threshold': threshold, 'mask': mask } self.createPdfBox() self.createPdfTable() self.createImageBox() self.createImageTable() self.createButtonBox() self.createStatusBar() self.updatePdfTable() def createPdfBox(self): hbox = QHBoxLayout() self.vbox.addLayout(hbox) self.vbox.setAlignment(Qt.AlignTop) addPdfBtn = QPushButton("Add PDF", self) addPdfBtn.setFixedSize(self.btnWidth, self.btnHeight) addPdfBtn.clicked.connect(self.addPdfFiles) hbox.addWidget(addPdfBtn) delPdfBtn = QPushButton("Remove PDF", self) delPdfBtn.setFixedSize(self.btnWidth, self.btnHeight) delPdfBtn.clicked.connect(self.delPdfFiles) hbox.addWidget(delPdfBtn) hbox.addStretch(1) self.showGrid = QCheckBox("Show grid") self.showGrid.stateChanged.connect(self.showGridState) hbox.addWidget(self.showGrid) self.printCmd = QCheckBox("Print cmd") self.printCmd.stateChanged.connect(self.printCmdState) hbox.addWidget(self.printCmd) otherBtn = QPushButton("Others") otherBtn.setFixedSize(self.btnWidth, self.btnHeight) otherBtn.clicked.connect(self.otherBtn_clicked) hbox.addWidget(otherBtn) def createPdfTable(self): npdf = len(self.listPdf) self.pdfTable = QTableWidget() self.pdfTable.setRowCount(npdf) self.pdfTable.setColumnCount(2) self.pdfTable.setHorizontalHeaderLabels( "Select All;PDF Filename".split(";")) header = self.pdfTable.horizontalHeader() header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch) header.resizeSection(0, self.selectAllWidth) self.vbox.setAlignment(Qt.AlignTop) # self.pdfTable.setMaximumHeight(self.tableMaxHeight) self.vbox.addWidget(self.pdfTable) # If header is clicked self.selectAllPdf = False header.sectionClicked.connect(self.onPdfTableHeaderClicked) def onPdfTableHeaderClicked(self, logicalIndex): n = len(self.listPdf) if logicalIndex == 0: # If the first row is clicked if not self.selectAllPdf: # If self.selectAllPdf is False self.selectAllPdf = True for r in range(0, n): self.pdfTable.cellWidget(r, 0).findChild(type( QCheckBox())).setChecked(True) else: self.selectAllPdf = False for r in range(0, n): self.pdfTable.cellWidget(r, 0).findChild(type( QCheckBox())).setChecked(False) def createImageBox(self): hbox = QHBoxLayout() self.vbox.addLayout(hbox) addImageBtn = QPushButton("Add Image") addImageBtn.setFixedSize(self.btnWidth, self.btnHeight) addImageBtn.clicked.connect(lambda x: self.addEditImage(False)) hbox.addWidget(addImageBtn) delImageBtn = QPushButton("Remove Image") delImageBtn.setFixedSize(self.btnWidth, self.btnHeight) delImageBtn.clicked.connect(self.delImageFiles) hbox.addWidget(delImageBtn) hbox.addStretch(1) def delImageFiles(self): # Clear the status message self.statusBar.clearMessage() self.selectAllImage = False n = len(self.listImage) for r in range(0, n): if self.imageTable.cellWidget(r, 0).findChild(type( QCheckBox())).isChecked(): # Remove the element from the list del self.listImage[r] # Insert blank in the list so that the number of # elements remain the same. self.listImage.insert(r, "") # Remove the blanks that had been inserted while ("" in self.listImage): self.listImage.remove("") # Update the table self.updateImageTable() return def createImageTable(self): n = len(self.listImage) self.imageTable = QTableWidget() self.imageTable.setRowCount(n) self.imageTable.setColumnCount(9) self.imageTable.setHorizontalHeaderLabels( "Select All;Edit;Image;Template;XValue;YValue;Scale;Page;Rotation". split(";")) header = self.imageTable.horizontalHeader() # header.setSectionResizeMode(1,QtWidgets.QHeaderView.Stretch) header.resizeSection(0, self.selectAllWidth) header.resizeSection(1, 46) self.vbox.setAlignment(Qt.AlignTop) # self.imageTable.setMaximumHeight(self.tableMaxHeight) self.vbox.addWidget(self.imageTable) # If header is clicked self.selectAllImage = False header.sectionClicked.connect(self.onImageTableHeaderClicked) self.imageTable.itemChanged.connect(self.itemChangedText) return # If cell value have changed, then update them on the dictionary def itemChangedText(self, item): row = item.row() col = item.column() # Get the 'key' = column header key = self.imageTable.horizontalHeaderItem(col).text().lower() # Get the 'value' = cell value from the table value = str(self.imageTable.item(row, col).text()) # Update the dictionary self.listImage[row].update_info(key, value) return # If image header has been clicked def onImageTableHeaderClicked(self, logicalIndex): n = len(self.listImage) if logicalIndex == 0: # If the first row is clicked if not self.selectAllImage: # If self.selectAllImage is False self.selectAllImage = True for r in range(0, n): self.imageTable.cellWidget(r, 0).findChild( type(QCheckBox())).setChecked(True) else: self.selectAllImage = False for r in range(0, n): self.imageTable.cellWidget(r, 0).findChild( type(QCheckBox())).setChecked(False) def updateImageTable(self): n = len(self.listImage) # Block the signals so that any editing doesn't call any signal self.imageTable.blockSignals(True) # Clears the table self.imageTable.setRowCount(0) # Create an empty list of 'Edit' buttons self.editImageBtn = [] for row in range(0, n): # Insert a new row self.imageTable.insertRow(row) # Insert a checkbox in the first column (col = 0) qw = QWidget() self.checkbox = QCheckBox() self.checkbox.setCheckState(Qt.Unchecked) tabhlayout = QHBoxLayout(qw) tabhlayout.addWidget(self.checkbox) tabhlayout.setAlignment(Qt.AlignCenter) tabhlayout.setContentsMargins(0, 0, 0, 0) self.imageTable.setCellWidget(row, 0, qw) # Insert a checkbox in the second column (col = 1) # Append to the list of 'Edit' buttons self.editImageBtn.append(QPushButton('Edit')) self.editImageBtn[row].setStyleSheet('margin:3px') self.imageTable.setCellWidget(row, 1, self.editImageBtn[row]) self.editImageBtn[row].clicked.connect( lambda x: self.addEditImage(True)) for col in range(2, 9): # Get the column header in lowercase colheader = self.imageTable.horizontalHeaderItem( col).text().lower() if colheader == 'image' or colheader == 'template': # If the column header is 'image' or 'template', then # get the file basename and also make the cells read-only itemString = os.path.basename( str(self.listImage[row].info[colheader])) item = QTableWidgetItem(itemString) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) else: # Just get the value from the dictionary itemString = str(self.listImage[row].info[colheader]) item = QTableWidgetItem(itemString) # Align and insert the value in the cell item.setTextAlignment(Qt.AlignCenter) self.imageTable.setItem(row, col, item) self.imageTable.blockSignals(False) # Add or edit the image info def addEditImage(self, editBool): # Clear the status message self.statusBar.clearMessage() dlg = ImageOptionsDialog(self) # If edit then if editBool: # Get the row number 'r' buttonClicked = self.sender() index = self.imageTable.indexAt(buttonClicked.pos()) r = index.row() # Get the r-th row dictionary imageInfo = self.listImage[r].get_dict() # Insert the image info in the dialog dlg.editInfoDialog(imageInfo) if dlg.exec_() == ImageOptionsDialog.Accepted: data = dlg.get_output() if editBool: # If edit, the replace the original content with # the new content self.listImage[r] = data['image'] self.listImage[r] = ImageOptions(data) else: # If not editing old info, then add it to the end self.listImage.append(data['image']) k = len(self.listImage) self.listImage[k - 1] = ImageOptions(data) # Update the image table self.updateImageTable() return def createButtonBox(self): hbox = QHBoxLayout() self.vbox.addLayout(hbox) aboutBtn = QPushButton("About") aboutBtn.setFixedSize(self.btnWidth, self.btnHeight) aboutBtn.clicked.connect(self.aboutBtn_clicked) hbox.addWidget(aboutBtn, alignment=Qt.AlignLeft) self.helpBtn = QPushButton("Help") self.helpBtn.setFixedSize(self.btnWidth, self.btnHeight) self.helpBtn.clicked.connect(self.helpBtn_clicked) hbox.addWidget(self.helpBtn) hbox.addStretch(1) self.applyBtn = QPushButton("Apply") self.applyBtn.setFixedSize(self.btnWidth, self.btnHeight) self.applyBtn.clicked.connect(self.applyBtn_clicked) hbox.addWidget(self.applyBtn) quitBtn = QPushButton("Quit") quitBtn.setFixedSize(self.btnWidth, self.btnHeight) quitBtn.clicked.connect(self.close) hbox.addWidget(quitBtn) return def aboutBtn_clicked(self): # Clear the status message self.statusBar.clearMessage() infoMsg = ('Version: ' + self.version + '\n' + 'Author: ' + self.author) dlg = MessageDialog(title=self.title + ': About', text='Sign PDF GUI', informativeText=infoMsg, icon=QStyle.SP_MessageBoxInformation) dlg.setMinimumWidth(300) dlg.exec_() return def helpBtn_clicked(self): cmd = self.cliApp + ' --help' self.proc = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE) stdout, stderr = self.proc.communicate() rtn = self.proc.returncode if rtn != 0: print("Problem getting help text.") return rtn msg = self.cliApp + ' --help' detailedMsg = stdout.decode("utf-8") dlg = MessageDialog( title=self.title + ': Help', icon=QStyle.SP_MessageBoxInformation, text=msg, detailedText=detailedMsg, ) dlg.setMinimumSize(550, 400) dlg.exec_() return def applyBtn_clicked(self): n = len(self.listPdf) if n == 0: dlg = MessageDialog(title=self.title + ': Error', text='Warning: No pdf file supplied.', icon=QStyle.SP_MessageBoxCritical) dlg.exec_() return self.pd = ProgressDialog() self.pd.setMinimum(0) self.pd.setMaximum(n) self.pd.setFormat("%v/%m") self.work = Worker(self) self.thread = Thread(target=self.work.run) self.thread.start() if self.pd.exec_() == ProgressDialog.Rejected: self.work.terminate() def createStatusBar(self): self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) return def addPdfFiles(self): # Clear the status message self.statusBar.clearMessage() options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog files, _ = (QFileDialog.getOpenFileNames( self, "QFileDialog.getOpenFileNames()", "", "PDF Files (*.pdf)", options=options)) if files: self.listPdf.extend(files) self.updatePdfTable() def updatePdfTable(self): n = len(self.listPdf) self.pdfTable.setRowCount(0) # Clear the table for r in range(0, n): self.pdfTable.insertRow(r) qw = QWidget() self.checkbox = QCheckBox() self.checkbox.setCheckState(Qt.Unchecked) tabhlayout = QHBoxLayout(qw) tabhlayout.addWidget(self.checkbox) tabhlayout.setAlignment(Qt.AlignCenter) tabhlayout.setContentsMargins(0, 0, 0, 0) self.pdfTable.setCellWidget(r, 0, qw) item = QTableWidgetItem(self.listPdf[r]) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) self.pdfTable.setItem(r, 1, item) def showGridState(self): self.statusBar.clearMessage() return def printCmdState(self): self.statusBar.clearMessage() return def delPdfFiles(self): # Clear the status message self.statusBar.clearMessage() self.selectAllPdf = False n = len(self.listPdf) for r in range(0, n): if self.pdfTable.cellWidget(r, 0).findChild(type( QCheckBox())).isChecked(): # Remove the element from the list del self.listPdf[r] # Insert blank in the list so that the number of # elements remain the same. self.listPdf.insert(r, "") # Remove the blanks that had been inserted while ("" in self.listPdf): self.listPdf.remove("") # Update the table self.updatePdfTable() return def otherBtn_clicked(self): dlg = OtherDialog(self.otherConfigs) if dlg.exec_() == OtherDialog.Accepted: self.otherConfigs = dlg.get_output() return
class PlottingWidget(QtWidgets.QMainWindow): def __init__(self): super().__init__() # super(PrettyWidget, self).__init__() self.initUI() def initUI(self): self.setGeometry(600, 300, 1000, 600) self.center() self.setWindowTitle("Plot Trajectory") mainMenu = self.menuBar() fileMenu = mainMenu.addMenu("File") saveAction = QAction("Save as...") saveAction.setShortcut("Ctrl+S") saveAction.setStatusTip("Save plot to file") saveAction.setMenuRole(QAction.NoRole) saveAction.triggered.connect(self.file_save) fileMenu.addAction(saveAction) exitAction = QAction("&Exit", self) exitAction.setShortcut("Ctrl+Q") exitAction.setStatusTip("Exit Application") exitAction.setMenuRole(QAction.NoRole) exitAction.triggered.connect(self.close) fileMenu.addAction(exitAction) settingsMenu = mainMenu.addMenu("Settings") self.setStyleMenu = QMenu("Set Style", self) settingsMenu.addMenu(self.setStyleMenu) for style_name in [ "default", "fast", "ggplot", "grayscale", "seaborn" ]: styleAction = QAction(style_name, self, checkable=True) if style_name is CUR_STYLE: styleAction.setChecked(True) styleAction.triggered.connect(partial(self.set_style, style_name)) self.setStyleMenu.addAction(styleAction) self.setTimeWindowMenu = QMenu("Set Time Window", self) settingsMenu.addMenu(self.setTimeWindowMenu) for window_str in ["None", "s", "30s", "H", "D"]: windowAction = QAction(window_str, self, checkable=True) if window_str is TIME_WINDOW: windowAction.setChecked(True) windowAction.triggered.connect( partial(self.set_time_window, window_str)) self.setTimeWindowMenu.addAction(windowAction) # Grid Layout grid = QtWidgets.QGridLayout() widget = QtWidgets.QWidget(self) self.setCentralWidget(widget) widget.setLayout(grid) # Import CSV Button btn1 = QtWidgets.QPushButton("Import CSV", self) btn1.resize(btn1.sizeHint()) btn1.clicked.connect(self.getCSV) grid.addWidget(btn1, 1, 0) # Canvas and Toolbar self.figure = plt.figure(figsize=(15, 5)) self.canvas = FigureCanvas(self.figure) self.canvas.setContextMenuPolicy(Qt.CustomContextMenu) self.canvas.customContextMenuRequested.connect(self.popup) grid.addWidget(self.canvas, 2, 0, 1, 2) # DropDown mean / comboBox self.df = pd.DataFrame() self.columns = [] self.plot_list = [] self.comboBox = QtWidgets.QComboBox(self) self.comboBox.addItems(self.columns) grid.addWidget(self.comboBox, 0, 0) self.comboBox2 = QtWidgets.QComboBox(self) self.comboBox2.addItems(self.plot_list) grid.addWidget(self.comboBox2, 0, 1) # Plot Button btn2 = QtWidgets.QPushButton("Plot", self) btn2.resize(btn2.sizeHint()) btn2.clicked.connect(self.plot) grid.addWidget(btn2, 1, 1) # Progress bar self.progress = QProgressBar(self) # self.progress.setRange(0, 1) grid.addWidget(self.progress, 3, 0, 1, 2) self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.show() def set_style(self, style_name: str): global CUR_STYLE self.statusBar.showMessage(f"Style set to {style_name}") actions = self.setStyleMenu.actions() CUR_STYLE = style_name for action in actions: if action.text() == CUR_STYLE: # print(f"✓ {CUR_STYLE}") action.setChecked(True) else: action.setChecked(False) print(f"Style set to {CUR_STYLE}") def popup(self, pos): menu = QMenu() saveAction = menu.addAction("Save...") action = menu.exec_(self.canvas.viewport().mapToGlobal(pos)) if action == saveAction: self.file_save() def file_save(self, target="figure"): name = QtGui.QFileDialog.getSaveFileName(self, "Save File") if target == "figure": self.figure.savefig(name) def update_progress_bar(self, i: int): self.progress.setValue(i) max = self.progress.maximum() self.statusBar.showMessage(f"Loading ... {100*i/max:.0f}%") def set_progress_bar_max(self, max: int): self.progress.setMaximum(max) def clear_progress_bar(self): self.progress.hide() self.statusBar.showMessage("Completed.") def getCSV(self): self.statusBar.showMessage("Loading CSV...") filepath, _ = QtWidgets.QFileDialog.getOpenFileName( self, "Open CSV", (QtCore.QDir.homePath()), "CSV (*.csv *.tsv)") if filepath != "": self.filepath = filepath self.loaderThread = QThread() self.loaderWorker = QtFileLoader(filepath) self.loaderWorker.moveToThread(self.loaderThread) self.loaderThread.started.connect(self.loaderWorker.read_in_chunks) self.loaderWorker.intReady.connect(self.update_progress_bar) self.loaderWorker.progressMaximum.connect( self.set_progress_bar_max) # self.loaderWorker.read_in_chunks.connect(self.df) self.loaderWorker.completed.connect(self.list_to_df) self.loaderWorker.completed.connect(self.clear_progress_bar) self.loaderThread.finished.connect(self.loaderThread.quit) self.loaderThread.start() @pyqtSlot(list) def list_to_df(self, dfs: list): df = pd.concat(dfs) self.df = df self.columns = self.df.columns.tolist() self.plot_list = [ "Actogram", "Polar Bar", "Polar Histogram", "Trajectory" ] self.comboBox.clear() self.comboBox.addItems(self.columns) self.comboBox2.clear() self.comboBox2.addItems(self.plot_list) self.statusBar.clearMessage() def mousePressEvent(self, QMouseEvent): if QMouseEvent.button() == Qt.RightButton: print("Right Button Clicked") def load_project_structure(self, startpath, tree): """ Load Project structure tree :param startpath: :param tree: :return: """ from PyQt5.QtWidgets import QTreeWidgetItem from PyQt5.QtGui import QIcon for element in os.listdir(startpath): path_info = startpath + "/" + element parent_itm = QTreeWidgetItem(tree, [os.path.basename(element)]) if os.path.isdir(path_info): self.load_project_structure(path_info, parent_itm) parent_itm.setIcon(0, QIcon("assets/folder.ico")) else: parent_itm.setIcon(0, QIcon("assets/file.ico")) def set_time_window(self, window: str): global TIME_WINDOW TIME_WINDOW = window self.statusBar.showMessage(f"Time window set to {window}") actions = self.setTimeWindowMenu.actions() for action in actions: if action.text() == TIME_WINDOW: action.setChecked(True) else: action.setChecked(False) print(f"Time window set to {window}") def plot(self): plt.clf() plot_kind = self.comboBox2.currentText() self.statusBar.showMessage(f"Plotting {plot_kind}") projection = ("polar" if plot_kind in ["Polar Bar", "Polar Histogram"] else "rectilinear") ax = self.figure.add_subplot(111, projection=projection) title = f"{basename(self.filepath)}" # TODO: Move mapping to separate method if plot_kind == "Actogram": displacement = traja.trajectory.calc_displacement(self.df) if TIME_WINDOW != "None": displacement = displacement.rolling(TIME_WINDOW).mean() # from pyqtgraph.Qt import QtGui, QtCore traja.plotting.plot_actogram(displacement, ax=ax, interactive=False) elif plot_kind == "Trajectory": traja.plotting.plot(self.df, ax=ax, interactive=False) elif plot_kind == "Quiver": traja.plotting.plot_quiver(self.df, ax=ax, interactive=False) elif plot_kind == "Polar Bar": traja.plotting.polar_bar(self.df, ax=ax, title=title, interactive=False) elif plot_kind == "Polar Histogram": traja.plotting.polar_bar(self.df, ax=ax, title=title, overlap=False, interactive=False) plt.tight_layout() self.canvas.draw() self.statusBar.clearMessage() def center(self): qr = self.frameGeometry() cp = QtWidgets.QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft())
class BandwidthDialog(Ui_bandwidthDialog): def __init__(self): super(BandwidthDialog, self).__init__() self.__minBoxes = [] self.__maxBoxes = [] self.__minMaxValues = ((0.0, 0.0), (0.0, 0.0)) def setupUi(self, variables): super().setupUi(self) self.__setLayout(self, variables) self.__connectSlots() def __setLayout(self, bwDialog, variables): # self.variables = variables verticalLayout = QVBoxLayout() for var in variables: verticalLayout.addLayout( self.__addLineWithBandwidthParameters(var)) self.calculateButton = self.__makeCalculateButton() self.statusBar = QStatusBar() verticalLayout.addSpacerItem( QSpacerItem(20, 50, QSizePolicy.Expanding, QSizePolicy.Expanding)) verticalLayout.addWidget(self.calculateButton) verticalLayout.addWidget(self.statusBar) bwDialog.setLayout(verticalLayout) def __makeCalculateButton(self): calculateButton = QPushButton() calculateButton.setText("Calculate") calculateButton.setObjectName("calculateButton") return calculateButton def __addLineWithBandwidthParameters(self, var): horizontalLayout = QHBoxLayout() minText = QLabel(var + ' min:') maxText = QLabel('max:') minBox = QDoubleSpinBox() minBox.setMinimum(-1e20) self.__minBoxes.append(minBox) maxBox = QDoubleSpinBox() maxBox.setMinimum(-1e20) self.__maxBoxes.append(maxBox) horizontalLayout.addWidget(minText) horizontalLayout.addWidget(minBox) horizontalLayout.addWidget(maxText) horizontalLayout.addWidget(maxBox) return horizontalLayout def __disableButtonAndShowMessage(self): self.calculateButton.setDisabled(True) self.statusBar.showMessage("Min musi być większe niż max") def __enableButtonAndClearMessage(self): self.calculateButton.setEnabled(True) self.statusBar.clearMessage() def __calculateButtonClicked(self): self.__readMinMaxValues() if not self.__checkMinMaxIsCorrect(): self.__disableButtonAndShowMessage() return self.accept() def __readMinMaxValues(self): minValues = [minBox.value() for minBox in self.__minBoxes] maxValues = [maxBox.value() for maxBox in self.__maxBoxes] self.__minMaxValues = tuple(zip(minValues, maxValues)) def __checkMinMaxIsCorrect(self): for min, max in self.__minMaxValues: if min >= max: return False return True def __minValueChanged(self): self.__readMinMaxValues() if not self.__checkMinMaxIsCorrect(): self.__disableButtonAndShowMessage() else: self.__enableButtonAndClearMessage() def __maxValueChanged(self): self.__readMinMaxValues() if not self.__checkMinMaxIsCorrect(): self.__disableButtonAndShowMessage() else: self.__enableButtonAndClearMessage() def __connectSlots(self): for minBox in self.__minBoxes: minBox.valueChanged.connect(self.__minValueChanged) for maxBox in self.__maxBoxes: maxBox.valueChanged.connect(self.__maxValueChanged) self.calculateButton.clicked.connect(self.__calculateButtonClicked) def getMinMaxValues(self): # if '__minMaxValues' in locals(): # self.__minMaxValues = ((0.0, 0.0), (0.0, 0.0)) return self.__minMaxValues
class ErrorStatusBar(QWidget): """ A pop-up status bar for displaying messages about application errors to the user. Messages will be displayed for a given duration or until the message is cleared or updated with a new message. """ CSS = ''' #error_vertical_bar { background-color: #f22b5d; } #error_icon { background-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fff, stop: 0.2 #fff, stop: 1 #fff ); } #error_status_bar { background-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fff, stop: 0.2 #fff, stop: 1 #fff ); font-weight: bold; color: #f22b5d; } ''' def __init__(self): super().__init__() # Set styles self.setStyleSheet(self.CSS) # Set layout layout = QHBoxLayout(self) self.setLayout(layout) # Remove margins and spacing layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) # Error vertical bar self.vertical_bar = QWidget() self.vertical_bar.setObjectName('error_vertical_bar') # Set css id self.vertical_bar.setFixedWidth(10) # Error icon self.label = SvgLabel('error_icon.svg', svg_size=QSize(32, 32)) self.label.setObjectName('error_icon') # Set css id self.label.setFixedWidth(42) # Error status bar self.status_bar = QStatusBar() self.status_bar.setObjectName('error_status_bar') # Set css id self.status_bar.setSizeGripEnabled(False) # Add widgets to layout layout.addWidget(self.vertical_bar) layout.addWidget(self.label) layout.addWidget(self.status_bar) # Hide until a message needs to be displayed self.vertical_bar.hide() self.label.hide() self.status_bar.hide() # Only show errors for a set duration self.status_timer = QTimer() self.status_timer.timeout.connect(self._on_status_timeout) def _hide(self): self.vertical_bar.hide() self.label.hide() self.status_bar.hide() def _show(self): self.vertical_bar.show() self.label.show() self.status_bar.show() def _on_status_timeout(self): self._hide() def update_message(self, message: str, duration: int): """ Display a status message to the user for a given duration. """ self.status_bar.showMessage(message, duration) self.status_timer.start(duration) self._show() def clear_message(self): """ Clear any message currently in the status bar. """ self.status_bar.clearMessage() self._hide()
class TransformationMap(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setWindowTitle( 'Define transformations between coordinate systems') self.recWidth = 80 self.recHeight = 50 self.circleRadius = 20 self.rectangles = [ QRect(int(self.width() / 2 - 40), int(self.height() / 2 - 25), self.recWidth, self.recHeight), QRect(int(self.width() / 2 - 40), int(self.height() / 2 + 95), self.recWidth, self.recHeight) ] self.labels = ['System 1', 'System 2'] self.transformations = {} self.statusbar = QStatusBar() self.btnAddRect = QPushButton('Add\nSystem', self) self.btnAddRect.clicked.connect(self.addRect) self.btnAddRect.setFixedSize(110, 50) self.btnClear = QPushButton('Clear', self) self.btnClear.clicked.connect(self.clear) self.btnClear.setFixedSize(110, 50) self.btnAddConnect = QPushButton('Add\nTransformation', self) self.btnAddConnect.clicked.connect(self.addConnection) self.btnAddConnect.setFixedSize(110, 50) self.btnAddConnect.setCheckable(True) self.btnAddConnect.setChecked(False) self.btnSave = QPushButton('Save', self) self.btnSave.clicked.connect(self.save) self.btnSave.setFixedSize(110, 50) self.btnSave.setEnabled(False) self.btnLoad = QPushButton('Load', self) self.btnLoad.clicked.connect(self.load) self.btnLoad.setFixedSize(110, 50) layout = QVBoxLayout() layout.addWidget(self.btnAddConnect) layout.addWidget(self.btnAddRect) layout.addWidget(self.btnClear) layout.addItem(QSpacerItem(10, 15)) layout.addStretch() layout.addWidget(self.btnSave) layout.addWidget(self.btnLoad) layout.setContentsMargins(0, 0, 0, 0) layout.addStretch() layout.addWidget(self.statusbar) self.setLayout(layout) self.resize(800, 600) self.pen = QPen(QColor(0, 0, 0)) self.pen.setWidth(2) self.blackBrush = QBrush(QColor(255, 255, 255, 255)) self.highlight = QColor(255, 255, 180, 255) self.blueBrush = QBrush(QColor(200, 230, 250, 255)) self.add_connection_mode = False self.connection_point = None self.current_rectangle = -1 self.setMouseTracking(True) def clear(self): msg = QMessageBox.warning( None, 'Confirm clear', 'Do you want to clear all systems and transformations?', QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok) if msg == QMessageBox.Cancel: return self.rectangles = [ QRect(self.width() / 2 - 40, self.height() / 2 - 25, self.recWidth, self.recHeight), QRect(self.width() / 2 - 40, self.height() / 2 + 95, self.recWidth, self.recHeight) ] self.labels = ['System 1', 'System 2'] self.btnAddConnect.setEnabled(True) self.btnSave.setEnabled(False) self.transformations = {} self.repaint() def addRect(self): self.rectangles.append( QRect(int(self.width() / 2 - 40), int(self.height() / 2 - 25), self.recWidth, self.recHeight)) self.labels.append('System %d' % len(self.rectangles)) self.btnAddConnect.setEnabled(True) self.btnSave.setEnabled(False) self.repaint() def addConnection(self): self.btnAddConnect.setChecked(True) self.add_connection_mode = True self.statusbar.showMessage('Draw a line between two systems') def save(self): filename, _ = QFileDialog.getSaveFileName( self, 'Choose the file name', '', 'All files (*)', options=QFileDialog.Options() | QFileDialog.DontUseNativeDialog) if not filename: return with open(filename, 'w') as f: f.write('|'.join(self.labels)) f.write('\n') f.write('|'.join( map(lambda p: '%d,%d' % (p.x(), p.y()), [rec.topLeft() for rec in self.rectangles]))) f.write('\n') for (i, j), t in self.transformations.items(): if i > j: continue f.write('%d|%d|%s' % (i, j, repr(t))) f.write('\n') def load(self): msg = QMessageBox.warning( None, 'Confirm load', 'Do you want to load configuration file?\n(Your current workspace will be erased)', QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok) if msg == QMessageBox.Cancel: return filename, _ = QFileDialog.getOpenFileName( self, 'Choose the file name', '', 'All files (*)', options=QFileDialog.Options() | QFileDialog.DontUseNativeDialog) if not filename: return try: with open(filename, 'r') as f: new_labels = f.readline().rstrip().split('|') coords = f.readline().rstrip().split('|') new_rectangles = [] for coord in coords: x, y = map(int, coord.split(',')) new_rectangles.append( QRect(x, y, self.recWidth, self.recHeight)) new_transformations = {} for line in f.readlines(): i, j, params = line.rstrip().split('|') i, j = int(i), int(j) angle, scalexy, scalez, dx, dy, dz = map( float, params.split()) new_transformations[i, j] = Transformation( angle, scalexy, scalez, dx, dy, dz) new_transformations[j, i] = new_transformations[i, j].inverse() if len(new_labels) < 2: raise ValueError if not is_connected(list(range(len(new_labels))), new_transformations.keys()): raise ValueError except (ValueError, IndexError): QMessageBox.critical(self, 'Error', 'The configuration is not valid.', QMessageBox.Ok) return self.btnAddConnect.setEnabled(False) self.btnSave.setEnabled(True) self.labels = new_labels self.rectangles = new_rectangles self.transformations = new_transformations self.repaint() def mousePressEvent(self, event): pos = event.pos() for index, rec in enumerate(self.rectangles): if rec.contains(pos): self.current_rectangle = index if self.add_connection_mode: self.connection_point = pos break def mouseMoveEvent(self, event): if self.current_rectangle > -1: if self.add_connection_mode: self.connection_point = event.pos() else: self.rectangles[self.current_rectangle].moveCenter(event.pos()) self.repaint() def mouseReleaseEvent(self, event): pos = event.pos() if self.current_rectangle > -1 and self.add_connection_mode: for index, rec in enumerate(self.rectangles): if rec.contains(pos): if self.current_rectangle != index and ( self.current_rectangle, index) not in self.transformations: dlg = AddTransformationDialog( self.labels[self.current_rectangle], self.labels[index]) value = dlg.exec_() if value == QDialog.Accepted: self.transformations[self.current_rectangle, index] = dlg.transformation self.transformations[ index, self. current_rectangle] = dlg.transformation.inverse( ) if is_connected(list(range(len(self.rectangles))), self.transformations.keys()): self.btnAddConnect.setEnabled(False) self.btnSave.setEnabled(True) break self.add_connection_mode = False self.btnAddConnect.setChecked(False) self.current_rectangle = -1 self.repaint() self.statusbar.clearMessage() def mouseDoubleClickEvent(self, event): current_index = -1 pos = event.pos() for index, rec in enumerate(self.rectangles): if rec.contains(pos): current_index = index break if current_index > -1: dlg = EditSystemDialog(self.labels[current_index], len(self.labels) > 2) value = dlg.exec_() if value == QDialog.Accepted: self.labels[current_index] = dlg.labelBox.text() elif value == QDialog.Rejected and dlg.deleted: self.rectangles = [ self.rectangles[i] for i in range(len(self.rectangles)) if i != current_index ] self.labels = [ self.labels[i] for i in range(len(self.labels)) if i != current_index ] new_transformation = {} for i, j in self.transformations: if i == current_index or j == current_index: continue new_i, new_j = i - 1 if i > current_index else i, j - 1 if j > current_index else j new_transformation[new_i, new_j] = self.transformations[i, j] self.transformations = new_transformation if is_connected(list(range(len(self.rectangles))), self.transformations.keys()): self.btnAddConnect.setEnabled(False) self.btnSave.setEnabled(True) else: self.btnAddConnect.setEnabled(True) self.btnSave.setEnabled(False) self.repaint() else: for i, j in self.transformations: if i > j: continue p1, p2 = self.rectangles[i].center( ), self.rectangles[j].center() x_center, y_center = (p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2 if max(abs(x_center - event.x()), abs(y_center - event.y())) < self.circleRadius: dlg = EditTransformationDialog(self.labels[i], self.labels[j], self.transformations[i, j], self.transformations[j, i]) value = dlg.exec_() if value == QDialog.Accepted: self.transformations[i, j] = dlg.trans self.transformations[j, i] = dlg.inverse_trans elif value == QDialog.Rejected and dlg.deleted: del self.transformations[i, j] del self.transformations[j, i] self.btnAddConnect.setEnabled(True) self.btnSave.setEnabled(False) break def paintEvent(self, event): painter = QPainter(self) painter.setPen(self.pen) painter.setBrush(self.blackBrush) for i in range(len(self.rectangles) - 1): for j in range(i + 1, len(self.rectangles)): if (i, j) in self.transformations: p1 = self.rectangles[i].center() p2 = self.rectangles[j].center() painter.drawLine(p1, p2) painter.setBrush(self.blueBrush) painter.drawEllipse( QPoint((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2), self.circleRadius, self.circleRadius) painter.setBrush(self.blackBrush) for i, rec in enumerate(self.rectangles): painter.drawRect(rec) painter.drawText(rec, Qt.AlignCenter, self.labels[i]) if self.current_rectangle > -1: if self.add_connection_mode: painter.drawLine( self.rectangles[self.current_rectangle].center(), self.connection_point) else: painter.fillRect(self.rectangles[self.current_rectangle], self.highlight) painter.drawText(self.rectangles[self.current_rectangle], Qt.AlignCenter, self.labels[self.current_rectangle])
class Form(QWidget, Ui_Form): def __init__(self): super().__init__() self.setupUi(self) self.statusbar = QStatusBar(self) self.statusbar.move(0, 420) self.statusbar.resize(494, 20) self.comboBox.addItem("Молотый") self.comboBox.addItem("В зернах") self.pushButton.clicked.connect(self.coffee) self.mode = 0 def clear(self): self.lineEdit.clear() self.lineEdit_2.clear() self.lineEdit_3.clear() self.lineEdit_4.clear() self.lineEdit_5.clear() def coffee(self): if self.mode == 0: if self.lineEdit.text(): try: name = self.lineEdit.text() degree = self.lineEdit_2.text() bg = self.comboBox.currentText() desc = self.lineEdit_3.text() price = int(self.lineEdit_4.text()) vol = int(self.lineEdit_5.text()) win.cur.execute(f""" INSERT INTO coffee(name, degree, bg, description, price, volume) VALUES('{name}', '{degree}', '{bg}', '{desc}', {price}, {vol}) """) win.con.commit() self.statusbar.clearMessage() win.update() self.close() except Exception: self.statusbar.showMessage("Неправильный формат ввода") elif self.mode == 1: if self.lineEdit.text(): try: cid = int(self.row[0].text()) name = self.lineEdit.text() degree = self.lineEdit_2.text() bg = self.comboBox.currentText() desc = self.lineEdit_3.text() price = int(self.lineEdit_4.text()) vol = int(self.lineEdit_5.text()) win.cur.execute(f""" UPDATE coffee SET name = '{name}' WHERE id = {cid} """) win.cur.execute(f""" UPDATE coffee SET degree = '{degree}' WHERE id = {cid} """) win.cur.execute(f""" UPDATE coffee SET bg = '{bg}' WHERE id = {cid} """) win.cur.execute(f""" UPDATE coffee SET description = '{desc}' WHERE id = {cid} """) win.cur.execute(f""" UPDATE coffee SET price = {price} WHERE id = {cid} """) win.cur.execute(f""" UPDATE coffee SET volume = {vol} WHERE id = {cid} """) win.con.commit() self.statusbar.clearMessage() win.update() self.close() except Exception as error: self.statusbar.showMessage("Неправильный формат ввода") print(error) def setvalues(self): self.row = [] rn = win.tableWidget.selectedItems()[0].row() for i in range(7): self.row.append(win.tableWidget.item(rn, i)) self.lineEdit.setText(self.row[1].text()) self.lineEdit_2.setText(self.row[2].text()) self.lineEdit_3.setText(self.row[4].text()) self.lineEdit_4.setText(self.row[5].text()) self.lineEdit_5.setText(self.row[6].text()) if self.row[3].text() == "Молотый": self.comboBox.setCurrentIndex(0) else: self.comboBox.setCurrentIndex(1)
class Main(QMainWindow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) layout = QWidget(self) self.setCentralWidget(layout) grid = QGridLayout() grid.setSpacing(10) rssLabel = QLabel("RSS Feed:", self) self.rssInput = QLineEdit(self) self.rssInput.textEdited.connect(self.enableButtons) self.btnCheckRss = QPushButton("Load", self) self.btnCheckRss.setToolTip("Loads the RSS") self.btnCheckRss.setEnabled(False) self.btnCheckRss.clicked.connect(self.showRss) inputLabel = QLabel("Looking for:", self) self.entryInput = QLineEdit(self) self.entryInput.textChanged.connect(self.enableButtons) timerLabel = QLabel("Check:", self) self.combo = QComboBox(self) self.combo.addItems([ "Once", "Every minute", "Every 5 minutes", "Every 15 minutes", "Every 30 minutes", "Every hour" ]) self.combo.setEnabled(False) self.statusBar = QStatusBar() self.buttonStart = QPushButton("Check the RSS feed", self) self.buttonStart.setEnabled(False) self.buttonStart.clicked.connect(self.startChecking) grid.addWidget(rssLabel, 1, 0) grid.addWidget(self.rssInput, 1, 1) grid.addWidget(self.btnCheckRss, 1, 2) grid.addWidget(inputLabel, 2, 0) grid.addWidget(self.entryInput, 2, 1) # grid.addWidget(self.btnHelpInput,2,2) grid.addWidget(timerLabel, 3, 0) grid.addWidget(self.combo, 3, 1, 1, 2) grid.addWidget(self.buttonStart, 4, 0, 1, 3) self.rssdialog = FeedEntries() self.rssdialog.reloadButton.clicked.connect(self.showRss) self.timer = QBasicTimer() self.loadedFlag = False layout.setLayout(grid) self.setStatusBar(self.statusBar) self.statusBar.showMessage("Ready") self.setWindowTitle('RSS Checker') def enableButtons(self): if len(self.rssInput.text()) > 0: self.loadedFlag = False self.rssdialog.purgeAll() self.btnCheckRss.setEnabled(True) if len(self.entryInput.text()) > 0: self.buttonStart.setEnabled(True) self.combo.setEnabled(True) else: self.buttonStart.setEnabled(False) self.combo.setEnabled(False) else: self.btnCheckRss.setEnabled(False) def rssEntriesWarning(self, feed): if len(feed.entries) == 0: self.statusBar.showMessage("Warning!") QMessageBox.warning( self, "Warning!", "The current RSS has no entries.\nPlease make sure you are using a valid RSS feed" ) self.statusBar.showMessage("Ready") return True else: return False def startChecking(self): if not self.timer.isActive(): if not self.checkRSS(): timer = self.combo.currentIndex() times = [0, 60000, 300000, 900000, 1800000, 3600000] if timer != 0: self.btnCheckRss.setEnabled(False) self.combo.setEnabled(False) self.entryInput.setEnabled(False) self.rssInput.setEnabled(False) self.timer.start(times[timer], self) now = self.getTime() message = "Last checked: " + now self.statusBar.showMessage(message) self.buttonStart.setText('Stop') elif self.timer.isActive(): self.btnCheckRss.setEnabled(True) self.combo.setEnabled(True) self.entryInput.setEnabled(True) self.rssInput.setEnabled(True) self.timer.stop() self.buttonStart.setText('Check the RSS feed') self.statusBar.clearMessage() def checkRSS(self): flag = False entries = self.getRss() if entries == list(): return False check = self.entryInput.text() name, number = self.getWords(check) found = list() message = "Looking into the RSS feed for " + check + " ..." self.statusBar.showMessage(message) for post in entries: if name in post['title'].lower() and number in post['title'].lower( ): found.append(post) self.statusBar.clearMessage() flag = True if not flag: self.statusBar.showMessage("Not found :(") else: self.showRss(found) return flag def getTime(self): now = datetime.datetime.now() timestamp = datetime.time(now.hour, now.minute).isoformat()[:-3] logger.debug(timestamp) return timestamp def timerEvent(self, e): if self.checkRSS(): self.timer.stop() self.btnCheckRss.setEnabled(True) self.combo.setEnabled(True) self.entryInput.setEnabled(True) self.rssInput.setEnabled(True) self.buttonStart.setText('Check the RSS feed') self.statusBar.showMessage() else: message = "Last checked: " + self.getTime().zfill(2) self.statusBar.showMessage(message) def getRss(self): rss = self.rssInput.text() if rss != str(): self.statusBar.showMessage("Reading the RSS Feed...") feed = feedparser.parse(rss) if not self.rssEntriesWarning(feed): entries = list() now = self.getTime() for post in feed.entries: entry = { "title": post.title, "link": post.link, "added": now } entries.append(entry) else: return list() return entries def showRss(self, entries=None): logger.info(entries) if not entries: results = self.getRss() else: results = entries if results == list(): return if not self.loadedFlag: self.loadedFlag = True for i in results: self.rssdialog.addItems(i, self.rssdialog.feedlist.rowCount()) else: for i in reversed(results): self.rssdialog.addItems(i, 0) self.rssdialog.show() def getWords(self, string): string = string.split(".")[0] m = re.findall(r"\[([A-Za-z0-9_]+)\]", string) logger.debug((string, m)) for line in m: remove = "[" + line + "]" string = string.replace(remove, "") string = string.lstrip().rstrip() logger.debug(string) if (any(char.isdigit() for char in string)): newString = string[::-1] counter = 0 for number in newString: if number.isdigit(): counter += 1 else: break number = (string[-counter:]).lower() name = string[:-(counter + 1)].lower() logger.debug(newString) else: number = '' name = string logger.debug((number, name)) return name, number
class mainWindow(QMainWindow): # Define the digit count used in the game count = 3 def __init__(self, parent=None): super().__init__(parent) # Initialize the main widget self.gameWidget = SBGame() self.setCentralWidget(self.gameWidget) # Window title & status bar self.setWindowTitle('Software Project II') self.statusBar = QStatusBar(self) self.setStatusBar(self.statusBar) # Connect button callbacks self.gameWidget.guessButton.clicked.connect(self.guessClicked) self.gameWidget.newGameButton.clicked.connect(self.startGame) self.gameWidget.hintButton.clicked.connect(self.help) # Initialize a new game self.game = StrikeBall() self.startGame() def help(self): appendedString = " 1. 우리편(나)이 0~9까지 임의의 네자리 수를 정한다." + '\n' + "2. 상대편(맞추는 사람)이 임의의 3자리 수를 부른다." + '\n' + "3. 우리편(나)이 상대편(맞추는 사람)이 부른 3자리 수를 듣고 스트라이크(S), 볼(B)의 개수를 알려준다." + '\n' + "4. 3스트라이크를 알아내면 게임은 끝이난다" self.gameWidget.log.setText(appendedString) def startGame(self): # Start a new game self.game.newGame(self.count) # Clear dirty output generated by the last game self.gameWidget.Noutput.clear() self.gameWidget.Soutput.clear() self.gameWidget.Boutput.clear() self.gameWidget.userInput.clear() self.gameWidget.log.clear() # Show new game status message and set "game over" flag to False self.statusBar.showMessage('New game started - count: %d' % self.count) self.gameOver = False def guessClicked(self): # If the "game over" flag is set, we do not accept any input if self.gameOver: self.statusBar.showMessage('Game Over!') return # Clear status bar message, get user input - clear it afterwards self.statusBar.clearMessage() userGuess = self.gameWidget.userInput.text() self.gameWidget.userInput.clear() # Check input length, deny if it doesn't match userGuesshint = str(userGuess) if userGuesshint == "hint": # a = self.game.hint() self.statusBar.showMessage('%d in secret number' % self.game.hint()) return # self.game.hint() elif userGuesshint == "answer": self.statusBar.showMessage('answer is %d' % self.game.answer()) return elif len(userGuess) != self.count: self.statusBar.showMessage('Count must be %d!' % self.count) return # Do the math - logic is defined in the last semester s, b = self.game.guess(userGuess) # Format output string and show it to the user strikes, balls = ' '.join('O' * s), ' '.join('O' * b) self.gameWidget.Noutput.setText(' '.join(userGuess)) self.gameWidget.Soutput.setText(strikes) self.gameWidget.Boutput.setText(balls) # We also need some accumulated output to enjoy the game logString = '%s -> S: %d, B: %d' % (userGuess, s, b) ballcontrol = self.game.getGuessCount1() / self.game.getGuessCount( ) * 100 appendedString = self.gameWidget.log.toPlainText( ) + logString + " 당신의 제구력은 : " + str(ballcontrol) + '\n' self.gameWidget.log.setText(appendedString) # If the user gets enough strikes, congratulate him/her, and # don't forget to set the "game over" flag to True if s == self.count: guessCount = self.game.getGuessCount() self.statusBar.showMessage('You got it in %d tries!' % guessCount) appendedString = self.gameWidget.log.toPlainText() + '********' self.gameWidget.log.setText(appendedString) self.gameOver = True
class InteractivePlotter(QMainWindow): '''main class for this tool''' def __init__(self, parent=None): super(InteractivePlotter, self).__init__(parent) self.showMaximized() self.setWindowTitle("SummaryExplorer") QApplication.processEvents() self.plot_fame = FigFrame(self) self.layout = QtWidgets.QVBoxLayout() self.layout.addWidget(self.plot_fame) self.setLayout(self.layout) self.setCentralWidget(self.plot_fame) self.showMaximized() self.raw_path = '' mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('File') imageMenu = mainMenu.addMenu('Images') loadButton = QAction('Load', self) loadButton.setStatusTip('Load data') loadButton.setShortcut("Ctrl+o") loadButton.triggered.connect(self.callLoadData) fileMenu.addAction(loadButton) self.saveButton = QAction('Save', self) self.saveButton.setStatusTip('Save PSD data to xls') self.saveButton.setShortcut("Ctrl+s") self.saveButton.triggered.connect(self.plot_fame.graph_view.save_data) fileMenu.addAction(self.saveButton) self.saveButton.setEnabled(False) avwinButton = QAction('Average window', self) avwinButton.setStatusTip('Change the average window') avwinButton.setShortcut("Ctrl+w") avwinButton.triggered.connect(self.modify_av_wind) fileMenu.addAction(avwinButton) exitButton = QAction('Exit', self) exitButton.setStatusTip('Close') exitButton.triggered.connect(self.close) fileMenu.addAction(exitButton) self.rawButton = QAction('Raw Image', self) self.rawButton.setShortcut("r") self.rawButton.triggered.connect(self.find_raw_data) imageMenu.addAction(self.rawButton) self.rawButton.setEnabled(False) self.imcButton = QAction('Corrected Image', self) self.imcButton.setShortcut("c") self.imcButton.triggered.connect(self.find_imc_data) imageMenu.addAction(self.imcButton) self.imcButton.setEnabled(False) self.toggleButton = QAction('Toggle plot p', self) self.toggleButton.setShortcut("p") self.toggleButton.triggered.connect( self.plot_fame.graph_view.toggle_plot) self.toggleButton.setEnabled(False) mainMenu.addAction(self.toggleButton) self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.statusBar.showMessage('Hello. Load a -STATS.csv file to start', 1e12) def callLoadData(self): self.statusBar.showMessage('Loading data. PLEASE WAIT', 1e12) self.plot_fame.graph_view.load_data() self.raw_path = '' self.raw_files = '' self.saveButton.setEnabled(True) self.rawButton.setEnabled(True) self.imcButton.setEnabled(True) self.toggleButton.setEnabled(True) self.statusBar.clearMessage() self.setWindowTitle("SummaryExplorer: " + self.plot_fame.graph_view.stats_filename) def keyPressEvent(self, event): pressedkey = event.key() if (pressedkey == QtCore.Qt.Key_Up) or (pressedkey == QtCore.Qt.Key_W): self.plot_fame.graph_view.av_window += pd.Timedelta(seconds=1) self.plot_fame.graph_view.update_plot() event.accept() elif (pressedkey == QtCore.Qt.Key_Right) or (pressedkey == QtCore.Qt.Key_D): self.plot_fame.graph_view.mid_time += pd.Timedelta(seconds=1) self.plot_fame.graph_view.update_plot() event.accept() elif (pressedkey == QtCore.Qt.Key_Down) or (pressedkey == QtCore.Qt.Key_S): self.plot_fame.graph_view.av_window -= pd.Timedelta(seconds=1) self.plot_fame.graph_view.av_window = max( pd.Timedelta(seconds=1), self.plot_fame.graph_view.av_window) self.plot_fame.graph_view.update_plot() event.accept() elif (pressedkey == QtCore.Qt.Key_Left) or (pressedkey == QtCore.Qt.Key_A): self.plot_fame.graph_view.mid_time -= pd.Timedelta(seconds=1) self.plot_fame.graph_view.av_window = max( pd.Timedelta(seconds=1), self.plot_fame.graph_view.av_window) self.plot_fame.graph_view.update_plot() event.accept() else: event.ignore() def find_imc_data(self): self.extract_filename() if len(self.raw_files) == 0: return bg_window = pd.to_timedelta(5, unit='S') start_time = self.plot_fame.graph_view.mid_time - bg_window / 2 end_time = self.plot_fame.graph_view.mid_time + bg_window / 2 u = pd.to_datetime(self.plot_fame.graph_view.u) midtimeidx = np.argwhere((u >= start_time) & (u < end_time)) ws = waitsplash() self.statusBar.showMessage( 'Creating background from ' + str(len(midtimeidx)) + ' images', 1e12) imbg = np.float64(silcam_load(self.raw_files[midtimeidx[0][0]])) for i in range(len(midtimeidx) - 1): imbg += np.float64( silcam_load(self.raw_files[midtimeidx[i + 1][0]])) imbg /= len(midtimeidx) imraw = np.float64(silcam_load(self.filename)) imc = correct_im_fast(imbg, imraw) self.statusBar.showMessage('Background done.', 1e12) ws.close() self.plot_image(imc) def find_raw_data(self): self.extract_filename() if len(self.raw_files) == 0: return img = silcam_load(self.filename) self.plot_image(img) def extract_filename(self): if self.raw_path == '': self.raw_path = QFileDialog.getExistingDirectory( self, caption='Where are the raw data?', directory=self.raw_path) self.raw_files = sorted(glob(os.path.join(self.raw_path, '*.silc'))) if len(self.raw_files) == 0: self.raw_files = sorted( glob(os.path.join(self.raw_path, '*.bmp'))) if len(self.raw_files) == 0: self.statusBar.showMessage('No data here: ' + self.raw_path, 1e12) self.raw_path = '' return midtimeidx = np.argwhere( self.plot_fame.graph_view.u > self.plot_fame.graph_view.mid_time )[0] search_time = self.plot_fame.graph_view.u[midtimeidx].to_pydatetime( )[0] print('search_time', search_time) estimate_filename = os.path.join( self.raw_path, search_time.strftime('D%Y%m%dT%H%M%S.*.*')) filename = glob(estimate_filename) if len(filename) == 0: print('can' 't find this:', estimate_filename) return self.filename = filename[0] def plot_image(self, img): cv = FigureCanvas(plt.figure(figsize=(5, 3))) cv.setWindowTitle(self.filename) plt.imshow(img) plt.title(self.filename) plt.gca().axis('off') cv.show() def modify_av_wind(self): '''allow the user to modify the averaging period of interest''' window_seconds = self.plot_fame.graph_view.av_window.seconds input_value, okPressed = QInputDialog.getInt(self, "Get integer", "Average window:", window_seconds, 0, 60 * 60, 1) if okPressed: self.plot_fame.graph_view.av_window = pd.Timedelta( seconds=input_value) if not self.plot_fame.graph_view.stats_filename == '': self.plot_fame.graph_view.update_plot()
def message_end(self, message): if message == '': self.hide() QStatusBar.clearMessage(self) self._widgetStatus.show()
class Player(QtWidgets.QMainWindow): def __init__(self, muted=False, save_frames=False, master=None): QtWidgets.QMainWindow.__init__(self, master) self.setWindowIcon(QIcon("icons/app.svg")) self.title = "Bilkent Video Annotation Tool" self.muted = muted self.save_frames = save_frames self.setWindowTitle(self.title) options = QFileDialog.Options() options |= QFileDialog.ShowDirsOnly options |= QFileDialog.Directory # options |= QFileDialog.DontUseNativeDialog supported_formats = [ ".mp3", ".mp4", ".avi", ".wmv", ".mp4", ".mov", ".ogg", ".wav", ".ogm" ] self.video_paths = [] while len(self.video_paths) == 0: videos_dir = str( QFileDialog.getExistingDirectory(self, "Select Videos Directory", options=options)) self.video_paths = [] for fmt in supported_formats: self.video_paths += [ f for f in glob.glob(videos_dir + "**/*" + fmt, recursive=False) ] print(self.video_paths) if len(self.video_paths) == 0 or len(videos_dir) == 0: QtWidgets.QMessageBox.question( self, 'No videos exist', "Please select a directory containing videos.", QtWidgets.QMessageBox.Ok) self.annotations_dir = "" while len(self.annotations_dir) == 0: self.annotations_dir = str( QFileDialog.getExistingDirectory( self, "Select Annotations Directory", options=options)) print(self.annotations_dir) self.annotation_paths = [ f for f in glob.glob(self.annotations_dir + "**/*.json", recursive=False) ] if len(self.annotations_dir) == 0: QtWidgets.QMessageBox.question( self, 'No directory selected.', "Please select a directory for annotations", QtWidgets.QMessageBox.Ok) self.num_videos = len(self.video_paths) self.current_video = 0 self.annotations = {} for annotation_path in self.annotation_paths: j = json.load(open(annotation_path, "r")) self.annotations[j["name"]] = j print(self.annotation_paths) self.createVideoPlayer() self.createUI() self.createToolbar() self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.current_annotation = "A" self.statusbar.showMessage("Current Annotation: " + self.current_annotation) self.createShortcuts() is_video_set = False for i, video_path in enumerate(self.video_paths): if "\\" in video_path: video_name = video_path.split("\\")[-1] else: video_name = video_path.split("/")[-1] if video_name not in self.annotations: self.file = self.OpenFile(video_path) self.current_video_attrs = self.annotations.get( video_name, { "name": video_name, "path": video_path, "annotations": {} }) self.annotations[self.current_video_attrs[ "name"]] = self.current_video_attrs self.current_video = i is_video_set = True break if not is_video_set: video_path = self.video_paths[0] if "\\" in video_path: video_name = video_path.split("\\")[-1] else: video_name = video_path.split("/")[-1] self.file = self.OpenFile(video_path) self.current_video_attrs = self.annotations.get( video_name, { "name": video_name, "path": video_path, "annotations": {} }) self.annotations[ self.current_video_attrs["name"]] = self.current_video_attrs self.play() self.next_visible = True self.prev_visible = True self.setVisibilities() def setPrevNextVisibility(self): self.prev_visible = self.current_video != 0 self.next_visible = self.current_video != self.num_videos - 1 self.remove_visible = self.current_video_attrs[ "name"] in self.annotations and len(self.annotations[ self.current_video_attrs["name"]]["annotations"]) > 0 self.action_previous.setVisible(self.prev_visible) self.action_next.setVisible(self.next_visible) self.action_remove_annotations.setVisible(self.remove_visible) self.statusbar.clearMessage() self.statusbar.showMessage("Current Annotation: " + self.current_annotation) def createShortcuts(self): self.shortcut_playpause = QShortcut(QKeySequence(QtCore.Qt.Key_Return), self) self.shortcut_playpause.activated.connect(self.playPauseShortcut) self.shortcut_previous = QShortcut(QKeySequence(QtCore.Qt.Key_Left), self) self.shortcut_previous.activated.connect(self.previousShortcut) self.shortcut_next = QShortcut(QKeySequence(QtCore.Qt.Key_Right), self) self.shortcut_next.activated.connect(self.nextShortcut) self.shortcut_annotate = QShortcut(QKeySequence(QtCore.Qt.Key_Space), self) self.shortcut_annotate.activated.connect(self.annotate) self.shortcut_remove_annotation = QShortcut( QKeySequence(QtCore.Qt.Key_Backspace), self) self.shortcut_remove_annotation.activated.connect( self.removeAnnotations) for s in string.ascii_uppercase: key = getattr(QtCore.Qt, "Key_" + s) shortcut = QShortcut(QKeySequence(key), self) shortcut.activated.connect(self.changeAnnotationShortcut(s)) def changeAnnotationShortcut(self, s): def annotationShortcut(): self.current_annotation = s self.statusbar.clearMessage() self.statusbar.showMessage("Current Annotation: " + self.current_annotation) return annotationShortcut def removeAnnotations(self): self.current_video_attrs["annotations"] = {} self.annotations[ self.current_video_attrs["name"]] = self.current_video_attrs self.setVisibilities() def previousShortcut(self): if self.prev_visible: self.previous() def nextShortcut(self): if self.next_visible: self.next() def setVisibilities(self): self.setPrevNextVisibility() self.markwidget.setAnnotations( self.annotations[self.current_video_attrs["name"]]["annotations"]) def annotate(self): self.current_video_attrs["annotations"][self.current_annotation] = [ self.mediaplayer.get_position() ] + self.current_video_attrs["annotations"].get( self.current_annotation, []) self.annotations[ self.current_video_attrs["name"]] = self.current_video_attrs self.setVisibilities() if self.save_frames: self.writeFrameToFile() def writeFrameToFile(self): path_to_save = os.path.join(self.annotations_dir, self.current_annotation) if not os.path.exists(path_to_save): os.mkdir(path_to_save) frame_file_name = os.path.join( path_to_save, f'{self.current_video_attrs["name"]}_{str(self.mediaplayer.get_position())}' .replace(".", "_") + '.png') self.mediaplayer.video_take_snapshot(0, frame_file_name, 0, 0) def saveAnnotation(self, annotation): with open( os.path.join(self.annotations_dir, annotation["name"] + ".json"), "w+") as f: json.dump(annotation, f) def playPauseShortcut(self): if self.isPaused: self.play() else: self.pause() def createVideoPlayer(self): self.instance = vlc.Instance() self.mediaplayer = self.instance.media_player_new() if self.muted: self.mediaplayer.audio_set_volume(0) self.isPaused = False def createToolbar(self): toolbar = QToolBar("Manage Video") toolbar.setIconSize(QSize(32, 32)) self.addToolBar(toolbar) self.action_play = QAction(QIcon("icons/play-button.png"), "Play", self) self.action_play.triggered.connect(self.play) self.action_play.setStatusTip("Play Video [Enter Key]") toolbar.addAction(self.action_play) self.action_pause = QAction(QIcon("icons/pause.png"), "Pause", self) self.action_pause.triggered.connect(self.pause) self.action_pause.setVisible(False) self.action_pause.setStatusTip("Pause Video [Enter Key]") toolbar.addAction(self.action_pause) self.action_previous = QAction(QIcon("icons/previous.png"), "Previous Video", self) self.action_previous.setStatusTip("Previous Video [Left Arrow]") self.action_previous.triggered.connect(self.previous) toolbar.addAction(self.action_previous) self.action_next = QAction(QIcon("icons/next.png"), "Next Video", self) self.action_next.triggered.connect(self.next) self.action_next.setStatusTip("Next Video [Right Arrow]") toolbar.addAction(self.action_next) self.action_annotate = QAction( QIcon("icons/plus.png"), "Annotate to current frame of the video", self) self.action_annotate.triggered.connect(self.annotate) self.action_annotate.setStatusTip( "Annotate to current frame of the video [Space Key]") toolbar.addAction(self.action_annotate) self.action_remove_annotations = QAction( QIcon("icons/cancel.png"), "Remove current video's annotations", self) self.action_remove_annotations.triggered.connect( self.removeAnnotations) self.action_remove_annotations.setStatusTip( "Remove current video's annotations [Backspace Key]") toolbar.addAction(self.action_remove_annotations) def play(self): print("Play clicked") self.PlayPause() def pause(self): print("Pause clicked") self.PlayPause() def previous(self): print("Previous clicked") if self.current_video - 1 < 0: return self.saveAnnotation(self.current_video_attrs) if not self.isPaused: self.Stop() self.current_video -= 1 video_path = self.video_paths[self.current_video] if "\\" in video_path: video_name = video_path.split("\\")[-1] else: video_name = video_path.split("/")[-1] self.file = self.OpenFile(video_path) if video_name in self.annotations: self.current_video_attrs = self.annotations[video_name] else: self.current_video_attrs = { "name": video_name, "path": video_path, "annotations": {} } self.annotations[video_name] = self.current_video_attrs self.progress.setValue(self.current_video) self.setVisibilities() self.play() def next(self): print("Next clicked") self.saveAnnotation(self.current_video_attrs) if not self.isPaused: self.Stop() self.current_video += 1 if self.current_video == self.num_videos: QtWidgets.QMessageBox.question( self, "No more videos left.", "All videos are annotated. Now, opening the first video...", QtWidgets.QMessageBox.Ok) self.current_video = 0 video_path = self.video_paths[self.current_video] if "\\" in video_path: video_name = video_path.split("\\")[-1] else: video_name = video_path.split("/")[-1] self.file = self.OpenFile(video_path) if video_name in self.annotations: self.current_video_attrs = self.annotations[video_name] else: self.current_video_attrs = { "name": video_name, "path": video_path, "annotations": {} } self.annotations[video_name] = self.current_video_attrs self.progress.setValue(self.current_video) self.setVisibilities() self.play() def createUI(self): """Set up the user interface, signals & slots """ self.widget = QtWidgets.QWidget(self) self.setCentralWidget(self.widget) # In this widget, the video will be drawn # if sys.platform == "darwin": # for MacOS # self.videoframe = QtWidgets.QMacCocoaViewContainer(0) # else: # self.videoframe = QtWidgets.QFrame() self.videoframe = QtWidgets.QFrame() self.palette = self.videoframe.palette() self.palette.setColor(QtGui.QPalette.Window, QtGui.QColor(0, 0, 0)) self.videoframe.setPalette(self.palette) self.videoframe.setAutoFillBackground(True) self.positionslider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) self.positionslider.setToolTip("Position") self.positionslider.setMaximum(1000) self.positionslider.sliderMoved.connect(self.setPosition) self.vboxlayout = QtWidgets.QVBoxLayout() self.vboxlayout.addWidget(self.videoframe) self.vboxlayout.addWidget(self.positionslider) self.markwidget = MarkWidget() self.vboxlayout.addWidget(self.markwidget) self.widget.setLayout(self.vboxlayout) self.progress = QtWidgets.QProgressBar(self) self.progress.setMaximum(self.num_videos) self.vboxlayout.addWidget(self.progress) self.timer = QtCore.QTimer(self) self.timer.setInterval(100) self.timer.timeout.connect(self.updateUI) def PlayPause(self): """Toggle play/pause status """ if self.mediaplayer.is_playing(): self.mediaplayer.pause() self.action_play.setVisible(True) self.action_pause.setVisible(False) self.isPaused = True else: self.mediaplayer.play() self.action_play.setVisible(False) self.action_pause.setVisible(True) self.timer.start() self.isPaused = False def Stop(self): """Stop player """ self.mediaplayer.stop() def OpenFile(self, filename=None): """Open a media file in a MediaPlayer """ if filename is None or filename is False: print("Attempt to openup OpenFile") filenameraw = QtWidgets.QFileDialog.getOpenFileName( self, "Open File", os.path.expanduser('~')) filename = filenameraw[0] if not filename: return # create the media if sys.version < '3': filename = unicode(filename) self.media = self.instance.media_new(filename) # put the media in the media player self.mediaplayer.set_media(self.media) # parse the metadata of the file self.media.parse() # set the title of the track as window title self.setWindowTitle(self.title + " | " + self.media.get_meta(0)) # the media player has to be 'connected' to the QFrame # (otherwise a video would be displayed in it's own window) # this is platform specific! # you have to give the id of the QFrame (or similar object) to # vlc, different platforms have different functions for this if sys.platform.startswith('linux'): # for Linux using the X Server self.mediaplayer.set_xwindow(self.videoframe.winId()) elif sys.platform == "win32": # for Windows self.mediaplayer.set_hwnd(self.videoframe.winId()) elif sys.platform == "darwin": # for MacOS self.mediaplayer.set_nsobject(int(self.videoframe.winId())) def setPosition(self, position): """Set the position """ # setting the position to where the slider was dragged self.mediaplayer.set_position(position / 1000.0) # the vlc MediaPlayer needs a float value between 0 and 1, Qt # uses integer variables, so you need a factor; the higher the # factor, the more precise are the results # (1000 should be enough) def updateUI(self): """updates the user interface""" # setting the slider to the desired position self.positionslider.setValue(self.mediaplayer.get_position() * 1000) if not self.mediaplayer.is_playing(): # no need to call this function if nothing is played self.timer.stop() if not self.isPaused: self.Stop() self.next()
class App(QMainWindow): def __init__(self): super().__init__() self.title = 'IT567 Port Scanner' self.left = 10 self.top = 10 self.width = 400 self.height = 400 self.initUI() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.host_label = QLabel("IPs:", self) self.host_label.move(20, 14) self.host_text = QLineEdit(self) self.host_text.move(80, 20) self.host_text.resize(140, 20) self.port_label = QLabel("Ports:", self) self.port_label.move(20, 44) self.port_text = QLineEdit(self) self.port_text.move(80, 50) self.port_text.resize(140, 20) self.tcp_button = QRadioButton("TCP", self) self.tcp_button.move(20, 80) self.tcp_button.setChecked(True) self.udp_button = QRadioButton("UDP", self) self.udp_button.move(80, 80) # Create a button in the window self.button = QPushButton('Scan', self) self.button.move(20, 120) self.button.setAutoDefault(True) self.output = QTextEdit(self) self.output.setReadOnly(True) self.output.move(20, 160) self.output.resize(360, 210) # connect button to function on_click self.button.clicked.connect(self.on_click) self.button.pressed.connect(self.on_pressed) self.show() @pyqtSlot() def on_pressed(self): self.button.setEnabled(False) self.output.clear() @pyqtSlot() def on_click(self): if not self.host_text.text(): self.statusBar.showMessage("No hosts specified") self.button.setEnabled(True) return if not self.port_text.text(): self.statusBar.showMessage("No ports specified") self.button.setEnabled(True) return try: hosts = host_list(self.host_text.text()) ports = port_list(self.port_text.text()) except ValueError as e: self.statusBar.showMessage(str(e)) self.button.setEnabled(True) return self.statusBar.showMessage("Scanning...") for host in hosts: udp = self.udp_button.isChecked() protocol = "UDP" if udp else "TCP" self.output.append("Host {} ({}):".format(host, protocol)) try: for port in scan_host(host, ports, udp=udp): self.output.append(str(port)) except socket.error as e: self.output.append(str(e)) self.output.append("") self.statusBar.clearMessage() self.output.append("Done") self.button.setEnabled(True)