class LocalButtonsConf(OptionsDialogGroupBox): def __init__(self, name, main): self.main = main OptionsDialogGroupBox.__init__(self, name, main) self.buttonBox = QGroupBox("Pins") self.buttonBoxLayout = QVBoxLayout() self.buttonBox.setLayout(self.buttonBoxLayout) def initUI(self): vbox = QVBoxLayout() self.polBox = QCheckBox("Invert") vbox.addWidget(self.polBox) self.buttongroup = QButtonGroup() self.buttongroup.setExclusive(False) vbox.addWidget(self.buttonBox) self.setLayout(vbox) def initButtons(self, num): #delete buttons self.num = num # Remove buttons for i in range(self.buttonBoxLayout.count()): b = self.buttonBoxLayout.takeAt(0) self.buttonBoxLayout.removeItem(b) b.widget().deleteLater() for b in self.buttongroup.buttons(): self.buttongroup.removeButton(b) self.buttonBox.update() for i in range(self.num): cb = QCheckBox(str(i + 1)) self.buttongroup.addButton(cb, i) self.buttonBoxLayout.addWidget(cb) def localcb(mask): for i in range(self.num): self.buttongroup.button(i).setChecked(mask & (1 << i)) self.main.comms.serialGetAsync("local_btnmask?", localcb, int) def apply(self): mask = 0 for i in range(self.num): if (self.buttongroup.button(i).isChecked()): mask |= 1 << i self.main.comms.serialWrite("local_btnmask=" + str(mask)) self.main.comms.serialWrite("local_btnpol=" + ("1" if self.polBox.isChecked() else "0")) def readValues(self): self.main.comms.serialGetAsync("local_btnpins?", self.initButtons, int) self.main.comms.serialGetAsync("local_btnpol?", self.polBox.setChecked, int)
class DMSUnitWgt(QWidget): unitTabDataWdg = None decorateTypeWgt: DMSDecorateTypeWgt = None decorateDataWgt: DMSDecorateDataWgt = None currentBuilding: DB_Building = None unitDict: dict = {} def __init__(self, parent=None): super(DMSUnitWgt, self).__init__(parent) self.initUI() self.initTrigger() def initUI(self): self.ui = Ui_UnitWgt() self.ui.setupUi(self) self.ui.verticalLayout.setContentsMargins(0, 0, 0, 0) self.setContentsMargins(0, 0, 0, 0) self.decorateTypeWgt = DMSDecorateTypeWgt(self) self.decorateDataWgt = DMSDecorateDataWgt(self) count = self.ui.verticalLayout.count() self.ui.verticalLayout.addWidget(self.decorateDataWgt) self.groupButton = QButtonGroup(self) def unitChanged(self): # self.decorateDataWgt. pass def initTrigger(self): self.ui.pBtnAddUnit.clicked.connect(self.addUnit) self.ui.pBtnDleleteUnit.clicked.connect(self.deleteUnit) self.groupButton.buttonClicked.connect(self.unitChanged) def setCurrentBuilding(self, building_id): if self.currentBuilding and self.currentBuilding.id == building_id: return self.currentBuilding = None building: DB_Building = dmsDatabase().getRecordById( DB_Building, building_id) if building is None: self.updateUiEnabled() return self.currentBuilding = building self.clearUnit() self.loadUnit() self.updateUiEnabled() def getCurrentUnit(self): pass def addUnit(self): unit = newUnit(self.currentBuilding) unit_tool_btn = self.createToolButton(unit) unit_tool_btn.setChecked(True) def deleteUnit(self): _id = self.groupButton.checkedId() _button = self.groupButton.checkedButton() self.groupButton.removeButton(_button) delete(_button) customDeleteRecord(DB_Building_Unit, _id) self.updateUiEnabled() def createToolButton(self, business_unit) -> QToolButton: if business_unit is None: return unit_tool_btn = QToolButton() unit_tool_btn.setText(business_unit.name) unit_tool_btn.setCheckable(True) count = self.ui.horizontalLayout.count() self.ui.horizontalLayout.insertWidget(count - 3, unit_tool_btn) self.unitDict[business_unit.id] = unit_tool_btn self.groupButton.addButton(unit_tool_btn, business_unit.id) return unit_tool_btn def loadUnit(self): if self.currentBuilding is None: return unit_list = dmsDatabase().getTableList( DB_Building_Unit, "building_id = " + str(self.currentBuilding.id)) if len(unit_list) == 0: return first_item: QToolButton = None for item in unit_list: unit_tool_btn = self.createToolButton(item) if first_item is None: first_item = unit_tool_btn first_item.setChecked(True) def clearUnit(self): if len(self.unitDict) == 0: return tool_btn_list = self.unitDict.values() for var in self.groupButton.buttons(): self.groupButton.removeButton(var) for item in tool_btn_list: self.ui.horizontalLayout.removeWidget(item) delete(item) self.unitDict.clear() def updateUnitDate(self, currentBuildingID, previousBuildingID=None): """ 槽函数 :param currentBuildingID: :param previousBuildingID: :return: """ pass # # Todo 待梳理嵌套关系 # print(currentBuildingID, previousBuildingID) # dateTableWidget = self.unitTabWdg.currentWidget() # dateTableWidget = DMSDecorateDataWgt() # # decorateTaskList: List[DB_Decorate_Type] = dmsProject().getTableList(DB_Decorate_Type, filter_str=currentBuildingID).orderBy( # # DB_Decorate_Type.order) # decorateTaskList: List[DB_Decorate_Type] = dmsDatabase().getTableList(DB_Decorate_Type) # tableHeaderList = [task.name for task in decorateTaskList] # dateTableWidget.setHorizontalHeaderLabels(tableHeaderList) def updateUiEnabled(self): enabled = False if len(self.unitDict) == 0: enabled = False else: enabled = True self.ui.pBtnDleleteUnit.setEnabled(enabled)
class ToggleToolBar(QWidget): index = 0 buttons = [] rows = [] maxRow = 7 maxCol = 4 selectedFrame = [] selectedButtons = [] def __init__(self): super(ToggleToolBar, self).__init__() self.setFixedSize(300,560) self.container = QVBoxLayout() self.container.setAlignment(Qt.AlignLeft) self.container.setSpacing(5) for i in range(0,self.maxRow): row = QHBoxLayout() row.setAlignment(Qt.AlignTop) row.setSpacing(5) self.container.addLayout(row) self.rows.append(row) self.buttonGroup = QButtonGroup() self.buttonGroup.setExclusive(False) self.setLayout(self.container) self.buttonGroup.buttonClicked[int].connect(self.imageSelected) def imageSelected(self,imgId): button = self.buttons[imgId] if button.pixMap in self.selectedFrame and (not button.isChecked()): self.selectedFrame.remove(button.pixMap) self.selectedButtons.remove(button) if (not (button.pixMap in self.selectedFrame)) and button.isChecked(): self.selectedFrame.append(button.pixMap) self.selectedButtons.append(button) def getSelected(self): return self.selectedFrame def clearAllSelected(self): for button in self.selectedButtons: button.setChecked(False) self.selectedButtons = [] self.selectedFrame = [] def addImageButton(self,image): imageButton = ImageToggleButton(self.index,image) self.buttonGroup.addButton(imageButton,self.index) self.rows[self.index//self.maxCol].addWidget(imageButton) self.buttons.append(imageButton) self.index += 1 def createImageButtons(self,imagePath): groupImg = QImage(imagePath) width = groupImg.width() height = groupImg.height() frameSize = width for i in range(0,height//width): img = groupImg.copy(0,i*frameSize,frameSize,frameSize); self.addImageButton(img) def removeAllButton(self): for i in range(0,self.index): row = self.rows[i // self.maxCol] row.removeWidget(self.buttons[i]) self.buttonGroup.removeButton(self.buttons[i]) self.buttons[i].close() self.buttons = [] self.index = 0
class MarkHandler(QWidget): def __init__(self, parent, maxScore, markStyle): super(MarkHandler, self).__init__() self.parent = parent # Set max score/mark self.maxScore = maxScore # Set current score/mark. self.currentScore = 0 # One button for each possible mark, and a dictionary to store them. self.markButtons = {} # Styling for buttons self.redStyle = ( "border: 2px solid #ff0000; background: " "qlineargradient(x1:0,y1:0,x2:1,y2:0, stop: 0 #ff0000, " "stop: 0.3 #ffcccc, stop: 0.7 #ffcccc, stop: 1 #ff0000);") # By default we set style to marking-UP. self.style = "Up" # Keep last delta used self.lastDelta = 0 self.setLayout(QGridLayout()) self._setStyle(markStyle) self.setDeltaButtonMenu() def _setStyle(self, markStyle): """Sets the mark entry style - either total, up or down Total - user just clicks the total mark. Up - score starts at zero and increments. Down - score starts at max and decrements. """ # if passed a marking style, then set up accordingly. if markStyle == 1: self.setMarkingTotal() elif markStyle == 3: self.setMarkingDown() else: # Default to mark-up. self.setMarkingUp() self.ve = QButtonGroup() self.ve.setExclusive(True) for s, x in self.markButtons.items(): self.ve.addButton(x) def resetAndMaybeChange(self, maxScore, markStyle): """Reset score, replace max/style with new values, regen buttons. Total - user just clicks the total mark. Up - score starts at zero and increments. Down - score starts at max and decrements. """ d = {"Total": 1, "Up": 2, "Down": 3} if self.maxScore == maxScore and d[self.style] == markStyle: if markStyle == 3: self.setMark(self.maxScore) else: self.setMark(0) self.updateRelevantDeltaActions() return log.info("Adjusting for new number or new style") for k, x in self.markButtons.items(): self.ve.removeButton(x) self.layout().removeWidget(x) x.deleteLater() self.markButtons.clear() self.currentScore = 0 self.maxScore = maxScore self.markButtons = {} self._setStyle(markStyle) self.setDeltaButtonMenu() def getButtonList(self): """Return a list of the buttons""" return self.markButtons.values() def setMarkingUp(self): self.setMark(0) grid = self.layout() # assume our container will deal with margins grid.setContentsMargins(0, 0, 0, 0) grid.setSpacing(3) ncolumn = min(self.maxScore, 5) for k in range(0, self.maxScore + 1): b = QToolButton() self.markButtons[k] = b b.setText("+{}".format(k)) b.setCheckable(True) # b.setAutoExclusive(True) grid.addWidget(b, k // ncolumn + 1, k % ncolumn, 1, 1) b.clicked.connect(self.setDeltaMark) b.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.style = "Up" def setMarkingDown(self): self.setMark(self.maxScore) grid = self.layout() # assume our container will deal with margins grid.setContentsMargins(0, 0, 0, 0) grid.setSpacing(3) ncolumn = min(self.maxScore, 5) for k in range(0, self.maxScore + 1): b = QToolButton() self.markButtons[k] = b b.setText("-{}".format(k)) b.setCheckable(True) # b.setAutoExclusive(True) grid.addWidget(b, k // ncolumn + 1, k % ncolumn, 1, 1) b.clicked.connect(self.setDeltaMark) b.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.parent.totalMarkSet(self.currentScore) self.style = "Down" def setMarkingTotal(self): grid = self.layout() self.ptmb = QPushButton() if self.maxScore > 5: ncolumn = 3 else: ncolumn = 2 for k in range(0, self.maxScore + 1): self.markButtons[k] = QPushButton("{}".format(k)) grid.addWidget(self.markButtons[k], k // ncolumn, k % ncolumn) self.markButtons[k].clicked.connect(self.setTotalMark) self.markButtons[k].setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.parent.totalMarkSet(self.currentScore) self.style = "Total" def setDeltaMark(self): self.sender().setChecked(True) # yuck, but this will ensure other tools are not checked self.parent.ui.deltaButton.setChecked(True) self.currentDelta = self.sender().text() self.parent.deltaMarkSet(self.currentDelta) def setTotalMark(self): self.ptmb.setStyleSheet("") self.ptmb = self.sender() self.ptmb.setStyleSheet(self.redStyle) self.currentScore = int(self.sender().text()) self.parent.totalMarkSet(self.currentScore) def setMark(self, newScore): self.currentScore = newScore self.parent.totalMarkSet(self.currentScore) def clearButtonStyle(self): # TODO: kill this? but how to uncheck all in an exclusive group? if self.style == "Total": pass # don't clear the styling when marking total. else: # Try this one wierd trick... self.ve.setExclusive(False) for k, x in self.markButtons.items(): x.setChecked(False) self.ve.setExclusive(True) def loadDeltaValue(self, delta): # delta is a string idelta = int(delta) if abs(idelta) > self.maxScore or self.style == "Total": return self.markButtons[abs(idelta)].animateClick() def unpickleTotal(self, score): if (score <= self.maxScore) and (score >= 0) and (self.style == "Total"): self.markButtons[score].animateClick() def incrementDelta(self, dlt): # dlt is a string, so make int(delta) delta = int(dlt) if self.style == "Up": if delta < 0: delta = 0 else: delta += 1 if delta > self.maxScore: delta = 0 self.markButtons[delta].animateClick() elif self.style == "Down": if delta > 0: delta = -1 else: delta -= 1 if abs(delta) > self.maxScore: delta = -1 self.markButtons[-delta].animateClick() def clickDelta(self, dlt): # dlt is a string, so make int(delta) # be careful if this has been set by a no-delta comment. if dlt == ".": delta = 0 else: delta = int(dlt) if self.style == "Up": if delta < 0: delta = 0 self.markButtons[delta].animateClick() elif self.style == "Down": if delta > 0: delta = 0 self.markButtons[-delta].animateClick() def setDeltaButtonMenu(self): if self.style == "Total": # mark total - don't set anything return deltaMenu = QMenu("Set Delta") self.deltaActions = {} if self.style == "Up": # set to mark up for k in range(0, self.maxScore + 1): self.deltaActions[k] = deltaMenu.addAction("+{}".format(k)) self.deltaActions[k].triggered.connect( self.markButtons[k].animateClick) elif self.style == "Down": # set to mark down for k in range(0, self.maxScore + 1): self.deltaActions[k] = deltaMenu.addAction("-{}".format(k)) self.deltaActions[k].triggered.connect( self.markButtons[k].animateClick) self.parent.ui.deltaButton.setMenu(deltaMenu) self.updateRelevantDeltaActions() def updateRelevantDeltaActions(self): if self.style == "Total": return elif self.style == "Up": for k in range(0, self.maxScore + 1): if self.currentScore + k <= self.maxScore: self.deltaActions[k].setEnabled(True) self.markButtons[k].setEnabled(True) else: self.deltaActions[k].setEnabled(False) self.markButtons[k].setEnabled(False) elif self.style == "Down": for k in range(0, self.maxScore + 1): if self.currentScore >= k: self.deltaActions[k].setEnabled(True) self.markButtons[k].setEnabled(True) else: self.deltaActions[k].setEnabled(False) self.markButtons[k].setEnabled(False)
class MainWindow(QWidget): def __init__(self, inList): super().__init__() self.inList = inList self.nameFrom = 'Folder' self.codec = 'utvideo' self.alpha = False self.frameRate = 24 self.defaulStyle = '' self.okIcon = QIcon(self.style().standardIcon(QStyle.SP_CustomBase)) self.okPix = QPixmap(self.okIcon.pixmap(QSize(13, 13))) self.goodIcon = QIcon(self.style().standardIcon(QStyle.SP_DialogApplyButton)) self.goodPix = QPixmap(self.goodIcon.pixmap(QSize(13, 13))) self.badIcon = QIcon(self.style().standardIcon(QStyle.SP_MessageBoxCritical)) self.badPix = QPixmap(self.badIcon.pixmap(QSize(13, 13))) self.processingIcon = QIcon(self.style().standardIcon(QStyle.SP_ArrowRight)) self.processingPix = QPixmap(self.processingIcon.pixmap(QSize(13, 13))) self.removeIcon = QIcon(self.style().standardIcon(QStyle.SP_DockWidgetCloseButton)) self.removePix = QPixmap(self.removeIcon.pixmap(QSize(19, 19))) self.folderIcon = QIcon(self.style().standardIcon(QStyle.SP_FileDialogNewFolder)) self.folderPix = QPixmap(self.folderIcon.pixmap(QSize(19, 19))) self.pbList = [] self.chList = [] self.lblList = [] self.rmbList = [] #self.newFolders = [] self.initUI() def initUI(self): self.resize(720, 300) self.setWindowTitle('FFMpeg Python Compressor') self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(11) #COMBOBOX LABELS self.gridLayoutControlls = QGridLayout() self.codecLabel = QLabel('Codec', self) self.codecLabel.setMinimumHeight(13) self.alphaLabel = QLabel('Alpha' , self) self.alphaLabel.setMinimumHeight(13) self.frameRateLabel = QLabel('Frame Rate' , self) self.frameRateLabel.setMinimumHeight(13) self.gridLayoutControlls.addWidget(self.codecLabel, 0, 0, 1, 1) self.gridLayoutControlls.addWidget(self.alphaLabel, 0, 1, 1, 1) self.gridLayoutControlls.addWidget(self.frameRateLabel, 0, 2, 1, 1) #COMBOBOXES AND COMPRESS BUTTON self.codecComboBox = QComboBox(self) self.codecComboBox.setMinimumSize(80,23) self.codecComboBox.addItem("UT Video") self.codecComboBox.activated[str].connect(self.chooseCodec) self.alphaComboBox = QComboBox(self) self.alphaComboBox.setMinimumSize(80,23) self.alphaComboBox.addItem("No Alpha") self.alphaComboBox.addItem("with Alpha") self.alphaComboBox.activated[str].connect(self.chooseAlpha) self.frameRateComboBox = QComboBox(self) self.frameRateComboBox.setMinimumSize(80,23) self.frameRateComboBox.addItem("23.976") self.frameRateComboBox.addItem("24.00") self.frameRateComboBox.addItem("29.97") self.frameRateComboBox.addItem("30.00") self.frameRateComboBox.setCurrentIndex(1) self.frameRateComboBox.activated[str].connect(self.chooseFrameRate) self.compressButton = QPushButton('Compress', self) self.compressButton.setMinimumSize(80,23) self.compressButton.clicked[bool].connect(self.compressPress) self.gridLayoutControlls.addWidget(self.codecComboBox, 1, 0, 1, 1) self.gridLayoutControlls.addWidget(self.alphaComboBox, 1, 1, 1, 1) self.gridLayoutControlls.addWidget(self.frameRateComboBox, 1, 2, 1, 1) self.gridLayoutControlls.addWidget(self.compressButton, 1, 3, 1, 1) #RADIO BUTTON GROUP self.groupBox = QButtonGroup(self) self.radio1 = QRadioButton('Output file name from Folder name', self) self.radio1.setMinimumSize(80,25) self.radio2 = QRadioButton('Output file name from File name', self) self.radio2.setMinimumSize(80,25) self.radio1.setChecked(True) self.groupBox.addButton(self.radio1,1) self.groupBox.addButton(self.radio2,2) self.groupBox.buttonClicked[int].connect(self.radioBtnState) self.gridLayoutControlls.addWidget(self.radio1, 2, 0, 1, 2) self.gridLayoutControlls.addWidget(self.radio2, 2, 2, 1, 2) #LINE self.line = QFrame(self) self.line.setLineWidth(2) self.line.setMinimumHeight(3) self.line.setFrameShape(QFrame.HLine) self.line.setFrameShadow(QFrame.Sunken) self.gridLayoutControlls.addWidget(self.line, 3, 0, 1, 4) #PROGRESS BAR self.gridLayoutProgress = QGridLayout() self.gridLayoutProgress.setVerticalSpacing(11) self.gridLayoutProgress.setHorizontalSpacing(6) self.gridLayoutProgress.setSizeConstraint(QLayout.SetNoConstraint) self.removeGroupBox = QButtonGroup(self) self.addProgressBarUI(self.inList) self.removeGroupBox.buttonClicked[int].connect(self.removeButtonClicked) #ADD MORE AREA self.gridLayoutAddMore = QGridLayout() self.gridLayoutAddMore.setContentsMargins(0, 0, 0, 0) self.dragAndDropLabel_1 = QLabel("Drag and Drop folders here", self) self.dragAndDropLabel_1.setMinimumSize(QSize(120, 40)) self.dragAndDropLabel_1.setAlignment(Qt.AlignCenter) self.dragAndDropLabel_2 = QLabel("", self) self.dragAndDropLabel_2.setFixedSize(QSize(20, 40)) self.dragAndDropLabel_2.setAlignment(Qt.AlignCenter) self.dragAndDropLabel_2.setPixmap(self.folderPix) sI = QSpacerItem(40, 40,QSizePolicy.Expanding, QSizePolicy.Minimum) sI2 = QSpacerItem(40, 40,QSizePolicy.Expanding, QSizePolicy.Minimum) self.gridLayoutAddMore.addItem(sI, 1, 0, 1, 1) self.gridLayoutAddMore.addWidget(self.dragAndDropLabel_2, 1, 1, 1, 1) self.gridLayoutAddMore.addWidget(self.dragAndDropLabel_1, 1, 2, 1, 1) self.gridLayoutAddMore.addItem(sI2, 1, 3, 1, 1) #DEBUG AREA self.gridLayoutDebug = QGridLayout() self.line_2 = QFrame(self) self.line_2.setLineWidth(2) self.line_2.setFrameShape(QFrame.HLine) self.line_2.setFrameShadow(QFrame.Sunken) self.exploreOutputBtn = QPushButton('Explore Output',self) self.exploreOutputBtn.clicked[bool].connect(self.exploreOutput) self.hideShowLog = QPushButton('Show Log',self) self.hideShowLog.setCheckable(True) self.hideShowLog.clicked[bool].connect(self.showDebugLog) #self.hideShowLog.setMinimumSize(QSize(0, 20)) self.logText = QPlainTextEdit('',self) self.logText.setReadOnly(True) self.logText.hide() self.spacerItem = QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Expanding) self.gridLayoutDebug.addWidget(self.line_2, 0, 0, 1, 1) self.gridLayoutDebug.addWidget(self.exploreOutputBtn, 1, 0, 1, 1) self.gridLayoutDebug.addWidget(self.hideShowLog, 2, 0, 1, 1) self.gridLayoutDebug.addWidget(self.logText, 3, 0, 1, 1) self.gridLayoutDebug.addItem(self.spacerItem, 4, 0, 1, 1) self.verticalLayout.addLayout(self.gridLayoutControlls) self.verticalLayout.addLayout(self.gridLayoutProgress) self.verticalLayout.addLayout(self.gridLayoutAddMore) self.verticalLayout.addLayout(self.gridLayoutDebug) # Enable dragging and dropping onto the GUI self.setAcceptDrops(True) #QtCore.QMetaObject.connectSlotsByName(self) self.show() self.setMinimumSize(self.size()) self.threadpool = QThreadPool() self.threadpool.setMaxThreadCount(1) print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) ''' Progress bar populate function ''' def addProgressBarUI(self, arr): pbCount = len(self.pbList) for i in range(len(arr)): tempCheckBox = QCheckBox(self) tempCheckBox.setChecked(True) tempCheckBox.setMinimumSize(14,21) tempRemoveButton = QPushButton(self) tempRemoveButton.setIcon(self.removeIcon) tempRemoveButton.setFlat(True) tempRemoveButton.setIconSize(QSize(19,19)) tempRemoveButton.setFixedSize(QSize(19,21)) tempPB = QProgressBar(self) tempPB.setMinimumSize(50,21) tempPB.setMinimum(0) tempPB.setMaximum(100) tempPB.setTextVisible(True) tempPB.setFormat(str(arr[i])+" %p%") tempPB.setAlignment(Qt.AlignCenter) tempPB.setValue(0) if i==0: self.defaulStyle = tempPB.styleSheet() tempStatusLabel = QLabel(self) tempStatusLabel.setPixmap(self.okPix) tempStatusLabel.setMinimumSize(13,21) self.gridLayoutProgress.addWidget(tempCheckBox, pbCount+i, 0, 1, 1) self.gridLayoutProgress.addWidget(tempPB, pbCount+i, 1, 1, 1) self.gridLayoutProgress.addWidget(tempStatusLabel, pbCount+i, 2, 1, 1) self.gridLayoutProgress.addWidget(tempRemoveButton, pbCount+i, 3, 1, 1) self.removeGroupBox.addButton(tempRemoveButton, pbCount+i) self.pbList.append(tempPB) self.chList.append(tempCheckBox) self.lblList.append(tempStatusLabel) self.rmbList.append(tempRemoveButton) ''' Drag+Drop Functions ''' # The following three methods set up dragging and dropping for the app def dragEnterEvent(self, e): if e.mimeData().hasUrls: e.accept() else: e.ignore() def dragMoveEvent(self, e): if e.mimeData().hasUrls: e.accept() else: e.ignore() def dropEvent(self, e): """ Drop files directly onto the widget File locations are stored in fname :param e: :return: """ newFolders = [] if e.mimeData().hasUrls: e.setDropAction(Qt.CopyAction) e.accept() # Workaround for OSx dragging and dropping for url in e.mimeData().urls(): if op_sys == 'Darwin': #check for dir here as well fname = str(NSURL.URLWithString_(str(url.toString())).filePathURL().path()) else: fname = str(url.toLocalFile()) if os.path.isdir(fname) == True: newFolders.append(fname) #print(fname) #self.fname = fname #print(self.fname) #self.load_image() self.addNewFolders(newFolders) self.inList = self.inList + newFolders else: e.ignore() def addNewFolders(self, newFolders): self.addProgressBarUI(newFolders) self.setMinimumHeight(self.height()+len(newFolders)*32) #self.resize(self.width(),self.height()+200) self.update() self.adjustSize() self.setMinimumSize(self.size()) ''' Button Functions ''' def chooseAlpha(self, text): switcher={ "No Alpha":False, "with Alpha":True } self.alpha = switcher.get(text,"Invalid day of week") #print (self.alpha) def chooseCodec(self, text): switcher={ "UT Video":"utvideo" } self.codec = switcher.get(text,"Invalid day of week") #print (self.codec) def chooseFrameRate(self, text): self.frameRate = float(text) #print (self.frameRate) def currentData(self, widget): return widget.currentText() def radioBtnState(self, text): switcher={ 1:'Folder', 2:'File' } self.nameFrom = switcher.get(text,"Invalid day of week") #print(self.nameFrom) def removeButtonClicked(self, i): #print('remove trigger on id '+str(i)) #self.pbList.pop(i) ''' self.pbList[i].hide() self.chList[i].setChecked(False) self.chList[i].hide() self.lblList[i].hide() self.rmbList[i].hide() ''' print(self.gridLayoutProgress.rowCount()) self.pbList[i].setParent(None) self.chList[i].setChecked(False) self.chList[i].setParent(None) self.lblList[i].setParent(None) self.rmbList[i].setParent(None) self.removeGroupBox.removeButton(self.rmbList[i]) self.gridLayoutProgress.removeWidget(self.pbList[i]) self.gridLayoutProgress.removeWidget(self.chList[i]) self.gridLayoutProgress.removeWidget(self.lblList[i]) self.gridLayoutProgress.removeWidget(self.rmbList[i]) self.gridLayoutProgress.invalidate() self.gridLayoutProgress = QGridLayout() self.gridLayoutProgress.setVerticalSpacing(11) self.gridLayoutProgress.setHorizontalSpacing(6) self.gridLayoutProgress.setSizeConstraint(QLayout.SetDefaultConstraint) self.verticalLayout.insertLayout(1,self.gridLayoutProgress) print(self.gridLayoutProgress.rowCount()) ''' print(self.pbList) print(self.chList) print(self.lblList) print(self.rmbList) ''' self.pbList.pop(i) self.chList.pop(i) self.lblList.pop(i) self.rmbList.pop(i) self.inList.pop(i) #clear the gridLayout for j in reversed(range(len(self.pbList))): self.pbList[j].setParent(None) self.chList[j].setParent(None) self.lblList[j].setParent(None) self.rmbList[j].setParent(None) #reorder the gridLayout for j in range(len(self.pbList)): self.gridLayoutProgress.addWidget(self.chList[j], j, 0, 1, 1) self.gridLayoutProgress.addWidget(self.pbList[j], j, 1, 1, 1) self.gridLayoutProgress.addWidget(self.lblList[j], j, 2, 1, 1) self.gridLayoutProgress.addWidget(self.rmbList[j], j, 3, 1, 1) self.removeGroupBox.setId(self.rmbList[j],j) self.setMinimumHeight(self.height()-30) #self.setMinimumHeight(100) self.adjustSize() self.setMinimumSize(self.size()) print(self.gridLayoutProgress.rowCount()) #self.correctSize() ''' for j in range(len(self.removeGroupBox.buttons())): button = self.removeGroupBox.buttons()[j] #print(button) #print('original id '+str(self.removeGroupBox.id(button))) #print('new id '+str(j)) self.removeGroupBox.setId(button,j) ''' def correctSize(self): self.logText.show() self.gridLayoutDebug.removeItem(self.spacerItem) self.adjustSize() self.setMinimumSize(self.size()) self.repaint() self.gridLayoutDebug.addItem(self.spacerItem) self.logText.hide() self.setMinimumHeight(100) self.adjustSize() self.setMinimumSize(self.size()) def showDebugLog(self, bol): if bol: self.logText.show() self.hideShowLog.setText('Hide Log') self.gridLayoutDebug.removeItem(self.spacerItem) self.adjustSize() #self.resize(self.width(), self.height()+80) self.setMinimumSize(self.size()) else: self.gridLayoutDebug.addItem(self.spacerItem) self.logText.hide() self.hideShowLog.setText('Show Log') self.setMinimumHeight(100) self.adjustSize() self.setMinimumSize(self.size()) #self.resize(self.width(), 100) #self.setGeometry(0,0,self.width(),100) ''' Execution Functions ''' def execute_this_fn(self, path, codec, alpha, frameRate, nameFrom, i, progress_callback, errorFFMPEG_callback): #print(path) pyCompression = pyFFMEGCompress(path, codec, alpha, frameRate, nameFrom) ffProcess = pyCompression.ffmpegCompress() self.lblList[i].setPixmap(self.processingPix) #with kwargs kwargs = {'progress_callback':progress_callback, 'errorFFMPEG_callback':errorFFMPEG_callback} pyCompression.printProcess(ffProcess, **kwargs) return (pyCompression.debugString,pyCompression.error,i) def printOutput(self, s): print("Printing output "+ str(s)) def threadComplete(self, r): #print("THREAD COMPLETE! WITH ERROR " + str(r[2]) ) if r[1] == False: self.lblList[r[2]].setPixmap(self.goodPix) self.pbList[r[2]].setStyleSheet("QProgressBar::chunk {background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #44dd14,stop: 0.4999 #39c10f,stop: 0.5 #39c10f,stop: 1 #39c10f );border-radius: 3px; border: 1px solid #29880b;}QProgressBar{color:white}") self.pbList[r[2]].setValue(100) def errorPB(self, err): for i in range(len(self.pbList)): if self.pbList[i].format() == err: self.pbList[i].setValue(100) self.pbList[i].setStyleSheet("QProgressBar::chunk {background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #FF0350,stop: 0.4999 #FF0020,stop: 0.5 #FF0019,stop: 1 #FF0000 );border-radius: 3px; border: 1px solid #a60233;}QProgressBar{color:white}") self.pbList[i].setFormat(self.pbList[i].format()+" - Error") self.chList[i].setChecked(False) self.lblList[i].setPixmap(self.badPix) def resetProgressBar(self, pb, text, lbl): pb.setValue(0) pb.setFormat(text + ' %p%') pb.setStyleSheet(self.defaulStyle) lbl.setPixmap(self.okPix) def compressPress(self): for i in range(len(self.pbList)): if self.chList[i].isChecked(): self.resetProgressBar(self.pbList[i],self.inList[i],self.lblList[i]) worker = Worker(self.execute_this_fn, self.inList[i], self.codec, self.alpha, self.frameRate, self.nameFrom, i) # Any other args, kwargs are passed to the run function #worker.signals.result.connect(self.printOutput) worker.signals.result.connect(self.logText.appendPlainText) worker.signals.progress.connect(self.pbList[i].setValue) worker.signals.errorFFMPEG.connect(self.errorPB) worker.signals.error.connect(self.errorPB) worker.signals.finished.connect(self.threadComplete) #worker.signals.finished.connect(self.logText.appendPlainText) # Execute self.threadpool.start(worker) def exploreOutput(self): FILEBROWSER_PATH = os.path.join(os.getenv('WINDIR'), 'explorer.exe') explorePath = os.path.normpath('C:\\ExportedMOVs') subprocess.run([FILEBROWSER_PATH, explorePath])
class Classbar(QWidget): def __init__(self, state): super().__init__() self.state = state self.state.classbar = self self.classes = {} self.classes_group = QButtonGroup() self.class_label = QLabel('Current class: \n') self.layout = None self.init_gui() classes = list(self.state.classes) self.state.classes = [] for c in classes: self.add_class(c) def init_gui(self): self.setMinimumHeight(400) self.setMaximumWidth(150) wrapper_layout = QVBoxLayout() box = QGroupBox('Classes') self.layout = QVBoxLayout() wrapper_layout.setAlignment(QtCore.Qt.AlignTop) self.layout.setAlignment(QtCore.Qt.AlignTop) box.setLayout(self.layout) wrapper_layout.addWidget(box) self.layout.addWidget(self.class_label) self._init_add_remove_buttons(self.layout) self.setLayout(wrapper_layout) def _init_add_remove_buttons(self, layout): box = QGroupBox() box.setMaximumHeight(50) layout.addWidget(box) layout = QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) box.setLayout(layout) add_button = QPushButton('+') remove_button = QPushButton('-') add_button.clicked.connect(self.trigger_add_class_dialog) remove_button.clicked.connect( lambda: self.remove_class(self.state.active_class)) layout.addWidget(add_button) layout.addWidget(remove_button) return box def add_class(self, name: str): if name in self.classes.keys(): return self.classes[name] = QRadioButton(name) add_class = self.classes[name] self.classes_group.addButton(add_class) self.layout.addWidget(add_class) self.state.classes.append(name) add_class.clicked.connect(lambda: self.set_active_class(name)) def remove_class(self, name: str): if not name: return if self.state.active_class == name: self.set_active_class('') self.state.classes.remove(name) remove_class = self.classes[name] del self.classes[name] self.classes_group.removeButton(remove_class) self.layout.removeWidget(remove_class) remove_class.deleteLater() def trigger_add_class_dialog(self): new_class, ok = QInputDialog.getText( self, 'New Class', 'Enter the name of the new class:') if ok: self.add_class(new_class) self.state.display.source_label.setFocus() def set_active_class(self, name): self.class_label.setText('Current Class: \n' + name) self.state.active_class = name
class AttGenW(QGridLayout): _code = { 1: "???", 11: "0~0.5", 12: "0.5~1.0", 13: "1.0~2.0", 14: "2.0~5.0", 15: "5.0以", 21: "0~0.5", 22: "0.5~1.0", 23: "1.0~2.0", 24: "2.0~3.0", 25: "3.0~4.0", 26: "4.0~5.0", 27: "5.0以上", 31: "0~0.5m未満", 32: "0.5~3.0", 33: "3.0~5.0", 34: "5.0~10.0", 35: "10.0~20.0", 36: "20.0以上", 41: "0~0.3", 42: "0.3~0.5", 43: "0.5~1.0", 44: "1.0~3.0", 45: "3.0~5.0", 46: "5.0~10.0", 47: "10.0~20.0", 48: "20.0以上", 99: "XXX" } _color = { 1: QColor(0, 255, 255), 11: QColor(255, 153, 0), 12: QColor(0, 255, 85), 13: QColor(0, 255, 255), 14: QColor(0, 0, 255), 15: QColor(102, 0, 255), 21: QColor(255, 153, 0), 22: QColor(0, 255, 85), 23: QColor(0, 255, 255), 24: QColor(0, 0, 255), 25: QColor(255, 0, 102), 26: QColor(255, 0, 255), 27: QColor(102, 0, 255), 31: QColor(255, 153, 0), 32: QColor(0, 255, 85), 33: QColor(0, 255, 255), 34: QColor(0, 0, 255), 35: QColor(255, 0, 102), 36: QColor(255, 0, 255), 41: QColor(255, 153, 0), 42: QColor(0, 255, 85), 43: QColor(0, 255, 255), 44: QColor(0, 0, 255), 45: QColor(255, 0, 102), 46: QColor(255, 0, 255), 47: QColor(102, 0, 255), 48: QColor(102, 102, 255), 99: QColor(0, 0, 0) } tableUpdate = pyqtSignal(int) selUpdate = pyqtSignal() useUpdate = pyqtSignal() colUpdate = pyqtSignal(int) def __init__(self): super(AttGenW, self).__init__() self.newrow = 0 self.table = {} self.create_widgets() self.set_widgets() self.layout_widgets() self.create_connections() def create_widgets(self): self.title = QLabel("* Generate Attributes *") self.set1 = QPushButton("1段階") self.set5 = QPushButton("5段階") self.set6 = QPushButton("6段階") self.set7 = QPushButton("7段階") self.set8 = QPushButton("8段階") self.clr = QPushButton("clear") self.shwA = QPushButton("all") self.shwS = QPushButton("use") self.shwN = QPushButton("none") self.bg = QButtonGroup() def set_widgets(self): color_label(self.title, QColor("black"), QColor("white")) color_button(self.set1, QColor(255, 0, 0)) color_button(self.set5, QColor(255, 0, 0)) color_button(self.set6, QColor(255, 0, 0)) color_button(self.set7, QColor(255, 0, 0)) color_button(self.set8, QColor(255, 0, 0)) color_button(self.shwA, QColor(255, 255, 0)) color_button(self.shwS, QColor(255, 255, 0)) color_button(self.shwN, QColor(255, 255, 0)) color_button(self.clr, QColor(255, 0, 0)) def layout_widgets(self): self.addWidget(self.title, 0, 0, 1, 8) self.addWidget(self.shwA, 1, 0) self.addWidget(self.shwS, 1, 1) self.addWidget(self.shwN, 1, 2) self.addWidget(self.set1, 2, 0) self.addWidget(self.set5, 2, 1) self.addWidget(self.set6, 2, 2) self.addWidget(self.set7, 2, 3) self.addWidget(self.set8, 2, 4) self.addWidget(self.clr, 2, 7) self.addWidget(QLabel("use"), 3, 0) self.addWidget(QLabel("show"), 3, 1) self.addWidget(QLabel("new"), 3, 2) self.addWidget(QLabel("old"), 3, 3) self.addWidget(QLabel("pixs"), 3, 4) self.addWidget(QLabel("RGB"), 3, 5) self.addWidget(QLabel("HSV"), 3, 6) def create_connections(self): self.set1.clicked.connect(self.gen1) self.set5.clicked.connect(self.gen5) self.set6.clicked.connect(self.gen6) self.set7.clicked.connect(self.gen7) self.set8.clicked.connect(self.gen8) self.clr.clicked.connect(self.clr_table) self.shwA.clicked.connect(self.show_all) self.shwS.clicked.connect(self.show_selected) self.shwN.clicked.connect(self.show_none) def clr_table(self): if self.table: for k, v in self.table.items(): if k[1] == "act": self.bg.removeButton(v) if k[1] not in ("att", "col", "idx"): v.hide() v.destroy() self.table = {} self.tableUpdate.emit(0) self.newrow = 0 def gen1(self): if self.table != {}: return for i in range(1, 2): self.add_att(i) self.add_ex() self.table[(0, "sel")].setChecked(True) self.tableUpdate.emit(1) def gen5(self): if self.table != {}: return for i in range(11, 16): self.add_att(i) self.add_ex() self.table[(0, "sel")].setChecked(True) self.tableUpdate.emit(5) def gen6(self): if self.table != {}: return for i in range(31, 37): self.add_att(i) self.add_ex() self.table[(0, "sel")].setChecked(True) self.tableUpdate.emit(6) def gen7(self): if self.table != {}: return for i in range(21, 28): self.add_att(i) self.add_ex() self.table[(0, "sel")].setChecked(True) self.tableUpdate.emit(7) def gen8(self): if self.table != {}: return for i in range(41, 49): self.add_att(i) self.add_ex() self.table[(0, "sel")].setChecked(True) self.tableUpdate.emit(8) def add_ex(self): self.add_att(99) def add_att(self, i): off = 4 idx = self.newrow self.newrow += 1 att = self._code[i] self.table[(idx, "idx")] = i self.table[(idx, "att")] = att self.table[(idx, "col")] = self._color[i] self.table[(idx, "sel")] = QRadioButton() self.table[(idx, "act")] = QCheckBox() self.table[(idx, "pix")] = QLabel("0") self.table[(idx, "new")] = QPushButton(att) self.table[(idx, "old")] = QPushButton(att) self.table[(idx, "rgb")] = QLabel() self.table[(idx, "hsv")] = QLabel() self.table[(idx, "hsl")] = QLabel() self.bg.addButton(self.table[(idx, "sel")], i) color_button(self.table[(idx, "new")], self.table[(idx, "col")]) self.addWidget(self.table[(idx, "sel")], idx + off, 0) self.addWidget(self.table[(idx, "act")], idx + off, 1) self.addWidget(self.table[(idx, "new")], idx + off, 2) self.addWidget(self.table[(idx, "old")], idx + off, 3) self.addWidget(self.table[(idx, "pix")], idx + off, 4) self.addWidget(self.table[(idx, "rgb")], idx + off, 5) self.addWidget(self.table[(idx, "hsv")], idx + off, 6) self.table[(idx, "new")].clicked.connect(lambda: self.button_color1(idx)) self.table[(idx, "old")].clicked.connect(lambda: self.button_color2(idx)) self.table[(idx, "act")].clicked.connect(self.selUpdate.emit) self.table[(idx, "sel")].clicked.connect(self.useUpdate.emit) print("ADDATT", i) def set_old_col(self, idx, col): color_button(self.table[(idx, "old")], col) self.table[(idx, "rgb")].setText(str(col.getRgb()[:3])) self.table[(idx, "hsv")].setText(str(col.getHsv()[:3])) def select_color(self, idx, col=None, auto=False): if not col: forbidden = { self.table[i, "col"].getRgb()[:3] for i in range(self.newrow) } col = get_color(auto=auto, forbidden=forbidden) if col is None: return self.table[(idx, "col")] = col color_button(self.table[idx, "new"], col) self.colUpdate.emit(idx) def button_color1(self, idx): self.select_color(idx) def button_color2(self, idx): self.random_color(idx) def random_color(self, idx, col=None): self.select_color(idx, auto=True) def show_all(self): for idx in range(self.newrow): if self.table[(idx, "idx")] < 99: self.table[(idx, "act")].setChecked(True) self.selUpdate.emit() def show_selected(self): for idx in range(self.newrow): self.table[(idx, "act")].setChecked(self.table[(idx, "sel")].isChecked()) self.selUpdate.emit() def show_none(self): for idx in range(self.newrow): self.table[(idx, "act")].setChecked(False) self.selUpdate.emit() def selected(self): try: return self.bg.checkedId() except: return None def select(self, att): for idx in range(self.newrow): if self.table[(idx, "idx")] == att: self.table[(idx, "sel")].setChecked(True) def next_att(self): for i in range(self.newrow - 1): if self.table[i, "sel"].isChecked(): self.table[i + 1, "sel"].setChecked(True) break else: if self.table: self.table[0, "sel"].setChecked(True)
class TabBarWidget(QWidget): """ A vertical tab bar widget using tool buttons as for tabs. """ currentChanged = Signal(int) def __init__(self, parent=None, **kwargs): QWidget.__init__(self, parent, **kwargs) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) self.setLayout(layout) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.__tabs = [] self.__currentIndex = -1 self.__changeOnHover = False self.__iconSize = QSize(26, 26) self.__group = QButtonGroup(self, exclusive=True) self.__group.buttonPressed[QAbstractButton].connect( self.__onButtonPressed ) self.setMouseTracking(True) self.__sloppyButton = None self.__sloppyRegion = QRegion() self.__sloppyTimer = QTimer(self, singleShot=True) self.__sloppyTimer.timeout.connect(self.__onSloppyTimeout) def setChangeOnHover(self, changeOnHover): """ If set to ``True`` the tab widget will change the current index when the mouse hovers over a tab button. """ if self.__changeOnHover != changeOnHover: self.__changeOnHover = changeOnHover def changeOnHover(self): """ Does the current tab index follow the mouse cursor. """ return self.__changeOnHover def count(self): """ Return the number of tabs in the widget. """ return len(self.__tabs) def addTab(self, text, icon=None, toolTip=None): """ Add a new tab and return it's index. """ return self.insertTab(self.count(), text, icon, toolTip) def insertTab(self, index, text, icon=None, toolTip=None): """ Insert a tab at `index` """ button = TabButton(self, objectName="tab-button") button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) button.setIconSize(self.__iconSize) button.setMouseTracking(True) self.__group.addButton(button) button.installEventFilter(self) tab = _Tab(text, icon, toolTip, button, None, None) self.layout().insertWidget(index, button) self.__tabs.insert(index, tab) self.__updateTab(index) if self.currentIndex() == -1: self.setCurrentIndex(0) return index def removeTab(self, index): """ Remove a tab at `index`. """ if index >= 0 and index < self.count(): tab = self.__tabs.pop(index) layout_index = self.layout().indexOf(tab.button) if layout_index != -1: self.layout().takeAt(layout_index) self.__group.removeButton(tab.button) tab.button.removeEventFilter(self) if tab.button is self.__sloppyButton: self.__sloppyButton = None self.__sloppyRegion = QRegion() tab.button.deleteLater() tab.button.setParent(None) if self.currentIndex() == index: if self.count(): self.setCurrentIndex(max(index - 1, 0)) else: self.setCurrentIndex(-1) def setTabIcon(self, index, icon): """ Set the `icon` for tab at `index`. """ self.__tabs[index] = self.__tabs[index]._replace(icon=icon) self.__updateTab(index) def setTabToolTip(self, index, toolTip): """ Set `toolTip` for tab at `index`. """ self.__tabs[index] = self.__tabs[index]._replace(toolTip=toolTip) self.__updateTab(index) def setTabText(self, index, text): """ Set tab `text` for tab at `index` """ self.__tabs[index] = self.__tabs[index]._replace(text=text) self.__updateTab(index) def setTabPalette(self, index, palette): """ Set the tab button palette. """ self.__tabs[index] = self.__tabs[index]._replace(palette=palette) self.__updateTab(index) def setCurrentIndex(self, index): """ Set the current tab index. """ if self.__currentIndex != index: self.__currentIndex = index self.__sloppyRegion = QRegion() self.__sloppyButton = None if index != -1: self.__tabs[index].button.setChecked(True) self.currentChanged.emit(index) def currentIndex(self): """ Return the current index. """ return self.__currentIndex def button(self, index): """ Return the `TabButton` instance for index. """ return self.__tabs[index].button def setIconSize(self, size): if self.__iconSize != size: self.__iconSize = size for tab in self.__tabs: tab.button.setIconSize(self.__iconSize) def __updateTab(self, index): """ Update the tab button. """ tab = self.__tabs[index] b = tab.button if tab.text: b.setText(tab.text) if tab.icon is not None and not tab.icon.isNull(): b.setIcon(tab.icon) if tab.palette: b.setPalette(tab.palette) def __onButtonPressed(self, button): for i, tab in enumerate(self.__tabs): if tab.button is button: self.setCurrentIndex(i) break def __calcSloppyRegion(self, current): """ Given a current mouse cursor position return a region of the widget where hover/move events should change the current tab only on a timeout. """ p1 = current + QPoint(0, 2) p2 = current + QPoint(0, -2) p3 = self.pos() + QPoint(self.width()+10, 0) p4 = self.pos() + QPoint(self.width()+10, self.height()) return QRegion(QPolygon([p1, p2, p3, p4])) def __setSloppyButton(self, button): """ Set the current sloppy button (a tab button inside sloppy region) and reset the sloppy timeout. """ if not button.isChecked(): self.__sloppyButton = button delay = self.style().styleHint(QStyle.SH_Menu_SubMenuPopupDelay, None) # The delay timeout is the same as used by Qt in the QMenu. self.__sloppyTimer.start(delay) else: self.__sloppyTimer.stop() def __onSloppyTimeout(self): if self.__sloppyButton is not None: button = self.__sloppyButton self.__sloppyButton = None if not button.isChecked(): index = [tab.button for tab in self.__tabs].index(button) self.setCurrentIndex(index) def eventFilter(self, receiver, event): if event.type() == QEvent.MouseMove and \ isinstance(receiver, TabButton): pos = receiver.mapTo(self, event.pos()) if self.__sloppyRegion.contains(pos): self.__setSloppyButton(receiver) else: if not receiver.isChecked(): index = [tab.button for tab in self.__tabs].index(receiver) self.setCurrentIndex(index) #also update sloppy region if mouse is moved on the same icon self.__sloppyRegion = self.__calcSloppyRegion(pos) return QWidget.eventFilter(self, receiver, event) def leaveEvent(self, event): self.__sloppyButton = None self.__sloppyRegion = QRegion() return QWidget.leaveEvent(self, event)
class SAFTVRMieParametersWidget(ParametersWidget): """ Widget for changing interaction coefficients and pure fluid parameters for the SAFT-VR Mie model """ def __init__(self, data, settings_name, parent=None): super().__init__(data, settings_name, parent) loadUi("gui/layouts/saftvrmie_parameters.ui", self) self.tab_stack_indices = {} self.list_name = None self.component_id = None self.pure_param_m_label.setText("m:") self.pure_param_sigma_label.setText("\u03C3:") self.pure_param_epsilon_label.setText("\u03B5 / k:") self.pure_param_lambda_a_label.setText("\u03BB a:") self.pure_param_lambda_r_label.setText("\u03BB r:") # Validators for input self.float_validator = FloatValidator() self.set_validators() self.pure_param_m_edit.editingFinished.connect(self.save_pure_fluid_params) self.pure_param_sigma_edit.editingFinished.connect(self.save_pure_fluid_params) self.pure_param_epsilon_edit.editingFinished.connect(self.save_pure_fluid_params) self.pure_param_lambda_a_edit.editingFinished.connect(self.save_pure_fluid_params) self.pure_param_lambda_r_edit.editingFinished.connect(self.save_pure_fluid_params) self.component_btngroup = QButtonGroup() self.component_btngroup.buttonClicked.connect(self.show_component_pure_params) self.pure_params_frame.hide() self.composition_list.currentItemChanged.connect(self.on_chosen_composition_list) def init_widget(self, data, settings_name): """ Populates the list with the available compositions, calculates interaction parameters, and creates a table to display the matrix :param data: Session data :param settings_name: Name of the current model setup :return: """ self.settings = data["Model setups"][settings_name] self.thermopack = get_thermopack(category=self.settings["Model category"]) list_names = [] for i in range(self.composition_list.count()): list_names.append(self.composition_list.item(i).text()) for list_name in self.component_lists.keys(): if list_name in self.settings["Parameters"].keys(): if "Pure fluid parameters" not in self.settings["Parameters"][list_name].keys(): self.settings["Parameters"][list_name]["Pure fluid parameters"] = {} else: self.settings["Parameters"][list_name] = { "Coefficient matrices": {}, "Pure fluid parameters": {} } existing_matrices = self.settings["Parameters"][list_name]["Coefficient matrices"].keys() if "SAFT-VR Mie Epsilon" not in existing_matrices: # Create one tab for each list in QTabWidget self.calculate_matrix_data(list_name) self.epsilon_table = self.get_table(list_name, "SAFT-VR Mie Epsilon") self.sigma_table = self.get_table(list_name, "SAFT-VR Mie Sigma") self.gamma_table = self.get_table(list_name, "SAFT-VR Mie Gamma") self.epsilon_table.itemChanged.connect( lambda item: self.change_coeff(item, "SAFT-VR Mie Epsilon")) self.sigma_table.itemChanged.connect( lambda item: self.change_coeff(item, "SAFT-VR Mie Sigma")) self.gamma_table.itemChanged.connect( lambda item: self.change_coeff(item, "SAFT-VR Mie Gamma")) tab_widget = SAFTVRMieTabWidget(self.epsilon_table, self.sigma_table, self.gamma_table) if list_name not in self.tab_stack_indices.keys(): index = self.tab_stack.addWidget(tab_widget) self.tab_stack_indices[list_name] = index self.init_composition_list() self.tab_stack.setCurrentIndex(0) self.pure_params_frame.hide() for button in self.component_btngroup.buttons(): self.component_btngroup.removeButton(button) self.component_btn_layout.removeWidget(button) button.hide() def set_validators(self): """ Sets a validator for input fields to ensure a valid float input """ self.pure_param_m_edit.setValidator(self.float_validator) self.pure_param_sigma_edit.setValidator(self.float_validator) self.pure_param_epsilon_edit.setValidator(self.float_validator) self.pure_param_lambda_a_edit.setValidator(self.float_validator) self.pure_param_lambda_r_edit.setValidator(self.float_validator) def save_pure_fluid_params(self): """ Saves the current pure fluid parameters to the session data """ if not self.list_name or not self.component_id: return m = float(self.pure_param_m_edit.text()) sigma = float(self.pure_param_sigma_edit.text()) epsilon = float(self.pure_param_epsilon_edit.text()) lambda_a = float(self.pure_param_lambda_a_edit.text()) lambda_r = float(self.pure_param_lambda_r_edit.text()) fluid_params = self.settings["Parameters"][self.list_name]["Pure fluid parameters"][self.component_id] fluid_params["M"] = m fluid_params["Sigma"] = sigma fluid_params["Epsilon"] = epsilon fluid_params["Lambda a"] = lambda_a fluid_params["Lambda r"] = lambda_r def show_component_pure_params(self, button): """ When a component is chosen, the corresponding pure fluid parameters are displayed :param button: Clicked radio button giving the chosen component """ comp_name = button.text() list_name = self.composition_list.currentItem().text() self.pure_params_frame.show() init_thermopack(self.thermopack, self.component_lists[list_name], list_name, self.settings) self.component_id = get_comp_id(self.component_lists[list_name], comp_name) comp_index = self.thermopack.getcompindex(self.component_id) m, sigma, eps_div_k, lambda_a, lambda_r = self.thermopack.get_pure_fluid_param(comp_index) self.pure_param_m_edit.setText(str(m)) self.pure_param_sigma_edit.setText(str(sigma)) self.pure_param_epsilon_edit.setText(str(eps_div_k)) self.pure_param_lambda_a_edit.setText(str(lambda_a)) self.pure_param_lambda_r_edit.setText(str(lambda_r)) def calculate_matrix_data(self, list_name): """ Calculates binary coefficients for all composition lists and stores them in the session data. :param list_name: str, Name of component list """ component_list = self.component_lists[list_name]["Names"] size = len(component_list) epsilon_matrix_data = np.zeros(shape=(size, size)) sigma_matrix_data = np.zeros(shape=(size, size)) gamma_matrix_data = np.zeros(shape=(size, size)) init_thermopack(self.thermopack, self.component_lists[list_name], list_name, self.settings) for row in range(size - 1): for col in range(row + 1, size): identity1 = self.component_lists[list_name]["Identities"][row] identity2 = self.component_lists[list_name]["Identities"][col] index1 = self.thermopack.getcompindex(identity1) index2 = self.thermopack.getcompindex(identity2) epsilon_kij = self.thermopack.get_eps_kij(index1, index2) sigma_lij = self.thermopack.get_sigma_lij(index1, index2) lr_gammaij = self.thermopack.get_lr_gammaij(index1, index2) # Symmetric matrices epsilon_matrix_data[row][col] = epsilon_kij epsilon_matrix_data[col][row] = epsilon_kij sigma_matrix_data[row][col] = sigma_lij sigma_matrix_data[col][row] = sigma_lij gamma_matrix_data[row][col] = lr_gammaij gamma_matrix_data[col][row] = lr_gammaij for row in range(size): epsilon_matrix_data[row][row] = 0.0 sigma_matrix_data[row][row] = 0.0 gamma_matrix_data[row][row] = 0.0 epsilon_matrix_data = epsilon_matrix_data.tolist() sigma_matrix_data = sigma_matrix_data.tolist() gamma_matrix_data = gamma_matrix_data.tolist() coeff_matrices = self.settings["Parameters"][list_name]["Coefficient matrices"] coeff_matrices["SAFT-VR Mie Epsilon"] = epsilon_matrix_data coeff_matrices["SAFT-VR Mie Sigma"] = sigma_matrix_data coeff_matrices["SAFT-VR Mie Gamma"] = gamma_matrix_data def on_chosen_composition_list(self, list_item): """ Show the correct tab with interaction coefficient matrices, and display radio buttons with all components in the given composition. :param list_item: Chosen composition """ self.list_name = list_item.text() if not self.list_name: return index = self.tab_stack_indices[self.list_name] self.tab_stack.setCurrentIndex(index) self.pure_params_frame.hide() component_list = self.component_lists[self.list_name]["Names"] for button in self.component_btngroup.buttons(): self.component_btngroup.removeButton(button) self.component_btn_layout.removeWidget(button) button.hide() if "Pure fluid parameters" not in self.settings["Parameters"][self.list_name].keys(): self.settings["Parameters"][self.list_name]["Pure fluid parameters"] = {} pure_fluid_params = self.settings["Parameters"][self.list_name]["Pure fluid parameters"] for comp_name in component_list: comp_id = get_comp_id(self.component_lists[self.list_name], comp_name) if comp_id not in pure_fluid_params.keys(): pure_fluid_params[comp_id] = { "M": None, "Sigma": None, "Epsilon": None, "Lambda a": None, "Lambda r": None } button = QRadioButton(comp_name) self.component_btngroup.addButton(button) self.component_btn_layout.addWidget(button) def change_coeff(self, item, table_name): """ Changes a value (interaction coefficient) in the given table :param item: New value :param table_name: Name of coefficient matrix (VDW K, HV1 A, SAFT-VR Mie Sigma, ...) """ row, col = item.row(), item.column() component_list = self.composition_list.currentItem().text() matrix = self.settings["Parameters"][component_list]["Coefficient matrices"][table_name] try: value = float(item.text().replace(",", ".")) except ValueError: previous_value = matrix[row][col] item.setText(str(previous_value)) return matrix[row][col] = value matrix[col][row] = value item.tableWidget().item(col, row).setText(str(value))