summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTannin <devnull@localhost>2014-07-27 18:34:32 +0200
committerTannin <devnull@localhost>2014-07-27 18:34:32 +0200
commit470b6ed0bf20525988d719d23725f7c9d19a9f36 (patch)
tree289500f0d9e0f17f488fbc1dd53bfd5498ebeb65 /src
parent0050cb07409d775efe14e728c1cef4a2c33aa1db (diff)
- browser dialog now has a hidden url-field (for testing only)
- loot_cli is no longer part of this project. I will probably create a fork of loot that allows command-line usage instead - loot integration now works with such a modified loot version - integrated loot will now also integrate incompatibility messages in the MO UI - overwrite-markers are now updated as the list order is changed - fnis checker will now always allow the user to ignore fnis errors - plugin interface now has a function to wait for handles returned from startApplication (which can be job or process handles) - bugfix: non-mo mods sharing the name with regular mods now have a different internal name - bugfix: using hotkeys the vanilla game-plugins could be moved
Diffstat (limited to 'src')
-rw-r--r--src/browserdialog.cpp30
-rw-r--r--src/browserdialog.h4
-rw-r--r--src/browserdialog.ui29
-rw-r--r--src/browserview.cpp3
-rw-r--r--src/genericicondelegate.cpp (renamed from src/pluginflagicondelegate.cpp)2
-rw-r--r--src/genericicondelegate.h (renamed from src/pluginflagicondelegate.h)6
-rw-r--r--src/mainwindow.cpp139
-rw-r--r--src/mainwindow.h4
-rw-r--r--src/modinfo.cpp103
-rw-r--r--src/modinfo.h13
-rw-r--r--src/modlist.cpp4
-rw-r--r--src/modlistsortproxy.cpp16
-rw-r--r--src/modlistsortproxy.h3
-rw-r--r--src/modlistview.cpp1
-rw-r--r--src/organizer.pro4
-rw-r--r--src/organizerproxy.cpp5
-rw-r--r--src/organizerproxy.h1
-rw-r--r--src/pluginlist.cpp7
-rw-r--r--src/viewmarkingscrollbar.cpp3
19 files changed, 277 insertions, 100 deletions
diff --git a/src/browserdialog.cpp b/src/browserdialog.cpp
index 4897ea4f..521459d0 100644
--- a/src/browserdialog.cpp
+++ b/src/browserdialog.cpp
@@ -37,6 +37,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QDir>
#include <QWebFrame>
#include <QDesktopWidget>
+#include <QKeyEvent>
@@ -57,9 +58,12 @@ BrowserDialog::BrowserDialog(QWidget *parent)
m_Tabs = this->findChild<QTabWidget*>("browserTabWidget");
+ installEventFilter(this);
+
connect(m_Tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int)));
-}
+ ui->urlEdit->setVisible(false);
+}
BrowserDialog::~BrowserDialog()
{
@@ -108,13 +112,14 @@ BrowserView *BrowserDialog::getCurrentView()
}
-void BrowserDialog::urlChanged(const QUrl&)
+void BrowserDialog::urlChanged(const QUrl &url)
{
BrowserView *currentView = getCurrentView();
if (currentView != NULL) {
ui->backBtn->setEnabled(currentView->history()->canGoBack());
ui->fwdBtn->setEnabled(currentView->history()->canGoForward());
}
+ ui->urlEdit->setText(url.toString());
}
@@ -268,3 +273,24 @@ void BrowserDialog::on_browserTabWidget_currentChanged(int index)
ui->fwdBtn->setEnabled(currentView->history()->canGoForward());
}
}
+
+void BrowserDialog::on_urlEdit_returnPressed()
+{
+ QWebView *currentView = getCurrentView();
+ if (currentView != NULL) {
+ currentView->setUrl(QUrl(ui->urlEdit->text()));
+ }
+}
+
+bool BrowserDialog::eventFilter(QObject *object, QEvent *event)
+{
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *keyEvent = reinterpret_cast<QKeyEvent*>(event);
+ if ((keyEvent->modifiers() & Qt::ControlModifier)
+ && (keyEvent->key() == Qt::Key_U)) {
+ ui->urlEdit->setVisible(!ui->urlEdit->isVisible());
+ return true;
+ }
+ }
+ return QDialog::eventFilter(object, event);
+}
diff --git a/src/browserdialog.h b/src/browserdialog.h
index c6e0aab6..10b44fac 100644
--- a/src/browserdialog.h
+++ b/src/browserdialog.h
@@ -63,6 +63,7 @@ public:
**/
void openUrl(const QUrl &url);
+ virtual bool eventFilter(QObject *object, QEvent *event);
signals:
/**
@@ -103,6 +104,8 @@ private slots:
void on_browserTabWidget_currentChanged(int index);
+ void on_urlEdit_returnPressed();
+
private:
QString guessFileName(const QString &url);
@@ -119,6 +122,7 @@ private:
QTabWidget *m_Tabs;
+
};
#endif // BROWSERDIALOG_H
diff --git a/src/browserdialog.ui b/src/browserdialog.ui
index 7d154fbb..c682fc5d 100644
--- a/src/browserdialog.ui
+++ b/src/browserdialog.ui
@@ -17,7 +17,16 @@
<property name="spacing">
<number>0</number>
</property>
- <property name="margin">
+ <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>
@@ -180,7 +189,16 @@
<property name="spacing">
<number>6</number>
</property>
- <property name="margin">
+ <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>
@@ -238,6 +256,13 @@
</widget>
</item>
<item>
+ <widget class="QLineEdit" name="urlEdit">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
diff --git a/src/browserview.cpp b/src/browserview.cpp
index bd43a18e..aeb16520 100644
--- a/src/browserview.cpp
+++ b/src/browserview.cpp
@@ -28,6 +28,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <Shlwapi.h>
#include "utility.h"
+
BrowserView::BrowserView(QWidget *parent)
: QWebView(parent)
{
@@ -36,7 +37,6 @@ BrowserView::BrowserView(QWidget *parent)
page()->settings()->setMaximumPagesInCache(10);
}
-
QWebView *BrowserView::createWindow(QWebPage::WebWindowType)
{
BrowserView *newView = new BrowserView(parentWidget());
@@ -44,7 +44,6 @@ QWebView *BrowserView::createWindow(QWebPage::WebWindowType)
return newView;
}
-
bool BrowserView::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::ShortcutOverride) {
diff --git a/src/pluginflagicondelegate.cpp b/src/genericicondelegate.cpp
index a4f66c04..c3471735 100644
--- a/src/pluginflagicondelegate.cpp
+++ b/src/genericicondelegate.cpp
@@ -1,4 +1,4 @@
-#include "pluginflagicondelegate.h"
+#include "genericicondelegate.h"
#include "pluginlist.h"
#include <QList>
diff --git a/src/pluginflagicondelegate.h b/src/genericicondelegate.h
index 3c05db72..8bc75e27 100644
--- a/src/pluginflagicondelegate.h
+++ b/src/genericicondelegate.h
@@ -1,5 +1,5 @@
-#ifndef PLUGINFLAGICONDELEGATE_H
-#define PLUGINFLAGICONDELEGATE_H
+#ifndef GENERICICONDELEGATE_H
+#define GENERICICONDELEGATE_H
#include "icondelegate.h"
@@ -33,4 +33,4 @@ private:
bool m_Compact;
};
-#endif // PLUGINFLAGICONDELEGATE_H
+#endif // GENERICICONDELEGATE_H
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index a3887a23..4aea645f 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -49,7 +49,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "questionboxmemory.h"
#include "tutorialmanager.h"
#include "modflagicondelegate.h"
-#include "pluginflagicondelegate.h"
+#include "genericicondelegate.h"
#include "credentialsdialog.h"
#include "selectiondialog.h"
#include "csvbuilder.h"
@@ -728,6 +728,7 @@ void MainWindow::savePluginList()
void MainWindow::modFilterActive(bool filterActive)
{
if (filterActive) {
+ m_ModList.setOverwriteMarkers(std::set<unsigned int>(), std::set<unsigned int>());
ui->modList->setStyleSheet("QTreeView { border: 2px ridge #f00; }");
} else if (ui->groupCombo->currentIndex() != 0) {
ui->modList->setStyleSheet("QTreeView { border: 2px ridge #337733; }");
@@ -784,7 +785,6 @@ bool MainWindow::saveCurrentLists()
return true;
}
-
bool MainWindow::addProfile()
{
QComboBox *profileBox = findChild<QComboBox*>("profileBox");
@@ -807,7 +807,6 @@ bool MainWindow::addProfile()
}
}
-
void MainWindow::hookUpWindowTutorials()
{
QDirIterator dirIter(QApplication::applicationDirPath() + "/tutorials", QStringList("*.js"), QDir::Files);
@@ -829,7 +828,6 @@ void MainWindow::hookUpWindowTutorials()
}
}
-
void MainWindow::showEvent(QShowEvent *event)
{
refreshFilters();
@@ -2773,6 +2771,19 @@ void MainWindow::modorder_changed()
m_CurrentProfile->writeModlist();
saveArchiveList();
m_DirectoryStructure->getFileRegister()->sortOrigins();
+
+ { // refresh selection
+ QModelIndex current = ui->modList->currentIndex();
+ if (current.isValid()) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(current.data(Qt::UserRole + 1).toInt());
+ modInfo->doConflictCheck();
+ m_ModList.setOverwriteMarkers(modInfo->getModOverwrite(), modInfo->getModOverwritten());
+ if (m_ModListSortProxy != NULL) {
+ m_ModListSortProxy->invalidate();
+ }
+ ui->modList->verticalScrollBar()->repaint();
+ }
+ }
}
void MainWindow::procError(QProcess::ProcessError error)
@@ -2960,6 +2971,7 @@ void MainWindow::refreshFilters()
{
QItemSelection currentSelection = ui->modList->selectionModel()->selection();
+ QVariant currentIndexName = ui->modList->currentIndex().data();
ui->modList->setCurrentIndex(QModelIndex());
QStringList selectedItems;
@@ -2998,8 +3010,11 @@ void MainWindow::refreshFilters()
matches.at(0)->setSelected(true);
}
}
-
ui->modList->selectionModel()->select(currentSelection, QItemSelectionModel::Select);
+ QModelIndexList matchList = ui->modList->model()->match(ui->modList->model()->index(0, 0), Qt::DisplayRole, currentIndexName);
+ if (matchList.size() > 0) {
+ ui->modList->setCurrentIndex(matchList.at(0));
+ }
}
@@ -3069,9 +3084,14 @@ void MainWindow::modlistChanged(const QModelIndex&, int)
void MainWindow::modlistSelectionChanged(const QModelIndex &current, const QModelIndex&)
{
- ModInfo::Ptr selectedMod = ModInfo::getByIndex(current.data(Qt::UserRole + 1).toInt());
- m_ModList.setOverwriteMarkers(selectedMod->getModOverwrite(), selectedMod->getModOverwritten());
- if (m_ModListSortProxy != NULL) {
+ if (current.isValid()) {
+ ModInfo::Ptr selectedMod = ModInfo::getByIndex(current.data(Qt::UserRole + 1).toInt());
+ m_ModList.setOverwriteMarkers(selectedMod->getModOverwrite(), selectedMod->getModOverwritten());
+ } else {
+ m_ModList.setOverwriteMarkers(std::set<unsigned int>(), std::set<unsigned int>());
+ }
+ if ((m_ModListSortProxy != NULL)
+ && !m_ModListSortProxy->beingInvalidated()) {
m_ModListSortProxy->invalidate();
}
ui->modList->verticalScrollBar()->repaint();
@@ -5277,11 +5297,12 @@ void MainWindow::processLOOTOut(const std::string &lootOut, std::string &reportU
boost::split(lines, lootOut, boost::is_any_of("\r\n"));
std::tr1::regex exRequires("\"([^\"]*)\" requires \"([^\"]*)\", but it is missing\\.");
+ std::tr1::regex exIncompatible("\"([^\"]*)\" is incompatible with \"([^\"]*)\", but both are present\\.");
foreach (const std::string &line, lines) {
if (line.length() > 0) {
size_t progidx = line.find("[progress]");
- size_t reportidx = line.find("[report]");
+ size_t reportidx = line.find("[Report]");
size_t erroridx = line.find("[error]");
if (progidx != std::string::npos) {
dialog.setLabelText(line.substr(progidx + 11).c_str());
@@ -5296,8 +5317,12 @@ void MainWindow::processLOOTOut(const std::string &lootOut, std::string &reportU
std::string modName(match[1].first, match[1].second);
std::string dependency(match[2].first, match[2].second);
m_PluginList.addInformation(modName.c_str(), tr("depends on missing \"%1\"").arg(dependency.c_str()));
+ } else if (std::tr1::regex_match(line, match, exIncompatible)) {
+ std::string modName(match[1].first, match[1].second);
+ std::string dependency(match[2].first, match[2].second);
+ m_PluginList.addInformation(modName.c_str(), tr("incompatible with \"%1\"").arg(dependency.c_str()));
} else {
- qDebug("%s", line.c_str());
+ qDebug("[loot] %s", line.c_str());
}
}
}
@@ -5350,6 +5375,65 @@ HANDLE MainWindow::startApplication(const QString &executable, const QStringList
return spawnBinaryDirect(binary, arguments, profileName, currentDirectory, steamAppID);
}
+
+bool MainWindow::waitForProcessOrJob(HANDLE handle, LPDWORD exitCode)
+{
+ LockedDialog *dialog = new LockedDialog(this);
+ dialog->show();
+ setEnabled(false);
+ ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); this->setEnabled(true); });
+
+ DWORD retLen;
+ JOBOBJECT_BASIC_PROCESS_ID_LIST info;
+
+ bool isJobHandle = true;
+
+ ULONG lastProcessID = ULONG_MAX;
+ HANDLE processHandle = handle;
+
+ DWORD res = ::MsgWaitForMultipleObjects(1, &handle, false, 500, QS_KEY | QS_MOUSE);
+ while ((res != WAIT_FAILED) && (res != WAIT_OBJECT_0) && !dialog->unlockClicked()) {
+ if (isJobHandle) {
+ if (::QueryInformationJobObject(handle, JobObjectBasicProcessIdList, &info, sizeof(info), &retLen) > 0) {
+ if (info.NumberOfProcessIdsInList == 0) {
+ // fake signaled state
+ res = WAIT_OBJECT_0;
+ break;
+ } else {
+ // this is indeed a job handle. Figure out one of the process handles as well.
+ if (lastProcessID != info.ProcessIdList[0]) {
+ lastProcessID = info.ProcessIdList[0];
+ if (processHandle != handle) {
+ ::CloseHandle(processHandle);
+ }
+ processHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, lastProcessID);
+ }
+ }
+ } else {
+ // the info-object I passed only provides space for 1 process id. but since this code only cares about whether there
+ // is more than one that's good enough. ERROR_MORE_DATA simply signals there are at least two processes running.
+ // any other error probably means the handle is a regular process handle, probably caused by running MO in a job without
+ // the right to break out.
+ if (::GetLastError() != ERROR_MORE_DATA) {
+ isJobHandle = false;
+ }
+ }
+ }
+
+ // keep processing events so the app doesn't appear dead
+ QCoreApplication::processEvents();
+
+ res = ::MsgWaitForMultipleObjects(1, &handle, false, 500, QS_KEY | QS_MOUSE);
+ }
+
+ if (exitCode != NULL) {
+ ::GetExitCodeProcess(processHandle, exitCode);
+ }
+ ::CloseHandle(processHandle);
+
+ return res == WAIT_OBJECT_0;
+}
+
void MainWindow::on_bossButton_clicked()
{
std::string reportURL;
@@ -5368,18 +5452,21 @@ void MainWindow::on_bossButton_clicked()
dialog.show();
QStringList parameters;
- parameters << "--game" << ToQString(GameInfo::instance().getGameShortName())
+ parameters << "--unattended"
+ << "--stdout"
+ << "--noreport"
+ << "--game" << ToQString(GameInfo::instance().getGameShortName())
<< "--gamePath" << QString("\"%1\"").arg(ToQString(GameInfo::instance().getGameDirectory()));
- if (!m_DidUpdateMasterList) {
- parameters << "--updateMasterlist";
+ if (m_DidUpdateMasterList) {
+ parameters << "--skipUpdateMasterlist";
+ } else {
m_DidUpdateMasterList = true;
}
-
HANDLE stdOutWrite = INVALID_HANDLE_VALUE;
HANDLE stdOutRead = INVALID_HANDLE_VALUE;
createStdoutPipe(&stdOutRead, &stdOutWrite);
- HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/lootcli.exe"),
+ HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/LOOT.exe"),
parameters.join(" "),
m_CurrentProfile->getName(),
m_Settings.logLevel(),
@@ -5395,6 +5482,8 @@ void MainWindow::on_bossButton_clicked()
DWORD retLen;
JOBOBJECT_BASIC_PROCESS_ID_LIST info;
bool isJobHandle = true;
+ ULONG lastProcessID;
+ HANDLE processHandle = loot;
if (loot != INVALID_HANDLE_VALUE) {
DWORD res = ::MsgWaitForMultipleObjects(1, &loot, false, 1000, QS_KEY | QS_MOUSE);
@@ -5404,6 +5493,14 @@ void MainWindow::on_bossButton_clicked()
if (info.NumberOfProcessIdsInList == 0) {
qDebug("no more processes in job");
break;
+ } else {
+ if (lastProcessID != info.ProcessIdList[0]) {
+ lastProcessID = info.ProcessIdList[0];
+ if (processHandle != loot) {
+ ::CloseHandle(processHandle);
+ }
+ processHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, lastProcessID);
+ }
}
} else {
// the info-object I passed only provides space for 1 process id. but since this code only cares about whether there
@@ -5437,7 +5534,8 @@ void MainWindow::on_bossButton_clicked()
processLOOTOut(remainder, reportURL, errorMessages, dialog);
}
DWORD exitCode = 0UL;
- ::GetExitCodeProcess(loot, &exitCode);
+ ::GetExitCodeProcess(processHandle, &exitCode);
+ ::CloseHandle(processHandle);
if (exitCode != 0UL) {
reportError(tr("loot failed. Exit code was: %1").arg(exitCode));
return;
@@ -5460,11 +5558,12 @@ void MainWindow::on_bossButton_clicked()
if (reportURL.length() > 0) {
m_IntegratedBrowser.setWindowTitle("LOOT Report");
QString report(reportURL.c_str());
- if (QFile::exists(report)) {
- m_IntegratedBrowser.openUrl(QUrl::fromLocalFile(report));
- } else {
- qWarning("report file missing");
+ QStringList temp = report.split("?");
+ QUrl url = QUrl::fromLocalFile(temp.at(0));
+ if (temp.size() > 1) {
+ url.setEncodedQuery(temp.at(1).toUtf8());
}
+ m_IntegratedBrowser.openUrl(url);
}
refreshESPList();
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 62503062..124dde5f 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -134,9 +134,11 @@ public:
HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "", const QString &profile = "");
+ bool waitForProcessOrJob(HANDLE processHandle, LPDWORD exitCode = NULL);
+
void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo);
- void waitForProcessOrJob(HANDLE processHandle);
+
public slots:
void refreshLists();
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index cb20567e..60df0137 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -359,67 +359,72 @@ std::vector<ModInfo::EFlag> ModInfoWithConflictInfo::getFlags() const
}
-ModInfoWithConflictInfo::EConflictType ModInfoWithConflictInfo::isConflicted() const
+void ModInfoWithConflictInfo::doConflictCheck() const
{
- // this is costy so cache the result
- QTime now = QTime::currentTime();
- if (m_LastConflictCheck.isNull() || (m_LastConflictCheck.secsTo(now) > 10)) {
- m_OverwriteList.clear();
- m_OverwrittenList.clear();
- bool regular = false;
+ m_OverwriteList.clear();
+ m_OverwrittenList.clear();
+ bool regular = false;
- int dataID = 0;
- if ((*m_DirectoryStructure)->originExists(L"data")) {
- dataID = (*m_DirectoryStructure)->getOriginByName(L"data").getID();
- }
+ int dataID = 0;
+ if ((*m_DirectoryStructure)->originExists(L"data")) {
+ dataID = (*m_DirectoryStructure)->getOriginByName(L"data").getID();
+ }
- std::wstring name = ToWString(this->name());
- if ((*m_DirectoryStructure)->originExists(name)) {
- FilesOrigin &origin = (*m_DirectoryStructure)->getOriginByName(name);
- std::vector<FileEntry::Ptr> files = origin.getFiles();
- // for all files in this origin
- for (auto iter = files.begin(); iter != files.end(); ++iter) {
- const std::vector<int> &alternatives = (*iter)->getAlternatives();
- if ((alternatives.size() == 0)
- || (alternatives[0] == dataID)) {
- // no alternatives -> no conflict
- regular = true;
- } else {
- if ((*iter)->getOrigin() != origin.getID()) {
- FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID((*iter)->getOrigin());
+ std::wstring name = ToWString(this->name());
+ if ((*m_DirectoryStructure)->originExists(name)) {
+ FilesOrigin &origin = (*m_DirectoryStructure)->getOriginByName(name);
+ std::vector<FileEntry::Ptr> files = origin.getFiles();
+ // for all files in this origin
+ for (auto iter = files.begin(); iter != files.end(); ++iter) {
+ const std::vector<int> &alternatives = (*iter)->getAlternatives();
+ if ((alternatives.size() == 0)
+ || (alternatives[0] == dataID)) {
+ // no alternatives -> no conflict
+ regular = true;
+ } else {
+ if ((*iter)->getOrigin() != origin.getID()) {
+ FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID((*iter)->getOrigin());
+ unsigned int altIndex = ModInfo::getIndex(ToQString(altOrigin.getName()));
+ m_OverwrittenList.insert(altIndex);
+ }
+ // for all non-providing alternative origins
+ for (auto altIter = alternatives.begin(); altIter != alternatives.end(); ++altIter) {
+ if ((*altIter != dataID) && (*altIter != origin.getID())) {
+ FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID(*altIter);
unsigned int altIndex = ModInfo::getIndex(ToQString(altOrigin.getName()));
- m_OverwrittenList.insert(altIndex);
- }
- // for all non-providing alternative origins
- for (auto altIter = alternatives.begin(); altIter != alternatives.end(); ++altIter) {
- if ((*altIter != dataID) && (*altIter != origin.getID())) {
- FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID(*altIter);
- unsigned int altIndex = ModInfo::getIndex(ToQString(altOrigin.getName()));
- if (origin.getPriority() > altOrigin.getPriority()) {
- m_OverwriteList.insert(altIndex);
- } else {
- m_OverwrittenList.insert(altIndex);
- }
+ if (origin.getPriority() > altOrigin.getPriority()) {
+ m_OverwriteList.insert(altIndex);
+ } else {
+ m_OverwrittenList.insert(altIndex);
}
}
}
}
}
+ }
- m_LastConflictCheck = QTime::currentTime();
+ m_LastConflictCheck = QTime::currentTime();
- if (!m_OverwriteList.empty() && !m_OverwrittenList.empty())
- m_CurrentConflictState = CONFLICT_MIXED;
- else if (!m_OverwriteList.empty())
- m_CurrentConflictState = CONFLICT_OVERWRITE;
- else if (!m_OverwrittenList.empty()) {
- if (!regular) {
- m_CurrentConflictState = CONFLICT_REDUNDANT;
- } else {
- m_CurrentConflictState = CONFLICT_OVERWRITTEN;
- }
+ if (!m_OverwriteList.empty() && !m_OverwrittenList.empty())
+ m_CurrentConflictState = CONFLICT_MIXED;
+ else if (!m_OverwriteList.empty())
+ m_CurrentConflictState = CONFLICT_OVERWRITE;
+ else if (!m_OverwrittenList.empty()) {
+ if (!regular) {
+ m_CurrentConflictState = CONFLICT_REDUNDANT;
+ } else {
+ m_CurrentConflictState = CONFLICT_OVERWRITTEN;
}
- else m_CurrentConflictState = CONFLICT_NONE;
+ }
+ else m_CurrentConflictState = CONFLICT_NONE;
+}
+
+ModInfoWithConflictInfo::EConflictType ModInfoWithConflictInfo::isConflicted() const
+{
+ // this is costy so cache the result
+ QTime now = QTime::currentTime();
+ if (m_LastConflictCheck.isNull() || (m_LastConflictCheck.secsTo(now) > 10)) {
+ doConflictCheck();
}
return m_CurrentConflictState;
diff --git a/src/modinfo.h b/src/modinfo.h
index e2121828..1097e5ba 100644
--- a/src/modinfo.h
+++ b/src/modinfo.h
@@ -498,17 +498,20 @@ public:
virtual void saveMeta() {}
/**
- * @brief retrieve list of mods (as mod index) that are overwritten by this one. Updates may be delayed
- * @return
+ * @return retrieve list of mods (as mod index) that are overwritten by this one. Updates may be delayed
*/
virtual std::set<unsigned int> getModOverwrite() { return std::set<unsigned int>(); }
/**
- * @brief retrieve list of mods (as mod index) that overwrite this one. Updates may be delayed
- * @return
+ * @return list of mods (as mod index) that overwrite this one. Updates may be delayed
*/
virtual std::set<unsigned int> getModOverwritten() { return std::set<unsigned int>(); }
+ /**
+ * @brief update conflict information
+ */
+ virtual void doConflictCheck() const {}
+
signals:
/**
@@ -567,6 +570,8 @@ public:
virtual std::set<unsigned int> getModOverwritten() { return m_OverwrittenList; }
+ virtual void doConflictCheck() const;
+
private:
enum EConflictType {
diff --git a/src/modlist.cpp b/src/modlist.cpp
index ca173b18..681d880c 100644
--- a/src/modlist.cpp
+++ b/src/modlist.cpp
@@ -224,7 +224,6 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
return QString();
}
} else {
- //return tr("None");
return QVariant();
}
}
@@ -887,6 +886,8 @@ void ModList::removeRow(int row, const QModelIndex&)
void ModList::notifyChange(int rowStart, int rowEnd)
{
if (rowStart < 0) {
+ m_Overwrite.clear();
+ m_Overwritten.clear();
beginResetModel();
endResetModel();
} else {
@@ -1021,6 +1022,7 @@ bool ModList::eventFilter(QObject *obj, QEvent *event)
notifyChange(idx.row());
}
}
+ emit modorder_changed();
return true;
} else if (keyEvent->key() == Qt::Key_Delete) {
QItemSelectionModel *selectionModel = itemView->selectionModel();
diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp
index d790e277..ecd1755d 100644
--- a/src/modlistsortproxy.cpp
+++ b/src/modlistsortproxy.cpp
@@ -34,6 +34,7 @@ ModListSortProxy::ModListSortProxy(Profile* profile, QObject *parent)
, m_CurrentFilter()
, m_FilterActive(false)
, m_FilterMode(FILTER_AND)
+ , m_BeingInvalidated(false)
{
m_EnabledColumns.set(ModList::COL_FLAGS);
m_EnabledColumns.set(ModList::COL_NAME);
@@ -43,7 +44,6 @@ ModListSortProxy::ModListSortProxy(Profile* profile, QObject *parent)
// but I don't know why. This should be necessary
}
-
void ModListSortProxy::setProfile(Profile *profile)
{
m_Profile = profile;
@@ -72,7 +72,6 @@ Qt::ItemFlags ModListSortProxy::flags(const QModelIndex &modelIndex) const
return flags;
}
-
void ModListSortProxy::displayColumnSelection(const QPoint &pos)
{
QMenu menu;
@@ -103,7 +102,6 @@ void ModListSortProxy::displayColumnSelection(const QPoint &pos)
emit layoutChanged();
}
-
void ModListSortProxy::enableAllVisible()
{
if (m_Profile == NULL) return;
@@ -115,7 +113,6 @@ void ModListSortProxy::enableAllVisible()
invalidate();
}
-
void ModListSortProxy::disableAllVisible()
{
if (m_Profile == NULL) return;
@@ -127,7 +124,6 @@ void ModListSortProxy::disableAllVisible()
invalidate();
}
-
bool ModListSortProxy::lessThan(const QModelIndex &left,
const QModelIndex &right) const
{
@@ -208,15 +204,16 @@ bool ModListSortProxy::lessThan(const QModelIndex &left,
return lt;
}
-
void ModListSortProxy::updateFilter(const QString &filter)
{
m_CurrentFilter = filter;
updateFilterActive();
+ // workaround because qt throws a fit if, as a result of this invalidation, another invalidate is called
+ m_BeingInvalidated = true;
invalidateFilter();
+ m_BeingInvalidated = false;
}
-
bool ModListSortProxy::hasConflictFlag(const std::vector<ModInfo::EFlag> &flags) const
{
foreach (ModInfo::EFlag flag, flags) {
@@ -231,7 +228,6 @@ bool ModListSortProxy::hasConflictFlag(const std::vector<ModInfo::EFlag> &flags)
return false;
}
-
bool ModListSortProxy::filterMatchesModAnd(ModInfo::Ptr info, bool enabled) const
{
for (auto iter = m_CategoryFilter.begin(); iter != m_CategoryFilter.end(); ++iter) {
@@ -306,8 +302,6 @@ bool ModListSortProxy::filterMatchesModOr(ModInfo::Ptr info, bool enabled) const
return false;
}
-
-
bool ModListSortProxy::filterMatchesMod(ModInfo::Ptr info, bool enabled) const
{
if (!m_CurrentFilter.isEmpty() &&
@@ -330,7 +324,6 @@ void ModListSortProxy::setFilterMode(ModListSortProxy::FilterMode mode)
}
}
-
bool ModListSortProxy::filterAcceptsRow(int row, const QModelIndex &parent) const
{
if (m_Profile == NULL) {
@@ -362,7 +355,6 @@ bool ModListSortProxy::filterAcceptsRow(int row, const QModelIndex &parent) cons
}
}
-
bool ModListSortProxy::dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent)
{
diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h
index fc7edcd5..cb474200 100644
--- a/src/modlistsortproxy.h
+++ b/src/modlistsortproxy.h
@@ -83,6 +83,7 @@ public:
return rowCount(parent) > 0;
}
+ bool beingInvalidated() const { return m_BeingInvalidated; }
public slots:
@@ -116,6 +117,8 @@ private:
bool m_FilterActive;
FilterMode m_FilterMode;
+ bool m_BeingInvalidated;
+
};
#endif // MODLISTSORTPROXY_H
diff --git a/src/modlistview.cpp b/src/modlistview.cpp
index 2789afe1..50a13a8c 100644
--- a/src/modlistview.cpp
+++ b/src/modlistview.cpp
@@ -38,7 +38,6 @@ ModListView::ModListView(QWidget *parent)
: QTreeView(parent)
, m_Scrollbar(new ViewMarkingScrollBar(this->model(), this))
{
-// setStyle(new ModListViewStyle(style(), indentation()));
setVerticalScrollBar(m_Scrollbar);
}
diff --git a/src/organizer.pro b/src/organizer.pro
index 19d3a3a0..994da396 100644
--- a/src/organizer.pro
+++ b/src/organizer.pro
@@ -88,7 +88,7 @@ SOURCES += \
json.cpp \
safewritefile.cpp \
modflagicondelegate.cpp \
- pluginflagicondelegate.cpp \
+ genericicondelegate.cpp \
organizerproxy.cpp \
viewmarkingscrollbar.cpp
@@ -168,7 +168,7 @@ HEADERS += \
safewritefile.h\
pdll.h \
modflagicondelegate.h \
- pluginflagicondelegate.h \
+ genericicondelegate.h \
organizerproxy.h \
viewmarkingscrollbar.h
diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp
index c48bc765..8adfda7e 100644
--- a/src/organizerproxy.cpp
+++ b/src/organizerproxy.cpp
@@ -104,6 +104,11 @@ HANDLE OrganizerProxy::startApplication(const QString &executable, const QString
return m_Proxied->startApplication(executable, args, cwd, profile);
}
+bool OrganizerProxy::waitForApplication(HANDLE handle, LPDWORD exitCode) const
+{
+ return m_Proxied->waitForProcessOrJob(handle, exitCode);
+}
+
bool OrganizerProxy::onAboutToRun(const std::function<bool (const QString &)> &func)
{
auto conn = m_Proxied->m_AboutToRun.connect(func);
diff --git a/src/organizerproxy.h b/src/organizerproxy.h
index 017908e5..7e49c99c 100644
--- a/src/organizerproxy.h
+++ b/src/organizerproxy.h
@@ -35,6 +35,7 @@ public:
virtual MOBase::IPluginList *pluginList();
virtual MOBase::IModList *modList();
virtual HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "", const QString &profile = "");
+ virtual bool waitForApplication(HANDLE handle, LPDWORD exitCode = NULL) const;
virtual void refreshModList(bool saveChanges);
virtual bool onAboutToRun(const std::function<bool(const QString&)> &func);
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index 5159871d..3532397d 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -1089,6 +1089,13 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event)
diff = 1;
}
QModelIndexList rows = selectionModel->selectedRows();
+ // remove elements that aren't supposed to be movable
+ QMutableListIterator<QModelIndex> iter(rows);
+ while (iter.hasNext()) {
+ if ((iter.next().flags() & Qt::ItemIsDragEnabled) == 0) {
+ iter.remove();
+ }
+ }
if (keyEvent->key() == Qt::Key_Down) {
for (int i = 0; i < rows.size() / 2; ++i) {
rows.swap(i, rows.size() - i - 1);
diff --git a/src/viewmarkingscrollbar.cpp b/src/viewmarkingscrollbar.cpp
index eca37562..f1b1ba34 100644
--- a/src/viewmarkingscrollbar.cpp
+++ b/src/viewmarkingscrollbar.cpp
@@ -14,6 +14,9 @@ ViewMarkingScrollBar::ViewMarkingScrollBar(QAbstractItemModel *model, QWidget *p
void ViewMarkingScrollBar::paintEvent(QPaintEvent *event)
{
+ if (m_Model == NULL) {
+ return;
+ }
QScrollBar::paintEvent(event);
QStyleOptionSlider styleOption;