summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTannin <devnull@localhost>2013-09-11 22:54:45 +0200
committerTannin <devnull@localhost>2013-09-11 22:54:45 +0200
commitaf6e1c3ab4f3687c88715dffff8b1bf2f38a15d6 (patch)
tree414f43c931e2e040344e87d2f6317196c1cea108 /src
parent50325c8fc23fdeed6e1acb90917e8e2889a1140f (diff)
- when installing mods from outside the download directory the absolute path is now stored
- added a context menu to the toolbar buttons so tool icons can be removed directly - initweaks modinfo tab is now always available and allows new ini tweaks to be created - fake esms are now treated as masters (as they should) - MO will now display a warning if not all masters of an esp are enabled. The tooltip gives a list of required masters - bugfix: path returned by getfullpathname was sometimes not correctly terminated - bugfix: path after reverse-rerouting was sometimes incorrect, missing a path separator - bugfix: change of current directory sometimes used a fake directory without need - bugfix: icons in shortcut menu were not alwayscorrectly updated
Diffstat (limited to 'src')
-rw-r--r--src/ModOrganizer.pro3
-rw-r--r--src/downloadlistwidget.cpp2
-rw-r--r--src/downloadlistwidgetcompact.cpp2
-rw-r--r--src/installationmanager.cpp7
-rw-r--r--src/mainwindow.cpp64
-rw-r--r--src/mainwindow.h6
-rw-r--r--src/mainwindow.ui59
-rw-r--r--src/modinfodialog.cpp36
-rw-r--r--src/modinfodialog.h3
-rw-r--r--src/modinfodialog.ui14
-rw-r--r--src/organizer.pro12
-rw-r--r--src/pluginlist.cpp75
-rw-r--r--src/pluginlist.h40
-rw-r--r--src/resources.qrc4
-rw-r--r--src/resources/dialog-warning_16.png (warning_16)bin0 -> 603 bytes
-rw-r--r--src/version.rc4
16 files changed, 208 insertions, 123 deletions
diff --git a/src/ModOrganizer.pro b/src/ModOrganizer.pro
index db395ffd..c8bfe6df 100644
--- a/src/ModOrganizer.pro
+++ b/src/ModOrganizer.pro
@@ -13,7 +13,8 @@ SUBDIRS = bsatk \
proxydll \
nxmhandler \
BossDummy \
- pythonRunner
+ pythonRunner \
+ esptk
hookdll.depends = shared
organizer.depends = shared, uibase, plugins
diff --git a/src/downloadlistwidget.cpp b/src/downloadlistwidget.cpp
index 3a7dac66..b657ca69 100644
--- a/src/downloadlistwidget.cpp
+++ b/src/downloadlistwidget.cpp
@@ -150,7 +150,7 @@ void DownloadListWidgetDelegate::paint(QPainter *painter, const QStyleOptionView
}
m_InstallLabel->setPalette(labelPalette);
if (m_Manager->isInfoIncomplete(downloadIndex)) {
- m_NameLabel->setText("<img src=\":/MO/gui/resources/dialog-warning_16.png\" /> " + m_NameLabel->text());
+ m_NameLabel->setText("<img src=\":/MO/gui/warning_16\" /> " + m_NameLabel->text());
}
} else {
m_InstallLabel->setVisible(false);
diff --git a/src/downloadlistwidgetcompact.cpp b/src/downloadlistwidgetcompact.cpp
index 0cbdd0b1..8dd6e275 100644
--- a/src/downloadlistwidgetcompact.cpp
+++ b/src/downloadlistwidgetcompact.cpp
@@ -137,7 +137,7 @@ void DownloadListWidgetCompactDelegate::paint(QPainter *painter, const QStyleOpt
m_DoneLabel->setForegroundRole(QPalette::WindowText);
}
if (m_Manager->isInfoIncomplete(downloadIndex)) {
- m_NameLabel->setText("<img src=\":/MO/gui/resources/dialog-warning_16.png\"/> " + m_NameLabel->text());
+ m_NameLabel->setText("<img src=\":/MO/gui/warning_16\"/> " + m_NameLabel->text());
}
} else {
m_DoneLabel->setVisible(false);
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp
index af2e6852..588dbaa4 100644
--- a/src/installationmanager.cpp
+++ b/src/installationmanager.cpp
@@ -664,8 +664,11 @@ bool InstallationManager::install(const QString &fileName, GuessedValue<QString>
modName.update(guessedModName, GUESS_GOOD);
}
- qDebug("using mod name \"%s\" (id %d)", modName->toUtf8().constData(), modID);
- m_CurrentFile = fileInfo.fileName();
+ m_CurrentFile = fileInfo.absoluteFilePath();
+ if (fileInfo.dir() == QDir(ToQString(GameInfo::instance().getDownloadDir()))) {
+ m_CurrentFile = fileInfo.fileName();
+ }
+ qDebug("using mod name \"%s\" (id %d) -> %s", modName->toUtf8().constData(), modID, qPrintable(m_CurrentFile));
// open the archive and construct the directory tree the installers work on
bool archiveOpen = m_CurrentArchive->open(ToWString(QDir::toNativeSeparators(fileName)).c_str(),
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 2988c602..c37f0743 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -144,7 +144,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
m_InstallationManager(this), m_Translator(NULL), m_TranslatorQt(NULL),
m_Updater(NexusInterface::instance(), this), m_CategoryFactory(CategoryFactory::instance()),
m_CurrentProfile(NULL), m_AskForNexusPW(false), m_LoginAttempted(false),
- m_ArchivesInit(false), m_ContextItem(NULL), m_CurrentSaveView(NULL),
+ m_ArchivesInit(false), m_ContextItem(NULL), m_ContextAction(NULL), m_CurrentSaveView(NULL),
m_GameInfo(new GameInfoImpl())
{
ui->setupUi(this);
@@ -261,6 +261,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget
connect(&TutorialManager::instance(), SIGNAL(windowTutorialFinished(QString)), this, SLOT(windowTutorialFinished(QString)));
+ connect(ui->toolBar, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(toolBar_customContextMenuRequested(QPoint)));
+
connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString)));
m_CheckBSATimer.setSingleShot(true);
@@ -1325,17 +1327,6 @@ void MainWindow::setExecutableIndex(int index)
executableBox->setCurrentIndex(1);
}
- const Executable &selectedExecutable = executableBox->itemData(executableBox->currentIndex()).value<Executable>();
-
- QIcon addIcon(":/MO/gui/link");
- QIcon removeIcon(":/MO/gui/remove");
-
- QFileInfo linkDesktopFile(QDir::fromNativeSeparators(getDesktopDirectory()) + "/" + selectedExecutable.m_Title + ".lnk");
- QFileInfo linkMenuFile(QDir::fromNativeSeparators(getStartMenuDirectory()) + "/" + selectedExecutable.m_Title + ".lnk");
-
- ui->linkButton->menu()->actions().at(0)->setIcon(selectedExecutable.m_Toolbar ? removeIcon : addIcon);
- ui->linkButton->menu()->actions().at(1)->setIcon(linkDesktopFile.exists() ? removeIcon : addIcon);
- ui->linkButton->menu()->actions().at(2)->setIcon(linkMenuFile.exists() ? removeIcon : addIcon);
}
@@ -1768,14 +1759,14 @@ void MainWindow::checkBSAList()
if (item->checkState(0) == Qt::Unchecked) {
if (m_DefaultArchives.contains(filename)) {
- item->setIcon(0, QIcon(":/MO/gui/resources/dialog-warning.png"));
+ 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/resources/dialog-warning.png"));
+ 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;
@@ -1790,7 +1781,7 @@ void MainWindow::checkBSAList()
}
if (warning) {
- ui->tabWidget->setTabIcon(1, QIcon(":/MO/gui/resources/dialog-warning.png"));
+ ui->tabWidget->setTabIcon(1, QIcon(":/MO/gui/warning"));
} else {
ui->tabWidget->setTabIcon(1, QIcon());
}
@@ -2735,8 +2726,13 @@ void MainWindow::reinstallMod_clicked()
QString installationFile = modInfo->getInstallationFile();
if (installationFile.length() != 0) {
QString fullInstallationFile;
- if (QFileInfo(installationFile).isAbsolute()) {
- fullInstallationFile = installationFile;
+ QFileInfo fileInfo(installationFile);
+ if (fileInfo.isAbsolute()) {
+ if (fileInfo.exists()) {
+ fullInstallationFile = installationFile;
+ } else {
+ fullInstallationFile = m_DownloadManager.getOutputDirectory().append("/").append(fileInfo.fileName());
+ }
} else {
fullInstallationFile = m_DownloadManager.getOutputDirectory().append("/").append(installationFile);
}
@@ -4494,6 +4490,25 @@ void MainWindow::unlockESPIndex()
}
+void MainWindow::removeFromToolbar()
+{
+ Executable &exe = m_ExecutablesList.find(m_ContextAction->text());
+ exe.m_Toolbar = false;
+ updateToolBar();
+}
+
+
+void MainWindow::toolBar_customContextMenuRequested(const QPoint &point)
+{
+ QAction *action = ui->toolBar->actionAt(point);
+ if (action->objectName().startsWith("custom_")) {
+ m_ContextAction = action;
+ QMenu menu;
+ menu.addAction(tr("Remove"), this, SLOT(removeFromToolbar()));
+ menu.exec(ui->toolBar->mapToGlobal(point));
+ }
+}
+
void MainWindow::on_espList_customContextMenuRequested(const QPoint &pos)
{
m_ContextRow = m_PluginListSortProxy->mapToSource(ui->espList->indexAt(pos)).row();
@@ -4565,3 +4580,18 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index)
m_ModListSortProxy->setSourceModel(&m_ModList);
}
}
+
+void MainWindow::on_linkButton_pressed()
+{
+ const Executable &selectedExecutable = ui->executablesListBox->itemData(ui->executablesListBox->currentIndex()).value<Executable>();
+
+ QIcon addIcon(":/MO/gui/link");
+ QIcon removeIcon(":/MO/gui/remove");
+
+ QFileInfo linkDesktopFile(QDir::fromNativeSeparators(getDesktopDirectory()) + "/" + selectedExecutable.m_Title + ".lnk");
+ QFileInfo linkMenuFile(QDir::fromNativeSeparators(getStartMenuDirectory()) + "/" + selectedExecutable.m_Title + ".lnk");
+
+ ui->linkButton->menu()->actions().at(0)->setIcon(selectedExecutable.m_Toolbar ? removeIcon : addIcon);
+ ui->linkButton->menu()->actions().at(1)->setIcon(linkDesktopFile.exists() ? removeIcon : addIcon);
+ ui->linkButton->menu()->actions().at(2)->setIcon(linkMenuFile.exists() ? removeIcon : addIcon);
+}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index c56a98c6..152c0a27 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -276,6 +276,8 @@ private:
int m_ContextRow;
QTreeWidgetItem *m_ContextItem;
+ QAction *m_ContextAction;
+
int m_SelectedSaveGame;
Settings m_Settings;
@@ -454,6 +456,9 @@ private slots:
void downloadSpeed(const QString &serverName, int bytesPerSecond);
+ void toolBar_customContextMenuRequested(const QPoint &point);
+ void removeFromToolbar();
+
private slots: // ui slots
// actions
void on_actionAdd_Profile_triggered();
@@ -485,6 +490,7 @@ private slots: // ui slots
void on_displayCategoriesBtn_toggled(bool checked);
void on_groupCombo_currentIndexChanged(int index);
void on_categoriesList_itemSelectionChanged();
+ void on_linkButton_pressed();
};
#endif // MAINWINDOW_H
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index 3a65ca27..54611235 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -31,16 +31,7 @@
<property name="spacing">
<number>4</number>
</property>
- <property name="leftMargin">
- <number>6</number>
- </property>
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="rightMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>6</number>
</property>
<item>
@@ -730,16 +721,7 @@ p, li { white-space: pre-wrap; }
<string notr="true">Archives</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
- <property name="leftMargin">
- <number>6</number>
- </property>
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="rightMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>6</number>
</property>
<item>
@@ -818,16 +800,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
<string>Data</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
- <property name="leftMargin">
- <number>6</number>
- </property>
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="rightMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>6</number>
</property>
<item>
@@ -897,16 +870,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye
<string>Saves</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
- <property name="leftMargin">
- <number>6</number>
- </property>
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="rightMargin">
- <number>6</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>6</number>
</property>
<item>
@@ -935,16 +899,7 @@ p, li { white-space: pre-wrap; }
<string>Downloads</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
- <property name="leftMargin">
- <number>2</number>
- </property>
- <property name="topMargin">
- <number>2</number>
- </property>
- <property name="rightMargin">
- <number>2</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>2</number>
</property>
<item>
@@ -1045,7 +1000,7 @@ p, li { white-space: pre-wrap; }
<bool>true</bool>
</property>
<property name="contextMenuPolicy">
- <enum>Qt::PreventContextMenu</enum>
+ <enum>Qt::CustomContextMenu</enum>
</property>
<property name="windowTitle">
<string>Tool Bar</string>
@@ -1210,7 +1165,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="icon">
<iconset resource="resources.qrc">
- <normaloff>:/MO/gui/resources/dialog-warning.png</normaloff>:/MO/gui/resources/dialog-warning.png</iconset>
+ <normaloff>:/MO/gui/warning</normaloff>:/MO/gui/warning</iconset>
</property>
<property name="text">
<string>No Problems</string>
diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp
index 3cf31f7e..75e7e499 100644
--- a/src/modinfodialog.cpp
+++ b/src/modinfodialog.cpp
@@ -38,6 +38,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <QFileSystemModel>
#include <Shlwapi.h>
#include <sstream>
+#include <QInputDialog>
using QtJson::Json;
@@ -146,7 +147,7 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo
QTabWidget *tabWidget = findChild<QTabWidget*>("tabWidget");
tabWidget->setTabEnabled(TAB_TEXTFILES, textFileList->count() != 0);
- tabWidget->setTabEnabled(TAB_INIFILES, (iniFileList->count() != 0) || (iniTweaksList->count() != 0));
+ //tabWidget->setTabEnabled(TAB_INIFILES, (iniFileList->count() != 0) || (iniTweaksList->count() != 0));
tabWidget->setTabEnabled(TAB_IMAGES, thumbnailArea->count() != 0);
tabWidget->setTabEnabled(TAB_ESPS, (inactiveESPList->count() != 0) || (activeESPList->count() != 0));
tabWidget->setTabEnabled(TAB_CONFLICTS, m_Origin != NULL);
@@ -409,8 +410,6 @@ void ModInfoDialog::openTextFile(const QString &fileName)
void ModInfoDialog::openIniFile(const QString &fileName)
{
- QPushButton* saveButton = findChild<QPushButton*>("saveButton");
-
QFile iniFile(fileName);
iniFile.open(QIODevice::ReadOnly);
QByteArray buffer = iniFile.readAll();
@@ -421,7 +420,7 @@ void ModInfoDialog::openIniFile(const QString &fileName)
iniFileView->setProperty("encoding", codec->name());
iniFile.close();
- saveButton->setEnabled(false);
+ ui->saveButton->setEnabled(false);
}
@@ -515,8 +514,9 @@ void ModInfoDialog::saveCurrentIniFile()
{
QVariant fileNameVar = ui->iniFileView->property("currentFile");
QVariant encodingVar = ui->iniFileView->property("encoding");
- if (fileNameVar.isValid()) {
+ if (fileNameVar.isValid() && !fileNameVar.toString().isEmpty()) {
QString fileName = fileNameVar.toString();
+ QDir().mkpath(QFileInfo(fileName).absolutePath());
QFile txtFile(fileName);
txtFile.open(QIODevice::WriteOnly);
txtFile.resize(0);
@@ -1171,3 +1171,29 @@ void ModInfoDialog::on_prevButton_clicked()
emit modOpenPrev();
this->accept();
}
+
+
+void ModInfoDialog::createTweak()
+{
+ QString name = QInputDialog::getText(this, tr("Name"), tr("Please enter a name"));
+ if (!fixDirectoryName(name)) {
+ QMessageBox::critical(this, tr("Error"), tr("Invalid name. Must be a valid file name"));
+ return;
+ } else if (name.isEmpty()) {
+ return;
+ } else if (ui->iniTweaksList->findItems(name, Qt::MatchFixedString).count() != 0) {
+ QMessageBox::critical(this, tr("Error"), tr("A tweak by that name exists"));
+ return;
+ }
+
+ QListWidgetItem *newTweak = new QListWidgetItem(name);
+ newTweak->setData(Qt::UserRole, "INI Tweaks/" + name + ".ini");
+ ui->iniTweaksList->addItem(newTweak);
+}
+
+void ModInfoDialog::on_iniTweaksList_customContextMenuRequested(const QPoint &pos)
+{
+ QMenu menu;
+ menu.addAction(tr("Create Tweak"), this, SLOT(createTweak()));
+ menu.exec(ui->iniTweaksList->mapToGlobal(pos));
+}
diff --git a/src/modinfodialog.h b/src/modinfodialog.h
index c3f3838c..b33b743e 100644
--- a/src/modinfodialog.h
+++ b/src/modinfodialog.h
@@ -186,6 +186,9 @@ private slots:
void on_prevButton_clicked();
+ void on_iniTweaksList_customContextMenuRequested(const QPoint &pos);
+
+ void createTweak();
private:
Ui::ModInfoDialog *ui;
diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui
index 343d4646..7e06745d 100644
--- a/src/modinfodialog.ui
+++ b/src/modinfodialog.ui
@@ -106,6 +106,9 @@
<height>16777215</height>
</size>
</property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
</widget>
</item>
</layout>
@@ -224,16 +227,7 @@ p, li { white-space: pre-wrap; }
<property name="spacing">
<number>0</number>
</property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
+ <property name="margin">
<number>0</number>
</property>
<item>
diff --git a/src/organizer.pro b/src/organizer.pro
index c877875b..339a50cd 100644
--- a/src/organizer.pro
+++ b/src/organizer.pro
@@ -77,7 +77,10 @@ SOURCES += \
qtgroupingproxy.cpp \
modlistview.cpp \
problemsdialog.cpp \
- serverinfo.cpp
+ serverinfo.cpp \
+ ../esptk/record.cpp \
+ ../esptk/espfile.cpp \
+ ../esptk/subrecord.cpp
HEADERS += \
transfersavesdialog.h \
@@ -142,7 +145,10 @@ HEADERS += \
qtgroupingproxy.h \
modlistview.h \
problemsdialog.h \
- serverinfo.h
+ serverinfo.h \
+ ../esptk/record.h \
+ ../esptk/espfile.h \
+ ../esptk/subrecord.h
FORMS += \
transfersavesdialog.ui \
@@ -174,7 +180,7 @@ FORMS += \
savetextasdialog.ui \
problemsdialog.ui
-INCLUDEPATH += ../shared ../archive ../uibase ../bsatk "$(BOOSTPATH)"
+INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk "$(BOOSTPATH)"
LIBS += -L"$(BOOSTPATH)/stage/lib"
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index 95780c18..f73805fd 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -23,6 +23,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <utility.h>
#include "settings.h"
#include <gameinfo.h>
+#include <espfile.h>
#include <windows_error.h>
#include <QtDebug>
@@ -140,7 +141,7 @@ void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseD
bool archive = false;
FilesOrigin &origin = baseDirectory.getOriginByID(current->getOrigin(archive));
- m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName())));
+ m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName()), ToQString(current->getFullPath())));
}
}
@@ -329,6 +330,8 @@ void PluginList::readEnabledFrom(const QString &fileName)
}
file.close();
+
+ testMasters();
}
@@ -589,6 +592,31 @@ int PluginList::columnCount(const QModelIndex &) const
}
+void PluginList::testMasters()
+{
+ std::set<QString> enabledMasters;
+ for (auto iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
+ if (iter->m_Enabled) {
+ enabledMasters.insert(iter->m_Name.toLower());
+ }
+ }
+
+ for (auto iter = m_ESPs.begin(); iter != m_ESPs.end(); ++iter) {
+ iter->m_MasterUnset = false;
+ if (iter->m_Enabled) {
+ for (auto master = iter->m_Masters.begin(); master != iter->m_Masters.end(); ++master) {
+ if (enabledMasters.find(master->toLower()) == enabledMasters.end()) {
+ iter->m_MasterUnset = true;
+ break;
+ }
+ }
+ }
+ }
+
+ emit layoutChanged();
+}
+
+
QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
{
int index = modelIndex.row();
@@ -613,13 +641,22 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
} break;
}
} else if ((role == Qt::DecorationRole) && (modelIndex.column() == 0)) {
- if (m_LockedOrder.find(m_ESPs[index].m_Name.toLower()) != m_LockedOrder.end()) {
+ if (m_ESPs[index].m_MasterUnset) {
+ return QIcon(":/MO/gui/warning");
+ } else if (m_LockedOrder.find(m_ESPs[index].m_Name.toLower()) != m_LockedOrder.end()) {
return QIcon(":/MO/gui/locked");
} else {
return QVariant();
}
} else if ((role == Qt::CheckStateRole) && (modelIndex.column() == 0)) {
return m_ESPs[index].m_Enabled ? Qt::Checked : Qt::Unchecked;
+ } else if (role == Qt::FontRole) {
+ QFont result;
+ if (m_ESPs[index].m_IsMaster) {
+ result.setItalic(true);
+ result.setWeight(QFont::Bold);
+ }
+ return result;
} else if (role == Qt::TextAlignmentRole) {
if (modelIndex.column() == 0) {
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
@@ -630,7 +667,11 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const
if (m_ESPs[index].m_ForceEnabled) {
return tr("This plugin can't be disabled (enforced by the game)");
} else {
- return tr("Origin: %1").arg(m_ESPs[index].m_OriginName);
+ QString text = tr("Origin: %1").arg(m_ESPs[index].m_OriginName);
+ if (m_ESPs[index].m_MasterUnset) {
+ text += "\nDepends on the following masters: " + SetJoin(m_ESPs[index].m_Masters, ", ");
+ }
+ return text;
}
} else {
return QVariant();
@@ -694,17 +735,16 @@ void PluginList::setPluginPriority(int row, int &newPriority)
{
int newPriorityTemp = newPriority;
- QString sourceExtension = m_ESPs[row].m_Name.right(3).toLower();
- if (sourceExtension == "esp") {
+ if (!m_ESPs[row].m_IsMaster) {
// don't allow esps to be moved above esms
while ((newPriorityTemp < static_cast<int>(m_ESPsByPriority.size() - 1)) &&
- (m_ESPs[m_ESPsByPriority[newPriorityTemp]].m_Name.right(3).toLower() == "esm")) {
+ m_ESPs[m_ESPsByPriority[newPriorityTemp]].m_IsMaster) {
++newPriorityTemp;
}
} else {
// don't allow esms to be moved below esps
while ((newPriorityTemp > 0) &&
- (m_ESPs[m_ESPsByPriority[newPriorityTemp - 1]].m_Name.right(3).toLower() == "esp")) {
+ !m_ESPs[m_ESPsByPriority[newPriorityTemp]].m_IsMaster) {
--newPriorityTemp;
}
// also don't allow "regular" esms to be moved above primary plugins
@@ -774,6 +814,8 @@ void PluginList::changePluginPriority(std::vector<int> rows, int newPriority)
void PluginList::startSaveTime()
{
+ testMasters();
+
if (!m_SaveTimer.isActive()) {
m_SaveTimer.start(2000);
}
@@ -814,7 +856,6 @@ bool PluginList::dropMimeData(const QMimeData *mimeData, Qt::DropAction action,
}
changePluginPriority(sourceRows, newPriority);
-
return false;
}
@@ -883,3 +924,21 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event)
}
return QObject::eventFilter(obj, event);
}
+
+
+PluginList::ESPInfo::ESPInfo(const QString &name, bool enabled, FILETIME time, const QString &originName, const QString &fullPath)
+ : m_Name(name), m_Enabled(enabled), m_ForceEnabled(enabled), m_Removed(false), m_Priority(0),
+ m_LoadOrder(-1), m_Time(time), m_OriginName(originName)
+{
+ try {
+ ESP::File file(ToWString(fullPath));
+ m_IsMaster = file.isMaster();
+ std::set<std::string> masters = file.masters();
+ for (auto iter = masters.begin(); iter != masters.end(); ++iter) {
+ m_Masters.insert(QString(iter->c_str()));
+ }
+ } catch (const std::exception &e) {
+ reportError(tr("failed to parse esp file %1: %2").arg(fullPath).arg(e.what()));
+ m_IsMaster = false;
+ }
+}
diff --git a/src/pluginlist.h b/src/pluginlist.h
index 003abd53..b1f1cc0e 100644
--- a/src/pluginlist.h
+++ b/src/pluginlist.h
@@ -171,28 +171,11 @@ signals:
private:
- void syncLoadOrder();
- void updateIndices();
-
- void writePlugins(const QString &fileName, bool writeUnchecked) const;
- void writeLockedOrder(const QString &fileName) const;
-
- bool readLoadOrder(const QString &fileName);
- void readLockedOrderFrom(const QString &fileName);
- void setPluginPriority(int row, int &newPriority);
- void changePluginPriority(std::vector<int> rows, int newPriority);
-
- void startSaveTime();
-
-private:
-
struct ESPInfo {
- ESPInfo(const QString &name, bool enabled, FILETIME time, const QString &originName)
- : m_Name(name), m_Enabled(enabled), m_ForceEnabled(enabled), m_Removed(false), m_Priority(0),
- m_LoadOrder(-1), m_Time(time), m_OriginName(originName),
- m_IsMaster(name.endsWith("esm", Qt::CaseInsensitive)) {}
+ ESPInfo(const QString &name, bool enabled, FILETIME time, const QString &originName, const QString &fullPath);
QString m_Name;
+ QString m_FullPath;
bool m_Enabled;
bool m_ForceEnabled;
bool m_Removed;
@@ -201,6 +184,8 @@ private:
FILETIME m_Time;
QString m_OriginName;
bool m_IsMaster;
+ std::set<QString> m_Masters;
+ mutable bool m_MasterUnset;
};
friend bool ByName(const ESPInfo& LHS, const ESPInfo& RHS);
@@ -209,6 +194,23 @@ private:
private:
+ void syncLoadOrder();
+ void updateIndices();
+
+ void writePlugins(const QString &fileName, bool writeUnchecked) const;
+ void writeLockedOrder(const QString &fileName) const;
+
+ bool readLoadOrder(const QString &fileName);
+ void readLockedOrderFrom(const QString &fileName);
+ void setPluginPriority(int row, int &newPriority);
+ void changePluginPriority(std::vector<int> rows, int newPriority);
+
+ void startSaveTime();
+
+ void testMasters();
+
+private:
+
std::vector<ESPInfo> m_ESPs;
std::map<QString, int> m_ESPsByName;
diff --git a/src/resources.qrc b/src/resources.qrc
index df17ea79..3f27e2cc 100644
--- a/src/resources.qrc
+++ b/src/resources.qrc
@@ -27,8 +27,7 @@
<file>resources/emblem-important.png</file>
<file>resources/check.png</file>
<file>mo_icon.ico</file>
- <file>resources/dialog-warning.png</file>
- <file>resources/dialog-warning_16.png</file>
+ <file alias="warning">resources/dialog-warning.png</file>
<file alias="emblem_backup">resources/symbol-backup.png</file>
<file alias="icon_tools">resources/applications-accessories.png</file>
<file alias="emblem_problem">resources/emblem-unreadable.png</file>
@@ -51,5 +50,6 @@
<file alias="emblem_conflict_redundant">resources/conflict-redundant.png</file>
<file alias="emblem_notes">resources/accessories-text-editor.png</file>
<file alias="version_date">resources/x-office-calendar.png</file>
+ <file alias="warning_16">resources/dialog-warning_16.png</file>
</qresource>
</RCC>
diff --git a/src/resources/dialog-warning_16.png (warning_16) b/src/resources/dialog-warning_16.png (warning_16)
new file mode 100644
index 00000000..a9e4ff39
--- /dev/null
+++ b/src/resources/dialog-warning_16.png (warning_16)
Binary files differ
diff --git a/src/version.rc b/src/version.rc
index 010c7d4c..fb8dcf7c 100644
--- a/src/version.rc
+++ b/src/version.rc
@@ -1,7 +1,7 @@
#include "Winver.h"
-#define VER_FILEVERSION 0,99,6,0
-#define VER_FILEVERSION_STR "0,99,6,0\0"
+#define VER_FILEVERSION 0,99,7,0
+#define VER_FILEVERSION_STR "0,99,7,0\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION