Пример #1
0
def drawIconWithShadow(icon: QIcon,
                       rect: QRect,
                       p: QPainter,
                       iconMode: QIcon.Mode = None,
                       dipRadius: int = None,
                       color: QColor = None,
                       dipOffset: QPoint = None):
    if iconMode is None:
        iconMode = QIcon.Normal
    if color is None:
        color = QColor(0, 0, 0, 130)
    if dipRadius is None:
        dipRadius = 3
    if dipOffset is None:
        dipOffset = QPoint(1, -2)

    devicePixelRatio: int = p.device().devicePixelRatio()
    pixmapName = "icon %s %s %s %s" % (icon.cacheKey(), iconMode,
                                       rect.height(), devicePixelRatio)
    cache = QPixmapCache.find(pixmapName)
    if cache is None:
        # High-dpi support: The in parameters (rect, radius, offset) are in
        # device-independent pixels. The call to QIcon::pixmap() below might
        # return a high-dpi pixmap, which will in that case have a devicePixelRatio
        # different than 1. The shadow drawing caluculations are done in device
        # pixels.
        window = p.device().window().windowHandle()
        px = icon.pixmap(window, rect.size(), iconMode)
        radius = dipRadius * devicePixelRatio
        offset = dipOffset * devicePixelRatio
        cache = QPixmap(px.size() + QSize(radius * 2, radius * 2))
        cache.fill(Qt.transparent)
        cachePainter = QPainter(cache)

        if iconMode == QIcon.Disabled:
            hasDisabledState = len(icon.availableSizes()) == len(
                icon.availableSizes(QIcon.Disabled))
            if not hasDisabledState:
                px = disabledSideBarIcon(icon.pixmap(window, rect.size()))
        elif TOOLBAR_ICON_SHADOW:
            # Draw shadow
            tmp = QImage(px.size() + QSize(radius * 2, radius * 2 + 1),
                         QImage.Format_ARGB32_Premultiplied)
            tmp.fill(Qt.transparent)

            tmpPainter = QPainter(tmp)
            tmpPainter.setCompositionMode(QPainter.CompositionMode_Source)
            tmpPainter.drawPixmap(
                QRect(radius, radius, px.width(), px.height()), px)
            tmpPainter.end()

            # blur the alpha channel
            blurred = QImage(tmp.size(), QImage.Format_ARGB32_Premultiplied)
            blurred.fill(Qt.transparent)
            blurPainter = QPainter(blurred)
            #qt_blurImage(blurPainter, tmp, radius, False, True)
            # implement qt_blurImage via QLabel with QGraphicsBlurEffect
            # FIXME: alignment is broken
            scene = QGraphicsScene()
            item = QGraphicsPixmapItem(QPixmap.fromImage(tmp))
            effect = QGraphicsBlurEffect()
            effect.setBlurRadius(radius)
            item.setGraphicsEffect(effect)
            scene.addItem(item)
            scene.render(blurPainter)
            blurPainter.end()
            tmp = blurred

            # blacken the image...
            tmpPainter.begin(tmp)
            tmpPainter.setCompositionMode(QPainter.CompositionMode_SourceIn)
            tmpPainter.fillRect(tmp.rect(), color)
            tmpPainter.end()

            tmpPainter.begin(tmp)
            tmpPainter.setCompositionMode(QPainter.CompositionMode_SourceIn)
            tmpPainter.fillRect(tmp.rect(), color)
            tmpPainter.end()

            # draw the blurred drop shadow...
            cachePainter.drawImage(
                QRect(0, 0,
                      cache.rect().width(),
                      cache.rect().height()), tmp)

        # Draw the actual pixmap...
        cachePainter.drawPixmap(
            QRect(
                QPoint(radius, radius) + offset, QSize(px.width(),
                                                       px.height())), px)
        cachePainter.end()
        cache.setDevicePixelRatio(devicePixelRatio)
        QPixmapCache.insert(pixmapName, cache)

    targetRect = cache.rect()
    targetRect.setSize(targetRect.size() / cache.devicePixelRatio())
    targetRect.moveCenter(rect.center() - dipOffset)
    p.drawPixmap(targetRect, cache)
Пример #2
0
class Reminder(ShowCenterMixin, OsxMenuMixin, TimerMixin):
    def __init__(self):
        self.app = QApplication(sys.argv)
        self.app.setQuitOnLastWindowClosed(False)
        self.app.setApplicationName(SPINBOX_WINDOW_TITLE)
        self.screen_height = self.app.primaryScreen().geometry().height()
        styleSheet = open(APP_STYLESHEET).read()
        if sys.platform == 'darwin':
            c = self.app.palette().color(QPalette.Highlight)
            color = 'rgba({},{},{},10%)'.format(c.red(), c.green(), c.blue())
            styleSheet = styleSheet.replace('palette(highlight)', color)
        self.app.setStyleSheet(styleSheet)

        self.setup_icon()
        self.setup_menu()
        self.setup_popup()
        self.setup_window()
        self.init_saved_alarm()
        self.idle()
        self.run()

    def on_button_clicked(self, *args):
        self.window.hide()
        h = self.spins[0].value()
        m = self.spins[1].value()
        s = self.spins[2].value()
        self.start_timer(h, m, s)

    def setup_window(self):
        self.window = QWidget()
        self.window.setProperty('objectName', 'window')
        self.window.setWindowTitle(SPINBOX_WINDOW_TITLE)
        self.window.setWindowFlags(self.window.windowFlags()
                                   | Qt.WindowStaysOnTopHint | Qt.Dialog)
        vlayout = QVBoxLayout(self.window)
        hlayout = QHBoxLayout()
        hlayout.setSpacing(SPINBOX_WINDOW_SPACING)

        self.spins = []
        for label in ['h', 'm', 's']:
            button_spin = ButtonSpinBox(label=label)
            spin = button_spin.spin
            self.spins.append(spin)
            hlayout.addLayout(button_spin)

        button = QPushButton(BUTTON_LABEL)
        button.setProperty('objectName', 'start')

        vlayout.addLayout(hlayout)
        vlayout.addWidget(button)

        button.clicked.connect(self.on_button_clicked)
        self.window.closeEvent = self.on_window_close

    def on_window_close(self, *args):
        self.window.hide()

    def setup_icon(self):
        self.icon_normal = QIcon(ALARM_PATH)
        self.icon = QSystemTrayIcon(self.icon_normal)
        self.icon_urgent = QIcon(ALARM_URGENT_PATH)
        self.icon_active = QIcon(ALARM_ACTIVE_PATH)
        self.icon.activated.connect(self.activate_menu)

    def setup_menu(self):
        self.menu = QMenu()
        clock_item = QWidgetAction(self.menu)
        self.clock = QPushButton(' ')
        self.clock.setProperty('objectName', 'menu')
        font = self.clock.font()
        font.setPixelSize(CLOCK_FONT_SIZE)
        self.clock.setFont(font)
        clock_item.setDefaultWidget(self.clock)
        self.clock.clicked.connect(self.activate_window)

        exit_item = QWidgetAction(self.menu)
        label = QPushButton(EXIT_LABEL)
        label.setProperty('objectName', 'menu')
        exit_item.setDefaultWidget(label)
        label.clicked.connect(self.activate_exit)

        self.menu.addAction(clock_item)
        self.menu.addAction(exit_item)

        if sys.platform == 'darwin':
            clock_item.button = self.clock
            exit_item.button = label
            self.menu.actions = [clock_item, exit_item]
            self.set_up_menu_macos(self.menu)

    def setup_popup(self):
        self.popup = QWidget()
        self.popup.setProperty('objectName', 'popup')
        vlayout = QVBoxLayout(self.popup)
        label = QLabel(ALERT_TEXT)
        vlayout.addWidget(label)
        self.popup.setWindowFlags(Qt.Sheet | Qt.Popup | Qt.WindowStaysOnTopHint
                                  | Qt.FramelessWindowHint)

        self.popup.mouseReleaseEvent = self.on_popup_release

    def on_popup_release(self, *args):
        self.popup.hide()

    def activate_menu(self, reason):
        if reason != QSystemTrayIcon.Trigger:
            return
        if self.icon.icon().cacheKey() == self.icon_urgent.cacheKey():
            self.clear_alarm()
            self.set_icon(self.icon_normal)
        self.update_clock()
        if sys.platform == 'darwin':
            self.on_menu_activated_macos()
            self.icon.setContextMenu(self.menu)
            self.icon.setContextMenu(None)
            return
        icon_pos = self.icon.geometry().bottomRight()
        width = min(self.menu.geometry().width(), 135)
        if icon_pos.y() > self.screen_height / 2:
            pos = icon_pos - QPoint(width, 40)
            self.menu.popup(pos, self.menu.actions()[-1])
        else:
            pos = icon_pos - QPoint(width, 0)
            self.menu.popup(pos)

    def activate_window(self, *args):
        if sys.platform == 'darwin':
            clock_action = self.menu.actions[0]
            clock_action.activate(clock_action.Trigger)
        self.show_center(self.window)

    def activate_exit(self, *args):
        os._exit(0)

    def set_icon(self, icon):
        self.icon.setIcon(icon)

    def update_clock_text(self, text):
        self.clock.setText(text)

    def show_popup(self):
        self.show_center(self.popup)

    def is_menu_visible(self):
        if sys.platform == 'darwin':
            return True
        return self.menu.isVisible()

    def run(self):
        timer = QTimer()
        timer.setInterval(1000)
        timer.timeout.connect(self.idle)
        timer.start(1000)
        self.icon.show()
        sys.exit(self.app.exec_())