diff options
Diffstat (limited to 'raveos-center/raveos_center/elemek.py')
| -rw-r--r-- | raveos-center/raveos_center/elemek.py | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/raveos-center/raveos_center/elemek.py b/raveos-center/raveos_center/elemek.py new file mode 100644 index 0000000..72f68ea --- /dev/null +++ b/raveos-center/raveos_center/elemek.py @@ -0,0 +1,387 @@ +import math + +from PyQt6.QtCore import QEvent, QPointF, QRectF, QSize, Qt, QTimer, pyqtSignal +from PyQt6.QtGui import QColor, QPainter, QPolygonF +from PyQt6.QtWidgets import ( + QAbstractButton, + QFrame, + QGridLayout, + QHBoxLayout, + QLabel, + QPushButton, + QScrollArea, + QSizePolicy, + QVBoxLayout, + QWidget, +) + + +def cimke(szoveg, nev=None, tordel=False): + c = QLabel(szoveg) + if nev: + c.setObjectName(nev) + c.setWordWrap(tordel) + return c + + +def gomb(szoveg, fo=False, kicsi=False): + g = QPushButton(szoveg) + g.setCursor(Qt.CursorShape.PointingHandCursor) + if fo: + g.setProperty("fo", True) + if kicsi: + g.setProperty("kicsi", True) + return g + + +def frissit_stilus(widget): + widget.style().unpolish(widget) + widget.style().polish(widget) + + +class Kartya(QFrame): + def __init__(self, cim=None, terkoz=10, margo=20): + super().__init__() + self.setObjectName("kartya") + self.elrendezes = QVBoxLayout(self) + self.elrendezes.setContentsMargins(margo, margo, margo, margo) + self.elrendezes.setSpacing(terkoz) + if cim: + self.elrendezes.addWidget(cimke(cim.upper(), "kartyacim")) + + +class Racs(QWidget): + def __init__(self, min_szelesseg, terkoz=16): + super().__init__() + self.min_szelesseg = min_szelesseg + self.elemek = [] + self.rejtett = set() + self.oszlopok = 0 + self.racs = QGridLayout(self) + self.racs.setContentsMargins(0, 0, 0, 0) + self.racs.setSpacing(terkoz) + + def hozzaad(self, widget): + self.elemek.append(widget) + self._rendez(force=True) + + def resizeEvent(self, esemeny): + super().resizeEvent(esemeny) + self._rendez() + + def szur(self, lathatok): + self.rejtett = {w for w in self.elemek if w not in lathatok} + for w in self.elemek: + w.setVisible(w not in self.rejtett) + self._rendez(force=True) + + def _rendez(self, force=False): + terkoz = self.racs.spacing() + lathatok = [w for w in self.elemek if w not in self.rejtett] + oszlopok = max(1, (self.width() + terkoz) // (self.min_szelesseg + terkoz)) + if self.min_szelesseg < 260: + oszlopok = min(oszlopok, max(1, len(lathatok))) + if oszlopok == self.oszlopok and not force: + return + self.oszlopok = oszlopok + for w in self.elemek: + self.racs.removeWidget(w) + for i, w in enumerate(lathatok): + self.racs.addWidget(w, i // oszlopok, i % oszlopok) + self.updateGeometry() + oldal = self.parent() + while oldal is not None and not isinstance(oldal, Oldal): + oldal = oldal.parent() + if oldal is not None and oldal.kitolt: + QTimer.singleShot(0, oldal._igazit) + for o in range(self.racs.columnCount()): + self.racs.setColumnStretch(o, 1 if o < oszlopok else 0) + + +class _KitoltoTartalom(QWidget): + def sizeHint(self): + return self.minimumSizeHint() + + def heightForWidth(self, szelesseg): + elrendezes = self.layout() + if elrendezes and elrendezes.hasHeightForWidth(): + return elrendezes.minimumHeightForWidth(szelesseg) + return self.minimumSizeHint().height() + + +class Oldal(QScrollArea): + def __init__(self, kozpont, eyebrow, cim, kitolt=False): + super().__init__() + self.kozpont = kozpont + self.setWidgetResizable(True) + self.setFrameShape(QFrame.Shape.NoFrame) + self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + self.kitolt = kitolt + tartalom = _KitoltoTartalom() if kitolt else QWidget() + self.setWidget(tartalom) + if kitolt: + tartalom.installEventFilter(self) + self.torzs = QVBoxLayout(tartalom) + self.torzs.setContentsMargins(48, 40, 48, 40) + self.torzs.setSpacing(32) + + fejlec = QHBoxLayout() + fejlec.setSpacing(16) + cimsor = QVBoxLayout() + cimsor.setSpacing(6) + self.eyebrow = cimke(eyebrow, "eyebrow") + self.cim = cimke(cim.upper(), "h1") + cimsor.addWidget(self.eyebrow) + cimsor.addWidget(self.cim) + fejlec.addLayout(cimsor) + fejlec.addStretch(1) + self.gombsor = QHBoxLayout() + self.gombsor.setSpacing(8) + fejlec.addLayout(self.gombsor) + fejlec.setAlignment(self.gombsor, Qt.AlignmentFlag.AlignBottom) + self.torzs.addLayout(fejlec) + + def eventFilter(self, objektum, esemeny): + if self.kitolt and objektum is self.widget() and esemeny.type() == QEvent.Type.LayoutRequest: + QTimer.singleShot(0, self._igazit) + return super().eventFilter(objektum, esemeny) + + def resizeEvent(self, esemeny): + super().resizeEvent(esemeny) + if self.kitolt: + self._igazit() + + def _igazit(self): + tartalom = self.widget() + nezet = self.viewport() + magassag = max(nezet.height(), tartalom.heightForWidth(nezet.width())) + if tartalom.height() != magassag or tartalom.width() != nezet.width(): + tartalom.resize(nezet.width(), magassag) + + def fejlec_gomb(self, gomb_widget): + self.gombsor.addWidget(gomb_widget) + return gomb_widget + + def megjelenik(self, *_): + pass + + def indulaskor(self): + pass + + def elerheto(self, *_): + return True + + +class Fulsor(QWidget): + def __init__(self, fulek, valtas): + super().__init__() + self.setObjectName("fulsor") + self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True) + sor = QHBoxLayout(self) + sor.setContentsMargins(0, 0, 0, 0) + sor.setSpacing(0) + self.gombok = {} + for azon, szoveg in fulek: + g = QPushButton(szoveg) + g.setObjectName("ful") + g.setCursor(Qt.CursorShape.PointingHandCursor) + g.clicked.connect(lambda _=False, a=azon: valtas(a)) + self.gombok[azon] = g + sor.addWidget(g) + sor.addStretch(1) + + def aktiv(self, azon): + for a, g in self.gombok.items(): + g.setProperty("aktiv", a == azon) + frissit_stilus(g) + + +class Verem(QWidget): + currentChanged = pyqtSignal(int) + + def __init__(self): + super().__init__() + self._lapok = [] + self._aktualis = -1 + self._elrendezes = QVBoxLayout(self) + self._elrendezes.setContentsMargins(0, 0, 0, 0) + self._elrendezes.setSpacing(0) + + def addWidget(self, widget): + self._lapok.append(widget) + self._elrendezes.addWidget(widget) + if self._aktualis < 0: + self.setCurrentIndex(0) + else: + widget.hide() + return len(self._lapok) - 1 + + def count(self): + return len(self._lapok) + + def widget(self, index): + return self._lapok[index] if 0 <= index < len(self._lapok) else None + + def indexOf(self, widget): + return self._lapok.index(widget) if widget in self._lapok else -1 + + def currentIndex(self): + return self._aktualis + + def currentWidget(self): + return self.widget(self._aktualis) + + def setCurrentIndex(self, index): + if not 0 <= index < len(self._lapok): + return + for i, lap in enumerate(self._lapok): + lap.setVisible(i == index) + valtozott = index != self._aktualis + self._aktualis = index + self.updateGeometry() + if valtozott: + self.currentChanged.emit(index) + + def setCurrentWidget(self, widget): + self.setCurrentIndex(self.indexOf(widget)) + + +class Kapcsolo(QAbstractButton): + def __init__(self): + super().__init__() + self.setCheckable(True) + self.setCursor(Qt.CursorShape.PointingHandCursor) + self.setFixedSize(QSize(44, 24)) + self.setAccessibleName("kapcsoló") + + def sizeHint(self): + return QSize(44, 24) + + def paintEvent(self, _): + from raveos_center import stilus + + festo = QPainter(self) + festo.setRenderHint(QPainter.RenderHint.Antialiasing, False) + be = self.isChecked() + aktiv = self.isEnabled() + palya = QColor(stilus.ZOLD if be else stilus.AKTIV) + keret = QColor(stilus.ZOLD if be else stilus.KERET_EROS) + if not aktiv: + palya = QColor(stilus.KERET if not be else "#3d5a36") + keret = palya + festo.setPen(keret) + festo.setBrush(palya) + festo.drawRect(QRectF(0.5, 0.5, self.width() - 1, self.height() - 1)) + gomb_meret = self.height() - 8 + x = self.width() - gomb_meret - 4 if be else 4 + festo.setPen(Qt.PenStyle.NoPen) + festo.setBrush(QColor(stilus.ZOLDON_SZOVEG if be else stilus.SZOVEG_HALVANY)) + festo.drawRect(QRectF(x, 4, gomb_meret, gomb_meret)) + festo.end() + + +class Csillagok(QWidget): + valasztva = pyqtSignal(int) + TERKOZ = 6 + LEPESEK = {Qt.Key.Key_Right: 1, Qt.Key.Key_Up: 1, Qt.Key.Key_Left: -1, Qt.Key.Key_Down: -1} + SZAMOK = {Qt.Key.Key_1: 1, Qt.Key.Key_2: 2, Qt.Key.Key_3: 3, Qt.Key.Key_4: 4, Qt.Key.Key_5: 5} + + def __init__(self, meret=22, valaszthato=False): + super().__init__() + self.meret = meret + self.ertek = 0.0 + self.mutatott = 0 + self.valaszthato = valaszthato + self.setFixedSize(self.sizeHint()) + self.setAccessibleName("csillagos értékelés") + if valaszthato: + self.setMouseTracking(True) + self.setCursor(Qt.CursorShape.PointingHandCursor) + self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) + + def sizeHint(self): + return QSize(self.meret * 5 + self.TERKOZ * 4, self.meret) + + def beallit(self, ertek): + self.ertek = max(0.0, min(5.0, float(ertek))) + self.setToolTip(f"{self.ertek:.1f} / 5" if not self.valaszthato else "") + self.update() + + def _index(self, pont): + return max(1, min(5, int(pont.x() // (self.meret + self.TERKOZ)) + 1)) + + def _valaszt(self, ertek): + self.beallit(ertek) + self.valasztva.emit(int(ertek)) + + def mouseMoveEvent(self, esemeny): + if self.valaszthato and self.isEnabled(): + self.mutatott = self._index(esemeny.position()) + self.update() + + def leaveEvent(self, esemeny): + self.mutatott = 0 + self.update() + super().leaveEvent(esemeny) + + def mouseReleaseEvent(self, esemeny): + if self.valaszthato and esemeny.button() == Qt.MouseButton.LeftButton and self.rect().contains( + esemeny.position().toPoint() + ): + self._valaszt(self._index(esemeny.position())) + super().mouseReleaseEvent(esemeny) + + def keyPressEvent(self, esemeny): + if not self.valaszthato: + return super().keyPressEvent(esemeny) + try: + kulcs = Qt.Key(esemeny.key()) + except ValueError: + kulcs = None + if kulcs in self.LEPESEK: + self._valaszt(max(1, min(5, int(self.ertek) + self.LEPESEK[kulcs]))) + elif kulcs in self.SZAMOK: + self._valaszt(self.SZAMOK[kulcs]) + else: + super().keyPressEvent(esemeny) + + def _sokszog(self, bal): + r = self.meret / 2 + kozep = QPointF(bal + r, r * 1.05) + pontok = [] + for i in range(10): + sugar = r if i % 2 == 0 else r * 0.42 + szog = math.radians(-90 + i * 36) + pontok.append(QPointF(kozep.x() + sugar * math.cos(szog), kozep.y() + sugar * math.sin(szog))) + return QPolygonF(pontok) + + def paintEvent(self, _): + from raveos_center import stilus + + festo = QPainter(self) + festo.setRenderHint(QPainter.RenderHint.Antialiasing, True) + festo.setPen(Qt.PenStyle.NoPen) + ertek = self.mutatott or self.ertek + tele = QColor(stilus.SARGA if self.isEnabled() else stilus.SZOVEG_HALVANY) + for i in range(5): + bal = i * (self.meret + self.TERKOZ) + csillag = self._sokszog(bal) + festo.setBrush(QColor(stilus.KERET_EROS)) + festo.drawPolygon(csillag) + resz = max(0.0, min(1.0, ertek - i)) + if resz > 0: + festo.save() + festo.setClipRect(QRectF(bal, 0, self.meret * resz, self.meret)) + festo.setBrush(tele) + festo.drawPolygon(csillag) + festo.restore() + if self.hasFocus(): + festo.setPen(QColor(stilus.ZOLD)) + festo.setBrush(Qt.BrushStyle.NoBrush) + festo.drawRect(QRectF(0.5, 0.5, self.width() - 1, self.height() - 1)) + festo.end() + + +def nyujthato(widget): + widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) + return widget |