diff options
author | Alex <robotbrain@robotbrain.info> | 2015-08-18 19:10:17 -0400 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2015-09-06 16:00:07 +0200 |
commit | 583e5946f4cd29f0a18bcc4fad5608de739aa113 (patch) | |
tree | a3386315509351bb936a68bce4d9bdc1ea2e4cd1 | |
parent | 16df6c16f315aaa30ea844c8ea90ad425f9d4c89 (diff) | |
download | MultiMC-583e5946f4cd29f0a18bcc4fad5608de739aa113.tar MultiMC-583e5946f4cd29f0a18bcc4fad5608de739aa113.tar.gz MultiMC-583e5946f4cd29f0a18bcc4fad5608de739aa113.tar.lz MultiMC-583e5946f4cd29f0a18bcc4fad5608de739aa113.tar.xz MultiMC-583e5946f4cd29f0a18bcc4fad5608de739aa113.zip |
GH-1047 World management for instances. Removal only currently.
-rw-r--r-- | application/CMakeLists.txt | 3 | ||||
-rw-r--r-- | application/InstancePageProvider.h | 3 | ||||
-rw-r--r-- | application/pages/WorldListPage.cpp | 94 | ||||
-rw-r--r-- | application/pages/WorldListPage.h | 69 | ||||
-rw-r--r-- | application/pages/WorldListPage.ui | 94 | ||||
-rw-r--r-- | logic/CMakeLists.txt | 4 | ||||
-rw-r--r-- | logic/minecraft/LegacyInstance.cpp | 11 | ||||
-rw-r--r-- | logic/minecraft/LegacyInstance.h | 2 | ||||
-rw-r--r-- | logic/minecraft/MinecraftInstance.h | 5 | ||||
-rw-r--r-- | logic/minecraft/OneSixInstance.cpp | 16 | ||||
-rw-r--r-- | logic/minecraft/OneSixInstance.h | 3 | ||||
-rw-r--r-- | logic/minecraft/World.cpp | 72 | ||||
-rw-r--r-- | logic/minecraft/World.h | 47 | ||||
-rw-r--r-- | logic/minecraft/WorldList.cpp | 226 | ||||
-rw-r--r-- | logic/minecraft/WorldList.h | 101 |
15 files changed, 750 insertions, 0 deletions
diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index 1cc37a5d..f72b6a16 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -177,6 +177,8 @@ SET(MULTIMC_SOURCES pages/LegacyJarModPage.h pages/LegacyUpgradePage.cpp pages/LegacyUpgradePage.h + pages/WorldListPage.cpp + pages/WorldListPage.h # GUI - global settings pages pages/global/AccountListPage.cpp @@ -272,6 +274,7 @@ SET(MULTIMC_UIS pages/OtherLogsPage.ui pages/LegacyJarModPage.ui pages/LegacyUpgradePage.ui + pages/WorldListPage.ui # Global settings pages pages/global/AccountListPage.ui diff --git a/application/InstancePageProvider.h b/application/InstancePageProvider.h index 1da4c9f1..c3ae17c1 100644 --- a/application/InstancePageProvider.h +++ b/application/InstancePageProvider.h @@ -12,6 +12,7 @@ #include "pages/OtherLogsPage.h" #include "pages/BasePageProvider.h" #include "pages/LegacyJarModPage.h" +#include "pages/WorldListPage.h" #include <pathutils.h> @@ -39,6 +40,7 @@ public: values.append(new ResourcePackPage(onesix.get())); values.append(new TexturePackPage(onesix.get())); values.append(new NotesPage(onesix.get())); + values.append(new WorldListPage(onesix.get(), onesix->worldList(), "worlds", "worlds", tr("Worlds"), "Worlds")); values.append(new ScreenshotsPage(PathCombine(onesix->minecraftRoot(), "screenshots"))); values.append(new InstanceSettingsPage(onesix.get())); } @@ -54,6 +56,7 @@ public: values.append(new ModFolderPage(legacy.get(), legacy->coreModList(), "coremods", "coremods", tr("Core mods"), "Loader-mods")); values.append(new TexturePackPage(legacy.get())); values.append(new NotesPage(legacy.get())); + values.append(new WorldListPage(legacy.get(), legacy->worldList(), "worlds", "worlds", tr("Worlds"), "Worlds")); values.append(new ScreenshotsPage(PathCombine(legacy->minecraftRoot(), "screenshots"))); values.append(new InstanceSettingsPage(legacy.get())); } diff --git a/application/pages/WorldListPage.cpp b/application/pages/WorldListPage.cpp new file mode 100644 index 00000000..662b7452 --- /dev/null +++ b/application/pages/WorldListPage.cpp @@ -0,0 +1,94 @@ +// +// Created by robotbrain on 8/18/15. +// + +#include "WorldListPage.h" +#include "ui_WorldListPage.h" +#include "minecraft/WorldList.h" +#include "dialogs/ModEditDialogCommon.h" +#include <QEvent> +#include <QKeyEvent> + +WorldListPage::WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worlds, QString id, + QString iconName, QString displayName, QString helpPage, + QWidget *parent) + : QWidget(parent), ui(new Ui::WorldListPage) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide(); + m_inst = inst; + m_worlds = worlds; + m_id = id; + m_displayName = displayName; + m_iconName = iconName; + m_helpName = helpPage; + ui->worldTreeView->setModel(m_worlds.get()); + ui->worldTreeView->installEventFilter(this); + auto smodel = ui->worldTreeView->selectionModel(); + connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + SLOT(modCurrent(QModelIndex, QModelIndex))); +} + +void WorldListPage::opened() +{ + m_worlds->startWatching(); +} + +void WorldListPage::closed() +{ + m_worlds->stopWatching(); +} + +WorldListPage::~WorldListPage() +{ + m_worlds->stopWatching(); + delete ui; +} + +bool WorldListPage::shouldDisplay() const +{ + if (m_inst) + return !m_inst->isRunning(); + return true; +} + +bool WorldListPage::worldListFilter(QKeyEvent *keyEvent) +{ + switch (keyEvent->key()) + { + case Qt::Key_Delete: + on_rmWorldBtn_clicked(); + return true; + default: + break; + } + return QWidget::eventFilter(ui->worldTreeView, keyEvent); +} + +bool WorldListPage::eventFilter(QObject *obj, QEvent *ev) +{ + if (ev->type() != QEvent::KeyPress) + { + return QWidget::eventFilter(obj, ev); + } + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); + if (obj == ui->worldTreeView) + return worldListFilter(keyEvent); + return QWidget::eventFilter(obj, ev); +} +void WorldListPage::on_rmWorldBtn_clicked() +{ + int first, last; + auto list = ui->worldTreeView->selectionModel()->selectedRows(); + + if (!lastfirst(list, first, last)) + return; + m_worlds->stopWatching(); + m_worlds->deleteWorlds(first, last); + m_worlds->startWatching(); +} + +void WorldListPage::on_viewFolderBtn_clicked() +{ + openDirInDefaultProgram(m_worlds->dir().absolutePath(), true); +} diff --git a/application/pages/WorldListPage.h b/application/pages/WorldListPage.h new file mode 100644 index 00000000..f55f2999 --- /dev/null +++ b/application/pages/WorldListPage.h @@ -0,0 +1,69 @@ +// +// Created by robotbrain on 8/18/15. +// + +#pragma once + +#include <QWidget> + +#include "minecraft/OneSixInstance.h" +#include "BasePage.h" +#include <MultiMC.h> +#include <pathutils.h> + +class WorldList; +namespace Ui +{ +class WorldListPage; +} + +class WorldListPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit WorldListPage(BaseInstance *inst, std::shared_ptr<WorldList> worlds, QString id, + QString iconName, QString displayName, QString helpPage = "", + QWidget *parent = 0); + virtual ~WorldListPage(); + + virtual QString displayName() const override + { + return m_displayName; + } + virtual QIcon icon() const override + { + return MMC->getThemedIcon(m_iconName); + } + virtual QString id() const override + { + return m_id; + } + virtual QString helpPage() const override + { + return m_helpName; + } + virtual bool shouldDisplay() const; + + virtual void opened(); + virtual void closed(); + +protected: + bool eventFilter(QObject *obj, QEvent *ev); + bool worldListFilter(QKeyEvent *ev); + +protected: + BaseInstance *m_inst; + +private: + Ui::WorldListPage *ui; + std::shared_ptr<WorldList> m_worlds; + QString m_iconName; + QString m_id; + QString m_displayName; + QString m_helpName; + +private slots: + void on_rmWorldBtn_clicked(); + void on_viewFolderBtn_clicked(); +}; diff --git a/application/pages/WorldListPage.ui b/application/pages/WorldListPage.ui new file mode 100644 index 00000000..b8100acd --- /dev/null +++ b/application/pages/WorldListPage.ui @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>WorldListPage</class> + <widget class="QWidget" name="WorldListPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>723</width> + <height>532</height> + </rect> + </property> + <property name="windowTitle"> + <string>Mods</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>Tab 1</string> + </attribute> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QTreeView" name="worldTreeView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="dragDropMode"> + <enum>QAbstractItemView::DropOnly</enum> + </property> + </widget> + </item> + <item row="0" column="1"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QPushButton" name="rmWorldBtn"> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="viewFolderBtn"> + <property name="text"> + <string>&View Folder</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/logic/CMakeLists.txt b/logic/CMakeLists.txt index 1f6b62bf..df2aea28 100644 --- a/logic/CMakeLists.txt +++ b/logic/CMakeLists.txt @@ -199,6 +199,10 @@ set(LOGIC_SOURCES minecraft/Mod.cpp minecraft/ModList.h minecraft/ModList.cpp + minecraft/World.h + minecraft/World.cpp + minecraft/WorldList.h + minecraft/WorldList.cpp # FTB ftb/OneSixFTBInstance.h diff --git a/logic/minecraft/LegacyInstance.cpp b/logic/minecraft/LegacyInstance.cpp index 9dd50c80..ff345033 100644 --- a/logic/minecraft/LegacyInstance.cpp +++ b/logic/minecraft/LegacyInstance.cpp @@ -33,6 +33,7 @@ #include <launch/steps/TextPrint.h> #include <launch/steps/CheckJava.h> #include "minecraft/ModList.h" +#include "minecraft/WorldList.h" #include <MMCZip.h> LegacyInstance::LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir) @@ -319,6 +320,16 @@ std::shared_ptr<ModList> LegacyInstance::texturePackList() const return texture_pack_list; } +std::shared_ptr<WorldList> LegacyInstance::worldList() const +{ + if (!m_world_list) + { + m_world_list.reset(new WorldList(savesDir())); + } + m_world_list->update(); + return m_world_list; +} + QString LegacyInstance::jarModsDir() const { return PathCombine(instanceRoot(), "instMods"); diff --git a/logic/minecraft/LegacyInstance.h b/logic/minecraft/LegacyInstance.h index 8663daba..724fcd33 100644 --- a/logic/minecraft/LegacyInstance.h +++ b/logic/minecraft/LegacyInstance.h @@ -49,6 +49,7 @@ public: std::shared_ptr<ModList> coreModList() const; std::shared_ptr<ModList> loaderModList() const; std::shared_ptr<ModList> texturePackList() const override; + std::shared_ptr<WorldList> worldList() const override; ////// Directories ////// QString libDir() const; @@ -126,6 +127,7 @@ protected: mutable std::shared_ptr<ModList> core_mod_list; mutable std::shared_ptr<ModList> loader_mod_list; mutable std::shared_ptr<ModList> texture_pack_list; + mutable std::shared_ptr<WorldList> m_world_list; std::shared_ptr<Setting> m_lwjglFolderSetting; protected slots: diff --git a/logic/minecraft/MinecraftInstance.h b/logic/minecraft/MinecraftInstance.h index b3af2fe8..8c6838e7 100644 --- a/logic/minecraft/MinecraftInstance.h +++ b/logic/minecraft/MinecraftInstance.h @@ -6,6 +6,7 @@ #include "multimc_logic_export.h" class ModList; +class WorldList; class MULTIMC_LOGIC_EXPORT MinecraftInstance: public BaseInstance { @@ -25,6 +26,10 @@ public: { return nullptr; } + virtual std::shared_ptr<WorldList> worldList() const + { + return nullptr; + } /// get all jar mods applicable to this instance's jar virtual QList<Mod> getJarMods() const { diff --git a/logic/minecraft/OneSixInstance.cpp b/logic/minecraft/OneSixInstance.cpp index 57fa0a68..b0fab8af 100644 --- a/logic/minecraft/OneSixInstance.cpp +++ b/logic/minecraft/OneSixInstance.cpp @@ -35,6 +35,7 @@ #include "minecraft/AssetsUtils.h" #include "icons/IconList.h" +#include "minecraft/WorldList.h" OneSixInstance::OneSixInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir) : MinecraftInstance(globalSettings, settings, rootDir) @@ -392,6 +393,16 @@ std::shared_ptr<ModList> OneSixInstance::texturePackList() const return m_texture_pack_list; } +std::shared_ptr<WorldList> OneSixInstance::worldList() const +{ + if (!m_world_list) + { + m_world_list.reset(new WorldList(worldDir())); + } + m_world_list->update(); + return m_world_list; +} + bool OneSixInstance::setIntendedVersionId(QString version) { settings()->set("IntendedVersion", version); @@ -556,6 +567,11 @@ QString OneSixInstance::libDir() const return PathCombine(minecraftRoot(), "lib"); } +QString OneSixInstance::worldDir() const +{ + return PathCombine(minecraftRoot(), "saves"); +} + QStringList OneSixInstance::extraArguments() const { auto list = BaseInstance::extraArguments(); diff --git a/logic/minecraft/OneSixInstance.h b/logic/minecraft/OneSixInstance.h index 963bd152..68be1d4d 100644 --- a/logic/minecraft/OneSixInstance.h +++ b/logic/minecraft/OneSixInstance.h @@ -36,6 +36,7 @@ public: std::shared_ptr<ModList> coreModList() const; std::shared_ptr<ModList> resourcePackList() const override; std::shared_ptr<ModList> texturePackList() const override; + std::shared_ptr<WorldList> worldList() const override; virtual QList<Mod> getJarMods() const override; virtual void createProfile(); @@ -48,6 +49,7 @@ public: QString loaderModsDir() const; QString coreModsDir() const; QString libDir() const; + QString worldDir() const; virtual QString instanceConfigFolder() const override; virtual std::shared_ptr<Task> createUpdateTask() override; @@ -102,6 +104,7 @@ protected: mutable std::shared_ptr<ModList> m_core_mod_list; mutable std::shared_ptr<ModList> m_resource_pack_list; mutable std::shared_ptr<ModList> m_texture_pack_list; + mutable std::shared_ptr<WorldList> m_world_list; }; Q_DECLARE_METATYPE(std::shared_ptr<OneSixInstance>) diff --git a/logic/minecraft/World.cpp b/logic/minecraft/World.cpp new file mode 100644 index 00000000..0f7e0db1 --- /dev/null +++ b/logic/minecraft/World.cpp @@ -0,0 +1,72 @@ +/* Copyright 2013-2015 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QDir> +#include <QString> +#include "World.h" +#include <pathutils.h> + +World::World(const QFileInfo &file) +{ + repath(file); +} + +void World::repath(const QFileInfo &file) +{ + m_file = file; + m_name = file.fileName(); + is_valid = file.isDir() && QDir(file.filePath()).exists("level.dat"); +} + +bool World::replace(World &with) +{ + if (!destroy()) + return false; + bool success = copyPath(with.m_file.filePath(), m_file.path()); + if (success) + { + m_name = with.m_name; + m_file.refresh(); + } + return success; +} + +bool World::destroy() +{ + if(!is_valid) return false; + if (m_file.isDir()) + { + QDir d(m_file.filePath()); + if (d.removeRecursively()) + { + return true; + } + return false; + } + else + { + return false; + } + return true; +} + +bool World::operator==(const World &other) const +{ + return is_valid == other.is_valid && name() == other.name(); +} +bool World::strongCompare(const World &other) const +{ + return is_valid == other.is_valid && name() == other.name(); +} diff --git a/logic/minecraft/World.h b/logic/minecraft/World.h new file mode 100644 index 00000000..d00062e7 --- /dev/null +++ b/logic/minecraft/World.h @@ -0,0 +1,47 @@ +/* Copyright 2013-2015 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include <QFileInfo> + +class World +{ +public: + World(const QFileInfo &file); + QString name() const + { + return m_name; + } + bool isValid() const + { + return is_valid; + } + // delete all the files of this mod + bool destroy(); + // replace this mod with a copy of the other + bool replace(World &with); + // change the mod's filesystem path (used by mod lists for *MAGIC* purposes) + void repath(const QFileInfo &file); + + // WEAK compare operator - used for replacing mods + bool operator==(const World &other) const; + bool strongCompare(const World &other) const; + +protected: + + QFileInfo m_file; + QString m_name; + bool is_valid; +}; diff --git a/logic/minecraft/WorldList.cpp b/logic/minecraft/WorldList.cpp new file mode 100644 index 00000000..ae0077e9 --- /dev/null +++ b/logic/minecraft/WorldList.cpp @@ -0,0 +1,226 @@ +/* Copyright 2013-2015 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WorldList.h" +#include <pathutils.h> +#include <QMimeData> +#include <QUrl> +#include <QUuid> +#include <QString> +#include <QFileSystemWatcher> +#include <QDebug> + +WorldList::WorldList(const QString &dir) + : QAbstractListModel(), m_dir(dir) +{ + ensureFolderPathExists(m_dir.absolutePath()); + m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs | + QDir::NoSymLinks); + m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware); + m_watcher = new QFileSystemWatcher(this); + is_watching = false; + connect(m_watcher, SIGNAL(directoryChanged(QString)), this, + SLOT(directoryChanged(QString))); +} + +void WorldList::startWatching() +{ + update(); + is_watching = m_watcher->addPath(m_dir.absolutePath()); + if (is_watching) + { + qDebug() << "Started watching " << m_dir.absolutePath(); + } + else + { + qDebug() << "Failed to start watching " << m_dir.absolutePath(); + } +} + +void WorldList::stopWatching() +{ + is_watching = !m_watcher->removePath(m_dir.absolutePath()); + if (!is_watching) + { + qDebug() << "Stopped watching " << m_dir.absolutePath(); + } + else + { + qDebug() << "Failed to stop watching " << m_dir.absolutePath(); + } +} + +void WorldList::internalSort(QList<World> &what) +{ + auto predicate = [](const World &left, const World &right) + { + return left.name().localeAwareCompare(right.name()) < 0; + }; + std::sort(what.begin(), what.end(), predicate); +} + +bool WorldList::update() +{ + if (!isValid()) + return false; + + QList<World> orderedWorlds; + QList<World> newWorlds; + m_dir.refresh(); + auto folderContents = m_dir.entryInfoList(); + // if there are any untracked files... + if (folderContents.size()) + { + // the order surely changed! + for (auto entry : folderContents) + { + World w(entry); + if(w.isValid()) { + newWorlds.append(w); + } + } + internalSort(newWorlds); + orderedWorlds.append(newWorlds); + } + beginResetModel(); + worlds.swap(orderedWorlds); + endResetModel(); + return true; +} + +void WorldList::directoryChanged(QString path) +{ + update(); +} + +bool WorldList::isValid() +{ + return m_dir.exists() && m_dir.isReadable(); +} + +bool WorldList::deleteWorld(int index) +{ + if (index >= worlds.size() || index < 0) + return false; + World &m = worlds[index]; + if (m.destroy()) + { + beginRemoveRows(QModelIndex(), index, index); + worlds.removeAt(index); + endRemoveRows(); + emit changed(); + return true; + } + return false; +} + +bool WorldList::deleteWorlds(int first, int last) +{ + for (int i = first; i <= last; i++) + { + World &m = worlds[i]; + m.destroy(); + } + beginRemoveRows(QModelIndex(), first, last); + worlds.erase(worlds.begin() + first, worlds.begin() + last + 1); + endRemoveRows(); + emit changed(); + return true; +} + +int WorldList::columnCount(const QModelIndex &parent) const +{ + return 1; +} + +QVariant WorldList::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + int row = index.row(); + int column = index.column(); + + if (row < 0 || row >= worlds.size()) + return QVariant(); + + switch (role) + { + case Qt::DisplayRole: + switch (column) + { + case NameColumn: + return worlds[row].name(); + + default: + return QVariant(); + } + + case Qt::ToolTipRole: + return worlds[row].name(); + default: + return QVariant(); + } +} + +QVariant WorldList::headerData(int section, Qt::Orientation orientation, int role) const +{ + switch (role) + { + case Qt::DisplayRole: + switch (section) + { + case NameColumn: + return tr("Name"); + default: + return QVariant(); + } + + case Qt::ToolTipRole: + switch (section) + { + case NameColumn: + return tr("The name of the world."); + default: + return QVariant(); + } + default: + return QVariant(); + } + return QVariant(); +} + +QStringList WorldList::mimeTypes() const +{ + QStringList types; + types << "text/plain"; + return types; +} + +QMimeData *WorldList::mimeData(const QModelIndexList &indexes) const +{ + QMimeData *data = new QMimeData(); + + if (indexes.size() == 0) + return data; + + auto idx = indexes[0]; + int row = idx.row(); + if (row < 0 || row >= worlds.size()) + return data; + + data->setText(QString::number(row)); + return data; +} diff --git a/logic/minecraft/WorldList.h b/logic/minecraft/WorldList.h new file mode 100644 index 00000000..3f337c72 --- /dev/null +++ b/logic/minecraft/WorldList.h @@ -0,0 +1,101 @@ +/* + * Copyright 2015 <copyright holder> <email> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include <QList> +#include <QString> +#include <QDir> +#include <QAbstractListModel> +#include "minecraft/World.h" + +class QFileSystemWatcher; + +class WorldList : public QAbstractListModel +{ + Q_OBJECT +public: + enum Columns { + NameColumn + }; + + WorldList ( const QString &dir ); + + virtual QVariant data ( const QModelIndex &index, int role = Qt::DisplayRole ) const; + + virtual int rowCount ( const QModelIndex &parent = QModelIndex() ) const { + return size(); + } + ; + virtual QVariant headerData ( int section, Qt::Orientation orientation, + int role = Qt::DisplayRole ) const; + virtual int columnCount ( const QModelIndex &parent ) const; + + size_t size() const { + return worlds.size(); + } + ; + bool empty() const { + return size() == 0; + } + World &operator[] ( size_t index ) { + return worlds[index]; + } + + /// Reloads the mod list and returns true if the list changed. + virtual bool update(); + + /// Deletes the mod at the given index. + virtual bool deleteWorld ( int index ); + + /// Deletes all the selected mods + virtual bool deleteWorlds ( int first, int last ); + + /// get data for drag action + virtual QMimeData *mimeData ( const QModelIndexList &indexes ) const; + /// get the supported mime types + virtual QStringList mimeTypes() const; + + void startWatching(); + void stopWatching(); + + virtual bool isValid(); + + QDir dir() { + return m_dir; + } + + const QList<World> & allWorlds() { + return worlds; + } + +private: + void internalSort ( QList<World> & what ); + private +slots: + void directoryChanged ( QString path ); + +signals: + void changed(); + +protected: + QFileSystemWatcher *m_watcher; + bool is_watching; + QDir m_dir; + QList<World> worlds; +}; + |