aboutsummaryrefslogtreecommitdiff
path: root/libs/installer_fomod_plus/scanner/FomodPlusScanner.cpp
blob: 4770178323286111518f5efae4d2279c35a3dcc1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "FomodPlusScanner.h"

#include "archiveparser.h"
#include "FomodDBEntry.h"

#include <QDialog>
#include <QPushButton>
#include <QProgressBar>
#include <QVBoxLayout>
#include <QMessageBox>
#include <archive.h>

#include <QLabel>
#include <QMovie>
#include <iostream>

#include "stringutil.h"

using ScanCallbackFn = std::function<bool(IModInterface*, ScanResult result)>;

bool FomodPlusScanner::init(IOrganizer* organizer)
{
    mOrganizer = organizer;

    mDialog = new QDialog();
    mDialog->setWindowTitle(tr("FOMOD Scanner"));

    const auto layout = new QVBoxLayout(mDialog);

    const QString description = tr("Greetings, traveler.\n"
        "This tool will scan your load order for mods installed via FOMOD.\n"
        "It will also fix up any erroneous FOMOD flags from previous versions of FOMOD Plus :) \n\n"
        "Safe travels, and may your load order be free of conflicts.");

    const auto descriptionLabel = new QLabel(description, mDialog);
    descriptionLabel->setWordWrap(true); // Enable word wrap for large text
    descriptionLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    descriptionLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); // Align text to the top-left corner

    const auto gifLabel = new QLabel(mDialog);
    const auto movie    = new QMovie(":/fomod/wizard");
    gifLabel->setMovie(movie);
    movie->start();

    mProgressBar = new QProgressBar(mDialog);
    mProgressBar->setRange(0, mOrganizer->modList()->allMods().size());
    mProgressBar->setVisible(false);

    const auto scanButton   = new QPushButton(tr("Scan"), mDialog);
    const auto cancelButton = new QPushButton(tr("Cancel"), mDialog);

    layout->addWidget(descriptionLabel, 1);
    layout->addWidget(gifLabel, 1);
    layout->addWidget(mProgressBar, 1);
    layout->addWidget(scanButton, 1);
    layout->addWidget(cancelButton, 1);

    connect(cancelButton, &QPushButton::clicked, mDialog, &QDialog::reject);
    connect(scanButton, &QPushButton::clicked, this, &FomodPlusScanner::onScanClicked);
    connect(mDialog, &QDialog::finished, this, &FomodPlusScanner::cleanup);

    mDialog->setLayout(layout);
    mDialog->setMinimumSize(400, 300);
    mDialog->adjustSize();
    descriptionLabel->adjustSize();
    return true;
}

void FomodPlusScanner::onScanClicked() const
{
    mProgressBar->setVisible(true);
    const int added = scanLoadOrder(setFomodInfoForMod);
    mDialog->accept();
    QMessageBox::information(mDialog, tr("Scan Complete"),
        tr("The load order scan is complete. Updated filter info for ") + QString::number(added) + tr(" mods."));
    mOrganizer->refresh();
}

void FomodPlusScanner::cleanup() const
{
    mProgressBar->reset();
    mProgressBar->setVisible(false);
}

void FomodPlusScanner::display() const
{
    mDialog->exec();
}

int FomodPlusScanner::scanLoadOrder(const ScanCallbackFn& callback) const
{
    int progress = 0;
    int modified = 0;
    for (const auto& modName : mOrganizer->modList()->allMods()) {
        const auto mod          = mOrganizer->modList()->getMod(modName);
        if (const ScanResult result = openInstallationArchive(mod); callback(mod, result)) {
            modified++;
        }
        mProgressBar->setValue(++progress);
    }
    return modified;
}

ScanResult FomodPlusScanner::openInstallationArchive(const IModInterface* mod) const
{
    const auto downloadsDir         = mOrganizer->downloadsPath();
    const auto installationFilePath = mod->installationFile();
    return ArchiveParser::scanForFomodFiles(downloadsDir, installationFilePath, mod->name());
}

bool FomodPlusScanner::setFomodInfoForMod(IModInterface* mod, const ScanResult result)
{
    const auto pluginName = "FOMOD Plus";
    const auto setting    = mod->pluginSetting(pluginName, "fomod", 0);
    if (setting == 0 && ScanResult::HAS_FOMOD == result) {
        return mod->setPluginSetting(pluginName, "fomod", "{}");
    }
    if (setting != 0 && ScanResult::NO_FOMOD == result) {
        return mod->setPluginSetting(pluginName, "fomod", 0);
    }
    return false;
}

bool FomodPlusScanner::removeFomodInfoFromMod(IModInterface* mod, ScanResult)
{
    const auto pluginName = QString::fromStdString("FOMOD Plus");
    return mod->setPluginSetting(pluginName, "fomod", 0);
}