from PyQt6.QtCore import Qt from PyQt6.QtWidgets import ( QCheckBox, QFrame, QHBoxLayout, QLineEdit, QMessageBox, QPushButton, QVBoxLayout, QWidget, ) from raveos_center import katalogus from raveos_center.elemek import Kartya, Oldal, cimke, frissit_stilus, gomb from raveos_center.folyamat import FolyamatAblak from raveos_center.forditas import tr from raveos_center.hatter import gyorsitott AZON = "alkalmazasok" MENU = tr("Alkalmazások") IKON = "alkalmazasok" CSAK_TELEPITETT = "telepitett" class KattinthatoSor(QWidget): def __init__(self, jelolo): super().__init__() self.jelolo = jelolo self.setCursor(Qt.CursorShape.PointingHandCursor) def mouseReleaseEvent(self, esemeny): if esemeny.button() == Qt.MouseButton.LeftButton and self.rect().contains(esemeny.position().toPoint()): self.jelolo.toggle() super().mouseReleaseEvent(esemeny) class AppSor(QWidget): def __init__(self, app, oldal): super().__init__() self.app = app self.oldal = oldal self.telepitve = False self.setObjectName("appsor") self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True) doboz = QVBoxLayout(self) doboz.setContentsMargins(16, 12, 16, 12) doboz.setSpacing(8) felso = QHBoxLayout() felso.setSpacing(14) self.jelolo = QCheckBox() self.jelolo.setVisible(app["type"] != "message") self.jelolo.toggled.connect(self._sor_jelolve) felso.addWidget(self.jelolo) betu = cimke(app["name"][:1].upper(), "kezdobetu") betu.setAlignment(Qt.AlignmentFlag.AlignCenter) betu.setFixedSize(36, 36) felso.addWidget(betu) szovegek = QVBoxLayout() szovegek.setSpacing(2) nevsor = QHBoxLayout() nevsor.setSpacing(10) nev = cimke(app["name"]) nev.setStyleSheet("font-size: 14px; font-weight: 600;") nevsor.addWidget(nev) nevsor.addWidget(cimke(katalogus.forras(app), "monohalvany")) self.allapot = cimke(tr("TELEPÍTVE"), "allapotcimke") self.allapot.setProperty("szin", "zold") self.allapot.hide() nevsor.addWidget(self.allapot) nevsor.addStretch(1) szovegek.addLayout(nevsor) leiras = katalogus.loc(app.get("desc")) self.leiras = cimke(leiras, "halvany") self.leiras.setToolTip(leiras) self.leiras.setMinimumWidth(80) szovegek.addWidget(self.leiras) felso.addLayout(szovegek, 1) self.eltavolit_gomb = None if app["type"] == "choice": self.eltavolit_gomb = gomb(tr("Eltávolítás"), kicsi=True) self.eltavolit_gomb.clicked.connect(lambda: self._opcio_muvelet(False)) felso.addWidget(self.eltavolit_gomb) self.gomb = gomb("", kicsi=True) self.gomb.setMinimumWidth(110) self.gomb.clicked.connect(self._kattint) felso.addWidget(self.gomb) doboz.addLayout(felso) self.opciok = [] if app["type"] == "choice": self._opcio_lista(doboz) elif app["type"] != "message": self.setCursor(Qt.CursorShape.PointingHandCursor) self.frissit(oldal.index) def mouseReleaseEvent(self, esemeny): if ( esemeny.button() == Qt.MouseButton.LeftButton and self.app["type"] not in ("choice", "message") and self.rect().contains(esemeny.position().toPoint()) ): self.jelolo.toggle() super().mouseReleaseEvent(esemeny) def resizeEvent(self, esemeny): super().resizeEvent(esemeny) teljes = self.leiras.toolTip() self.leiras.setText( self.leiras.fontMetrics().elidedText(teljes, Qt.TextElideMode.ElideRight, max(80, self.leiras.width())) ) def _opcio_lista(self, doboz): lista = QVBoxLayout() lista.setContentsMargins(82, 4, 0, 0) lista.setSpacing(6) fej = QHBoxLayout() fej.addWidget(cimke(tr("VÁLASSZ, AKÁR TÖBBET IS"), "monohalvany")) fej.addStretch(1) mind = gomb(tr("Mind kijelölése"), kicsi=True) mind.clicked.connect(self._mind) fej.addWidget(mind) lista.addLayout(fej) for o in self.app.get("options", []): jelolo = QCheckBox(o["name"]) jelolo.setMinimumWidth(130) jelolo.toggled.connect(lambda _: self._gombok_opcio()) kontener = KattinthatoSor(jelolo) sor = QHBoxLayout(kontener) sor.setContentsMargins(0, 2, 0, 2) sor.setSpacing(10) sor.addWidget(jelolo) leiras = cimke(katalogus.loc(o.get("desc")), "halvany") sor.addWidget(leiras, 1) allapot = cimke(tr("TELEPÍTVE"), "allapotcimke") allapot.setProperty("szin", "zold") sor.addWidget(allapot) lista.addWidget(kontener) self.opciok.append((jelolo, allapot, o)) doboz.addLayout(lista) def _mind(self): mind = all(j.isChecked() for j, _, _ in self.opciok) for j, _, _ in self.opciok: j.setChecked(not mind) def _sor_jelolve(self, jelolve): if self.opciok: for j, _, _ in self.opciok: j.blockSignals(True) j.setChecked(jelolve) j.blockSignals(False) self._gombok_opcio() self.oldal.kijeles_valtozott() def torol_kijeles(self): self.jelolo.setChecked(False) def telepitendo(self): if self.app["type"] == "choice": opciok = self._kijelolt(False) return (self.app, opciok) if opciok else None if self.jelolo.isChecked() and not self.telepitve and self.app["type"] != "message": return (self.app, None) return None def eltavolitando(self): if self.app["type"] == "choice": opciok = self._kijelolt(True) return (self.app, opciok) if opciok else None if self.jelolo.isChecked() and self.telepitve and katalogus.eltavolithato(self.app): return (self.app, None) return None def _kijelolt(self, telepitett): return [ o["id"] for j, _, o in self.opciok if j.isChecked() and katalogus.opcio_telepitve(o, self.oldal.index) == telepitett ] def _gombok_opcio(self): uj = self._kijelolt(False) regi = self._kijelolt(True) self.jelolo.blockSignals(True) self.jelolo.setChecked(any(j.isChecked() for j, _, _ in self.opciok)) self.jelolo.blockSignals(False) self.oldal.kijeles_valtozott() self.gomb.setText(tr("Telepítés ({0})", len(uj)) if uj else tr("Telepítés")) self.gomb.setEnabled(bool(uj)) self.gomb.setProperty("fo", True) frissit_stilus(self.gomb) self.eltavolit_gomb.setText(tr("Eltávolítás ({0})", len(regi)) if regi else tr("Eltávolítás")) self.eltavolit_gomb.setEnabled(bool(regi)) def _opcio_muvelet(self, telepites): kijelolt = self._kijelolt(not telepites) if kijelolt: self.oldal.muvelet(self.app, telepites, kijelolt) def frissit(self, index): if self.app["type"] == "choice": db = 0 for _, allapot, o in self.opciok: fent = katalogus.opcio_telepitve(o, index) allapot.setVisible(fent) db += fent self.telepitve = db > 0 self.allapot.setText(tr("{0} / {1} TELEPÍTVE", db, len(self.opciok))) self.allapot.setVisible(db > 0) self._gombok_opcio() return if self.app["type"] == "message": self.gomb.setText(tr("Tudnivalók")) self.gomb.setProperty("fo", False) else: self.telepitve = katalogus.telepitve(self.app, index) self.allapot.setVisible(self.telepitve) if self.telepitve: self.gomb.setText(tr("Eltávolítás")) self.gomb.setEnabled(katalogus.eltavolithato(self.app)) self.gomb.setProperty("fo", False) else: self.gomb.setText(tr("Telepítés")) self.gomb.setEnabled(True) self.gomb.setProperty("fo", True) frissit_stilus(self.gomb) def _kattint(self): if self.app["type"] == "message": QMessageBox.information(self, self.app["name"], katalogus.loc(self.app.get("message"))) return if self.app["type"] == "choice": self._opcio_muvelet(True) return self.oldal.muvelet(self.app, not self.telepitve) class Csoport(QWidget): def __init__(self, nev): super().__init__() self.nev = nev doboz = QVBoxLayout(self) doboz.setContentsMargins(0, 0, 0, 0) doboz.setSpacing(10) self.fejlec = cimke("", "h2") doboz.addWidget(self.fejlec) self.lista = Kartya(terkoz=0, margo=0) doboz.addWidget(self.lista) self.sorok = [] def hozzaad(self, sor): self.sorok.append(sor) self.lista.elrendezes.addWidget(sor) def szur(self, lathatok): db = 0 utolso = None for sor in self.sorok: lathato = sor in lathatok sor.setVisible(lathato) sor.setProperty("utolso", False) if lathato: db += 1 utolso = sor if utolso: utolso.setProperty("utolso", True) for sor in self.sorok: frissit_stilus(sor) self.fejlec.setText(f"{self.nev.upper()} · {db}") self.setVisible(db > 0) return db class Alkalmazasok(Oldal): def __init__(self, kozpont): super().__init__(kozpont, "PACMAN · AUR · FLATPAK", tr("Alkalmazások")) self.katalogus = [] self.index = {"pacman": set(), "flatpak": set()} self.sorok = [] self.csoportok = {} self.kategoria = "all" self.kereso = QLineEdit() self.kereso.setPlaceholderText(tr("Keresés, pl. Steam, OBS, Discord")) self.kereso.setClearButtonEnabled(True) self.kereso.setMinimumWidth(220) self.kereso.setMaximumWidth(340) self.kereso.textChanged.connect(self._szur) self.fejlec_gomb(self.kereso) pillek = QHBoxLayout() pillek.setSpacing(8) self.pillek = {} for azon, nev in katalogus.KATEGORIAK + [(CSAK_TELEPITETT, tr("Csak telepítettek"))]: p = QPushButton(nev) p.setObjectName("pill") p.setCursor(Qt.CursorShape.PointingHandCursor) p.clicked.connect(lambda _=False, a=azon: self._kategoria(a)) self.pillek[azon] = p if azon == CSAK_TELEPITETT: pillek.addStretch(1) pillek.addWidget(p) self.torzs.addLayout(pillek) self.kiemelt = Kartya(terkoz=8, margo=24) self.kiemelt.setObjectName("kiemelt") ks = QHBoxLayout() ks.setSpacing(24) kszoveg = QVBoxLayout() kszoveg.setSpacing(6) kszoveg.addWidget(cimke(tr("CSOMAG · GAMING ALAPOK"), "eyebrow")) kszoveg.addWidget(cimke(tr("EGY KATTINTÁS, MINDEN AMI JÁTÉKHOZ KELL"), "h2", True)) kszoveg.addWidget( cimke(tr("Steam (Proton-GE-vel), Lutris, Heroic, GameMode és MangoHud egyben, előre beállítva."), "masodlagos", True) ) ks.addLayout(kszoveg, 1) self.kiemelt_gomb = gomb(tr("Csomag telepítése"), fo=True) self.kiemelt_gomb.clicked.connect(self._gaming_alapok) ks.addWidget(self.kiemelt_gomb, 0, Qt.AlignmentFlag.AlignVCenter) self.kiemelt.elrendezes.addLayout(ks) self.torzs.addWidget(self.kiemelt) self.hiba = cimke("", "figyelem", True) self.hiba.hide() self.torzs.addWidget(self.hiba) self._kijeles_sav() self.lista = QVBoxLayout() self.lista.setSpacing(28) self.torzs.addLayout(self.lista) self.ures = cimke(tr("Nincs találat."), "halvany") self.ures.hide() self.torzs.addWidget(self.ures) self.torzs.addStretch(1) self._betolt() self._kategoria("all") def _kijeles_sav(self): self.sav = QFrame(self) self.sav.setObjectName("kijelessav") s = QHBoxLayout(self.sav) s.setContentsMargins(48, 12, 48, 12) s.setSpacing(8) self.sav_szoveg = cimke("", "mono") s.addWidget(self.sav_szoveg) s.addStretch(1) torles = gomb(tr("Kijelölés törlése"), kicsi=True) torles.clicked.connect(self._kijeles_torles) s.addWidget(torles) self.sav_eltavolit = gomb(tr("Kijelöltek eltávolítása")) self.sav_eltavolit.clicked.connect(lambda: self._tomeges(False)) s.addWidget(self.sav_eltavolit) self.sav_telepit = gomb(tr("Kijelöltek telepítése"), fo=True) self.sav_telepit.clicked.connect(lambda: self._tomeges(True)) s.addWidget(self.sav_telepit) self.sav.hide() def resizeEvent(self, esemeny): super().resizeEvent(esemeny) magassag = self.sav.sizeHint().height() self.sav.setGeometry(0, self.height() - magassag, self.width(), magassag) def kijeles_valtozott(self): if not hasattr(self, "sav"): return uj = [x for x in (s.telepitendo() for s in self.sorok) if x] regi = [x for x in (s.eltavolitando() for s in self.sorok) if x] kijelolt = sum(1 for s in self.sorok if s.jelolo.isChecked()) latszik = kijelolt > 0 self.sav.setVisible(latszik) self.setViewportMargins(0, 0, 0, self.sav.sizeHint().height() if latszik else 0) self.sav_szoveg.setText(tr("{0} KIJELÖLVE", kijelolt)) self.sav_telepit.setText(tr("Kijelöltek telepítése ({0})", len(uj))) self.sav_telepit.setEnabled(bool(uj)) self.sav_eltavolit.setText(tr("Kijelöltek eltávolítása ({0})", len(regi))) self.sav_eltavolit.setEnabled(bool(regi)) if latszik: self.sav.raise_() magassag = self.sav.sizeHint().height() self.sav.setGeometry(0, self.height() - magassag, self.width(), magassag) def _kijeles_torles(self): for s in self.sorok: s.torol_kijeles() def _nev(self, app, opciok): if opciok: return ", ".join(f"{app['name']}: {o['name']}" for o in app.get("options", []) if o["id"] in opciok) return app["name"] def _tomeges(self, telepites): tetelek = [x for x in ((s.telepitendo() if telepites else s.eltavolitando()) for s in self.sorok) if x] if not tetelek: return nevek = [self._nev(app, opciok) for app, opciok in tetelek] if not telepites: valasz = QMessageBox.question( self, tr("Eltávolítás"), tr("Biztosan eltávolítod ezeket?\n\n") + "\n".join(nevek), QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No, ) if valasz != QMessageBox.StandardButton.Yes: return lepesek = [] for app, opciok in tetelek: for lepes in katalogus.lepesek(app, telepites, opciok): lepes.kotelezo = False lepesek.append(lepes) if not lepesek: return cim = ( tr("Telepítés: {0} alkalmazás", len(tetelek)) if telepites else tr("Eltávolítás: {0} alkalmazás", len(tetelek)) ) FolyamatAblak(self, cim, lepesek, tr("Minden lépés sikeresen lefutott."), tr("Nem minden lépés sikerült.")).exec() self._kijeles_torles() self.megjelenik() def _betolt(self): try: self.katalogus = katalogus.betolt() except (OSError, ValueError, RuntimeError) as e: self.hiba.setText(tr("Az alkalmazáskatalógus nem tölthető be: {0}", e)) self.hiba.show() return for azon, nev in katalogus.KATEGORIAK[1:]: csoport = Csoport(nev) self.csoportok[azon] = csoport self.lista.addWidget(csoport) for app in self.katalogus: csoport = self.csoportok.get(app["category"]) or self.csoportok["System"] sor = AppSor(app, self) self.sorok.append(sor) csoport.hozzaad(sor) def megjelenik(self, *_): gyorsitott("telepitett", katalogus.telepitett_index, kesz=self._index_kesz, kor=30) def _index_kesz(self, index): if index == self.index: return self.index = index for s in self.sorok: s.frissit(index) alap = [a for a in self.katalogus if a["id"] in katalogus.GAMING_ALAPOK] hianyzik = [a for a in alap if not katalogus.telepitve(a, index)] self.kiemelt_gomb.setEnabled(bool(hianyzik)) self.kiemelt_gomb.setText(tr("Csomag telepítése") if hianyzik else tr("Minden telepítve")) self._szur() def _kategoria(self, azon): self.kategoria = azon for a, p in self.pillek.items(): p.setProperty("aktiv", a == azon) frissit_stilus(p) self._szur() def _szur(self): szoveg = self.kereso.text().strip().lower() lathatok = set() for s in self.sorok: app = s.app if self.kategoria == CSAK_TELEPITETT: jo = s.telepitve else: jo = self.kategoria == "all" or app["category"] == self.kategoria if jo and (not szoveg or szoveg in app["name"].lower() or szoveg in katalogus.loc(app.get("desc")).lower()): lathatok.add(s) osszes = sum(c.szur(lathatok) for c in self.csoportok.values()) self.ures.setText( tr("Még nincs telepítve egyetlen alkalmazás sem a listából.") if self.kategoria == CSAK_TELEPITETT and not szoveg else tr("Nincs találat.") ) self.ures.setVisible(osszes == 0) self.kiemelt.setVisible(self.kategoria in ("all", "Games") and not szoveg) def muvelet(self, app, telepites, opciok=None): if not telepites: nevek = ", ".join(o["name"] for o in app.get("options", []) if o["id"] in (opciok or [])) or app["name"] valasz = QMessageBox.question( self, tr("Eltávolítás"), tr("Biztosan eltávolítod: {0}?", nevek), QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No, ) if valasz != QMessageBox.StandardButton.Yes: return lepesek = katalogus.lepesek(app, telepites, opciok) if not lepesek: return cim = tr("Telepítés: {0}", app["name"]) if telepites else tr("Eltávolítás: {0}", app["name"]) kesz = tr("{0} telepítve.", app["name"]) if telepites else tr("{0} eltávolítva.", app["name"]) FolyamatAblak(self, cim, lepesek, kesz).exec() self.megjelenik() def _gaming_alapok(self): lepesek = [] for app in self.katalogus: if app["id"] in katalogus.GAMING_ALAPOK and not katalogus.telepitve(app, self.index): lepesek += katalogus.lepesek(app, True) if not lepesek: return FolyamatAblak(self, tr("Gaming alapok telepítése"), lepesek, tr("A Gaming alapok telepítve.")).exec() self.megjelenik() OLDAL = Alkalmazasok