summaryrefslogtreecommitdiff
path: root/src/mainwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainwindow.cpp')
-rw-r--r--src/mainwindow.cpp226
1 files changed, 131 insertions, 95 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 8fcd4024..c6413fc1 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -164,7 +164,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
m_Updater(NexusInterface::instance(), this), m_CategoryFactory(CategoryFactory::instance()),
m_CurrentProfile(NULL), m_AskForNexusPW(false),
m_ArchivesInit(false), m_ContextItem(NULL), m_ContextAction(NULL), m_CurrentSaveView(NULL),
- m_GameInfo(new GameInfoImpl()), m_AboutToRun(), m_ModInstalled()
+ m_GameInfo(new GameInfoImpl()), m_AboutToRun(), m_ModInstalled(), m_DidUpdateMasterList(false)
{
ui->setupUi(this);
this->setWindowTitle(ToQString(GameInfo::instance().getGameName()) + " Mod Organizer v" + m_Updater.getVersion().displayString());
@@ -193,7 +193,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
updateToolBar();
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure);
+ ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
// set up mod list
m_ModListSortProxy = new ModListSortProxy(m_CurrentProfile, this);
@@ -320,6 +320,9 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
m_CheckBSATimer.setSingleShot(true);
connect(&m_CheckBSATimer, SIGNAL(timeout()), this, SLOT(checkBSAList()));
+ m_UpdateProblemsTimer.setSingleShot(true);
+ connect(&m_UpdateProblemsTimer, SIGNAL(timeout()), this, SLOT(updateProblemsButton()));
+
m_SaveMetaTimer.setSingleShot(false);
connect(&m_SaveMetaTimer, SIGNAL(timeout()), this, SLOT(saveModMetas()));
m_SaveMetaTimer.start(5000);
@@ -530,6 +533,14 @@ void MainWindow::updateToolBar()
}
+void MainWindow::scheduleUpdateButton()
+{
+ if (!m_UpdateProblemsTimer.isActive()) {
+ m_UpdateProblemsTimer.start(1000);
+ }
+}
+
+
void MainWindow::updateProblemsButton()
{
int numProblems = checkForProblems();
@@ -661,7 +672,7 @@ void MainWindow::createHelpWidget()
}
-void MainWindow::saveArchiveList()
+bool MainWindow::saveArchiveList()
{
if (m_ArchivesInit) {
SafeWriteFile archiveFile(m_CurrentProfile->getArchivesFileName());
@@ -680,10 +691,12 @@ void MainWindow::saveArchiveList()
}
if (archiveFile.commitIfDifferent(m_ArchiveListHash)) {
qDebug("%s saved", qPrintable(QDir::toNativeSeparators(m_CurrentProfile->getArchivesFileName())));
+ return true;
}
} else {
qWarning("archive list not initialised");
}
+ return false;
}
void MainWindow::savePluginList()
@@ -1034,31 +1047,48 @@ void MainWindow::toolPluginInvoke()
void MainWindow::requestDownload(const QUrl &url, QNetworkReply *reply)
{
QToolButton *browserBtn = qobject_cast<QToolButton*>(ui->toolBar->widgetForAction(ui->actionNexus));
-
- QList<QAction*> browserActions = browserBtn->menu()->actions();
- foreach (QAction *action, browserActions) {
- // the nexus action doesn't have a plugin connected currently
- if (action->data().isValid()) {
- IPluginModPage *plugin = qobject_cast<IPluginModPage*>(qvariant_cast<QObject*>(action->data()));
- if (plugin == NULL) {
- qCritical("invalid mod page. This is a bug");
- continue;
- }
- ModRepositoryFileInfo *fileInfo = new ModRepositoryFileInfo();
- if (plugin->handlesDownload(url, reply->url(), *fileInfo)) {
- fileInfo->repository = plugin->name();
- m_DownloadManager.addDownload(reply, fileInfo);
- return;
+ if (browserBtn->menu() != NULL) {
+ // go through modpage plugins, find one to handle the download.
+ QList<QAction*> browserActions = browserBtn->menu()->actions();
+ foreach (QAction *action, browserActions) {
+ // the nexus action doesn't have a plugin connected currently
+ if (action->data().isValid()) {
+ IPluginModPage *plugin = qobject_cast<IPluginModPage*>(qvariant_cast<QObject*>(action->data()));
+ if (plugin == NULL) {
+ qCritical("invalid mod page. This is a bug");
+ continue;
+ }
+ ModRepositoryFileInfo *fileInfo = new ModRepositoryFileInfo();
+ if (plugin->handlesDownload(url, reply->url(), *fileInfo)) {
+ fileInfo->repository = plugin->name();
+ m_DownloadManager.addDownload(reply, fileInfo);
+ return;
+ }
}
}
}
- if (QMessageBox::question(this, tr("Download?"),
- tr("A download has been started but no installed page plugin recognizes it.\n"
- "If you download anyway no information (i.e. version) will be associated with the download.\n"
- "Continue?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo());
+ // no mod found that could handle the download. Is it a nexus mod?
+ if (url.host() == "www.nexusmods.com") {
+ int modID = 0;
+ int fileID = 0;
+ QRegExp modExp("mods/(\\d+)");
+ if (modExp.indexIn(url.toString()) != -1) {
+ modID = modExp.cap(1).toInt();
+ }
+ QRegExp fileExp("fid=(\\d+)");
+ if (fileExp.indexIn(reply->url().toString()) != -1) {
+ fileID = fileExp.cap(1).toInt();
+ }
+ m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo(modID, fileID));
+ } else {
+ if (QMessageBox::question(this, tr("Download?"),
+ tr("A download has been started but no installed page plugin recognizes it.\n"
+ "If you download anyway no information (i.e. version) will be associated with the download.\n"
+ "Continue?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
+ m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo());
+ }
}
}
@@ -1131,7 +1161,7 @@ bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName)
IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(plugin);
if (diagnose != NULL) {
m_DiagnosisPlugins.push_back(diagnose);
- diagnose->onInvalidated([&] () { this->updateProblemsButton(); });
+ diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); });
}
}
{ // mod page plugin
@@ -1401,10 +1431,8 @@ void MainWindow::setExecutableIndex(int index)
} else {
executableBox->setCurrentIndex(1);
}
-
}
-
void MainWindow::activateSelectedProfile()
{
QString profileName = ui->profileBox->currentText();
@@ -1423,7 +1451,6 @@ void MainWindow::activateSelectedProfile()
refreshModList();
}
-
void MainWindow::on_profileBox_currentIndexChanged(int index)
{
if (ui->profileBox->isEnabled()) {
@@ -1629,8 +1656,6 @@ bool MainWindow::refreshProfiles(bool selectProfile)
std::set<QString> MainWindow::enabledArchives()
{
std::set<QString> result;
-
-
QFile archiveFile(m_CurrentProfile->getArchivesFileName());
if (archiveFile.open(QIODevice::ReadOnly)) {
while (!archiveFile.atEnd()) {
@@ -1641,7 +1666,6 @@ std::set<QString> MainWindow::enabledArchives()
return result;
}
-
void MainWindow::refreshDirectoryStructure()
{
m_DirectoryUpdate = true;
@@ -1655,7 +1679,6 @@ void MainWindow::refreshDirectoryStructure()
QTimer::singleShot(0, &m_DirectoryRefresher, SLOT(refresh()));
}
-
#if QT_VERSION >= 0x050000
extern QPixmap qt_pixmapFromWinHICON(HICON icon);
#else
@@ -1675,7 +1698,6 @@ QIcon MainWindow::iconForExecutable(const QString &filePath)
}
}
-
void MainWindow::refreshExecutablesList()
{
QComboBox* executablesList = findChild<QComboBox*>("executablesListBox");
@@ -1788,7 +1810,8 @@ void MainWindow::refreshModList(bool saveChanges)
if (saveChanges) {
m_CurrentProfile->writeModlistNow(true);
}
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure);
+ ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
+
m_CurrentProfile->refreshModStatus();
m_ModList.notifyChange(-1);
@@ -1952,15 +1975,6 @@ void MainWindow::checkBSAList()
item->setIcon(0, QIcon(":/MO/gui/warning"));
item->setToolTip(0, tr("This bsa is enabled in the ini file so it may be required!"));
modWarning = true;
-/* } else {
- QString espName = filename.mid(0, filename.length() - 3).append("esp").toLower();
- QString esmName = filename.mid(0, filename.length() - 3).append("esm").toLower();
- if (m_PluginList.isEnabled(espName) || m_PluginList.isEnabled(esmName)) {
- item->setIcon(0, QIcon(":/MO/gui/warning"));
- item->setToolTip(0, tr("This archive will still be loaded since there is a plugin of the same name but "
- "its files will not follow installation order!"));
- modWarning = true;
- }*/
}
}
}
@@ -2615,7 +2629,6 @@ void MainWindow::directory_refreshed()
if (m_CurrentProfile != NULL) {
refreshLists();
}
-// m_RefreshProgress->setVisible(false);
// some problem-reports may rely on the virtual directory tree so they need to be updated
// now
@@ -2628,7 +2641,6 @@ void MainWindow::directory_refreshed()
statusBar()->hide();
}
-
void MainWindow::externalMessage(const QString &message)
{
if (message.left(6).toLower() == "nxm://") {
@@ -2637,31 +2649,54 @@ void MainWindow::externalMessage(const QString &message)
}
}
+void MainWindow::updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo)
+{
+ // add files of the bsa to the directory structure
+ m_DirectoryRefresher.addModFilesToStructure(m_DirectoryStructure
+ , modInfo->name()
+ , m_CurrentProfile->getModPriority(index)
+ , modInfo->absolutePath()
+ , modInfo->stealFiles()
+ );
+ DirectoryRefresher::cleanStructure(m_DirectoryStructure);
+ // need to refresh plugin list now so we can activate esps
+ refreshESPList();
+ // activate all esps of the specified mod so the bsas get activated along with it
+ updateModActiveState(index, true);
+ // now we need to refresh the bsa list and save it so there is no confusion about what archives are avaiable and active
+ refreshBSAList();
+ saveArchiveList();
+ m_DirectoryRefresher.setMods(m_CurrentProfile->getActiveMods(), enabledArchives());
+
+ // finally also add files from bsas to the directory structure
+ m_DirectoryRefresher.addModBSAToStructure(m_DirectoryStructure
+ , modInfo->name()
+ , m_CurrentProfile->getModPriority(index)
+ , modInfo->absolutePath()
+ , modInfo->archives()
+ );
+}
void MainWindow::modStatusChanged(unsigned int index)
{
try {
ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
if (m_CurrentProfile->modEnabled(index)) {
- m_DirectoryRefresher.addModToStructure(m_DirectoryStructure
- , modInfo->name()
- , m_CurrentProfile->getModPriority(index)
- , modInfo->absolutePath()
- , modInfo->stealFiles()
- , modInfo->archives());
- DirectoryRefresher::cleanStructure(m_DirectoryStructure);
+ updateModInDirectoryStructure(index, modInfo);
} else {
if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name()));
origin.enable(false);
}
}
+ modInfo->clearCaches();
for (unsigned int i = 0; i < m_CurrentProfile->numMods(); ++i) {
ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
int priority = m_CurrentProfile->getModPriority(i);
if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
- m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority);
+ // priorities in the directory structure are one higher because data is 0
+ m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority + 1);
}
}
m_DirectoryStructure->getFileRegister()->sortOrigins();
@@ -2687,7 +2722,8 @@ void MainWindow::modorder_changed()
int priority = m_CurrentProfile->getModPriority(i);
if (m_CurrentProfile->modEnabled(i)) {
ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
- m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority);
+ // priorities in the directory structure are one higher because data is 0
+ m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority + 1);
}
}
refreshBSAList();
@@ -2706,33 +2742,30 @@ void MainWindow::procFinished(int, QProcess::ExitStatus)
this->sender()->deleteLater();
}
-
void MainWindow::profileRefresh()
{
- m_CurrentProfile->writeModlist();
+ // have to refresh mods twice (again in refreshModList), otherwise the refresh isn't complete. Not sure why
+ ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
+ m_CurrentProfile->refreshModStatus();
refreshModList();
}
-
void MainWindow::showMessage(const QString &message)
{
MessageDialog::showMessage(message, this);
}
-
void MainWindow::showError(const QString &message)
{
reportError(message);
}
-
void MainWindow::installMod_clicked()
{
installMod();
}
-
void MainWindow::renameModInList(QFile &modList, const QString &oldName, const QString &newName)
{
//TODO this code needs to be merged with ModList::readFrom
@@ -2894,6 +2927,8 @@ void MainWindow::refreshFilters()
addFilterItem(NULL, tr("<Checked>"), CategoryFactory::CATEGORY_SPECIAL_CHECKED);
addFilterItem(NULL, tr("<Unchecked>"), CategoryFactory::CATEGORY_SPECIAL_UNCHECKED);
addFilterItem(NULL, tr("<Update>"), CategoryFactory::CATEGORY_SPECIAL_UPDATEAVAILABLE);
+ addFilterItem(NULL, tr("<Managed by MO>"), CategoryFactory::CATEGORY_SPECIAL_MANAGED);
+ addFilterItem(NULL, tr("<Managed outside MO>"), CategoryFactory::CATEGORY_SPECIAL_UNMANAGED);
addFilterItem(NULL, tr("<No category>"), CategoryFactory::CATEGORY_SPECIAL_NOCATEGORY);
addFilterItem(NULL, tr("<Conflicted>"), CategoryFactory::CATEGORY_SPECIAL_CONFLICT);
addFilterItem(NULL, tr("<Not Endorsed>"), CategoryFactory::CATEGORY_SPECIAL_NOTENDORSED);
@@ -2958,37 +2993,37 @@ void MainWindow::restoreBackup_clicked()
}
}
-
-void MainWindow::modlistChanged(const QModelIndex &index, int role)
+void MainWindow::updateModActiveState(int index, bool active)
{
- if (role == Qt::CheckStateRole) {
- if (index.data(Qt::CheckStateRole).toBool()) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(index.row());
-
- QDir dir(modInfo->absolutePath());
- foreach (const QString &esm, dir.entryList(QStringList("*.esm"), QDir::Files)) {
- m_PluginList.enableESP(esm);
- }
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
- int enabled = 0;
- QStringList esps = dir.entryList(QStringList("*.esp"), QDir::Files);
- foreach (const QString &esp, esps) {
- if (!m_PluginList.isEnabled(esp)) {
- m_PluginList.enableESP(esp);
- ++enabled;
- }
- }
- if (enabled > 1) {
- MessageDialog::showMessage(tr("Multiple esps activated, please check that they don't conflict."), this);
- }
- m_PluginList.refreshLoadOrder();
- // immediately save affected lists
- savePluginList();
- saveArchiveList();
+ QDir dir(modInfo->absolutePath());
+ foreach (const QString &esm, dir.entryList(QStringList("*.esm"), QDir::Files)) {
+ m_PluginList.enableESP(esm, active);
+ }
+ int enabled = 0;
+ QStringList esps = dir.entryList(QStringList("*.esp"), QDir::Files);
+ foreach (const QString &esp, esps) {
+ if (active && !m_PluginList.isEnabled(esp)) {
+ m_PluginList.enableESP(esp, active);
+ ++enabled;
}
}
+ if (active && (enabled > 1)) {
+ MessageDialog::showMessage(tr("Multiple esps activated, please check that they don't conflict."), this);
+ }
+ m_PluginList.refreshLoadOrder();
+ // immediately save affected lists
+ savePluginList();
+// refreshBSAList();
}
+void MainWindow::modlistChanged(const QModelIndex&, int)
+{
+/* if (role == Qt::CheckStateRole) {
+ updateModActiveState(index.row(), index.data(Qt::CheckStateRole).toBool());
+ }*/
+}
void MainWindow::removeMod_clicked()
{
@@ -3145,12 +3180,9 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index,
dialog->raise();
dialog->activateWindow();
connect(dialog, SIGNAL(finished(int)), this, SLOT(overwriteClosed(int)));
- } else if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_FOREIGN) != flags.end()) {
- // nop - no menu for this file type
- return;
} else {
modInfo->saveMeta();
- ModInfoDialog dialog(modInfo, m_DirectoryStructure, this);
+ ModInfoDialog dialog(modInfo, m_DirectoryStructure, modInfo->hasFlag(ModInfo::FLAG_FOREIGN), this);
connect(&dialog, SIGNAL(nexusLinkActivated(QString)), this, SLOT(nexusLinkActivated(QString)));
connect(&dialog, SIGNAL(downloadRequest(QString)), this, SLOT(downloadRequestedNXM(QString)));
connect(&dialog, SIGNAL(modOpen(QString, int)), this, SLOT(displayModInformation(QString, int)), Qt::QueuedConnection);
@@ -3707,7 +3739,7 @@ void addMenuAsPushButton(QMenu *menu, QMenu *subMenu)
QMenu *MainWindow::modListContextMenu()
{
- QMenu *menu = new QMenu();
+ QMenu *menu = new QMenu(this);
menu->addAction(tr("Install Mod..."), this, SLOT(installMod_clicked()));
menu->addAction(tr("Enable all visible"), this, SLOT(enableVisibleMods()));
@@ -3734,7 +3766,6 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
if (m_ContextRow == -1) {
// no selection
menu = allMods;
- menu->setParent(this);
} else {
menu = new QMenu(this);
allMods->setTitle(tr("All Mods"));
@@ -4057,6 +4088,7 @@ void MainWindow::on_actionSettings_triggered()
{
QString oldModDirectory(m_Settings.getModDirectory());
QString oldCacheDirectory(m_Settings.getCacheDirectory());
+ bool oldDisplayForeign(m_Settings.displayForeign());
bool proxy = m_Settings.useProxy();
m_Settings.query(this);
m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
@@ -4072,9 +4104,9 @@ void MainWindow::on_actionSettings_triggered()
}
m_DownloadManager.setPreferredServers(m_Settings.getPreferredServers());
- if (m_Settings.getModDirectory() != oldModDirectory) {
- refreshModList();
- refreshLists();
+ if ((m_Settings.getModDirectory() != oldModDirectory)
+ || (m_Settings.displayForeign() != oldDisplayForeign)) {
+ profileRefresh();
}
if (m_Settings.getCacheDirectory() != oldCacheDirectory) {
@@ -4226,7 +4258,6 @@ void MainWindow::installDownload(int index)
MessageDialog::showMessage(tr("Installation successful"), this);
refreshModList();
-
QModelIndexList posList = m_ModList.match(m_ModList.index(0, 0), Qt::DisplayRole, static_cast<const QString&>(modName));
if (posList.count() == 1) {
ui->modList->scrollTo(posList.at(0));
@@ -5254,6 +5285,11 @@ void MainWindow::on_bossButton_clicked()
parameters << "--game" << ToQString(GameInfo::instance().getGameShortName())
<< "--gamePath" << QString("\"%1\"").arg(ToQString(GameInfo::instance().getGameDirectory()));
+ if (!m_DidUpdateMasterList) {
+ parameters << "--updateMasterlist";
+ m_DidUpdateMasterList = true;
+ }
+
HANDLE stdOutWrite = INVALID_HANDLE_VALUE;
HANDLE stdOutRead = INVALID_HANDLE_VALUE;
createStdoutPipe(&stdOutRead, &stdOutWrite);