diff --git a/.gitignore b/.gitignore index d7f9afe7..bd9315d5 100644 --- a/.gitignore +++ b/.gitignore @@ -42,5 +42,5 @@ AppDir *.spec site/ .desloppify/ - +*.geany .briefcase/ diff --git a/pyproject.toml b/pyproject.toml index 04f6f9ec..c943990a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "lufus" -version = "1.0.1b1" # keep synced with [tool.briefcase] version +version = "1.0.0" # keep synced with [tool.briefcase] version description = "A rufus clone written in Python and designed to work with Linux." readme = "README.md" license = "MIT" @@ -29,7 +29,7 @@ lufus = "lufus.__main__:main" [tool.briefcase] project_name = "Lufus" bundle = "com.github.hog185" -version = "1.0.1b1" # keep synced with [project] version +version = "1.0.0" # keep synced with [project] version url = "https://github.com/Hog185/Lufus" license.file = "LICENSE" author = "Hog185" diff --git a/scripts/build-appimage.sh b/scripts/build-appimage.sh index 4bb6ea7d..8286b087 100755 --- a/scripts/build-appimage.sh +++ b/scripts/build-appimage.sh @@ -4,16 +4,17 @@ set -euo pipefail ls -la # Install system dependencies -echo "------------ Installing system libraries ------------" -apt-get update && apt-get upgrade -y -INSTALLER="apt-get install -y" -if [[ -f requirements-system.txt ]]; then - $INSTALLER $(cat requirements-system.txt) >> appimage-setup.log - echo "System libraries installed." -else - echo "requirements-system.txt not found!" - exit 1 -fi +## COMMENTED BECAUSE ALREADY HANDELED IN YAML +# echo "------------ Installing system libraries ------------" +# apt-get update && apt-get upgrade -y +# INSTALLER="apt-get install -y" +# if [[ -f requirements-system.txt ]]; then +# $INSTALLER $(cat requirements-system.txt) >> appimage-setup.log +# echo "System libraries installed." +# else +# echo "requirements-system.txt not found!" +# exit 1 +# fi if command -v python3 &>/dev/null; then PYTHON=python3 diff --git a/src/lufus/drives/formatting.py b/src/lufus/drives/formatting.py index ff9f6f8e..14b80092 100644 --- a/src/lufus/drives/formatting.py +++ b/src/lufus/drives/formatting.py @@ -235,7 +235,11 @@ def check_device_bad_blocks() -> bool: probe.returncode, ) except Exception as exc: - log.warning("Could not probe sector size for %s: %s. Using default block size.", drive, exc) + log.warning( + "Could not probe sector size for %s: %s. Using default block size.", + drive, + exc, + ) # -s = show progress, -v = verbose output # -n = non-destructive read-write test (safe default) @@ -316,10 +320,30 @@ def _status(msg: str) -> None: "NTFS", "ntfs-3g", ), - 1: ("mkfs.vfat", lambda: ["-I", "-s", str(sectors_per_cluster), "-F", "32", raw_device], "FAT32", "dosfstools"), - 2: ("mkfs.exfat", lambda: ["-b", str(block_size), raw_device], "exFAT", "exfatprogs or exfat-utils"), - 3: ("mkfs.ext4", lambda: ["-b", str(block_size), raw_device], "ext4", "e2fsprogs"), - 4: ("mkudffs", lambda: ["--blocksize=" + str(sector_size), raw_device], "UDF", "udftools"), + 1: ( + "mkfs.vfat", + lambda: ["-I", "-s", str(sectors_per_cluster), "-F", "32", raw_device], + "FAT32", + "dosfstools", + ), + 2: ( + "mkfs.exfat", + lambda: ["-b", str(block_size), raw_device], + "exFAT", + "exfatprogs or exfat-utils", + ), + 3: ( + "mkfs.ext4", + lambda: ["-b", str(block_size), raw_device], + "ext4", + "e2fsprogs", + ), + 4: ( + "mkudffs", + lambda: ["--blocksize=" + str(sector_size), raw_device], + "UDF", + "udftools", + ), } if fs_type not in fs_configs: @@ -367,14 +391,30 @@ def _apply_partition_scheme(drive: str) -> None: # GPT — used for UEFI targets subprocess.run([_find_tool("parted"), "-s", raw_device, "mklabel", "gpt"], check=True) subprocess.run( - [_find_tool("parted"), "-s", raw_device, "mkpart", "primary", "1MiB", "100%"], + [ + _find_tool("parted"), + "-s", + raw_device, + "mkpart", + "primary", + "1MiB", + "100%", + ], check=True, ) else: # MBR — used for BIOS/legacy targets subprocess.run([_find_tool("parted"), "-s", raw_device, "mklabel", "msdos"], check=True) subprocess.run( - [_find_tool("parted"), "-s", raw_device, "mkpart", "primary", "1MiB", "100%"], + [ + _find_tool("parted"), + "-s", + raw_device, + "mkpart", + "primary", + "1MiB", + "100%", + ], check=True, ) log.info("Partition scheme %s applied to %s.", scheme_name, raw_device) @@ -388,6 +428,11 @@ def _apply_partition_scheme(drive: str) -> None: def drive_repair() -> None: + # todo: + # add smartctl check if possible + # use fsck to prevent deletion of files for repair + # use testdisk for partition recovery if possible + # do dd if=/dev/zero of=/dev/sdX bs=1M count=10 conv=notrunc before sfdisk use _, drive, _ = _get_mount_and_drive() if not drive: log.error("No drive node found. Cannot repair.") diff --git a/src/lufus/gui/dialogs.py b/src/lufus/gui/dialogs.py index 8be35203..19d7bca6 100644 --- a/src/lufus/gui/dialogs.py +++ b/src/lufus/gui/dialogs.py @@ -3,22 +3,26 @@ from PyQt6.QtWidgets import ( QApplication, QComboBox, + QCheckBox, QDialog, QFileDialog, QFrame, QHBoxLayout, QLabel, + QLineEdit, QMessageBox, QPushButton, QTextEdit, QVBoxLayout, ) -from PyQt6.QtCore import Qt, pyqtSignal -from PyQt6.QtGui import QFont +from PyQt6.QtCore import Qt, pyqtSignal, QRegularExpression, QUrl +from PyQt6.QtGui import QFont, QRegularExpressionValidator, QDesktopServices +import sys from lufus import state as states from lufus.gui.constants import THEME_DIR, _find_resource_dir from lufus.gui.scale import Scale +from lufus.lufus_logging import get_logger class LogWindow(QDialog): @@ -28,7 +32,6 @@ def __init__(self, parent=None): self._T = parent._T if parent else {} self._S: Scale = parent._S if parent else None self.setWindowTitle(self._T.get("log_window_title", "Log Window")) - if self._S: # apply scaled dimensions self.resize(self._S.px(650), self._S.px(450)) @@ -139,6 +142,12 @@ def __init__(self, parent=None): sep.setFrameShadow(QFrame.Shadow.Sunken) layout.addWidget(sep) + # version + lbl_ver = QLabel(states.version) + lbl_ver.setStyleSheet(f"font-family: {font_family}; font-size: {tool_pt}pt;") + lbl_ver.setAlignment(Qt.AlignmentFlag.AlignCenter) + layout.addWidget(lbl_ver) + # im lying ily (context text something area, whatever) self.about_text = QTextEdit() self.about_text.setReadOnly(True) @@ -146,6 +155,19 @@ def __init__(self, parent=None): self.about_text.setFrameShape(QFrame.Shape.NoFrame) self.about_text.setStyleSheet(f"font-family: {font_family}; font-size: {tool_pt}pt;") layout.addWidget(self.about_text, 1) + btn_row0 = QHBoxLayout() + btn_discord = QPushButton(self._T.get("btn_discord", "Join Discord Server")) + btn_discord.setFixedWidth(self._S.px(300) if self._S else 90) + btn_discord.clicked.connect(self.discord_open) + btn_row0.addWidget(btn_discord, alignment=Qt.AlignmentFlag.AlignCenter) + layout.addLayout(btn_row0) + + btn_row1 = QHBoxLayout() + btn_github = QPushButton(self._T.get("btn_github", "Open Github Repo")) + btn_github.setFixedWidth(self._S.px(300) if self._S else 90) + btn_github.clicked.connect(self.github_open) + btn_row1.addWidget(btn_github, alignment=Qt.AlignmentFlag.AlignCenter) + layout.addLayout(btn_row1) btn_row = QHBoxLayout() # close button or smth, whatever @@ -154,9 +176,16 @@ def __init__(self, parent=None): btn_close.clicked.connect(self.hide) btn_row.addWidget(btn_close, alignment=Qt.AlignmentFlag.AlignCenter) layout.addLayout(btn_row) - self.setLayout(layout) + def discord_open(self): + url = QUrl("https://discord.gg/4G6FeBwsxb") + QDesktopServices.openUrl(url) + + def github_open(self): + url = QUrl("https://github.com/Hog185/Lufus") + QDesktopServices.openUrl(url) + class SettingsDialog(QDialog): # signals for when settings change :D @@ -246,3 +275,102 @@ def _detect_themes(): # user themes follow the same folder structure :D custom = sorted(p.parent.name for p in user_themes_dir.glob("*/*_theme.json")) return builtin, custom + + +class WinTweaks(QDialog): + def __init__(self, parent=None): + super().__init__(parent) + re = QRegularExpression("^[a-zA-Z0-9_]*$") + validator = QRegularExpressionValidator(re) + self.setWindowTitle("Windows Tweaks (MAY BREAK! USE CAUTION)") + self.setFixedSize(600, 300) + self.ask_label = QLabel("Do you want to customize your windows installation?") + self.hardware_checkbox = QCheckBox("Remove requirement for 4GB+ RAM, Secure Boot and TPM 2.0") + self.hardware_checkbox.stateChanged.connect(self.update_winhardware) + self.microsoft_checkbox = QCheckBox("Remove requirement for an online Microsoft Account") + self.microsoft_checkbox.stateChanged.connect(self.update_winmicrosoftacc) + self.localacc_checkbox = QCheckBox("Create a local account with username:") + self.localacc_checkbox.stateChanged.connect(self.update_winlocalaccchk) + self.username_input = QLineEdit() + self.username_input.setMaxLength(20) + self.username_input.setValidator(validator) + self.username_input.setPlaceholderText("Enter username here...") + self.microsoft_checkbox.toggled.connect(self.localacc_checkbox.setEnabled) + self.localacc_checkbox.toggled.connect(self.username_input.setEnabled) + self.username_input.setEnabled(self.localacc_checkbox.isChecked()) + self.username_input.textChanged.connect(self.sync_username) + self.data_checkbox = QCheckBox("Disable data collection (skip privacy questions)") + self.data_checkbox.stateChanged.connect(self.update_winprivacy) + self.applytweaks_btn = QPushButton("Apply") + self.applytweaks_btn.clicked.connect(self.applywintweaks) + self.canceltweaks_btn = QPushButton("Cancel") + self.canceltweaks_btn.clicked.connect(self.reject) # closes window + layout = QVBoxLayout() + layout.setSpacing(15) + layout.setContentsMargins(20, 20, 20, 20) + layout.addWidget(self.ask_label, alignment=Qt.AlignmentFlag.AlignCenter) + layout.addWidget(self.hardware_checkbox) + layout.addWidget(self.microsoft_checkbox) + layout.addWidget(self.localacc_checkbox) + layout.addWidget(self.username_input) + layout.addWidget(self.data_checkbox) + button_layout = QHBoxLayout() + button_layout.addWidget(self.applytweaks_btn) + button_layout.addWidget(self.canceltweaks_btn) + layout.addLayout(button_layout) + layout.addStretch(1) + self.setLayout(layout) + + def log_message(self, msg): + # delegate logging to parent window if available, otherwise use module logger + parent = self.parent() + if parent is not None and hasattr(parent, "log_message"): + parent.log_message(msg) + else: + get_logger("wintweaks").info(msg) + + def update_winhardware(self): + # update winhardware req disable setting + states.win_hardware_bypass = 1 if self.hardware_checkbox.isChecked() else 0 + self.log_message( + f"Windows hardware requirement disable: {'enabled' if self.hardware_checkbox.isChecked() else 'disabled'}" + ) + + def update_winmicrosoftacc(self): + # update microsoft acc disable setting + states.win_microsoft_acc = 1 if self.microsoft_checkbox.isChecked() else 0 + self.log_message( + f"Microsoft account requirement disable: {'enabled' if self.microsoft_checkbox.isChecked() else 'disabled'}" + ) + + def update_winlocalaccchk(self): + # update local acc setting + states.win_local_acc_chk = 1 if self.localacc_checkbox.isChecked() else 0 + self.log_message( + f"Windows Local Account Add: {'enabled' if self.localacc_checkbox.isChecked() else 'disabled'}" + ) + + def sync_username(self, new_username): + # changes local username + states.win_local_acc = new_username + + def update_winprivacy(self): + # update win privacy setting + states.win_privacy = 1 if self.data_checkbox.isChecked() else 0 + self.log_message( + f"Windows privacy questions disable: {'enabled' if self.data_checkbox.isChecked() else 'disabled'}" + ) + # main tweaks apply logic function + + def applywintweaks(self): + # closes window + self.accept() + + +# for debug +# if __name__ == "__main__": +# # Standard boilerplate for testing the class standalone +# app = QApplication(sys.argv) +# window = WinTweaks() +# window.exec() +# sys.exit(app.exec()) diff --git a/src/lufus/gui/gui.py b/src/lufus/gui/gui.py index 3458bc64..af4cd738 100644 --- a/src/lufus/gui/gui.py +++ b/src/lufus/gui/gui.py @@ -43,6 +43,7 @@ from PyQt6.QtGui import QIcon from lufus import state +from lufus import state as states from lufus.drives.autodetect_usb import UsbMonitor from lufus.lufus_logging import get_logger from lufus.gui.themes.icon_utils import svg_icon @@ -50,8 +51,9 @@ from lufus.gui.scale import Scale from lufus.gui.i18n import load_translations from lufus.gui.redirector import StdoutRedirector -from lufus.gui.dialogs import LogWindow, AboutWindow, SettingsDialog +from lufus.gui.dialogs import LogWindow, AboutWindow, SettingsDialog, WinTweaks from lufus.gui.workers import FlashWorker, VerifyWorker +from lufus.writing.windows.tweaks import * # log level mapping for colors and methods _LOG_LEVELS = { @@ -603,7 +605,19 @@ def init_ui(self): # filesystem cluster and flash option selectors :D self.lbl_fs = QLabel(self._T.get("lbl_file_system", "File System")) self.combo_fs = QComboBox() - self.all_fs_options = ["NTFS", "FAT32", "exFAT", "ext4", "UDF", "HFS+", "ext2", "ext3", "Btrfs", "XFS", "ZFS"] + self.all_fs_options = [ + "NTFS", + "FAT32", + "exFAT", + "ext4", + "UDF", + "HFS+", + "ext2", + "ext3", + "Btrfs", + "XFS", + "ZFS", + ] self.combo_fs.addItems(["NTFS", "FAT32", "exFAT"]) self.combo_fs.currentTextChanged.connect(self.updateFS) @@ -823,7 +837,10 @@ def refresh_usb_devices(self): except Exception as e: # handle scan errors :3 self.statusBar.showMessage(self._T.get("status_scan_failed", "Scan Failed"), 3000) - self.log_message(f"USB scan raised exception: {type(e).__name__}: {str(e)}", level="ERROR") + self.log_message( + f"USB scan raised exception: {type(e).__name__}: {str(e)}", + level="ERROR", + ) QMessageBox.critical( self, self._T.get("msgbox_scan_error_title", "Scan Error"), @@ -1086,7 +1103,10 @@ def browse_file(self): self, self._T.get("dlg_select_image_title", "Select Image"), "", - self._T.get("dlg_select_image_filter", "Disk Images (*.iso *.dmg *.img *.bin *.raw);;All Files (*)"), + self._T.get( + "dlg_select_image_filter", + "Disk Images (*.iso *.dmg *.img *.bin *.raw);;All Files (*)", + ), ) if file_name: # load selected image file :3 @@ -1165,7 +1185,10 @@ def show_about(self): if self.about_window: self.about_window.close() self.about_window = AboutWindow(self) - content = self._T.get("about_content", "Lufus - USB Flash Tool\n\nA simple, open-source USB flashing utility.") + content = self._T.get( + "about_content", + "Lufus - USB Flash Tool\n\nA simple, open-source USB flashing utility.", + ) flat = getattr(self, "_flat_theme", {}) font_family = flat.get("fonts_family", "") fg_color = flat.get("colors_fg", "") @@ -1398,7 +1421,10 @@ def start_process(self): QMessageBox.warning( self, self._T.get("msgbox_invalid_hash_title", "Invalid Hash"), - self._T.get("msgbox_invalid_hash_body", "The provided SHA256 hash is invalid."), + self._T.get( + "msgbox_invalid_hash_body", + "The provided SHA256 hash is invalid.", + ), ) return @@ -1419,6 +1445,10 @@ def start_process(self): self.verify_worker.start() else: # skip verification and start flash :3 + if states.image_option == 0 and states.currentflash == 0: + dlg = WinTweaks(self) + if dlg.exec() == QDialog.DialogCode.Rejected: + return self.perform_flash() def on_verify_finished(self, success: bool): @@ -1426,6 +1456,14 @@ def on_verify_finished(self, success: bool): if success: self.log_message("SHA256 verification successful, proceeding to flash") self._clear_speed_eta() + if states.image_option == 0 and states.currentflash == 0: + dlg = WinTweaks(self) + if dlg.exec() == QDialog.DialogCode.Rejected: + self.btn_start.setEnabled(True) + self.btn_cancel.setEnabled(False) + self.progress_bar.setValue(0) + self.progress_bar.setFormat("") + return self.perform_flash() else: # verification failed (╯°□°)╯( ┻━┻ @@ -1474,6 +1512,7 @@ def perform_flash(self): self.flash_worker.progress.connect(self._on_progress, Qt.ConnectionType.QueuedConnection) self.flash_worker.status.connect(self._on_flash_status, Qt.ConnectionType.QueuedConnection) self.flash_worker.flash_done.connect(self.on_flash_finished, Qt.ConnectionType.QueuedConnection) + self.flash_worker.request_tweaks.connect(self.show_tweak_dialog, Qt.ConnectionType.QueuedConnection) self.flash_worker.start() self.btn_start.setEnabled(False) self.btn_cancel.setEnabled(True) @@ -1513,6 +1552,7 @@ def _start_flash_with_options(self, options: dict) -> None: self.flash_worker.progress.connect(self._on_progress, Qt.ConnectionType.QueuedConnection) self.flash_worker.status.connect(self._on_flash_status, Qt.ConnectionType.QueuedConnection) self.flash_worker.flash_done.connect(self.on_flash_finished, Qt.ConnectionType.QueuedConnection) + self.flash_worker.request_tweaks.connect(self.show_tweak_dialog, Qt.ConnectionType.QueuedConnection) self.flash_worker.start() self.btn_start.setEnabled(False) self.btn_cancel.setEnabled(True) @@ -1536,7 +1576,18 @@ def on_flash_finished(self, success: bool): # flash succeeded :D self.progress_bar.setValue(100) self.progress_bar.setFormat(self._T.get("progress_complete", "Complete")) + # change from fo to tweaks self.log_message("Flash operation finished with result: SUCCESS") + if states.image_option == 0 and states.currentflash == 0: + if getattr(states, "win_hardware_bypass", 0) == 1: + win_hardware_bypass() + if getattr(states, "win_microsoft_acc", 0) == 1: + if getattr(states, "win_local_acc_chk", 0) == 1: + win_local_acc_name() + else: + win_local_acc() + if getattr(states, "win_privacy", 0) == 1: + win_skip_privacy_questions() QMessageBox.information( self, self._T.get("msgbox_success_title", "Success"), @@ -1625,7 +1676,8 @@ def _apply_accessible_names(self) -> None: self.combo_image_option.setAccessibleName(self._T.get("acc_image_option", "Image option selector")) self.combo_image_option.setAccessibleDescription( self._T.get( - "acc_image_option_desc", "Choose the type of image to write: Windows, Linux, Other, or Format Only" + "acc_image_option_desc", + "Choose the type of image to write: Windows, Linux, Other, or Format Only", ) ) self.input_label.setAccessibleName(self._T.get("acc_volume_label", "Volume label input")) @@ -1642,7 +1694,10 @@ def _apply_accessible_names(self) -> None: self.chk_verify.setAccessibleName(self._T.get("acc_verify_hash", "Verify SHA256 checksum checkbox")) self.input_hash.setAccessibleName(self._T.get("acc_hash_input", "Expected SHA256 hash input")) self.input_hash.setAccessibleDescription( - self._T.get("acc_hash_input_desc", "Paste the expected 64-character SHA256 hash here") + self._T.get( + "acc_hash_input_desc", + "Paste the expected 64-character SHA256 hash here", + ) ) self.progress_bar.setAccessibleName(self._T.get("acc_progress", "Operation progress bar")) self.btn_start.setAccessibleName(self._T.get("acc_start", "Start operation")) @@ -1695,20 +1750,35 @@ def get_latest_release(self): data = json.loads(req.read().decode()) tag_name = data.get("tag_name", "") if not tag_name: - self.log_message("Update check: missing tag_name in API response", level="WARNING") + self.log_message( + "Update check: missing tag_name in API response", + level="WARNING", + ) return try: is_newer = version.parse(tag_name) > version.parse(current_version) except Exception: - self.log_message(f"Update check: could not parse version tag {tag_name!r}", level="WARNING") + self.log_message( + f"Update check: could not parse version tag {tag_name!r}", + level="WARNING", + ) return if is_newer: - self.log_message(f"New version found: {tag_name} > {current_version}", level="DEBUG") + self.log_message( + f"New version found: {tag_name} > {current_version}", + level="DEBUG", + ) else: - self.log_message(f"Running latest release build: {tag_name} <= {current_version}", level="INFO") + self.log_message( + f"Running latest release build: {tag_name} <= {current_version}", + level="INFO", + ) return else: - self.log_message(f"Couldn't get latest release, response: {req.status}", level="WARNING") + self.log_message( + f"Couldn't get latest release, response: {req.status}", + level="WARNING", + ) return except Exception as e: self.log_message(f"Update check failed: {e}", level="ERROR") @@ -1729,6 +1799,11 @@ def get_latest_release(self): else: self.log_message(f"download later button clicked", level="DEBUG") + # for win twaks + def show_tweak_dialog(self): + dialog = WinTweaks(self) + dialog.exec() + if __name__ == "__main__": # setup high dpi scaling :3 diff --git a/src/lufus/gui/languages/Deutsch.csv b/src/lufus/gui/languages/Deutsch.csv index 3d14b328..58fe1021 100644 --- a/src/lufus/gui/languages/Deutsch.csv +++ b/src/lufus/gui/languages/Deutsch.csv @@ -90,7 +90,6 @@ dlg_select_image_title,Abbild auswählen dlg_select_image_filter,Abbilder (*.iso *.dmg *.img *.bin *.raw);;Alle Dateien (*) about_content,"lufus ist ein in Python geschriebener USB-Image-Writer für Linux. Inspiriert vom originalen lufus-Tool für Windows. -Version: v1.0.0b1 GitHub: github.com/hog185/lufus" about_subtitle,USB-Flash-Tool btn_close,Schließen diff --git a/src/lufus/gui/languages/English.csv b/src/lufus/gui/languages/English.csv index c029fc25..385b5f3e 100644 --- a/src/lufus/gui/languages/English.csv +++ b/src/lufus/gui/languages/English.csv @@ -90,7 +90,6 @@ dlg_select_image_title,Select Disk Image dlg_select_image_filter,Disk Images (*.iso *.dmg *.img *.bin *.raw);;All Files (*) about_content,"Lufus is a disk image writer written in Python for Linux. Inspired by the original Rufus tool for Windows. -Version: v1.0.0b1 GitHub: github.com/hog185/lufus" about_subtitle,USB Flash Tool btn_close,Close diff --git "a/src/lufus/gui/languages/Espa\303\261ol.csv" "b/src/lufus/gui/languages/Espa\303\261ol.csv" index c9bf5f84..a4d54ada 100644 --- "a/src/lufus/gui/languages/Espa\303\261ol.csv" +++ "b/src/lufus/gui/languages/Espa\303\261ol.csv" @@ -92,7 +92,6 @@ dlg_select_image_filter,Imagenes ISO (*.iso);;All Files (*) about_content,"Lufus es una utilidad de escritura de discos para Linux hecha en Python. Inspirado por la herramienta original Rufus para Windows. -Version: v1.0.0b1 GitHub: github.com/hog185/lufus" about_subtitle,Herramienta de flash USB btn_close,Cerrar diff --git "a/src/lufus/gui/languages/Fran\303\247ais.csv" "b/src/lufus/gui/languages/Fran\303\247ais.csv" index 0cab6b00..f9030b5a 100644 --- "a/src/lufus/gui/languages/Fran\303\247ais.csv" +++ "b/src/lufus/gui/languages/Fran\303\247ais.csv" @@ -90,7 +90,6 @@ dlg_select_image_title,Sélectionner l'image disque dlg_select_image_filter,Images disque (*.iso *.dmg *.img *.bin *.raw);;Tous les fichiers (*) about_content,"Lufus est un logiciel libre d'écriture d'images disque écrit en Python pour GNU/Linux, inspiré par l'outil original Rufus, disponible uniquement pour Windows. -Version : v1.0.0b1 GitHub : https://github.com/Hog185/Lufus/" about_subtitle,Outil d'écriture USB btn_close,Fermer diff --git "a/src/lufus/gui/languages/Portugue\314\202s Brasileiro.csv" "b/src/lufus/gui/languages/Portugue\314\202s Brasileiro.csv" index d8f083f7..4e240134 100644 --- "a/src/lufus/gui/languages/Portugue\314\202s Brasileiro.csv" +++ "b/src/lufus/gui/languages/Portugue\314\202s Brasileiro.csv" @@ -90,7 +90,6 @@ dlg_select_image_title,Selecionar imagem de disco dlg_select_image_filter,Imagems ISO (*.iso);;Todos os arquivos (*) about_content,"O Lufus é um gravador de imagem escrito em python para o Linux. É inspirado no Rufus para o Windows. -Version: v1.0.0b1 GitHub: github.com/hog185/lufus" about_subtitle,Ferramenta de Flash USB btn_close,Fechar diff --git a/src/lufus/gui/languages/Svenska.csv b/src/lufus/gui/languages/Svenska.csv index bda0588f..c8f3a376 100644 --- a/src/lufus/gui/languages/Svenska.csv +++ b/src/lufus/gui/languages/Svenska.csv @@ -90,7 +90,6 @@ dlg_select_image_title,Välj enhetsavbildning dlg_select_image_filter,Enhetsavbildningar (*.iso *.dmg *.img *.bin *.raw);;Alla filer (*) about_content,"Lufus är ett verktyg för att skriva diskavbildningar, skrivet i Python för Linux. Inspirerat av det ursprungliga Rufus-verktyget för Windows. -Version: v1.0.0b1 GitHub: github.com/hog185/lufus" about_subtitle,USB-skrivningsverktyg btn_close,Stäng diff --git "a/src/lufus/gui/languages/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.csv" "b/src/lufus/gui/languages/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.csv" index ea94ee45..49f913c3 100644 --- "a/src/lufus/gui/languages/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.csv" +++ "b/src/lufus/gui/languages/\320\240\321\203\321\201\321\201\320\272\320\270\320\271.csv" @@ -90,7 +90,6 @@ dlg_select_image_title,Выберите образ для записи dlg_select_image_filter,Образы дисков (*.iso *.dmg *.img *.bin *.raw);;Все файлы (*) about_content,"Lufus - это программа для записи образов дисков, написанная на языке Python для Linux. Вдохновлено оригинальным инструментом Rufus для Windows. -Версия: v1.0.0b1 GitHub: github.com/hog185/lufus" about_subtitle,Инструмент для записи USB btn_close,Закрыть diff --git "a/src/lufus/gui/languages/\330\271\330\261\330\250\331\212.csv" "b/src/lufus/gui/languages/\330\271\330\261\330\250\331\212.csv" index 5a2e77c7..25bdd611 100644 --- "a/src/lufus/gui/languages/\330\271\330\261\330\250\331\212.csv" +++ "b/src/lufus/gui/languages/\330\271\330\261\330\250\331\212.csv" @@ -90,7 +90,6 @@ dlg_select_image_title,اختار ملف الصورة dlg_select_image_filter,Disk Images (*.iso *.dmg *.img *.bin *.raw);;كل الملفات (*) about_content,"لوفس (lufus) هو برنامج مصنوع بلغة بايثون لنظام تشغيل لينيكس. مستوحى من برنامج روفس (rufus) الأصلي لنظام تشغيل ويندوز. -الإصدار: 1.0.0b1 GitHub: github.com/hog185/lufus" about_subtitle,أداة USB Flash btn_close,إغلاق diff --git "a/src/lufus/gui/languages/\340\246\254\340\246\276\340\246\202\340\246\262\340\246\276.csv" "b/src/lufus/gui/languages/\340\246\254\340\246\276\340\246\202\340\246\262\340\246\276.csv" index c0fd3ea4..dcf7c800 100644 --- "a/src/lufus/gui/languages/\340\246\254\340\246\276\340\246\202\340\246\262\340\246\276.csv" +++ "b/src/lufus/gui/languages/\340\246\254\340\246\276\340\246\202\340\246\262\340\246\276.csv" @@ -90,7 +90,6 @@ dlg_select_image_title,ডিস্ক ইমেজ নির্বাচন ক dlg_select_image_filter,ডিস্ক ইমেজ (*.iso *.dmg *.img *.bin *.raw);;সব ফাইল (*) about_content,"লুফাস একটি ডিস্ক ইমেজ লেখার টুল যা লিনাক্সের জন্য Python দিয়ে তৈরি। উইন্ডোজের মূল Rufus টুল থেকে অনুপ্রাণিত। -ভার্সন: v1.0.0b1 GitHub: github.com/hog185/lufus" about_subtitle,USB ফ্ল্যাশ টুল btn_close,বন্ধ diff --git a/src/lufus/gui/workers.py b/src/lufus/gui/workers.py index 6c9bfb37..8b3158d7 100644 --- a/src/lufus/gui/workers.py +++ b/src/lufus/gui/workers.py @@ -51,6 +51,7 @@ class FlashWorker(QThread): progress = pyqtSignal(int) status = pyqtSignal(str) flash_done = pyqtSignal(bool) + request_tweaks = pyqtSignal() def __init__(self, options: dict, t: dict): super().__init__() @@ -109,7 +110,10 @@ def run(self): self.status.emit(self._T.get("status_format_complete", "Format complete!")) else: self.status.emit( - self._T.get("status_format_failed", "Format FAILED. Check the log above for the exact error.") + self._T.get( + "status_format_failed", + "Format FAILED. Check the log above for the exact error.", + ) ) elif image_option == 0: # Windows @@ -117,7 +121,11 @@ def run(self): # Any other mode (e.g. DD) uses the generic flash_usb path. scheme = PartitionScheme.SIMPLE_FAT32 success = flash_usb( - device_node, iso_path, scheme, progress_cb=self.progress.emit, status_cb=self.status.emit + device_node, + iso_path, + scheme, + progress_cb=self.progress.emit, + status_cb=self.status.emit, ) else: # Other flash modes (Linux, Other) diff --git a/src/lufus/state.py b/src/lufus/state.py index ccef2dee..a6c3117f 100644 --- a/src/lufus/state.py +++ b/src/lufus/state.py @@ -8,7 +8,7 @@ class AppState: """Mutable runtime state shared across the application.""" # App info - version: str = "v1.0.1b1" + version: str = "v1.0.0" # Format options filesystem_index: int = 0 # 0=NTFS, 1=FAT32, 2=exFAT, 3=ext4, 4=UDF @@ -21,7 +21,7 @@ class AppState: check_bad: int = 0 # 0=1 pass, 1=2 passes new_label: str = "USB_DRIVE" flash_mode: int = 0 # 0=ISO, 1=DD - + theme: str = "default" # Runtime state iso_path: str = "" device_node: str = "" @@ -36,6 +36,7 @@ class AppState: # Windows tweaks win_hardware_bypass: int = 0 win_microsoft_acc: int = 0 + win_local_acc_chk: int = 0 win_local_acc: str = "default" win_privacy: int = 0 diff --git a/src/lufus/utils.py b/src/lufus/utils.py index f57001cd..4065ff4b 100644 --- a/src/lufus/utils.py +++ b/src/lufus/utils.py @@ -22,11 +22,19 @@ def elevate_privileges() -> None: import logging logging.getLogger("lufus").warning( - "elevate_privileges: rejected suspicious LUFUS_THEME value %r", theme_val + "elevate_privileges: rejected suspicious LUFUS_THEME value %r", + theme_val, ) # Preserve DISPLAY and XAUTHORITY for GUI apps under pkexec/sudo - env_vars = ["DISPLAY", "XAUTHORITY", "XDG_RUNTIME_DIR", "WAYLAND_DISPLAY", "PYTHONPATH", "LUFUS_THEME"] + env_vars = [ + "DISPLAY", + "XAUTHORITY", + "XDG_RUNTIME_DIR", + "WAYLAND_DISPLAY", + "PYTHONPATH", + "LUFUS_THEME", + ] cmd = ["pkexec", "env"] for var in env_vars: