/*
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 MODLIST_H
#define MODLIST_H
#include "categories.h"
#include "moddatacontent.h"
#include "modinfo.h"
#include "nexusinterface.h"
#include "profile.h"
#include
#include
#include
#include
#include
#include
#ifndef Q_MOC_RUN
#include
#endif
#include
#include
#include
class QSortFilterProxyModel;
class PluginContainer;
class OrganizerCore;
class ModListDropInfo;
/**
* Model presenting an overview of the installed mod
* This is used in a view in the main window of MO. It combines general information
*about the mods from ModInfo with status information from the Profile
**/
class ModList : public QAbstractItemModel
{
Q_OBJECT
public:
enum ModListRole
{
// data(GroupingRole) contains the "group" role - This is used by the
// category and Nexus ID grouping proxy (but not the ByPriority proxy)
GroupingRole = Qt::UserRole,
IndexRole = Qt::UserRole + 1,
// data(AggrRole) contains aggregation information (for
// grouping I assume?)
AggrRole = Qt::UserRole + 2,
GameNameRole = Qt::UserRole + 3,
PriorityRole = Qt::UserRole + 4,
// marking role for the scrollbar
ScrollMarkRole = Qt::UserRole + 5,
// this is the first available role
ModUserRole = Qt::UserRole + 6
};
enum EColumn
{
COL_NAME,
COL_CONFLICTFLAGS,
COL_FLAGS,
COL_CONTENT,
COL_CATEGORY,
COL_AUTHOR,
COL_UPLOADER,
COL_MODID,
COL_GAME,
COL_VERSION,
COL_INSTALLTIME,
COL_PRIORITY,
COL_NOTES,
COL_LASTCOLUMN = COL_NOTES,
};
using SignalModInstalled = boost::signals2::signal;
using SignalModRemoved = boost::signals2::signal;
using SignalModStateChanged = boost::signals2::signal&)>;
using SignalModMoved = boost::signals2::signal;
public:
/**
* @brief constructor
* @todo ensure this view works without a profile set, otherwise there are
*intransparent dependencies on the initialisation order
**/
ModList(PluginContainer* pluginContainer, OrganizerCore* parent);
~ModList();
/**
* @brief set the profile used for status information
*
* @param profile the profile to use
**/
void setProfile(Profile* profile);
/**
* @brief retrieve the current sorting mode
* @note this is used to store the sorting mode between sessions
* @return current sorting mode, encoded to be compatible to previous versions
**/
int getCurrentSortingMode() const;
/**
* @brief remove the specified mod without asking for confirmation
* @param row the row to remove
*/
void removeRowForce(int row, const QModelIndex& parent);
void notifyChange(int rowStart, int rowEnd = -1);
static QString getColumnName(int column);
void changeModPriority(int sourceIndex, int newPriority);
void changeModPriority(std::vector sourceIndices, int newPriority);
void setPluginContainer(PluginContainer* pluginContainer);
bool modInfoAboutToChange(ModInfo::Ptr info);
void modInfoChanged(ModInfo::Ptr info);
void disconnectSlots();
int timeElapsedSinceLastChecked() const;
public:
/**
* @brief Notify the mod list that the given mod has been installed. This is used
* to notify the plugin that registered through onModInstalled().
*
* @param mod The installed mod.
*/
void notifyModInstalled(MOBase::IModInterface* mod) const;
/**
* @brief Notify the mod list that a mod has been removed. This is used
* to notify the plugin that registered through onModRemoved().
*
* @param modName Name of the removed mod.
*/
void notifyModRemoved(QString const& modName) const;
/**
* @brief Notify the mod list that the state of the specified mods has changed. This
* is used to notify the plugin that registered through onModStateChanged().
*
* @param modIndices Indices of the mods that changed.
*/
void notifyModStateChanged(QList modIndices) const;
public:
/// \copydoc MOBase::IModList::displayName
QString displayName(const QString& internalName) const;
/// \copydoc MOBase::IModList::allMods
QStringList allMods() const;
QStringList allModsByProfilePriority(MOBase::IProfile* profile = nullptr) const;
// \copydoc MOBase::IModList::getMod
MOBase::IModInterface* getMod(const QString& name) const;
// \copydoc MOBase::IModList::remove
bool removeMod(MOBase::IModInterface* mod);
// \copydoc MOBase::IModList::renameMod
MOBase::IModInterface* renameMod(MOBase::IModInterface* mod, const QString& name);
/// \copydoc MOBase::IModList::state
MOBase::IModList::ModStates state(const QString& name) const;
/// \copydoc MOBase::IModList::setActive
bool setActive(const QString& name, bool active);
/// \copydoc MOBase::IModList::setActive
int setActive(const QStringList& names, bool active);
/// \copydoc MOBase::IModList::priority
int priority(const QString& name) const;
/// \copydoc MOBase::IModList::setPriority
bool setPriority(const QString& name, int newPriority);
boost::signals2::connection
onModInstalled(const std::function& func);
boost::signals2::connection
onModRemoved(const std::function& func);
boost::signals2::connection onModStateChanged(
const std::function&)>&
func);
boost::signals2::connection
onModMoved(const std::function& func);
public: // implementation of virtual functions of QAbstractItemModel
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
virtual bool hasChildren(const QModelIndex& parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
virtual bool setData(const QModelIndex& index, const QVariant& value,
int role = Qt::EditRole);
virtual QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
virtual Qt::ItemFlags flags(const QModelIndex& modelIndex) const;
virtual bool removeRows(int row, int count, const QModelIndex& parent);
Qt::DropActions supportedDropActions() const override
{
return Qt::MoveAction | Qt::CopyAction;
}
QStringList mimeTypes() const override;
QMimeData* mimeData(const QModelIndexList& indexes) const override;
bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row,
int column, const QModelIndex& parent) const override;
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column,
const QModelIndex& parent) override;
virtual QModelIndex index(int row, int column,
const QModelIndex& parent = QModelIndex()) const;
virtual QModelIndex parent(const QModelIndex& child) const;
virtual QMap itemData(const QModelIndex& index) const;
public slots:
void onDragEnter(const QMimeData* data);
// enable/disable mods at the given indices.
//
void setActive(const QModelIndexList& indices, bool active);
// shift the priority of mods at the given indices by the given offset
//
void shiftModsPriority(const QModelIndexList& indices, int offset);
// change the priority of the mods specified by the given indices
//
void changeModsPriority(const QModelIndexList& indices, int priority);
// toggle the active state of mods at the given indices
//
bool toggleState(const QModelIndexList& indices);
signals:
// emitted when the priority of one or multiple mods have changed
//
// the sorting of the list can only be manually changed if the list is sorted by
// priority in which case the move is intended to change the priority of a mod.
//
void modPrioritiesChanged(const QModelIndexList& indices) const;
// emitted when the state (active/inactive) of one or multiple mods have changed
//
void modStatesChanged(const QModelIndexList& indices) const;
/**
* @brief emitted when the model wants a text to be displayed by the UI
*
* @param message the message to display
**/
void showMessage(const QString& message);
/**
* @brief signals change to the count of headers
*/
void resizeHeaders();
/**
* @brief emitted to remove a file origin
* @param name name of the orign to remove
*/
void removeOrigin(const QString& name);
/**
* @brief emitted after a mod has been renamed
* This signal MUST be used to fix the mod names in profiles (except the active one)
* and to invalidate/refresh other structures that may have become invalid with the
* rename
*
* @param oldName the old name of the mod
* @param newName new name of the mod
*/
void modRenamed(const QString& oldName, const QString& newName);
/**
* @brief emitted after a mod has been uninstalled
* @param fileName filename of the mod being uninstalled
*/
void modUninstalled(const QString& fileName);
/**
* @brief QML seems to handle overloaded signals poorly - create unique signal for
* tutorials
*/
void tutorialModlistUpdate();
/**
* @brief fileMoved emitted when a file is moved from one mod to another
* @param relativePath relative path of the file moved
* @param oldOriginName name of the origin that previously contained the file
* @param newOriginName name of the origin that now contains the file
*/
void fileMoved(const QString& relativePath, const QString& oldOriginName,
const QString& newOriginName);
/**
* @brief emitted to have the overwrite folder cleared
*/
void clearOverwrite();
void aboutToChangeData();
void postDataChanged();
// emitted when an item is dropped from the download list, the row is from the
// download list
//
void downloadArchiveDropped(int row, int priority);
// emitted when an external archive is dropped on the mod list
//
void externalArchiveDropped(const QUrl& url, int priority);
// emitted when an external folder is dropped on the mod list
//
void externalFolderDropped(const QUrl& url, int priority);
private:
// retrieve the display name of a mod or convert from a user-provided
// name to internal name
//
QString getDisplayName(ModInfo::Ptr info) const;
QString makeInternalName(ModInfo::Ptr info, QString name) const;
QString getFlagText(ModInfo::EFlag flag, ModInfo::Ptr modInfo) const;
QString getConflictFlagText(ModInfo::EConflictFlag flag, ModInfo::Ptr modInfo) const;
QString getColumnToolTip(int column) const;
bool renameMod(int index, const QString& newName);
MOBase::IModList::ModStates state(unsigned int modIndex) const;
// handle dropping of local URLs files
//
bool dropLocalFiles(const ModListDropInfo& dropInfo, int row,
const QModelIndex& parent);
// return the priority of the mod for a drop event
//
int dropPriority(int row, const QModelIndex& parent) const;
private:
struct TModInfo
{
TModInfo(unsigned int index, ModInfo::Ptr modInfo)
: modInfo(modInfo), nameOrder(index), priorityOrder(0), modIDOrder(0),
categoryOrder(0)
{}
ModInfo::Ptr modInfo;
unsigned int nameOrder;
unsigned int priorityOrder;
unsigned int modIDOrder;
unsigned int categoryOrder;
};
struct TModInfoChange
{
QString name;
QFlags state;
};
private:
OrganizerCore* m_Organizer;
Profile* m_Profile;
NexusInterface* m_NexusInterface;
std::set m_RequestIDs;
mutable bool m_Modified;
bool m_InNotifyChange;
bool m_DropOnMod = false;
QFontMetrics m_FontMetrics;
TModInfoChange m_ChangeInfo;
SignalModInstalled m_ModInstalled;
SignalModMoved m_ModMoved;
SignalModRemoved m_ModRemoved;
SignalModStateChanged m_ModStateChanged;
QElapsedTimer m_LastCheck;
PluginContainer* m_PluginContainer;
};
#endif // MODLIST_H