From d884f849d60db44f05a6a6b22f4ffcf520900389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 25 Aug 2013 01:32:42 +0200 Subject: All kinds of incremental improvements Redone the instance action toolbar: * Removed all the dead actions * Change icon and Rename are now morphed into a header * Added button for opening the config folder Implemented support for loose files and folders as legacy jar mods Added texture pack support --- logic/BaseInstance.h | 8 ++ logic/LegacyInstance.cpp | 36 +++++ logic/LegacyInstance.h | 6 + logic/LegacyInstance_p.h | 1 + logic/LegacyUpdate.cpp | 51 ++++--- logic/ModList.cpp | 342 +++++--------------------------------------- logic/ModList.h | 10 +- logic/NostalgiaInstance.cpp | 6 + logic/NostalgiaInstance.h | 1 + logic/OneSixInstance.cpp | 19 +++ logic/OneSixInstance.h | 5 + 11 files changed, 158 insertions(+), 327 deletions(-) (limited to 'logic') diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index 48481e26..13ed169f 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -149,6 +149,14 @@ public: /// create a mod edit dialog for the instance virtual QDialog * createModEditDialog ( QWidget* parent ) = 0; + + /// is a particular action enabled with this instance selected? + virtual bool menuActionEnabled(QString action_name) const = 0; + + virtual QString getStatusbarDescription() = 0; + + /// FIXME: this really should be elsewhere... + virtual QString instanceConfigFolder() const = 0; signals: /*! * \brief Signal emitted when properties relevant to the instance view change diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 9e191740..dce1d2f3 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -127,6 +127,19 @@ QSharedPointer< ModList > LegacyInstance::loaderModList() return d->loader_mod_list; } +QSharedPointer< ModList > LegacyInstance::texturePackList() +{ + I_D(LegacyInstance); + if(!d->texture_pack_list) + { + d->texture_pack_list.reset(new ModList(texturePackDir())); + } + else + d->texture_pack_list->update(); + return d->texture_pack_list; +} + + QDialog * LegacyInstance::createModEditDialog ( QWidget* parent ) { return new LegacyModEditDialog(this, parent); @@ -168,6 +181,10 @@ QString LegacyInstance::resourceDir() const { return PathCombine(minecraftRoot(), "resources"); } +QString LegacyInstance::texturePackDir() const +{ + return PathCombine(minecraftRoot(), "texturepacks"); +} QString LegacyInstance::runnableJar() const { @@ -178,6 +195,13 @@ QString LegacyInstance::modListFile() const { return PathCombine(instanceRoot(), "modlist"); } + +QString LegacyInstance::instanceConfigFolder() const +{ + return PathCombine(minecraftRoot(), "config"); +} + + /* bool LegacyInstance::shouldUpdateCurrentVersion() const { @@ -285,3 +309,15 @@ QString LegacyInstance::defaultCustomBaseJar() const return PathCombine(binDir(), "mcbackup.jar"); } +bool LegacyInstance::menuActionEnabled ( QString action_name ) const +{ + return true; +} + +QString LegacyInstance::getStatusbarDescription() +{ + if(shouldUpdate()) + return "Legacy : " + currentVersionId() + " -> " + intendedVersionId(); + else + return "Legacy : " + currentVersionId(); +} diff --git a/logic/LegacyInstance.h b/logic/LegacyInstance.h index 46c531d9..97502945 100644 --- a/logic/LegacyInstance.h +++ b/logic/LegacyInstance.h @@ -22,14 +22,17 @@ public: QSharedPointer jarModList(); QSharedPointer coreModList(); QSharedPointer loaderModList(); + QSharedPointer texturePackList(); ////// Directories ////// QString savesDir() const; + QString texturePackDir() const; QString jarModsDir() const; QString binDir() const; QString mlModsDir() const; QString coreModsDir() const; QString resourceDir() const; + virtual QString instanceConfigFolder() const; /*! * Whether or not the instance's minecraft.jar needs to be rebuilt. @@ -61,6 +64,9 @@ public: virtual QString defaultBaseJar() const; virtual QString defaultCustomBaseJar() const; + bool menuActionEnabled ( QString action_name ) const; + virtual QString getStatusbarDescription(); + protected slots: virtual void jarModsChanged(); }; \ No newline at end of file diff --git a/logic/LegacyInstance_p.h b/logic/LegacyInstance_p.h index a1d195b4..d1f417fe 100644 --- a/logic/LegacyInstance_p.h +++ b/logic/LegacyInstance_p.h @@ -12,4 +12,5 @@ struct LegacyInstancePrivate: public BaseInstancePrivate QSharedPointer jar_mod_list; QSharedPointer core_mod_list; QSharedPointer loader_mod_list; + QSharedPointer texture_pack_list; }; \ No newline at end of file diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index 9644cb80..0dc8ee72 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -271,7 +271,15 @@ bool LegacyUpdate::MergeZipFiles( QuaZip* into, QFileInfo from, QSet< QString >& { return false; } - if(!zipOutFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileInsideMod.getActualFileName()))) + /* + QuaZipFileInfo old_info; + fileInsideMod.getFileInfo(&old_info); + */ + QuaZipNewInfo info_out(fileInsideMod.getActualFileName()); + /* + info_out.externalAttr = old_info.externalAttr; + */ + if(!zipOutFile.open(QIODevice::WriteOnly, info_out)) { fileInsideMod.close(); return false; @@ -369,31 +377,32 @@ void LegacyUpdate::ModTheJar() } else if (mod.type() == Mod::MOD_SINGLEFILE) { - zipOut.close(); - QFile::remove(runnableJar.filePath()); - emitFailed("Loose files are NOT supported as jar mods."); - return; - /* - wxFileName destFileName = modFileName; - destFileName.MakeRelativeTo(m_inst->GetInstModsDir().GetFullPath()); - wxString destFile = destFileName.GetFullPath(); - - if (addedFiles.count(destFile) == 0) + auto filename = mod.filename(); + if(!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName())) { - wxFFileInputStream input(modFileName.GetFullPath()); - zipOut.PutNextEntry(destFile); - zipOut.Write(input); - - addedFiles.insert(destFile); + zipOut.close(); + QFile::remove(runnableJar.filePath()); + emitFailed("Failed to add " + filename.fileName() + " to the jar"); + return; } - */ + addedFiles.insert(filename.fileName()); + qDebug() << "Adding file " << filename.fileName() << " from " << filename.absoluteFilePath(); } else if (mod.type() == Mod::MOD_FOLDER) { - zipOut.close(); - QFile::remove(runnableJar.filePath()); - emitFailed("Folders are NOT supported as jar mods."); - return; + auto filename = mod.filename(); + QString what_to_zip = filename.absoluteFilePath(); + QDir dir(what_to_zip); + dir.cdUp(); + QString parent_dir = dir.absolutePath(); + if(!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, true, addedFiles)) + { + zipOut.close(); + QFile::remove(runnableJar.filePath()); + emitFailed("Failed to add " + filename.fileName() + " to the jar"); + return; + } + qDebug() << "Adding folder " << filename.fileName() << " from " << filename.absoluteFilePath(); } } diff --git a/logic/ModList.cpp b/logic/ModList.cpp index c3f3ced3..84511e4c 100644 --- a/logic/ModList.cpp +++ b/logic/ModList.cpp @@ -21,6 +21,7 @@ #include #include #include +#include ModList::ModList ( const QString& dir, const QString& list_file ) : QAbstractListModel(), m_dir(dir), m_list_file(list_file) @@ -28,9 +29,31 @@ ModList::ModList ( const QString& dir, const QString& list_file ) m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs | QDir::NoSymLinks); m_dir.setSorting(QDir::Name); m_list_id = QUuid::createUuid().toString(); + m_watcher = new QFileSystemWatcher(this); + is_watching = false; + connect(m_watcher,SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString))); update(); } +void ModList::startWatching() +{ + 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 ModList::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(); +} + + bool ModList::update() { if (!isValid()) @@ -88,6 +111,12 @@ bool ModList::update() return true; } +void ModList::directoryChanged ( QString path ) +{ + update(); +} + + QStringList ModList::readListFile() { QStringList stringList; @@ -333,11 +362,11 @@ QVariant ModList::headerData ( int section, Qt::Orientation orientation, int rol switch (section) { case 0: - return QString("Mod Name"); + return QString("Name"); case 1: - return QString("Mod Version"); + return QString("Version"); case 2: - return QString("MC Version"); + return QString("Minecraft"); } } @@ -412,6 +441,9 @@ bool ModList::dropMimeData ( const QMimeData* data, Qt::DropAction action, int r // files dropped from outside? if(data->hasUrls()) { + bool was_watching = is_watching; + if(was_watching) + stopWatching(); auto urls = data->urls(); for(auto url: urls) { @@ -422,6 +454,8 @@ bool ModList::dropMimeData ( const QMimeData* data, Qt::DropAction action, int r installMod(filename, row); qDebug() << "installing: " << filename; } + if(was_watching) + startWatching(); return true; } else if(data->hasText()) @@ -446,305 +480,3 @@ bool ModList::dropMimeData ( const QMimeData* data, Qt::DropAction action, int r return false; } - -/* -ModList::ModList(const QString &dir) - : modsFolder(dir) -{ - -} - -bool ModList::update(bool quickLoad) -{ - bool listChanged = false; - - // Check for mods in the list whose files do not exist and remove them from the list. - // If doing a quickLoad, erase the whole list. - for (size_t i = 0; i < size(); i++) - { - if (quickLoad || !at(i).GetFileName().FileExists()) - { - erase(begin() + i); - i--; - listChanged = true; - } - } - - // Add any mods in the mods folder that aren't already in the list. - if (LoadModListFromDir(QString(), quickLoad)) - listChanged = true; - - return listChanged; -} - -bool ModList::LoadModListFromDir(const QString& loadFrom, bool quickLoad) -{ - QString dir(loadFrom.isEmpty() ? modsFolder : loadFrom); - - QDir modDir(dir); - if (!modDir.exists()) - return false; - - bool listChanged = false; - - auto list = modDir.entryInfoList(QDir::Readable|QDir::NoDotAndDotDot, QDir::Name); - for(auto currentFile: list) - { - if (currentFile.isFile()) - { - if (quickLoad || FindByFilename(currentFile.absoluteFilePath()) == nullptr) - { - Mod mod(currentFile.absoluteFilePath()); - push_back(mod); - listChanged = true; - } - } - else if (currentFile.isDir()) - { - if (LoadModListFromDir(currentFile.absoluteFilePath())) - listChanged = true; - } - } - - return listChanged; -} - -Mod *ModList::FindByFilename(const QString& filename) -{ - // Search the list for a mod with the given filename. - for (auto iter = begin(); iter != end(); ++iter) - { - if (iter->GetFileName() == QFileInfo(filename)) - return &(*iter); - } - - // If nothing is found, return nullptr. - return nullptr; -} - -int ModList::FindIndexByFilename(const QString& filename) -{ - // Search the list for a mod with the given filename. - int i = 0; - for (auto iter = begin(); iter != end(); ++iter, i++) - { - if (iter->GetFileName() == QFileInfo(filename)) - return i; - } - - // If nothing is found, return nullptr. - return -1; -} - -Mod* ModList::FindByID(const QString& modID, const QString& modVersion) -{ - // Search the list for a mod that matches - for (auto iter = begin(); iter != end(); ++iter) - { - QString ID = iter->GetModID(); - QString version = iter->GetModVersion(); - if ( ID == modID && version == modVersion) - return &(*iter); - } - - // If nothing is found, return nullptr. - return nullptr; -} - -void ModList::LoadFromFile(const QString& file) -{ - if (!wxFileExists(file)) - return; - - wxFFileInputStream inputStream(file); - wxArrayString modListFile = ReadAllLines(inputStream); - - for (wxArrayString::iterator iter = modListFile.begin(); iter != modListFile.end(); iter++) - { - // Normalize the path to the instMods dir. - wxFileName modFile(*iter); - modFile.Normalize(wxPATH_NORM_ALL, modsFolder); - modFile.MakeRelativeTo(); - // if the file is gone, do not load it - if(!modFile.Exists()) - { - continue; - } - - if (FindByFilename(modFile.GetFullPath()) == nullptr) - { - push_back(Mod(modFile)); - } - } -} - -void ModList::SaveToFile(const QString& file) -{ - QString text; - for (iterator iter = begin(); iter != end(); ++iter) - { - wxFileName modFile = iter->GetFileName(); - modFile.MakeRelativeTo(modsFolder); - text.append(modFile.GetFullPath()); - text.append("\n"); - } - - wxTempFileOutputStream out(file); - WriteAllText(out, text); - out.Commit(); -} - -bool ModList::InsertMod(size_t index, const QString &filename, const QString& saveToFile) -{ - QFileInfo source(filename); - QFileInfo dest(PathCombine(modsFolder, source.fileName())); - - if (source != dest) - { - QFile::copy(source.absoluteFilePath(), dest.absoluteFilePath()); - } - - int oldIndex = FindIndexByFilename(dest.absoluteFilePath()); - - if (oldIndex != -1) - { - erase(begin() + oldIndex); - } - - if (index >= size()) - push_back(Mod(dest)); - else - insert(begin() + index, Mod(dest)); - - if (!saveToFile.isEmpty()) - SaveToFile(saveToFile); - - return true; -} - -bool ModList::DeleteMod(size_t index, const QString& saveToFile) -{ - Mod *mod = &at(index); - if(mod->GetModType() == Mod::MOD_FOLDER) - { - QDir dir(mod->GetFileName().absoluteFilePath()); - if(dir.removeRecursively()) - { - erase(begin() + index); - - if (!saveToFile.isEmpty()) - SaveToFile(saveToFile); - - return true; - } - else - { - // wxLogError(_("Failed to delete mod.")); - } - } - else if (QFile(mod->GetFileName().absoluteFilePath()).remove()) - { - erase(begin() + index); - - if (!saveToFile.isEmpty()) - SaveToFile(saveToFile); - - return true; - } - else - { - // wxLogError(_("Failed to delete mod.")); - } - return false; -} - -bool JarModList::InsertMod(size_t index, const QString &filename, const QString& saveToFile) -{ - QString saveFile = saveToFile; - if (saveToFile.isEmpty()) - saveFile = m_inst->GetModListFile().GetFullPath(); - - if (ModList::InsertMod(index, filename, saveFile)) - { - m_inst->setLWJGLVersion(true); - return true; - } - return false; -} - -bool JarModList::DeleteMod(size_t index, const QString& saveToFile) -{ - QString saveFile = saveToFile; - if (saveToFile.IsEmpty()) - saveFile = m_inst->GetModListFile().GetFullPath(); - - if (ModList::DeleteMod(index, saveFile)) - { - m_inst->SetNeedsRebuild(); - return true; - } - return false; -} - -bool JarModList::UpdateModList(bool quickLoad) -{ - if (ModList::UpdateModList(quickLoad)) - { - m_inst->SetNeedsRebuild(); - return true; - } - return false; -} - -bool FolderModList::LoadModListFromDir(const QString& loadFrom, bool quickLoad) -{ - QString dir(loadFrom.IsEmpty() ? modsFolder : loadFrom); - - if (!wxDirExists(dir)) - return false; - - bool listChanged = false; - wxDir modDir(dir); - - if (!modDir.IsOpened()) - { - wxLogError(_("Failed to open directory: ") + dir); - return false; - } - - QString currentFile; - if (modDir.GetFirst(¤tFile)) - { - do - { - wxFileName modFile(Path::Combine(dir, currentFile)); - - if (wxFileExists(modFile.GetFullPath()) || wxDirExists(modFile.GetFullPath())) - { - if (quickLoad || FindByFilename(modFile.GetFullPath()) == nullptr) - { - Mod mod(modFile.GetFullPath()); - push_back(mod); - listChanged = true; - } - } - } while (modDir.GetNext(¤tFile)); - } - - return listChanged; -} - -bool ModNameSort (const Mod & i,const Mod & j) -{ - if(i.GetModType() == j.GetModType()) - return (i.GetName().toLower() < j.GetName().toLower()); - return (i.GetModType() < j.GetModType()); -} - -bool FolderModList::UpdateModList ( bool quickLoad ) -{ - bool changed = ModList::UpdateModList(quickLoad); - std::sort(begin(),end(),ModNameSort); - return changed; -} -*/ diff --git a/logic/ModList.h b/logic/ModList.h index 61f3d596..5395e9ae 100644 --- a/logic/ModList.h +++ b/logic/ModList.h @@ -15,9 +15,10 @@ class BaseInstance; #include #include #include - #include "Mod.h" +class QFileSystemWatcher; + /** * A legacy mod list. * Backed by a folder. @@ -86,6 +87,9 @@ public: /// what drop actions do we support? virtual Qt::DropActions supportedDropActions() const; + void startWatching(); + void stopWatching(); + virtual bool isValid(); QDir dir() @@ -95,10 +99,14 @@ public: private: QStringList readListFile(); bool saveListFile(); +private slots: + void directoryChanged(QString path); signals: void changed(); protected: + QFileSystemWatcher * m_watcher; + bool is_watching; QDir m_dir; QString m_list_file; QString m_list_id; diff --git a/logic/NostalgiaInstance.cpp b/logic/NostalgiaInstance.cpp index 0a7f3c5a..039cd9ce 100644 --- a/logic/NostalgiaInstance.cpp +++ b/logic/NostalgiaInstance.cpp @@ -6,6 +6,12 @@ NostalgiaInstance::NostalgiaInstance ( const QString& rootDir, SettingsObject* s } +QString NostalgiaInstance::getStatusbarDescription() +{ + return "Nostalgia : " + intendedVersionId(); +} + + /* ADD MORE IF REQUIRED diff --git a/logic/NostalgiaInstance.h b/logic/NostalgiaInstance.h index b8858218..f2df1828 100644 --- a/logic/NostalgiaInstance.h +++ b/logic/NostalgiaInstance.h @@ -7,4 +7,5 @@ class NostalgiaInstance : public OneSixInstance Q_OBJECT public: explicit NostalgiaInstance(const QString &rootDir, SettingsObject * settings, QObject *parent = 0); + virtual QString getStatusbarDescription(); }; diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 2eca7cd7..4cbf17b2 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -226,3 +226,22 @@ QString OneSixInstance::defaultCustomBaseJar() const { return PathCombine(instanceRoot(), "custom.jar"); } + +bool OneSixInstance::menuActionEnabled ( QString action_name ) const +{ + if(action_name == "actionChangeInstLWJGLVersion") + return false; + if(action_name == "actionEditInstMods") + return false; + return true; +} + +QString OneSixInstance::getStatusbarDescription() +{ + return "One Six : " + intendedVersionId(); +} + +QString OneSixInstance::instanceConfigFolder() const +{ + return PathCombine(minecraftRoot(), "config"); +} diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index 654b91dc..7c28b4cc 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -32,6 +32,11 @@ public: virtual QString defaultBaseJar() const; virtual QString defaultCustomBaseJar() const; + + virtual bool menuActionEnabled ( QString action_name ) const; + virtual QString getStatusbarDescription(); + virtual QString instanceConfigFolder() const; + private: QStringList processMinecraftArgs( QString user, QString session ); }; \ No newline at end of file -- cgit v1.2.3