summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2020-08-22 01:34:55 +0200
committerPetr Mrázek <peterix@gmail.com>2020-08-22 01:34:55 +0200
commit8a0027c73a755849bf5b58c1509c71a543ddb982 (patch)
treef4c87ea06b753d771015f444bc1ff68a624c782e
parentc6c9feb3a2006f0b37736799f003a0fb87f68b18 (diff)
downloadMultiMC-8a0027c73a755849bf5b58c1509c71a543ddb982.tar
MultiMC-8a0027c73a755849bf5b58c1509c71a543ddb982.tar.gz
MultiMC-8a0027c73a755849bf5b58c1509c71a543ddb982.tar.lz
MultiMC-8a0027c73a755849bf5b58c1509c71a543ddb982.tar.xz
MultiMC-8a0027c73a755849bf5b58c1509c71a543ddb982.zip
NOISSUE Add world icons and world icon reset button
-rw-r--r--api/logic/minecraft/World.cpp17
-rw-r--r--api/logic/minecraft/World.h7
-rw-r--r--api/logic/minecraft/WorldList.cpp17
-rw-r--r--api/logic/minecraft/WorldList.h6
-rw-r--r--application/pages/instance/WorldListPage.cpp47
-rw-r--r--application/pages/instance/WorldListPage.h1
-rw-r--r--application/pages/instance/WorldListPage.ui15
7 files changed, 108 insertions, 2 deletions
diff --git a/api/logic/minecraft/World.cpp b/api/logic/minecraft/World.cpp
index 17dbf4ae..06a6080a 100644
--- a/api/logic/minecraft/World.cpp
+++ b/api/logic/minecraft/World.cpp
@@ -138,14 +138,31 @@ void World::repath(const QFileInfo &file)
m_folderName = file.fileName();
if(file.isFile() && file.suffix() == "zip")
{
+ m_iconFile = QString();
readFromZip(file);
}
else if(file.isDir())
{
+ QFileInfo assumedIconPath(file.absoluteFilePath() + "/icon.png");
+ if(assumedIconPath.exists()) {
+ m_iconFile = assumedIconPath.absoluteFilePath();
+ }
readFromFS(file);
}
}
+bool World::resetIcon()
+{
+ if(m_iconFile.isNull()) {
+ return false;
+ }
+ if(QFile(m_iconFile).remove()) {
+ m_iconFile = QString();
+ return true;
+ }
+ return false;
+}
+
void World::readFromFS(const QFileInfo &file)
{
auto bytes = getLevelDatDataFromFS(file);
diff --git a/api/logic/minecraft/World.h b/api/logic/minecraft/World.h
index 818701fa..d04c1040 100644
--- a/api/logic/minecraft/World.h
+++ b/api/logic/minecraft/World.h
@@ -40,6 +40,10 @@ public:
{
return m_actualName;
}
+ QString iconFile() const
+ {
+ return m_iconFile;
+ }
QDateTime lastPlayed() const
{
return m_lastPlayed;
@@ -70,6 +74,8 @@ public:
bool replace(World &with);
// change the world's filesystem path (used by world lists for *MAGIC* purposes)
void repath(const QFileInfo &file);
+ // remove the icon file, if any
+ bool resetIcon();
bool rename(const QString &to);
bool install(const QString &to, const QString &name= QString());
@@ -88,6 +94,7 @@ protected:
QString m_containerOffsetPath;
QString m_folderName;
QString m_actualName;
+ QString m_iconFile;
QDateTime levelDatTime;
QDateTime m_lastPlayed;
int64_t m_randomSeed = 0;
diff --git a/api/logic/minecraft/WorldList.cpp b/api/logic/minecraft/WorldList.cpp
index b7a24434..94b59da4 100644
--- a/api/logic/minecraft/WorldList.cpp
+++ b/api/logic/minecraft/WorldList.cpp
@@ -136,6 +136,19 @@ bool WorldList::deleteWorlds(int first, int last)
return true;
}
+bool WorldList::resetIcon(int row)
+{
+ if (row >= worlds.size() || row < 0)
+ return false;
+ World &m = worlds[row];
+ if(m.resetIcon()) {
+ emit dataChanged(index(row), index(row), {WorldList::IconFileRole});
+ return true;
+ }
+ return false;
+}
+
+
int WorldList::columnCount(const QModelIndex &parent) const
{
return 3;
@@ -195,6 +208,10 @@ QVariant WorldList::data(const QModelIndex &index, int role) const
{
return world.lastPlayed();
}
+ case IconFileRole:
+ {
+ return world.iconFile();
+ }
default:
return QVariant();
}
diff --git a/api/logic/minecraft/WorldList.h b/api/logic/minecraft/WorldList.h
index 37ad330a..db44daf9 100644
--- a/api/logic/minecraft/WorldList.h
+++ b/api/logic/minecraft/WorldList.h
@@ -44,7 +44,8 @@ public:
SeedRole,
NameRole,
GameModeRole,
- LastPlayedRole
+ LastPlayedRole,
+ IconFileRole
};
WorldList(const QString &dir);
@@ -81,6 +82,9 @@ public:
/// Deletes the mod at the given index.
virtual bool deleteWorld(int index);
+ /// Removes the world icon, if any
+ virtual bool resetIcon(int index);
+
/// Deletes all the selected mods
virtual bool deleteWorlds(int first, int last);
diff --git a/application/pages/instance/WorldListPage.cpp b/application/pages/instance/WorldListPage.cpp
index 8358a0f1..75741d22 100644
--- a/application/pages/instance/WorldListPage.cpp
+++ b/application/pages/instance/WorldListPage.cpp
@@ -31,6 +31,33 @@
#include <QProcess>
#include <FileSystem.h>
+class WorldListProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ WorldListProxyModel(QObject *parent) : QSortFilterProxyModel(parent) {}
+
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
+ {
+ QModelIndex sourceIndex = mapToSource(index);
+
+ if (index.column() == 0 && role == Qt::DecorationRole)
+ {
+ WorldList *worlds = qobject_cast<WorldList *>(sourceModel());
+ auto iconFile = worlds->data(sourceIndex, WorldList::IconFileRole).toString();
+ if(iconFile.isNull()) {
+ // NOTE: Minecraft uses the same placeholder for servers AND worlds
+ return MMC->getThemedIcon("unknown_server");
+ }
+ return QIcon(iconFile);
+ }
+
+ return sourceIndex.data(role);
+ }
+};
+
+
WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worlds, QWidget *parent)
: QMainWindow(parent), m_inst(inst), ui(new Ui::WorldListPage), m_worlds(worlds)
{
@@ -38,13 +65,14 @@ WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worl
ui->toolBar->insertSpacer(ui->actionRefresh);
- QSortFilterProxyModel * proxy = new QSortFilterProxyModel(this);
+ WorldListProxyModel * proxy = new WorldListProxyModel(this);
proxy->setSortCaseSensitivity(Qt::CaseInsensitive);
proxy->setSourceModel(m_worlds.get());
ui->worldTreeView->setSortingEnabled(true);
ui->worldTreeView->setModel(proxy);
ui->worldTreeView->installEventFilter(this);
ui->worldTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
+ ui->worldTreeView->setIconSize(QSize(64,64));
connect(ui->worldTreeView, &QTreeView::customContextMenuRequested, this, &WorldListPage::ShowContextMenu);
auto head = ui->worldTreeView->header();
@@ -142,6 +170,19 @@ void WorldListPage::on_actionView_Folder_triggered()
DesktopServices::openDirectory(m_worlds->dir().absolutePath(), true);
}
+void WorldListPage::on_actionReset_Icon_triggered()
+{
+ auto proxiedIndex = getSelectedWorld();
+
+ if(!proxiedIndex.isValid())
+ return;
+
+ if(m_worlds->resetIcon(proxiedIndex.row())) {
+ ui->actionReset_Icon->setEnabled(false);
+ }
+}
+
+
QModelIndex WorldListPage::getSelectedWorld()
{
auto index = ui->worldTreeView->selectionModel()->currentIndex();
@@ -255,6 +296,8 @@ void WorldListPage::worldChanged(const QModelIndex &current, const QModelIndex &
ui->actionRemove->setEnabled(enable);
ui->actionCopy->setEnabled(enable);
ui->actionRename->setEnabled(enable);
+ bool hasIcon = !index.data(WorldList::IconFileRole).isNull();
+ ui->actionReset_Icon->setEnabled(enable && hasIcon);
}
void WorldListPage::on_actionAdd_triggered()
@@ -342,3 +385,5 @@ void WorldListPage::on_actionRefresh_triggered()
{
m_worlds->update();
}
+
+#include "WorldListPage.moc"
diff --git a/application/pages/instance/WorldListPage.h b/application/pages/instance/WorldListPage.h
index c39420da..8ff14819 100644
--- a/application/pages/instance/WorldListPage.h
+++ b/application/pages/instance/WorldListPage.h
@@ -90,6 +90,7 @@ private slots:
void on_actionRename_triggered();
void on_actionRefresh_triggered();
void on_actionView_Folder_triggered();
+ void on_actionReset_Icon_triggered();
void worldChanged(const QModelIndex &current, const QModelIndex &previous);
void mceditState(LoggedProcess::State state);
diff --git a/application/pages/instance/WorldListPage.ui b/application/pages/instance/WorldListPage.ui
index ddb3dfa9..8d00f8f4 100644
--- a/application/pages/instance/WorldListPage.ui
+++ b/application/pages/instance/WorldListPage.ui
@@ -41,6 +41,12 @@
<property name="alternatingRowColors">
<bool>true</bool>
</property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="itemsExpandable">
+ <bool>false</bool>
+ </property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
@@ -79,6 +85,7 @@
<addaction name="actionCopy"/>
<addaction name="actionRemove"/>
<addaction name="actionMCEdit"/>
+ <addaction name="actionReset_Icon"/>
<addaction name="separator"/>
<addaction name="actionCopy_Seed"/>
<addaction name="actionRefresh"/>
@@ -124,6 +131,14 @@
<string>View Folder</string>
</property>
</action>
+ <action name="actionReset_Icon">
+ <property name="text">
+ <string>Reset Icon</string>
+ </property>
+ <property name="toolTip">
+ <string>Remove world icon to make the game re-generate it on next load.</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>