diff options
| author | Tannin <devnull@localhost> | 2013-09-21 19:25:33 +0200 |
|---|---|---|
| committer | Tannin <devnull@localhost> | 2013-09-21 19:25:33 +0200 |
| commit | dfca8be71b15bc13997110cc8777dd5a84a1fde7 (patch) | |
| tree | aac3cf02be006c1f5a15c48872db965fa6f7b10f /src/mainwindow.cpp | |
| parent | 08037bf876659d52b8bb8be26c7aca362555ef85 (diff) | |
- esp reader now handles invalid files more gracefully
- files moved will now also be treated as "deleted" in the old location so a newly created file with that same name is not created in overwrite
- introduced a mechanism by which MO can recognize if it crashed before when attempting to load a plugin. That plugin can be blacklisted so it doesn't get loaded again
- plugins can now programaticaly change their settings
- plugins can now store data persistently without exposing that data as settings
- requesting an unset-setting from a plugin is no longer treated as a bug
- clarified warning message for when files are in overwrite directory
- the proxyPython plugin will now discover if python initialization crashed MO on a previous session and give the user a chance to fix it or disable the plugin
- bugfix: GetModuleFileName modified the buffer past the zero termination. While this doesn't violate the API documentation it is different from the regular windows implementation
- bugfix: proxy plugins couldn't access the parent widget
- bugfix: when moving a file from overwrite to a mod the in-memory file structure wasn't updated
- bugfix: name input dialog for profiles allowed names that weren't valid directory names
- bugfix: profile dialog wasn't able to delete profiles if the name started or ended in whitespaces
- bugfix: The name-cells for plugin settings could be changed (without effect)
- removed a few obsolete files from the repository
Diffstat (limited to 'src/mainwindow.cpp')
| -rw-r--r-- | src/mainwindow.cpp | 94 |
1 files changed, 85 insertions, 9 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2c5e3707..ffec91a1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -98,6 +98,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QNetworkInterface> #include <QNetworkProxy> #include <QtConcurrentRun> +#include <QCoreApplication> #ifdef TEST_MODELS @@ -233,6 +234,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), this, SLOT(modlistChanged(QModelIndex, int))); connect(&m_ModList, SIGNAL(removeSelectedMods()), this, SLOT(removeMod_clicked())); connect(&m_ModList, SIGNAL(requestColumnSelect(QPoint)), this, SLOT(displayColumnSelection(QPoint))); + connect(&m_ModList, SIGNAL(fileMoved(QString, QString, QString)), this, SLOT(fileMoved(QString, QString, QString))); connect(ui->modList, SIGNAL(dropModeUpdate(bool)), &m_ModList, SLOT(dropModeUpdate(bool))); connect(m_ModListSortProxy, SIGNAL(filterActive(bool)), this, SLOT(modFilterActive(bool))); connect(ui->modFilterEdit, SIGNAL(textChanged(QString)), m_ModListSortProxy, SLOT(updateFilter(QString))); @@ -997,6 +999,7 @@ bool MainWindow::registerPlugin(QObject *plugin) { // proxy plugins IPluginProxy *proxy = qobject_cast<IPluginProxy*>(plugin); if (verifyPlugin(proxy)) { + proxy->setParentWidget(this); QStringList pluginNames = proxy->pluginList(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath())); foreach (const QString &pluginName, pluginNames) { try { @@ -1040,11 +1043,38 @@ void MainWindow::loadPlugins() registerPlugin(plugin); } + QFile loadCheck(QCoreApplication::applicationDirPath() + "/plugin_loadcheck.tmp"); + if (loadCheck.exists() && loadCheck.open(QIODevice::ReadOnly)) { + // oh, there was a failed plugin load last time. Find out which plugin was loaded last + QString fileName; + while (!loadCheck.atEnd()) { + fileName = QString::fromUtf8(loadCheck.readLine().constData()).trimmed(); + } + if (QMessageBox::question(this, tr("Plugin error"), + tr("It appears the plugin \"%1\" failed to load last startup and caused MO to crash. Do you want to disable it?\n" + "(Please note: If this is the first time you see this message for this plugin you may want to give it another try. " + "The plugin may be able to recover from the problem)").arg(fileName), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) { + m_Settings.addBlacklistPlugin(fileName); + } + loadCheck.close(); + } + + loadCheck.open(QIODevice::WriteOnly); + QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath()); qDebug("looking for plugins in %s", QDir::toNativeSeparators(pluginPath).toUtf8().constData()); QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot); + while (iter.hasNext()) { iter.next(); + if (m_Settings.pluginBlacklisted(iter.fileName())) { + qDebug("plugin \"%s\" blacklisted", qPrintable(iter.fileName())); + continue; + } + loadCheck.write(iter.fileName().toUtf8()); + loadCheck.write("\n"); + loadCheck.flush(); QString pluginName = iter.filePath(); if (QLibrary::isLibrary(pluginName)) { QPluginLoader pluginLoader(pluginName); @@ -1063,6 +1093,9 @@ void MainWindow::loadPlugins() } } + // remove the load check file on success + loadCheck.remove(); + m_DownloadManager.setSupportedExtensions(m_InstallationManager.getSupportedExtensions()); m_DiagnosisPlugins.push_back(this); @@ -1172,6 +1205,21 @@ QVariant MainWindow::pluginSetting(const QString &pluginName, const QString &key return m_Settings.pluginSetting(pluginName, key); } +void MainWindow::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value) +{ + m_Settings.setPluginSetting(pluginName, key, value); +} + +QVariant MainWindow::persistent(const QString &pluginName, const QString &key, const QVariant &def) const +{ + return m_Settings.pluginPersistent(pluginName, key, def); +} + +void MainWindow::setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync) +{ + m_Settings.setPluginPersistent(pluginName, key, value, sync); +} + QString MainWindow::pluginDataPath() const { QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath()); @@ -1273,11 +1321,9 @@ void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, this->setEnabled(true); refreshDirectoryStructure(); - refreshDataTree(); if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) { QFile::remove(m_CurrentProfile->getLoadOrderFileName()); } - refreshLists(); dialog->hide(); } } @@ -1622,11 +1668,15 @@ void MainWindow::refreshESPList() m_CurrentProfile->writeModlist(); // clear list - m_PluginList.refresh(m_CurrentProfile->getName(), - *m_DirectoryStructure, - m_CurrentProfile->getPluginsFileName(), - m_CurrentProfile->getLoadOrderFileName(), - m_CurrentProfile->getLockedOrderFileName()); + try { + m_PluginList.refresh(m_CurrentProfile->getName(), + *m_DirectoryStructure, + m_CurrentProfile->getPluginsFileName(), + m_CurrentProfile->getLoadOrderFileName(), + m_CurrentProfile->getLockedOrderFileName()); + } catch (const std::exception &e) { + reportError(tr("Failed to refresh list of esps: %s").arg(e.what())); + } } @@ -1926,7 +1976,6 @@ void MainWindow::on_btnRefreshData_clicked() { if (!m_DirectoryUpdate) { refreshDirectoryStructure(); - refreshDataTree(); } else { qDebug("directory update"); } @@ -2331,8 +2380,12 @@ void MainWindow::directory_refreshed() { DirectoryEntry *newStructure = m_DirectoryRefresher.getDirectoryStructure(); if (newStructure != NULL) { - delete m_DirectoryStructure; + DirectoryEntry *oldStructure = m_DirectoryStructure; m_DirectoryStructure = newStructure; + delete oldStructure; + + refreshDataTree(); + refreshLists(); } else { // TODO: don't know why this happens, this slot seems to get called twice with only one emit return; @@ -2541,6 +2594,29 @@ void MainWindow::modlistChanged(int) } +void MainWindow::fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName) +{ + const FileEntry::Ptr filePtr = m_DirectoryStructure->findFile(ToWString(filePath)); + if (filePtr.get() != NULL) { + try { + FilesOrigin &oldOrigin = m_DirectoryStructure->getOriginByName(ToWString(oldOriginName)); + FilesOrigin &newOrigin = m_DirectoryStructure->getOriginByName(ToWString(newOriginName)); + + QString fullNewPath = ToQString(newOrigin.getPath()) + "\\" + filePath; + WIN32_FIND_DATAW findData; + ::FindFirstFileW(ToWString(fullNewPath).c_str(), &findData); + + filePtr->addOrigin(newOrigin.getID(), findData.ftCreationTime, L""); + filePtr->removeOrigin(oldOrigin.getID()); + } catch (const std::exception &e) { + reportError(tr("Failed to move \"%1\" from mod \"%2\" to \"%3\": %4").arg(filePath).arg(oldOriginName).arg(newOriginName).arg(e.what())); + } + } else { + reportError(tr("Failed to relocate \"%1\"").arg(filePath)); + } +} + + QTreeWidgetItem *MainWindow::addFilterItem(QTreeWidgetItem *root, const QString &name, int categoryID) { QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(name)); |
