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:
parent
fe1b16a7ec
commit
333a51a48a
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||
</style></head><body style=" font-family:'Ubuntu'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
<p style="-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;"><br /></p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user