From e0eb97922d5ef4a1448e76f13374ebfda7fda403 Mon Sep 17 00:00:00 2001 From: Tannin Date: Wed, 27 Mar 2013 20:48:33 +0100 Subject: - added hooks for getFileVersion* functions - automatic donwload retry - support for storing multiple download urls - improved "query info" functionality - some cleanup to download manager code - external fomod installer dialog are now brought to front - added shell... functions to have windows handle problematic situations - added visual clue when filters are active - esps are now automatically activated when installing a mod - added option to never endorse a mod - added "previous" and "next" buttons to mod info dialog - improved the way messagedialog text is shortened - coloring in mod info dialog now visible in other color schemes - plugin list is now saved automatically - vanilla bsas are now enabled even if they are not listed in the ini file - bugfix: setting mod to maximum now doesn't try to place the mod below overwrite --- src/mainwindow.cpp | 221 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 157 insertions(+), 64 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5bc339d3..f2f3af65 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -196,14 +196,17 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(ui->savegameList, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(saveSelectionChanged(QListWidgetItem*))); - connect(&m_PluginList, SIGNAL(esplist_changed()), this, SLOT(esplist_changed())); + connect(&m_PluginList, SIGNAL(saveTimer()), this, SLOT(savePluginList())); connect(&m_ModList, SIGNAL(modorder_changed()), this, SLOT(modorder_changed())); connect(&m_ModList, SIGNAL(removeOrigin(QString)), this, SLOT(removeOrigin(QString))); connect(&m_ModList, SIGNAL(showMessage(QString)), this, SLOT(showMessage(QString))); connect(&m_ModList, SIGNAL(modRenamed(QString,QString)), this, SLOT(modRenamed(QString,QString))); + connect(m_ModListSortProxy, SIGNAL(filterActive(bool)), this, SLOT(modFilterActive(bool))); connect(ui->modFilterEdit, SIGNAL(textChanged(QString)), m_ModListSortProxy, SLOT(updateFilter(QString))); connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), m_PluginListSortProxy, SLOT(updateFilter(QString))); - connect(&m_ModList, SIGNAL(modlist_changed(int)), m_ModListSortProxy, SLOT(invalidate())); + connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(espFilterChanged(QString))); + connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), m_ModListSortProxy, SLOT(invalidate())); + connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), this, SLOT(modlistChanged(QModelIndex, int))); connect(&m_ModList, SIGNAL(removeSelectedMods()), this, SLOT(removeMod_clicked())); connect(&m_DirectoryRefresher, SIGNAL(refreshed()), this, SLOT(directory_refreshed())); @@ -212,6 +215,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(&m_Settings, SIGNAL(languageChanged(QString)), this, SLOT(languageChange(QString))); connect(&m_Settings, SIGNAL(styleChanged(QString)), this, SIGNAL(styleChanged(QString))); + connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString))); connect(&m_Updater, SIGNAL(restart()), this, SLOT(close())); connect(&m_Updater, SIGNAL(updateAvailable()), this, SLOT(updateAvailable())); @@ -252,6 +256,11 @@ MainWindow::~MainWindow() delete m_GameInfo; } +void MainWindow::updateStyle(const QString&) +{ + // no effect? + ensurePolished(); +} void MainWindow::resizeEvent(QResizeEvent *event) { @@ -503,6 +512,43 @@ void MainWindow::saveArchiveList() } } +void MainWindow::savePluginList() +{ + m_PluginList.saveTo(m_CurrentProfile->getPluginsFileName(), + m_CurrentProfile->getLoadOrderFileName(), + m_CurrentProfile->getLockedOrderFileName(), + m_CurrentProfile->getDeleterFileName(), + m_Settings.hideUncheckedPlugins()); + m_PluginList.saveLoadOrder(*m_DirectoryStructure); +} + +void MainWindow::modFilterActive(bool active) +{ + if (active) { + ui->modList->setStyleSheet("QTreeView { border: 2px ridge #f00; }"); + } else { + ui->modList->setStyleSheet(""); + } +} + +void MainWindow::espFilterChanged(const QString &filter) +{ + if (!filter.isEmpty()) { + ui->espList->setStyleSheet("QTreeView { border: 2px ridge #f00; }"); + } else { + ui->espList->setStyleSheet(""); + } +} + +void MainWindow::downloadFilterChanged(const QString &filter) +{ + if (!filter.isEmpty()) { + ui->downloadView->setStyleSheet("QTreeView { border: 2px ridge #f00; }"); + } else { + ui->downloadView->setStyleSheet(""); + } +} + bool MainWindow::saveCurrentLists() { if (m_DirectoryUpdate) { @@ -511,19 +557,8 @@ bool MainWindow::saveCurrentLists() } // save plugin list - try { - m_PluginList.saveTo(m_CurrentProfile->getPluginsFileName(), - m_CurrentProfile->getLoadOrderFileName(), - m_CurrentProfile->getLockedOrderFileName(), - m_CurrentProfile->getDeleterFileName(), - m_Settings.hideUncheckedPlugins()); - - if (!m_PluginList.saveLoadOrder(*m_DirectoryStructure)) { - MessageDialog::showMessage(tr("load order could not be saved"), this); - } else { - ui->btnSave->setEnabled(false); - } + savePluginList(); } catch (const std::exception &e) { reportError(tr("failed to save load order: %1").arg(e.what())); } @@ -644,6 +679,7 @@ void MainWindow::closeEvent(QCloseEvent* event) void MainWindow::createFirstProfile() { if (!refreshProfiles(false)) { + qDebug("creating default profile"); Profile newProf("Default", false); refreshProfiles(false); } @@ -895,6 +931,11 @@ QString MainWindow::profilePath() const return m_CurrentProfile->getPath(); } +QString MainWindow::downloadsPath() const +{ + return QDir::fromNativeSeparators(m_Settings.getDownloadDirectory()); +} + VersionInfo MainWindow::appVersion() const { return m_Updater.getVersion(); @@ -1404,8 +1445,6 @@ void MainWindow::refreshESPList() m_CurrentProfile->getLoadOrderFileName(), m_CurrentProfile->getLockedOrderFileName()); //m_PluginList.readFrom(m_CurrentProfile->getPluginsFileName()); - - findChild("btnSave")->setEnabled(false); } @@ -1432,6 +1471,11 @@ void MainWindow::refreshBSAList() if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), L"", buffer, 256, iniFileName.c_str()) != 0) { m_DefaultArchives = ToQString(buffer).split(','); + } else { + std::vector vanillaBSAs = GameInfo::instance().getVanillaBSAs(); + for (auto iter = vanillaBSAs.begin(); iter != vanillaBSAs.end(); ++iter) { + m_DefaultArchives.append(ToQString(*iter)); + } } if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().append(L"2").c_str(), @@ -1651,7 +1695,6 @@ void MainWindow::on_btnRefreshData_clicked() void MainWindow::on_tabWidget_currentChanged(int index) { - saveCurrentLists(); if (index == 0) { refreshESPList(); } else if (index == 1) { @@ -1721,12 +1764,6 @@ void MainWindow::installMod() } -void MainWindow::on_btnSave_clicked() -{ - saveCurrentLists(); -} - - void MainWindow::on_startButton_clicked() { QComboBox* executablesList = findChild("executablesListBox"); @@ -1982,12 +2019,6 @@ bool MainWindow::setCurrentProfile(const QString &name) } -void MainWindow::esplist_changed() -{ - findChild("btnSave")->setEnabled(true); -} - - void MainWindow::refresher_progress(int percent) { m_RefreshProgress->setValue(percent); @@ -2220,6 +2251,8 @@ void MainWindow::addCategoryFilters(QTreeWidgetItem *root, const std::set & void MainWindow::refreshFilters() { + QItemSelection currentSelection = ui->modList->selectionModel()->selection(); + ui->modList->setCurrentIndex(QModelIndex()); // save previous filter text so we can restore it later, in case the filter still exists then @@ -2258,6 +2291,8 @@ void MainWindow::refreshFilters() currentItem = currentItem->parent(); } } + + ui->modList->selectionModel()->select(currentSelection, QItemSelectionModel::Select); } @@ -2284,7 +2319,7 @@ void MainWindow::restoreBackup_clicked() (QMessageBox::question(this, tr("Overwrite?"), tr("This will replace the existing mod \"%1\". Continue?").arg(regName), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)) { - if (modDir.exists(regName) && !removeDir(modDir.absoluteFilePath(regName))) { + if (modDir.exists(regName) && !shellDelete(QStringList(modDir.absoluteFilePath(regName)), NULL)) { reportError(tr("failed to remove mod \"%1\"").arg(regName)); } else { QString destinationPath = QDir::fromNativeSeparators(m_Settings.getModDirectory()) + "/" + regName; @@ -2298,6 +2333,29 @@ void MainWindow::restoreBackup_clicked() } +void MainWindow::modlistChanged(const QModelIndex &index, int role) +{ + 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); + } + + QStringList esps = dir.entryList(QStringList("*.esp"), QDir::Files); + foreach (const QString &esp, esps) { + m_PluginList.enableESP(esp); + } + if (esps.count() > 1) { + MessageDialog::showMessage(tr("Multiple esps activated, please check that they don't conflict."), this); + } + } + } +} + + void MainWindow::removeMod_clicked() { try { @@ -2370,6 +2428,11 @@ void MainWindow::endorse_clicked() endorseMod(ModInfo::getByIndex(m_ContextRow)); } +void MainWindow::dontendorse_clicked() +{ + ModInfo::getByIndex(m_ContextRow)->setNeverEndorse(); +} + void MainWindow::unendorse_clicked() { @@ -2397,13 +2460,14 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, ModInfoDialog dialog(modInfo, m_DirectoryStructure, 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))); + connect(&dialog, SIGNAL(modOpen(QString, int)), this, SLOT(displayModInformation(QString, int)), Qt::QueuedConnection); + connect(&dialog, SIGNAL(modOpenNext()), this, SLOT(modOpenNext()), Qt::QueuedConnection); + connect(&dialog, SIGNAL(modOpenPrev()), this, SLOT(modOpenPrev()), Qt::QueuedConnection); connect(&dialog, SIGNAL(originModified(int)), this, SLOT(originModified(int))); connect(&dialog, SIGNAL(endorseMod(ModInfo::Ptr)), this, SLOT(endorseMod(ModInfo::Ptr))); dialog.openTab(tab); dialog.exec(); - modInfo->saveMeta(); emit modInfoDisplayed(); } @@ -2429,6 +2493,43 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, } +void MainWindow::modOpenNext() +{ + QModelIndex index = m_ModListSortProxy->mapFromSource(m_ModList.index(m_ContextRow, 0)); + index = m_ModListSortProxy->index((index.row() + 1) % m_ModListSortProxy->rowCount(), 0); + + m_ContextRow = m_ModListSortProxy->mapToSource(index).row(); + ModInfo::Ptr mod = ModInfo::getByIndex(m_ContextRow); + std::vector flags = mod->getFlags(); + if ((std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) || + (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end())) { + // skip overwrite and backups + modOpenNext(); + } else { + displayModInformation(m_ContextRow); + } +} + +void MainWindow::modOpenPrev() +{ + QModelIndex index = m_ModListSortProxy->mapFromSource(m_ModList.index(m_ContextRow, 0)); + int row = index.row() - 1; + if (row == -1) { + row = m_ModListSortProxy->rowCount() - 1; + } + + m_ContextRow = m_ModListSortProxy->mapToSource(m_ModListSortProxy->index(row, 0)).row(); + ModInfo::Ptr mod = ModInfo::getByIndex(m_ContextRow); + std::vector flags = mod->getFlags(); + if ((std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) || + (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) != flags.end())) { + // skip overwrite and backups + modOpenPrev(); + } else { + displayModInformation(m_ContextRow); + } +} + void MainWindow::displayModInformation(const QString &modName, int tab) { unsigned int index = ModInfo::getIndex(modName); @@ -2537,31 +2638,6 @@ void MainWindow::syncOverwrite() } -void MainWindow::setPriorityMax() -{ - int newPriority = m_CurrentProfile->numMods() - 1; - m_CurrentProfile->setModPriority(m_ContextRow, newPriority); -} - - -void MainWindow::setPriorityManually() -{ -// m_CurrentProfile->setModPriority(m_ContextRow, m_CurrentProfile->numMods() - 1); - - int current = m_CurrentProfile->getModPriority(m_ContextRow); - int newPriority = QInputDialog::getInt(this, tr("Priority"), tr("Choose Priority"), current, 0, m_ModList.rowCount() - 1); - m_ModList.changeModPriority(m_ContextRow, newPriority); -// m_CurrentProfile->setModPriority(m_ContextRow, newPriority); -} - - -void MainWindow::setPriorityMin() -{ - int newPriority = 0; - m_CurrentProfile->setModPriority(m_ContextRow, newPriority); -} - - void MainWindow::cancelModListEditor() { ui->modList->setEnabled(false); @@ -2572,6 +2648,7 @@ void MainWindow::cancelModListEditor() void MainWindow::on_modList_doubleClicked(const QModelIndex &index) { try { + m_ContextRow = m_ModListSortProxy->mapToSource(index).row(); displayModInformation(m_ModListSortProxy->mapToSource(index).row()); // workaround to cancel the editor that might have opened because of // selection-click @@ -2648,12 +2725,21 @@ void MainWindow::saveCategories() return; } // m_ModList.resetCategories(m_ContextRow); - saveCategoriesFromMenu(menu, m_ContextRow); + + QModelIndexList selected = ui->modList->selectionModel()->selectedRows(); + if (selected.size() > 0) { + for (int i = 0; i < selected.size(); ++i) { + saveCategoriesFromMenu(menu, m_ModListSortProxy->mapToSource(selected.at(i)).row()); + } + } else { + saveCategoriesFromMenu(menu, m_ContextRow); + } refreshFilters(); } + void MainWindow::savePrimaryCategory() { QMenu *menu = qobject_cast(sender()); @@ -2662,13 +2748,16 @@ void MainWindow::savePrimaryCategory() return; } - ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow); foreach (QAction* action, menu->actions()) { QWidgetAction *widgetAction = qobject_cast(action); if (widgetAction != NULL) { QRadioButton *btn = qobject_cast(widgetAction->defaultWidget()); if (btn->isChecked()) { - modInfo->setPrimaryCategory(widgetAction->data().toInt()); + QModelIndexList selected = ui->modList->selectionModel()->selectedRows(); + for (int i = 0; i < selected.size(); ++i) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ModListSortProxy->mapToSource(selected.at(i)).row()); + modInfo->setPrimaryCategory(widgetAction->data().toInt()); + } break; } } @@ -2847,6 +2936,10 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) } break; case ModInfo::ENDORSED_FALSE: { menu.addAction(tr("Endorse"), this, SLOT(endorse_clicked())); + menu.addAction(tr("Don't endorse"), this, SLOT(dontendorse_clicked())); + } break; + case ModInfo::ENDORSED_NEVER: { + menu.addAction(tr("Endorse"), this, SLOT(endorse_clicked())); } break; default: { QAction *action = new QAction(tr("Endorsement state unknown"), &menu); @@ -2875,7 +2968,8 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) void MainWindow::on_categoriesList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *) { if (current != NULL) { - m_ModListSortProxy->setCategoryFilter(current->data(0, Qt::UserRole).toInt()); + int filter = current->data(0, Qt::UserRole).toInt(); + m_ModListSortProxy->setCategoryFilter(filter); ui->currentCategoryLabel->setText(QString("(%1)").arg(current->text(0))); } } @@ -2986,7 +3080,6 @@ void MainWindow::linkToolbar() void MainWindow::linkDesktop() { QComboBox* executablesList = findChild("executablesListBox"); -// QPushButton *linkButton = findChild("linkDesktopButton"); const Executable &selectedExecutable = executablesList->itemData(executablesList->currentIndex()).value(); QString linkName = getDesktopDirectory() + "\\" + selectedExecutable.m_Title + ".lnk"; @@ -3131,7 +3224,7 @@ void MainWindow::downloadRequestedNXM(const QString &url) void MainWindow::downloadRequested(QNetworkReply *reply, int modID, const QString &fileName) { try { - if (m_DownloadManager.addDownload(reply, fileName, modID)) { + if (m_DownloadManager.addDownload(reply, QStringList(), fileName, modID)) { MessageDialog::showMessage(tr("Download started"), this); } } catch (const std::exception &e) { @@ -3228,7 +3321,6 @@ void MainWindow::installDownload(int index) } else { reportError(tr("mod \"%1\" not found").arg(modName)); } - m_DownloadManager.markInstalled(index); emit modInstalled(); @@ -3558,6 +3650,7 @@ void MainWindow::updateDownloadListDelegate() DownloadListSortProxy *sortProxy = new DownloadListSortProxy(&m_DownloadManager, ui->downloadView); sortProxy->setSourceModel(new DownloadList(&m_DownloadManager, ui->downloadView)); connect(ui->downloadFilterEdit, SIGNAL(textChanged(QString)), sortProxy, SLOT(updateFilter(QString))); + connect(ui->downloadFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(downloadFilterChanged(QString))); ui->downloadView->setModel(sortProxy); ui->downloadView->sortByColumn(1, Qt::AscendingOrder); -- cgit v1.3.1 From 59d6b7840b1e7fdbb7475010273047b7bb185d3a Mon Sep 17 00:00:00 2001 From: Tannin Date: Fri, 29 Mar 2013 09:41:41 +0100 Subject: - post-merge cleanup --- src/installationmanager.cpp | 263 -------------------------------------- src/mainwindow.cpp | 1 - src/mainwindow.ui | 4 +- src/resources/emblem-favorite.png | Bin 915 -> 839 bytes 4 files changed, 2 insertions(+), 266 deletions(-) (limited to 'src/mainwindow.cpp') diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp index 96d3743f..1abb19da 100644 --- a/src/installationmanager.cpp +++ b/src/installationmanager.cpp @@ -684,269 +684,6 @@ bool EndsWith(LPCWSTR string, LPCWSTR subString) } -bool InstallationManager::installFomodInternal(DirectoryTree *&baseNode, const QString &fomodPath, const QString &modsDirectory, - int modID, const QString &version, const QString &newestVersion, int categoryID, - QString &modName, bool nameGuessed, bool &manualRequest) -{ - qDebug("treating as fomod archive"); - - FileData* const *data; - size_t size; - m_CurrentArchive->getFileList(data, size); - wchar_t *installerFiles[] = { L"fomod\\info.xml", L"fomod\\ModuleConfig.xml", - L"fomod\\script.cs", L"fomod\\screenshot.png", NULL }; - for (size_t i = 0; i < size; ++i) { - data[i]->setSkip(true); - if (data[i]->getFileName() == NULL) { - qCritical("invalid archive file name"); - } - for (int fileIdx = 0; installerFiles[fileIdx] != NULL; ++fileIdx) { - if (EndsWith(data[i]->getFileName(), installerFiles[fileIdx])) { - wchar_t *baseName = wcsrchr(installerFiles[fileIdx], '\\'); - if (baseName != NULL) { - data[i]->setSkip(false); - data[i]->setOutputFileName(baseName); - m_TempFilesToDelete.insert(ToQString(baseName)); - } else { - qCritical("failed to find backslash in %ls", installerFiles[fileIdx]); - } - break; - } - } - if (EndsWith(data[i]->getFileName(), L".png") || - EndsWith(data[i]->getFileName(), L".jpg") || - EndsWith(data[i]->getFileName(), L".gif") || - EndsWith(data[i]->getFileName(), L".bmp")) { - const wchar_t *baseName = wcsrchr(data[i]->getFileName(), '\\'); - if (baseName == NULL) { - baseName = data[i]->getFileName(); - } else { - ++baseName; - } - data[i]->setSkip(false); - data[i]->setOutputFileName(baseName); - m_TempFilesToDelete.insert(ToQString(baseName)); - } - } - - m_InstallationProgress.setWindowTitle(tr("Preparing installer")); - m_InstallationProgress.setLabelText(QString()); - m_InstallationProgress.setValue(0); - m_InstallationProgress.setWindowModality(Qt::WindowModal); - m_InstallationProgress.show(); - - // unpack only the files we need for the installer - if (!m_CurrentArchive->extract(ToWString(QDir::toNativeSeparators(QDir::tempPath())).c_str(), - new MethodCallback(this, &InstallationManager::updateProgress), - new MethodCallback(this, &InstallationManager::dummyProgressFile), - new MethodCallback(this, &InstallationManager::report7ZipError))) { - throw std::runtime_error("extracting failed"); - } - - m_InstallationProgress.hide(); - - bool success = false; - try { - FomodInstallerDialog dialog(modName, nameGuessed, fomodPath); - - FileData* const *data; - size_t size; - m_CurrentArchive->getFileList(data, size); - - // the installer will want to unpack screenshots... - for (size_t i = 0; i < size; ++i) { - data[i]->setSkip(true); - } - - dialog.initData(); - if (dialog.exec() == QDialog::Accepted) { - modName = dialog.getName(); - baseNode = dialog.updateTree(baseNode); - mapToArchive(baseNode); - - if (doInstall(modsDirectory, modName, modID, version, newestVersion, categoryID)) { - success = true; - } - } else { - if (dialog.manualRequested()) { - manualRequest = true; - modName = dialog.getName(); - } - } - } catch (const std::exception &e) { - reportError(tr("Installation as fomod failed: %1").arg(e.what())); - manualRequest = true; - } - return success; -} - - -static BOOL CALLBACK BringToFront(HWND hwnd, LPARAM lParam) -{ - DWORD procid; - - GetWindowThreadProcessId(hwnd, &procid); - - if (procid == static_cast(lParam)) { - ::SetForegroundWindow(hwnd); - ::SetLastError(NOERROR); - return FALSE; - } else { - return TRUE; - } -} - - -bool InstallationManager::installFomodExternal(const QString &fileName, const QString &pluginsFileName, const QString &modDirectory) -{ - wchar_t binary[MAX_PATH]; - wchar_t parameters[1024]; // maximum: 2xMAX_PATH + approx 20 characters - wchar_t currentDirectory[MAX_PATH]; - - _snwprintf(binary, MAX_PATH, L"%ls", ToWString(QDir::toNativeSeparators(m_NCCPath)).c_str()); - _snwprintf(parameters, 1024, L"-g %ls -p \"%ls\" -i \"%ls\" \"%ls\"", - GameInfo::instance().getGameShortName().c_str(), - ToWString(QDir::toNativeSeparators(pluginsFileName)).c_str(), - ToWString(QDir::toNativeSeparators(fileName)).c_str(), - ToWString(QDir::toNativeSeparators(modDirectory)).c_str()); - _snwprintf(currentDirectory, MAX_PATH, L"%ls", ToWString(QFileInfo(m_NCCPath).absolutePath()).c_str()); - - GameInfo &gameInfo = GameInfo::instance(); - - QStringList copiedFiles; - QStringList patterns; - patterns.append(QDir::fromNativeSeparators(ToQString(gameInfo.getBinaryName()))); - patterns.append("*se_loader.exe"); - QDirIterator iter(QDir::fromNativeSeparators(ToQString(gameInfo.getGameDirectory())), patterns); - QDir modDir(modDirectory); - while (iter.hasNext()) { - iter.next(); - QString destination = modDir.absoluteFilePath(iter.fileInfo().fileName()); - if (QFile::copy(iter.fileInfo().absoluteFilePath(), destination)) { - copiedFiles.append(destination); - } - } - ON_BLOCK_EXIT([&copiedFiles] { - foreach (const QString &fileName, copiedFiles) { - if (!QFile::remove(fileName)) qCritical("failed to remove %s", qPrintable(fileName)); - } - }); - - SHELLEXECUTEINFOW execInfo = {0}; - execInfo.cbSize = sizeof(SHELLEXECUTEINFOW); - execInfo.fMask = SEE_MASK_NOCLOSEPROCESS; - execInfo.hwnd = NULL; - execInfo.lpVerb = L"open"; - execInfo.lpFile = binary; - execInfo.lpParameters = parameters; - execInfo.lpDirectory = currentDirectory; - execInfo.nShow = SW_SHOW; - - if (!::ShellExecuteExW(&execInfo)) { - reportError(tr("failed to start %1").arg(m_NCCPath)); - return false; - } - - QProgressDialog busyDialog(tr("Preparing external installer, this can take a few minutes.\nNote: This installer will not be aware of other installed mods (including skse)!"), tr("Force Close"), 0, 0, m_ParentWidget); - busyDialog.setWindowModality(Qt::WindowModal); - bool confirmCancel = false; - busyDialog.show(); - bool finished = false; - DWORD procid = ::GetProcessId(execInfo.hProcess); - bool inFront = false; - while (true) { - QCoreApplication::processEvents(); - if (!inFront) { - if (!::EnumWindows(BringToFront, procid) && (::GetLastError() == NOERROR)) { - inFront = true; - } - } - DWORD res = ::WaitForSingleObject(execInfo.hProcess, 100); - if (res == WAIT_OBJECT_0) { - finished = true; - break; - } else if ((busyDialog.wasCanceled()) || (res != WAIT_TIMEOUT)) { - if (!confirmCancel) { - confirmCancel = true; - busyDialog.hide(); - busyDialog.reset(); - busyDialog.show(); - busyDialog.setCancelButtonText(tr("Confirm")); - } else { - break; - } - } - } - - if (!finished) { - ::TerminateProcess(execInfo.hProcess, 1); - return false; - } - - DWORD exitCode = 128; - ::GetExitCodeProcess(execInfo.hProcess, &exitCode); - - ::CloseHandle(execInfo.hProcess); - - if ((exitCode == 0) || (exitCode == 10)) { // 0 = success, 10 = incomplete installation - bool errorOccured = false; - { // move all installed files from the data directory one directory up - QDir targetDir(modDirectory); - - QDirIterator dirIter(targetDir.absoluteFilePath("Data"), QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); - bool hasFiles = false; - - while (dirIter.hasNext()) { - dirIter.next(); - QFileInfo fileInfo = dirIter.fileInfo(); - QString newName = targetDir.absoluteFilePath(fileInfo.fileName()); - if (fileInfo.isFile() && QFile::exists(newName)) { - if (!QFile::remove(newName)) { - qCritical("failed to overwrite %s", qPrintable(newName)); - errorOccured = true; - } - } // if it's a directory and the target exists that isn't really a problem - - if (!QFile::rename(fileInfo.absoluteFilePath(), newName)) { - // moving doesn't work when merging - if (!copyDir(fileInfo.absoluteFilePath(), newName, true)) { - qCritical("failed to move %s to %s", qPrintable(fileInfo.absoluteFilePath()), qPrintable(newName)); - errorOccured = true; - } - } - hasFiles = true; - } - // recognition of canceled installation in the external installer is broken so we assume the installation was - // canceled if no files were installed - if (!hasFiles) { - exitCode = 11; - } - } - - QString dataDir = modDirectory.mid(0).append("/Data"); - if (!removeDir(dataDir)) { - qCritical("failed to remove data directory from %s", dataDir.toUtf8().constData()); - errorOccured = true; - } - if (errorOccured) { - reportError(tr("Finalization of the installation failed. The mod may or may not work correctly. See mo_interface.log for details")); - } - } else if (exitCode != 11) { // 11 = manually canceled - reportError(tr("installation failed (errorcode %1)").arg(exitCode)); - } - - if ((exitCode == 0) || (exitCode == 10)) { - return true; - } else { - // after cancelation or error the installer may leave the empty mod directory - if (!shellDelete(QStringList(modDirectory), NULL)) { - qCritical ("failed to remove empty mod directory %s", modDirectory.toUtf8().constData()); - } - return false; - } -} - - bool InstallationManager::wasCancelled() { return m_CurrentArchive->getLastError() == Archive::ERROR_EXTRACT_CANCELLED; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2f6710cc..2efbdc0f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -210,7 +210,6 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(ui->modFilterEdit, SIGNAL(textChanged(QString)), m_ModListSortProxy, SLOT(updateFilter(QString))); connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), m_PluginListSortProxy, SLOT(updateFilter(QString))); connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(espFilterChanged(QString))); - connect(&m_ModList, SIGNAL(modlist_changed(int)), this, SLOT(modlistChanged(int))); connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), this, SLOT(modlistChanged(QModelIndex, int))); connect(&m_ModList, SIGNAL(removeSelectedMods()), this, SLOT(removeMod_clicked())); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index e9fa8db6..b7d0057e 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -299,10 +299,10 @@ p, li { white-space: pre-wrap; } QAbstractItemView::SelectRows - 0 + 20 - false + true true diff --git a/src/resources/emblem-favorite.png b/src/resources/emblem-favorite.png index c777c757..b43e09c7 100644 Binary files a/src/resources/emblem-favorite.png and b/src/resources/emblem-favorite.png differ -- cgit v1.3.1