added select instance dialog for copying/adding worlds

This commit is contained in:
Ice Yeti 2026-06-11 21:10:16 -04:00
parent eed16bac87
commit 7e7de65fb4
5 changed files with 92 additions and 15 deletions

View file

@ -825,6 +825,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings->registerSetting("TPDownloadGeometry", "");
m_settings->registerSetting("ShaderDownloadGeometry", "");
m_settings->registerSetting("DataPackDownloadGeometry", "");
m_settings->registerSetting("SelectInstanceGeometry", "");
// data pack window
// in future, more pages may be added - so this name is chosen to avoid needing migration

View file

@ -48,9 +48,9 @@
#include "MinecraftInstance.h"
MultiWorldList::MultiWorldList(const QList<BaseInstance*>& instances) : QAbstractListModel(), m_instances(instances)
MultiWorldList::MultiWorldList(const QList<BaseInstance*>& instances) : QAbstractListModel(), allInstances(instances)
{
for (BaseInstance* inst : m_instances) {
for (BaseInstance* inst : allInstances) {
m_dirs.append(dynamic_cast<MinecraftInstance*>(inst)->worldDir());
}
@ -109,7 +109,7 @@ bool MultiWorldList::update()
QList<InstanceWorld> newWorlds;
for (BaseInstance* inst : m_instances) {
for (BaseInstance* inst : allInstances) {
QDir dir = dynamic_cast<MinecraftInstance*>(inst)->worldDir();
dir.refresh();
auto folderContents = dir.entryInfoList();
@ -154,7 +154,7 @@ QList<QString> MultiWorldList::instDirPaths() const
{
QList<QString> dirList;
for (BaseInstance* instance : m_instances) { //use m_dirs??? iy
for (BaseInstance* instance : allInstances) {
dirList.append(QFileInfo(instance->instanceRoot()).absoluteFilePath());
}
@ -399,14 +399,15 @@ Qt::DropActions MultiWorldList::supportedDropActions() const
return Qt::CopyAction | Qt::MoveAction;
}
void MultiWorldList::installWorld(QFileInfo filename)
void MultiWorldList::installWorld(BaseInstance* instance, QFileInfo filename)
{
qDebug() << "installing:" << filename.absoluteFilePath();
World w(filename);
if (!w.isValid()) {
return;
}
w.install(m_dirs[0].absolutePath()); //add option for which instance to install to iy
w.install(QDir(dynamic_cast<MinecraftInstance*>(instance)->worldDir()).absolutePath());
update();
}
bool MultiWorldList::dropMimeData(const QMimeData* data,
@ -434,9 +435,7 @@ bool MultiWorldList::dropMimeData(const QMimeData* data,
QFileInfo worldInfo(filename);
if (!m_dirs[0].entryInfoList().contains(worldInfo)) { //same as above, add option for which instance to install to iy
installWorld(worldInfo);
}
emit fileDropped(worldInfo);
}
if (was_watching)
startWatching();

View file

@ -53,7 +53,7 @@ class MultiWorldList : public QAbstractListModel {
virtual bool update();
/// Install a world from location
void installWorld(QFileInfo filename);
void installWorld(BaseInstance* instance, QFileInfo filename);
/// Deletes the mod at the given index.
virtual bool deleteWorld(int index);
@ -90,17 +90,22 @@ class MultiWorldList : public QAbstractListModel {
const QList<InstanceWorld>& allWorlds() const { return m_worlds; }
QList<BaseInstance*> getInstances() const { return allInstances; }
private slots:
void directoryChanged(QString path);
void loadWorldsAsync();
signals:
void changed();
void fileDropped(QFileInfo worldInfo);
protected:
QList<BaseInstance*> m_instances;
QFileSystemWatcher* m_watcher;
bool m_isWatching;
QList<QDir> m_dirs;
QList<InstanceWorld> m_worlds;
private:
QList<BaseInstance*> allInstances;
};

View file

@ -60,6 +60,7 @@
#include "ui/GuiUtil.h"
#include "Application.h"
#include "icons/IconList.h"
#include "pages/instance/DataPackPage.h"
class MultiWorldListProxyModel : public QSortFilterProxyModel {
@ -113,6 +114,8 @@ MultiWorldListPage::MultiWorldListPage(MultiWorldList* worlds, QWidget* parent)
connect(ui->worldTreeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MultiWorldListPage::worldChanged);
connect(ui->worldTreeView, &QAbstractItemView::doubleClicked, this, &MultiWorldListPage::worldDoubleClicked);
worldChanged(QModelIndex(), QModelIndex());
connect(m_worlds, &MultiWorldList::fileDropped, this, &MultiWorldListPage::fileDropped);
}
void MultiWorldListPage::openedImpl()
@ -400,7 +403,11 @@ void MultiWorldListPage::on_actionAdd_triggered()
if (!list.empty()) {
m_worlds->stopWatching();
for (auto filename : list) {
m_worlds->installWorld(QFileInfo(filename));
auto *instance = selectInstance(tr("Select instance to add world '%1' to.").arg(QFileInfo(filename).fileName()));
if (instance != nullptr) {
m_worlds->installWorld(instance, QFileInfo(filename));
}
}
m_worlds->startWatching();
}
@ -434,14 +441,66 @@ void MultiWorldListPage::on_actionCopy_triggered()
return;
auto worldVariant = m_worlds->data(index, MultiWorldList::ObjectRole);
auto world = (World*)worldVariant.value<void*>();
auto *world = static_cast<InstanceWorld*>(worldVariant.value<void*>());
bool ok = false;
QString name =
QInputDialog::getText(this, tr("World name"), tr("Enter a new name for the copy."), QLineEdit::Normal, world->name(), &ok);
QInputDialog::getText(this, tr("World name"), tr("Enter a new name for the copy."), QLineEdit::Normal, world->world.name(), &ok);
if (ok && name.length() > 0) {
world->install(m_worlds->dirs()[0].absolutePath(), name); //ask which instance iy
auto *instance = selectInstance(tr("Select instance to copy world to."), world->instance);
if (instance != nullptr) {
world->world.install((QDir(instance->worldDir())).absolutePath(), name);
m_worlds->update();
}
}
}
Q_DECLARE_METATYPE(BaseInstance*);
MinecraftInstance* MultiWorldListPage::selectInstance(const QString& message, BaseInstance* preselectedInstance)
{
auto *dialog = new QDialog(this);
dialog->setWindowTitle(tr("Select Instance"));
dialog->resize(static_cast<int>(std::max(0.5 * window()->width(), 400.0)),
static_cast<int>(std::max(0.75 * window()->height(), 400.0)));
dialog->restoreGeometry(QByteArray::fromBase64(APPLICATION->settings()->get("SelectInstanceGeometry").toByteArray()));
auto layout = new QVBoxLayout(dialog);
layout->addWidget(new QLabel(message));
auto instanceList = new QListWidget(dialog);
for (auto instance : m_worlds->getInstances()) {
auto *item = new QListWidgetItem(instanceList);
item->setText(instance->name());
item->setIcon(APPLICATION->icons()->getIcon(instance->iconKey()));
item->setData(Qt::UserRole, QVariant::fromValue(instance));
if (instance == preselectedInstance) {
instanceList->setCurrentItem(item);
}
}
layout->addWidget(instanceList);
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject);
connect(buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
layout->addWidget(buttonBox);
dialog->setLayout(layout);
connect(dialog, &QDialog::finished, this,
[dialog]() { APPLICATION->settings()->set("SelectInstanceGeometry", dialog->saveGeometry().toBase64()); });
if (dialog->exec() == QDialog::Accepted) {
return static_cast<MinecraftInstance*>(instanceList->currentItem()->data(Qt::UserRole).value<BaseInstance*>());
}
return nullptr;
}
void MultiWorldListPage::on_actionRename_triggered()
@ -495,6 +554,17 @@ void MultiWorldListPage::worldDoubleClicked(const QModelIndex& index)
join(proxy->mapToSource(index));
}
void MultiWorldListPage::fileDropped(const QFileInfo& worldInfo)
{
auto *instance = selectInstance(tr("Select instance to add world '%1' to.").arg(worldInfo.fileName()));
if (instance != nullptr) {
if (!QDir(instance->worldDir()).entryInfoList().contains(worldInfo)) {
m_worlds->installWorld(instance, worldInfo);
}
}
}
void MultiWorldListPage::on_actionJoin_triggered()
{
QModelIndex index = getSelectedWorld();

View file

@ -79,6 +79,7 @@ class MultiWorldListPage : public QMainWindow, public BasePage {
bool worldSafetyNagQuestion(const QString& actionType);
void mceditError();
void join(QModelIndex index);
MinecraftInstance* selectInstance(const QString& message, BaseInstance* instance = nullptr);
private:
Ui::MultiWorldListPage* ui;
@ -105,6 +106,7 @@ class MultiWorldListPage : public QMainWindow, public BasePage {
void mceditState(LoggedProcess::State state);
void on_actionJoin_triggered();
void worldDoubleClicked(const QModelIndex& index);
void fileDropped(const QFileInfo& worldInfo);
void ShowContextMenu(const QPoint& pos);
};