def uninstall(self): """Uninstalls selected mods.""" self.uninstall_button.setEnabled(False) selected = self.get_selected_rows() if selected: # sanity check result = QtWidgets.QMessageBox().information( self, "Confirmation", "This will permamentaly delete {} mod(s). Are you sure you want to continue?".format( len(selected) ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No, ) if result == QtWidgets.QMessageBox.No: self.uninstall_button.setEnabled(True) return progress = progress_widget(self, self.appctxt) progress.set_infinite() for _id in self.get_selected_rows(): # first, get the mod name and enabled status (mod_folder, enabled) = self.main_table.get_basic_info(_id) # setup uninstaller thread uninstaller = flight_sim.uninstall_mod_thread( self.sim_folder, mod_folder, enabled ) uninstaller.activity_update.connect(progress.set_activity) def failed(err): typ = type(err) message = err logger.exception("Failed to uninstall mod") QtWidgets.QMessageBox().warning( self, "Error", "Something went terribly wrong.\n{}: {}".format(typ, message), ) # start the thread with thread.thread_wait( uninstaller.finished, failed_signal=uninstaller.failed, failed_func=failed, update_signal=uninstaller.activity_update, ): uninstaller.start() # refresh the data self.refresh() self.uninstall_button.setEnabled(True)
def check_version(self): """Checks the application version and allows user to open browser to update.""" installed = version.is_installed() return_url = version.check_version(self.appctxt, installed) if return_url: result, remember = version_check_widget(self, installed).exec_() if result == QtWidgets.QMessageBox.Yes: if installed: # progress bar progress = progress_widget(self, self.appctxt) progress.set_percent() progress.set_activity( "Downloading latest version ({})".format(return_url) ) # setup downloader thread downloader = version.download_new_version_thread(return_url) downloader.activity_update.connect(progress.set_percentage) def failed(err): typ = type(err) message = err logger.exception("Failed to download new version") QtWidgets.QMessageBox().warning( self, "Error", "Something went terribly wrong.\n{}: {}".format( typ, message ), ) # start the thread with thread.thread_wait( downloader.finished, finish_func=version.install_new_version, failed_signal=downloader.failed, failed_func=failed, update_signal=downloader.activity_update, ): downloader.start() progress.close() else: webbrowser.open(return_url) elif remember: config.set_key_value(config.NEVER_VER_CHEK_KEY, True)
def disable(self): """Disables selected mods.""" self.disable_button.setEnabled(False) progress = progress_widget(self, self.appctxt) progress.set_infinite() for _id in self.get_selected_rows(): # first, get the mod name and disable status (mod_folder, enabled) = self.main_table.get_basic_info(_id) if not enabled: continue # setup disabler thread disabler = flight_sim.disable_mod_thread(self.sim_folder, mod_folder) disabler.activity_update.connect(progress.set_activity) def failed(err): typ = type(err) message = err logger.exception("Failed to disable mod") QtWidgets.QMessageBox().warning( self, "Error", "Something went terribly wrong.\n{}: {}".format( typ, message), ) # start the thread with thread.thread_wait( disabler.finished, failed_signal=disabler.failed, failed_func=failed, update_signal=disabler.activity_update, ): disabler.start() # refresh the data self.refresh() progress.close() self.disable_button.setEnabled(True)
def base_action( self, core_func, button=None, sanity_dialog=None, empty_check=False, empty_val=None, refresh=True, ): """Base function for GUI actions.""" if empty_check and not empty_val: return if button: button.setEnabled(False) # sanity check if sanity_dialog: question = sanity_dialog() if not question: # cancel button.setEnabled(True) return # build progress widget progress = progress_widget(self, self.appctxt) progress.set_mode(progress.INFINITE) # execute the core function core_func(progress) progress.close() # refresh the data if refresh: self.refresh(automated=True) # cleanup if button: button.setEnabled(True)
def create_backup(self): """Creates a backup of all enabled mods.""" archive = QtWidgets.QFileDialog.getSaveFileName( parent=self, caption="Save Backup As", dir=os.path.join( config.BASE_FOLDER, "msfs-mod-backup-{}.zip".format( datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") ), ), filter=ARCHIVE_FILTER, )[0] # no selection will be blank if not archive: return progress = progress_widget(self, self.appctxt) progress.set_infinite() # setup backuper thread backuper = flight_sim.create_backup_thread(self.sim_folder, archive) backuper.activity_update.connect(progress.set_activity) def failed(err): typ = type(err) message = err if flight_sim.ExtractionError == typ: QtWidgets.QMessageBox().warning( self, "Error", "Unable to create archive {}. You need to install a program which can create this, such as 7zip or WinRar.".format( archive ), ) else: logger.exception("Failed to create backup") QtWidgets.QMessageBox().warning( self, "Error", "Something went terribly wrong.\n{}: {}".format(typ, message), ) # start the thread, with extra 20 min timeout with thread.thread_wait( backuper.finished, timeout=1200000, failed_signal=backuper.failed, failed_func=failed, update_signal=backuper.activity_update, ): backuper.start() result = QtWidgets.QMessageBox().information( self, "Success", "Backup successfully saved to {}. Would you like to open this directory?".format( archive ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.Yes, ) # open resulting directory if result == QtWidgets.QMessageBox.Yes: # this will always be opening a folder and therefore is safe os.startfile(os.path.dirname(archive)) # nosec
def install_folder(self): """Installs selected mod folders.""" # self.install_button.setEnabled(False) # first, let user select multiple folders mod_folder = QtWidgets.QFileDialog.getExistingDirectory( parent=self, caption="Select mod folder", dir=os.path.join(os.path.expanduser("~"), "Downloads"), ) # cancel if result was empty if not mod_folder: return progress = progress_widget(self, self.appctxt) progress.set_infinite() succeeded = [] def finish(result): # this function is required as the results will be a list, # which is not a hashable type succeeded.extend(result) def failed(err): typ = type(err) message = err if flight_sim.NoManifestError == typ: QtWidgets.QMessageBox().warning( self, "Error", "Unable to install mod {}. This is likely due to it missing a manifest.json file.".format( mod_folder ), ) elif files.AccessError == typ: QtWidgets.QMessageBox().warning( self, "Error", "Unable to install mod {} due to a permissions issue (unable to delete file/folder {}). Relaunch the program as an administrator.".format( mod_folder, message ), ) elif flight_sim.NoModsError == typ: QtWidgets.QMessageBox().warning( self, "Error", "Unable to find any mods inside {}".format(mod_folder), ) else: logger.exception("Failed to install mod folder") QtWidgets.QMessageBox().warning( self, "Error", "Something went terribly wrong.\n{}: {}".format(typ, message), ) # setup installer thread installer = flight_sim.install_mods_thread(self.sim_folder, mod_folder) installer.activity_update.connect(progress.set_activity) # start the thread with thread.thread_wait( installer.finished, finish_func=finish, failed_signal=installer.failed, failed_func=failed, update_signal=installer.activity_update, ): installer.start() progress.close() if succeeded: QtWidgets.QMessageBox().information( self, "Success", "{} mod(s) installed!\n{}".format( len(succeeded), "\n".join(["- {}".format(mod) for mod in succeeded]) ), ) # refresh the data self.refresh()