feat: display mod dependencies

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97 2025-06-28 23:50:54 +03:00
parent 8277fd41ae
commit 7dd1690947
No known key found for this signature in database
GPG Key ID: 55EF5DA53DB36318
6 changed files with 258 additions and 137 deletions

View File

@ -385,3 +385,20 @@ bool ModFolderModel::setResourceEnabled(const QModelIndexList& indexes, EnableAc
auto affected = getAffectedMods(indexes, action); auto affected = getAffectedMods(indexes, action);
return ResourceFolderModel::setResourceEnabled(indexes + affected, action); return ResourceFolderModel::setResourceEnabled(indexes + affected, action);
} }
QStringList reqToList(QList<Mod*> l)
{
QStringList req;
for (auto m : l) {
req << m->name();
}
return req;
}
QStringList ModFolderModel::requiresList(QString id)
{
return reqToList(m_requires[id]);
}
QStringList ModFolderModel::requiredByList(QString id)
{
return reqToList(m_requiredBy[id]);
}

View File

@ -95,6 +95,10 @@ class ModFolderModel : public ResourceFolderModel {
RESOURCE_HELPERS(Mod) RESOURCE_HELPERS(Mod)
public:
QStringList requiresList(QString id);
QStringList requiredByList(QString id);
private slots: private slots:
void onParseSucceeded(int ticket, QString resource_id) override; void onParseSucceeded(int ticket, QString resource_id) override;
void onParseFinished(); void onParseFinished();

View File

@ -119,7 +119,7 @@ void ModFolderPage::updateFrame(const QModelIndex& current, [[maybe_unused]] con
auto sourceCurrent = m_filterModel->mapToSource(current); auto sourceCurrent = m_filterModel->mapToSource(current);
int row = sourceCurrent.row(); int row = sourceCurrent.row();
const Mod& mod = m_model->at(row); const Mod& mod = m_model->at(row);
ui->frame->updateWithMod(mod); ui->frame->updateWithMod(mod, m_model->requiresList(mod.mod_id()), m_model->requiredByList(mod.mod_id()));
} }
void ModFolderPage::removeItems(const QItemSelection& selection) void ModFolderPage::removeItems(const QItemSelection& selection)

View File

@ -54,28 +54,34 @@ void setupLinkToolTip(QLabel* label)
}); });
} }
InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), ui(new Ui::InfoFrame) InfoFrame::InfoFrame(QWidget* parent) : QFrame(parent), m_ui(new Ui::InfoFrame)
{ {
ui->setupUi(this); m_ui->setupUi(this);
ui->descriptionLabel->setHidden(true); m_ui->descriptionLabel->setHidden(true);
ui->nameLabel->setHidden(true); m_ui->nameLabel->setHidden(true);
ui->licenseLabel->setHidden(true); m_ui->licenseLabel->setHidden(true);
ui->issueTrackerLabel->setHidden(true); m_ui->issueTrackerLabel->setHidden(true);
setupLinkToolTip(ui->iconLabel); setupLinkToolTip(m_ui->iconLabel);
setupLinkToolTip(ui->descriptionLabel); setupLinkToolTip(m_ui->descriptionLabel);
setupLinkToolTip(ui->nameLabel); setupLinkToolTip(m_ui->nameLabel);
setupLinkToolTip(ui->licenseLabel); setupLinkToolTip(m_ui->licenseLabel);
setupLinkToolTip(ui->issueTrackerLabel); setupLinkToolTip(m_ui->issueTrackerLabel);
updateHiddenState(); updateHiddenState();
connect(m_ui->moreInfoBtn, &QPushButton::clicked, this, [this]() {
auto nextIndex = (m_ui->infoStacked->currentIndex() + 1) % 2;
m_ui->infoStacked->setCurrentIndex(nextIndex);
m_ui->moreInfoBtn->setText(nextIndex == 0 ? ">" : "<");
});
m_ui->moreInfoBtn->hide();
} }
InfoFrame::~InfoFrame() InfoFrame::~InfoFrame()
{ {
delete ui; delete m_ui;
} }
void InfoFrame::updateWithMod(Mod const& m) void InfoFrame::updateWithMod(Mod const& m, QStringList requiresList, QStringList requiredByList)
{ {
if (m.type() == ResourceType::FOLDER) { if (m.type() == ResourceType::FOLDER) {
clear(); clear();
@ -141,6 +147,26 @@ void InfoFrame::updateWithMod(Mod const& m)
issueTracker += "<a href=\"" + m.issueTracker() + "\">" + m.issueTracker() + "</a>"; issueTracker += "<a href=\"" + m.issueTracker() + "\">" + m.issueTracker() + "</a>";
} }
setIssueTracker(issueTracker); setIssueTracker(issueTracker);
if (requiredByList.isEmpty()) {
m_ui->requiredGB->hide();
} else {
m_ui->requiredGB->show();
m_ui->requiredView->clear();
m_ui->requiredView->addItems(requiredByList);
}
if (requiresList.isEmpty()) {
m_ui->requiresGB->hide();
} else {
m_ui->requiresGB->show();
m_ui->requiresView->clear();
m_ui->requiresView->addItems(requiresList);
}
if (requiresList.isEmpty() && requiredByList.isEmpty()) {
m_ui->infoStacked->setCurrentIndex(0);
m_ui->moreInfoBtn->setText(">");
}
m_ui->moreInfoBtn->setHidden(requiresList.isEmpty() && requiredByList.isEmpty());
} }
void InfoFrame::updateWithResource(const Resource& resource) void InfoFrame::updateWithResource(const Resource& resource)
@ -227,7 +253,8 @@ void InfoFrame::updateWithResourcePack(ResourcePack& resource_pack)
setImage(resource_pack.image({ 64, 64 })); setImage(resource_pack.image({ 64, 64 }));
} }
void InfoFrame::updateWithDataPack(DataPack& data_pack) { void InfoFrame::updateWithDataPack(DataPack& data_pack)
{
setName(renderColorCodes(data_pack.name())); setName(renderColorCodes(data_pack.name()));
setDescription(renderColorCodes(data_pack.description())); setDescription(renderColorCodes(data_pack.description()));
setImage(data_pack.image({ 64, 64 })); setImage(data_pack.image({ 64, 64 }));
@ -254,12 +281,13 @@ void InfoFrame::clear()
setImage(); setImage();
setLicense(); setLicense();
setIssueTracker(); setIssueTracker();
m_ui->moreInfoBtn->hide();
} }
void InfoFrame::updateHiddenState() void InfoFrame::updateHiddenState()
{ {
if (ui->descriptionLabel->isHidden() && ui->nameLabel->isHidden() && ui->licenseLabel->isHidden() && if (m_ui->descriptionLabel->isHidden() && m_ui->nameLabel->isHidden() && m_ui->licenseLabel->isHidden() &&
ui->issueTrackerLabel->isHidden()) { m_ui->issueTrackerLabel->isHidden()) {
setHidden(true); setHidden(true);
} else { } else {
setHidden(false); setHidden(false);
@ -269,10 +297,10 @@ void InfoFrame::updateHiddenState()
void InfoFrame::setName(QString text) void InfoFrame::setName(QString text)
{ {
if (text.isEmpty()) { if (text.isEmpty()) {
ui->nameLabel->setHidden(true); m_ui->nameLabel->setHidden(true);
} else { } else {
ui->nameLabel->setText(text); m_ui->nameLabel->setText(text);
ui->nameLabel->setHidden(false); m_ui->nameLabel->setHidden(false);
} }
updateHiddenState(); updateHiddenState();
} }
@ -280,14 +308,14 @@ void InfoFrame::setName(QString text)
void InfoFrame::setDescription(QString text) void InfoFrame::setDescription(QString text)
{ {
if (text.isEmpty()) { if (text.isEmpty()) {
ui->descriptionLabel->setHidden(true); m_ui->descriptionLabel->setHidden(true);
updateHiddenState(); updateHiddenState();
return; return;
} else { } else {
ui->descriptionLabel->setHidden(false); m_ui->descriptionLabel->setHidden(false);
updateHiddenState(); updateHiddenState();
} }
ui->descriptionLabel->setToolTip(""); m_ui->descriptionLabel->setToolTip("");
QString intermediatetext = text.trimmed(); QString intermediatetext = text.trimmed();
bool prev(false); bool prev(false);
QChar rem('\n'); QChar rem('\n');
@ -309,8 +337,8 @@ void InfoFrame::setDescription(QString text)
doc.setHtml(text); doc.setHtml(text);
if (doc.characterCount() > maxCharacterElide) { if (doc.characterCount() > maxCharacterElide) {
ui->descriptionLabel->setOpenExternalLinks(false); m_ui->descriptionLabel->setOpenExternalLinks(false);
ui->descriptionLabel->setTextFormat(Qt::TextFormat::RichText); // This allows injecting HTML here. m_ui->descriptionLabel->setTextFormat(Qt::TextFormat::RichText); // This allows injecting HTML here.
m_description = text; m_description = text;
// move the cursor to the character elide, doesn't see html // move the cursor to the character elide, doesn't see html
@ -323,25 +351,25 @@ void InfoFrame::setDescription(QString text)
cursor.insertHtml("<a href=\"#mod_desc\">...</a>"); cursor.insertHtml("<a href=\"#mod_desc\">...</a>");
labeltext.append(doc.toHtml()); labeltext.append(doc.toHtml());
connect(ui->descriptionLabel, &QLabel::linkActivated, this, &InfoFrame::descriptionEllipsisHandler); connect(m_ui->descriptionLabel, &QLabel::linkActivated, this, &InfoFrame::descriptionEllipsisHandler);
} else { } else {
ui->descriptionLabel->setTextFormat(Qt::TextFormat::AutoText); m_ui->descriptionLabel->setTextFormat(Qt::TextFormat::AutoText);
labeltext.append(finaltext); labeltext.append(finaltext);
} }
ui->descriptionLabel->setText(labeltext); m_ui->descriptionLabel->setText(labeltext);
} }
void InfoFrame::setLicense(QString text) void InfoFrame::setLicense(QString text)
{ {
if (text.isEmpty()) { if (text.isEmpty()) {
ui->licenseLabel->setHidden(true); m_ui->licenseLabel->setHidden(true);
updateHiddenState(); updateHiddenState();
return; return;
} else { } else {
ui->licenseLabel->setHidden(false); m_ui->licenseLabel->setHidden(false);
updateHiddenState(); updateHiddenState();
} }
ui->licenseLabel->setToolTip(""); m_ui->licenseLabel->setToolTip("");
QString intermediatetext = text.trimmed(); QString intermediatetext = text.trimmed();
bool prev(false); bool prev(false);
QChar rem('\n'); QChar rem('\n');
@ -357,26 +385,26 @@ void InfoFrame::setLicense(QString text)
QString labeltext; QString labeltext;
labeltext.reserve(300); labeltext.reserve(300);
if (finaltext.length() > 290) { if (finaltext.length() > 290) {
ui->licenseLabel->setOpenExternalLinks(false); m_ui->licenseLabel->setOpenExternalLinks(false);
ui->licenseLabel->setTextFormat(Qt::TextFormat::RichText); m_ui->licenseLabel->setTextFormat(Qt::TextFormat::RichText);
m_license = text; m_license = text;
// This allows injecting HTML here. // This allows injecting HTML here.
labeltext.append("<html><body>" + finaltext.left(287) + "<a href=\"#mod_desc\">...</a></body></html>"); labeltext.append("<html><body>" + finaltext.left(287) + "<a href=\"#mod_desc\">...</a></body></html>");
connect(ui->licenseLabel, &QLabel::linkActivated, this, &InfoFrame::licenseEllipsisHandler); connect(m_ui->licenseLabel, &QLabel::linkActivated, this, &InfoFrame::licenseEllipsisHandler);
} else { } else {
ui->licenseLabel->setTextFormat(Qt::TextFormat::AutoText); m_ui->licenseLabel->setTextFormat(Qt::TextFormat::AutoText);
labeltext.append(finaltext); labeltext.append(finaltext);
} }
ui->licenseLabel->setText(labeltext); m_ui->licenseLabel->setText(labeltext);
} }
void InfoFrame::setIssueTracker(QString text) void InfoFrame::setIssueTracker(QString text)
{ {
if (text.isEmpty()) { if (text.isEmpty()) {
ui->issueTrackerLabel->setHidden(true); m_ui->issueTrackerLabel->setHidden(true);
} else { } else {
ui->issueTrackerLabel->setText(text); m_ui->issueTrackerLabel->setText(text);
ui->issueTrackerLabel->setHidden(false); m_ui->issueTrackerLabel->setHidden(false);
} }
updateHiddenState(); updateHiddenState();
} }
@ -384,10 +412,10 @@ void InfoFrame::setIssueTracker(QString text)
void InfoFrame::setImage(QPixmap img) void InfoFrame::setImage(QPixmap img)
{ {
if (img.isNull()) { if (img.isNull()) {
ui->iconLabel->setHidden(true); m_ui->iconLabel->setHidden(true);
} else { } else {
ui->iconLabel->setHidden(false); m_ui->iconLabel->setHidden(false);
ui->iconLabel->setPixmap(img); m_ui->iconLabel->setPixmap(img);
} }
} }

View File

@ -61,7 +61,7 @@ class InfoFrame : public QFrame {
void clear(); void clear();
void updateWithMod(Mod const& m); void updateWithMod(Mod const& m, QStringList requiresList = {}, QStringList requiredByList = {});
void updateWithResource(Resource const& resource); void updateWithResource(Resource const& resource);
void updateWithResourcePack(ResourcePack& rp); void updateWithResourcePack(ResourcePack& rp);
void updateWithDataPack(DataPack& rp); void updateWithDataPack(DataPack& rp);
@ -78,7 +78,7 @@ class InfoFrame : public QFrame {
void updateHiddenState(); void updateHiddenState();
private: private:
Ui::InfoFrame* ui; Ui::InfoFrame* m_ui;
QString m_description; QString m_description;
QString m_license; QString m_license;
class QMessageBox* m_current_box = nullptr; class QMessageBox* m_current_box = nullptr;

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>527</width> <width>527</width>
<height>113</height> <height>130</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -19,7 +19,7 @@
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
<height>120</height> <height>130</height>
</size> </size>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
@ -35,6 +35,169 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item row="1" column="0">
<widget class="QPushButton" name="moreInfoBtn">
<property name="text">
<string>&gt;</string>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="2">
<widget class="QStackedWidget" name="infoStacked">
<widget class="QWidget" name="base">
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="2">
<widget class="QLabel" name="descriptionLabel">
<property name="toolTip">
<string notr="true"/>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string notr="true"/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="issueTrackerLabel">
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="licenseLabel">
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="extra">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="requiresGB">
<property name="title">
<string>Requires</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QListWidget" name="requiresView">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="spacing">
<number>10</number>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="requiredGB">
<property name="title">
<string>Required by</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QListWidget" name="requiredView">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="movement">
<enum>QListView::Static</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="spacing">
<number>10</number>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="0" column="0" rowspan="2"> <item row="0" column="0" rowspan="2">
<widget class="QLabel" name="iconLabel"> <widget class="QLabel" name="iconLabel">
<property name="minimumSize"> <property name="minimumSize">
@ -60,97 +223,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QLabel" name="descriptionLabel">
<property name="toolTip">
<string notr="true"/>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string notr="true"/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="licenseLabel">
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="issueTrackerLabel">
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>