class PCheckBox(QFrame): """ Customized check box """ stateChanged = Signal(bool) def __init__(self, parent=None): super().__init__(parent) self.is_checked = False self.direction = 1 # 0: LeftToRight, 1: RightToLeft self.spacing = 5 self.between = True self.label = ElideLabel(self) self.label.setObjectName("checkBoxText") self.check = PCheck(self) self.check.stateChanged.connect(self.stateChanged) def set_direction(self, direction_): self.direction = direction_ if self.between: if self.direction == 0: self.label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) elif self.direction == 1: self.label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.update_positions() def set_text_alignment(self, align): self.label.setAlignment(align) def set_text_font(self, font): self.label.setFont(font) def set_text_color(self, color): self.label.setStyleSheet( f"#checkBoxText {{color: rgb({color.red()}, {color.green()}, {color.blue()})}}" ) def set_text(self, text_): self.label.setText(text_) def text(self): return self.label.text() def update_positions(self): if self.direction == 0: # LeftToRight, checkbox on the left self.check.setGeometry(0, 0, self.height(), self.height()) self.label.setGeometry(self.check.width() + self.spacing, 0, self.width() - self.check.width() - 5, self.height()) else: self.check.setGeometry(self.width() - self.height() - self.spacing, 0, self.height(), self.height()) self.label.setGeometry(0, 0, self.width() - self.check.width() - 5, self.height()) def resizeEvent(self, event): QFrame.resizeEvent(self, event) self.update_positions() font = self.label.font() font.setPointSize(self.height() / 2) self.label.setFont(font)
class AppCard(QFrame): """A Card widget derived from QFrame contains app icon, app name, app developer, app description, app rating, etc""" STYLES = STYLES Q_ENUM(STYLES) def __init__(self, parent=None): QFrame.__init__(self, parent) self.setFixedSize(200, 300) self.setObjectName("Card") self.setAutoFillBackground(True) self.appId = -1 self.appIcon = "./img/card/bird.png" self.appBack = "./img/card/card_back.png" self.appName = "PROS Smart CPQ for Manufacturing" self.appDev = "By PROS\nWeb apps" self.appRating = 0 self.appFeedback = 0 self.appState = 0 self.style_str = "border: 1px solid #ddd; background: qlineargradient(spread:pad, x1:0 y1:0, x2:1 y2:1, stop:0 rgba(255, 255, 255, 255), stop:1 rgba(225, 225, 225, 225));" self.appDesc = "Deliver Sales Automation and Profits Through Personalized Selling" self.setBackgroundImage(self.appBack) self.iconSize = 48, 48 self.iconMargins = 10, 10, 10, 10 self.iconFrameStyle = STYLES.STYLE_DEFAULT self.iconFrame = QLabel(self) self.iconFrame.setAutoFillBackground(True) self.iconFrame.setObjectName("IconFrame") self.iconFrame.setStyleSheet(self.iconFrameStyle) self.imgIcon = QLabel(self.iconFrame) self.imgIcon.setPixmap(QPixmap(self.appIcon)) self.imgIcon.setFixedSize(48, 48) self.imgIcon.setScaledContents(True) self.iconLayout = QHBoxLayout(self.iconFrame) self.iconLayout.setContentsMargins(10, 10, 10, 10) self.iconLayout.setAlignment(Qt.AlignLeft) self.iconLayout.addWidget(self.imgIcon, Qt.AlignLeft) self.iconFrame.setLayout(self.iconLayout) self.txtName = ElideLabel("", self) self.txtName.setText(self.appName) self.txtName.setFont(QFont("Roboto", 15)) self.txtName.setElideMode(1) self.txtName.setWordWrap(True) self.txtDev = ElideLabel("", self) self.txtDev.setWordWrap(True) self.txtDev.setText(self.appDev) self.txtDev.setFont(QFont("Roboto", 8)) self.txtDesc = ElideLabel("", self) self.txtDesc.setText(self.appDesc) self.txtDesc.setAlignment(Qt.AlignTop) self.txtDesc.setFont(QFont("Roboto", 10)) self.txtDesc.setElideMode(1) self.txtDesc.setWordWrap(True) self.starRating = StarRating(self) self.feedbackGiven = QLabel(self) self.feedbackGiven.setObjectName("Feedback") self.feedbackGiven.setStyleSheet("#Feedback{color: #ababab}") self.feedbackGiven.setFont(QFont("Roboto", 12)) self.feedbackGiven.setAlignment(Qt.AlignVCenter) self.feedbackGiven.setText("(" + str(self.appFeedback) + ")") self.btnInstall = Button('Install', self) self.btnInstall.clicked.connect(self.onInstallClicked) self.btnLaunch = Button('Launch', self) self.btnLaunch.setButtonType(Button.BUTTON_TYPE.LAUNCH) self.btnLaunch.clicked.connect(self.onLaunchClicked) self.btnLaunch.hide() self.btnUninstall = Button('Uninstall', self) self.btnUninstall.setButtonType(Button.BUTTON_TYPE.DELETE) self.btnUninstall.clicked.connect(self.onUninstallClicked) self.btnUninstall.hide() self.shadowEffect = QGraphicsDropShadowEffect(self) self.shadowEffect.setBlurRadius(9) self.shadowEffect.setColor(QColor(225, 225, 225)) self.shadowEffect.setOffset(5, 5) self.setGraphicsEffect(self.shadowEffect) self.frameLayout = QVBoxLayout(self) self.frameLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout = QVBoxLayout() self.mainLayout.setSpacing(5) self.mainLayout.setContentsMargins(10, 0, 10, 15) self.ratingLayout = QHBoxLayout() self.ratingLayout.setSpacing(5) self.ratingLayout.addWidget(self.starRating, 1, Qt.AlignLeft) self.ratingLayout.addWidget(self.feedbackGiven, 1, Qt.AlignLeft) self.separator = QFrame(self) self.separator.setObjectName("line") self.separator.setFixedHeight(2) self.separator.setFixedWidth(self.width()) self.separator.setFrameShape(QFrame.HLine) self.separator.setFrameShadow(QFrame.Sunken) self.btnLayout = QHBoxLayout() self.btnLayout.setContentsMargins(5, 5, 5, 10) self.btnLayout.setSpacing(20) self.btnLayout.setAlignment(Qt.AlignHCenter) self.btnLayout.addWidget(self.btnInstall) self.btnLayout.addWidget(self.btnUninstall) self.btnLayout.addWidget(self.btnLaunch) self.mainLayout.addWidget(self.txtName, 1, Qt.AlignLeft) self.mainLayout.addWidget(self.txtDev, 1, Qt.AlignLeft) self.mainLayout.addWidget(self.txtDesc, 3, Qt.AlignLeft) self.mainLayout.addLayout(self.ratingLayout, Qt.AlignLeft) self.frameLayout.addWidget(self.iconFrame, 1) self.frameLayout.addLayout(self.mainLayout) self.frameLayout.addWidget(self.separator) self.frameLayout.addLayout(self.btnLayout) self.setLayout(self.frameLayout) self.setAppState(self.appState) self.show() #automatically adjust child widgets' sizes based on the frame's geometry #this might affect widgets' sizes def autoAdjust(self): self.starRating.adjustWidthByHeight(self.height()/15) self.feedbackGiven.setFixedHeight(self.height()/16) self.iconFrame.setFixedHeight(self.height()/5) self.setIconSize(self.iconFrame.height() * 4 / 5, self.iconFrame.height() *4 / 5) mm = self.iconFrame.height() / (5 * 2) self.setIconMargins(mm, mm, mm, mm) #set fixed size for the icon, maybe called logo or brand def setIconSize(self, aw, ah): self.iconSize = aw, ah self.imgIcon.setFixedSize(self.iconSize[0], self.iconSize[1]) #set icon margins within the icon frame def setIconMargins(self, ml, mt = 0, mr = 0, mb = 0): self.iconMargins = ml, mt, mr, mb mml, mmt, mmr, mmb = self.mainLayout.getContentsMargins() self.iconLayout.setContentsMargins(mml, mt, mmr, mb) #set icon frame's style, you can stylize background(single color, gradient or image), border, etc def setIconFrameStyle(self, style): self.iconFrameStyle = style self.iconFrame.setStyleSheet(self.iconFrameStyle) @pyqtSlot() def onInstallClicked(self): QMessageBox.information(None, "ID: " + str(self.appId), "Install button clicked") @pyqtSlot() def onUninstallClicked(self): QMessageBox.information(None, "ID: " + str(self.appId), "Gonna uninstall the app?") @pyqtSlot() def onLaunchClicked(self): QMessageBox.information(None, "ID: " + str(self.appId), "Launch is not ready yet!") #set whether the app is already installed or not, accordingly show or hide appropriate buttons def setAppState(self, state): if state == 0: self.btnInstall.show() self.btnUninstall.hide() self.btnLaunch.hide() elif state == 1: self.btnInstall.hide() self.btnUninstall.show() self.btnLaunch.show() self.autoAdjust() #return current app state def getAppState(self): return self.appState #set applicaton name def setAppName(self, name): if name != self.appName: self.appName = name self.txtName.setText(self.appName) #return application name def getAppName(self): return self.appName #set developer name, or could be company name def setAppDevName(self, name): if name != self.appDev: self.appDev = name self.txtDev.setText(self.appDev) #return developer name def getAppDevName(self): return self.appDev #set description about application def setAppDesc(self, desc): if desc != self.appDesc: self.appDesc = desc self.txtDesc.setText(self.appDesc) #return description of application def getAppDesc(self): return self.appDesc #set application icon with appropriate file path def setAppIcon(self, imgPath): if imgPath != self.appIcon: self.appIcon = imgPath self.imgIcon.setPixmap(QPixmap(self.appIcon)) #return QPixmap of icon def getAppIconPixmap(self): return QPixmap(self.appIcon) #return path to icon def getAppIconPath(self): return self.appIcon #set applicaiton star rating and count of given feedbacks def setAppRating(self, rating, feedback): if rating != self.appRating or feedback != self.appFeedback: self.appRating, self.appFeedback = rating, feedback self.starRating.setRating(rating) self.feedbackGiven.setText("(" + str(feedback) + ")") #return star rating value and the count of given feedbacks def getAppRating(self): return (self.appRating, self.appFeedback) #set path to background would be embedded into stylesheet string def setBackgroundImage(self, img): self.appBack = img self.setStyleSheet("#Card{" + self.style_str + " background-image: url(" + self.appBack + ")}") #set application ID def setAppId(self, id): self.appId = id #return app ID def getAppId(self): return self.appId #set blur radius of frame's shadow effect def setShadowBlurRadius(self, radius): self.shadowEffect.setBlurRadius(radius) #set shadow offset of frame's shadow effect def setShadowOffset(self, offX, offY): self.shadowEffect.setOffset(offX, offY) #set shadow color of frame's shadow effect def setShadowColor(self, color): self.shadowEffect.setColor(color) #set font of application name def setAppNameFont(self, font): self.txtName.setFont(font) #set font of developer name def setAppDevFont(self, font): self.txtDev.setFont(font) #set font of description to the app def setAppDescFont(self, font): self.txtDesc.setFont(font);
class PCard(QFrame): def __init__(self, parent=None): super().__init__(parent) self.setObjectName("PCard") self.border_radius = 8 self.text_color = QColor(255, 255, 255) self.lighttext_color = QColor(self.text_color.red() - 30, self.text_color.green() - 30, self.text_color.blue() - 30) self.back_color = QColor(108, 108, 115) self.title = "30 Barry Rise, Bowdon, Altrincham, Greater Manchester" self.homename = "Park_Home" self.rooms = "5" self.fontSize = 11 self.font = QFont("Roboto", self.fontSize) self.posteddate = "12/10/19" self.price = "$20, 000 pcm" self.description = "Superb opportunity to purchase this bright and spacious two bedroom flat occupying the two bedroom flat occupying the " self.pictures = [ 'image1.jpg', 'image2.jpg', 'image1.jpg', 'image2.jpg' ] self.init_ui() self.set_style() def init_ui(self): self.pic_label = QLabel(self) self.pic_label.setObjectName("PCardPicture") self.pic_label.setAutoFillBackground(True) self.pic_label.setScaledContents(True) self.pic_label.setPixmap(QPixmap(self.pictures[0])) self.title_label = ElideLabel(self) self.title_label.setObjectName("PCardTitle") self.title_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.title_label.setText(self.title) self.title_label.setWordWrap(True) self.set_style_label(self.title_label, 1) self.homename_label = QLabel(self) self.homename_label.setObjectName("PCardHomeName") self.homename_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.homename_label.setText(self.homename) self.set_style_label(self.homename_label, 0) self.rooms_label = QLabel(self) self.rooms_label.setObjectName("PCardRooms") self.rooms_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.rooms_label.setText(self.rooms) self.set_style_label(self.rooms_label, 0) self.posteddate_label = QLabel(self) self.posteddate_label.setObjectName("PCardPostedDate") self.posteddate_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.posteddate_label.setText("posted " + self.posteddate) self.set_style_label(self.posteddate_label, 0) self.description_label = ElideLabel(self) self.description_label.setObjectName("PCardDescription") self.description_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.description_label.setText(self.description) self.set_style_label(self.description_label, 0) self.price_label = QLabel(self) self.price_label.setObjectName("PCardPrice") self.price_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.price_label.setText(self.price) self.set_style_label(self.price_label, 1) self.set_font(self.font) def set_font(self, font): self.fontSize = font.pointSize() self.homename_label.setFont(font) self.rooms_label.setFont(font) self.posteddate_label.setFont(font) self.description_label.setFont(font) self.title_label.setFont( QFont(font.family(), self.fontSize + 3, QFont.DemiBold)) self.price_label.setFont( QFont(font.family(), self.fontSize + 3, QFont.DemiBold)) def set_style_label(self, label, dark): if dark == 0: color = self.lighttext_color else: color = self.text_color qssString = f"#{label.objectName()} {{background: rgba({self.back_color.red()}, {self.back_color.green()}, {self.back_color.blue()}, 255);" \ f"color: rgb({color.red()}, {color.green()}, {color.blue()}); padding: 2px; }}" label.setStyleSheet(qssString) def set_border_radius(self, rad): self.border_radius = rad print(rad) self.set_style() def set_text_color(self, color): self.text_color = color self.lighttext_color = QColor(self.text_color.red() - 30, self.text_color.green() - 30, self.text_color.blue() - 30) self.set_style() def set_back_color(self, color): self.back_color = color self.set_style() def set_style(self): self.setStyleSheet( f"#PCard {{border-radius: {self.border_radius}; " f"background: rgb({self.back_color.red()}, {self.back_color.green()}, {self.back_color.blue()}); " f"color: rgb({self.text_color.red()}, {self.text_color.green()}, {self.text_color.blue()});}}" ) def resizeEvent(self, event): self.setFixedHeight(self.width() * 1.2) self.pic_label.setGeometry(0, 0, self.width(), self.height() * 0.61) self.title_label.setGeometry(0, self.height() * 0.61, self.width() * 11 / 12, self.height() * 0.12) self.homename_label.setGeometry(0, self.height() * 0.73, self.width() / 3, self.height() * 0.07) self.rooms_label.setGeometry(self.width() / 3, self.height() * 0.73, self.width() / 6, self.height() * 0.07) self.posteddate_label.setGeometry(self.width() / 2, self.height() * 0.73, self.width() / 2, self.height() * 0.07) self.description_label.setGeometry(5, self.height() * 0.8, self.width() - 10, self.height() * 0.1) self.price_label.setGeometry(self.width() * 0.5, self.height() * 0.9, self.width() * 0.5 - self.border_radius, self.height() * 0.1) self.set_border_radius(self.height() / 25) def paintEvent(self, event): painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) painter.setPen(Qt.NoPen) painter.setBrush(self.back_color) painter.drawRoundedRect(QRect(0, 0, self.width(), self.height()), self.border_radius, self.border_radius)