Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import sys
- import os
- import subprocess
- from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QTextEdit, QVBoxLayout, QWidget, QMessageBox
- from PySide6.QtGui import QColor, QDesktopServices, QIcon
- from PySide6.QtCore import Qt, QUrl, QRunnable, QThreadPool, Signal, QObject
- class FastbootWorker(QRunnable):
- """
- A QRunnable subclass to execute fastboot commands in a separate thread.
- Signals are used to communicate results and log messages back to the GUI thread.
- """
- class Signals(QObject):
- """
- Defines the signals available from a running worker thread.
- """
- log_message = Signal(str, QColor)
- process_finished = Signal(bool, str)
- user_action_required = Signal()
- error = Signal(str)
- def __init__(self, command_args: str, is_device_check: bool=False):
- super().__init__()
- self.command_args = command_args
- self.is_device_check = is_device_check
- self.signals = self.Signals()
- def run(self):
- """
- Executes the fastboot command and emits signals based on the outcome.
- """
- self.signals.log_message.emit(f'Executing: fastboot {self.command_args}', QColor('black'))
- try:
- process = subprocess.run(['fastboot', self.command_args], capture_output=True, text=True, check=False, creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == 'win32' else 0)
- stdout = process.stdout.strip()
- stderr = process.stderr.strip()
- exit_code = process.returncode
- if stdout:
- self.signals.log_message.emit(f'Output: {stdout}', QColor('gray'))
- if stderr:
- self.signals.log_message.emit(f'Error Output: {stderr}', QColor('red'))
- success = False
- if self.is_device_check:
- success = 'fastboot' in stdout.lower()
- else:
- success = exit_code == 0
- if not success:
- self.signals.log_message.emit(f'Command failed: fastboot {self.command_args}', QColor('red'))
- self.signals.process_finished.emit(success, self.command_args)
- except FileNotFoundError:
- error_msg = "Error: 'fastboot' command not found. Make sure fastboot is installed and in your system's PATH."
- self.signals.log_message.emit(error_msg, QColor('red'))
- self.signals.error.emit(error_msg)
- self.signals.process_finished.emit(False, self.command_args)
- except Exception as e:
- error_msg = f'An unexpected error occurred during fastboot execution: {e}'
- self.signals.log_message.emit(error_msg, QColor('red'))
- self.signals.error.emit(error_msg)
- self.signals.process_finished.emit(False, self.command_args)
- class FRPToolApp(QMainWindow):
- """
- Main application window for the GSMYOGESH FRP Removal Tool.
- """
- def __init__(self):
- super().__init__()
- self.is_process_running = False
- self.thread_pool = QThreadPool.globalInstance()
- self._current_worker = None
- self.init_ui()
- self.display_welcome_message()
- def init_ui(self):
- """
- Initializes the user interface elements and layout.
- """
- self.setWindowTitle('A065 F065 FRP REMOVAL BY GSMYOGESH.COM')
- self.setGeometry(100, 100, 600, 400)
- central_widget = QWidget()
- self.setCentralWidget(central_widget)
- layout = QVBoxLayout(central_widget)
- self.instruction_label = QLabel('Connect DEVICE in FASTBOOT MODE')
- self.instruction_label.setObjectName('instructionLabel')
- layout.addWidget(self.instruction_label)
- self.log_text_edit = QTextEdit()
- self.log_text_edit.setReadOnly(True)
- self.log_text_edit.setObjectName('logTextEdit')
- layout.addWidget(self.log_text_edit)
- self.remove_frp_button = QPushButton('REMOVE FRP')
- self.remove_frp_button.setObjectName('removeFRPButton')
- self.remove_frp_button.clicked.connect(self.start_frp_removal)
- layout.addWidget(self.remove_frp_button)
- self.apply_qss()
- def apply_qss(self):
- """
- Applies Qt Style Sheet (QSS) to the application for styling.
- Removed unsupported CSS properties like box-shadow, transition, transform.
- """
- qss = '\n QMainWindow {\n background-color: #f0f2f5; /* Light gray background */\n }\n\n #instructionLabel {\n font-family: "Segoe UI", sans-serif;\n font-size: 16px;\n font-weight: bold;\n color: #333;\n padding: 10px;\n text-align: center;\n background-color: #e0e5ec; /* Soft background */\n border-radius: 8px;\n margin: 10px;\n /* box-shadow: 2px 2px 5px rgba(0,0,0,0.1); Removed: Unsupported in QSS */\n }\n\n #logTextEdit {\n font-family: "Consolas", "Monaco", monospace;\n font-size: 13px;\n color: #333;\n background-color: #ffffff;\n border: 1px solid #c0c0c0;\n border-radius: 8px;\n padding: 10px;\n margin: 10px;\n /* box-shadow: inset 1px 1px 3px rgba(0,0,0,0.1); Removed: Unsupported in QSS */\n }\n\n #removeFRPButton {\n background-color: #4CAF50; /* Green */\n color: white;\n font-family: "Segoe UI", sans-serif;\n font-size: 16px;\n font-weight: bold;\n border: none;\n border-radius: 10px;\n padding: 12px 24px;\n margin: 10px;\n min-height: 40px;\n /* box-shadow: 3px 3px 6px rgba(0,0,0,0.2); Removed: Unsupported in QSS */\n /* transition: background-color 0.3s ease, transform 0.1s ease; Removed: Unsupported in QSS */\n }\n\n #removeFRPButton:hover {\n background-color: #45a049; /* Darker green on hover */\n /* transform: translateY(-2px); Removed: Unsupported in QSS */\n }\n\n #removeFRPButton:pressed {\n background-color: #3e8e41; /* Even darker on press */\n /* transform: translateY(0); Removed: Unsupported in QSS */\n /* box-shadow: 1px 1px 3px rgba(0,0,0,0.2); Removed: Unsupported in QSS */\n }\n\n #removeFRPButton:disabled {\n background-color: #cccccc;\n color: #666666;\n /* box-shadow: none; Removed: Unsupported in QSS */\n }\n '
- self.setStyleSheet(qss)
- def display_welcome_message(self):
- """
- Clears the log and displays the initial welcome messages.
- """
- self.log_text_edit.clear()
- self.log_message('Samsung A065 - U1,U2,U3', QColor('blue'))
- self.log_message('Samsung F065', QColor('blue'))
- self.log_message('BY GSMYOGESH.COM', QColor('darkblue'))
- self.log_message('\nEnter Device in Fastboot Mode', QColor('red'))
- self.log_message('\nReady to start FRP removal process...', QColor('black'))
- self.log_message('Make sure your device is connected in FASTBOOT MODE!\n', QColor('black'))
- def log_message(self, message: str, color: QColor):
- """
- Appends a colored message to the log text edit.
- Uses HTML for rich text formatting.
- """
- if self.thread() != QApplication.instance().thread():
- self.log_text_edit.append(f"<span style='color:{color.name()};'>{message}</span>")
- else:
- self.log_text_edit.append(f"<span style='color:{color.name()};'>{message}</span>")
- self.log_text_edit.verticalScrollBar().setValue(self.log_text_edit.verticalScrollBar().maximum())
- def show_message_box(self, title: str, message: str, icon: QMessageBox.Icon, buttons: QMessageBox.StandardButtons):
- """
- Displays a custom message box (replaces C# MessageBox.Show).
- """
- msg_box = QMessageBox(self)
- msg_box.setWindowTitle(title)
- msg_box.setText(message)
- msg_box.setIcon(icon)
- msg_box.setStandardButtons(buttons)
- msg_box.setWindowFlags(msg_box.windowFlags() + Qt.WindowStaysOnTopHint)
- return msg_box.exec()
- def open_website(self, url: str):
- """
- Opens the specified URL in the default web browser.
- """
- try:
- QDesktopServices.openUrl(QUrl(url))
- self.log_message(f'Opened website: {url}', QColor('blue'))
- except Exception as e:
- self.log_message(f'Could not open website automatically: {e}', QColor('orange'))
- def start_frp_removal(self):
- """
- Initiates the FRP removal process.
- Manages the state of the process and button.
- """
- if self.is_process_running:
- self.show_message_box('Process Running', 'FRP removal process is already running!', QMessageBox.Icon.Warning, QMessageBox.StandardButton.Ok)
- return
- self.is_process_running = True
- self.remove_frp_button.setEnabled(False)
- self.remove_frp_button.setText('PROCESSING...')
- self.log_text_edit.clear()
- self._step_check_devices()
- def _step_check_devices(self):
- """Step 1: Check for connected devices."""
- self.log_message('Starting FRP removal process...', QColor('blue'))
- self.log_message('Checking connected devices...', QColor('black'))
- self._current_worker = FastbootWorker('devices', is_device_check=True)
- self._current_worker.signals.log_message.connect(self.log_message)
- self._current_worker.signals.process_finished.connect(self._handle_check_devices_result)
- self._current_worker.signals.error.connect(self._handle_error)
- self.thread_pool.start(self._current_worker)
- def _handle_check_devices_result(self, success: bool, command_args: str):
- """Handles the result of the 'fastboot devices' command."""
- if self._current_worker:
- self._current_worker.signals.process_finished.disconnect(self._handle_check_devices_result)
- self._current_worker.signals.log_message.disconnect(self.log_message)
- self._current_worker.signals.error.disconnect(self._handle_error)
- if not success:
- self.log_message('No device found in fastboot mode!', QColor('red'))
- self.show_message_box('Device Not Found', 'No device detected in fastboot mode!\nPlease connect your device in fastboot mode and try again.', QMessageBox.Icon.Critical, QMessageBox.StandardButton.Ok)
- self._reset_ui_state()
- else:
- self.log_message('Device detected in fastboot mode.', QColor('green'))
- self._step_flashing_unlock()
- self._current_worker = None
- def _step_flashing_unlock(self):
- """Step 2: Start flashing unlock."""
- self.log_message('Preparing device...', QColor('black'))
- self._current_worker = FastbootWorker('flashing unlock')
- self._current_worker.signals.log_message.connect(self.log_message)
- self._current_worker.signals.process_finished.connect(self._handle_flashing_unlock_result)
- self._current_worker.signals.error.connect(self._handle_error)
- self.thread_pool.start(self._current_worker)
- def _handle_flashing_unlock_result(self, success: bool, command_args: str):
- """Handles the result of 'fastboot flashing unlock' and prompts user."""
- if self._current_worker:
- self._current_worker.signals.process_finished.disconnect(self._handle_flashing_unlock_result)
- self._current_worker.signals.log_message.disconnect(self.log_message)
- self._current_worker.signals.error.disconnect(self._handle_error)
- if not success:
- self.log_message('Failed to initiate flashing unlock. Check device status.', QColor('red'))
- self.show_message_box('Unlock Failed', 'Failed to initiate flashing unlock. Please ensure your device is ready.', QMessageBox.Icon.Critical, QMessageBox.StandardButton.Ok)
- self._reset_ui_state()
- self._current_worker = None
- return
- reply = self.show_message_box('User Action Required', 'PRESS VOLUME UP TO CONTINUE\n\nOn your device:\n1. Use Volume UP/DOWN to navigate\n2. Press Volume UP to confirm unlock\n3. Click OK here after confirming on device', QMessageBox.Icon.Information, QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Cancel)
- if reply == QMessageBox.StandardButton.Ok:
- self._step_erase_persistent()
- else:
- self.log_message('Process cancelled by user.', QColor('red'))
- self._reset_ui_state()
- self._current_worker = None
- def _step_erase_persistent(self):
- """Step 3: Erase persistent partition."""
- self.log_message('Processing device data...', QColor('black'))
- self._current_worker = FastbootWorker('erase persistent')
- self._current_worker.signals.log_message.connect(self.log_message)
- self._current_worker.signals.process_finished.connect(self._handle_erase_persistent_result)
- self._current_worker.signals.error.connect(self._handle_error)
- self.thread_pool.start(self._current_worker)
- def _handle_erase_persistent_result(self, success: bool, command_args: str):
- """Handles the result of 'fastboot erase persistent'."""
- if self._current_worker:
- self._current_worker.signals.process_finished.disconnect(self._handle_erase_persistent_result)
- self._current_worker.signals.log_message.disconnect(self.log_message)
- self._current_worker.signals.error.disconnect(self._handle_error)
- if not success:
- self.log_message('Failed to erase persistent partition.', QColor('red'))
- self.show_message_box('Erase Failed', 'Failed to erase persistent partition. Please check logs for details.', QMessageBox.Icon.Critical, QMessageBox.StandardButton.Ok)
- self._reset_ui_state()
- else:
- self.log_message('Persistent partition erased.', QColor('green'))
- self._step_erase_userdata()
- self._current_worker = None
- def _step_erase_userdata(self):
- """Step 4: Erase userdata partition."""
- self.log_message('Clearing device memory...', QColor('black'))
- self._current_worker = FastbootWorker('erase userdata')
- self._current_worker.signals.log_message.connect(self.log_message)
- self._current_worker.signals.process_finished.connect(self._handle_erase_userdata_result)
- self._current_worker.signals.error.connect(self._handle_error)
- self.thread_pool.start(self._current_worker)
- def _handle_erase_userdata_result(self, success: bool, command_args: str):
- """Handles the result of 'fastboot erase userdata'."""
- if self._current_worker:
- self._current_worker.signals.process_finished.disconnect(self._handle_erase_userdata_result)
- self._current_worker.signals.log_message.disconnect(self.log_message)
- self._current_worker.signals.error.disconnect(self._handle_error)
- if not success:
- self.log_message('Failed to erase userdata partition.', QColor('red'))
- self.show_message_box('Erase Failed', 'Failed to erase userdata partition. Please check logs for details.', QMessageBox.Icon.Critical, QMessageBox.StandardButton.Ok)
- self._reset_ui_state()
- else:
- self.log_message('Userdata partition erased.', QColor('green'))
- self._step_flash_super()
- self._current_worker = None
- def _step_flash_super(self):
- """Step 5: Flash super.img."""
- self.log_message('Installing system files... This may take several minutes...', QColor('black'))
- super_img_path = os.path.join(os.getcwd(), 'super.img')
- if not os.path.exists(super_img_path):
- error_msg = f'Error: super.img not found at {super_img_path}. Please ensure the file exists.'
- self.log_message(error_msg, QColor('red'))
- self.show_message_box('File Not Found', error_msg, QMessageBox.Icon.Critical, QMessageBox.StandardButton.Ok)
- self._reset_ui_state()
- return
- command = f'flash super "{super_img_path}"'
- self._current_worker = FastbootWorker(command)
- self._current_worker.signals.log_message.connect(self.log_message)
- self._current_worker.signals.process_finished.connect(self._handle_flash_super_result)
- self._current_worker.signals.error.connect(self._handle_error)
- self.thread_pool.start(self._current_worker)
- def _handle_flash_super_result(self, success: bool, command_args: str):
- """Handles the result of 'fastboot flash super'."""
- if self._current_worker:
- self._current_worker.signals.process_finished.disconnect(self._handle_flash_super_result)
- self._current_worker.signals.log_message.disconnect(self.log_message)
- self._current_worker.signals.error.disconnect(self._handle_error)
- if not success:
- self.log_message('Failed to flash super.img.', QColor('red'))
- self.show_message_box('Flash Failed', 'Failed to flash super.img. Please check logs for details.', QMessageBox.Icon.Critical, QMessageBox.StandardButton.Ok)
- self._reset_ui_state()
- else:
- self.log_message('super.img flashed successfully.', QColor('green'))
- self._step_reboot()
- self._current_worker = None
- def _step_reboot(self):
- """Step 6: Reboot the device."""
- self.log_message('Finalizing process...', QColor('black'))
- self._current_worker = FastbootWorker('reboot')
- self._current_worker.signals.log_message.connect(self.log_message)
- self._current_worker.signals.process_finished.connect(self._handle_reboot_result)
- self._current_worker.signals.error.connect(self._handle_error)
- self.thread_pool.start(self._current_worker)
- def _handle_reboot_result(self, success: bool, command_args: str):
- """Handles the result of 'fastboot reboot' and finalizes the process."""
- if self._current_worker:
- self._current_worker.signals.process_finished.disconnect(self._handle_reboot_result)
- self._current_worker.signals.log_message.disconnect(self.log_message)
- self._current_worker.signals.error.disconnect(self._handle_error)
- if not success:
- self.log_message('Failed to reboot device. Please reboot manually.', QColor('orange'))
- else:
- self.log_message('Device rebooted successfully.', QColor('green'))
- self.log_message('\nFRP REMOVAL COMPLETED!', QColor('green'))
- self.log_message('\nIMPORTANT INSTRUCTIONS:', QColor('red'))
- self.log_message('1. PUT PHONE TO DOWNLOAD MODE', QColor('red'))
- self.log_message('2. LONG PRESS VOLUME UP BUTTON TO RELOCK BOOTLOADER', QColor('red'))
- self.log_message('\nPowered By GSMYOGESH', QColor('blue'))
- self.log_message('Contact: +917043259004', QColor('blue'))
- self.show_message_box('Process Complete', 'FRP Removal Process Completed!\n\nNEXT STEPS:\n1. Put phone in DOWNLOAD MODE\n2. Long press VOLUME UP to relock bootloader\n\nContact: +917043259004\nWebsite: WWW.GSMYOGESH.COM', QMessageBox.Icon.Information, QMessageBox.StandardButton.Ok)
- self.open_website('https://www.gsmyogesh.com')
- self._reset_ui_state()
- self._current_worker = None
- def _handle_error(self, error_message: str):
- """Handles errors reported by worker threads."""
- self.log_message(f'An error occurred: {error_message}', QColor('red'))
- self.show_message_box('Error', f'An error occurred during the process: {error_message}', QMessageBox.Icon.Critical, QMessageBox.StandardButton.Ok)
- self._reset_ui_state()
- if self._current_worker:
- self._current_worker.signals.process_finished.disconnect(self._handle_error)
- self._current_worker.signals.log_message.disconnect(self.log_message)
- self._current_worker.signals.error.disconnect(self._handle_error)
- self._current_worker = None
- def _reset_ui_state(self):
- """Resets the UI elements to their initial state after a process completes or fails."""
- self.is_process_running = False
- self.remove_frp_button.setEnabled(True)
- self.remove_frp_button.setText('REMOVE FRP')
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- window = FRPToolApp()
- window.show()
- sys.exit(app.exec())
Advertisement
Add Comment
Please, Sign In to add comment