%PDF- %PDF-
Direktori : /lib/calibre/calibre/gui2/ |
Current File : //lib/calibre/calibre/gui2/layout_menu.py |
#!/usr/bin/env python3 # License: GPLv3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net> from qt.core import ( QFontMetrics, QHBoxLayout, QIcon, QMenu, QStylePainter, QPushButton, QSize, QSizePolicy, Qt, QWidget, QStyleOption, QStyle, QEvent) ICON_SZ = 64 class LayoutItem(QWidget): def __init__(self, button, parent=None): QWidget.__init__(self, parent) self.mouse_over = False self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) self.button = button self.text = button.label self.setCursor(Qt.CursorShape.PointingHandCursor) self.fm = QFontMetrics(self.font()) self._bi = self._di = None @property def bright_icon(self): if self._bi is None: self._bi = self.button.icon().pixmap(ICON_SZ, ICON_SZ) return self._bi @property def dull_icon(self): if self._di is None: self._di = self.button.icon().pixmap(ICON_SZ, ICON_SZ, mode=QIcon.Mode.Disabled) return self._di def event(self, ev): m = None et = ev.type() if et == QEvent.Type.Enter: m = True elif et == QEvent.Type.Leave: m = False if m is not None and m != self.mouse_over: self.mouse_over = m self.update() return QWidget.event(self, ev) def sizeHint(self): br = self.fm.boundingRect(self.text) w = max(br.width(), ICON_SZ) + 10 h = 2 * self.fm.lineSpacing() + ICON_SZ + 8 return QSize(w, h) def paintEvent(self, ev): shown = self.button.isChecked() ls = self.fm.lineSpacing() painter = QStylePainter(self) if self.mouse_over: tool = QStyleOption() tool.initFrom(self) tool.rect = self.rect() tool.state = QStyle.StateFlag.State_Raised | QStyle.StateFlag.State_Active | QStyle.StateFlag.State_MouseOver painter.drawPrimitive(QStyle.PrimitiveElement.PE_PanelButtonTool, tool) painter.drawText( 0, 0, self.width(), ls, Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextSingleLine, self.text) text = _('Hide') if shown else _('Show') f = self.font() f.setBold(True) painter.setFont(f) painter.drawText( 0, self.height() - ls, self.width(), ls, Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextSingleLine, text) x = (self.width() - ICON_SZ) // 2 y = ls + (self.height() - ICON_SZ - 2 * ls) // 2 pmap = self.bright_icon if shown else self.dull_icon painter.drawPixmap(x, y, pmap) painter.end() class LayoutMenu(QMenu): def __init__(self, parent=None): QMenu.__init__(self, parent) self.l = l = QHBoxLayout(self) l.setSpacing(20) self.items = [] if parent is None: buttons = [ QPushButton(QIcon(I(i + '.png')), i, self) for i in 'search tags cover_flow grid book'.split()] for b in buttons: b.setVisible(False), b.setCheckable(True), b.setChecked(b.text() in 'tags grid') b.label = b.text().capitalize() else: buttons = parent.layout_buttons for b in buttons: self.items.append(LayoutItem(b, self)) l.addWidget(self.items[-1]) self.current_item = None def sizeHint(self): return QWidget.sizeHint(self) def paintEvent(self, ev): return QWidget.paintEvent(self, ev) def item_for_ev(self, ev): for item in self.items: if item.geometry().contains(ev.pos()): return item def mousePressEvent(self, ev): if ev.button() != Qt.MouseButton.LeftButton: ev.ignore() return if (ev.pos().isNull() and not ev.screenPos().isNull()) or not self.rect().contains(ev.pos()): self.hide() self.current_item = self.item_for_ev(ev) if self.current_item is not None: ev.accept() else: ev.ignore() def mouseReleaseEvent(self, ev): if ev.button() != Qt.MouseButton.LeftButton: ev.ignore() return item = self.item_for_ev(ev) if item is not None and item is self.current_item: ev.accept() self.hide() item.button.click() if __name__ == '__main__': from calibre.gui2 import Application app = Application([]) w = LayoutMenu() w.show() w.exec()