Files
Nugget/gui/main_window.py
2025-04-03 12:11:22 -04:00

1203 lines
57 KiB
Python

from PySide6 import QtCore, QtWidgets, QtGui
from enum import Enum
from os import name as os_name
import webbrowser
import plistlib
from pymobiledevice3.lockdown import create_using_usbmux
from qt.ui_mainwindow import Ui_Nugget
from controllers.web_request_handler import is_update_available
from devicemanagement.constants import Version
from devicemanagement.device_manager import DeviceManager
from gui.dialogs import GestaltDialog, UpdateAppDialog, PBHelpDialog
from gui.apply_worker import ApplyThread, ApplyAlertMessage
from tweaks.tweaks import tweaks
from tweaks.custom_gestalt_tweaks import CustomGestaltTweaks, ValueTypeStrings
from tweaks.daemons_tweak import Daemon
App_Version = "5.1"
App_Build = 0
class Page(Enum):
Home = 0
Gestalt = 1
FeatureFlags = 2
EUEnabler = 3
Springboard = 4
InternalOptions = 5
Daemons = 6
Posterboard = 7
RiskyTweaks = 8
Apply = 9
Settings = 10
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, device_manager: DeviceManager):
super(MainWindow, self).__init__()
self.device_manager = device_manager
self.ui = Ui_Nugget()
self.ui.setupUi(self)
self.show_uuid = False
self.pb_mainLayout = None
self.applying_in_progress = False
self.threadpool = QtCore.QThreadPool()
self.loadSettings()
# Check for an update
if is_update_available(App_Version, App_Build):
# notify with prompt to download the new version from github
UpdateAppDialog().exec()
# Update the app version/build number label
self.updateAppVersionLabel()
## DEVICE BAR
self.refresh_devices()
self.ui.refreshBtn.clicked.connect(self.refresh_devices)
self.ui.devicePicker.currentIndexChanged.connect(self.change_selected_device)
## SIDE BAR ACTIONS
self.ui.homePageBtn.clicked.connect(self.on_homePageBtn_clicked)
self.ui.gestaltPageBtn.clicked.connect(self.on_gestaltPageBtn_clicked)
self.ui.featureFlagsPageBtn.clicked.connect(self.on_featureFlagsPageBtn_clicked)
self.ui.euEnablerPageBtn.clicked.connect(self.on_euEnablerPageBtn_clicked)
self.ui.springboardOptionsPageBtn.clicked.connect(self.on_springboardOptionsPageBtn_clicked)
self.ui.internalOptionsPageBtn.clicked.connect(self.on_internalOptionsPageBtn_clicked)
self.ui.daemonsPageBtn.clicked.connect(self.on_daemonsPageBtn_clicked)
self.ui.posterboardPageBtn.clicked.connect(self.on_posterboardPageBtn_clicked)
self.ui.advancedPageBtn.clicked.connect(self.on_advancedPageBtn_clicked)
self.ui.applyPageBtn.clicked.connect(self.on_applyPageBtn_clicked)
self.ui.settingsPageBtn.clicked.connect(self.on_settingsPageBtn_clicked)
## HOME PAGE ACTIONS
self.ui.phoneVersionLbl.linkActivated.connect(self.toggle_version_label)
## HOME PAGE LINKS
self.ui.bigNuggetBtn.clicked.connect(self.on_bigNuggetBtn_clicked)
self.ui.starOnGithubBtn.clicked.connect(self.on_githubBtn_clicked)
self.ui.leminGithubBtn.clicked.connect(self.on_leminGitHubBtn_clicked)
self.ui.leminTwitterBtn.clicked.connect(self.on_leminTwitterBtn_clicked)
self.ui.leminKoFiBtn.clicked.connect(self.on_leminKoFiBtn_clicked)
self.ui.posterRestoreBtn.clicked.connect(self.on_posterRestoreBtn_clicked)
self.ui.snoolieBtn.clicked.connect(self.on_snoolieBtn_clicked)
self.ui.disfordottieBtn.clicked.connect(self.on_disfordottieBtn_clicked)
self.ui.mikasaBtn.clicked.connect(self.on_mikasaBtn_clicked)
self.ui.libiBtn.clicked.connect(self.on_libiBtn_clicked)
self.ui.jjtechBtn.clicked.connect(self.on_jjtechBtn_clicked)
self.ui.qtBtn.clicked.connect(self.on_qtBtn_clicked)
self.ui.discordBtn.clicked.connect(self.on_discordBtn_clicked)
## ELIGIBILITY PAGE ACTIONS
self.ui.euEnablerEnabledChk.toggled.connect(self.on_euEnablerEnabledChk_toggled)
self.ui.methodChoiceDrp.activated.connect(self.on_methodChoiceDrp_activated)
self.ui.regionCodeTxt.textEdited.connect(self.on_regionCodeTxt_textEdited)
self.ui.enableAIChk.toggled.connect(self.on_enableAIChk_toggled)
self.ui.eligFileChk.toggled.connect(self.on_eligFileChk_toggled)
self.ui.languageTxt.hide() # to be removed later
self.ui.languageLbl.hide() # to be removed later
self.ui.languageTxt.textEdited.connect(self.on_languageTxt_textEdited)
self.ui.spoofedModelDrp.activated.connect(self.on_spoofedModelDrp_activated)
self.ui.spoofHardwareChk.toggled.connect(self.on_spoofHardwareChk_toggled)
self.ui.spoofCPUChk.toggled.connect(self.on_spoofCPUChk_toggled)
## FEATURE FLAGS PAGE
self.ui.clockAnimChk.toggled.connect(self.on_clockAnimChk_toggled)
self.ui.lockscreenChk.toggled.connect(self.on_lockscreenChk_clicked)
self.ui.photosChk.toggled.connect(self.on_photosChk_clicked)
self.ui.aiChk.toggled.connect(self.on_aiChk_clicked)
## SPRINGBOARD OPTIONS PAGE ACTIONS
self.ui.footnoteTxt.textEdited.connect(self.on_footnoteTxt_textEdited)
self.ui.disableLockRespringChk.toggled.connect(self.on_disableLockRespringChk_clicked)
self.ui.disableDimmingChk.toggled.connect(self.on_disableDimmingChk_clicked)
self.ui.disableBatteryAlertsChk.toggled.connect(self.on_disableBatteryAlertsChk_clicked)
self.ui.disableCrumbChk.toggled.connect(self.on_disableCrumbChk_clicked)
self.ui.enableSupervisionTextChk.toggled.connect(self.on_enableSupervisionTextChk_clicked)
self.ui.enableAirPlayChk.toggled.connect(self.on_enableAirPlayChk_clicked)
## INTERNAL OPTIONS PAGE ACTIONS
self.ui.buildVersionChk.toggled.connect(self.on_buildVersionChk_clicked)
self.ui.RTLChk.toggled.connect(self.on_RTLChk_clicked)
self.ui.metalHUDChk.toggled.connect(self.on_metalHUDChk_clicked)
self.ui.iMessageChk.toggled.connect(self.on_iMessageChk_clicked)
self.ui.IDSChk.toggled.connect(self.on_IDSChk_clicked)
self.ui.VCChk.toggled.connect(self.on_VCChk_clicked)
self.ui.appStoreChk.toggled.connect(self.on_appStoreChk_clicked)
self.ui.notesChk.toggled.connect(self.on_notesChk_clicked)
self.ui.showTouchesChk.toggled.connect(self.on_showTouchesChk_clicked)
self.ui.hideRespringChk.toggled.connect(self.on_hideRespringChk_clicked)
self.ui.enableWakeVibrateChk.toggled.connect(self.on_enableWakeVibrateChk_clicked)
self.ui.pasteSoundChk.toggled.connect(self.on_pasteSoundChk_clicked)
self.ui.notifyPastesChk.toggled.connect(self.on_notifyPastesChk_clicked)
## DAEMONS PAGE ACTIONS
self.ui.modifyDaemonsChk.toggled.connect(self.on_modifyDaemonsChk_clicked)
self.ui.thermalmonitordChk.toggled.connect(self.on_thermalmonitordChk_clicked)
self.ui.otadChk.toggled.connect(self.on_otadChk_clicked)
self.ui.usageTrackingAgentChk.toggled.connect(self.on_usageTrackingAgentChk_clicked)
self.ui.gameCenterChk.toggled.connect(self.on_gameCenterChk_clicked)
self.ui.screenTimeChk.toggled.connect(self.on_screenTimeChk_clicked)
self.ui.clearScreenTimeAgentChk.toggled.connect(self.on_clearScreenTimeAgentChk_clicked)
self.ui.crashReportsChk.toggled.connect(self.on_crashReportsChk_clicked)
self.ui.atwakeupChk.toggled.connect(self.on_atwakeupChk_clicked)
self.ui.tipsChk.toggled.connect(self.on_tipsChk_clicked)
self.ui.vpndChk.toggled.connect(self.on_vpndChk_clicked)
self.ui.wapicChk.toggled.connect(self.on_wapicChk_clicked)
self.ui.healthdChk.toggled.connect(self.on_healthdChk_clicked)
self.ui.airprintChk.toggled.connect(self.on_airprintChk_clicked)
self.ui.assistiveTouchChk.toggled.connect(self.on_assistiveTouchChk_clicked)
self.ui.icloudChk.toggled.connect(self.on_icloudChk_clicked)
self.ui.hotspotChk.toggled.connect(self.on_hotspotChk_clicked)
self.ui.passbookChk.toggled.connect(self.on_passbookChk_clicked)
self.ui.spotlightChk.toggled.connect(self.on_spotlightChk_clicked)
self.ui.voiceControlChk.toggled.connect(self.on_voiceControlChk_clicked)
## POSTERBOARD PAGE ACTIONS
self.ui.modifyPosterboardsChk.toggled.connect(self.on_modifyPosterboardsChk_clicked)
self.ui.tendiesPageBtn.clicked.connect(self.on_tendiesPageBtn_clicked)
self.ui.videoPageBtn.clicked.connect(self.on_videoPageBtn_clicked)
self.ui.importTendiesBtn.clicked.connect(self.on_importTendiesBtn_clicked)
self.ui.resetPRBExtBtn.clicked.connect(self.on_resetPRBExtBtn_clicked)
self.ui.deleteAllDescriptorsBtn.clicked.connect(self.on_deleteAllDescriptorsBtn_clicked)
self.ui.chooseVideoBtn.clicked.connect(self.on_chooseVideoBtn_clicked)
self.ui.reverseLoopChk.toggled.connect(self.on_reverseLoopChk_toggled)
self.ui.useForegroundChk.toggled.connect(self.on_useForegroundChk_toggled)
self.ui.caVideoChk.hide()
self.ui.clearSuggestedBtn.hide()
self.ui.chooseThumbBtn.hide()
self.ui.pbVideoThumbLbl.hide()
self.ui.findPBBtn.clicked.connect(self.on_findPBBtn_clicked)
self.ui.pbHelpBtn.clicked.connect(self.on_pbHelpBtn_clicked)
## RISKY OPTIONS PAGE ACTIONS
self.ui.disableOTAChk.toggled.connect(self.on_disableOTAChk_clicked)
self.ui.enableResolutionChk.toggled.connect(self.on_enableResolutionChk_clicked)
self.ui.resHeightTxt.textEdited.connect(self.on_resHeightTxt_textEdited)
self.ui.resWidthTxt.textEdited.connect(self.on_resWidthTxt_textEdited)
## APPLY PAGE ACTIONS
self.ui.applyTweaksBtn.clicked.connect(self.on_applyPageBtn_clicked)
self.ui.removeTweaksBtn.clicked.connect(self.on_removeTweaksBtn_clicked)
self.ui.chooseGestaltBtn.clicked.connect(self.on_chooseGestaltBtn_clicked)
self.ui.resetGestaltBtn.clicked.connect(self.on_resetGestaltBtn_clicked)
## SETTINGS PAGE ACTIONS
self.ui.allowWifiApplyingChk.toggled.connect(self.on_allowWifiApplyingChk_toggled)
self.ui.autoRebootChk.toggled.connect(self.on_autoRebootChk_toggled)
self.ui.showRiskyChk.toggled.connect(self.on_showRiskyChk_toggled)
self.ui.showAllSpoofableChk.toggled.connect(self.on_showAllSpoofableChk_toggled)
self.ui.revertRdarChk.toggled.connect(self.on_revertRdarChk_toggled)
self.ui.skipSetupChk.toggled.connect(self.on_skipSetupChk_toggled)
self.ui.supervisionChk.toggled.connect(self.on_supervisionChk_toggled)
self.ui.supervisionOrganization.textEdited.connect(self.on_supervisionOrgTxt_textEdited)
self.ui.resetPairBtn.clicked.connect(self.on_resetPairBtn_clicked)
## MOBILE GESTALT PAGE ACTIONS
self.ui.dynamicIslandDrp.activated.connect(self.on_dynamicIslandDrp_activated)
self.ui.rdarFixChk.clicked.connect(self.on_rdarFixChk_clicked)
self.ui.modelNameChk.toggled.connect(self.on_modelNameChk_clicked)
self.ui.modelNameTxt.textEdited.connect(self.on_modelNameTxt_textEdited)
self.ui.bootChimeChk.clicked.connect(self.on_bootChimeChk_clicked)
self.ui.chargeLimitChk.clicked.connect(self.on_chargeLimitChk_clicked)
self.ui.tapToWakeChk.clicked.connect(self.on_tapToWakeChk_clicked)
self.ui.iphone16SettingsChk.clicked.connect(self.on_iphone16SettingsChk_clicked)
self.ui.parallaxChk.clicked.connect(self.on_parallaxChk_clicked)
self.ui.stageManagerChk.clicked.connect(self.on_stageManagerChk_clicked)
self.ui.enableMedusaChk.clicked.connect(self.on_enableMedusaChk_clicked)
self.ui.ipadAppsChk.clicked.connect(self.on_ipadAppsChk_clicked)
self.ui.shutterChk.clicked.connect(self.on_shutterChk_clicked)
self.ui.findMyFriendsChk.clicked.connect(self.on_findMyFriendsChk_clicked)
self.ui.pencilChk.clicked.connect(self.on_pencilChk_clicked)
self.ui.actionButtonChk.clicked.connect(self.on_actionButtonChk_clicked)
self.ui.internalInstallChk.clicked.connect(self.on_internalInstallChk_clicked)
self.ui.internalStorageChk.clicked.connect(self.on_internalStorageChk_clicked)
self.ui.collisionSOSChk.clicked.connect(self.on_collisionSOSChk_clicked)
self.ui.aodChk.clicked.connect(self.on_aodChk_clicked)
self.ui.aodVibrancyChk.clicked.connect(self.on_aodVibrancyChk_clicked)
self.ui.addGestaltKeyBtn.clicked.connect(self.on_addGestaltKeyBtn_clicked)
self.ui.aiEnablerContent.hide()
self.ui.resChangerContent.hide()
self.ui.resHeightWarningLbl.hide()
self.ui.resWidthWarningLbl.hide()
self.ui.pbActionLbl.hide()
## GENERAL INTERFACE FUNCTIONS
def updateInterfaceForNewDevice(self):
# update the home page
self.updatePhoneInfo()
def updateAppVersionLabel(self):
new_text: str = self.ui.appVersionLbl.text()
new_text = new_text.replace("%VERSION", App_Version)
if App_Build > 0:
new_text = new_text.replace("%BETATAG", f"(beta {App_Build})")
else:
new_text = new_text.replace("%BETATAG", "")
self.ui.appVersionLbl.setText(new_text)
## DEVICE BAR FUNCTIONS
@QtCore.Slot()
def refresh_devices(self):
# get the devices
self.device_manager.get_devices(self.settings)
# clear the picker
self.ui.devicePicker.clear()
self.ui.restoreProgressBar.hide()
if len(self.device_manager.devices) == 0:
self.ui.devicePicker.setEnabled(False)
self.ui.devicePicker.addItem('None')
self.ui.pages.setCurrentIndex(Page.Home.value)
self.ui.homePageBtn.setChecked(True)
# hide all pages
self.ui.sidebarDiv1.hide()
self.ui.gestaltPageBtn.hide()
self.ui.featureFlagsPageBtn.hide()
self.ui.euEnablerPageBtn.hide()
self.ui.springboardOptionsPageBtn.hide()
self.ui.internalOptionsPageBtn.hide()
self.ui.daemonsPageBtn.hide()
self.ui.posterboardPageBtn.hide()
self.ui.advancedPageBtn.hide()
self.ui.sidebarDiv2.hide()
self.ui.applyPageBtn.hide()
self.ui.resetPairBtn.hide()
self.ui.showRiskyChk.hide()
else:
self.ui.devicePicker.setEnabled(True)
# populate the ComboBox with device names
for device in self.device_manager.devices:
tag = ""
if self.device_manager.apply_over_wifi:
if device.connected_via_usb:
tag = " (@ USB)"
else:
tag = " (@ WiFi)"
self.ui.devicePicker.addItem(f"{device.name}{tag}")
# show all pages
self.ui.sidebarDiv1.show()
self.ui.springboardOptionsPageBtn.show()
self.ui.internalOptionsPageBtn.show()
self.ui.daemonsPageBtn.show()
self.ui.posterboardPageBtn.show()
if self.device_manager.allow_risky_tweaks:
self.ui.advancedPageBtn.show()
self.ui.resetPRBExtBtn.show()
else:
self.ui.advancedPageBtn.hide()
self.ui.resetPRBExtBtn.hide()
self.ui.sidebarDiv2.show()
self.ui.applyPageBtn.show()
self.ui.gestaltPageContent.setDisabled(False)
self.ui.featureFlagsPageContent.setDisabled(False)
self.ui.euEnablerPageContent.setDisabled(False)
self.ui.springboardOptionsPageContent.setDisabled(False)
self.ui.internalOptionsPageContent.setDisabled(False)
self.ui.advancedOptionsPageContent.setDisabled(False)
self.ui.resetPairBtn.show()
self.ui.showRiskyChk.show()
# update the selected device
self.ui.devicePicker.setCurrentIndex(0)
self.change_selected_device(0)
def setup_spoofedModelDrp_models(self):
# hide all the models first
for i in range(1, self.ui.spoofedModelDrp.count()):
try:
self.ui.spoofedModelDrp.removeItem(1)
except:
pass
# indexes 1-6 for iPhones, 7-(len(values) - 1) for iPads
# TODO: Make this get fetched from the gui on app startup
spoof_drp_options = ["iPhone 15 Pro (iPhone16,1)", "iPhone 15 Pro Max (iPhone16,2)", "iPhone 16 (iPhone17,3)", "iPhone 16 Plus (iPhone17,4)", "iPhone 16 Pro (iPhone17,1)", "iPhone 16 Pro Max (iPhone17,2)", "iPad Mini (A17 Pro) (W) (iPad16,1)", "iPad Mini (A17 Pro) (C) (iPad16,2)", "iPad Pro (13-inch) (M4) (W) (iPad16,5)", "iPad Pro (13-inch) (M4) (C) (iPad16,6)", "iPad Pro (11-inch) (M4) (W) (iPad16,3)", "iPad Pro (11-inch) (M4) (C) (iPad16,4)", "iPad Pro (12.9-inch) (M2) (W) (iPad14,5)", "iPad Pro (12.9-inch) (M2) (C) (iPad14,6)", "iPad Pro (11-inch) (M2) (W) (iPad14,3)", "iPad Pro (11-inch) (M2) (C) (iPad14,4)", "iPad Air (13-inch) (M2) (W) (iPad14,10)", "iPad Air (13-inch) (M2) (C) (iPad14,11)", "iPad Air (11-inch) (M2) (W) (iPad14,8)", "iPad Air (11-inch) (M2) (C) (iPad14,9)", "iPad Pro (11-inch) (M1) (W) (iPad13,4)", "iPad Pro (11-inch) (M1) (C) (iPad13,5)", "iPad Pro (12.9-inch) (M1) (W) (iPad13,8)", "iPad Pro (12.9-inch) (M1) (C) (iPad13,9)", "iPad Air (M1) (W) (iPad13,16)", "iPad Air (M1) (C) (iPad13,17)"]
if self.device_manager.show_all_spoofable_models or self.device_manager.get_current_device_model().startswith("iPhone"):
# re-enable iPhone spoof models
self.ui.spoofedModelDrp.addItems(spoof_drp_options[:6])
if self.device_manager.show_all_spoofable_models or self.device_manager.get_current_device_model().startswith("iPad"):
# re-enable iPad spoof models
self.ui.spoofedModelDrp.addItems(spoof_drp_options[6:])
def change_selected_device(self, index):
self.ui.showAllSpoofableChk.hide()
if len(self.device_manager.devices) > 0:
self.device_manager.set_current_device(index=index)
# hide options that are for newer versions
# remove the new dynamic island options
MinTweakVersions = {
"no_patch": [self.ui.chooseGestaltBtn, self.ui.gestaltPageBtn, self.ui.resetGestaltBtn, self.ui.gestaltLocationLbl, self.ui.gestaltLocationTitleLbl, self.ui.showAllSpoofableChk],
"exploit": [("18.0", self.ui.featureFlagsPageBtn), ("18.1", self.ui.eligFileChk), ("1.0", self.ui.regularDomainsLbl)],
"18.1": [self.ui.enableAIChk, self.ui.aiEnablerContent],
"18.0": [self.ui.aodChk, self.ui.aodVibrancyChk, self.ui.iphone16SettingsChk]
}
MaxTweakVersions = {
"patch": [self.ui.revertRdarChk, self.ui.revertRdarLine],
"17.7": [self.ui.euEnablerContent],
"18.0": [self.ui.photosChk, self.ui.aiChk]
}
try:
self.ui.dynamicIslandDrp.removeItem(6)
self.ui.dynamicIslandDrp.removeItem(5)
except:
pass
self.set_rdar_fix_label()
device_ver = Version(self.device_manager.data_singleton.current_device.version)
patched: bool = self.device_manager.get_current_device_patched()
# toggle option visibility for the minimum versions
for version in MinTweakVersions.keys():
if version == "exploit":
# disable if the exploit is not available
for pair in MinTweakVersions[version]:
if self.device_manager.data_singleton.current_device.has_exploit() and device_ver >= Version(pair[0]):
pair[1].show()
else:
pair[1].hide()
elif version == "no_patch":
# hide patched version items
for view in MinTweakVersions[version]:
if patched:
view.hide()
else:
view.show()
else:
# show views if the version is higher
parsed_ver = Version(version)
for view in MinTweakVersions[version]:
if device_ver >= parsed_ver:
view.show()
else:
view.hide()
# toggle option visibility for the max versions
for version in MaxTweakVersions.keys():
if version == "patch":
if patched:
view.hide()
else:
view.show()
else:
parsed_ver = Version(version)
for view in MaxTweakVersions[version]:
if device_ver <= parsed_ver:
view.show()
else:
view.hide()
if device_ver >= Version("18.0"):
# show the other dynamic island options
self.ui.dynamicIslandDrp.addItem("2622 (iPhone 16 Pro Dynamic Island)")
self.ui.dynamicIslandDrp.addItem("2868 (iPhone 16 Pro Max Dynamic Island)")
# eligibility page button
if not patched and device_ver >= Version("17.4") and (device_ver <= Version("17.7") or device_ver >= Version("18.1")):
self.ui.euEnablerPageBtn.show()
else:
self.ui.euEnablerPageBtn.hide()
# hide the ai content if not on
if device_ver >= Version("18.1") and not tweaks["AIGestalt"].enabled:
self.ui.aiEnablerContent.hide()
self.setup_spoofedModelDrp_models()
else:
self.device_manager.set_current_device(index=None)
# update the interface
self.updateInterfaceForNewDevice()
def loadSettings(self):
self.settings = QtCore.QSettings()
try:
# load the settings
apply_over_wifi = self.settings.value("apply_over_wifi", False, type=bool)
auto_reboot = self.settings.value("auto_reboot", True, type=bool)
risky_tweaks = self.settings.value("show_risky_tweaks", False, type=bool)
show_all_spoofable = self.settings.value("show_all_spoofable_models", False, type=bool)
skip_setup = self.settings.value("skip_setup", True, type=bool)
supervised = self.settings.value("supervised", False, type=bool)
organization_name = self.settings.value("organization_name", "", type=str)
self.ui.allowWifiApplyingChk.setChecked(apply_over_wifi)
self.ui.autoRebootChk.setChecked(auto_reboot)
self.ui.showRiskyChk.setChecked(risky_tweaks)
self.ui.showAllSpoofableChk.setChecked(show_all_spoofable)
self.ui.skipSetupChk.setChecked(skip_setup)
self.ui.supervisionChk.setChecked(supervised)
self.ui.supervisionOrganization.setText(organization_name)
# hide/show the warning label
if skip_setup:
self.ui.skipSetupOnLbl.show()
else:
self.ui.skipSetupOnLbl.hide()
self.device_manager.apply_over_wifi = apply_over_wifi
self.device_manager.auto_reboot = auto_reboot
self.device_manager.allow_risky_tweaks = risky_tweaks
self.device_manager.show_all_spoofable_models = show_all_spoofable
self.device_manager.skip_setup = skip_setup
self.device_manager.supervised = supervised
self.device_manager.organization_name = organization_name
except:
pass
## SIDE BAR FUNCTIONS
def on_homePageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.Home.value)
def on_gestaltPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.Gestalt.value)
def on_featureFlagsPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.FeatureFlags.value)
def on_euEnablerPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.EUEnabler.value)
def on_springboardOptionsPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.Springboard.value)
def on_internalOptionsPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.InternalOptions.value)
def on_daemonsPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.Daemons.value)
def on_posterboardPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.Posterboard.value)
def on_advancedPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.RiskyTweaks.value)
def on_applyPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.Apply.value)
def on_settingsPageBtn_clicked(self):
self.ui.pages.setCurrentIndex(Page.Settings.value)
def update_side_btn_color(self, btn: QtWidgets.QToolButton, toggled: bool):
if toggled:
btn.setStyleSheet("QToolButton {\ncolor: #00FF00;\n}")
else:
btn.setStyleSheet("")
## HOME PAGE
def updatePhoneInfo(self):
# name label
self.ui.phoneNameLbl.setText(self.device_manager.get_current_device_name())
# version label
ver = self.device_manager.get_current_device_version()
build = self.device_manager.get_current_device_build()
self.show_uuid = False
if ver != "":
self.show_version_text(version=ver, build=build)
else:
self.ui.phoneVersionLbl.setText("Please connect a device.")
def toggle_version_label(self):
if self.show_uuid:
self.show_uuid = False
ver = self.device_manager.get_current_device_version()
build = self.device_manager.get_current_device_build()
if ver != "":
self.show_version_text(version=ver, build=build)
else:
self.show_uuid = True
uuid = self.device_manager.get_current_device_uuid()
if uuid != "":
self.ui.phoneVersionLbl.setText(f"<a style=\"text-decoration:none; color: white\" href=\"#\">{uuid}</a>")
def show_version_text(self, version: str, build: str):
support_str: str = "<span style=\"color: #32d74b;\">Supported!</span></a>"
if Version(version) < Version("17.0"):
support_str = "<span style=\"color: #ff0000;\">Not Supported.</span></a>"
elif self.device_manager.get_current_device_patched():
# sparserestore fully patched
support_str = "<span style=\"color: #ffff00;\">Partially Supported.</span></a>"
self.ui.phoneVersionLbl.setText(f"<a style=\"text-decoration:none; color: white;\" href=\"#\">iOS {version} ({build}) {support_str}")
## HOME PAGE LINKS
def on_bigMilkBtn_clicked(self):
webbrowser.open_new_tab("https://cowabun.ga")
def on_leminGitHubBtn_clicked(self):
webbrowser.open_new_tab("https://github.com/leminlimez")
def on_leminTwitterBtn_clicked(self):
webbrowser.open_new_tab("https://twitter.com/LeminLimez")
def on_leminKoFiBtn_clicked(self):
webbrowser.open_new_tab("https://ko-fi.com/leminlimez")
def on_posterRestoreBtn_clicked(self):
webbrowser.open_new_tab("https://discord.gg/gWtzTVhMvh")
def on_snoolieBtn_clicked(self):
webbrowser.open_new_tab("https://github.com/0xilis/python-aar-stuff")
def on_disfordottieBtn_clicked(self):
webbrowser.open_new_tab("https://twitter.com/disfordottie")
def on_mikasaBtn_clicked(self):
webbrowser.open_new_tab("https://github.com/Mikasa-san/QuietDaemon")
def on_libiBtn_clicked(self):
webbrowser.open_new_tab("https://github.com/doronz88/pymobiledevice3")
def on_jjtechBtn_clicked(self):
webbrowser.open_new_tab("https://github.com/JJTech0130/TrollRestore")
def on_qtBtn_clicked(self):
webbrowser.open_new_tab("https://www.qt.io/product/development-tools")
def on_discordBtn_clicked(self):
webbrowser.open_new_tab("https://discord.gg/MN8JgqSAqT")
def on_githubBtn_clicked(self):
webbrowser.open_new_tab("https://github.com/leminlimez/Nugget")
def on_bigNuggetBtn_clicked(self):
webbrowser.open_new_tab("https://cowabun.ga")
## MOBILE GESTALT PAGE
def set_rdar_fix_label(self):
rdar_title = tweaks["RdarFix"].get_rdar_title()
if rdar_title == "hide":
self.ui.rdarFixChk.hide()
else:
self.ui.rdarFixChk.show()
self.ui.rdarFixChk.setText(f"{rdar_title} (modifies resolution)")
def on_dynamicIslandDrp_activated(self, index: int):
if index == 0:
tweaks["DynamicIsland"].set_enabled(False)
tweaks["RdarFix"].set_di_type(-1)
else:
# disable X gestures on devices other than iPhone SEs
# the lazy way, better option would be to remove it from the menu but I didn't want to rework all that
model = self.device_manager.get_current_device_model()
if index != 1 or (model == "iPhone12,8" or model == "iPhone14,6"):
tweaks["DynamicIsland"].set_selected_option(index - 1)
else:
tweaks["DynamicIsland"].set_enabled(False)
tweaks["RdarFix"].set_di_type(tweaks["DynamicIsland"].value[tweaks["DynamicIsland"].get_selected_option()])
self.set_rdar_fix_label()
def on_rdarFixChk_clicked(self, checked: bool):
tweaks["RdarFix"].set_enabled(checked)
def on_modelNameChk_clicked(self, checked: bool):
tweaks["ModelName"].set_enabled(checked)
def on_modelNameTxt_textEdited(self, text: str):
tweaks["ModelName"].set_value(text, toggle_enabled=False)
def on_bootChimeChk_clicked(self, checked: bool):
tweaks["BootChime"].set_enabled(checked)
def on_chargeLimitChk_clicked(self, checked: bool):
tweaks["ChargeLimit"].set_enabled(checked)
def on_tapToWakeChk_clicked(self, checked: bool):
tweaks["TapToWake"].set_enabled(checked)
def on_iphone16SettingsChk_clicked(self, checked: bool):
tweaks["CameraButton"].set_enabled(checked)
def on_parallaxChk_clicked(self, checked: bool):
tweaks["Parallax"].set_enabled(checked)
def on_stageManagerChk_clicked(self, checked: bool):
tweaks["StageManager"].set_enabled(checked)
def on_enableMedusaChk_clicked(self, checked: bool):
tweaks["Medusa"].set_enabled(checked)
def on_ipadAppsChk_clicked(self, checked: bool):
tweaks["iPadApps"].set_enabled(checked)
def on_shutterChk_clicked(self, checked: bool):
# TODO: allow the user to select the region
tweaks["Shutter"].set_enabled(checked)
def on_findMyFriendsChk_clicked(self, checked: bool):
tweaks["FindMyFriends"].set_enabled(checked)
def on_pencilChk_clicked(self, checked: bool):
tweaks["Pencil"].set_enabled(checked)
def on_actionButtonChk_clicked(self, checked: bool):
tweaks["ActionButton"].set_enabled(checked)
def on_internalInstallChk_clicked(self, checked: bool):
tweaks["InternalInstall"].set_enabled(checked)
def on_internalStorageChk_clicked(self, checked: bool):
tweaks["InternalStorage"].set_enabled(checked)
def on_collisionSOSChk_clicked(self, checked: bool):
tweaks["CollisionSOS"].set_enabled(checked)
def on_aodChk_clicked(self, checked: bool):
tweaks["AOD"].set_enabled(checked)
def on_aodVibrancyChk_clicked(self, checked: bool):
tweaks["AODVibrancy"].set_enabled(checked)
def update_custom_gestalt_value_type(self, id, idx, valueField: QtWidgets.QLineEdit):
new_str = CustomGestaltTweaks.set_tweak_value_type(id, idx)
# update the value
valueField.setText(new_str)
def delete_custom_gestalt_key(self, id: int, widget: QtWidgets.QWidget):
CustomGestaltTweaks.deactivate_tweak(id)
self.ui.customKeysLayout.removeWidget(widget)
widget.setParent(None)
def on_addGestaltKeyBtn_clicked(self):
# create a blank gestalt value with default value of 1
key_identifier = CustomGestaltTweaks.create_tweak()
widget = QtWidgets.QWidget()
widget.setFixedHeight(35)
widget.setStyleSheet("QWidget { background: none; border: 1px solid #3b3b3b; border-radius: 8px; }")
hlayout = QtWidgets.QHBoxLayout(widget)
hlayout.setContentsMargins(9, 2, 9, 2)
# create the key field
keyField = QtWidgets.QLineEdit(widget)
# keyField.setMaximumWidth(200)
keyField.setPlaceholderText("Key")
keyField.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeft)
keyField.setTextMargins(5, 0, 5, 0)
keyField.textEdited.connect(lambda txt, id=key_identifier: CustomGestaltTweaks.set_tweak_key(id, txt))
hlayout.addWidget(keyField)
# create the delete button
delBtn = QtWidgets.QToolButton(widget)
delBtn.setIcon(QtGui.QIcon(":/icon/trash.svg"))
delBtn.setStyleSheet("QToolButton { margin-right: 8px; background: none; border: none; }\nQToolButton:pressed { background: none; color: #FFFFFF; }")
delBtn.clicked.connect(lambda _, id=key_identifier, w=widget: self.delete_custom_gestalt_key(id, w))
hlayout.addWidget(delBtn)
# create the type dropdown
valueTypeDrp = QtWidgets.QComboBox(widget)
valueTypeDrp.setStyleSheet("QComboBox {\n background-color: #3b3b3b;\n border: none;\n color: #e8e8e8;\n font-size: 14px;\n padding-left: 8px;\n border-radius: 8px;\n}\n\nQComboBox::drop-down {\n image: url(:/icon/caret-down-fill.svg);\n icon-size: 16px;\n subcontrol-position: right center;\n margin-right: 8px;\n}\n\nQComboBox QAbstractItemView {\n background-color: #3b3b3b;\n outline: none;\n margin-top: 1px;\n}\n\nQComboBox QAbstractItemView::item {\n background-color: #3b3b3b;\n color: #e8e8e8;\n padding-left: 8px;\n}\n\nQComboBox QAbstractItemView::item:hover {\n background-color: #535353;\n color: #ffffff;\n}")
valueTypeDrp.setFixedWidth(120)
valueTypeDrp.addItems(ValueTypeStrings)
valueTypeDrp.setCurrentIndex(0)
# create the value edit field
valueField = QtWidgets.QLineEdit(widget)
valueField.setMaximumWidth(175)
valueField.setPlaceholderText("Value")
valueField.setText("1")
valueField.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight)
valueField.setTextMargins(5, 0, 5, 0)
valueField.textEdited.connect(lambda txt, id=key_identifier: CustomGestaltTweaks.set_tweak_value(id, txt))
valueTypeDrp.activated.connect(lambda idx, id=key_identifier, vf=valueField: self.update_custom_gestalt_value_type(id, idx, vf))
hlayout.addWidget(valueTypeDrp)
hlayout.addWidget(valueField)
# add it to the main widget
widget.setDisabled(False)
self.ui.customKeysLayout.addWidget(widget)
## FEATURE FLAGS PAGE
def on_clockAnimChk_toggled(self, checked: bool):
tweaks["ClockAnim"].set_enabled(checked)
def on_lockscreenChk_clicked(self, checked: bool):
tweaks["Lockscreen"].set_enabled(checked)
def on_photosChk_clicked(self, checked: bool):
tweaks["PhotoUI"].set_enabled(checked)
def on_aiChk_clicked(self, checked: bool):
tweaks["AI"].set_enabled(checked)
## ELIGIBILITY PAGE
def on_euEnablerEnabledChk_toggled(self, checked: bool):
tweaks["EUEnabler"].set_enabled(checked)
def on_methodChoiceDrp_activated(self, index: int):
tweaks["EUEnabler"].set_selected_option(index)
def on_regionCodeTxt_textEdited(self, text: str):
tweaks["EUEnabler"].set_region_code(text)
def on_enableAIChk_toggled(self, checked: bool):
# tweaks["AIEligibility"].set_enabled(checked)
tweaks["AIGestalt"].set_enabled(checked)
# change the visibility of stuff
if checked:
self.ui.aiEnablerContent.show()
else:
self.ui.aiEnablerContent.hide()
def on_eligFileChk_toggled(self, checked: bool):
tweaks["AIEligibility"].set_enabled(checked)
if checked:
self.ui.languageTxt.show()
self.ui.languageLbl.show()
else:
self.ui.languageTxt.hide()
self.ui.languageLbl.hide()
def on_languageTxt_textEdited(self, text: str):
tweaks["AIEligibility"].set_language_code(text)
def on_spoofedModelDrp_activated(self, index: int):
idx_to_apply = index
if not self.device_manager.show_all_spoofable_models and not self.device_manager.get_current_device_model().startswith("iPhone"):
# offset the index for ipads
idx_to_apply += 6
tweaks["SpoofModel"].set_selected_option(idx_to_apply, is_enabled=(index != 0))
tweaks["SpoofHardware"].set_selected_option(idx_to_apply, is_enabled=(index != 0 and self.ui.spoofHardwareChk.isChecked()))
tweaks["SpoofCPU"].set_selected_option(idx_to_apply, is_enabled=(index != 0 and self.ui.spoofCPUChk.isChecked()))
def on_spoofHardwareChk_toggled(self, checked: bool):
tweaks["SpoofHardware"].set_enabled(checked and tweaks["SpoofHardware"].selected_option != 0)
def on_spoofCPUChk_toggled(self, checked: bool):
tweaks["SpoofCPU"].set_enabled(checked and tweaks["SpoofCPU"].selected_option != 0)
## SPRINGBOARD OPTIONS PAGE
def on_footnoteTxt_textEdited(self, text: str):
tweaks["LockScreenFootnote"].set_value(text, toggle_enabled=True)
def on_disableLockRespringChk_clicked(self, checked: bool):
tweaks["SBDontLockAfterCrash"].set_enabled(checked)
def on_disableDimmingChk_clicked(self, checked: bool):
tweaks["SBDontDimOrLockOnAC"].set_enabled(checked)
def on_disableBatteryAlertsChk_clicked(self, checked: bool):
tweaks["SBHideLowPowerAlerts"].set_enabled(checked)
def on_disableCrumbChk_clicked(self, checked: bool):
tweaks["SBNeverBreadcrumb"].set_enabled(checked)
def on_enableSupervisionTextChk_clicked(self, checked: bool):
tweaks["SBShowSupervisionTextOnLockScreen"].set_enabled(checked)
def on_enableAirPlayChk_clicked(self, checked: bool):
tweaks["AirplaySupport"].set_enabled(checked)
## INTERNAL OPTIONS PAGE
def on_buildVersionChk_clicked(self, checked: bool):
tweaks["SBBuildNumber"].set_enabled(checked)
def on_RTLChk_clicked(self, checked: bool):
tweaks["RTL"].set_enabled(checked)
def on_metalHUDChk_clicked(self, checked: bool):
tweaks["MetalForceHudEnabled"].set_enabled(checked)
def on_iMessageChk_clicked(self, checked: bool):
tweaks["iMessageDiagnosticsEnabled"].set_enabled(checked)
def on_IDSChk_clicked(self, checked: bool):
tweaks["IDSDiagnosticsEnabled"].set_enabled(checked)
def on_VCChk_clicked(self, checked: bool):
tweaks["VCDiagnosticsEnabled"].set_enabled(checked)
def on_appStoreChk_clicked(self, checked: bool):
tweaks["AppStoreDebug"].set_enabled(checked)
def on_notesChk_clicked(self, checked: bool):
tweaks["NotesDebugMode"].set_enabled(checked)
def on_showTouchesChk_clicked(self, checked: bool):
tweaks["BKDigitizerVisualizeTouches"].set_enabled(checked)
def on_hideRespringChk_clicked(self, checked: bool):
tweaks["BKHideAppleLogoOnLaunch"].set_enabled(checked)
def on_enableWakeVibrateChk_clicked(self, checked: bool):
tweaks["EnableWakeGestureHaptic"].set_enabled(checked)
def on_pasteSoundChk_clicked(self, checked: bool):
tweaks["PlaySoundOnPaste"].set_enabled(checked)
def on_notifyPastesChk_clicked(self, checked: bool):
tweaks["AnnounceAllPastes"].set_enabled(checked)
## DAEMONS PAGE
def on_modifyDaemonsChk_clicked(self, checked: bool):
tweaks["Daemons"].set_enabled(checked)
self.ui.daemonsPageContent.setDisabled(not checked)
def on_thermalmonitordChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.thermalmonitord.value, value=checked)
if checked:
# set the modify toggle checked so it actually applies
self.on_modifyDaemonsChk_clicked(True)
def on_otadChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.OTA.value, value=checked)
def on_usageTrackingAgentChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.UsageTrackingAgent.value, value=checked)
def on_gameCenterChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.GameCenter.value, value=checked)
def on_screenTimeChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.ScreenTime.value, value=checked)
def on_clearScreenTimeAgentChk_clicked(self, checked: bool):
tweaks["ClearScreenTimeAgentPlist"].set_enabled(checked)
def on_crashReportsChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.CrashReports.value, value=checked)
def on_atwakeupChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.ATWAKEUP.value, value=checked)
def on_tipsChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.Tips.value, value=checked)
def on_vpndChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.VPN.value, value=checked)
def on_wapicChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.ChineseLAN.value, value=checked)
def on_healthdChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.HealthKit.value, value=checked)
def on_airprintChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.AirPrint.value, value=checked)
def on_assistiveTouchChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.AssistiveTouch.value, value=checked)
def on_icloudChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.iCloud.value, value=checked)
def on_hotspotChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.InternetTethering.value, value=checked)
def on_passbookChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.PassBook.value, value=checked)
def on_spotlightChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.Spotlight.value, value=checked)
def on_voiceControlChk_clicked(self, checked: bool):
tweaks["Daemons"].set_multiple_values(Daemon.VoiceControl.value, value=checked)
## PosterBoard Page
def delete_pb_file(self, file, widget):
if file in tweaks["PosterBoard"].tendies:
tweaks["PosterBoard"].tendies.remove(file)
widget.deleteLater()
def load_posterboard(self):
if len(tweaks["PosterBoard"].tendies) == 0:
return
if self.pb_mainLayout == None:
# Create scroll layout
self.pb_mainLayout = QtWidgets.QVBoxLayout()
self.pb_mainLayout.setContentsMargins(0, 0, 0, 0)
self.pb_mainLayout.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop)
# Create a QWidget to act as the container for the scroll area
scrollWidget = QtWidgets.QWidget()
# Set the main layout (containing all the widgets) on the scroll widget
scrollWidget.setLayout(self.pb_mainLayout)
# Create a QScrollArea to hold the content widget (scrollWidget)
scrollArea = QtWidgets.QScrollArea()
scrollArea.setWidgetResizable(True) # Allow the content widget to resize within the scroll area
scrollArea.setFrameStyle(QtWidgets.QScrollArea.NoFrame) # Remove the outline from the scroll area
# Set the scrollWidget as the content widget of the scroll area
scrollArea.setWidget(scrollWidget)
# Set the size policy of the scroll area to expand in both directions
scrollArea.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
# Set the scroll area as the central widget of the main window
scrollLayout = QtWidgets.QVBoxLayout()
scrollLayout.setContentsMargins(0, 0, 0, 0)
scrollLayout.addWidget(scrollArea)
self.ui.pbFilesList.setLayout(scrollLayout)
widgets = {}
# Iterate through the files
for tendie in tweaks["PosterBoard"].tendies:
if tendie.loaded:
continue
widget = QtWidgets.QWidget()
widgets[tendie] = widget
# create the icon/label
titleBtn = QtWidgets.QToolButton(widget)
titleBtn.setIcon(QtGui.QIcon(tendie.get_icon()))
titleBtn.setIconSize(QtCore.QSize(20, 20))
titleBtn.setText(f" {tendie.name}")
titleBtn.setStyleSheet("QToolButton {\n background-color: transparent;\n icon-size: 20px;\n}")
titleBtn.setToolButtonStyle(QtCore.Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
titleBtn.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
delBtn = QtWidgets.QToolButton(widget)
delBtn.setIcon(QtGui.QIcon(":/icon/trash.svg"))
delBtn.clicked.connect(lambda _, file=tendie: (widgets[file].deleteLater(), tweaks["PosterBoard"].tendies.remove(file)))
spacer = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
# main layout
layout = QtWidgets.QHBoxLayout(widget)
layout.setContentsMargins(0, 0, 0, 3)
layout.addWidget(titleBtn)
layout.addItem(spacer)
layout.addWidget(delBtn)
# Add the widget to the mainLayout
widget.setLayout(layout)
self.pb_mainLayout.addWidget(widget)
tendie.loaded = True
def on_modifyPosterboardsChk_clicked(self, checked: bool):
tweaks["PosterBoard"].set_enabled(checked)
self.ui.pbPages.setDisabled(not checked)
# PB Pages Selectors
def on_tendiesPageBtn_clicked(self):
self.ui.tendiesPageBtn.setChecked(True)
self.ui.videoPageBtn.setChecked(False)
self.ui.pbPages.setCurrentIndex(0)
def on_videoPageBtn_clicked(self):
self.ui.tendiesPageBtn.setChecked(False)
self.ui.videoPageBtn.setChecked(True)
self.ui.pbPages.setCurrentIndex(1)
# Tendies Page
def on_importTendiesBtn_clicked(self):
selected_files, _ = QtWidgets.QFileDialog.getOpenFileNames(self, "Select PosterBoard Files", "", "Zip Files (*.tendies)", options=QtWidgets.QFileDialog.ReadOnly)
tweaks["PosterBoard"].resetting = False
self.ui.pbActionLbl.hide()
if selected_files != None and len(selected_files) > 0:
# user selected files, add them
for file in selected_files:
if not tweaks["PosterBoard"].add_tendie(file):
# alert that there are too many
detailsBox = QtWidgets.QMessageBox()
detailsBox.setIcon(QtWidgets.QMessageBox.Critical)
detailsBox.setWindowTitle("Error!")
detailsBox.setText("You selected too many descriptors! The limit is 10.")
detailsBox.exec()
break
self.load_posterboard()
def on_deleteAllDescriptorsBtn_clicked(self):
if tweaks["PosterBoard"].resetting and tweaks["PosterBoard"].resetType == 0:
tweaks["PosterBoard"].resetting = False
self.ui.pbActionLbl.hide()
else:
tweaks["PosterBoard"].resetting = True
tweaks["PosterBoard"].resetType = 0
self.ui.pbActionLbl.setText("! Set to Clear Collections Wallpapers")
self.ui.pbActionLbl.show()
def on_resetPRBExtBtn_clicked(self):
if tweaks["PosterBoard"].resetting and tweaks["PosterBoard"].resetType == 1:
tweaks["PosterBoard"].resetting = False
self.ui.pbActionLbl.hide()
else:
tweaks["PosterBoard"].resetting = True
tweaks["PosterBoard"].resetType = 1
self.ui.pbActionLbl.setText("! Set to Reset PRB Extension")
self.ui.pbActionLbl.show()
# Video Page
def on_chooseThumbBtn_clicked(self):
selected_file, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select Image File", "", "Image Files (*.heic)", options=QtWidgets.QFileDialog.ReadOnly)
tweaks["PosterBoard"].resetting = False
if selected_file != None and selected_file != "":
tweaks["PosterBoard"].videoThumbnail = selected_file
self.ui.pbVideoThumbLbl.setText(f"Current Thumbnail: {selected_file}")
else:
tweaks["PosterBoard"].videoThumbnail = None
self.ui.pbVideoThumbLbl.setText("Current Thumbnail: None")
def on_chooseVideoBtn_clicked(self):
selected_file, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select Video File", "", "Video Files (*.mov *.mp4)", options=QtWidgets.QFileDialog.ReadOnly)
tweaks["PosterBoard"].resetting = False
if selected_file != None and selected_file != "":
tweaks["PosterBoard"].videoFile = selected_file
self.ui.pbVideoLbl.setText(f"Current Video: {selected_file}")
else:
tweaks["PosterBoard"].videoFile = None
self.ui.pbVideoLbl.setText("Current Video: None")
def on_clearSuggestedBtn_clicked(self):
if tweaks["PosterBoard"].resetting and tweaks["PosterBoard"].resetType == 2:
tweaks["PosterBoard"].resetting = False
self.ui.pbActionLbl.hide()
else:
tweaks["PosterBoard"].resetting = True
tweaks["PosterBoard"].resetType = 2
self.ui.pbActionLbl.setText("! Set to Clear Suggested Photos")
self.ui.pbActionLbl.show()
def on_caVideoChk_toggled(self, checked: bool):
tweaks["PosterBoard"].loop_video = checked
# hide thumbnail button and label
if checked:
self.ui.chooseThumbBtn.hide()
self.ui.pbVideoThumbLbl.hide()
self.ui.clearSuggestedBtn.hide()
self.ui.reverseLoopChk.show()
self.ui.useForegroundChk.show()
else:
self.ui.chooseThumbBtn.show()
self.ui.pbVideoThumbLbl.show()
self.ui.clearSuggestedBtn.show()
self.ui.reverseLoopChk.hide()
self.ui.useForegroundChk.hide()
def on_reverseLoopChk_toggled(self, checked: bool):
tweaks["PosterBoard"].reverse_video = checked
def on_useForegroundChk_toggled(self, checked: bool):
tweaks["PosterBoard"].use_foreground = checked
def on_findPBBtn_clicked(self):
webbrowser.open_new_tab("https://cowabun.ga/wallpapers")
def on_pbHelpBtn_clicked(self):
dialog = PBHelpDialog()
dialog.exec()
## Risky Options Page
def on_disableOTAChk_clicked(self, checked: bool):
tweaks["DisableOTAFile"].set_enabled(checked)
def on_enableResolutionChk_clicked(self, checked: bool):
tweaks["CustomResolution"].set_enabled(checked)
# toggle the ui content
if checked:
self.ui.resChangerContent.show()
else:
self.ui.resChangerContent.hide()
def on_resHeightTxt_textEdited(self, txt: str):
if txt == "":
# remove the canvas_height value
tweaks["CustomResolution"].value.pop("canvas_height", None)
self.ui.resHeightWarningLbl.hide()
return
try:
val = int(txt)
tweaks["CustomResolution"].value["canvas_height"] = val
self.ui.resHeightWarningLbl.hide()
except:
self.ui.resHeightWarningLbl.show()
def on_resWidthTxt_textEdited(self, txt: str):
if txt == "":
# remove the canvas_width value
tweaks["CustomResolution"].value.pop("canvas_width", None)
self.ui.resWidthWarningLbl.hide()
return
try:
val = int(txt)
tweaks["CustomResolution"].value["canvas_width"] = val
self.ui.resWidthWarningLbl.hide()
except:
self.ui.resWidthWarningLbl.show()
## SETTINGS PAGE
def on_allowWifiApplyingChk_toggled(self, checked: bool):
self.device_manager.apply_over_wifi = checked
# save the setting
self.settings.setValue("apply_over_wifi", checked)
def on_showRiskyChk_toggled(self, checked: bool):
self.device_manager.allow_risky_tweaks = checked
# save the setting
self.settings.setValue("show_risky_tweaks", checked)
# toggle the button visibility
if checked:
self.ui.advancedPageBtn.show()
self.ui.resetPRBExtBtn.show()
else:
self.ui.advancedPageBtn.hide()
self.ui.resetPRBExtBtn.hide()
def on_showAllSpoofableChk_toggled(self, checked: bool):
self.device_manager.show_all_spoofable_models = checked
# save the setting
self.settings.setValue("show_all_spoofable_models", checked)
# refresh the list of spoofable models
self.setup_spoofedModelDrp_models()
def on_autoRebootChk_toggled(self, checked: bool):
self.device_manager.auto_reboot = checked
# save the setting
self.settings.setValue("auto_reboot", checked)
def on_revertRdarChk_toggled(self, checked: bool):
tweaks["RdarFix"].set_enabled(checked)
def on_skipSetupChk_toggled(self, checked: bool):
self.device_manager.skip_setup = checked
# save the setting
self.settings.setValue("skip_setup", checked)
# hide/show the warning label
if checked:
self.ui.skipSetupOnLbl.show()
else:
self.ui.skipSetupOnLbl.hide()
def on_supervisionOrgTxt_textEdited(self, text: str):
self.device_manager.organization_name = text
self.settings.setValue("organization_name", text)
def on_supervisionChk_toggled(self, checked: bool):
self.device_manager.supervised = checked
# save the setting
self.settings.setValue("supervised", checked)
# Device Options
def on_resetPairBtn_clicked(self):
self.device_manager.reset_device_pairing()
## APPLY PAGE
def on_chooseGestaltBtn_clicked(self):
selected_file, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select Mobile Gestalt File", "", "Plist Files (*.plist)", options=QtWidgets.QFileDialog.ReadOnly)
if selected_file == "" or selected_file == None:
self.device_manager.data_singleton.gestalt_path = None
self.ui.gestaltLocationLbl.setText("None")
# show the warning labels
self.ui.mgaWarningLbl.show()
self.ui.mgaWarningLbl2.show()
else:
# verify that the gestalt is correct and compatible
with open(selected_file, 'rb') as in_fp:
gestalt_plist = plistlib.load(in_fp)
if not "CacheExtra" in gestalt_plist:
detailsBox = QtWidgets.QMessageBox()
detailsBox.setIcon(QtWidgets.QMessageBox.Critical)
detailsBox.setWindowTitle("Error!")
detailsBox.setText("The file is not a mobile gestalt file!")
detailsBox.exec()
return
if (
not "qNNddlUK+B/YlooNoymwgA" in gestalt_plist["CacheExtra"]
or not "0+nc/Udy4WNG8S+Q7a/s1A" in gestalt_plist["CacheExtra"]
or gestalt_plist["CacheExtra"]["qNNddlUK+B/YlooNoymwgA"] != self.device_manager.data_singleton.current_device.version
or gestalt_plist["CacheExtra"]["0+nc/Udy4WNG8S+Q7a/s1A"] != self.device_manager.data_singleton.current_device.model
):
dialog = GestaltDialog(
device_manager=self.device_manager,
gestalt_label=self.ui.gestaltLocationLbl,
selected_file=selected_file
)
dialog.exec()
else:
self.device_manager.data_singleton.gestalt_path = selected_file
self.ui.gestaltLocationLbl.setText(selected_file)
# hide the warning labels
self.ui.mgaWarningLbl.hide()
self.ui.mgaWarningLbl2.hide()
def update_label(self, txt: str):
self.ui.statusLbl.setText(txt)
def update_bar(self, percent):
self.ui.restoreProgressBar.setValue(int(percent))
def on_removeTweaksBtn_clicked(self):
self.apply_changes(resetting=True)
def on_resetGestaltBtn_clicked(self):
self.device_manager.reset_mobilegestalt(self.settings, update_label=self.update_label)
@QtCore.Slot()
def on_applyTweaksBtn_clicked(self):
self.apply_changes()
def apply_changes(self, resetting: bool = False):
if not self.applying_in_progress:
self.applying_in_progress = True
self.worker_thread = ApplyThread(manager=self.device_manager, resetting=resetting)
self.worker_thread.progress.connect(self.ui.statusLbl.setText)
self.worker_thread.alert.connect(self.alert_message)
self.worker_thread.finished.connect(self.finish_apply_thread)
self.worker_thread.finished.connect(self.worker_thread.deleteLater)
self.worker_thread.start()
def alert_message(self, alert: ApplyAlertMessage):
print(alert.txt)
detailsBox = QtWidgets.QMessageBox()
detailsBox.setIcon(alert.icon)
detailsBox.setWindowTitle(alert.title)
detailsBox.setText(alert.txt)
if alert.detailed_txt != None:
detailsBox.setDetailedText(alert.detailed_txt)
detailsBox.exec()
def finish_apply_thread(self):
self.applying_in_progress = False