diff options
| author | Tannin <devnull@localhost> | 2013-09-11 22:54:45 +0200 |
|---|---|---|
| committer | Tannin <devnull@localhost> | 2013-09-11 22:54:45 +0200 |
| commit | af6e1c3ab4f3687c88715dffff8b1bf2f38a15d6 (patch) | |
| tree | 414f43c931e2e040344e87d2f6317196c1cea108 | |
| parent | 50325c8fc23fdeed6e1acb90917e8e2889a1140f (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
| -rw-r--r-- | src/ModOrganizer.pro | 3 | ||||
| -rw-r--r-- | src/downloadlistwidget.cpp | 2 | ||||
| -rw-r--r-- | src/downloadlistwidgetcompact.cpp | 2 | ||||
| -rw-r--r-- | src/installationmanager.cpp | 7 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 64 | ||||
| -rw-r--r-- | src/mainwindow.h | 6 | ||||
| -rw-r--r-- | src/mainwindow.ui | 59 | ||||
| -rw-r--r-- | src/modinfodialog.cpp | 36 | ||||
| -rw-r--r-- | src/modinfodialog.h | 3 | ||||
| -rw-r--r-- | src/modinfodialog.ui | 14 | ||||
| -rw-r--r-- | src/organizer.pro | 12 | ||||
| -rw-r--r-- | src/pluginlist.cpp | 75 | ||||
| -rw-r--r-- | src/pluginlist.h | 40 | ||||
| -rw-r--r-- | src/resources.qrc | 4 | ||||
| -rw-r--r-- | src/resources/dialog-warning_16.png (warning_16) | bin | 0 -> 603 bytes | |||
| -rw-r--r-- | src/version.rc | 4 |
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) Binary files differnew file mode 100644 index 00000000..a9e4ff39 --- /dev/null +++ b/src/resources/dialog-warning_16.png (warning_16) 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
|
