/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see .
*/
#ifndef PROFILE_H
#define PROFILE_H
#include "modinfo.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace MOBase { class IPluginGame; }
/**
* @brief represents a profile
**/
class Profile : public QObject, public MOBase::IProfile
{
Q_OBJECT
public:
typedef boost::shared_ptr Ptr;
public:
/**
* @brief constructor
*
* This constructor is used to create a new profile so it is to be assumed a profile
* by this name does not yet exist
* @param name name of the new profile
* @param filter save game filter. Defaults to <no filter>.
**/
Profile(const QString &name, MOBase::IPluginGame const *gamePlugin, bool useDefaultSettings);
/**
* @brief constructor
*
* This constructor is used to open an existing profile though it will also try to repair
* the profile if important files are missing (including the directory itself) so technically,
* invoking this should always produce a working profile
* @param directory directory to read the profile from
**/
Profile(const QDir &directory, MOBase::IPluginGame const *gamePlugin);
Profile(const Profile &reference);
~Profile();
/**
* @return true if this profile (still) exists on disc
*/
bool exists() const;
/**
* @param name of the new profile
* @param reference profile to copy from
**/
static Profile *createPtrFrom(const QString &name, const Profile &reference, MOBase::IPluginGame const *gamePlugin);
static void renameModInAllProfiles(const QString& oldName, const QString& newName);
void writeModlist();
void writeModlistNow(bool onlyIfPending=false);
void cancelModlistWrite();
/**
* @brief test if this profile uses archive invalidation
*
* @param supported if this is not null, the parameter will be set to false if invalidation is not supported in this profile
* @return true if archive invalidation is active
* @note currently, invalidation is not supported if the relevant entry in the ini file does not exist
**/
bool invalidationActive(bool *supported) const;
/**
* @brief deactivate archive invalidation if it was active
**/
void deactivateInvalidation();
/**
* @brief activate archive invalidation
**/
void activateInvalidation();
/**
* @return true if this profile uses local save games
*/
virtual bool localSavesEnabled() const override;
/**
* @brief enables or disables the use of local save games for this profile
* when disabling the user will be asked if he wants to remove the save games
* in the profile
* @param enable if true, local saves are enabled, otherewise they are disabled
*/
bool enableLocalSaves(bool enable);
/**
* @return true if this profile uses local ini files
*/
virtual bool localSettingsEnabled() const override;
/**
* @brief enables or disables the use of local ini files for this profile
* disabling this does not delete existing ini files but the global ones will be used
* @param enable
*/
bool enableLocalSettings(bool enable);
/**
* @return name of the profile (this is identical to its directory name)
**/
virtual QString name() const override { return m_Directory.dirName(); }
/**
* @return the path of the plugins file in this profile
* @todo is this required? can the functionality using this function be moved to the Profile-class?
**/
QString getPluginsFileName() const;
/**
* @return the path of the loadorder file in this profile
**/
QString getLoadOrderFileName() const;
/**
* @return the path of the file containing locked mod indices
*/
QString getLockedOrderFileName() const;
/**
* @return the path of the modlist file in this profile
*/
QString getModlistFileName() const;
/**
* @return path of the archives file in this profile
*/
QString getArchivesFileName() const;
/**
* @return the path of the delete file in this profile
* @note the deleter file lists plugins that should be hidden from the game and other tools
**/
QString getDeleterFileName() const;
/**
* @return the path of the ini file in this profile
* @todo since the game can contain multiple ini files (i.e. skyrim.ini skyrimprefs.ini)
* the concept of this function is somewhat broken
**/
QString getIniFileName() const;
/**
* @return the path of the tweak ini in this profile
*/
QString getProfileTweaks() const;
/**
* @return path to this profile
**/
virtual QString absolutePath() const override;
/**
* @return path to this profile's save games
**/
QString savePath() const;
/**
* @brief rename profile
* @param newName new name of profile
*/
void rename(const QString &newName);
/**
* @brief create the ini file to be used by the game
*
* the tweaked ini file constructed by this file is a merger
* of the game-ini of this profile with ini tweaks applied */
void createTweakedIniFile();
/**
* @brief re-read the modlist.txt and update the mod status from it
**/
void refreshModStatus();
/**
* @brief retrieve a list of mods that are enabled in this profile
*
* @return list of active mods sorted by priority (ascending). "first" is the mod name, "second" is its path
**/
std::vector > getActiveMods();
/**
* retrieve the number of mods for which this object has status information.
* This is usually the same as ModInfo::getNumMods() except between
* calls to ModInfo::updateFromDisc() and the Profile::refreshModStatus()
*
* @return number of mods for which the profile has status information
**/
size_t numMods() const { return m_ModStatus.size(); }
/**
* @return the number of mods that can be enabled and where the priority can be modified
*/
unsigned int numRegularMods() const { return m_NumRegularMods; }
/**
* @brief retrieve the mod index based on the priority
*
* @param priority priority to look up
* @return the index of the mod
* @throw std::exception an exception is thrown if there is no mod with the specified priority
**/
unsigned int modIndexByPriority(unsigned int priority) const;
/**
* @brief enable or disable a mod
*
* @param index index of the mod to enable/disable
* @param enabled true if the mod is to be enabled, false if it is to be disabled
**/
void setModEnabled(unsigned int index, bool enabled);
/**
* change the priority of a mod. Of course this also changes the priority of other mods.
* The priority of the mods in the range ]old, new priority] are shifted so that no gaps
* are possible.
*
* @param index index of the mod to change
* @param newPriority the new priority value
*
* @todo what happens if the new priority is outside the range?
**/
void setModPriority(unsigned int index, int &newPriority);
/**
* @brief determine if a mod is enabled
*
* @param index index of the mod to look up
* @return true if the mod is enabled, false otherwise
**/
bool modEnabled(unsigned int index) const;
/**
* @brief query the priority of a mod
*
* @param index index of the mod to look up
* @return priority of the specified mod
**/
int getModPriority(unsigned int index) const;
void dumpModStatus() const;
QVariant setting(const QString §ion, const QString &name,
const QVariant &fallback = QVariant());
void storeSetting(const QString §ion, const QString &name,
const QVariant &value);
void removeSetting(const QString §ion, const QString &name);
signals:
/**
* @brief emitted whenever the status (enabled/disabled) of a mod changed
*
* @param index index of the mod that changed
**/
void modStatusChanged(unsigned int index);
public slots:
// should only be called by DelayedFileWriter, use writeModlist() and writeModlistNow() instead
void doWriteModlist();
private:
class ModStatus {
friend class Profile;
public:
ModStatus() : m_Overwrite(false), m_Enabled(false), m_Priority(-1) {}
private:
bool m_Overwrite;
bool m_Enabled;
int m_Priority;
};
private:
Profile& operator=(const Profile &reference); // not implemented
void initTimer();
void updateIndices();
void copyFilesTo(QString &target) const;
std::vector splitDZString(const wchar_t *buffer) const;
void mergeTweak(const QString &tweakName, const QString &tweakedIni) const;
void mergeTweaks(ModInfo::Ptr modInfo, const QString &tweakedIni) const;
void touchFile(QString fileName);
void finishChangeStatus() const;
static void renameModInList(QFile &modList, const QString &oldName, const QString &newName);
private:
QDir m_Directory;
QSettings *m_Settings;
const MOBase::IPluginGame *m_GamePlugin;
mutable QByteArray m_LastModlistHash;
std::vector m_ModStatus;
std::vector m_ModIndexByPriority;
unsigned int m_NumRegularMods;
MOBase::DelayedFileWriter m_ModListWriter;
};
#endif // PROFILE_H