Exemple #1
0
            def on_name_changed(old, new):
                try:
                    self.Manager.rename_profile(new, old)

                except exceptions.ProfileError as pe:
                    message('critical', "Error During Rename Operation",
                            text=str(pe), buttons='ok')
    def on_path_edit(self, key):
        """
        Called when the user manually edits a path box
        """
        new_value = self.path_boxes[key].text()
        label = self.indicator_labels[key]

        # if they cleared the box, mark it missing
        if not new_value:
            self._mark_missing_path(label)

        elif not os.path.isabs(new_value):
            # then they didn't enter an absolute path
            self._mark_nonabs_path(label)

        # if they entered a valid path
        elif os.path.exists(new_value):
            # hide the label cause we're all good
            label.setVisible(False)

        else: # but if it was invalid...
            # show a messagebox asking if they would like to create it
            if message(title='Path not found',
                       text="Would you like to create this directory?",
                       info_text=new_value):
                create_dir(new_value)

                # and just to make sure...
                if os.path.exists(new_value):
                    label.setVisible(False)
                else:
                    self._mark_invalid_path(label)
            # if they say no, mark it invalid
            else:
                self._mark_invalid_path(label)
Exemple #3
0
    def on_remove_profile_action(self):
        """
        Show a warning about irreversibly deleting the profile, then, if
        the user accept the warning, proceed to delete the profile from
        disk and remove its entry from the profile selector.
        """
        profile = self.Manager.profile

        # TODO: while it can probably be safely assumed that currentData() and currentIndex() will refer to the same profile as Manager.profile, it is NOT guaranteed; we should either verify that they are indeed the same or search the model for the profile name (as pulled from the manager) to avoid the issue altogether
        if message('warning', 'Confirm Delete Profile',
                   'Delete "' + profile.name + '"?',
                   'Choosing "Yes" below will remove this profile '
                   'and all saved information within it, including '
                   'customized load-orders, ini-edits, etc. Note '
                   'that installed mods will not be affected. This '
                   'cannot be undone. Do you wish to continue?'):
            self.Manager.delete_profile(
                self._selector.currentData())
            self._selector.removeItem(
                self._selector.currentIndex())
Exemple #4
0
    def _move_and_update_path(self, key, newpath, remove_old):
        """Move the contents of the given AppFolder to a new
        location on disk. If successful, also update the local
        paths property"""
        try:
            MManager.Folders[key].move(newpath, remove_old, False)

        except exceptions.FileDeletionError as e:
            # old dir could not be removed, but all data was copied;
            # path value still updated in this case
            self.LOGGER.exception(e)
            message('warning',
                    "Could not remove original folder.",
                    "The following error occurred:",
                    detailed_text=str(e),
                    buttons='ok',
                    default_button='ok')
            self.paths[key] = MManager.Folders[key].get_path()

        except exceptions.FileAccessError as e:
            # some error with destination path
            self.LOGGER.exception(e)
            message('critical',
                    "Cannot perform move operation.",
                    "The following error occurred:",
                    detailed_text=str(e),
                    buttons='ok',
                    default_button='ok')

        except exceptions.MultiFileError as mfe:
            # destination was ok, but could not copy some/all contents
            # for some reason
            s = ""
            for file, exc in mfe.errors:
                self.LOGGER.exception(exc)
                s += f"{file}: {exc}\n"
            message(
                'critical',
                title="Errors during move operation",
                text=
                "The move operation may not have fully completed. The following errors were encountered: ",
                buttons='ok',
                default_button='ok',
                detailed_text=s)

        else:
            # no errors!
            self.paths[key] = MManager.Folders[key].get_path()
Exemple #5
0
    async def do_install(self, archive, ready_callback=lambda:None):
        """
        Determine the type of install (auto, manual, fomod), get the necessary
         info from the ModManager/InstallManager, and launch the necessary
         interface.

        :param archive: path to the mod archive to install
        :param ready_callback: called when an installer dialog is about to be shown.
        """
        with TemporaryDirectory() as tmpdir:
            self.LOGGER << "Created temporary directory at %s" % tmpdir

            installer = await Manager.get_installer(archive, tmpdir)

            ready_callback()

            # Fomod config was found and prepared
            if installer.has_fomod:
                await self.run_fomod_installer(installer, tmpdir)

            else:
                self.LOGGER << "No FOMOD config found."

                # count the files, and get the mod structure
                # count = await installer.get_file_count()
                # tree = await installer.mod_structure_tree()


                # retrieve a view of the archive's contents as a pseudo-filesystem
                modfs = await installer.mkarchivefs()

                # print("count:", count)
                # print(tree)

                # dataroot (folder which contains the actual game data) may
                # be different the current root of the filesystem
                # count, gamedata, dataroot = self.fsck_modfs(modfs)

                # if dataroot != modfs.root:




                # toplevcount, toplevdata = installer.analyze_structure_tree(tree)

                # print(toplevcount, toplevdata)

                # if count:

                ## check the root of the file hierarchy for usable data
                if modfs.fsck_quick():
                    ## if it's there, install the mod automatically

                    # await self.extraction_progress_dialog()
                    message("information", title="Game Data Found",
                            text="Here's where I'd automatically "
                                 "install the mod for you if I were "
                                 "working correctly. But I won't, "
                                 "because I'm not.")


                    # await installer.extract("/tmp/testinstall",
                    #                         entries=toplevdata["folders"]
                    #                                 +toplevdata["files"],
                    #                         callback=
                    #              )
                else:
                    ## perform one last check if the previous search turned up nothing:
                    # if there is only one item on the top level
                    # of the mod and that item is a directory, then check inside that
                    # directory for the necessary files.

                    _list = modfs.listdir("/") # list of items in the root

                       ## only 1 item...   ## which is a directory... ## that contains game data
                    if len(_list) == 1 and modfs.is_dir(_list[0]) and modfs.fsck_quick(_list[0]):
                        message("information", title="Game Data Found",
                                text="In immediate subdirectory '{}'. Automatic install of this data would be performed now.".format(_list[0]))

                    else:
                        self.logger.debug("no toplevel items found; showing manual install dialog")
                        await self._show_manual_install_dialog(modfs)
    def apply_changes(self):
        """
        Save the user changes to the appropriate config files.
        """
        # TODO: disable the OK/Apply buttons when there are no changes to apply.
        # TODO: allow resetting the paths to default

        for pref, cbox in self.checkboxes.items():
            app_settings.Set(pref, cbox.isChecked())

        # check for a change in the profile-load-policy
        if self._active_plp != self._selected_plp:
            app_settings.Set(
                UI.PROFILE_LOAD_POLICY,
                self._selected_plp)

        # check if any of the paths have changed and update accordingly
        for key, path in self.paths.items():
            newpath = self.path_boxes[key].text()

            # skip if unchanged
            if path == newpath: continue

            # allow changing if the path is valid or cleared
            if not newpath:
                # if they unset the path, just change it
                self._update_path(key, newpath)

            # if they set a valid new path, ask if they want to copy
            # their existing data (assuming there is any)
            # TODO: remember choice. Also for everything else in app
            elif os.path.isabs(newpath) and os.path.exists(newpath):
                if not path:
                    # if the path is currently unset, nothing to move
                    self._update_path(key, newpath)
                else:
                    do_move, remove_old = checkbox_message(
                        title="Transfer {} Data?".format(
                            constants.DisplayNames[key]),
                        text="Would you like to move your existing "
                             "data to the new location?",
                        checkbox_text="Also remove original directory",
                        checkbox_checked=True)
                    if do_move:
                        try:
                            Config.move_dir(key, newpath, remove_old)
                        except exceptions.FileAccessError as e:
                            message('critical',
                                    "Cannot perform move operation.",
                                    "The following error occurred:",
                                    str(e), buttons='ok',
                                    default_button='ok')
                        except exceptions.MultiFileError as mfe:
                            s=""
                            for file, exc in mfe.errors:
                                s+="{0}: {1}\n".format(file, exc)
                            message('critical',
                                    title="Errors during move operation",
                                    text="The move operation may not have fully completed. The following errors were encountered: ",
                                    info_text=s,
                                    buttons='ok', default_button='ok')
                        else:
                            self._update_path(key, newpath)
                    else:
                        self._update_path(key, newpath)

        # and now let's do it again for the overrides
        sp = self._selected_profile
        for d, box in self.override_boxes.items():
            newovrd = box.text()

            if newovrd == sp.diroverride(d):
                continue

            if not newovrd or (os.path.isabs(newovrd)
                               and os.path.exists(newovrd)):
                sp.setoverride(d, newovrd)