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 | |
| 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')
| -rw-r--r-- | src/activatemodsdialog.cpp | 5 | ||||
| -rw-r--r-- | src/activatemodsdialog.h | 1 | ||||
| -rw-r--r-- | src/archivetree.cpp | 98 | ||||
| -rw-r--r-- | src/archivetree.h | 55 | ||||
| -rw-r--r-- | src/executableslist.cpp | 10 | ||||
| -rw-r--r-- | src/finddialog.cpp | 48 | ||||
| -rw-r--r-- | src/finddialog.h | 73 | ||||
| -rw-r--r-- | src/main.cpp | 2 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 94 | ||||
| -rw-r--r-- | src/mainwindow.h | 6 | ||||
| -rw-r--r-- | src/modlist.cpp | 8 | ||||
| -rw-r--r-- | src/modlist.h | 8 | ||||
| -rw-r--r-- | src/noeditdelegate.cpp | 10 | ||||
| -rw-r--r-- | src/noeditdelegate.h | 12 | ||||
| -rw-r--r-- | src/organizer.pro | 15 | ||||
| -rw-r--r-- | src/overwriteinfodialog.cpp | 1 | ||||
| -rw-r--r-- | src/pluginlist.cpp | 8 | ||||
| -rw-r--r-- | src/profile.cpp | 1 | ||||
| -rw-r--r-- | src/profileinputdialog.cpp | 55 | ||||
| -rw-r--r-- | src/profilesdialog.cpp | 45 | ||||
| -rw-r--r-- | src/settings.cpp | 80 | ||||
| -rw-r--r-- | src/settings.h | 47 | ||||
| -rw-r--r-- | src/settingsdialog.cpp | 12 | ||||
| -rw-r--r-- | src/settingsdialog.h | 2 | ||||
| -rw-r--r-- | src/settingsdialog.ui | 182 | ||||
| -rw-r--r-- | src/shared/gameinfo.cpp | 20 | ||||
| -rw-r--r-- | src/shared/skyriminfo.cpp | 4 | ||||
| -rw-r--r-- | src/shared/skyriminfo.h | 2 | ||||
| -rw-r--r-- | src/version.rc | 4 |
29 files changed, 456 insertions, 452 deletions
diff --git a/src/activatemodsdialog.cpp b/src/activatemodsdialog.cpp index cf798189..8d463fba 100644 --- a/src/activatemodsdialog.cpp +++ b/src/activatemodsdialog.cpp @@ -65,11 +65,6 @@ ActivateModsDialog::~ActivateModsDialog() } -void ActivateModsDialog::on_buttonBox_accepted() -{ -} - - std::set<QString> ActivateModsDialog::getModsToActivate() { std::set<QString> result; diff --git a/src/activatemodsdialog.h b/src/activatemodsdialog.h index db0bf7fa..845167aa 100644 --- a/src/activatemodsdialog.h +++ b/src/activatemodsdialog.h @@ -62,7 +62,6 @@ public: std::set<QString> getESPsToActivate(); private slots: - void on_buttonBox_accepted(); private: Ui::ActivateModsDialog *ui; diff --git a/src/archivetree.cpp b/src/archivetree.cpp deleted file mode 100644 index 0484b241..00000000 --- a/src/archivetree.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "archivetree.h"
-#include <QDragMoveEvent>
-
-ArchiveTree::ArchiveTree(QWidget *parent) :
- QTreeWidget(parent)
-{
-}
-
-
-bool ArchiveTree::testMovePossible(QTreeWidgetItem *source, QTreeWidgetItem *target)
-{
- if ((target == NULL) ||
- (source == NULL)) {
- return false;
- }
-
- if ((source == target) ||
- (source->parent() == target)) {
- return false;
- }
-
- return true;
-}
-
-void ArchiveTree::dragEnterEvent(QDragEnterEvent *event)
-{
- QTreeWidgetItem *source = this->currentItem();
- if ((source == NULL) || (source->parent() == NULL)) {
- // can't change top level
- event->ignore();
- return;
- } else {
- QTreeWidget::dragEnterEvent(event);
- }
-
-}
-
-void ArchiveTree::dragMoveEvent(QDragMoveEvent *event)
-{
- if (!testMovePossible(this->currentItem(), itemAt(event->pos()))) {
- event->ignore();
- } else {
- QTreeWidget::dragMoveEvent(event);
- }
-}
-
-
-void ArchiveTree::dropEvent(QDropEvent *event)
-{
- event->ignore();
-
- QTreeWidgetItem *target = itemAt(event->pos());
-
- QList<QTreeWidgetItem*> sourceItems = this->selectedItems();
- for (QList<QTreeWidgetItem*>::iterator iter = sourceItems.begin();
- iter != sourceItems.end(); ++iter) {
- QTreeWidgetItem *source = *iter;
- if ((source->parent() != NULL) && - testMovePossible(source, target)) { - source->parent()->removeChild(source); - if (target->data(0, Qt::UserRole).toInt() != 0) { - // target is a file - if (target->parent() == NULL) { - // this should really not happen, how should a - // file get to the top level?
- return;
- }
- int index = target->parent()->indexOfChild(target);
- target->parent()->insertChild(index, source);
- emit changed();
- } else {
- // target is a directory
- target->insertChild(target->childCount(), source);
- emit changed();
- }
- }
- }
-
-}
diff --git a/src/archivetree.h b/src/archivetree.h deleted file mode 100644 index 775bf8b9..00000000 --- a/src/archivetree.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef ARCHIVETREE_H
-#define ARCHIVETREE_H
-
-#include <QTreeWidget>
-
-/**
- * @brief QT tree widget used to display the content of an archive in the manual installation dialog
- **/
-class ArchiveTree : public QTreeWidget
-{
-
- Q_OBJECT
-
-public:
-
- explicit ArchiveTree(QWidget *parent = 0);
-
-signals:
-
- void changed();
-
-public slots:
-
-protected:
-
- virtual void dragEnterEvent(QDragEnterEvent *event);
- virtual void dragMoveEvent(QDragMoveEvent *event);
- virtual void dropEvent(QDropEvent *event);
-
-private:
-
- bool testMovePossible(QTreeWidgetItem *source, QTreeWidgetItem *target);
-
-};
-
-#endif // ARCHIVETREE_H
diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 4e39c1a3..c486a4ca 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -172,16 +172,6 @@ void ExecutablesList::addExecutable(const QString &title, const QString &executa } } -/*void ExecutablesList::remove(const QString &executableName) -{ - for (std::vector<Executable>::iterator iter = m_Executables.begin(); iter != m_Executables.end(); ++iter) { - if (iter->m_Custom && (iter->m_BinaryInfo.absoluteFilePath() == executableName)) { - m_Executables.erase(iter); - break; - } - } -}*/ - void ExecutablesList::remove(const QString &title) { diff --git a/src/finddialog.cpp b/src/finddialog.cpp deleted file mode 100644 index 58b70ade..00000000 --- a/src/finddialog.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "finddialog.h"
-#include "ui_finddialog.h"
-
-FindDialog::FindDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::FindDialog)
-{
- ui->setupUi(this);
-}
-
-FindDialog::~FindDialog()
-{
- delete ui;
-}
-
-void FindDialog::on_nextBtn_clicked()
-{
- emit findNext();
-}
-
-void FindDialog::on_patternEdit_textChanged(const QString &pattern)
-{
- emit patternChanged(pattern);
-}
-
-void FindDialog::on_closeBtn_clicked()
-{
- this->close();
-}
diff --git a/src/finddialog.h b/src/finddialog.h deleted file mode 100644 index 70493654..00000000 --- a/src/finddialog.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright (C) 2012 Sebastian Herbord. All rights reserved. - -This file is part of Mod Organizer. - -Mod Organizer is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Mod Organizer is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef FINDDIALOG_H
-#define FINDDIALOG_H
-
-#include <QDialog>
-
-namespace Ui {
- class FindDialog;
-}
-
-/**
- * @brief Find dialog used in the TextView dialog
- **/
-class FindDialog : public QDialog
-{
-
- Q_OBJECT
-
-public:
-
- /**
- * @brief constructor
- *
- * @param parent parent widget
- **/
- explicit FindDialog(QWidget *parent = 0);
-
- ~FindDialog();
-
-signals:
-
- /**
- * @brief emitted when the user wants to jump to the next location matching the pattern
- **/
- void findNext();
-
- /**
- * @brief emitted when the user changes the pattern to search for
- *
- * @param pattern the new search pattern
- **/
- void patternChanged(const QString &pattern);
-
-private slots:
- void on_nextBtn_clicked();
-
- void on_patternEdit_textChanged(const QString &arg1);
-
- void on_closeBtn_clicked();
-
-private:
- Ui::FindDialog *ui;
-};
-
-#endif // FINDDIALOG_H
diff --git a/src/main.cpp b/src/main.cpp index 1d40dfeb..5a694121 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -343,7 +343,7 @@ int main(int argc, char *argv[]) bool done = false; while (!done) { - if (!GameInfo::init(moPath, ToWString(gamePath))) { + if (!GameInfo::init(moPath, ToWString(QDir::toNativeSeparators(gamePath)))) { if (!gamePath.isEmpty()) { reportError(QObject::tr("No game identified in \"%1\". The directory is required to contain " "the game binary and its launcher.").arg(gamePath)); 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)); diff --git a/src/mainwindow.h b/src/mainwindow.h index 152c0a27..54ae0e96 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -105,6 +105,9 @@ public: virtual bool removeMod(MOBase::IModInterface *mod); virtual void modDataChanged(MOBase::IModInterface *mod); virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const; + virtual void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value); + virtual QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def = QVariant()) const; + virtual void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync = true); virtual QString pluginDataPath() const; virtual void installMod(const QString &fileName); virtual QString resolvePath(const QString &fileName) const; @@ -315,6 +318,8 @@ private: std::vector<MOBase::IPluginDiagnose*> m_DiagnosisPlugins; std::vector<QString> m_UnloadedPlugins; + QFile m_PluginsCheck; + private slots: void showMessage(const QString &message); @@ -435,6 +440,7 @@ private slots: void updateStyle(const QString &style); void modlistChanged(const QModelIndex &index, int role); + void fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName); void savePluginList(); diff --git a/src/modlist.cpp b/src/modlist.cpp index 5aa8fbb9..b5a7182e 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -477,6 +477,7 @@ Qt::ItemFlags ModList::flags(const QModelIndex &modelIndex) const return result; } + QStringList ModList::mimeTypes() const { QStringList result = QAbstractItemModel::mimeTypes(); @@ -544,6 +545,12 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa QDir modDirectory(modInfo->absolutePath()); QDir gameDirectory(QDir::fromNativeSeparators(ToQString(MOShared::GameInfo::instance().getOverwriteDir()))); + unsigned int overwriteIndex = ModInfo::findMod([](ModInfo::Ptr mod) -> bool { + std::vector<ModInfo::EFlag> flags = mod->getFlags(); + return std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end(); }); + + QString overwriteName = ModInfo::getByIndex(overwriteIndex)->name(); + foreach (const QUrl &url, mimeData->urls()) { QString relativePath = gameDirectory.relativeFilePath(url.toLocalFile()); if (relativePath.startsWith("..")) { @@ -552,6 +559,7 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa } source.append(url.toLocalFile()); target.append(modDirectory.absoluteFilePath(relativePath)); + emit fileMoved(relativePath, overwriteName, modInfo->name()); } if (source.count() != 0) { diff --git a/src/modlist.h b/src/modlist.h index 069de40b..7e76d677 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -182,6 +182,14 @@ signals: */ void removeSelectedMods(); + /** + * @brief fileMoved emitted when a file is moved from one mod to another + * @param relativePath relative path of the file moved + * @param oldOriginName name of the origin that previously contained the file + * @param newOriginName name of the origin that now contains the file + */ + void fileMoved(const QString &relativePath, const QString &oldOriginName, const QString &newOriginName); + protected: // event filter, handles event from the header and the tree view itself diff --git a/src/noeditdelegate.cpp b/src/noeditdelegate.cpp new file mode 100644 index 00000000..ab8a4880 --- /dev/null +++ b/src/noeditdelegate.cpp @@ -0,0 +1,10 @@ +#include "noeditdelegate.h"
+
+NoEditDelegate::NoEditDelegate(QObject *parent)
+ : QStyledItemDelegate(parent)
+{
+}
+
+QWidget *NoEditDelegate::createEditor(QWidget*, const QStyleOptionViewItem&, const QModelIndex&) const {
+ return NULL;
+}
diff --git a/src/noeditdelegate.h b/src/noeditdelegate.h new file mode 100644 index 00000000..d0ba2f68 --- /dev/null +++ b/src/noeditdelegate.h @@ -0,0 +1,12 @@ +#ifndef NOEDITDELEGATE_H
+#define NOEDITDELEGATE_H
+
+#include <QStyledItemDelegate>
+
+class NoEditDelegate: public QStyledItemDelegate {
+public:
+ NoEditDelegate(QObject *parent = NULL);
+ virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+};
+
+#endif // NOEDITDELEGATE_H
diff --git a/src/organizer.pro b/src/organizer.pro index 339a50cd..e89b6e99 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -51,7 +51,6 @@ SOURCES += \ json.cpp \
installationmanager.cpp \
helper.cpp \
- finddialog.cpp \
filedialogmemory.cpp \
executableslist.cpp \
editexecutablesdialog.cpp \
@@ -66,7 +65,6 @@ SOURCES += \ categoriesdialog.cpp \
categories.cpp \
bbcode.cpp \
- archivetree.cpp \
activatemodsdialog.cpp \
moapplication.cpp \
profileinputdialog.cpp \
@@ -80,7 +78,8 @@ SOURCES += \ serverinfo.cpp \
../esptk/record.cpp \
../esptk/espfile.cpp \
- ../esptk/subrecord.cpp
+ ../esptk/subrecord.cpp \
+ noeditdelegate.cpp
HEADERS += \
transfersavesdialog.h \
@@ -119,7 +118,6 @@ HEADERS += \ json.h \
installationmanager.h \
helper.h \
- finddialog.h \
filedialogmemory.h \
executableslist.h \
editexecutablesdialog.h \
@@ -134,7 +132,6 @@ HEADERS += \ categoriesdialog.h \
categories.h \
bbcode.h \
- archivetree.h \
activatemodsdialog.h \
moapplication.h \
profileinputdialog.h \
@@ -148,7 +145,9 @@ HEADERS += \ serverinfo.h \
../esptk/record.h \
../esptk/espfile.h \
- ../esptk/subrecord.h
+ ../esptk/subrecord.h \
+ ../esptk/espexceptions.h \
+ noeditdelegate.h
FORMS += \
transfersavesdialog.ui \
@@ -218,8 +217,8 @@ TRANSLATIONS = organizer_de.ts \ organizer_zh_CN.ts \
organizer_cs.ts \
organizer_tr.ts \
- organizer_ru.ts \
- organizer.en.ts
+# organizer.en.ts \
+ organizer_ru.ts
!isEmpty(TRANSLATIONS) {
isEmpty(QMAKE_LRELEASE) {
diff --git a/src/overwriteinfodialog.cpp b/src/overwriteinfodialog.cpp index 11e7b552..e215146f 100644 --- a/src/overwriteinfodialog.cpp +++ b/src/overwriteinfodialog.cpp @@ -37,7 +37,6 @@ public: virtual int columnCount(const QModelIndex &parent) const { m_RegularColumnCount = QFileSystemModel::columnCount(parent); -// return m_RegularColumnCount + 1; return m_RegularColumnCount; } diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index ea23fcdd..6cb9bdf7 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -140,8 +140,12 @@ void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseD std::find(primaryPlugins.begin(), primaryPlugins.end(), ToWString(filename.toLower())) != primaryPlugins.end(); bool archive = false; - FilesOrigin &origin = baseDirectory.getOriginByID(current->getOrigin(archive)); - m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName()), ToQString(current->getFullPath()))); + try { + FilesOrigin &origin = baseDirectory.getOriginByID(current->getOrigin(archive)); + m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName()), ToQString(current->getFullPath()))); + } catch (const std::exception &e) { + reportError(tr("failed to update esp info for file %1 (source id: %2), error: %3").arg(filename).arg(current->getOrigin(archive)).arg(e.what())); + } } } diff --git a/src/profile.cpp b/src/profile.cpp index 330bfa09..07f7010e 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -755,6 +755,7 @@ QString Profile::getIniFileName() const return m_Directory.absoluteFilePath(ToQString(primaryIniFile)); } + QString Profile::getPath() const { return QDir::cleanPath(m_Directory.absolutePath()); diff --git a/src/profileinputdialog.cpp b/src/profileinputdialog.cpp index 7402d4d5..af33dcdd 100644 --- a/src/profileinputdialog.cpp +++ b/src/profileinputdialog.cpp @@ -17,29 +17,32 @@ You should have received a copy of the GNU General Public License along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. */ -#include "profileinputdialog.h"
-#include "ui_profileinputdialog.h"
-
-ProfileInputDialog::ProfileInputDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::ProfileInputDialog)
-{
- ui->setupUi(this);
-}
-
-ProfileInputDialog::~ProfileInputDialog()
-{
- delete ui;
-}
-
-QString ProfileInputDialog::getName() const
-{
- return ui->nameEdit->text().trimmed();
-}
-
-
-bool ProfileInputDialog::getPreferDefaultSettings() const
-{
- return ui->defaultSettingsBox->checkState() == Qt::Checked;
-}
-
+#include "profileinputdialog.h" +#include "ui_profileinputdialog.h" +#include <utility.h> + +ProfileInputDialog::ProfileInputDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::ProfileInputDialog) +{ + ui->setupUi(this); +} + +ProfileInputDialog::~ProfileInputDialog() +{ + delete ui; +} + +QString ProfileInputDialog::getName() const +{ + QString result = ui->nameEdit->text(); + MOBase::fixDirectoryName(result); + return result; +} + + +bool ProfileInputDialog::getPreferDefaultSettings() const +{ + return ui->defaultSettingsBox->checkState() == Qt::Checked; +} + diff --git a/src/profilesdialog.cpp b/src/profilesdialog.cpp index 9955ecd2..69872a24 100644 --- a/src/profilesdialog.cpp +++ b/src/profilesdialog.cpp @@ -150,36 +150,55 @@ void ProfilesDialog::on_copyProfileButton_clicked() { bool okClicked; QString name = QInputDialog::getText(this, tr("Name"), tr("Please enter a name for the new profile"), QLineEdit::Normal, QString(), &okClicked); - if (okClicked && (name.size() > 0)) { - QListWidget *profilesList = findChild<QListWidget*>("profilesList"); + fixDirectoryName(name); + if (okClicked) { + if (name.size() > 0) { + QListWidget *profilesList = findChild<QListWidget*>("profilesList"); - try { - const Profile::Ptr currentProfile = profilesList->currentItem()->data(Qt::UserRole).value<Profile::Ptr>(); - createProfile(name, *currentProfile); - } catch (const std::exception &e) { - reportError(tr("failed to copy profile: %1").arg(e.what())); + try { + const Profile::Ptr currentProfile = profilesList->currentItem()->data(Qt::UserRole).value<Profile::Ptr>(); + createProfile(name, *currentProfile); + } catch (const std::exception &e) { + reportError(tr("failed to copy profile: %1").arg(e.what())); + } + } else { + QMessageBox::warning(this, tr("Invalid name"), tr("Invalid profile name")); } } } void ProfilesDialog::on_removeProfileButton_clicked() { - QMessageBox confirmBox(QMessageBox::Question, tr("Confirm"), tr("Are you sure you want to remove this profile?"), + QMessageBox confirmBox(QMessageBox::Question, tr("Confirm"), tr("Are you sure you want to remove this profile (including local savegames if any)?"), QMessageBox::Yes | QMessageBox::No); if (confirmBox.exec() == QMessageBox::Yes) { QListWidget *profilesList = findChild<QListWidget*>("profilesList"); Profile::Ptr currentProfile = profilesList->currentItem()->data(Qt::UserRole).value<Profile::Ptr>(); - - // on destruction, the profile object would write the profile.ini file again, so - // we have to get rid of the it before deleting the directory - QString profilePath = currentProfile->getPath(); + QString profilePath; + if (currentProfile.get() == NULL) { + profilePath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())) + "/" + profilesList->currentItem()->text(); + if (QMessageBox::question(this, tr("Profile broken"), + tr("This profile you're about to delete seems to be broken or the path is invalid. " + "I'm about to delete the following folder: \"%1\". Proceed?").arg(profilePath), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { + return; + } + } else { + // on destruction, the profile object would write the profile.ini file again, so + // we have to get rid of the it before deleting the directory + profilePath = currentProfile->getPath(); + } QListWidgetItem* item = profilesList->takeItem(profilesList->currentRow()); if (item != NULL) { delete item; } - shellDelete(QStringList(profilePath)); + if (!shellDelete(QStringList(profilePath))) { + qWarning("Failed to shell-delete \"%s\" (errorcode %lu), trying regular delete", qPrintable(profilePath), ::GetLastError()); + if (!removeDir(profilePath)) { + qWarning("regular delete failed too"); + } + } } } diff --git a/src/settings.cpp b/src/settings.cpp index 39b6dba7..42a8d693 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -87,6 +87,19 @@ void Settings::clearPlugins() { m_Plugins.clear(); m_PluginSettings.clear(); + + m_PluginBlacklist.clear(); + int count = m_Settings.beginReadArray("pluginBlacklist"); + for (int i = 0; i < count; ++i) { + m_Settings.setArrayIndex(i); + m_PluginBlacklist.insert(m_Settings.value("name").toString()); + } + m_Settings.endArray(); +} + +bool Settings::pluginBlacklisted(const QString &fileName) const +{ + return m_PluginBlacklist.contains(fileName); } void Settings::registerPlugin(IPlugin *plugin) @@ -275,16 +288,47 @@ QVariant Settings::pluginSetting(const QString &pluginName, const QString &key) { auto iterPlugin = m_PluginSettings.find(pluginName); if (iterPlugin == m_PluginSettings.end()) { - throw MyException(tr("setting for invalid plugin \"%1\" requested").arg(key)); + return QVariant(); } auto iterSetting = iterPlugin->find(key); if (iterSetting == iterPlugin->end()) { - throw MyException(tr("invalid setting \"%1\" requested for plugin \"%2\"").arg(key).arg(pluginName)); + return QVariant(); } return *iterSetting; } +void Settings::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value) +{ + auto iterPlugin = m_PluginSettings.find(pluginName); + if (iterPlugin == m_PluginSettings.end()) { + throw MyException(tr("attempt to store setting for unknown plugin \"%1\"").arg(pluginName)); + } + + // store the new setting both in memory and in the ini + m_PluginSettings[pluginName][key] = value; + m_Settings.setValue("Plugins/" + pluginName + "/" + key, value); +} + +QVariant Settings::pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const +{ + if (!m_PluginSettings.contains(pluginName)) { + return def; + } + return m_Settings.value("PluginPersistance/" + pluginName + "/" + key, def); +} + +void Settings::setPluginPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync) +{ + if (!m_PluginSettings.contains(pluginName)) { + throw MyException(tr("attempt to store setting for unknown plugin \"%1\"").arg(pluginName)); + } + m_Settings.setValue("PluginPersistance/" + pluginName + "/" + key, value); + if (sync) { + m_Settings.sync(); + } +} + QString Settings::language() { QString result = m_Settings.value("Settings/language", "").toString(); @@ -330,6 +374,23 @@ void Settings::updateServers(const QList<ServerInfo> &servers) m_Settings.sync(); } +void Settings::addBlacklistPlugin(const QString &fileName) +{ + m_PluginBlacklist.insert(fileName); + writePluginBlacklist(); +} + +void Settings::writePluginBlacklist() +{ + m_Settings.beginWriteArray("pluginBlacklist"); + int idx = 0; + foreach (const QString &plugin, m_PluginBlacklist) { + m_Settings.setArrayIndex(idx++); + m_Settings.setValue("name", plugin); + } + + m_Settings.endArray(); +} void Settings::addLanguages(QComboBox *languageBox) { @@ -443,6 +504,7 @@ void Settings::query(QWidget *parent) // plugis page QListWidget *pluginsList = dialog.findChild<QListWidget*>("pluginsList"); + QListWidget *pluginBlacklistList = dialog.findChild<QListWidget*>("pluginBlacklist"); // workarounds page QCheckBox *forceEnableBox = dialog.findChild<QCheckBox*>("forceEnableBox"); @@ -522,6 +584,7 @@ void Settings::query(QWidget *parent) nmmVersionEdit->setText(m_Settings.value("Settings/nmm_version", "0.33.1").toString()); logLevelBox->setCurrentIndex(logLevel()); + // display plugin settings foreach (IPlugin *plugin, m_Plugins) { QListWidgetItem *listItem = new QListWidgetItem(plugin->name(), pluginsList); listItem->setData(Qt::UserRole, QVariant::fromValue((void*)plugin)); @@ -529,6 +592,12 @@ void Settings::query(QWidget *parent) pluginsList->addItem(listItem); } + // display plugin blacklist + foreach (const QString &pluginName, m_PluginBlacklist) { + pluginBlacklistList->addItem(pluginName); + } + + // display server preferences m_Settings.beginGroup("Servers"); foreach (const QString &key, m_Settings.childKeys()) { QVariantMap val = m_Settings.value(key).toMap(); @@ -624,6 +693,13 @@ void Settings::query(QWidget *parent) } } + // store plugin blacklist + m_PluginBlacklist.clear(); + foreach (QListWidgetItem *item, pluginBlacklistList->findItems("*", Qt::MatchWildcard)) { + m_PluginBlacklist.insert(item->text()); + } + writePluginBlacklist(); + // store server preference m_Settings.beginGroup("Servers"); for (int i = 0; i < knownServersList->count(); ++i) { diff --git a/src/settings.h b/src/settings.h index bf17d162..51ee6b92 100644 --- a/src/settings.h +++ b/src/settings.h @@ -57,6 +57,7 @@ public: /** * @brief register plugin to be configurable * @param plugin the plugin to register + * @return true if the plugin may be registered, false if it is blacklisted */ void registerPlugin(MOBase::IPlugin *plugin); @@ -195,11 +196,38 @@ public: * @param pluginName name of the plugin * @param key name of the setting to retrieve * @return the requested value as a QVariant - * @throws an exception is thrown if this setting doesn't exist + * @note an invalid QVariant is returned if the the plugin/setting is not declared */ QVariant pluginSetting(const QString &pluginName, const QString &key) const; /** + * @brief set a setting for one of the installed mods + * @param pluginName name of the plugin + * @param key name of the setting to change + * @param value the new value to set + * @throw an exception is thrown if pluginName is invalid + */ + void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value); + + /** + * @brief retrieve a persistent value for a plugin + * @param pluginName name of the plugin to store data for + * @param key id of the value to retrieve + * @param def default value to return if the value is not set + * @return the requested value + */ + QVariant pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const; + + /** + * @brief set a persistent value for a plugin + * @param pluginName name of the plugin to store data for + * @param key id of the value to retrieve + * @param value value to set + * @throw an exception is thrown if pluginName is invalid + */ + void setPluginPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync); + + /** * @return short code of the configured language (corresponding to the translation files) */ QString language(); @@ -210,6 +238,19 @@ public: */ void updateServers(const QList<ServerInfo> &servers); + /** + * @brief add a plugin that is to be blacklisted + * @param fileName name of the plugin to blacklist + */ + void addBlacklistPlugin(const QString &fileName); + + /** + * @brief test if a plugin is blacklisted and shouldn't be loaded + * @param fileName name of the plugin + * @return true if the file is blacklisted + */ + bool pluginBlacklisted(const QString &fileName) const; + private: QString obfuscate(const QString &password) const; @@ -219,6 +260,8 @@ private: void addStyles(QComboBox *styleBox); bool isNXMHandler(bool *modifyable); void setNXMHandlerActive(bool active, bool writable); + void readPluginBlacklist(); + void writePluginBlacklist(); private slots: @@ -241,6 +284,8 @@ private: QMap<QString, QMap<QString, QVariant> > m_PluginSettings; + QSet<QString> m_PluginBlacklist; + }; #endif // WORKAROUNDS_H diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index 9f268455..c8908ddb 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -21,10 +21,12 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "ui_settingsdialog.h" #include "categoriesdialog.h" #include "helper.h" +#include "noeditdelegate.h" #include <gameinfo.h> #include <QDirIterator> #include <QFileDialog> #include <QMessageBox> +#include <QShortcut> #define WIN32_LEAN_AND_MEAN #include <Windows.h> @@ -37,6 +39,9 @@ SettingsDialog::SettingsDialog(QWidget *parent) : TutorableDialog("SettingsDialog", parent), ui(new Ui::SettingsDialog) { ui->setupUi(this); + + QShortcut *delShortcut = new QShortcut(QKeySequence(Qt::Key_Delete), ui->pluginBlacklist); + connect(delShortcut, SIGNAL(activated()), this, SLOT(deleteBlacklistItem())); } SettingsDialog::~SettingsDialog() @@ -146,6 +151,8 @@ void SettingsDialog::on_pluginsList_currentItemChanged(QListWidgetItem *current, for (auto iter = settings.begin(); iter != settings.end(); ++iter) { QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList(iter.key())); QVariant value = *iter; + + ui->pluginSettingsList->setItemDelegateForColumn(0, new NoEditDelegate()); newItem->setData(1, Qt::DisplayRole, value); newItem->setData(1, Qt::EditRole, value); @@ -153,3 +160,8 @@ void SettingsDialog::on_pluginsList_currentItemChanged(QListWidgetItem *current, ui->pluginSettingsList->addTopLevelItem(newItem); } } + +void SettingsDialog::deleteBlacklistItem() +{ + ui->pluginBlacklist->takeItem(ui->pluginBlacklist->currentIndex().row()); +} diff --git a/src/settingsdialog.h b/src/settingsdialog.h index 3bfc1706..718574a0 100644 --- a/src/settingsdialog.h +++ b/src/settingsdialog.h @@ -73,6 +73,8 @@ private slots: void on_pluginsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous); + void deleteBlacklistItem(); + private: Ui::SettingsDialog *ui; }; diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui index b63965f9..e7bd0fa3 100644 --- a/src/settingsdialog.ui +++ b/src/settingsdialog.ui @@ -406,102 +406,116 @@ p, li { white-space: pre-wrap; } <attribute name="title">
<string>Plugins</string>
</attribute>
- <layout class="QHBoxLayout" name="horizontalLayout_7" stretch="0,1">
+ <layout class="QVBoxLayout" name="verticalLayout_9" stretch="0,0,0">
<item>
- <widget class="QListWidget" name="pluginsList">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_7" stretch="0,1">
+ <layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
- <layout class="QFormLayout" name="formLayout_2">
- <item row="0" column="0">
- <widget class="QLabel" name="label_13">
- <property name="text">
- <string>Author:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="authorLabel">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_15">
- <property name="text">
- <string>Version:</string>
- </property>
- </widget>
+ <widget class="QListWidget" name="pluginsList">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_7" stretch="0,1">
+ <item>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_13">
+ <property name="text">
+ <string>Author:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="authorLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_15">
+ <property name="text">
+ <string>Version:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="versionLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_14">
+ <property name="text">
+ <string>Description:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="descriptionLabel">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
- <item row="1" column="1">
- <widget class="QLabel" name="versionLabel">
- <property name="text">
- <string/>
+ <item>
+ <widget class="QTreeWidget" name="pluginSettingsList">
+ <property name="indentation">
+ <number>0</number>
</property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_14">
- <property name="text">
- <string>Description:</string>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
</property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="descriptionLabel">
- <property name="text">
- <string/>
+ <property name="itemsExpandable">
+ <bool>false</bool>
</property>
- <property name="wordWrap">
- <bool>true</bool>
+ <property name="expandsOnDoubleClick">
+ <bool>false</bool>
</property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="headerDefaultSectionSize">
+ <number>100</number>
+ </attribute>
+ <column>
+ <property name="text">
+ <string>Key</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value</string>
+ </property>
+ </column>
</widget>
</item>
</layout>
</item>
- <item>
- <widget class="QTreeWidget" name="pluginSettingsList">
- <property name="indentation">
- <number>0</number>
- </property>
- <property name="rootIsDecorated">
- <bool>false</bool>
- </property>
- <property name="itemsExpandable">
- <bool>false</bool>
- </property>
- <property name="expandsOnDoubleClick">
- <bool>false</bool>
- </property>
- <attribute name="headerVisible">
- <bool>false</bool>
- </attribute>
- <attribute name="headerDefaultSectionSize">
- <number>100</number>
- </attribute>
- <column>
- <property name="text">
- <string>Key</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Value</string>
- </property>
- </column>
- </widget>
- </item>
</layout>
</item>
+ <item>
+ <widget class="QLabel" name="label_18">
+ <property name="text">
+ <string>Blacklisted Plugins (use <del> to remove):</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="pluginBlacklist"/>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="workaroundTab">
@@ -638,7 +652,7 @@ Please note that MO does identify itself as MO to the webserver, it's not lying tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again.</string>
</property>
<property name="inputMask">
- <string notr="true">009.009.009</string>
+ <string notr="true">009.009.009; </string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
diff --git a/src/shared/gameinfo.cpp b/src/shared/gameinfo.cpp index fd5072bf..6b53450d 100644 --- a/src/shared/gameinfo.cpp +++ b/src/shared/gameinfo.cpp @@ -62,36 +62,36 @@ void GameInfo::identifyMyGamesDirectory(const std::wstring &file) }
-bool GameInfo::identifyGame(const std::wstring &omoDirectory, const std::wstring &searchPath)
+bool GameInfo::identifyGame(const std::wstring &moDirectory, const std::wstring &searchPath)
{
if (OblivionInfo::identifyGame(searchPath)) {
- s_Instance = new OblivionInfo(omoDirectory, searchPath);
+ s_Instance = new OblivionInfo(moDirectory, searchPath);
} else if (Fallout3Info::identifyGame(searchPath)) {
- s_Instance = new Fallout3Info(omoDirectory, searchPath);
+ s_Instance = new Fallout3Info(moDirectory, searchPath);
} else if (FalloutNVInfo::identifyGame(searchPath)) {
- s_Instance = new FalloutNVInfo(omoDirectory, searchPath);
+ s_Instance = new FalloutNVInfo(moDirectory, searchPath);
} else if (SkyrimInfo::identifyGame(searchPath)) {
- s_Instance = new SkyrimInfo(omoDirectory, searchPath);
+ s_Instance = new SkyrimInfo(moDirectory, searchPath);
}
return s_Instance != NULL;
}
-bool GameInfo::init(const std::wstring &omoDirectory, const std::wstring &gamePath)
+bool GameInfo::init(const std::wstring &moDirectory, const std::wstring &gamePath)
{
if (s_Instance == NULL) {
if (gamePath.length() == 0) {
// search upward in the directory until a recognized game-binary is found
- std::wstring searchPath(omoDirectory);
- while (!identifyGame(omoDirectory, searchPath)) {
+ std::wstring searchPath(moDirectory);
+ while (!identifyGame(moDirectory, searchPath)) {
size_t lastSep = searchPath.find_last_of(L"/\\");
if (lastSep == std::string::npos) {
return false;
}
searchPath.erase(lastSep);
}
- } else if (!identifyGame(omoDirectory, gamePath)) {
+ } else if (!identifyGame(moDirectory, gamePath)) {
return false;
}
}
@@ -204,4 +204,4 @@ std::wstring GameInfo::getSpecialPath(LPCWSTR name) const return temp;
}
-} // namespace MOShared +} // namespace MOShared
diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp index 80cf4c80..8c6b79ef 100644 --- a/src/shared/skyriminfo.cpp +++ b/src/shared/skyriminfo.cpp @@ -33,8 +33,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. namespace MOShared {
-SkyrimInfo::SkyrimInfo(const std::wstring &omoDirectory, const std::wstring &gameDirectory)
- : GameInfo(omoDirectory, gameDirectory)
+SkyrimInfo::SkyrimInfo(const std::wstring &moDirectory, const std::wstring &gameDirectory)
+ : GameInfo(moDirectory, gameDirectory)
{
identifyMyGamesDirectory(L"skyrim");
diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h index 4760c38b..c5d31ff0 100644 --- a/src/shared/skyriminfo.h +++ b/src/shared/skyriminfo.h @@ -95,7 +95,7 @@ public: private:
- SkyrimInfo(const std::wstring &omoDirectory, const std::wstring &gameDirectory);
+ SkyrimInfo(const std::wstring &moDirectory, const std::wstring &gameDirectory);
static bool identifyGame(const std::wstring &searchPath);
diff --git a/src/version.rc b/src/version.rc index 7e988897..16e006cf 100644 --- a/src/version.rc +++ b/src/version.rc @@ -1,7 +1,7 @@ #include "Winver.h"
-#define VER_FILEVERSION 1,0,0,1
-#define VER_FILEVERSION_STR "1,0,0,1\0"
+#define VER_FILEVERSION 1,0,2,0
+#define VER_FILEVERSION_STR "1,0,2,0\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
|
