1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Launcher now supports submods. See forum thread for details.

This commit is contained in:
Ivan Savenko 2014-03-20 17:06:25 +00:00
parent fe1b16a7ec
commit 333a51a48a
10 changed files with 272 additions and 132 deletions

View File

@ -106,6 +106,18 @@ QString CModEntry::getName() const
QVariant CModEntry::getValue(QString value) const
{
if (repository.contains(value) && localData.contains(value))
{
// value is present in both repo and locally installed. Select one from latest version
QString installedVer = localData["installedVersion"].toString();
QString availableVer = repository["latestVersion"].toString();
if (compareVersions(installedVer, availableVer))
return repository[value];
else
return localData[value];
}
if (repository.contains(value))
return repository[value];
@ -149,15 +161,36 @@ void CModList::setModSettings(QVariant data)
modSettings = data.toMap();
}
void CModList::modChanged(QString modID)
{
}
static QVariant getValue(QVariantMap input, QString path)
{
if (path.size() > 1)
{
QString entryName = path.section('/', 0, 1);
QString remainder = "/" + path.section('/', 2, -1);
entryName.remove(0, 1);
return getValue(input.value(entryName).toMap(), remainder);
}
else
{
return input;
}
}
CModEntry CModList::getMod(QString modname) const
{
assert(hasMod(modname));
QVariantMap repo;
QVariantMap local = localModList[modname].toMap();
QVariantMap settings;
QVariant conf = modSettings[modname];
QString path = modname;
path = "/" + path.replace(".", "/mods/");
QVariant conf = getValue(modSettings, path);
if (conf.isNull())
{
settings["active"] = true; // default
@ -165,22 +198,22 @@ CModEntry CModList::getMod(QString modname) const
else
{
if (conf.canConvert<QVariantMap>())
settings = modSettings[modname].toMap();
settings = conf.toMap();
else
settings.insert("active", conf);
}
for (auto entry : repositories)
{
if (entry.contains(modname))
QVariant repoVal = getValue(entry, path);
if (repoVal.isValid())
{
if (repo.empty())
repo = entry[modname].toMap();
repo = repoVal.toMap();
else
{
if (CModEntry::compareVersions(repo["version"].toString(),
entry[modname].toMap()["version"].toString()))
repo = entry[modname].toMap();
if (CModEntry::compareVersions(repo["version"].toString(), repoVal.toMap()["version"].toString()))
repo = repoVal.toMap();
}
}
}

View File

@ -65,6 +65,7 @@ public:
virtual void addRepository(QVariantMap data);
virtual void setLocalModList(QVariantMap data);
virtual void setModSettings(QVariant data);
virtual void modChanged(QString modID);
// returns mod by name. Note: mod MUST exist
CModEntry getMod(QString modname) const;

View File

@ -7,10 +7,10 @@ namespace ModFields
{
static const QString names [ModFields::COUNT] =
{
"name",
"",
"",
"modType",
"name",
"version",
"size",
"author"
@ -18,10 +18,10 @@ namespace ModFields
static const QString header [ModFields::COUNT] =
{
"Name",
"", // status icon
"", // status icon
"Type",
"Name",
"Version",
"Size",
"Author"
@ -38,13 +38,17 @@ namespace ModStatus
}
CModListModel::CModListModel(QObject *parent) :
QAbstractTableModel(parent)
QAbstractItemModel(parent)
{
}
QString CModListModel::modIndexToName(int index) const
QString CModListModel::modIndexToName(const QModelIndex & index) const
{
return indexToName[index];
if (index.isValid())
{
return modNameToID.at(index.internalId());
}
return "";
}
QVariant CModListModel::getValue(const CModEntry &mod, int field) const
@ -95,30 +99,34 @@ QVariant CModListModel::getTextAlign(int field) const
{
if (field == ModFields::SIZE)
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
else
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
//if (field == ModFields::NAME)
// return QVariant(Qt::AlignHCenter | Qt::AlignVCenter);
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
}
QVariant CModListModel::data(const QModelIndex &index, int role) const
{
if (index.isValid())
{
auto mod = getMod(modIndexToName(index.row()));
auto mod = getMod(modIndexToName(index));
switch (role)
{
case Qt::DecorationRole: return getIcon(mod, index.column());
case Qt::DisplayRole: return getText(mod, index.column());
case Qt::UserRole: return getValue(mod, index.column());
case Qt::TextAlignmentRole: return getTextAlign(index.column());
case ModRoles::ValueRole: return getValue(mod, index.column());
case ModRoles::ModNameRole: return mod.getName();
}
}
return QVariant();
}
int CModListModel::rowCount(const QModelIndex &) const
int CModListModel::rowCount(const QModelIndex & index) const
{
return indexToName.size();
if (index.isValid())
return modIndex[modIndexToName(index)].size();
return modIndex[""].size();
}
int CModListModel::columnCount(const QModelIndex &) const
@ -152,26 +160,60 @@ void CModListModel::addRepository(QVariantMap data)
endResetModel();
}
void CModListModel::setLocalModList(QVariantMap data)
void CModListModel::modChanged(QString modID)
{
beginResetModel();
CModList::setLocalModList(data);
endResetModel();
}
void CModListModel::setModSettings(QVariant data)
{
beginResetModel();
CModList::setModSettings(data);
endResetModel();
int index = modNameToID.indexOf(modID);
QModelIndex parent = this->parent(createIndex(0, 0, index));
int row = modIndex[modIndexToName(parent)].indexOf(modID);
emit dataChanged(createIndex(row, 0, index), createIndex(row, 4, index));
}
void CModListModel::endResetModel()
{
indexToName = getModList();
modNameToID = getModList();
modIndex.clear();
for (const QString & str : modNameToID)
{
if (str.contains('.'))
{
modIndex[str.section('.', 0, -2)].append(str);
}
else
{
modIndex[""].append(str);
}
}
QAbstractItemModel::endResetModel();
}
QModelIndex CModListModel::index(int row, int column, const QModelIndex &parent) const
{
if (parent.isValid())
{
if (modIndex[modIndexToName(parent)].size() > row)
return createIndex(row, column, modNameToID.indexOf(modIndex[modIndexToName(parent)][row]));
}
else
{
if (modIndex[""].size() > row)
return createIndex(row, column, modNameToID.indexOf(modIndex[""][row]));
}
return QModelIndex();
}
QModelIndex CModListModel::parent(const QModelIndex &child) const
{
QString modID = modNameToID[child.internalId()];
for (auto entry = modIndex.begin(); entry != modIndex.end(); entry++) // because using range-for entry type is QMap::value_type oO
{
if (entry.key() != "" && entry.value().indexOf(modID) != -1)
{
return createIndex(entry.value().indexOf(modID), child.column(), modNameToID.indexOf(entry.key()));
}
}
return QModelIndex();
}
void CModFilterModel::setTypeFilter(int filteredType, int filterMask)
{
this->filterMask = filterMask;
@ -179,17 +221,35 @@ void CModFilterModel::setTypeFilter(int filteredType, int filterMask)
invalidateFilter();
}
bool CModFilterModel::filterMatches(int modIndex) const
bool CModFilterModel::filterMatchesThis(const QModelIndex &source) const
{
CModEntry mod = base->getMod(base->modIndexToName(modIndex));
return (mod.getModStatus() & filterMask) == filteredType;
CModEntry mod = base->getMod(source.data(ModRoles::ModNameRole).toString());
return (mod.getModStatus() & filterMask) == filteredType &&
QSortFilterProxyModel::filterAcceptsRow(source.row(), source.parent());
}
bool CModFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (filterMatches(source_row))
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
QModelIndex index = base->index(source_row, 0, source_parent);
if (filterMatchesThis(index))
{
return true;
}
for (size_t i=0; i<base->rowCount(index); i++)
{
if (filterMatchesThis(index.child(i, 0)))
return true;
}
QModelIndex parent = source_parent;
while (parent.isValid())
{
if (filterMatchesThis(parent))
return true;
parent = parent.parent();
}
return false;
}
@ -200,5 +260,5 @@ CModFilterModel::CModFilterModel(CModListModel * model, QObject * parent):
filterMask(ModStatus::MASK_NONE)
{
setSourceModel(model);
setSortRole(Qt::UserRole);
setSortRole(ModRoles::ValueRole);
}

View File

@ -9,10 +9,10 @@ namespace ModFields
{
enum EModFields
{
NAME,
STATUS_ENABLED,
STATUS_UPDATE,
TYPE,
NAME,
VERSION,
SIZE,
AUTHOR,
@ -20,36 +20,50 @@ namespace ModFields
};
}
class CModListModel : public QAbstractTableModel, public CModList
namespace ModRoles
{
enum EModRoles
{
ValueRole = Qt::UserRole,
ModNameRole
};
}
class CModListModel : public QAbstractItemModel, public CModList
{
Q_OBJECT
QVector<QString> indexToName;
QVector<QString> modNameToID;
// contains mapping mod -> numbered list of submods
// mods that have no parent located under "" key (empty string)
QMap<QString, QVector<QString>> modIndex;
void endResetModel();
QString modIndexToName(const QModelIndex & index) const;
QVariant getTextAlign(int field) const;
QVariant getValue(const CModEntry & mod, int field) const;
QVariant getText(const CModEntry & mod, int field) const;
QVariant getIcon(const CModEntry & mod, int field) const;
public:
/// CModListContainer overrides
void resetRepositories();
void addRepository(QVariantMap data);
void setLocalModList(QVariantMap data);
void setModSettings(QVariant data);
QString modIndexToName(int index) const;
explicit CModListModel(QObject *parent = 0);
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
/// CModListContainer overrides
void resetRepositories() override;
void addRepository(QVariantMap data) override;
void modChanged(QString modID);
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
signals:
public slots:
@ -62,7 +76,7 @@ class CModFilterModel : public QSortFilterProxyModel
int filteredType;
int filterMask;
bool filterMatches(int modIndex) const;
bool filterMatchesThis(const QModelIndex & source) const;
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
public:

View File

@ -24,6 +24,7 @@ void CModListView::setupFilterModel()
filterModel->setFilterKeyColumn(-1); // filter across all columns
filterModel->setSortCaseSensitivity(Qt::CaseInsensitive); // to make it more user-friendly
filterModel->setDynamicSortFilter(true);
}
void CModListView::setupModsView()
@ -31,20 +32,26 @@ void CModListView::setupModsView()
ui->allModsView->setModel(filterModel);
// input data is not sorted - sort it before display
ui->allModsView->sortByColumn(ModFields::TYPE, Qt::AscendingOrder);
ui->allModsView->setColumnWidth(ModFields::NAME, 185);
ui->allModsView->setColumnWidth(ModFields::STATUS_ENABLED, 30);
ui->allModsView->setColumnWidth(ModFields::STATUS_UPDATE, 30);
ui->allModsView->setColumnWidth(ModFields::TYPE, 80);
ui->allModsView->setColumnWidth(ModFields::NAME, 180);
ui->allModsView->setColumnWidth(ModFields::TYPE, 75);
ui->allModsView->setColumnWidth(ModFields::SIZE, 80);
ui->allModsView->setColumnWidth(ModFields::VERSION, 60);
ui->allModsView->header()->setSectionResizeMode(ModFields::STATUS_ENABLED, QHeaderView::Fixed);
ui->allModsView->header()->setSectionResizeMode(ModFields::STATUS_UPDATE, QHeaderView::Fixed);
ui->allModsView->setUniformRowHeights(true);
connect( ui->allModsView->selectionModel(), SIGNAL( currentRowChanged( const QModelIndex &, const QModelIndex & )),
this, SLOT( modSelected( const QModelIndex &, const QModelIndex & )));
connect( filterModel, SIGNAL( modelReset()),
this, SLOT( modelReset()));
selectMod(filterModel->rowCount() > 0 ? 0 : -1);
connect( modModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(dataChanged(QModelIndex,QModelIndex)));
}
CModListView::CModListView(QWidget *parent) :
@ -61,7 +68,8 @@ CModListView::CModListView(QWidget *parent) :
ui->progressWidget->setVisible(false);
dlManager = nullptr;
loadRepositories();
//loadRepositories();
hideModInfo();
}
void CModListView::loadRepositories()
@ -133,39 +141,45 @@ QString CModListView::genModInfoText(CModEntry &mod)
QString lineTemplate = prefix + "%2</p>";
QString urlTemplate = prefix + "<a href=\"%2\"><span style=\" text-decoration: underline; color:#0000ff;\">%2</span></a></p>";
QString textTemplate = prefix + "</p><p align=\"justify\">%2</p>";
QString noteTemplate = "<p align=\"justify\">%1: %2</p>";
QString listTemplate = "<p align=\"justify\">%1: %2</p>";
QString noteTemplate = "<p align=\"justify\">%1</p>";
QString result;
result += "<html><body>";
result += replaceIfNotEmpty(mod.getValue("name"), lineTemplate.arg("Mod name"));
result += replaceIfNotEmpty(mod.getValue("installedVersion"), lineTemplate.arg("Installed version"));
result += replaceIfNotEmpty(mod.getValue("latestVersion"), lineTemplate.arg("Latest version"));
result += replaceIfNotEmpty(CModEntry::sizeToString(mod.getValue("size").toDouble()), lineTemplate.arg("Download size"));
result += replaceIfNotEmpty(mod.getValue("author"), lineTemplate.arg("Authors"));
result += replaceIfNotEmpty(mod.getValue("contact"), urlTemplate.arg("Home"));
result += replaceIfNotEmpty(mod.getValue("depends"), lineTemplate.arg("Required mods"));
result += replaceIfNotEmpty(mod.getValue("conflicts"), lineTemplate.arg("Conflicting mods"));
result += replaceIfNotEmpty(mod.getValue("description"), textTemplate.arg("Description"));
result += replaceIfNotEmpty(mod.getValue("name"), lineTemplate.arg(tr("Mod name")));
result += replaceIfNotEmpty(mod.getValue("installedVersion"), lineTemplate.arg(tr("Installed version")));
result += replaceIfNotEmpty(mod.getValue("latestVersion"), lineTemplate.arg(tr("Latest version")));
if (mod.getValue("size").toDouble() != 0)
result += replaceIfNotEmpty(CModEntry::sizeToString(mod.getValue("size").toDouble()), lineTemplate.arg(tr("Download size")));
result += replaceIfNotEmpty(mod.getValue("author"), lineTemplate.arg(tr("Authors")));
result += replaceIfNotEmpty(mod.getValue("contact"), urlTemplate.arg(tr("Home")));
result += replaceIfNotEmpty(mod.getValue("depends"), lineTemplate.arg(tr("Required mods")));
result += replaceIfNotEmpty(mod.getValue("conflicts"), lineTemplate.arg(tr("Conflicting mods")));
result += replaceIfNotEmpty(mod.getValue("description"), textTemplate.arg(tr("Description")));
result += "<p></p>"; // to get some empty space
QString unknownDeps = "This mod can not be installed or enabled because following dependencies are not present";
QString blockingMods = "This mod can not be enabled because following mods are incompatible with this mod";
QString hasActiveDependentMods = "This mod can not be disabled because it is required to run following mods";
QString hasDependentMods = "This mod can not be uninstalled or updated because it is required to run following mods";
QString unknownDeps = tr("This mod can not be installed or enabled because following dependencies are not present");
QString blockingMods = tr("This mod can not be enabled because following mods are incompatible with this mod");
QString hasActiveDependentMods = tr("This mod can not be disabled because it is required to run following mods");
QString hasDependentMods = tr("This mod can not be uninstalled or updated because it is required to run following mods");
QString thisIsSubmod = tr("This is submod and it can not be installed or uninstalled separately from parent mod");
QString notes;
notes += replaceIfNotEmpty(findInvalidDependencies(mod.getName()), noteTemplate.arg(unknownDeps));
notes += replaceIfNotEmpty(findBlockingMods(mod.getName()), noteTemplate.arg(blockingMods));
notes += replaceIfNotEmpty(findInvalidDependencies(mod.getName()), listTemplate.arg(unknownDeps));
notes += replaceIfNotEmpty(findBlockingMods(mod.getName()), listTemplate.arg(blockingMods));
if (mod.isEnabled())
notes += replaceIfNotEmpty(findDependentMods(mod.getName(), true), noteTemplate.arg(hasActiveDependentMods));
notes += replaceIfNotEmpty(findDependentMods(mod.getName(), true), listTemplate.arg(hasActiveDependentMods));
if (mod.isInstalled())
notes += replaceIfNotEmpty(findDependentMods(mod.getName(), false), noteTemplate.arg(hasDependentMods));
notes += replaceIfNotEmpty(findDependentMods(mod.getName(), false), listTemplate.arg(hasDependentMods));
if (mod.getName().contains('.'))
notes += noteTemplate.arg(thisIsSubmod);
if (notes.size())
result += textTemplate.arg("Notes").arg(notes);
result += textTemplate.arg(tr("Notes")).arg(notes);
result += "</body></html>";
return result;
@ -183,28 +197,31 @@ void CModListView::disableModInfo()
ui->hideModInfoButton->setEnabled(false);
}
void CModListView::selectMod(int index)
void CModListView::dataChanged(const QModelIndex & topleft, const QModelIndex & bottomRight)
{
if (index < 0)
selectMod(ui->allModsView->currentIndex());
}
void CModListView::selectMod(const QModelIndex & index)
{
if (!index.isValid())
{
disableModInfo();
}
else
{
enableModInfo();
auto mod = modModel->getMod(modModel->modIndexToName(index));
auto mod = modModel->getMod(index.data(ModRoles::ModNameRole).toString());
ui->textBrowser->setHtml(genModInfoText(mod));
bool hasInvalidDeps = !findInvalidDependencies(modModel->modIndexToName(index)).empty();
bool hasBlockingMods = !findBlockingMods(modModel->modIndexToName(index)).empty();
bool hasDependentMods = !findDependentMods(modModel->modIndexToName(index), true).empty();
bool hasInvalidDeps = !findInvalidDependencies(index.data(ModRoles::ModNameRole).toString()).empty();
bool hasBlockingMods = !findBlockingMods(index.data(ModRoles::ModNameRole).toString()).empty();
bool hasDependentMods = !findDependentMods(index.data(ModRoles::ModNameRole).toString(), true).empty();
ui->disableButton->setVisible(mod.isEnabled());
ui->enableButton->setVisible(mod.isDisabled());
ui->installButton->setVisible(mod.isAvailable());
ui->uninstallButton->setVisible(mod.isInstalled());
ui->installButton->setVisible(mod.isAvailable() && !mod.getName().contains('.'));
ui->uninstallButton->setVisible(mod.isInstalled() && !mod.getName().contains('.'));
ui->updateButton->setVisible(mod.isUpdateable());
// Block buttons if action is not allowed at this time
@ -232,7 +249,7 @@ void CModListView::keyPressEvent(QKeyEvent * event)
void CModListView::modSelected(const QModelIndex & current, const QModelIndex & )
{
selectMod(filterModel->mapToSource(current).row());
selectMod(current);
}
void CModListView::on_hideModInfoButton_clicked()
@ -243,10 +260,10 @@ void CModListView::on_hideModInfoButton_clicked()
showModInfo();
}
void CModListView::on_allModsView_doubleClicked(const QModelIndex &index)
void CModListView::on_allModsView_activated(const QModelIndex &index)
{
showModInfo();
selectMod(filterModel->mapToSource(index).row());
selectMod(index);
}
void CModListView::on_lineEdit_textChanged(const QString &arg1)
@ -319,7 +336,7 @@ QStringList CModListView::findDependentMods(QString mod, bool excludeDisabled)
void CModListView::on_enableButton_clicked()
{
QString modName = modModel->modIndexToName(filterModel->mapToSource(ui->allModsView->currentIndex()).row());
QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
assert(findBlockingMods(modName).empty());
assert(findInvalidDependencies(modName).empty());
@ -332,7 +349,7 @@ void CModListView::on_enableButton_clicked()
void CModListView::on_disableButton_clicked()
{
QString modName = modModel->modIndexToName(filterModel->mapToSource(ui->allModsView->currentIndex()).row());
QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
if (modModel->hasMod(modName) &&
modModel->getMod(modName).isEnabled())
@ -343,7 +360,7 @@ void CModListView::on_disableButton_clicked()
void CModListView::on_updateButton_clicked()
{
QString modName = modModel->modIndexToName(filterModel->mapToSource(ui->allModsView->currentIndex()).row());
QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
assert(findInvalidDependencies(modName).empty());
@ -358,7 +375,7 @@ void CModListView::on_updateButton_clicked()
void CModListView::on_uninstallButton_clicked()
{
QString modName = modModel->modIndexToName(filterModel->mapToSource(ui->allModsView->currentIndex()).row());
QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
// NOTE: perhaps add "manually installed" flag and uninstall those dependencies that don't have it?
if (modModel->hasMod(modName) &&
@ -373,7 +390,7 @@ void CModListView::on_uninstallButton_clicked()
void CModListView::on_installButton_clicked()
{
QString modName = modModel->modIndexToName(filterModel->mapToSource(ui->allModsView->currentIndex()).row());
QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
assert(findInvalidDependencies(modName).empty());
@ -537,8 +554,8 @@ void CModListView::on_pushButton_clicked()
void CModListView::modelReset()
{
//selectMod(filterModel->mapToSource(ui->allModsView->currentIndex()).row());
selectMod(filterModel->rowCount() > 0 ? 0 : -1);
if (ui->modInfoWidget->isVisible())
selectMod(filterModel->rowCount() > 0 ? filterModel->index(0,0) : QModelIndex());
}
void CModListView::checkManagerErrors()

View File

@ -61,9 +61,10 @@ public:
void enableModInfo();
void disableModInfo();
void selectMod(int index);
void selectMod(const QModelIndex & index);
private slots:
void dataChanged(const QModelIndex & topleft, const QModelIndex & bottomRight);
void modSelected(const QModelIndex & current, const QModelIndex & previous);
void downloadProgress(qint64 current, qint64 max);
void downloadFinished(QStringList savedFiles, QStringList failedFiles, QStringList errors);
@ -72,8 +73,6 @@ private slots:
void on_hideModInfoButton_clicked();
void on_allModsView_doubleClicked(const QModelIndex &index);
void on_lineEdit_textChanged(const QString &arg1);
void on_comboBox_currentIndexChanged(int index);
@ -90,6 +89,8 @@ private slots:
void on_pushButton_clicked();
void on_allModsView_activated(const QModelIndex &index);
private:
Ui::CModListView *ui;
};

View File

@ -109,7 +109,7 @@
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTableView" name="allModsView">
<widget class="QTreeView" name="allModsView">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
@ -119,7 +119,7 @@
<property name="iconSize">
<size>
<width>32</width>
<height>20</height>
<height>32</height>
</size>
</property>
<property name="verticalScrollMode">
@ -131,12 +131,9 @@
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<property name="expandsOnDoubleClick">
<bool>false</bool>
</attribute>
</property>
</widget>
</item>
</layout>
@ -220,8 +217,8 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>

View File

@ -66,7 +66,7 @@ void CModManager::loadMods()
for (auto modname : installedMods)
{
ResourceID resID("Mods/" + modname + "/mod.json");
ResourceID resID(CModInfo::getModFile(modname));
if (CResourceHandler::get()->existsResource(resID))
{
std::string name = *CResourceHandler::get()->getResourceName(resID);
@ -114,6 +114,9 @@ bool CModManager::canInstallMod(QString modname)
{
auto mod = modList->getMod(modname);
if (mod.getName().contains('.'))
return addError(modname, "Can not install submod");
if (mod.isInstalled())
return addError(modname, "Mod is already installed");
@ -126,6 +129,9 @@ bool CModManager::canUninstallMod(QString modname)
{
auto mod = modList->getMod(modname);
if (mod.getName().contains('.'))
return addError(modname, "Can not uninstall submod");
if (!mod.isInstalled())
return addError(modname, "Mod is not installed");
@ -191,17 +197,32 @@ bool CModManager::canDisableMod(QString modname)
return true;
}
static QVariant writeValue(QString path, QVariantMap input, QVariant value)
{
if (path.size() > 1)
{
QString entryName = path.section('/', 0, 1);
QString remainder = "/" + path.section('/', 2, -1);
entryName.remove(0, 1);
input.insert(entryName, writeValue(remainder, input.value(entryName).toMap(), value));
return input;
}
else
{
return value;
}
}
bool CModManager::doEnableMod(QString mod, bool on)
{
QVariant value(on);
QVariantMap list = modSettings["activeMods"].toMap();
QVariantMap modData = list[mod].toMap();
modData.insert("active", value);
list.insert(mod, modData);
modSettings.insert("activeMods", list);
QString path = mod;
path = "/activeMods/" + path.replace(".", "/mods/") + "/active";
modSettings = writeValue(path, modSettings, QVariant(on)).toMap();
modList->setModSettings(modSettings["activeMods"]);
modList->modChanged(mod);
JsonUtils::JsonToFile(settingsPath(), modSettings);
@ -215,11 +236,6 @@ bool CModManager::doInstallMod(QString modname, QString archivePath)
if (!QFile(archivePath).exists())
return addError(modname, "Mod archive is missing");
// FIXME: recheck wog/vcmi data behavior - they have bits of data in our trunk
// FIXME: breaks when there is Era mod with same name
//if (QDir(destDir + modname).exists())
// return addError(modname, "Mod with such name is already installed");
if (localMods.contains(modname))
return addError(modname, "Mod with such name is already installed");
@ -237,6 +253,7 @@ bool CModManager::doInstallMod(QString modname, QString archivePath)
localMods.insert(modname, json);
modList->setLocalModList(localMods);
modList->modChanged(modname);
return true;
}
@ -258,6 +275,7 @@ bool CModManager::doUninstallMod(QString modname)
localMods.remove(modname);
modList->setLocalModList(localMods);
modList->modChanged(modname);
return true;
}

View File

@ -668,7 +668,7 @@ std::vector<std::string> CModHandler::getModList(std::string path)
return foundMods;
}
void CModHandler::loadMods(std::string path, std::string parent, const JsonNode & modSettings)
void CModHandler::loadMods(std::string path, std::string parent, const JsonNode & modSettings, bool enableMods)
{
for (std::string modName : getModList(path))
{
@ -682,11 +682,10 @@ void CModHandler::loadMods(std::string path, std::string parent, const JsonNode
mod.dependencies.insert(parent);
allMods[modFullName] = mod;
if (mod.enabled)
{
if (mod.enabled && enableMods)
activeMods.push_back(modFullName);
loadMods(CModInfo::getModDir(modFullName) + '/', modFullName, modSettings[modName]["mods"]);
}
loadMods(CModInfo::getModDir(modFullName) + '/', modFullName, modSettings[modName]["mods"], enableMods && mod.enabled);
}
}
}
@ -695,7 +694,7 @@ void CModHandler::loadMods()
{
const JsonNode modConfig = loadModSettings("config/modSettings.json");
loadMods("", "", modConfig["activeMods"]);
loadMods("", "", modConfig["activeMods"], true);
coreMod = CModInfo("core", modConfig["core"], JsonNode(ResourceID("config/gameConfig.json")));
coreMod.name = "Original game files";

View File

@ -214,7 +214,7 @@ class DLL_LINKAGE CModHandler
std::vector <TModID> resolveDependencies(std::vector<TModID> input) const;
std::vector<std::string> getModList(std::string path);
void loadMods(std::string path, std::string namePrefix, const JsonNode & modSettings);
void loadMods(std::string path, std::string namePrefix, const JsonNode & modSettings, bool enableMods);
public:
CIdentifierStorage identifiers;