NOISSUE Add world icons and world icon reset button
This commit is contained in:
parent
c6c9feb3a2
commit
8a0027c73a
@ -138,14 +138,31 @@ void World::repath(const QFileInfo &file)
|
|||||||
m_folderName = file.fileName();
|
m_folderName = file.fileName();
|
||||||
if(file.isFile() && file.suffix() == "zip")
|
if(file.isFile() && file.suffix() == "zip")
|
||||||
{
|
{
|
||||||
|
m_iconFile = QString();
|
||||||
readFromZip(file);
|
readFromZip(file);
|
||||||
}
|
}
|
||||||
else if(file.isDir())
|
else if(file.isDir())
|
||||||
{
|
{
|
||||||
|
QFileInfo assumedIconPath(file.absoluteFilePath() + "/icon.png");
|
||||||
|
if(assumedIconPath.exists()) {
|
||||||
|
m_iconFile = assumedIconPath.absoluteFilePath();
|
||||||
|
}
|
||||||
readFromFS(file);
|
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)
|
void World::readFromFS(const QFileInfo &file)
|
||||||
{
|
{
|
||||||
auto bytes = getLevelDatDataFromFS(file);
|
auto bytes = getLevelDatDataFromFS(file);
|
||||||
|
@ -40,6 +40,10 @@ public:
|
|||||||
{
|
{
|
||||||
return m_actualName;
|
return m_actualName;
|
||||||
}
|
}
|
||||||
|
QString iconFile() const
|
||||||
|
{
|
||||||
|
return m_iconFile;
|
||||||
|
}
|
||||||
QDateTime lastPlayed() const
|
QDateTime lastPlayed() const
|
||||||
{
|
{
|
||||||
return m_lastPlayed;
|
return m_lastPlayed;
|
||||||
@ -70,6 +74,8 @@ public:
|
|||||||
bool replace(World &with);
|
bool replace(World &with);
|
||||||
// change the world's filesystem path (used by world lists for *MAGIC* purposes)
|
// change the world's filesystem path (used by world lists for *MAGIC* purposes)
|
||||||
void repath(const QFileInfo &file);
|
void repath(const QFileInfo &file);
|
||||||
|
// remove the icon file, if any
|
||||||
|
bool resetIcon();
|
||||||
|
|
||||||
bool rename(const QString &to);
|
bool rename(const QString &to);
|
||||||
bool install(const QString &to, const QString &name= QString());
|
bool install(const QString &to, const QString &name= QString());
|
||||||
@ -88,6 +94,7 @@ protected:
|
|||||||
QString m_containerOffsetPath;
|
QString m_containerOffsetPath;
|
||||||
QString m_folderName;
|
QString m_folderName;
|
||||||
QString m_actualName;
|
QString m_actualName;
|
||||||
|
QString m_iconFile;
|
||||||
QDateTime levelDatTime;
|
QDateTime levelDatTime;
|
||||||
QDateTime m_lastPlayed;
|
QDateTime m_lastPlayed;
|
||||||
int64_t m_randomSeed = 0;
|
int64_t m_randomSeed = 0;
|
||||||
|
@ -136,6 +136,19 @@ bool WorldList::deleteWorlds(int first, int last)
|
|||||||
return true;
|
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
|
int WorldList::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return 3;
|
return 3;
|
||||||
@ -195,6 +208,10 @@ QVariant WorldList::data(const QModelIndex &index, int role) const
|
|||||||
{
|
{
|
||||||
return world.lastPlayed();
|
return world.lastPlayed();
|
||||||
}
|
}
|
||||||
|
case IconFileRole:
|
||||||
|
{
|
||||||
|
return world.iconFile();
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,8 @@ public:
|
|||||||
SeedRole,
|
SeedRole,
|
||||||
NameRole,
|
NameRole,
|
||||||
GameModeRole,
|
GameModeRole,
|
||||||
LastPlayedRole
|
LastPlayedRole,
|
||||||
|
IconFileRole
|
||||||
};
|
};
|
||||||
|
|
||||||
WorldList(const QString &dir);
|
WorldList(const QString &dir);
|
||||||
@ -81,6 +82,9 @@ public:
|
|||||||
/// Deletes the mod at the given index.
|
/// Deletes the mod at the given index.
|
||||||
virtual bool deleteWorld(int index);
|
virtual bool deleteWorld(int index);
|
||||||
|
|
||||||
|
/// Removes the world icon, if any
|
||||||
|
virtual bool resetIcon(int index);
|
||||||
|
|
||||||
/// Deletes all the selected mods
|
/// Deletes all the selected mods
|
||||||
virtual bool deleteWorlds(int first, int last);
|
virtual bool deleteWorlds(int first, int last);
|
||||||
|
|
||||||
|
@ -31,6 +31,33 @@
|
|||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <FileSystem.h>
|
#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)
|
WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worlds, QWidget *parent)
|
||||||
: QMainWindow(parent), m_inst(inst), ui(new Ui::WorldListPage), m_worlds(worlds)
|
: 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);
|
ui->toolBar->insertSpacer(ui->actionRefresh);
|
||||||
|
|
||||||
QSortFilterProxyModel * proxy = new QSortFilterProxyModel(this);
|
WorldListProxyModel * proxy = new WorldListProxyModel(this);
|
||||||
proxy->setSortCaseSensitivity(Qt::CaseInsensitive);
|
proxy->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||||
proxy->setSourceModel(m_worlds.get());
|
proxy->setSourceModel(m_worlds.get());
|
||||||
ui->worldTreeView->setSortingEnabled(true);
|
ui->worldTreeView->setSortingEnabled(true);
|
||||||
ui->worldTreeView->setModel(proxy);
|
ui->worldTreeView->setModel(proxy);
|
||||||
ui->worldTreeView->installEventFilter(this);
|
ui->worldTreeView->installEventFilter(this);
|
||||||
ui->worldTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
|
ui->worldTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
ui->worldTreeView->setIconSize(QSize(64,64));
|
||||||
connect(ui->worldTreeView, &QTreeView::customContextMenuRequested, this, &WorldListPage::ShowContextMenu);
|
connect(ui->worldTreeView, &QTreeView::customContextMenuRequested, this, &WorldListPage::ShowContextMenu);
|
||||||
|
|
||||||
auto head = ui->worldTreeView->header();
|
auto head = ui->worldTreeView->header();
|
||||||
@ -142,6 +170,19 @@ void WorldListPage::on_actionView_Folder_triggered()
|
|||||||
DesktopServices::openDirectory(m_worlds->dir().absolutePath(), true);
|
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()
|
QModelIndex WorldListPage::getSelectedWorld()
|
||||||
{
|
{
|
||||||
auto index = ui->worldTreeView->selectionModel()->currentIndex();
|
auto index = ui->worldTreeView->selectionModel()->currentIndex();
|
||||||
@ -255,6 +296,8 @@ void WorldListPage::worldChanged(const QModelIndex ¤t, const QModelIndex &
|
|||||||
ui->actionRemove->setEnabled(enable);
|
ui->actionRemove->setEnabled(enable);
|
||||||
ui->actionCopy->setEnabled(enable);
|
ui->actionCopy->setEnabled(enable);
|
||||||
ui->actionRename->setEnabled(enable);
|
ui->actionRename->setEnabled(enable);
|
||||||
|
bool hasIcon = !index.data(WorldList::IconFileRole).isNull();
|
||||||
|
ui->actionReset_Icon->setEnabled(enable && hasIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldListPage::on_actionAdd_triggered()
|
void WorldListPage::on_actionAdd_triggered()
|
||||||
@ -342,3 +385,5 @@ void WorldListPage::on_actionRefresh_triggered()
|
|||||||
{
|
{
|
||||||
m_worlds->update();
|
m_worlds->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "WorldListPage.moc"
|
||||||
|
@ -90,6 +90,7 @@ private slots:
|
|||||||
void on_actionRename_triggered();
|
void on_actionRename_triggered();
|
||||||
void on_actionRefresh_triggered();
|
void on_actionRefresh_triggered();
|
||||||
void on_actionView_Folder_triggered();
|
void on_actionView_Folder_triggered();
|
||||||
|
void on_actionReset_Icon_triggered();
|
||||||
void worldChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
void worldChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
void mceditState(LoggedProcess::State state);
|
void mceditState(LoggedProcess::State state);
|
||||||
|
|
||||||
|
@ -41,6 +41,12 @@
|
|||||||
<property name="alternatingRowColors">
|
<property name="alternatingRowColors">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="rootIsDecorated">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="itemsExpandable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="sortingEnabled">
|
<property name="sortingEnabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -79,6 +85,7 @@
|
|||||||
<addaction name="actionCopy"/>
|
<addaction name="actionCopy"/>
|
||||||
<addaction name="actionRemove"/>
|
<addaction name="actionRemove"/>
|
||||||
<addaction name="actionMCEdit"/>
|
<addaction name="actionMCEdit"/>
|
||||||
|
<addaction name="actionReset_Icon"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionCopy_Seed"/>
|
<addaction name="actionCopy_Seed"/>
|
||||||
<addaction name="actionRefresh"/>
|
<addaction name="actionRefresh"/>
|
||||||
@ -124,6 +131,14 @@
|
|||||||
<string>View Folder</string>
|
<string>View Folder</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</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>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
Loading…
Reference in New Issue
Block a user