summaryrefslogtreecommitdiff
path: root/raveos-center/raveos_center/oldalak/rendszer
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-center/raveos_center/oldalak/rendszer')
-rw-r--r--raveos-center/raveos_center/oldalak/rendszer/__init__.py49
-rw-r--r--raveos-center/raveos_center/oldalak/rendszer/driverek.py159
-rw-r--r--raveos-center/raveos_center/oldalak/rendszer/gaming.py306
-rw-r--r--raveos-center/raveos_center/oldalak/rendszer/karbantartas.py177
-rw-r--r--raveos-center/raveos_center/oldalak/rendszer/mentes.py283
-rw-r--r--raveos-center/raveos_center/oldalak/rendszer/secureboot.py256
-rw-r--r--raveos-center/raveos_center/oldalak/rendszer/snapshotok.py247
7 files changed, 1477 insertions, 0 deletions
diff --git a/raveos-center/raveos_center/oldalak/rendszer/__init__.py b/raveos-center/raveos_center/oldalak/rendszer/__init__.py
new file mode 100644
index 0000000..60b5768
--- /dev/null
+++ b/raveos-center/raveos_center/oldalak/rendszer/__init__.py
@@ -0,0 +1,49 @@
+import importlib
+
+from raveos_center.elemek import Fulsor, Oldal, Verem
+
+AZON = "rendszer"
+MENU = "Rendszer"
+IKON = "rendszer"
+
+FULEK = ["driverek", "gaming", "karbantartas", "snapshotok", "secureboot", "mentes"]
+
+
+class Rendszer(Oldal):
+ def __init__(self, kozpont):
+ super().__init__(kozpont, "DRIVEREK · GAMING · KARBANTARTÁS · SNAPSHOTOK", "Rendszer", kitolt=True)
+ self.fulek = {}
+ modulok = [importlib.import_module(f"{__name__}.{nev}") for nev in FULEK]
+ self.fulsor = Fulsor([(m.AZON, m.CIM) for m in modulok], self.valt)
+ self.torzs.addWidget(self.fulsor)
+ self.verem = Verem()
+ for m in modulok:
+ ful = m.FUL(kozpont)
+ self.fulek[m.AZON] = ful
+ self.verem.addWidget(ful)
+ self.torzs.addWidget(self.verem, 1)
+ self.aktiv = modulok[0].AZON if modulok else None
+ if self.aktiv:
+ self.fulsor.aktiv(self.aktiv)
+
+ def valt(self, azon, *args):
+ if azon not in self.fulek:
+ return
+ self.aktiv = azon
+ self.fulsor.aktiv(azon)
+ self.verem.setCurrentWidget(self.fulek[azon])
+ self.fulek[azon].megjelenik(*args)
+
+ def elerheto(self, ful=None, *_):
+ return ful is None or ful in self.fulek
+
+ def megjelenik(self, ful=None, *args):
+ self.valt(ful if ful in self.fulek else self.aktiv, *args)
+
+ def indulaskor(self):
+ for ful in self.fulek.values():
+ if hasattr(ful, "indulaskor"):
+ ful.indulaskor()
+
+
+OLDAL = Rendszer
diff --git a/raveos-center/raveos_center/oldalak/rendszer/driverek.py b/raveos-center/raveos_center/oldalak/rendszer/driverek.py
new file mode 100644
index 0000000..499e87a
--- /dev/null
+++ b/raveos-center/raveos_center/oldalak/rendszer/driverek.py
@@ -0,0 +1,159 @@
+from PyQt6.QtCore import Qt
+from PyQt6.QtWidgets import QHBoxLayout, QMessageBox, QVBoxLayout, QWidget
+
+from raveos_center import driverek, muveletek
+from raveos_center.elemek import Kartya, cimke, gomb
+from raveos_center.folyamat import FolyamatAblak
+from raveos_center.hatter import ervenytelenit, gyorsitott
+
+AZON = "driverek"
+CIM = "Driverek"
+
+
+class EszkozSor(QWidget):
+ def __init__(self, elem, telepit):
+ super().__init__()
+ self.setObjectName("appsor")
+ self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
+ sor = QHBoxLayout(self)
+ sor.setContentsMargins(16, 12, 16, 12)
+ sor.setSpacing(16)
+ szovegek = QVBoxLayout()
+ szovegek.setSpacing(3)
+ nev = cimke(elem["nev"], tordel=True)
+ nev.setStyleSheet("font-size: 14px; font-weight: 600;")
+ szovegek.addWidget(nev)
+ szovegek.addWidget(cimke(f"Jelenlegi driver: {elem['jelenlegi'] or 'nincs betöltve'}", "monohalvany"))
+ if elem["hianyzik"]:
+ hiany = cimke(f"Hiányzó csomagok: {' '.join(elem['hianyzik'])}", "monohalvany", True)
+ hiany.setStyleSheet("color: #d9a441;")
+ szovegek.addWidget(hiany)
+ if elem["megjegyzes"]:
+ szovegek.addWidget(cimke(elem["megjegyzes"], "halvany", True))
+ sor.addLayout(szovegek, 1)
+ if elem["hianyzik"]:
+ g = gomb("Ajánlott telepítése", fo=True, kicsi=True)
+ g.setEnabled(muveletek.helper_elerheto())
+ g.clicked.connect(lambda: telepit([elem]))
+ sor.addWidget(g, 0, Qt.AlignmentFlag.AlignVCenter)
+ else:
+ rendben = cimke("RENDBEN", "allapotcimke")
+ rendben.setProperty("szin", "zold")
+ sor.addWidget(rendben, 0, Qt.AlignmentFlag.AlignVCenter)
+
+
+class Driverek(QWidget):
+ def __init__(self, kozpont):
+ super().__init__()
+ self.kozpont = kozpont
+ self.elemek = []
+ self.kapott = None
+ doboz = QVBoxLayout(self)
+ doboz.setContentsMargins(0, 20, 0, 0)
+ doboz.setSpacing(16)
+ fej = QHBoxLayout()
+ fej.addWidget(
+ cimke(
+ "A RaveOS felismeri a géped eszközeit, és megmutatja, melyikhez van ajánlott driver. "
+ "A videokártya drivere a telepítéskor is ugyanígy kerül fel.",
+ "masodlagos",
+ True,
+ ),
+ 1,
+ )
+ self.ujra = gomb("Újraellenőrzés", kicsi=True)
+ self.ujra.clicked.connect(self.frissit)
+ fej.addWidget(self.ujra, 0, Qt.AlignmentFlag.AlignTop)
+ self.mind = gomb("Minden ajánlott telepítése", fo=True, kicsi=True)
+ self.mind.clicked.connect(lambda: self._telepit([e for e in self.elemek if e["hianyzik"]]))
+ self.mind.hide()
+ fej.addWidget(self.mind, 0, Qt.AlignmentFlag.AlignTop)
+ doboz.addLayout(fej)
+ self.figyelem = cimke("", "figyelem", True)
+ self.figyelem.hide()
+ doboz.addWidget(self.figyelem)
+ self.lista = QVBoxLayout()
+ self.lista.setSpacing(20)
+ doboz.addLayout(self.lista)
+ doboz.addStretch(1)
+
+ def megjelenik(self, *_):
+ gyorsitott("driverek", driverek.allapot, kesz=self._kesz, hiba=self._hiba, kor=120)
+
+ def frissit(self):
+ self.ujra.setEnabled(False)
+ ervenytelenit("driverek")
+ gyorsitott("driverek", driverek.allapot, kesz=self._kesz, hiba=self._hiba)
+
+ def _hiba(self, uzenet):
+ self.ujra.setEnabled(True)
+ self.figyelem.setText(f"A hardver felismerése nem sikerült: {uzenet}")
+ self.figyelem.show()
+
+ def _kesz(self, elemek):
+ self.ujra.setEnabled(True)
+ if elemek == self.kapott:
+ return
+ self.kapott = elemek
+ self.elemek = elemek
+ while self.lista.count():
+ w = self.lista.takeAt(0).widget()
+ if w:
+ w.deleteLater()
+ if not muveletek.helper_elerheto():
+ self.figyelem.setText("A RaveOS Center rendszerhelpere nincs telepítve, ezért driver nem telepíthető.")
+ self.figyelem.show()
+ else:
+ self.figyelem.hide()
+ if driverek.szkript() is None:
+ self.figyelem.setText("A driverfelismerő szkript nincs telepítve.")
+ self.figyelem.show()
+ for azon, nev in driverek.KATEGORIAK:
+ sajat = [e for e in elemek if e["kategoria"] == azon]
+ if not sajat:
+ continue
+ csoport = QWidget()
+ cs = QVBoxLayout(csoport)
+ cs.setContentsMargins(0, 0, 0, 0)
+ cs.setSpacing(10)
+ cs.addWidget(cimke(nev.upper(), "h2"))
+ kartya = Kartya(terkoz=0, margo=0)
+ for i, e in enumerate(sajat):
+ sor = EszkozSor(e, self._telepit)
+ sor.setProperty("utolso", i == len(sajat) - 1)
+ kartya.elrendezes.addWidget(sor)
+ cs.addWidget(kartya)
+ self.lista.addWidget(csoport)
+ if not elemek:
+ self.lista.addWidget(cimke("Nem található kezelhető eszköz.", "halvany"))
+ hianyzo = [e for e in elemek if e["hianyzik"]]
+ self.mind.setVisible(len(hianyzo) > 1)
+ self.mind.setEnabled(muveletek.helper_elerheto())
+
+ def _telepit(self, elemek):
+ if not elemek:
+ return
+ lepesek = []
+ egyeb = []
+ if any(e["gpu"] for e in elemek):
+ lepesek.append(muveletek.Lepes("Videokártya driverek", muveletek.root("driverek")))
+ for e in elemek:
+ if not e["gpu"]:
+ egyeb += [p for p in e["hianyzik"] if p not in egyeb]
+ if egyeb:
+ lepesek.append(muveletek.Lepes("További driverek", muveletek.root("telepit", *egyeb)))
+ ablak = FolyamatAblak(self, "Driverek telepítése", lepesek, "A driverek telepítve.")
+ ablak.exec()
+ if ablak.rendben and any(driverek.ujrainditas_kell(e) for e in elemek):
+ doboz = QMessageBox(self)
+ doboz.setWindowTitle("Újraindítás szükséges")
+ doboz.setText("Az új videokártya-driver az újraindítás után töltődik be.")
+ most = doboz.addButton("Újraindítás most", QMessageBox.ButtonRole.AcceptRole)
+ doboz.addButton("Később", QMessageBox.ButtonRole.RejectRole)
+ doboz.exec()
+ if doboz.clickedButton() is most:
+ muveletek.Futtato(self).indit([muveletek.Lepes("Újraindítás", ["systemctl", "reboot"])])
+ self.frissit()
+
+
+FUL = Driverek
diff --git a/raveos-center/raveos_center/oldalak/rendszer/gaming.py b/raveos-center/raveos_center/oldalak/rendszer/gaming.py
new file mode 100644
index 0000000..5d410e9
--- /dev/null
+++ b/raveos-center/raveos_center/oldalak/rendszer/gaming.py
@@ -0,0 +1,306 @@
+from PyQt6.QtCore import QObject, Qt, pyqtSignal
+from PyQt6.QtWidgets import QComboBox, QHBoxLayout, QMessageBox, QProgressBar, QVBoxLayout, QWidget
+
+from raveos_center import gaming, muveletek, proton
+from raveos_center.elemek import Kapcsolo, Kartya, cimke, gomb
+from raveos_center.folyamat import FolyamatAblak
+from raveos_center.hatter import ervenytelenit, gyorsitott, hatterben, tarolt
+
+AZON = "gaming"
+CIM = "Gaming"
+
+BEALLITASOK = [
+ ("gamemode", "GameMode", "CPU és I/O prioritás játék közben. A Lutris és a Heroic magától használja, Steamben a "
+ "játék indítási opciójába írd: gamemoderun %command%"),
+ ("mangohud", "MangoHud alapból", "FPS, hőmérséklet és terhelés kijelzése minden Vulkan és OpenGL játékban. "
+ "Játék közben a jobb Shift + F12 elrejti, a jobb Shift + F10 vált a kijelző módok között."),
+ ("utemezo", "Játékra hangolt ütemező", "Az scx_lavd ütemező gaming módban: egyenletesebb képkockaidő, amikor a "
+ "háttérben más is fut. Kikapcsolva a kernel saját BORE ütemezője dolgozik."),
+ ("gamescope", "Gamescope session", "Külön, konzolszerű Steam játékmenet, a bejelentkező képernyőn választható."),
+ ("governor", "Performance CPU governor", "Játék közben teljes órajel, a játék bezárása után visszaáll."),
+ ("ntsync", "NTSync", "Gyorsabb Windows-szinkronizáció Wine és Proton alatt."),
+]
+
+
+class _Jelzo(QObject):
+ haladas = pyqtSignal(int)
+
+
+def alkalmaz(szulo, valtozasok):
+ lepesek = []
+ helyi = []
+ for azon, be in valtozasok:
+ l, h = gaming.lepesek(azon, be)
+ lepesek += l
+ if h:
+ helyi.append(h)
+ if lepesek:
+ ablak = FolyamatAblak(szulo, "Gaming beállítások", lepesek, "A beállítás elkészült.")
+ ablak.exec()
+ if not ablak.rendben:
+ return "A beállítás nem sikerült teljesen, a részleteket a napló mutatja."
+ for h in helyi:
+ try:
+ h()
+ except OSError as e:
+ return f"A beállítás nem sikerült: {e}"
+ return None
+
+
+class Sor(QWidget):
+ def __init__(self, nev, leiras, utolso=False):
+ super().__init__()
+ self.setObjectName("appsor")
+ self.setProperty("utolso", utolso)
+ self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
+ self.sor = QHBoxLayout(self)
+ self.sor.setContentsMargins(16, 14, 16, 14)
+ self.sor.setSpacing(16)
+ self.szovegek = QVBoxLayout()
+ self.szovegek.setSpacing(3)
+ cim = cimke(nev)
+ cim.setStyleSheet("font-size: 14px; font-weight: 600;")
+ self.szovegek.addWidget(cim)
+ self.szovegek.addWidget(cimke(leiras, "halvany", True))
+ self.megjegyzes = cimke("", "monohalvany", True)
+ self.megjegyzes.hide()
+ self.szovegek.addWidget(self.megjegyzes)
+ self.sor.addLayout(self.szovegek, 1)
+
+ def jegyzet(self, szoveg):
+ self.megjegyzes.setText(szoveg)
+ self.megjegyzes.setVisible(bool(szoveg))
+
+
+class BeallitasSor(Sor):
+ def __init__(self, azon, nev, leiras, valt, utolso=False):
+ super().__init__(nev, leiras, utolso)
+ self.azon = azon
+ self.kapcsolo = Kapcsolo()
+ self.kapcsolo.setAccessibleName(nev)
+ self.kapcsolo.clicked.connect(lambda be: valt(self.azon, be))
+ self.sor.addWidget(self.kapcsolo, 0, Qt.AlignmentFlag.AlignVCenter)
+
+ def beallit(self, adat, foglalt):
+ self.kapcsolo.blockSignals(True)
+ self.kapcsolo.setChecked(adat["aktiv"])
+ self.kapcsolo.blockSignals(False)
+ helper = muveletek.helper_elerheto() or not adat["root"]
+ self.kapcsolo.setEnabled(adat["elerheto"] and helper and not foglalt)
+ self.jegyzet(adat["megjegyzes"])
+ self.kapcsolo.update()
+
+
+class ProtonGeSor(Sor):
+ def __init__(self, szulo):
+ super().__init__(
+ "Proton-GE",
+ "A GloriousEggroll Proton-változata, több játékhoz tartalmaz javítást és videokodeket. A Steam "
+ "újraindítása után a játék Tulajdonságok > Kompatibilitás menüjében választható.",
+ )
+ self.szulo = szulo
+ self.kiadas = None
+ self.fut = False
+ self.jelzo = _Jelzo()
+ self.sav = QProgressBar()
+ self.sav.setObjectName("sav")
+ self.sav.setTextVisible(False)
+ self.sav.setFixedHeight(6)
+ self.sav.hide()
+ self.jelzo.haladas.connect(self.sav.setValue)
+ self.szovegek.addWidget(self.sav)
+ gombok = QVBoxLayout()
+ gombok.setSpacing(6)
+ self.telepit_gomb = gomb("Legújabb telepítése", fo=True, kicsi=True)
+ self.telepit_gomb.clicked.connect(self._telepit)
+ self.regiek_gomb = gomb("Régiek törlése", kicsi=True)
+ self.regiek_gomb.clicked.connect(self._regiek)
+ self.torol_gomb = gomb("Mind törlése", kicsi=True)
+ self.torol_gomb.clicked.connect(self._mind)
+ for g in (self.telepit_gomb, self.regiek_gomb, self.torol_gomb):
+ gombok.addWidget(g)
+ gombok.addStretch(1)
+ self.sor.addLayout(gombok)
+
+ def frissit(self):
+ if self.fut:
+ return
+ self._mutat()
+ gyorsitott("proton_ge", proton.legujabb, kesz=self._kiadas, hiba=lambda _: self._kiadas(None), kor=3600)
+
+ def _kiadas(self, kiadas):
+ self.kiadas = kiadas or self.kiadas
+ if not self.fut:
+ self._mutat()
+
+ def _mutat(self, szoveg=None):
+ lista = proton.telepitett()
+ van_steam = bool(proton.celmappak())
+ naprakesz = bool(self.kiadas and lista and lista[0] == self.kiadas["nev"])
+ if szoveg is None:
+ szoveg = f"Telepítve: {', '.join(lista)}" if lista else "Nincs telepítve."
+ if self.kiadas and not naprakesz:
+ szoveg += f" Legújabb: {self.kiadas['nev']}"
+ if not van_steam:
+ szoveg = "Nem található Steam. Telepítsd, és indítsd el egyszer."
+ self.jegyzet(szoveg)
+ self.telepit_gomb.setText("Naprakész" if naprakesz else "Legújabb telepítése")
+ self.telepit_gomb.setEnabled(not self.fut and not naprakesz and van_steam)
+ self.regiek_gomb.setVisible(bool(proton.regiek()))
+ self.regiek_gomb.setEnabled(not self.fut)
+ self.torol_gomb.setVisible(bool(lista))
+ self.torol_gomb.setEnabled(not self.fut)
+
+ def _telepit(self):
+ self.fut = True
+ self.sav.setValue(0)
+ self.sav.show()
+ self._mutat("Letöltés és ellenőrzés, ez néhány percig tarthat.")
+ hatterben(self._letolt, kesz=self._kesz, hiba=self._hiba)
+
+ def _letolt(self):
+ kiadas = self.kiadas or proton.legujabb()
+ proton.telepit(kiadas, self.jelzo.haladas.emit)
+ return kiadas
+
+ def _kesz(self, kiadas):
+ self.fut = False
+ self.kiadas = kiadas
+ self.sav.hide()
+ self._mutat()
+
+ def _hiba(self, uzenet):
+ self.fut = False
+ self.sav.hide()
+ self._mutat()
+ QMessageBox.warning(self.szulo, "Proton-GE", f"A telepítés nem sikerült: {uzenet}")
+
+ def _torles(self, parok, kerdes):
+ if not parok or QMessageBox.question(self.szulo, "Proton-GE", kerdes) != QMessageBox.StandardButton.Yes:
+ return
+ try:
+ for mappa, nev in parok:
+ proton.torol(nev, [mappa] if mappa else None)
+ except OSError as e:
+ QMessageBox.warning(self.szulo, "Proton-GE", f"A törlés nem sikerült: {e}")
+ self._mutat()
+
+ def _regiek(self):
+ parok = proton.regiek()
+ nevek = ", ".join(sorted({n for _, n in parok}))
+ self._torles(parok, f"Törlöd a régebbi verziókat ({nevek})? Minden Steam-telepítésben a legújabb megmarad.")
+
+ def _mind(self):
+ self._torles(
+ [(None, n) for n in proton.telepitett()],
+ "Törlöd az összes Proton-GE verziót? Az ezeket használó játékok a Steam alap Protonjára váltanak.",
+ )
+
+
+class Gaming(QWidget):
+ def __init__(self, kozpont):
+ super().__init__()
+ self.kozpont = kozpont
+ self.adat = None
+ self.foglalt = False
+ self.hibauzenet = ""
+ doboz = QVBoxLayout(self)
+ doboz.setContentsMargins(0, 20, 0, 0)
+ doboz.setSpacing(16)
+ doboz.addWidget(
+ cimke(
+ "Játékhoz hasznos beállítások. Mindegyik bármikor visszakapcsolható. Az Áttekintés Gaming mód "
+ "kapcsolója a GameMode-ot, a performance governort, az NTSync-et és a játékra hangolt ütemezőt "
+ "kapcsolja egyszerre.",
+ "masodlagos",
+ True,
+ )
+ )
+ self.figyelem = cimke("", "figyelem", True)
+ self.figyelem.hide()
+ doboz.addWidget(self.figyelem)
+
+ kartya = Kartya(terkoz=0, margo=0)
+ self.sorok = {}
+ for i, (azon, nev, leiras) in enumerate(BEALLITASOK):
+ sor = BeallitasSor(azon, nev, leiras, self.valt, i == len(BEALLITASOK) - 1)
+ self.sorok[azon] = sor
+ kartya.elrendezes.addWidget(sor)
+ self.hud_mod = QComboBox()
+ for mod, nev in gaming.MANGOHUD_MODOK:
+ self.hud_mod.addItem(nev, mod)
+ self.hud_mod.activated.connect(self._hud_mod)
+ hud_sor = QHBoxLayout()
+ hud_sor.setSpacing(8)
+ hud_sor.addWidget(cimke("Kijelző:", "halvany"))
+ hud_sor.addWidget(self.hud_mod)
+ hud_sor.addStretch(1)
+ self.sorok["mangohud"].szovegek.addSpacing(6)
+ self.sorok["mangohud"].szovegek.addLayout(hud_sor)
+ doboz.addWidget(kartya)
+
+ doboz.addSpacing(8)
+ doboz.addWidget(cimke("PROTON VERZIÓK", "h2"))
+ proton_kartya = Kartya(terkoz=0, margo=0)
+ self.proton_ge = ProtonGeSor(self)
+ proton_kartya.elrendezes.addWidget(self.proton_ge)
+ self.sorok["proton_cachyos"] = BeallitasSor(
+ "proton_cachyos",
+ "Proton-CachyOS",
+ "A CachyOS Proton-változata a rendszer csomagkezelőjéből, a rendszerfrissítéssel együtt frissül. "
+ "Kb. 1,6 GB. A Steam újraindítása után választható.",
+ self.valt,
+ True,
+ )
+ proton_kartya.elrendezes.addWidget(self.sorok["proton_cachyos"])
+ doboz.addWidget(proton_kartya)
+ doboz.addStretch(1)
+
+ def megjelenik(self, *_):
+ self.frissit()
+ self.proton_ge.frissit()
+
+ def frissit(self):
+ if tarolt("gaming") is None:
+ self.foglalt = True
+ for sor in self.sorok.values():
+ sor.kapcsolo.setEnabled(False)
+ gyorsitott("gaming", gaming.allapot, kesz=self._kesz, hiba=lambda _: self._kesz(self.adat), kor=30)
+
+ def _kesz(self, adat):
+ self.foglalt = False
+ index = self.hud_mod.findData(gaming.mangohud_mod())
+ self.hud_mod.setCurrentIndex(max(0, index))
+ if adat is None:
+ self._figyelmeztet("Az állapot nem olvasható be, próbáld újra a fül újbóli megnyitásával.")
+ return
+ self.adat = adat
+ for azon, sor in self.sorok.items():
+ sor.beallit(adat[azon], self.foglalt)
+ if self.hibauzenet:
+ self._figyelmeztet(self.hibauzenet)
+ elif not muveletek.helper_elerheto():
+ self._figyelmeztet("A RaveOS Center rendszerhelpere nincs telepítve, a legtöbb beállítás nem módosítható.")
+ else:
+ self.figyelem.hide()
+
+ def _figyelmeztet(self, szoveg):
+ self.figyelem.setText(szoveg)
+ self.figyelem.show()
+
+ def _hud_mod(self):
+ try:
+ gaming.mangohud_mod_beallit(self.hud_mod.currentData())
+ except OSError as e:
+ QMessageBox.warning(self, "MangoHud", f"A beállítás nem sikerült: {e}")
+
+ def valt(self, azon, be):
+ self.alkalmaz([(azon, be)])
+
+ def alkalmaz(self, valtozasok):
+ self.hibauzenet = alkalmaz(self, valtozasok) or ""
+ ervenytelenit("gaming")
+ self.frissit()
+
+
+FUL = Gaming
diff --git a/raveos-center/raveos_center/oldalak/rendszer/karbantartas.py b/raveos-center/raveos_center/oldalak/rendszer/karbantartas.py
new file mode 100644
index 0000000..91b7113
--- /dev/null
+++ b/raveos-center/raveos_center/oldalak/rendszer/karbantartas.py
@@ -0,0 +1,177 @@
+from PyQt6.QtCore import Qt
+from PyQt6.QtWidgets import QDialog, QHBoxLayout, QListWidget, QListWidgetItem, QVBoxLayout, QWidget
+
+from raveos_center import karbantartas, muveletek
+from raveos_center.elemek import Kartya, Racs, cimke, gomb
+from raveos_center.folyamat import FolyamatAblak
+from raveos_center.hatter import gyorsitott, tarolt
+
+AZON = "karbantartas"
+CIM = "Karbantartás"
+
+MUVELETEK = [
+ ("cache", "paccache -rk2", "Csomag cache ürítése",
+ "Minden csomagból csak az utolsó két verzió marad, az eltávolított csomagok fájljai törlődnek.", True),
+ ("arva", "pacman -Qdtq", "Árva csomagok",
+ "Már semmi által nem használt függőségek eltávolítása. Az előnézetben egyenként kiveheted, amit megtartanál.", True),
+ ("naplo", "journalctl --vacuum", "Naplók takarítása",
+ "A két hétnél régebbi rendszernaplók törlése, legfeljebb 100 MB marad.", True),
+ ("tukrok", "reflector", "Tükrök frissítése",
+ "A leggyorsabb közeli letöltési szerverek kiválasztása. A régi lista biztonsági másolatként megmarad.", False),
+ ("kulcsok", "pacman-key --populate", "Kulcsok frissítése",
+ "A csomagaláíró kulcsok újratöltése. Segít, ha a frissítés aláírási hibával áll le.", False),
+ ("flatpak", "flatpak uninstall --unused", "Flatpak takarítás",
+ "A már egyik alkalmazás által sem használt runtime-ok eltávolítása.", True),
+]
+
+
+class ElonezetAblak(QDialog):
+ def __init__(self, szulo, cim, szoveg, elemek, valaszthato, gomb_szoveg):
+ super().__init__(szulo)
+ self.setWindowTitle(cim)
+ self.resize(640, 480)
+ doboz = QVBoxLayout(self)
+ doboz.setContentsMargins(28, 24, 28, 20)
+ doboz.setSpacing(12)
+ doboz.addWidget(cimke("ELŐNÉZET", "eyebrow"))
+ doboz.addWidget(cimke(cim.upper(), "h2", True))
+ doboz.addWidget(cimke(szoveg, "masodlagos", True))
+ self.lista = QListWidget()
+ for elem in elemek:
+ sor = QListWidgetItem(elem)
+ if valaszthato:
+ sor.setFlags(sor.flags() | Qt.ItemFlag.ItemIsUserCheckable)
+ sor.setCheckState(Qt.CheckState.Checked)
+ self.lista.addItem(sor)
+ self.lista.setVisible(bool(elemek))
+ doboz.addWidget(self.lista, 1)
+ if not elemek:
+ doboz.addStretch(1)
+ gombok = QHBoxLayout()
+ gombok.addStretch(1)
+ megse = gomb("Mégse")
+ megse.clicked.connect(self.reject)
+ gombok.addWidget(megse)
+ self.mehet = gomb(gomb_szoveg, fo=True)
+ self.mehet.clicked.connect(self.accept)
+ gombok.addWidget(self.mehet)
+ doboz.addLayout(gombok)
+ if valaszthato:
+ self.lista.itemChanged.connect(lambda _: self.mehet.setEnabled(bool(self.kivalasztott())))
+
+ def kivalasztott(self):
+ return [
+ self.lista.item(i).text()
+ for i in range(self.lista.count())
+ if self.lista.item(i).checkState() == Qt.CheckState.Checked
+ ]
+
+
+class MuveletKartya(Kartya):
+ def __init__(self, parancs, nev, leiras, futtat):
+ super().__init__(terkoz=8, margo=20)
+ self.elrendezes.addWidget(cimke(parancs, "monohalvany"))
+ cim = cimke(nev)
+ cim.setStyleSheet("font-size: 15px; font-weight: 600;")
+ self.elrendezes.addWidget(cim)
+ self.elrendezes.addWidget(cimke(leiras, "halvany", True))
+ self.elrendezes.addStretch(1)
+ self.osszegzes = cimke("Ellenőrzés...", "monozold", True)
+ self.elrendezes.addWidget(self.osszegzes)
+ sor = QHBoxLayout()
+ self.gomb = gomb("Futtatás", kicsi=True)
+ self.gomb.clicked.connect(futtat)
+ sor.addWidget(self.gomb)
+ sor.addStretch(1)
+ self.elrendezes.addLayout(sor)
+
+
+class Karbantartas(QWidget):
+ def __init__(self, kozpont):
+ super().__init__()
+ self.kozpont = kozpont
+ self.adat = {}
+ doboz = QVBoxLayout(self)
+ doboz.setContentsMargins(0, 20, 0, 0)
+ doboz.setSpacing(16)
+ doboz.addWidget(
+ cimke(
+ "Rendszeres takarítás és javítás. A törléssel járó műveletek előtt megmutatjuk, mi kerülne törlésre, "
+ "és csak a megerősítésed után futnak.",
+ "masodlagos",
+ True,
+ )
+ )
+ self.figyelem = cimke("", "figyelem", True)
+ self.figyelem.hide()
+ doboz.addWidget(self.figyelem)
+ self.racs = Racs(260, 12)
+ self.kartyak = {}
+ for azon, parancs, nev, leiras, _ in MUVELETEK:
+ kartya = MuveletKartya(parancs, nev, leiras, lambda _=False, a=azon: self._futtat(a))
+ self.kartyak[azon] = kartya
+ self.racs.hozzaad(kartya)
+ doboz.addWidget(self.racs)
+ doboz.addStretch(1)
+
+ def megjelenik(self, *_):
+ helper = muveletek.helper_elerheto()
+ self.figyelem.setText("A RaveOS Center rendszerhelpere nincs telepítve, a műveletek nem futtathatók.")
+ self.figyelem.setVisible(not helper)
+ for azon in self.kartyak:
+ self._ellenoriz(azon)
+
+ def _ellenoriz(self, azon):
+ kartya = self.kartyak[azon]
+ if tarolt(f"karbantartas_{azon}") is None:
+ kartya.gomb.setEnabled(False)
+ kartya.osszegzes.setText("Ellenőrzés...")
+ gyorsitott(
+ f"karbantartas_{azon}",
+ karbantartas.ELONEZETEK[azon],
+ kesz=lambda adat, a=azon: self._kesz(a, adat),
+ hiba=lambda uzenet, a=azon: self._kesz(a, {"elerheto": False, "osszegzes": uzenet, "elemek": []}),
+ kor=60,
+ )
+
+ def _kesz(self, azon, adat):
+ self.adat[azon] = adat
+ kartya = self.kartyak[azon]
+ kartya.osszegzes.setText(adat["osszegzes"])
+ torlo = next(m[4] for m in MUVELETEK if m[0] == azon)
+ teendo = not torlo or azon == "naplo" or bool(adat["elemek"])
+ kartya.gomb.setEnabled(adat["elerheto"] and teendo and muveletek.helper_elerheto())
+
+ def _futtat(self, azon):
+ adat = self.adat.get(azon)
+ if not adat:
+ return
+ nev = next(m[2] for m in MUVELETEK if m[0] == azon)
+ kivalasztott = None
+ if azon == "cache":
+ szoveg = f"Ezek a csomagfájlok törlődnek a cache-ből ({adat['osszegzes']}). A telepített programokat nem érinti."
+ elif azon == "arva":
+ szoveg = (
+ "Pontosan ezek a csomagok törlődnek, más nem. Vedd ki a pipát annál, amit megtartanál. "
+ "Utána újabb árva függőségek jelenhetnek meg, ezeket a kártya újra megmutatja."
+ )
+ elif azon == "naplo":
+ szoveg = f"{adat['osszegzes']}. A két hétnél régebbi naplók törlődnek, és legfeljebb 100 MB marad."
+ elif azon == "flatpak":
+ szoveg = "Ezek a runtime-ok törlődnek. Az alkalmazásaid továbbra is működnek."
+ else:
+ szoveg = ""
+ if szoveg:
+ ablak = ElonezetAblak(self, nev, szoveg, adat["elemek"], azon == "arva", "Törlés")
+ if ablak.exec() != QDialog.DialogCode.Accepted:
+ return
+ if azon == "arva":
+ kivalasztott = ablak.kivalasztott()
+ lepesek = karbantartas.lepesek(azon, adat, kivalasztott)
+ if not lepesek:
+ return
+ FolyamatAblak(self, nev, lepesek, "A művelet elkészült.").exec()
+ self._ellenoriz(azon)
+
+
+FUL = Karbantartas
diff --git a/raveos-center/raveos_center/oldalak/rendszer/mentes.py b/raveos-center/raveos_center/oldalak/rendszer/mentes.py
new file mode 100644
index 0000000..6ad5967
--- /dev/null
+++ b/raveos-center/raveos_center/oldalak/rendszer/mentes.py
@@ -0,0 +1,283 @@
+from datetime import datetime
+from pathlib import Path
+
+from PyQt6.QtCore import QObject, Qt, pyqtSignal
+from PyQt6.QtWidgets import (
+ QCheckBox,
+ QFrame,
+ QScrollArea,
+ QFileDialog,
+ QHBoxLayout,
+ QLabel,
+ QLineEdit,
+ QMessageBox,
+ QPlainTextEdit,
+ QProgressBar,
+ QSizePolicy,
+ QVBoxLayout,
+ QWidget,
+)
+
+from raveos_center import katalogus, mentesek, muveletek
+from raveos_center.elemek import Kartya, cimke, gomb
+from raveos_center.hatter import hatterben
+
+AZON = "mentes"
+CIM = "Mentés"
+
+MERET = {"small": "kicsi", "medium": "közepes", "large": "nagy", "xlarge": "nagyon nagy"}
+
+
+class RovidUt(QLabel):
+ def __init__(self, ut):
+ super().__init__(ut)
+ self.teljes = ut
+ self.setObjectName("monohalvany")
+ self.setToolTip(ut)
+ self.setMinimumWidth(60)
+ self.setSizePolicy(QSizePolicy.Policy.Ignored, QSizePolicy.Policy.Preferred)
+
+ def resizeEvent(self, esemeny):
+ super().resizeEvent(esemeny)
+ self.setText(self.fontMetrics().elidedText(self.teljes, Qt.TextElideMode.ElideMiddle, self.width()))
+
+
+class _Jelzo(QObject):
+ naplo = pyqtSignal(str)
+ haladas = pyqtSignal(int)
+
+
+def elem_sor(elem, bejelolve):
+ sor = QWidget()
+ s = QHBoxLayout(sor)
+ s.setContentsMargins(0, 4, 0, 4)
+ s.setSpacing(12)
+ jelolo = QCheckBox()
+ jelolo.setChecked(bejelolve)
+ s.addWidget(jelolo)
+ szovegek = QVBoxLayout()
+ szovegek.setSpacing(0)
+ nev = cimke(katalogus.loc(elem.get("label")) or elem["id"])
+ nev.setStyleSheet("font-weight: 600;")
+ szovegek.addWidget(nev)
+ szovegek.addWidget(RovidUt(str(mentesek.abszolut(elem))))
+ if elem.get("note"):
+ szovegek.addWidget(cimke(katalogus.loc(elem["note"]), "halvany", True))
+ s.addLayout(szovegek, 1)
+ if elem.get("scope") == "system":
+ s.addWidget(cimke("ROOT", "allapotcimke"))
+ if elem.get("size_hint"):
+ s.addWidget(cimke(MERET.get(elem["size_hint"], elem["size_hint"]), "halvany"))
+ jelolo.nev = nev
+ return sor, jelolo
+
+
+class Mentes(QWidget):
+ def __init__(self, kozpont):
+ super().__init__()
+ self.kozpont = kozpont
+ self.fut = False
+ self.mentes_jelolok = []
+ self.visszaallitas_jelolok = []
+ self.jelzo = _Jelzo()
+ doboz = QVBoxLayout(self)
+ doboz.setContentsMargins(0, 24, 0, 0)
+ doboz.setSpacing(20)
+ doboz.addWidget(
+ cimke(
+ "Mentsd el az alkalmazásaid beállításait és a fontos mappáidat egyetlen fájlba, és állítsd vissza "
+ "őket egy másik gépen vagy újratelepítés után. A ROOT jelölésű elemekhez a rendszer jelszót kér.",
+ "masodlagos",
+ True,
+ )
+ )
+
+ oszlopok = QHBoxLayout()
+ oszlopok.setSpacing(24)
+ doboz.addLayout(oszlopok, 1)
+ bal = QVBoxLayout()
+ bal.setSpacing(16)
+ jobb = QVBoxLayout()
+ jobb.setSpacing(16)
+ oszlopok.addLayout(bal, 3)
+ oszlopok.addLayout(jobb, 2)
+
+ mentes = Kartya("Mentés", terkoz=10, margo=20)
+ gorgeto = QScrollArea()
+ gorgeto.setWidgetResizable(True)
+ gorgeto.setFrameShape(QFrame.Shape.NoFrame)
+ gorgeto.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
+ gorgeto.setMinimumHeight(160)
+ lista_doboz = QWidget()
+ gorgeto.setWidget(lista_doboz)
+ self.mentes_lista = QVBoxLayout(lista_doboz)
+ self.mentes_lista.setContentsMargins(0, 0, 12, 0)
+ self.mentes_lista.setSpacing(2)
+ mentes.elrendezes.addWidget(gorgeto, 1)
+ cel_sor = QHBoxLayout()
+ cel_sor.setSpacing(8)
+ self.cel = QLineEdit(str(Path.home() / f"raveos-mentes-{datetime.now():%Y%m%d}.tar.gz"))
+ cel_sor.addWidget(self.cel, 1)
+ tallozas = gomb("Tallózás", kicsi=True)
+ tallozas.clicked.connect(self._cel_valaszt)
+ cel_sor.addWidget(tallozas)
+ mentes.elrendezes.addSpacing(8)
+ mentes.elrendezes.addWidget(cimke("Mentés helye", "kartyacim"))
+ mentes.elrendezes.addLayout(cel_sor)
+ gs = QHBoxLayout()
+ gs.addStretch(1)
+ self.mentes_gomb = gomb("Mentés indítása", fo=True)
+ self.mentes_gomb.clicked.connect(self._mentes)
+ gs.addWidget(self.mentes_gomb)
+ mentes.elrendezes.addLayout(gs)
+ bal.addWidget(mentes, 1)
+
+ vissza = Kartya("Visszaállítás", terkoz=10, margo=20)
+ fs = QHBoxLayout()
+ fs.setSpacing(8)
+ self.forras = QLineEdit()
+ self.forras.setPlaceholderText("Válaszd ki a mentésfájlt (.tar.gz)")
+ self.forras.setReadOnly(True)
+ fs.addWidget(self.forras, 1)
+ valaszt = gomb("Mentés kiválasztása", kicsi=True)
+ valaszt.clicked.connect(self._forras_valaszt)
+ fs.addWidget(valaszt)
+ vissza.elrendezes.addLayout(fs)
+ self.vissza_lista = QVBoxLayout()
+ self.vissza_lista.setSpacing(2)
+ vissza.elrendezes.addLayout(self.vissza_lista)
+ vissza.elrendezes.addWidget(
+ cimke("A visszaállítás felülírja a meglévő fájlokat a kiválasztott helyeken.", "halvany", True)
+ )
+ vs = QHBoxLayout()
+ vs.addStretch(1)
+ self.vissza_gomb = gomb("Visszaállítás", fo=True)
+ self.vissza_gomb.setEnabled(False)
+ self.vissza_gomb.clicked.connect(self._visszaallitas)
+ vs.addWidget(self.vissza_gomb)
+ vissza.elrendezes.addLayout(vs)
+ jobb.addWidget(vissza)
+
+ self.sav = QProgressBar()
+ self.sav.setObjectName("sav")
+ self.sav.setTextVisible(False)
+ self.sav.setFixedHeight(6)
+ jobb.addWidget(self.sav)
+ jobb.addWidget(cimke("NAPLÓ", "h2"))
+ self.naplo = QPlainTextEdit()
+ self.naplo.setObjectName("naplo")
+ self.naplo.setReadOnly(True)
+ self.naplo.setMinimumHeight(100)
+ jobb.addWidget(self.naplo, 1)
+ self.jelzo.naplo.connect(self.naplo.appendPlainText)
+ self.jelzo.haladas.connect(self.sav.setValue)
+ self._mentes_lista_epit()
+
+ def _mentes_lista_epit(self):
+ try:
+ csoportok = mentesek.csoportok()
+ except (OSError, ValueError, RuntimeError) as e:
+ self.mentes_lista.addWidget(cimke(f"A mentési lista nem tölthető be: {e}", "figyelem", True))
+ return
+ self.mentes_lista.addStretch(0)
+ for csoport in csoportok:
+ fej = cimke(katalogus.loc(csoport.get("label")).upper(), "monozold")
+ self.mentes_lista.addSpacing(8)
+ self.mentes_lista.addWidget(fej)
+ if csoport.get("description"):
+ self.mentes_lista.addWidget(cimke(katalogus.loc(csoport["description"]), "halvany", True))
+ for elem in csoport.get("items", []):
+ sor, jelolo = elem_sor(elem, elem.get("default_selected", False))
+ self.mentes_lista.addWidget(sor)
+ self.mentes_jelolok.append((jelolo, elem))
+
+ def megjelenik(self, *_):
+ self._gombok()
+
+ def _gombok(self):
+ self.mentes_gomb.setEnabled(not self.fut)
+ self.vissza_gomb.setEnabled(not self.fut and bool(self.visszaallitas_jelolok))
+
+ def _cel_valaszt(self):
+ ut, _ = QFileDialog.getSaveFileName(self, "Mentés helye", self.cel.text(), "Mentés (*.tar.gz)")
+ if ut:
+ self.cel.setText(ut if ut.endswith(".tar.gz") else ut + ".tar.gz")
+
+ def _forras_valaszt(self):
+ ut, _ = QFileDialog.getOpenFileName(self, "Mentés kiválasztása", str(Path.home()), "Mentés (*.tar.gz)")
+ if not ut:
+ return
+ self.forras.setText(ut)
+ self._tartalom([])
+ hatterben(mentesek.tartalom, ut, kesz=self._tartalom, hiba=lambda u: self._hiba(f"A fájl nem olvasható: {u}"))
+
+ def _tartalom(self, lista):
+ while self.vissza_lista.count():
+ w = self.vissza_lista.takeAt(0).widget()
+ if w:
+ w.deleteLater()
+ self.visszaallitas_jelolok = []
+ if not lista:
+ self.vissza_lista.addWidget(cimke("Ebben a fájlban nincs visszaállítható elem.", "halvany"))
+ for elem in lista:
+ sor, jelolo = elem_sor(elem, True)
+ self.vissza_lista.addWidget(sor)
+ self.visszaallitas_jelolok.append((jelolo, elem))
+ if any(e.get("regi") for e in lista):
+ self.vissza_lista.addWidget(
+ cimke("Régi (App Installer) formátumú mentés: a rendszerelemek ebből nem állíthatók vissza.", "halvany", True)
+ )
+ self._gombok()
+
+ def _hiba(self, szoveg):
+ self.naplo.appendPlainText(f"[HIBA] {szoveg}")
+
+ def _rootot_kell(self, elemek):
+ if any(e.get("scope") == "system" for e in elemek) and not muveletek.helper_elerheto():
+ QMessageBox.warning(self, "Mentés", "A rendszerelemekhez a RaveOS Center rendszerhelpere szükséges, de nincs telepítve.")
+ return False
+ return True
+
+ def _mentes(self):
+ elemek = [e for j, e in self.mentes_jelolok if j.isChecked()]
+ cel = self.cel.text().strip()
+ if not elemek or not cel or not self._rootot_kell(elemek):
+ return
+ if Path(cel).exists():
+ if QMessageBox.question(self, "Mentés", f"A fájl már létezik, felülírod?\n{cel}") != QMessageBox.StandardButton.Yes:
+ return
+ self._indul(f"Mentés indul: {cel}")
+ hatterben(
+ mentesek.mentes, cel, elemek, self.jelzo.naplo.emit, self.jelzo.haladas.emit,
+ kesz=lambda n: self._vege(f"Mentés kész: {n} elem, {cel}"),
+ hiba=lambda u: self._vege(f"A mentés nem sikerült: {u}", False),
+ )
+
+ def _visszaallitas(self):
+ elemek = [e for j, e in self.visszaallitas_jelolok if j.isChecked()]
+ if not elemek or not self._rootot_kell(elemek):
+ return
+ if QMessageBox.question(
+ self, "Visszaállítás", f"{len(elemek)} elem visszaállítása felülírja a meglévő fájlokat. Folytatod?"
+ ) != QMessageBox.StandardButton.Yes:
+ return
+ self._indul(f"Visszaállítás indul: {self.forras.text()}")
+ hatterben(
+ mentesek.visszaallitas, self.forras.text(), elemek, self.jelzo.naplo.emit, self.jelzo.haladas.emit,
+ kesz=lambda n: self._vege(f"Visszaállítás kész: {n} elem."),
+ hiba=lambda u: self._vege(f"A visszaállítás nem sikerült: {u}", False),
+ )
+
+ def _indul(self, szoveg):
+ self.fut = True
+ self._gombok()
+ self.sav.setValue(0)
+ self.naplo.appendPlainText(szoveg)
+
+ def _vege(self, szoveg, rendben=True):
+ self.fut = False
+ self._gombok()
+ self.naplo.appendPlainText(szoveg if rendben else f"[HIBA] {szoveg}")
+
+
+FUL = Mentes
diff --git a/raveos-center/raveos_center/oldalak/rendszer/secureboot.py b/raveos-center/raveos_center/oldalak/rendszer/secureboot.py
new file mode 100644
index 0000000..00ca444
--- /dev/null
+++ b/raveos-center/raveos_center/oldalak/rendszer/secureboot.py
@@ -0,0 +1,256 @@
+import shutil
+import subprocess
+
+from PyQt6.QtWidgets import QHBoxLayout, QMessageBox, QPlainTextEdit, QVBoxLayout, QWidget
+
+from raveos_center import muveletek
+from raveos_center.elemek import Kartya, Racs, cimke, gomb
+from raveos_center.hatter import ervenytelenit, gyorsitott, tarolt
+
+AZON = "secureboot"
+CIM = "Secure Boot"
+
+SZKRIPT = "raveos-secureboot-setup"
+UJRAINDITAS_KELL = 10
+
+LEPESEK_SZOVEG = [
+ "telepíti a szükséges eszközöket (sbsigntools, efitools),",
+ "létrehoz egy saját, csak ehhez a géphez tartozó aláíró kulcsot,",
+ "aláírja a rendszerbetöltőt, a kernelt és a külső kernelmodulokat (pl. NVIDIA),",
+ "beírja a firmware-be a RaveOS, a Microsoft és a saját géped kulcsát, így a Windows is tovább indul,",
+ "beállít egy automatikus aláírást, ami minden kernelfrissítés után újra aláír.",
+]
+
+
+def allapot_lekerdez():
+ if not shutil.which(SZKRIPT):
+ return None
+ kimenet = subprocess.run([SZKRIPT, "--status"], capture_output=True, text=True, timeout=30)
+ adat = {}
+ for sor in kimenet.stdout.splitlines():
+ if "=" in sor and not sor.startswith("["):
+ k, _, v = sor.partition("=")
+ adat[k.strip()] = v.strip()
+ if not adat and "Nem UEFI" in kimenet.stdout:
+ adat["uefi"] = "0"
+ return adat
+
+
+class SecureBoot(QWidget):
+ def __init__(self, kozpont):
+ super().__init__()
+ self.kozpont = kozpont
+ doboz = QVBoxLayout(self)
+ doboz.setContentsMargins(0, 20, 0, 0)
+ doboz.setSpacing(16)
+ doboz.addWidget(
+ cimke(
+ "A Secure Boot csak aláírt rendszerbetöltőt és kernelt enged elindulni. Akkor hasznos, ha a gépen "
+ "Windows is van, és ott olyan játék vagy program fut, ami bekapcsolt Secure Bootot kér (például egyes "
+ "csalásvédelmek vagy a Windows 11). A beállítás után a RaveOS és a Windows is elindul.",
+ "masodlagos",
+ True,
+ )
+ )
+ oszlopok = QHBoxLayout()
+ oszlopok.setSpacing(24)
+ bal = QVBoxLayout()
+ bal.setSpacing(12)
+ oszlopok.addLayout(bal, 3)
+ doboz.addLayout(oszlopok, 1)
+ self.racs = Racs(110, 10)
+ self.ertekek = {}
+ for kulcs, nev in (
+ ("secureboot", "Secure Boot"),
+ ("setupmode", "Setup Mode"),
+ ("keys", "Gépkulcs"),
+ ("signed", "Aláírások"),
+ ):
+ k = Kartya(nev, terkoz=6, margo=14)
+ ertek = cimke("...", "nagyszam")
+ k.elrendezes.addWidget(ertek)
+ self.ertekek[kulcs] = ertek
+ self.racs.hozzaad(k)
+ bal.addWidget(self.racs)
+ self.figyelem = cimke("", "figyelem", True)
+ self.figyelem.hide()
+ bal.addWidget(self.figyelem)
+ bal.addWidget(
+ cimke(
+ "FIGYELEM, BITLOCKER: ha a gépen Windows is van BitLockerrel, a beállítás előtt a Windowsban függeszd "
+ "fel a BitLockert (manage-bde -protectors -disable C: -rebootcount 2), vagy legyen kéznél a 48 jegyű "
+ "helyreállítási kulcs. Enélkül a Windows a következő indításkor ezt a kulcsot fogja kérni.",
+ "figyelem",
+ True,
+ )
+ )
+
+ leiras = Kartya("A beállítás lépései", terkoz=6)
+ leiras.elrendezes.addWidget(cimke("A Beállítás gomb egymás után:", "masodlagos"))
+ for i, szoveg in enumerate(LEPESEK_SZOVEG, 1):
+ sor = QHBoxLayout()
+ sor.setSpacing(10)
+ jel = cimke(f"{i}.", "monozold")
+ jel.setFixedWidth(22)
+ sor.addWidget(jel)
+ sor.addWidget(cimke(szoveg, "masodlagos", True), 1)
+ leiras.elrendezes.addLayout(sor)
+ leiras.elrendezes.addSpacing(6)
+ leiras.elrendezes.addWidget(
+ cimke(
+ "Ehhez a firmware-nek Setup Mode-ban kell lennie: a BIOS/UEFI beállításokban töröld a Secure Boot "
+ "kulcsokat (Clear Secure Boot keys / Reset to Setup Mode). Ha nincs Setup Mode-ban, a Center szól, "
+ "és újraindítás után a beállítás magától folytatódik.",
+ "halvany",
+ True,
+ )
+ )
+
+ leiras.setMinimumWidth(300)
+ leiras.setMaximumWidth(420)
+ jobb = QVBoxLayout()
+ jobb.addWidget(leiras)
+ jobb.addStretch(1)
+ oszlopok.addLayout(jobb, 2)
+
+ gombok = QHBoxLayout()
+ gombok.setSpacing(8)
+ self.frissit_gomb = gomb("Állapot frissítése")
+ self.frissit_gomb.clicked.connect(self.frissit)
+ self.ujra_gomb = gomb("Újra aláírás")
+ self.ujra_gomb.setToolTip("Ha a gépkulcs már megvan, csak újra aláírja a rendszerbetöltőt, a kernelt és a modulokat.")
+ self.ujra_gomb.clicked.connect(lambda: self._futtat("resign", "Újra aláírás"))
+ self.beallit_gomb = gomb("Beállítás", fo=True)
+ self.beallit_gomb.clicked.connect(self._beallit)
+ gombok.addWidget(self.frissit_gomb)
+ gombok.addStretch(1)
+ gombok.addWidget(self.ujra_gomb)
+ gombok.addWidget(self.beallit_gomb)
+ bal.addLayout(gombok)
+
+ bal.addWidget(cimke("NAPLÓ", "h2"))
+ self.naplo = QPlainTextEdit()
+ self.naplo.setObjectName("naplo")
+ self.naplo.setReadOnly(True)
+ self.naplo.setMinimumHeight(80)
+ bal.addWidget(self.naplo, 1)
+
+ self.futtato = muveletek.Futtato(self)
+ self.futtato.sor.connect(self.naplo.appendPlainText)
+ self.futtato.kesz.connect(self._kesz)
+ self.adat = {}
+
+ def megjelenik(self, *_):
+ self._betolt()
+
+ def frissit(self):
+ ervenytelenit("secureboot")
+ self._betolt()
+
+ def _betolt(self):
+ if tarolt("secureboot") is None:
+ for e in self.ertekek.values():
+ e.setText("...")
+ gyorsitott(
+ "secureboot", allapot_lekerdez, kesz=self._allapot,
+ hiba=lambda u: self._hiba(f"Az állapot nem olvasható: {u}"), kor=60,
+ )
+
+ def _hiba(self, szoveg):
+ self.figyelem.setText(szoveg)
+ self.figyelem.show()
+
+ def _allapot(self, adat):
+ self.adat = adat or {}
+ self.figyelem.hide()
+ if adat is None:
+ for e in self.ertekek.values():
+ e.setText("-")
+ self._hiba("A Secure Boot beállító (raveos-secureboot-setup) nincs telepítve.")
+ self._gombok(False)
+ return
+ if adat.get("uefi") == "0":
+ for e in self.ertekek.values():
+ e.setText("-")
+ self._hiba("Ez a gép nem UEFI módban indult, ezért a Secure Boot nem érhető el.")
+ self._gombok(False)
+ return
+ def ki(ertek, igen, nem):
+ return igen if ertek == "1" else nem if ertek == "0" else "?"
+ self._beir("secureboot", ki(adat.get("secureboot"), "BE", "KI"), adat.get("secureboot") == "1")
+ self._beir("setupmode", ki(adat.get("setupmode"), "IGEN", "NEM"), adat.get("setupmode") == "1")
+ self._beir("keys", ki(adat.get("keys"), "MEGVAN", "NINCS"), adat.get("keys") == "1")
+ self._beir("signed", ki(adat.get("signed"), "RENDBEN", "HIÁNYZIK"), adat.get("signed") == "1")
+ if adat.get("pending") == "1":
+ self._hiba("A beállítás félbemaradt, és a következő újraindításkor magától folytatódik.")
+ self._gombok(True)
+
+ def _beir(self, kulcs, szoveg, zold):
+ e = self.ertekek[kulcs]
+ e.setText(szoveg)
+ e.setProperty("zold", zold)
+ e.style().unpolish(e)
+ e.style().polish(e)
+
+ def _gombok(self, elerheto):
+ fut = self.futtato.fut()
+ helper = muveletek.helper_elerheto()
+ self.beallit_gomb.setEnabled(elerheto and helper and not fut)
+ self.ujra_gomb.setEnabled(elerheto and helper and not fut and self.adat.get("keys") == "1")
+ self.frissit_gomb.setEnabled(not fut)
+
+ def _beallit(self):
+ valasz = QMessageBox.question(
+ self,
+ "Secure Boot beállítása",
+ "A beállítás kulcsokat ír a firmware-be, és aláírja a rendszerbetöltőt és a kernelt. "
+ "Ha Windows is van a gépen BitLockerrel, előtte függeszd fel a BitLockert.\n\nFolytatod?",
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
+ QMessageBox.StandardButton.No,
+ )
+ if valasz == QMessageBox.StandardButton.Yes:
+ self._futtat("setup", "Secure Boot beállítása")
+
+ def _futtat(self, mod, cimke_szoveg):
+ self.naplo.clear()
+ self._gombok(False)
+ self.futtato.indit([muveletek.Lepes(cimke_szoveg, muveletek.root("secureboot", mod))])
+
+ def _bios_ujrainditas(self, cim, szoveg):
+ doboz = QMessageBox(self)
+ doboz.setWindowTitle(cim)
+ doboz.setText(szoveg)
+ most = doboz.addButton("Újraindítás a BIOS-ba", QMessageBox.ButtonRole.AcceptRole)
+ doboz.addButton("Később", QMessageBox.ButtonRole.RejectRole)
+ doboz.exec()
+ if doboz.clickedButton() is most:
+ muveletek.Futtato(self).indit(
+ [
+ muveletek.Lepes(
+ "Újraindítás a firmware beállításaiba",
+ ["bash", "-c", "systemctl reboot --firmware-setup || systemctl reboot"],
+ )
+ ]
+ )
+
+ def _kesz(self, rendben, _hibasak):
+ kod = self.futtato.utolso_kod
+ if rendben:
+ self._bios_ujrainditas(
+ "Secure Boot",
+ "Az aláírások és a kulcsok készen vannak.\n\nA BIOS-ban állítsd a Secure Bootot Enabled-re, "
+ "majd mentsd el a beállítást és indítsd újra a gépet.",
+ )
+ elif kod == UJRAINDITAS_KELL:
+ self._bios_ujrainditas(
+ "Újraindítás szükséges",
+ "A firmware nincs Setup Mode-ban.\n\nA BIOS-ban a Secure Boot menüben töröld a kulcsokat "
+ "(Key Management, Clear Secure Boot keys), így a gép Setup Mode-ba kerül. Mentés után indítsd újra "
+ "a gépet: a beállítás indítás után magától befejeződik.",
+ )
+ else:
+ QMessageBox.warning(self, "Secure Boot", "A művelet nem sikerült. A részleteket a napló mutatja.")
+ self.frissit()
+
+
+FUL = SecureBoot
diff --git a/raveos-center/raveos_center/oldalak/rendszer/snapshotok.py b/raveos-center/raveos_center/oldalak/rendszer/snapshotok.py
new file mode 100644
index 0000000..8d9b08c
--- /dev/null
+++ b/raveos-center/raveos_center/oldalak/rendszer/snapshotok.py
@@ -0,0 +1,247 @@
+from PyQt6.QtCore import QProcess, Qt
+from PyQt6.QtWidgets import QHBoxLayout, QInputDialog, QLineEdit, QMessageBox, QVBoxLayout, QWidget
+
+from raveos_center import muveletek, snapshotok
+from raveos_center.elemek import Kartya, cimke, gomb
+from raveos_center.folyamat import FolyamatAblak
+from raveos_center.hatter import ervenytelenit, gyorsitott, tarolt
+
+AZON = "snapshotok"
+CIM = "Snapshotok"
+
+
+class SnapshotSor(QWidget):
+ def __init__(self, elem, utolso, visszaallit, torol):
+ super().__init__()
+ self.setObjectName("appsor")
+ self.setProperty("utolso", utolso)
+ self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
+ sor = QHBoxLayout(self)
+ sor.setContentsMargins(16, 12, 16, 12)
+ sor.setSpacing(16)
+ datum = cimke(elem["datum"], "mono")
+ datum.setFixedWidth(150)
+ sor.addWidget(datum)
+ szovegek = QVBoxLayout()
+ szovegek.setSpacing(2)
+ szovegek.addWidget(cimke(elem["leiras"] or "-", None, True))
+ szovegek.addWidget(cimke(f"#{elem['szam']} {elem['tipus_nev']}", "monohalvany"))
+ sor.addLayout(szovegek, 1)
+ helper = muveletek.helper_elerheto()
+ vissza = gomb("Visszaállítás", kicsi=True)
+ vissza.setEnabled(helper)
+ vissza.clicked.connect(lambda: visszaallit(elem))
+ sor.addWidget(vissza, 0, Qt.AlignmentFlag.AlignVCenter)
+ torles = gomb("Törlés", kicsi=True)
+ torles.setEnabled(helper)
+ torles.clicked.connect(lambda: torol(elem))
+ sor.addWidget(torles, 0, Qt.AlignmentFlag.AlignVCenter)
+
+
+class Snapshotok(QWidget):
+ def __init__(self, kozpont):
+ super().__init__()
+ self.kozpont = kozpont
+ self.adat = None
+ doboz = QVBoxLayout(self)
+ doboz.setContentsMargins(0, 20, 0, 0)
+ doboz.setSpacing(16)
+ fej = QHBoxLayout()
+ fej.setSpacing(16)
+ self.leiras = cimke(
+ "A btrfs snapshot a rendszer egy pillanatnyi állapota. Ha egy frissítés után gond van, egy korábbi "
+ "állapotra vissza tudsz állni. A saját fájljaidat (/home) a visszaállítás nem érinti.",
+ "masodlagos",
+ True,
+ )
+ fej.addWidget(self.leiras, 1)
+ self.uj_gomb = gomb("Új snapshot", fo=True)
+ self.uj_gomb.clicked.connect(self.uj)
+ fej.addWidget(self.uj_gomb, 0, Qt.AlignmentFlag.AlignTop)
+ doboz.addLayout(fej)
+ self.info = cimke("", "monozold", True)
+ self.info.hide()
+ doboz.addWidget(self.info)
+ self.figyelem = cimke("", "figyelem", True)
+ self.figyelem.hide()
+ doboz.addWidget(self.figyelem)
+ self.beallitas_gomb = gomb("Snapper beállítása", fo=True)
+ self.beallitas_gomb.clicked.connect(self._beallitas)
+ self.beallitas_gomb.hide()
+ gs = QHBoxLayout()
+ gs.addWidget(self.beallitas_gomb)
+ gs.addStretch(1)
+ doboz.addLayout(gs)
+ self.kartya = Kartya(terkoz=0, margo=0)
+ doboz.addWidget(self.kartya)
+ doboz.addStretch(1)
+
+ def megjelenik(self, *args):
+ if tarolt("snapshotok") is None:
+ self.uj_gomb.setEnabled(False)
+ self._info("Betöltés...")
+ gyorsitott("snapshotok", snapshotok.allapot, kesz=self._kesz, hiba=self._hiba, kor=30)
+ if args and args[0] == "uj":
+ self.uj()
+
+ def frissit(self):
+ ervenytelenit("snapshotok", "snapshot")
+ gyorsitott("snapshotok", snapshotok.allapot, kesz=self._kesz, hiba=self._hiba)
+
+ def _hiba(self, uzenet):
+ self._figyelmeztet(f"A snapshotok nem olvashatók: {uzenet}")
+
+ def _info(self, szoveg):
+ self.info.setText(szoveg)
+ self.info.setVisible(bool(szoveg))
+
+ def _figyelmeztet(self, szoveg):
+ self.figyelem.setText(szoveg)
+ self.figyelem.setVisible(bool(szoveg))
+
+ def _kesz(self, adat):
+ self.adat = adat
+ helper = muveletek.helper_elerheto()
+ kesz = adat["fajlrendszer"] == "btrfs" and adat["snapper"]
+ self.uj_gomb.setVisible(kesz)
+ self.uj_gomb.setEnabled(kesz and helper)
+ self.beallitas_gomb.setVisible(snapshotok.snapper_telepitheto(adat))
+ self.beallitas_gomb.setEnabled(helper)
+ self.kartya.setVisible(kesz)
+ if adat["fajlrendszer"] != "btrfs":
+ self._info("")
+ self._figyelmeztet(
+ f"Snapshothoz btrfs fájlrendszer kell. Ez a gép {adat['fajlrendszer'] or 'ismeretlen'} fájlrendszert "
+ "használ, ezért itt nem érhető el. A RaveOS telepítésekor a lemez partícionálásánál ext4 és btrfs "
+ "közül lehet választani: ha snapshotot szeretnél, a btrfs-t válaszd."
+ )
+ return
+ if not adat["snapper"]:
+ self._info("")
+ if snapshotok.snapper_telepitheto(adat):
+ self._figyelmeztet(
+ "A gép btrfs-t használ, de a snapper még nincs beállítva. Egy kattintással beállítható: "
+ "utána minden csomagművelet előtt automatikusan snapshot készül."
+ )
+ else:
+ self._figyelmeztet(
+ "A gép btrfs-t használ, de az alvolumen-elrendezése eltér a RaveOS-étól (@ és @snapshots), "
+ "ezért a snapper itt nem állítható be automatikusan."
+ )
+ return
+ if adat["alvolumen"] != "/@":
+ self._figyelmeztet("A rendszer most nem a fő alvolumenről (@) fut, ezért visszaállítás nem indítható.")
+ elif adat["hiba"]:
+ self._figyelmeztet(adat["hiba"])
+ elif not helper:
+ self._figyelmeztet("A RaveOS Center rendszerhelpere nincs telepítve, ezért snapshot nem kezelhető.")
+ else:
+ self._figyelmeztet("")
+ self._info(
+ ("Automatikus snapshot minden csomagművelet előtt és után (snap-pac). " if adat["snap_pac"] else "")
+ + f"{len(adat['lista'])} snapshot, a régiek automatikusan törlődnek."
+ )
+ self._lista(adat)
+
+ def _lista(self, adat):
+ elrendezes = self.kartya.elrendezes
+ while elrendezes.count():
+ w = elrendezes.takeAt(0).widget()
+ if w:
+ w.deleteLater()
+ if not adat["lista"]:
+ ures = cimke("Még nincs snapshot.", "halvany")
+ ures.setContentsMargins(16, 16, 16, 16)
+ elrendezes.addWidget(ures)
+ return
+ for i, elem in enumerate(adat["lista"]):
+ elrendezes.addWidget(SnapshotSor(elem, i == len(adat["lista"]) - 1, self.visszaallit, self.torol))
+
+ def _futtat(self, cim, lepes, siker):
+ ablak = FolyamatAblak(self, cim, [lepes], siker)
+ ablak.exec()
+ self.frissit()
+ return ablak.rendben
+
+ def uj(self):
+ if not self.adat or not self.uj_gomb.isEnabled():
+ return
+ leiras, ok = QInputDialog.getText(
+ self, "Új snapshot", "Leírás (például: Driver csere előtt):", QLineEdit.EchoMode.Normal, "Kézi snapshot"
+ )
+ leiras = leiras.strip()
+ if not ok:
+ return
+ if not snapshotok.ervenyes_leiras(leiras):
+ QMessageBox.warning(self, "Új snapshot", "A leírás 1-80 karakter lehet: betűk, számok, szóköz és . _ : , ( ) -")
+ return
+ self._futtat("Új snapshot", muveletek.Lepes("Snapshot készítése", muveletek.root("snapshot", leiras)), "A snapshot elkészült.")
+
+ def torol(self, elem):
+ if QMessageBox.question(
+ self, "Snapshot törlése", f"Törlöd a(z) #{elem['szam']} snapshotot?\n{elem['datum']} {elem['leiras']}"
+ ) != QMessageBox.StandardButton.Yes:
+ return
+ self._futtat(
+ "Snapshot törlése",
+ muveletek.Lepes("Snapshot törlése", muveletek.root("snapshot-torles", str(elem["szam"]))),
+ "A snapshot törölve.",
+ )
+
+ def visszaallit(self, elem):
+ kernelek = snapshotok.kernel_valtozas(elem["szam"])
+ ellenorizheto = kernelek is not None
+ kernelek = kernelek or []
+ hianyzo = [k for k in kernelek if not k["cache"]]
+ if hianyzo:
+ QMessageBox.warning(
+ self,
+ "Visszaállítás",
+ "Ennek a snapshotnak a kernelcsomagja már nincs meg a csomag-cache-ben "
+ f"({', '.join(k['nev'] + ' ' + k['regi'] for k in hianyzo)}), ezért a visszaállított rendszer nem "
+ "indulna el. Válassz újabb snapshotot.",
+ )
+ return
+ kernel_szoveg = "".join(f"\n- {k['nev']}: {k['most'] or 'nincs'} -> {k['regi']}" for k in kernelek)
+ szoveg = (
+ f"A rendszer visszaáll erre az állapotra:\n#{elem['szam']} {elem['datum']} {elem['leiras']}\n\n"
+ "A saját fájljaid (/home) nem változnak. A mostani rendszer a következő visszaállításig megmarad "
+ "tartalékként. A változás újraindítás után lép életbe."
+ + (f"\n\nA kernel is visszaáll:{kernel_szoveg}" if kernelek else "")
+ + ("" if ellenorizheto else "\n\nA snapshot kernelverziója innen nem olvasható, a visszaállítás előtt a rendszer "
+ "ellenőrzi, és ha a kernelcsomag hiányzik, nem végzi el.")
+ + "\n\nFolytatod?"
+ )
+ if QMessageBox.question(self, "Visszaállítás", szoveg) != QMessageBox.StandardButton.Yes:
+ return
+ rendben = self._futtat(
+ "Visszaállítás",
+ muveletek.Lepes("Snapshot visszaállítása", muveletek.root("snapshot-visszaallit", str(elem["szam"]))),
+ "A visszaállítás elkészült. Indítsd újra a gépet.",
+ )
+ if not rendben:
+ return
+ doboz = QMessageBox(self)
+ doboz.setWindowTitle("Visszaállítás")
+ doboz.setIcon(QMessageBox.Icon.Warning)
+ doboz.setText(
+ "A visszaállítás újraindítás után lép életbe. Amit addig a gépen változtatsz (telepítés, beállítás, "
+ "rendszerfájlok), az a tartalék rendszerbe kerül, és elvész. A /home-ban lévő fájljaid megmaradnak.\n\n"
+ "Javasolt most újraindítani."
+ )
+ most = doboz.addButton("Újraindítás most", QMessageBox.ButtonRole.AcceptRole)
+ doboz.addButton("Később", QMessageBox.ButtonRole.RejectRole)
+ doboz.setDefaultButton(most)
+ doboz.exec()
+ if doboz.clickedButton() is most:
+ QProcess.startDetached("systemctl", ["reboot"])
+
+ def _beallitas(self):
+ self._futtat(
+ "Snapper beállítása",
+ muveletek.Lepes("Snapper beállítása", muveletek.root("snapper-beallitas")),
+ "A snapper beállítva, az első snapshot elkészült.",
+ )
+
+
+FUL = Snapshotok