Collapse engine patch/undo/status into one dynamic button#37
Collapse engine patch/undo/status into one dynamic button#37RobThePCGuy wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the BlueStacks engine patching UI in main.py by replacing the separate patch, restore, and status label elements with a single dynamic button that updates its label, color, and action based on the current patch state. Feedback suggests filtering out None values in _engine_state to prevent a single unrecognized installation from disabling the button for other valid installations, and using QPalette and setFont instead of setStyleSheet to preserve native button styling.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| states = [integrity_patch.installation_patched(i["install_path"]) | ||
| for i in self.installations | ||
| if i.get("patch_mode") and i.get("install_path") | ||
| and os.path.isdir(i["install_path"])] | ||
| if states and all(s is True for s in states): | ||
| return "Engine: Patched ✓ (applies to every instance)", "#2e7d32" | ||
| return "patched" | ||
| if states and all(s is False for s in states): | ||
| return "Engine: Not patched — click \"Patch BlueStacks Engine\" once", "#c62828" | ||
| return "unpatched" | ||
| if any(s is True for s in states): | ||
| return "Engine: Partially patched — re-run \"Patch BlueStacks Engine\"", "#e65100" | ||
| return "Engine: status unknown (unrecognized build?)", "#616161" | ||
| return "partial" | ||
| return "unknown" |
There was a problem hiding this comment.
If there are multiple installations and one of them is unrecognized or unreadable (returning None from installation_patched), the presence of that single None value will cause _engine_state to fall through and return "unknown". Because "unknown" disables the single engine button, this completely prevents the user from patching or restoring other valid, recognized installations.
Filtering out None values from states ensures that unrecognized builds do not block the management of valid installations.
| states = [integrity_patch.installation_patched(i["install_path"]) | |
| for i in self.installations | |
| if i.get("patch_mode") and i.get("install_path") | |
| and os.path.isdir(i["install_path"])] | |
| if states and all(s is True for s in states): | |
| return "Engine: Patched ✓ (applies to every instance)", "#2e7d32" | |
| return "patched" | |
| if states and all(s is False for s in states): | |
| return "Engine: Not patched — click \"Patch BlueStacks Engine\" once", "#c62828" | |
| return "unpatched" | |
| if any(s is True for s in states): | |
| return "Engine: Partially patched — re-run \"Patch BlueStacks Engine\"", "#e65100" | |
| return "Engine: status unknown (unrecognized build?)", "#616161" | |
| return "partial" | |
| return "unknown" | |
| raw_states = [ | |
| integrity_patch.installation_patched(i["install_path"]) | |
| for i in self.installations | |
| if i.get("patch_mode") and i.get("install_path") | |
| and os.path.isdir(i["install_path"]) | |
| ] | |
| states = [s for s in raw_states if s is not None] | |
| if states and all(s is True for s in states): | |
| return "patched" | |
| if states and all(s is False for s in states): | |
| return "unpatched" | |
| if any(s is True for s in states): | |
| return "partial" | |
| return "unknown" |
| }[state] | ||
| self.engine_button.setText(text) | ||
| self.engine_button.setToolTip(tip) | ||
| self.engine_button.setStyleSheet(f"color: {color}; font-weight: bold;") |
There was a problem hiding this comment.
Applying a stylesheet via setStyleSheet on a QPushButton in PyQt5 often overrides the native platform styling (such as hover animations, rounded corners, and native borders on Windows).
To preserve the native OS look-and-feel of the button while still customizing its text color and making it bold, you can use QPalette and setFont instead.
| self.engine_button.setStyleSheet(f"color: {color}; font-weight: bold;") | |
| from PyQt5.QtGui import QPalette, QColor | |
| palette = self.engine_button.palette() | |
| palette.setColor(QPalette.ButtonText, QColor(color)) | |
| self.engine_button.setPalette(palette) | |
| font = self.engine_button.font() | |
| font.setBold(True) | |
| self.engine_button.setFont(font) |
6334f35 to
50a278f
Compare
Three separate widgets (Patch button, Undo button, status label) become a single state-driven button: - unpatched -> "Patch BlueStacks Engine (required for root)" (red), patches - patched -> "Engine patched - click to Undo" (green), restores - partial -> "Engine partially patched - click to finish patching" (orange) - unknown -> disabled, greyed The label, colour, tooltip, and click action all derive from the live engine state, re-read at click time so a stale label can't trigger the wrong action.
Replaces the three engine widgets — Patch button, Undo button, and the status label — with a single button whose label, colour, tooltip, and action all reflect the live engine state:
State is re-read at click time so a stale label can't send the action the wrong way. Busy-state disabling is handled by the existing
_set_busypath.Verified headlessly across all four states (correct label/colour/action/enabled) plus busy-disable.