Ejemplo n.º 1
0
    def _init_mods(self):
        p_dialog = dialogs.SplashProgress(
            parent=None,
            title=_("Computing data"),
            message=_("Please wait for the software to initialize it's data."),
        )
        p_dialog.show()

        filehandler.build_game_files_crc32(p_dialog.progress)
        filehandler.build_loose_files_crc32(p_dialog.progress)
        self.managed_archives.build_archives_list(p_dialog.progress)

        p_dialog.progress("", category=_("Conflict detection"))
        filehandler.generate_conflicts_between_archives(
            self.managed_archives, progress=p_dialog.progress)
        self.managed_archives.initiate_conflicts_detection()

        item = None
        p_dialog.progress("", category=_("Parsing archives"))
        # HACK: pylint doesn't recognize aliased objects, which Typing's MutableMapping are.
        for archive_name in self.managed_archives.keys():  # pylint: disable=no-member
            p_dialog.progress(archive_name)
            item = ListRowItem(filename=archive_name,
                               archive_manager=self.managed_archives)
            self.listWidget.addItem(item)
        self.managed_archives.diff_matched_with_loosefiles()
        self.listWidget.addItem(ListRowVirtualItem(self.managed_archives))

        if item:
            self.listWidget.setCurrentItem(item)
            self.listWidget.scrollToItem(item)
        self.setup_schedulers()
        p_dialog.done(1)
Ejemplo n.º 2
0
    def on_window_activate(self):
        if not self._ar_handler or not self._mod_handler:  # handlers not init
            return False
        if (not self._wd_watchers[WatchDogSchedules.ARCHIVES]
                and self.autorefresh_checkbox.isChecked()):
            self._schedule_watchdog("archives")
        if self.is_mod_repo_dirty:
            logger.debug("Loose files are dirty, reparsing...")
            bucket.loosefiles = {}
            self.statusbar.showMessage(_("Refreshing loose files..."))
            filehandler.build_loose_files_crc32()
            if self.autorefresh_checkbox.isChecked():
                self._schedule_watchdog("modules")

        logger.debug("Refreshing managed archives...")
        msg = " "
        msg.join([
            self.statusbar.currentMessage(),
            _("Refreshing managed archive...")
        ])
        self.statusbar.showMessage(msg)

        etype = None
        for etype, archive_name in self.managed_archives.refresh():
            if etype == ArchiveEvents.FILE_ADDED:
                self.listWidget.addItem(
                    ListRowItem(filename=archive_name,
                                archive_manager=self.managed_archives))
            if etype == ArchiveEvents.FILE_REMOVED:
                idx = self.get_row_index_by_name(archive_name)
                self._remove_row(archive_name, idx, preserve_managed=True)

        if etype or self.is_mod_repo_dirty:
            filehandler.generate_conflicts_between_archives(
                self.managed_archives)
            self.managed_archives.initiate_conflicts_detection()
            self.refresh_list_item_state()
            self._is_mod_repo_dirty = False

        msg = " "
        msg.join([self.statusbar.currentMessage(), _("Refresh done.")])
        self.statusbar.showMessage(msg, 10000)
        return False
Ejemplo n.º 3
0
    def _remove_row(self,
                    filename: str,
                    row: int,
                    preserve_managed: bool = False):
        """Remove a row from the interface's list.

        The `filename` argument is only needed if `preserved_managed` is set to
        `False` (the default). It is needed to remove information stored in the
        `managed_archives` object.

        Will refresh the conflicting files once done.

        Args:
            filename: Only needed if preserve_managed is False
            row: integer matching the row to remove
            preserve_managed: if False, delete information from the managed_archives
                object
        """
        if not preserve_managed:
            del self.managed_archives[filename]
        self.listWidget.takeItem(row)
        filehandler.generate_conflicts_between_archives(self.managed_archives)
Ejemplo n.º 4
0
    def _do_uninstall_selected_mod(self, widgetslist=None):
        """Delete all the archive matched files from the filesystem.

        Will not process archives with known mismatch.
        """
        if not widgetslist:  # called from a non-contextual triggers
            widgetslist = self.listWidget.selectedItems()
            if not widgetslist:
                logger.error(
                    "_do_uninstall_selected_mod called without selection.")
                return
        if isinstance(widgetslist, ListRowItem):
            widgetslist = [widgetslist]

        pd = QProgressDialog("Uninstalling mods...", "", 0, 100, parent=self)
        pd.setAutoClose(True)
        pd.setWindowModality(Qt.WindowModal)
        pd.setValue(pd.minimum())
        step = int(100 / len(widgetslist))  # increase progress by `step`
        mismatched = []
        failure = False
        self._do_enable_autorefresh(False)
        for item in widgetslist:
            if item.archive_instance.has_mismatched:
                mismatched.append(item.filename)
                continue
            logger.info("Uninstalling files from archive %s", item.filename)
            uninstall_status = filehandler.uninstall_files(
                item.archive_instance.uninstall_info(), pd, step)
            if not uninstall_status:
                failure = True
        pd.reset()

        self._do_enable_autorefresh(True)
        if mismatched:
            dialogs.q_information(_(
                "Some module couldn't be uninstalled, some of their files are mismatched.\n"
                "This is most likely due to another installed mod conflicting "
                "or changes occurred on the drive outside of the control of this software."
            ),
                                  detailed="\n".join(mismatched))

        sp = dialogs.SplashProgress(
            parent=None,
            title=_("Computing data"),
            message=_("Please wait for the software to initialize it's data."),
        )
        sp.show()
        sp.category.setText(_("Conflict detection:"))
        filehandler.generate_conflicts_between_archives(self.managed_archives,
                                                        progress=sp.progress)
        self.refresh_list_item_state()
        self.on_selection_change()
        sp.done(1)

        if failure:
            dialogs.q_warning(
                _("The uninstallation process failed at some point. Please report "
                  "this happened to the developper alongside with the error file "
                  "{logfile}.").format(logfile=get_config_dir("error.log")))
            return False
        return True
Ejemplo n.º 5
0
    def _do_install_selected_mod(self, widgetslist=None):
        """Method to install an archive's files to the game location."""
        if not widgetslist:  # called from a non-contextual call
            widgetslist = self.listWidget.selectedItems()
            if not widgetslist:
                logger.error(
                    "_do_install_selected_mod called without selection.")
                return
        if isinstance(widgetslist, ListRowItem):
            widgetslist = [widgetslist]
        self._do_enable_autorefresh(False)
        names = [item.filename for item in widgetslist]
        skipped, conflictors = [], []
        changes = False

        p_dialog = dialogs.SplashProgress(
            parent=None,
            title=_("Installing modules"),
            message=_("Please wait for the software to initialize it's data."),
        )
        p_dialog.show()

        for item in widgetslist:
            p_dialog.progress("Processing {}".format(item.filename))
            if item.archive_instance.all_matching or item.archive_instance.empty:
                continue
            if item.archive_instance.has_matched:
                skipped.append(item.filename)
                continue
            if any(name in item.archive_instance.known_conflictors()
                   for name in names):
                conflictors.append(item.filename)
                continue
            logger.info("Installing file %s", item.filename)
            files = filehandler.install_archive(
                item.filename, item.archive_instance.install_info())
            if not files:
                dialogs.q_warning(
                    _("The archive {filename} extracted with errors.\n"
                      "Please refer to {loglocation} for more information.").
                    format(filename=item.filename,
                           loglocation=os.path.join(get_base_path(),
                                                    "error.log")))
            else:
                changes = True

        self._do_enable_autorefresh(True)

        if changes:
            p_dialog.category.setText(_("Recomputing conflicts:"))
            filehandler.generate_conflicts_between_archives(
                self.managed_archives, p_dialog.progress)
            self.refresh_list_item_state()
        else:
            dialogs.q_information(
                "You tried to install an archive, but the state of your game "
                "res/mods/ folder hasn't changed. This would indicate that your "
                "archive contains no recognized file able to be installed.")
            logger.warning(
                "Tried to install something, but no changes were made on the drive."
            )
        p_dialog.done(1)

        if skipped:
            dialogs.q_information(_(
                "Some archives couldn't be installed during the process. "
                "Some of the files in those archives are already present "
                "on the disk."),
                                  detailed="\n".join(skipped))

        if conflictors:
            dialogs.q_information(_(
                "Some archives have conflicting files with each others and "
                "couldn't be installed alongside each other. You should "
                "selectively install one or manually resolve the "
                "problematic files."),
                                  detailed="\n".join(conflictors))
        self.on_selection_change()