summaryrefslogtreecommitdiff
path: root/src/pluginlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluginlist.cpp')
-rw-r--r--src/pluginlist.cpp85
1 files changed, 63 insertions, 22 deletions
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index cccb7d12..d3ffcdcb 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -18,7 +18,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pluginlist.h"
-#include "report.h"
#include "inject.h"
#include "settings.h"
#include "safewritefile.h"
@@ -28,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <gameinfo.h>
#include <iplugingame.h>
#include <espfile.h>
+#include <report.h>
#include <windows_error.h>
#include <QtDebug>
@@ -89,9 +89,9 @@ PluginList::~PluginList()
{
m_Refreshed.disconnect_all_slots();
m_PluginMoved.disconnect_all_slots();
+ m_PluginStateChanged.disconnect_all_slots();
}
-
QString PluginList::getColumnName(int column)
{
switch (column) {
@@ -297,13 +297,11 @@ void PluginList::addInformation(const QString &name, const QString &message)
}
}
-
bool PluginList::isEnabled(int index)
{
return m_ESPs.at(index).m_Enabled;
}
-
bool PluginList::readLoadOrder(const QString &fileName)
{
std::set<QString> availableESPs;
@@ -326,6 +324,10 @@ bool PluginList::readLoadOrder(const QString &fileName)
if (!file.open(QIODevice::ReadOnly)) {
return false;
}
+ if (file.size() == 0) {
+ // MO stores at least a header in the file. if it's completely empty the file is broken
+ return false;
+ }
while (!file.atEnd()) {
QByteArray line = file.readLine().trimmed();
QString modName;
@@ -446,8 +448,12 @@ void PluginList::writePlugins(const QString &fileName, bool writeUnchecked) cons
"Please see mo_interface.log for a list of affected plugins and rename them."));
}
- if (file.commitIfDifferent(m_LastSaveHash[fileName])) {
- qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData());
+ if (writtenCount == 0) {
+ qWarning("plugin list would be empty, this is almost certainly wrong. Not saving.");
+ } else {
+ if (file.commitIfDifferent(m_LastSaveHash[fileName])) {
+ qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData());
+ }
}
}
@@ -503,14 +509,16 @@ bool PluginList::saveLoadOrder(DirectoryEntry &directoryStructure)
return true;
}
- for (std::vector<ESPInfo>::iterator iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
- std::wstring espName = ToWString(iter->m_Name);
+ qDebug("setting file times on esps");
+
+ for (ESPInfo &esp : m_ESPs) {
+ std::wstring espName = ToWString(esp.m_Name);
const FileEntry::Ptr fileEntry = directoryStructure.findFile(espName);
if (fileEntry.get() != nullptr) {
QString fileName;
bool archive = false;
int originid = fileEntry->getOrigin(archive);
- fileName = QString("%1\\%2").arg(QDir::toNativeSeparators(ToQString(directoryStructure.getOriginByID(originid).getPath()))).arg(iter->m_Name);
+ fileName = QString("%1\\%2").arg(QDir::toNativeSeparators(ToQString(directoryStructure.getOriginByID(originid).getPath()))).arg(esp.m_Name);
HANDLE file = ::CreateFile(ToWString(fileName).c_str(), GENERIC_READ | GENERIC_WRITE,
0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
@@ -524,13 +532,13 @@ bool PluginList::saveLoadOrder(DirectoryEntry &directoryStructure)
}
ULONGLONG temp = 0;
- temp = (145731ULL + iter->m_Priority) * 24 * 60 * 60 * 10000000ULL;
+ temp = (145731ULL + esp.m_Priority) * 24 * 60 * 60 * 10000000ULL;
FILETIME newWriteTime;
newWriteTime.dwLowDateTime = (DWORD)(temp & 0xFFFFFFFF);
newWriteTime.dwHighDateTime = (DWORD)(temp >> 32);
- iter->m_Time = newWriteTime;
+ esp.m_Time = newWriteTime;
fileEntry->setFileTime(newWriteTime);
if (!::SetFileTime(file, nullptr, nullptr, &newWriteTime)) {
throw windows_error(QObject::tr("failed to set file time %1").arg(fileName).toUtf8().constData());
@@ -558,7 +566,6 @@ bool PluginList::isESPLocked(int index) const
return m_LockedOrder.find(m_ESPs.at(index).m_Name.toLower()) != m_LockedOrder.end();
}
-
void PluginList::lockESPIndex(int index, bool lock)
{
if (lock) {
@@ -573,7 +580,6 @@ qDebug(__FUNCTION__);
emit writePluginsList();
}
-
void PluginList::syncLoadOrder()
{
int loadOrder = 0;
@@ -595,9 +601,11 @@ void PluginList::refreshLoadOrder()
// set priorities according to locked load order
std::map<int, QString> lockedLoadOrder;
std::for_each(m_LockedOrder.begin(), m_LockedOrder.end(),
- [&lockedLoadOrder] (const std::pair<QString, int> &ele) { lockedLoadOrder[ele.second] = ele.first; });
+ [&lockedLoadOrder] (const std::pair<QString, int> &ele) {
+ lockedLoadOrder[ele.second] = ele.first; });
int targetPrio = 0;
+ bool savePluginsList = false;
// this is guaranteed to iterate from lowest key (load order) to highest
for (auto iter = lockedLoadOrder.begin(); iter != lockedLoadOrder.end(); ++iter) {
auto nameIter = m_ESPsByName.find(iter->second);
@@ -620,16 +628,22 @@ void PluginList::refreshLoadOrder()
setPluginPriority(index, temp);
m_ESPs[index].m_LoadOrder = iter->first;
syncLoadOrder();
- emit writePluginsList();
+ savePluginsList = true;
}
}
}
+ if (savePluginsList) {
+ emit writePluginsList();
+ }
}
+void PluginList::disconnectSlots() {
+ m_PluginMoved.disconnect_all_slots();
+ m_Refreshed.disconnect_all_slots();
+ m_PluginStateChanged.disconnect_all_slots();
+}
-
-
-IPluginList::PluginState PluginList::state(const QString &name) const
+IPluginList::PluginStates PluginList::state(const QString &name) const
{
auto iter = m_ESPsByName.find(name.toLower());
if (iter == m_ESPsByName.end()) {
@@ -693,6 +707,12 @@ QString PluginList::origin(const QString &name) const
}
}
+bool PluginList::onPluginStateChanged(const std::function<void (const QString &, PluginStates)> &func)
+{
+ auto conn = m_PluginStateChanged.connect(func);
+ return conn.connected();
+}
+
bool PluginList::onRefreshed(const std::function<void ()> &callback)
{
auto conn = m_Refreshed.connect(callback);
@@ -761,15 +781,13 @@ void PluginList::testMasters()
// emit layoutChanged();
}
-
QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
{
int index = modelIndex.row();
-
if ((role == Qt::DisplayRole)
|| (role == Qt::EditRole)) {
switch (modelIndex.column()) {
- case COL_NAME: {
+ case COL_NAME: {
return m_ESPs[index].m_Name;
} break;
case COL_PRIORITY: {
@@ -880,7 +898,11 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
bool PluginList::setData(const QModelIndex &modIndex, const QVariant &value, int role)
{
+ QString modName = modIndex.data().toString();
+ IPluginList::PluginStates oldState = state(modName);
+
bool result = false;
+
if (role == Qt::CheckStateRole) {
m_ESPs[modIndex.row()].m_Enabled = value.toInt() == Qt::Checked;
emit dataChanged(modIndex, modIndex);
@@ -900,6 +922,20 @@ bool PluginList::setData(const QModelIndex &modIndex, const QVariant &value, int
refreshLoadOrder();
}
}
+
+ IPluginList::PluginStates newState = state(modName);
+ if (oldState != newState) {
+ try {
+ m_PluginStateChanged(modName, newState);
+ testMasters();
+ emit dataChanged(this->index(0, 0), this->index(m_ESPs.size(), columnCount()));
+ } catch (const std::exception &e) {
+ qCritical("failed to invoke state changed notification: %s", e.what());
+ } catch (...) {
+ qCritical("failed to invoke state changed notification: unknown exception");
+ }
+ }
+
return result;
}
@@ -1024,6 +1060,7 @@ void PluginList::changePluginPriority(std::vector<int> rows, int newPriority)
layoutChange.finish();
refreshLoadOrder();
+ emit writePluginsList();
}
bool PluginList::dropMimeData(const QMimeData *mimeData, Qt::DropAction action, int row, int, const QModelIndex &parent)
@@ -1124,9 +1161,13 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event)
} else if (keyEvent->key() == Qt::Key_Space) {
QItemSelectionModel *selectionModel = itemView->selectionModel();
const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel*>(selectionModel->model());
+ QList<QPersistentModelIndex> indices;
+ for (QModelIndex idx : selectionModel->selectedRows()) {
+ indices.append(idx);
+ }
QModelIndex minRow, maxRow;
- foreach (QModelIndex idx, selectionModel->selectedRows()) {
+ for (QModelIndex idx : indices) {
if (proxyModel != nullptr) {
idx = proxyModel->mapToSource(idx);
}