def __setupUi(self): layout = QVBoxLayout() label = QLabel(self) pixmap, _ = config.splash_screen() label.setPixmap(pixmap) layout.addWidget(label, Qt.AlignCenter) name = QApplication.applicationName() version = QApplication.applicationVersion() text = ABOUT_TEMPLATE.format( name=escape(name), version=escape(version), ) # TODO: Also list all known add-on versions??. text_label = QLabel(text) layout.addWidget(text_label, Qt.AlignCenter) buttons = QDialogButtonBox( QDialogButtonBox.Close, Qt.Horizontal, self) layout.addWidget(buttons) buttons.rejected.connect(self.accept) layout.setSizeConstraint(QVBoxLayout.SetFixedSize) self.setLayout(layout)
def __setupUi(self): layout = QVBoxLayout() label = QLabel(self) pixmap, _ = config.splash_screen() label.setPixmap(pixmap) layout.addWidget(label, Qt.AlignCenter) try: from Orange.version import version from Orange.version import git_revision except ImportError: dist = pkg_resources.get_distribution("Orange3") version = dist.version git_revision = "Unknown" text = ABOUT_TEMPLATE.format(version=version, git_revision=git_revision[:7]) # TODO: Also list all known add-on versions. text_label = QLabel(text) layout.addWidget(text_label, Qt.AlignCenter) buttons = QDialogButtonBox(QDialogButtonBox.Close, Qt.Horizontal, self) layout.addWidget(buttons) buttons.rejected.connect(self.accept) layout.setSizeConstraint(QVBoxLayout.SetFixedSize) self.setLayout(layout)
def __setupUi(self): layout = QVBoxLayout() label = QLabel(self) pixmap, _ = config.splash_screen() label.setPixmap(pixmap) layout.addWidget(label, Qt.AlignCenter) name = QApplication.applicationName() version = QApplication.applicationVersion() text = ABOUT_TEMPLATE.format( name=escape(name), version=escape(version), ) # TODO: Also list all known add-on versions??. text_label = QLabel(text) layout.addWidget(text_label, Qt.AlignCenter) buttons = QDialogButtonBox(QDialogButtonBox.Close, Qt.Horizontal, self) layout.addWidget(buttons) buttons.rejected.connect(self.accept) layout.setSizeConstraint(QVBoxLayout.SetFixedSize) self.setLayout(layout)
class SingleLinkPage(QFrame): """ An simple (overly) large image with a external link """ def __init__(self, *args, image=QImage(), heading="", link=QUrl(), **kwargs): super().__init__(*args, **kwargs) self.__link = QUrl() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.__heading = QLabel() self.__content = QLabel() self.layout().addWidget(self.__heading) self.layout().addWidget(self.__content, 10, Qt.AlignCenter) self.__shadow = DropShadowFrame() self.__shadow.setWidget(self.__content) self.setImage(image) self.setHeading(heading) self.setLink(link) def setHeading(self, heading): self.__heading.setText("<h2>{}</h2>".format(heading)) def setImage(self, image): pm = pixmap_from_image(image) self.__content.setPixmap(pm) def setLink(self, url): self.__link = QUrl(url) if not self.__link.isEmpty(): self.__content.setCursor(Qt.PointingHandCursor) else: self.__content.unsetCursor() self.__content.setToolTip(self.__link.toString()) def mousePressEvent(self, event): if self.__content.geometry().contains(event.pos()) and \ not self.__link.isEmpty(): QDesktopServices.openUrl(self.__link) event.accept() else: super().mousePressEvent(event)
def update_legend(self, colors, labels): layout = self.legend.layout() while self.legend_items: w = self.legend_items.pop() layout.removeWidget(w) w.deleteLater() for row, (color, label) in enumerate(zip(colors, labels)): icon = QLabel() p = QPixmap(12, 12) p.fill(color) icon.setPixmap(p) label = QLabel(label) layout.addWidget(icon, row, 0) layout.addWidget(label, row, 1, alignment=Qt.AlignLeft) self.legend_items += (icon, label)
def setupUi(self): self.setLayout(QVBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().setSpacing(0) self.__mainLayout = QVBoxLayout() self.__mainLayout.setContentsMargins(0, 40, 0, 40) self.__mainLayout.setSpacing(65) self.layout().addLayout(self.__mainLayout) self.setStyleSheet(WELCOME_WIDGET_BUTTON_STYLE) dir_path = Path(__file__).resolve() parent_path = dir_path.parent.parent icon_path = f'{str(parent_path)}/icons' guanzhu_box = QVBoxLayout() guanzhu_label = QLabel() guanzhu_pic = QPixmap(icon_path + '/weixin.png') guanzhu_label.setPixmap(guanzhu_pic) guanzhu_text = QLabel('关注我们') guanzhu_box.addWidget(guanzhu_label, alignment=Qt.AlignVCenter | Qt.AlignHCenter) guanzhu_box.addWidget(guanzhu_text, alignment=Qt.AlignVCenter | Qt.AlignHCenter) zan_box = QVBoxLayout() zan_label = QLabel() pixmap = QPixmap(icon_path + '/zan.png') zan_label.setPixmap(pixmap) zan_text = QLabel('赞赏开发者') zan_box.addWidget(zan_label, alignment=Qt.AlignVCenter | Qt.AlignHCenter) zan_box.addWidget(zan_text, alignment=Qt.AlignVCenter | Qt.AlignHCenter) weixinBox = QHBoxLayout() weixinBox.addLayout(guanzhu_box) weixinBox.addLayout(zan_box) self.layout().addLayout(weixinBox) bottom_bar = QWidget(objectName="bottom-bar") bottom_bar_layout = QHBoxLayout() bottom_bar_layout.setContentsMargins(20, 10, 20, 10) bottom_bar.setLayout(bottom_bar_layout) bottom_bar.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Maximum) # self.__showAtStartupCheck = QCheckBox( # self.tr("启动时显示"), bottom_bar, checked=True # ) # self.__showAtStartupCheck = QCheckBox( # self.tr("启动时显示"), bottom_bar, checked=True # ) self.__feedbackLabel = QLabel( textInteractionFlags=Qt.TextBrowserInteraction, openExternalLinks=True, visible=False, ) # bottom_bar_layout.addWidget( # self.__showAtStartupCheck, alignment=Qt.AlignVCenter | Qt.AlignLeft # ) bottom_bar_layout.addWidget(self.__feedbackLabel, alignment=Qt.AlignVCenter | Qt.AlignRight) self.layout().addWidget(bottom_bar, alignment=Qt.AlignBottom, stretch=1) self.setSizeGripEnabled(False) self.setFixedSize(620, 590)
class MessageWidget(QWidget): """ A widget displaying a simple message to the user. This is an alternative to a full QMessageBox intended for inline modeless messages. [[icon] {Message text} (Ok) (Cancel)] """ #: Emitted when a button with the AcceptRole is clicked accepted = Signal() #: Emitted when a button with the RejectRole is clicked rejected = Signal() #: Emitted when a button with the HelpRole is clicked helpRequested = Signal() #: Emitted when a button is clicked clicked = Signal(QAbstractButton) class StandardButton(enum.IntEnum): NoButton, Ok, Close, Help = 0x0, 0x1, 0x2, 0x4 NoButton, Ok, Close, Help = list(StandardButton) class ButtonRole(enum.IntEnum): InvalidRole, AcceptRole, RejectRole, HelpRole = 0, 1, 2, 3 InvalidRole, AcceptRole, RejectRole, HelpRole = list(ButtonRole) _Button = namedtuple("_Button", ["button", "role", "stdbutton"]) def __init__(self, parent=None, icon=QIcon(), text="", wordWrap=False, textFormat=Qt.AutoText, standardButtons=NoButton, **kwargs): super().__init__(parent, **kwargs) self.__text = text self.__icon = QIcon() self.__wordWrap = wordWrap self.__standardButtons = MessageWidget.NoButton self._buttons = [] layout = QHBoxLayout() layout.setContentsMargins(8, 0, 8, 0) self.__iconlabel = QLabel(objectName="icon-label") self.__iconlabel.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.__textlabel = QLabel(objectName="text-label", text=text, wordWrap=wordWrap, textFormat=textFormat) if sys.platform == "darwin": self.__textlabel.setAttribute(Qt.WA_MacSmallSize) layout.addWidget(self.__iconlabel) layout.addWidget(self.__textlabel) self.setLayout(layout) self.setIcon(icon) self.setStandardButtons(standardButtons) def setText(self, text): """ Set the current message text. :type message: str """ if self.__text != text: self.__text = text self.__textlabel.setText(text) def text(self): """ Return the current message text. :rtype: str """ return self.__text def setIcon(self, icon): """ Set the message icon. :type icon: QIcon | QPixmap | QString | QStyle.StandardPixmap """ if isinstance(icon, QStyle.StandardPixmap): icon = self.style().standardIcon(icon) else: icon = QIcon(icon) if self.__icon != icon: self.__icon = QIcon(icon) if not self.__icon.isNull(): size = self.style().pixelMetric(QStyle.PM_SmallIconSize, None, self) pm = self.__icon.pixmap(QSize(size, size)) else: pm = QPixmap() self.__iconlabel.setPixmap(pm) self.__iconlabel.setVisible(not pm.isNull()) def icon(self): """ Return the current icon. :rtype: QIcon """ return QIcon(self.__icon) def setWordWrap(self, wordWrap): """ Set the message text wrap property :type wordWrap: bool """ if self.__wordWrap != wordWrap: self.__wordWrap = wordWrap self.__textlabel.setWordWrap(wordWrap) def wordWrap(self): """ Return the message text wrap property. :rtype: bool """ return self.__wordWrap def setTextFormat(self, textFormat): """ Set message text format :type textFormat: Qt.TextFormat """ self.__textlabel.setTextFormat(textFormat) def textFormat(self): """ Return the message text format. :rtype: Qt.TextFormat """ return self.__textlabel.textFormat() def changeEvent(self, event): # reimplemented if event.type() == 177: # QEvent.MacSizeChange: ... super().changeEvent(event) def setStandardButtons(self, buttons): for button in MessageWidget.StandardButton: existing = self.button(button) if button & buttons and existing is None: self.addButton(button) elif existing is not None: self.removeButton(existing) def standardButtons(self): return functools.reduce( operator.ior, (slot.stdbutton for slot in self._buttons if slot.stdbutton is not None), MessageWidget.NoButton) def addButton(self, button, *rolearg): """ addButton(QAbstractButton, ButtonRole) addButton(str, ButtonRole) addButton(StandardButton) Add and return a button """ stdbutton = None if isinstance(button, QAbstractButton): if len(rolearg) != 1: raise TypeError("Wrong number of arguments for " "addButton(QAbstractButton, role)") role = rolearg[0] elif isinstance(button, MessageWidget.StandardButton): if len(rolearg) != 0: raise TypeError("Wrong number of arguments for " "addButton(StandardButton)") stdbutton = button if button == MessageWidget.Ok: role = MessageWidget.AcceptRole button = QPushButton("Ok", default=False, autoDefault=False) elif button == MessageWidget.Close: role = MessageWidget.RejectRole # button = QPushButton( # default=False, autoDefault=False, flat=True, # icon=QIcon(self.style().standardIcon( # QStyle.SP_TitleBarCloseButton))) button = SimpleButton(icon=QIcon(self.style().standardIcon( QStyle.SP_TitleBarCloseButton))) elif button == MessageWidget.Help: role = MessageWidget.HelpRole button = QPushButton("Help", default=False, autoDefault=False) elif isinstance(button, str): if len(rolearg) != 1: raise TypeError("Wrong number of arguments for " "addButton(str, ButtonRole)") role = rolearg[0] button = QPushButton(button, default=False, autoDefault=False) if sys.platform == "darwin": button.setAttribute(Qt.WA_MacSmallSize) self._buttons.append(MessageWidget._Button(button, role, stdbutton)) button.clicked.connect(self._button_clicked) self._relayout() return button def removeButton(self, button): """ Remove a `button`. :type button: QAbstractButton """ slot = [s for s in self._buttons if s.button is button] if slot: slot = slot[0] self._buttons.remove(slot) self.layout().removeWidget(slot.button) slot.button.setParent(None) def buttonRole(self, button): """ Return the ButtonRole for button :type button: QAbstractButton """ for slot in self._buttons: if slot.button is button: return slot.role else: return MessageWidget.InvalidRole def button(self, standardButton): """ Return the button for the StandardButton. :type standardButton: StandardButton """ for slot in self._buttons: if slot.stdbutton == standardButton: return slot.button else: return None def _button_clicked(self): button = self.sender() role = self.buttonRole(button) self.clicked.emit(button) if role == MessageWidget.AcceptRole: self.accepted.emit() self.close() elif role == MessageWidget.RejectRole: self.rejected.emit() self.close() elif role == MessageWidget.HelpRole: self.helpRequested.emit() def _relayout(self): for slot in self._buttons: self.layout().removeWidget(slot.button) order = { MessageOverlayWidget.HelpRole: 0, MessageOverlayWidget.AcceptRole: 2, MessageOverlayWidget.RejectRole: 3, } orderd = sorted(self._buttons, key=lambda slot: order.get(slot.role, -1)) prev = self.__textlabel for slot in orderd: self.layout().addWidget(slot.button) QWidget.setTabOrder(prev, slot.button)
class OWCamera(OWWidget, ConcurrentWidgetMixin): name = "Camera" icon = "icons/WebcamCapture.svg" want_main_area = False class Outputs: DominantColors = Output("DominantColors", list) BouncingBalls = Output("BouncingBalls", list) def __init__(self): OWWidget.__init__(self) ConcurrentWidgetMixin.__init__(self) # self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.vc = cv.VideoCapture(0) self.vc.set(3, 640) # set width self.vc.set(4, 480) # set height self.image_label = QLabel() # self.image_label.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.controlArea.layout().addWidget(self.image_label) # self.resize(pixmap.width(), pixmap.height()) # # self.frame_timer = QTimer() # self.frame_timer.timeout.connect(self.update_frame) # self.frame_timer.start(0) # # self.output_timer = QTimer() # self.output_timer.timeout.connect(self.commit) # self.output_timer.start(0) # self.current_frame = None self.start(self.worker) self.setBlocking(False) def worker(self, state: TaskState): while True: state.set_partial_result(self.update_frame()) time.sleep(1 / 10) def on_partial_result(self, result): dominant, bb = result self.Outputs.DominantColors.send(dominant) self.Outputs.BouncingBalls.send(bb) def remap(self, x, in_min, in_max, out_min, out_max): return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min def update_frame(self): # read pixle values from camera _, frame = self.vc.read() balls = [None, None] if frame.size: # display image in orange widget image = QImage(frame[:, :, ::-1].copy(), frame.shape[1], frame.shape[0], QImage.Format_RGB888) pix = QPixmap.fromImage(image).scaled( self.image_label.size(), Qt.KeepAspectRatio | Qt.FastTransformation) self.image_label.setPixmap(pix) # Convert BGR to HSV hsv_image = cv.cvtColor(frame, cv.COLOR_BGR2HSV) # accumulated_mask = np.zeros(hsv_image.shape[:2], dtype='uint8') for index, (lower, upper) in enumerate(BOUNDARIES): mask = cv.inRange(hsv_image, lower, upper) size = self.remap(np.count_nonzero(mask), 0, mask.size, 0.2, 1) rgb_value = (cv.cvtColor( np.uint8([[cv.mean(hsv_image, mask)[:3]]]), cv.COLOR_HSV2RGB).flatten()) balls[index] = (tuple(rgb_value) if rgb_value.any() else None, size) # accumulated_mask = cv.bitwise_or(accumulated_mask, mask) dominant_colors = find_image_colors(hsv_image, image_processing_size=(100, 100)) # accumulated_mask = cv.bitwise_not(accumulated_mask) # res = cv.bitwise_and(frame, frame, mask=accumulated_mask) # print(res.reshape((res.shape[0] * res.shape[1], 3)).shape) # print(cv.mean(hsv_image, accumulated_mask)) # res = cv.resize(res, (100, 100), interpolation=cv.INTER_AREA) # if res.size: # # display image in orange widget # image = QImage(res[:, :, ::-1].copy(), res.shape[1], res.shape[0], QImage.Format_RGB888) # pix = QPixmap.fromImage(image).scaled(self.image_label.size(), Qt.KeepAspectRatio | Qt.FastTransformation) # self.image_label.setPixmap(pix) # res = res.reshape((res.shape[0] * res.shape[1], 3)) # res = res[~(res == 0).all(1)] # # # print(res) # # colors = find_image_colors(res, k=6, image_processing_size=(150, 150)) return dominant_colors, balls def onDeleteWidget(self): self.vc.release() super().onDeleteWidget()
class FancyWelcomeScreen(QWidget): """ Fancy welcome screen. +-----------+ | Welcome | +-----------+ | A | B | C | +---+---+---+ The upper part consist of static image while the lower items select some prespecified action. """ class StartItem(QWidget): """ An active item in the bottom row of the welcome screen. """ def __init__(self, *args, text="", icon=QIcon(), iconSize=QSize(), iconActive=QIcon(), **kwargs): self.__iconSize = QSize() self.__icon = QIcon() self.__icon_active = QIcon() self.__text = "" self.__active = False super().__init__(*args, **kwargs) self.setAutoFillBackground(True) font = self.font() font.setPointSize(18) self.setFont(font) self.setAttribute(Qt.WA_SetFont, False) self.setText(text) self.setIcon(icon) self.setIconSize(iconSize) self.setIconActive(iconActive) self.installEventFilter(self) def iconSize(self): if not self.__iconSize.isValid(): size = self.style().pixelMetric(QStyle.PM_LargeIconSize, None, self) * 2 return QSize(size, size) else: return QSize(self.__iconSize) def setIconSize(self, size): if size != self.__iconSize: self.__iconSize = QSize(size) self.updateGeometry() iconSize_ = Property(QSize, iconSize, setIconSize, designable=True) def icon(self): if self.__active: return QIcon(self.__icon_active) else: return QIcon(self.__icon) def setIcon(self, icon): self.__icon = QIcon(icon) self.update() icon_ = Property(QIcon, icon, setIcon, designable=True) def iconActive(self): return QIcon(self.__icon_active) def setIconActive(self, icon): self.__icon_active = QIcon(icon) self.update() icon_active_ = Property(QIcon, iconActive, setIconActive, designable=True) def sizeHint(self): return QSize(200, 150) def setText(self, text): if self.__text != text: self.__text = text self.updateGeometry() self.update() def text(self): return self.__text text_ = Property(str, text, setText, designable=True) def initStyleOption(self, option): # type: (QStyleOptionViewItem) -> None option.initFrom(self) option.backgroundBrush = option.palette.brush( self.backgroundRole()) option.font = self.font() option.text = self.text() option.icon = self.icon() option.decorationPosition = QStyleOptionViewItem.Top option.decorationAlignment = Qt.AlignCenter option.decorationSize = self.iconSize() option.displayAlignment = Qt.AlignCenter option.features = (QStyleOptionViewItem.WrapText | QStyleOptionViewItem.HasDecoration | QStyleOptionViewItem.HasDisplay) option.showDecorationSelected = True option.widget = self def paintEvent(self, event): style = self.style() # type: QStyle painter = QPainter(self) option = QStyleOption() option.initFrom(self) style.drawPrimitive(QStyle.PE_Widget, option, painter, self) option = QStyleOptionViewItem() self.initStyleOption(option) style.drawControl(QStyle.CE_ItemViewItem, option, painter, self) def eventFilter(self, obj, event): try: if event.type() == QEvent.Enter: self.__active = True self.setCursor(Qt.PointingHandCursor) self.update() return True elif event.type() == QEvent.Leave: self.__active = False self.unsetCursor() self.update() return True except Exception as ex: pass return False #: Signal emitted when the current selected item in changes. currentChanged = Signal(int) #: Signal emitted when the item is double clicked. activated = Signal(int) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setFocusPolicy(Qt.TabFocus) vlayout = QVBoxLayout(spacing=0) vlayout.setContentsMargins(0, 0, 0, 0) self.__currentIndex = -1 self.__contents = QLabel( sizePolicy=QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) vlayout.addWidget(self.__contents) hlayout = QHBoxLayout(spacing=0) hlayout.setContentsMargins(0, 0, 0, 0) self.__items = items = [ FancyWelcomeScreen.StartItem(objectName="item"), FancyWelcomeScreen.StartItem(objectName="item"), FancyWelcomeScreen.StartItem(objectName="item"), ] items[0].setProperty("-position", QStyleOptionViewItem.Beginning) items[1].setProperty("-position", QStyleOptionViewItem.Middle) items[-1].setProperty("-position", QStyleOptionViewItem.End) for item in items: hlayout.addWidget(item) vlayout.addLayout(hlayout) self.setLayout(vlayout) self.setCurrentIndex(0) def setImage(self, image): # type: (QImage) -> None """ Set the welcome image. Parameters ---------- image : QImage """ pixmap = pixmap_from_image(image) self.__contents.setPixmap(pixmap) def setItem(self, index, image): item = self.layout().itemAt(1).layout().itemAt(index) widget = item.widget() # type: FancyWelcomeScreen.StartItem widget.setIcon(image) def item(self, index): item = self.layout().itemAt(1).layout().itemAt(index) return item.widget() def setItemText(self, index, text): item = self.layout().itemAt(1).layout().itemAt(index) widget = item.widget() # type: FancyWelcomeScreen.StartItem widget.setText(text) def setItemIcon(self, index, icon): item = self.item(index) item.setIcon(icon) def setItemActiveIcon(self, index, icon): item = self.item(index) # type: FancyWelcomeScreen.StartItem item.setIconActive(icon) def setItemToolTip(self, index, tip): item = self.item(index) item.setToolTip(tip) def setCurrentIndex(self, index): self.__currentIndex = index def currentIndex(self): return self.__currentIndex def __indexAtPos(self, pos): # type: (QPoint) -> int for i, item in enumerate(self.__items): if item.geometry().contains(pos): return i return -1 def mousePressEvent(self, event): if event.button() == Qt.LeftButton: index = self.__indexAtPos(event.pos()) if index != -1: self.setCurrentIndex(index) event.accept() else: event.ignore() def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: index = self.__indexAtPos(event.pos()) if index != -1: self.setCurrentIndex(index) event.accept() else: event.ignore() def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: index = self.__indexAtPos(event.pos()) if index != -1: self.activated.emit(index) event.accept() else: event.ignore() def mouseDoubleClickEvent(self, event): if event.button() == Qt.LeftButton: index = self.__indexAtPos(event.pos()) if index != -1: self.activated.emit(index) event.accept() else: event.ignore() def keyPressEvent(self, event): if event.key() == Qt.Key_Right: direction = 1 elif event.key() == Qt.Key_Left: direction = -1 else: super().keyPressEvent(event) return event.accept() if len(self.__items): index = self.__currentIndex + direction self.setCurrentIndex(max(0, min(index, len(self.__items) - 1)))
class MessageWidget(QWidget): """ A widget displaying a simple message to the user. This is an alternative to a full QMessageBox intended for inline modeless messages. [[icon] {Message text} (Ok) (Cancel)] """ #: Emitted when a button with the AcceptRole is clicked accepted = Signal() #: Emitted when a button with the RejectRole is clicked rejected = Signal() #: Emitted when a button with the HelpRole is clicked helpRequested = Signal() #: Emitted when a button is clicked clicked = Signal(QAbstractButton) class StandardButton(enum.IntEnum): NoButton, Ok, Close, Help = 0x0, 0x1, 0x2, 0x4 NoButton, Ok, Close, Help = list(StandardButton) class ButtonRole(enum.IntEnum): InvalidRole, AcceptRole, RejectRole, HelpRole = 0, 1, 2, 3 InvalidRole, AcceptRole, RejectRole, HelpRole = list(ButtonRole) _Button = namedtuple("_Button", ["button", "role", "stdbutton"]) def __init__(self, parent=None, icon=QIcon(), text="", wordWrap=False, textFormat=Qt.AutoText, standardButtons=NoButton, **kwargs): super().__init__(parent, **kwargs) self.__text = text self.__icon = QIcon() self.__wordWrap = wordWrap self.__standardButtons = MessageWidget.NoButton self.__buttons = [] layout = QHBoxLayout() layout.setContentsMargins(8, 0, 8, 0) self.__iconlabel = QLabel(objectName="icon-label") self.__iconlabel.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.__textlabel = QLabel(objectName="text-label", text=text, wordWrap=wordWrap, textFormat=textFormat) if sys.platform == "darwin": self.__textlabel.setAttribute(Qt.WA_MacSmallSize) layout.addWidget(self.__iconlabel) layout.addWidget(self.__textlabel) self.setLayout(layout) self.setIcon(icon) self.setStandardButtons(standardButtons) def setText(self, text): """ Set the current message text. :type message: str """ if self.__text != text: self.__text = text self.__textlabel.setText(text) def text(self): """ Return the current message text. :rtype: str """ return self.__text def setIcon(self, icon): """ Set the message icon. :type icon: QIcon | QPixmap | QString | QStyle.StandardPixmap """ if isinstance(icon, QStyle.StandardPixmap): icon = self.style().standardIcon(icon) else: icon = QIcon(icon) if self.__icon != icon: self.__icon = QIcon(icon) if not self.__icon.isNull(): size = self.style().pixelMetric( QStyle.PM_SmallIconSize, None, self) pm = self.__icon.pixmap(QSize(size, size)) else: pm = QPixmap() self.__iconlabel.setPixmap(pm) self.__iconlabel.setVisible(not pm.isNull()) def icon(self): """ Return the current icon. :rtype: QIcon """ return QIcon(self.__icon) def setWordWrap(self, wordWrap): """ Set the message text wrap property :type wordWrap: bool """ if self.__wordWrap != wordWrap: self.__wordWrap = wordWrap self.__textlabel.setWordWrap(wordWrap) def wordWrap(self): """ Return the message text wrap property. :rtype: bool """ return self.__wordWrap def setTextFormat(self, textFormat): """ Set message text format :type textFormat: Qt.TextFormat """ self.__textlabel.setTextFormat(textFormat) def textFormat(self): """ Return the message text format. :rtype: Qt.TextFormat """ return self.__textlabel.textFormat() def changeEvent(self, event): # reimplemented if event.type() == 177: # QEvent.MacSizeChange: ... super().changeEvent(event) def setStandardButtons(self, buttons): for button in MessageWidget.StandardButton: existing = self.button(button) if button & buttons and existing is None: self.addButton(button) elif existing is not None: self.removeButton(existing) def standardButtons(self): return functools.reduce( operator.ior, (slot.stdbutton for slot in self.__buttons if slot.stdbutton is not None), MessageWidget.NoButton) def addButton(self, button, *rolearg): """ addButton(QAbstractButton, ButtonRole) addButton(str, ButtonRole) addButton(StandardButton) Add and return a button """ stdbutton = None if isinstance(button, QAbstractButton): if len(rolearg) != 1: raise TypeError("Wrong number of arguments for " "addButton(QAbstractButton, role)") role = rolearg[0] elif isinstance(button, MessageWidget.StandardButton): if len(rolearg) != 0: raise TypeError("Wrong number of arguments for " "addButton(StandardButton)") stdbutton = button if button == MessageWidget.Ok: role = MessageWidget.AcceptRole button = QPushButton("Ok", default=False, autoDefault=False) elif button == MessageWidget.Close: role = MessageWidget.RejectRole # button = QPushButton( # default=False, autoDefault=False, flat=True, # icon=QIcon(self.style().standardIcon( # QStyle.SP_TitleBarCloseButton))) button = SimpleButton( icon=QIcon(self.style().standardIcon( QStyle.SP_TitleBarCloseButton))) elif button == MessageWidget.Help: role = MessageWidget.HelpRole button = QPushButton("Help", default=False, autoDefault=False) elif isinstance(button, str): if len(rolearg) != 1: raise TypeError("Wrong number of arguments for " "addButton(str, ButtonRole)") role = rolearg[0] button = QPushButton(button, default=False, autoDefault=False) if sys.platform == "darwin": button.setAttribute(Qt.WA_MacSmallSize) self.__buttons.append(MessageWidget._Button(button, role, stdbutton)) button.clicked.connect(self.__button_clicked) self.__relayout() return button def removeButton(self, button): """ Remove a `button`. :type button: QAbstractButton """ slot = [s for s in self.__buttons if s.button is button] if slot: slot = slot[0] self.__buttons.remove(slot) self.layout().removeWidget(slot.button) slot.button.setParent(None) def buttonRole(self, button): """ Return the ButtonRole for button :type button: QAbsstractButton """ for slot in self.__buttons: if slot.button is button: return slot.role else: return MessageWidget.InvalidRole def button(self, standardButton): """ Return the button for the StandardButton. :type standardButton: StandardButton """ for slot in self.__buttons: if slot.stdbutton == standardButton: return slot.button else: return None def __button_clicked(self): button = self.sender() role = self.buttonRole(button) self.clicked.emit(button) if role == MessageWidget.AcceptRole: self.accepted.emit() self.close() elif role == MessageWidget.RejectRole: self.rejected.emit() self.close() elif role == MessageWidget.HelpRole: self.helpRequested.emit() def __relayout(self): for slot in self.__buttons: self.layout().removeWidget(slot.button) order = { MessageOverlayWidget.HelpRole: 0, MessageOverlayWidget.AcceptRole: 2, MessageOverlayWidget.RejectRole: 3, } orderd = sorted(self.__buttons, key=lambda slot: order.get(slot.role, -1)) prev = self.__textlabel for slot in orderd: self.layout().addWidget(slot.button) QWidget.setTabOrder(prev, slot.button)
class NotificationMessageWidget(QWidget): #: Emitted when a button with the AcceptRole is clicked accepted = Signal() #: Emitted when a button with the RejectRole is clicked rejected = Signal() #: Emitted when a button is clicked clicked = Signal(QAbstractButton) class StandardButton(enum.IntEnum): NoButton, Ok, Close = 0x0, 0x1, 0x2 NoButton, Ok, Close = list(StandardButton) class ButtonRole(enum.IntEnum): InvalidRole, AcceptRole, RejectRole, DismissRole = 0, 1, 2, 3 InvalidRole, AcceptRole, RejectRole, DismissRole = list(ButtonRole) _Button = namedtuple("_Button", ["button", "role", "stdbutton"]) def __init__(self, parent=None, icon=QIcon(), title="", text="", wordWrap=False, textFormat=Qt.PlainText, standardButtons=NoButton, acceptLabel="Ok", rejectLabel="No", **kwargs): super().__init__(parent, **kwargs) self._title = title self._text = text self._icon = QIcon() self._wordWrap = wordWrap self._standardButtons = NotificationMessageWidget.NoButton self._buttons = [] self._acceptLabel = acceptLabel self._rejectLabel = rejectLabel self._iconlabel = QLabel(objectName="icon-label") self._titlelabel = QLabel(objectName="title-label", text=title, wordWrap=wordWrap, textFormat=textFormat) self._textlabel = QLabel(objectName="text-label", text=text, wordWrap=wordWrap, textFormat=textFormat) self._textlabel.setTextInteractionFlags(Qt.TextBrowserInteraction) self._textlabel.setOpenExternalLinks(True) if sys.platform == "darwin": self._titlelabel.setAttribute(Qt.WA_MacSmallSize) self._textlabel.setAttribute(Qt.WA_MacSmallSize) layout = QHBoxLayout() self._iconlabel.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) layout.addWidget(self._iconlabel) layout.setAlignment(self._iconlabel, Qt.AlignTop) message_layout = QVBoxLayout() self._titlelabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) if sys.platform == "darwin": self._titlelabel.setContentsMargins(0, 1, 0, 0) else: self._titlelabel.setContentsMargins(0, 0, 0, 0) message_layout.addWidget(self._titlelabel) self._textlabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) message_layout.addWidget(self._textlabel) self.button_layout = QHBoxLayout() self.button_layout.setAlignment(Qt.AlignLeft) message_layout.addLayout(self.button_layout) layout.addLayout(message_layout) layout.setSpacing(7) self.setLayout(layout) self.setIcon(icon) self.setStandardButtons(standardButtons) def setText(self, text): """ Set the current message text. :type message: str """ if self._text != text: self._text = text self._textlabel.setText(text) def text(self): """ Return the current message text. :rtype: str """ return self._text def setTitle(self, title): """ Set the current title text. :type title: str """ if self._title != title: self._title = title self._titleLabel.setText(title) def title(self): """ Return the current title text. :rtype: str """ return self._title def setIcon(self, icon): """ Set the message icon. :type icon: QIcon | QPixmap | QString | QStyle.StandardPixmap """ if isinstance(icon, QStyle.StandardPixmap): icon = self.style().standardIcon(icon) else: icon = QIcon(icon) if self._icon != icon: self._icon = QIcon(icon) if not self._icon.isNull(): size = self.style().pixelMetric(QStyle.PM_SmallIconSize, None, self) pm = self._icon.pixmap(QSize(size, size)) else: pm = QPixmap() self._iconlabel.setPixmap(pm) self._iconlabel.setVisible(not pm.isNull()) def icon(self): """ Return the current icon. :rtype: QIcon """ return QIcon(self._icon) def setWordWrap(self, wordWrap): """ Set the message text wrap property :type wordWrap: bool """ if self._wordWrap != wordWrap: self._wordWrap = wordWrap self._textlabel.setWordWrap(wordWrap) def wordWrap(self): """ Return the message text wrap property. :rtype: bool """ return self._wordWrap def setTextFormat(self, textFormat): """ Set message text format :type textFormat: Qt.TextFormat """ self._textlabel.setTextFormat(textFormat) def textFormat(self): """ Return the message text format. :rtype: Qt.TextFormat """ return self._textlabel.textFormat() def setAcceptLabel(self, label): """ Set the accept button label. :type label: str """ self._acceptLabel = label def acceptLabel(self): """ Return the accept button label. :rtype str """ return self._acceptLabel def setRejectLabel(self, label): """ Set the reject button label. :type label: str """ self._rejectLabel = label def rejectLabel(self): """ Return the reject button label. :rtype str """ return self._rejectLabel def setStandardButtons(self, buttons): for button in NotificationMessageWidget.StandardButton: existing = self.button(button) if button & buttons and existing is None: self.addButton(button) elif existing is not None: self.removeButton(existing) def standardButtons(self): return functools.reduce( operator.ior, (slot.stdbutton for slot in self._buttons if slot.stdbutton is not None), NotificationMessageWidget.NoButton) def addButton(self, button, *rolearg): """ addButton(QAbstractButton, ButtonRole) addButton(str, ButtonRole) addButton(StandardButton) Add and return a button """ stdbutton = None if isinstance(button, QAbstractButton): if len(rolearg) != 1: raise TypeError("Wrong number of arguments for " "addButton(QAbstractButton, role)") role = rolearg[0] elif isinstance(button, NotificationMessageWidget.StandardButton): if rolearg: raise TypeError("Wrong number of arguments for " "addButton(StandardButton)") stdbutton = button if button == NotificationMessageWidget.Ok: role = NotificationMessageWidget.AcceptRole button = QPushButton(self._acceptLabel, default=False, autoDefault=False) elif button == NotificationMessageWidget.Close: role = NotificationMessageWidget.RejectRole button = QPushButton(self._rejectLabel, default=False, autoDefault=False) elif isinstance(button, str): if len(rolearg) != 1: raise TypeError("Wrong number of arguments for " "addButton(str, ButtonRole)") role = rolearg[0] button = QPushButton(button, default=False, autoDefault=False) if sys.platform == "darwin": button.setAttribute(Qt.WA_MacSmallSize) self._buttons.append( NotificationMessageWidget._Button(button, role, stdbutton)) button.clicked.connect(self._button_clicked) self._relayout() return button def _relayout(self): for slot in self._buttons: self.button_layout.removeWidget(slot.button) order = { NotificationWidget.AcceptRole: 0, NotificationWidget.RejectRole: 1, } ordered = sorted([ b for b in self._buttons if self.buttonRole(b.button) != NotificationMessageWidget.DismissRole ], key=lambda slot: order.get(slot.role, -1)) prev = self._textlabel for slot in ordered: self.button_layout.addWidget(slot.button) QWidget.setTabOrder(prev, slot.button) def removeButton(self, button): """ Remove a `button`. :type button: QAbstractButton """ slot = [s for s in self._buttons if s.button is button] if slot: slot = slot[0] self._buttons.remove(slot) self.layout().removeWidget(slot.button) slot.button.setParent(None) def buttonRole(self, button): """ Return the ButtonRole for button :type button: QAbstractButton """ for slot in self._buttons: if slot.button is button: return slot.role return NotificationMessageWidget.InvalidRole def button(self, standardButton): """ Return the button for the StandardButton. :type standardButton: StandardButton """ for slot in self._buttons: if slot.stdbutton == standardButton: return slot.button return None def _button_clicked(self): button = self.sender() role = self.buttonRole(button) self.clicked.emit(button) if role == NotificationMessageWidget.AcceptRole: self.accepted.emit() self.close() elif role == NotificationMessageWidget.RejectRole: self.rejected.emit() self.close()
def init_form(self): # Get the current path of the file rootPath = os.path.dirname(__file__) vlayout = QVBoxLayout() hlayout = QHBoxLayout() if _api.USED_API == _api.QT_API_PYQT5: hlayout.setContentsMargins(0, 0, 0, 0) vlayout.setContentsMargins(0, 0, 0, 0) elif _api.USED_API == _api.QT_API_PYQT4: hlayout.setMargin(0) vlayout.setMargin(0) self.setLayout(vlayout) # Add scroll area scrollarea = QScrollArea() self._scrollArea = scrollarea scrollarea.setMinimumHeight(140) scrollarea.setWidgetResizable(True) scrollarea.keyPressEvent = self.__scrollAreaKeyPressEvent scrollarea.keyReleaseEvent = self.__scrollAreaKeyReleaseEvent vlayout.addWidget(scrollarea) # The timeline widget self._time = widget = TimelineWidget(self) widget._scroll = scrollarea scrollarea.setWidget(widget) # Timeline zoom slider slider = QSlider(QtCore.Qt.Horizontal) slider.setFocusPolicy(QtCore.Qt.NoFocus) slider.setMinimum(1) slider.setMaximum(100) slider.setValue(10) slider.setPageStep(1) slider.setTickPosition(QSlider.NoTicks) # TicksBothSides slider.valueChanged.connect(self.__scaleSliderChange) slider_label_zoom_in = QLabel() slider_label_zoom_out = QLabel() slider_label_zoom_in.setPixmap( conf.PYFORMS_PIXMAP_EVENTTIMELINE_ZOOM_IN) slider_label_zoom_out.setPixmap( conf.PYFORMS_PIXMAP_EVENTTIMELINE_ZOOM_OUT) self._zoomLabel = QLabel("100%") hlayout.addWidget(self._zoomLabel) hlayout.addWidget(slider_label_zoom_out) hlayout.addWidget(slider) hlayout.addWidget(slider_label_zoom_in) # Import/Export Buttons btn_import = QPushButton("Import") btn_import.setIcon(conf.PYFORMS_ICON_EVENTTIMELINE_IMPORT) btn_import.clicked.connect(self.__open_import_win_evt) btn_export = QPushButton("Export") btn_export.setIcon(conf.PYFORMS_ICON_EVENTTIMELINE_EXPORT) btn_export.clicked.connect(self.__export) hlayout.addWidget(btn_import) hlayout.addWidget(btn_export) vlayout.addLayout(hlayout)