Skip to content

Commit b157ebb

Browse files
authored
Merge pull request #154 from Silarn/mainline_dev
Implementing archive parsing some prioritization
2 parents 554b468 + 385a888 commit b157ebb

16 files changed

+412
-83
lines changed

src/iuserinterface.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class IUserInterface
2828

2929
virtual void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab) = 0;
3030

31+
virtual void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives) = 0;
32+
33+
virtual MOBase::DelayedFileWriterBase &archivesWriter() = 0;
34+
3135
virtual ILockedWaitingForProcess* lock() = 0;
3236
virtual void unlock() = 0;
3337
};

src/mainwindow.cpp

Lines changed: 194 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ MainWindow::MainWindow(QSettings &initSettings
200200
, m_OrganizerCore(organizerCore)
201201
, m_PluginContainer(pluginContainer)
202202
, m_DidUpdateMasterList(false)
203+
, m_ArchiveListWriter(std::bind(&MainWindow::saveArchiveList, this))
203204
{
204205
QWebEngineProfile::defaultProfile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);
205206
QWebEngineProfile::defaultProfile()->setHttpCacheMaximumSize(52428800);
@@ -278,6 +279,8 @@ MainWindow::MainWindow(QSettings &initSettings
278279
ui->espList->setItemDelegateForColumn(PluginList::COL_FLAGS, new GenericIconDelegate(ui->espList));
279280
ui->espList->installEventFilter(m_OrganizerCore.pluginList());
280281

282+
ui->bsaList->setLocalMoveOnly(true);
283+
281284
bool pluginListAdjusted = registerWidgetState(ui->espList->objectName(), ui->espList->header(), "plugin_list_state");
282285
registerWidgetState(ui->dataTree->objectName(), ui->dataTree->header());
283286
registerWidgetState(ui->downloadView->objectName(),
@@ -358,6 +361,9 @@ MainWindow::MainWindow(QSettings &initSettings
358361

359362
connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString)));
360363

364+
m_CheckBSATimer.setSingleShot(true);
365+
connect(&m_CheckBSATimer, SIGNAL(timeout()), this, SLOT(checkBSAList()));
366+
361367
connect(ui->espList->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(esplistSelectionsChanged(QItemSelection)));
362368
connect(ui->modList->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(modlistSelectionsChanged(QItemSelection)));
363369

@@ -1142,17 +1148,17 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director
11421148
fileChild->setData(1, Qt::UserRole, source);
11431149
fileChild->setData(1, Qt::UserRole + 1, originID);
11441150

1145-
std::vector<int> alternatives = current->getAlternatives();
1151+
std::vector<std::pair<int, std::wstring>> alternatives = current->getAlternatives();
11461152

11471153
if (!alternatives.empty()) {
11481154
std::wostringstream altString;
11491155
altString << ToWString(tr("Also in: <br>"));
1150-
for (std::vector<int>::iterator altIter = alternatives.begin();
1156+
for (std::vector<std::pair<int, std::wstring>>::iterator altIter = alternatives.begin();
11511157
altIter != alternatives.end(); ++altIter) {
11521158
if (altIter != alternatives.begin()) {
11531159
altString << " , ";
11541160
}
1155-
altString << "<span style=\"white-space: nowrap;\"><i>" << m_OrganizerCore.directoryStructure()->getOriginByID(*altIter).getName() << "</font></span>";
1161+
altString << "<span style=\"white-space: nowrap;\"><i>" << m_OrganizerCore.directoryStructure()->getOriginByID(altIter->first).getName() << "</font></span>";
11561162
}
11571163
fileChild->setToolTip(1, QString("%1").arg(ToQString(altString.str())));
11581164
fileChild->setForeground(1, QBrush(Qt::red));
@@ -1378,6 +1384,151 @@ static QStringList toStringList(InputIterator current, InputIterator end)
13781384
return result;
13791385
}
13801386

1387+
void MainWindow::updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives)
1388+
{
1389+
m_DefaultArchives = defaultArchives;
1390+
ui->bsaList->clear();
1391+
ui->bsaList->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
1392+
std::vector<std::pair<UINT32, QTreeWidgetItem*>> items;
1393+
1394+
BSAInvalidation * invalidation = m_OrganizerCore.managedGame()->feature<BSAInvalidation>();
1395+
std::vector<FileEntry::Ptr> files = m_OrganizerCore.directoryStructure()->getFiles();
1396+
1397+
QStringList plugins = m_OrganizerCore.findFiles("", [](const QString &fileName) -> bool {
1398+
return fileName.endsWith(".esp", Qt::CaseInsensitive)
1399+
|| fileName.endsWith(".esm", Qt::CaseInsensitive)
1400+
|| fileName.endsWith(".esl", Qt::CaseInsensitive);
1401+
});
1402+
1403+
auto hasAssociatedPlugin = [&](const QString &bsaName) -> bool {
1404+
for (const QString &pluginName : plugins) {
1405+
QFileInfo pluginInfo(pluginName);
1406+
if (bsaName.startsWith(QFileInfo(pluginName).baseName(), Qt::CaseInsensitive)
1407+
&& (m_OrganizerCore.pluginList()->state(pluginInfo.fileName()) == IPluginList::STATE_ACTIVE)) {
1408+
return true;
1409+
}
1410+
}
1411+
return false;
1412+
};
1413+
1414+
for (FileEntry::Ptr current : files) {
1415+
QFileInfo fileInfo(ToQString(current->getName().c_str()));
1416+
1417+
if (fileInfo.suffix().toLower() == "bsa" || fileInfo.suffix().toLower() == "ba2") {
1418+
int index = activeArchives.indexOf(fileInfo.fileName());
1419+
if (index == -1) {
1420+
index = 0xFFFF;
1421+
}
1422+
else {
1423+
index += 2;
1424+
}
1425+
1426+
if ((invalidation != nullptr) && invalidation->isInvalidationBSA(fileInfo.fileName())) {
1427+
index = 1;
1428+
}
1429+
1430+
int originId = current->getOrigin();
1431+
FilesOrigin & origin = m_OrganizerCore.directoryStructure()->getOriginByID(originId);
1432+
1433+
QTreeWidgetItem * newItem = new QTreeWidgetItem(QStringList()
1434+
<< fileInfo.fileName()
1435+
<< ToQString(origin.getName()));
1436+
newItem->setData(0, Qt::UserRole, index);
1437+
newItem->setData(1, Qt::UserRole, originId);
1438+
newItem->setFlags(newItem->flags() & ~(Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable));
1439+
newItem->setCheckState(0, (index != -1) ? Qt::Checked : Qt::Unchecked);
1440+
newItem->setData(0, Qt::UserRole, false);
1441+
if (m_OrganizerCore.settings().forceEnableCoreFiles()
1442+
&& defaultArchives.contains(fileInfo.fileName())) {
1443+
newItem->setCheckState(0, Qt::Checked);
1444+
newItem->setDisabled(true);
1445+
newItem->setData(0, Qt::UserRole, true);
1446+
} else if (fileInfo.fileName().compare("update.bsa", Qt::CaseInsensitive) == 0) {
1447+
newItem->setCheckState(0, Qt::Checked);
1448+
newItem->setDisabled(true);
1449+
} else if (hasAssociatedPlugin(fileInfo.fileName())) {
1450+
newItem->setCheckState(0, Qt::Checked);
1451+
newItem->setDisabled(true);
1452+
} else {
1453+
newItem->setCheckState(0, Qt::Unchecked);
1454+
newItem->setDisabled(true);
1455+
}
1456+
if (index < 0) index = 0;
1457+
1458+
UINT32 sortValue = ((origin.getPriority() & 0xFFFF) << 16) | (index & 0xFFFF);
1459+
items.push_back(std::make_pair(sortValue, newItem));
1460+
}
1461+
}
1462+
std::sort(items.begin(), items.end(), BySortValue);
1463+
1464+
for (auto iter = items.begin(); iter != items.end(); ++iter) {
1465+
int originID = iter->second->data(1, Qt::UserRole).toInt();
1466+
1467+
FilesOrigin origin = m_OrganizerCore.directoryStructure()->getOriginByID(originID);
1468+
QString modName("data");
1469+
unsigned int modIndex = ModInfo::getIndex(ToQString(origin.getName()));
1470+
if (modIndex != UINT_MAX) {
1471+
ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex);
1472+
modName = modInfo->name();
1473+
}
1474+
QList<QTreeWidgetItem*> items = ui->bsaList->findItems(modName, Qt::MatchFixedString);
1475+
QTreeWidgetItem * subItem = nullptr;
1476+
if (items.length() > 0) {
1477+
subItem = items.at(0);
1478+
}
1479+
else {
1480+
subItem = new QTreeWidgetItem(QStringList(modName));
1481+
subItem->setFlags(subItem->flags() & ~Qt::ItemIsDragEnabled);
1482+
ui->bsaList->addTopLevelItem(subItem);
1483+
}
1484+
subItem->addChild(iter->second);
1485+
subItem->setExpanded(true);
1486+
}
1487+
checkBSAList();
1488+
}
1489+
1490+
void MainWindow::checkBSAList()
1491+
{
1492+
DataArchives * archives = m_OrganizerCore.managedGame()->feature<DataArchives>();
1493+
1494+
if (archives != nullptr) {
1495+
ui->bsaList->blockSignals(true);
1496+
ON_BLOCK_EXIT([&]() { ui->bsaList->blockSignals(false); });
1497+
1498+
QStringList defaultArchives = archives->archives(m_OrganizerCore.currentProfile());
1499+
1500+
bool warning = false;
1501+
1502+
for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) {
1503+
bool modWarning = false;
1504+
QTreeWidgetItem * tlItem = ui->bsaList->topLevelItem(i);
1505+
for (int j = 0; j < tlItem->childCount(); ++j) {
1506+
QTreeWidgetItem * item = tlItem->child(j);
1507+
QString filename = item->text(0);
1508+
item->setIcon(0, QIcon());
1509+
item->setToolTip(0, QString());
1510+
1511+
if (item->checkState(0) == Qt::Unchecked) {
1512+
if (defaultArchives.contains(filename)) {
1513+
item->setIcon(0, QIcon(":/MO/gui/warning"));
1514+
item->setToolTip(0, tr("This bsa is enabled in the ini file so it may be required!"));
1515+
modWarning = true;
1516+
}
1517+
}
1518+
}
1519+
if (modWarning) {
1520+
ui->bsaList->expandItem(ui->bsaList->topLevelItem(i));
1521+
warning = true;
1522+
}
1523+
}
1524+
if (warning) {
1525+
ui->tabWidget->setTabIcon(1, QIcon(":/MO/gui/warning"));
1526+
} else {
1527+
ui->tabWidget->setTabIcon(1, QIcon());
1528+
}
1529+
}
1530+
}
1531+
13811532
void MainWindow::saveModMetas()
13821533
{
13831534
for (unsigned int i = 0; i < ModInfo::getNumMods(); ++i) {
@@ -1524,10 +1675,12 @@ void MainWindow::on_tabWidget_currentChanged(int index)
15241675
if (index == 0) {
15251676
m_OrganizerCore.refreshESPList();
15261677
} else if (index == 1) {
1527-
refreshDataTree();
1678+
m_OrganizerCore.refreshBSAList();
15281679
} else if (index == 2) {
1529-
refreshSaveList();
1680+
refreshDataTree();
15301681
} else if (index == 3) {
1682+
refreshSaveList();
1683+
} else if (index == 4) {
15311684
ui->downloadView->scrollToBottom();
15321685
}
15331686
}
@@ -1806,6 +1959,7 @@ void MainWindow::modorder_changed()
18061959
}
18071960
m_OrganizerCore.refreshBSAList();
18081961
m_OrganizerCore.currentProfile()->modlistWriter().write();
1962+
m_ArchiveListWriter.write();
18091963
m_OrganizerCore.directoryStructure()->getFileRegister()->sortOrigins();
18101964

18111965
{ // refresh selection
@@ -2741,6 +2895,27 @@ void MainWindow::replaceCategories_MenuHandler() {
27412895
refreshFilters();
27422896
}
27432897

2898+
void MainWindow::saveArchiveList()
2899+
{
2900+
if (m_OrganizerCore.isArchivesInit()) {
2901+
SafeWriteFile archiveFile(m_OrganizerCore.currentProfile()->getArchivesFileName());
2902+
for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) {
2903+
QTreeWidgetItem * tlItem = ui->bsaList->topLevelItem(i);
2904+
for (int j = 0; j < tlItem->childCount(); ++j) {
2905+
QTreeWidgetItem * item = tlItem->child(j);
2906+
if (item->checkState(0) == Qt::Checked) {
2907+
archiveFile->write(item->text(0).toUtf8().append("\r\n"));
2908+
}
2909+
}
2910+
}
2911+
if (archiveFile.commitIfDifferent(m_ArchiveListHash)) {
2912+
qDebug("%s saved", qPrintable(QDir::toNativeSeparators(m_OrganizerCore.currentProfile()->getArchivesFileName())));
2913+
}
2914+
} else {
2915+
qWarning("archive list not initialised");
2916+
}
2917+
}
2918+
27442919
void MainWindow::checkModsForUpdates()
27452920
{
27462921
statusBar()->show();
@@ -3588,8 +3763,8 @@ void MainWindow::previewDataFile()
35883763
};
35893764

35903765
addFunc(file->getOrigin());
3591-
for (int i : file->getAlternatives()) {
3592-
addFunc(i);
3766+
for (auto alt : file->getAlternatives()) {
3767+
addFunc(alt.first);
35933768
}
35943769
if (preview.numVariants() > 0) {
35953770
preview.exec();
@@ -3957,6 +4132,12 @@ void MainWindow::displayColumnSelection(const QPoint &pos)
39574132
}
39584133
}
39594134

4135+
void MainWindow::on_bsaList_itemChanged(QTreeWidgetItem*, int)
4136+
{
4137+
m_ArchiveListWriter.write();
4138+
m_CheckBSATimer.start(500);
4139+
}
4140+
39604141
void MainWindow::on_actionProblems_triggered()
39614142
{
39624143
ProblemsDialog problems(m_PluginContainer.plugins<IPluginDiagnose>(), this);
@@ -4543,6 +4724,12 @@ void MainWindow::on_categoriesOrBtn_toggled(bool checked)
45434724
}
45444725
}
45454726

4727+
void MainWindow::on_managedArchiveLabel_linkHovered(const QString&)
4728+
{
4729+
QToolTip::showText(QCursor::pos(),
4730+
ui->managedArchiveLabel->toolTip());
4731+
}
4732+
45464733
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
45474734
{
45484735
//Accept copy or move drags to the download window. Link drags are not

src/mainwindow.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,15 @@ class MainWindow : public QMainWindow, public IUserInterface
120120
virtual void unlock() override;
121121

122122
bool addProfile();
123+
void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives);
123124
void refreshDataTree();
124125
void refreshSaveList();
125126

126127
void setModListSorting(int index);
127128
void setESPListSorting(int index);
128129

130+
void saveArchiveList();
131+
129132
void registerPluginTool(MOBase::IPluginTool *tool);
130133
void registerModPage(MOBase::IPluginModPage *modPage);
131134

@@ -148,6 +151,8 @@ class MainWindow : public QMainWindow, public IUserInterface
148151
virtual bool closeWindow();
149152
virtual void setWindowEnabled(bool enabled);
150153

154+
virtual MOBase::DelayedFileWriterBase &archivesWriter() override { return m_ArchiveListWriter; }
155+
151156
public slots:
152157

153158
void displayColumnSelection(const QPoint &pos);
@@ -346,6 +351,8 @@ private slots:
346351

347352
std::vector<QTreeWidgetItem*> m_RemoveWidget;
348353

354+
QByteArray m_ArchiveListHash;
355+
349356
bool m_DidUpdateMasterList;
350357

351358
LockedDialogBase *m_LockDialog { nullptr };
@@ -355,6 +362,8 @@ private slots:
355362

356363
std::vector<std::pair<QString, QHeaderView*>> m_PersistedGeometry;
357364

365+
MOBase::DelayedFileWriter m_ArchiveListWriter;
366+
358367
enum class ShortcutType {
359368
Toolbar,
360369
Desktop,
@@ -478,6 +487,8 @@ private slots:
478487

479488
void startExeAction();
480489

490+
void checkBSAList();
491+
481492
void updateProblemsButton();
482493

483494
void saveModMetas();
@@ -552,6 +563,7 @@ private slots: // ui slots
552563
void on_categoriesList_itemSelectionChanged();
553564
void on_linkButton_pressed();
554565
void on_showHiddenBox_toggled(bool checked);
566+
void on_bsaList_itemChanged(QTreeWidgetItem *item, int column);
555567
void on_bossButton_clicked();
556568

557569
void on_saveButton_clicked();
@@ -561,6 +573,7 @@ private slots: // ui slots
561573
void on_actionCopy_Log_to_Clipboard_triggered();
562574
void on_categoriesAndBtn_toggled(bool checked);
563575
void on_categoriesOrBtn_toggled(bool checked);
576+
void on_managedArchiveLabel_linkHovered(const QString &link);
564577
};
565578

566579

0 commit comments

Comments
 (0)