From a64ef966534f8dba6af889ba4bfce15691bfc85b Mon Sep 17 00:00:00 2001 From: Nippy Date: Sun, 1 Nov 2026 18:13:54 +0100 Subject: új telepítő MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../raveos_center/oldalak/rendszer/snapshotok.py | 247 +++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 raveos-center/raveos_center/oldalak/rendszer/snapshotok.py (limited to 'raveos-center/raveos_center/oldalak/rendszer/snapshotok.py') 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 -- cgit v1.3