diff options
| author | Jeremy Rimpo <jeremy.rimpo@servermonkey.com> | 2024-07-11 09:46:29 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-11 16:46:29 +0200 |
| commit | 193442e77362edfdb55636f907a14098be59fd2a (patch) | |
| tree | 9b2a1726857cedc6785afcec942a6e696f498ce7 | |
| parent | a4f6298111b9b4518d00e6df3a53dd176858dd34 (diff) | |
Archive preview support (#2056)
* Support for archive file previews
- Should account for alternates
- Extracts files and requests preview from plugins that claim support
| -rw-r--r-- | .github/workflows/build.yml | 2 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/filetree.cpp | 8 | ||||
| -rw-r--r-- | src/modinfodialog.cpp | 6 | ||||
| -rw-r--r-- | src/modinfodialogimages.cpp | 2 | ||||
| -rw-r--r-- | src/organizercore.cpp | 27 | ||||
| -rw-r--r-- | src/previewgenerator.cpp | 22 | ||||
| -rw-r--r-- | src/previewgenerator.h | 4 |
8 files changed, 54 insertions, 20 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 89f3bc7c..c5857574 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,5 +16,5 @@ jobs: qt-modules: qtpositioning qtwebchannel qtwebengine qtwebsockets mo2-third-parties: 7z zlib gtest libbsarch libloot openssl bzip2 python lz4 spdlog - boost boost-di sip pyqt pybind11 ss licenses explorerpp + boost boost-di sip pyqt pybind11 ss licenses explorerpp DirectXTex mo2-dependencies: usvfs cmake_common uibase githubpp bsatk esptk archive lootcli game_gamebryo diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 10459e7e..7188c03b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,8 +7,9 @@ mo2_configure_executable(organizer EXTRA_TRANSLATIONS ${MO2_SUPER_PATH}/game_gamebryo/src ${MO2_UIBASE_PATH}/src PRIVATE_DEPENDS uibase githubpp bsatk esptk archive usvfs lootcli boost::program_options - Qt::WebEngineWidgets Qt::WebSockets) + DirectXTex libbsarch Qt::WebEngineWidgets Qt::WebSockets) target_link_libraries(organizer PUBLIC Shlwapi) +target_include_directories(organizer PUBLIC ${DDS_ROOT}) mo2_install_target(organizer) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/dlls.manifest.qt6" diff --git a/src/filetree.cpp b/src/filetree.cpp index f043448f..6d397f24 100644 --- a/src/filetree.cpp +++ b/src/filetree.cpp @@ -246,16 +246,12 @@ void FileTree::activate(FileTreeItem* item) return; } - if (item->isFromArchive()) { - log::warn("cannot activate file from archive '{}'", item->filename()); - return; - } - const auto tryPreview = m_core.settings().interface().doubleClicksOpenPreviews(); if (tryPreview) { const QFileInfo fi(item->realPath()); - if (m_plugins.previewGenerator().previewSupported(fi.suffix().toLower())) { + if (m_plugins.previewGenerator().previewSupported(fi.suffix().toLower(), + item->isFromArchive())) { preview(item); return; } diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index d0e8d1ad..1798e987 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -42,12 +42,8 @@ const int max_scan_for_context_menu = 50; bool canPreviewFile(const PluginContainer& pluginContainer, bool isArchive, const QString& filename) { - if (isArchive) { - return false; - } - const auto ext = QFileInfo(filename).suffix().toLower(); - return pluginContainer.previewGenerator().previewSupported(ext); + return pluginContainer.previewGenerator().previewSupported(ext, isArchive); } bool isExecutableFilename(const QString& filename) diff --git a/src/modinfodialogimages.cpp b/src/modinfodialogimages.cpp index 1042eaca..7b250e1e 100644 --- a/src/modinfodialogimages.cpp +++ b/src/modinfodialogimages.cpp @@ -262,7 +262,7 @@ void ImagesTab::select(std::size_t i, Visibility v) ui->imagesPath->setText(QDir::toNativeSeparators(f->path())); ui->imagesExplore->setEnabled(true); if (plugin().previewGenerator().previewSupported( - QFileInfo(f->path()).suffix().toLower())) + QFileInfo(f->path()).suffix().toLower(), false)) ui->previewPluginButton->setEnabled(true); else ui->previewPluginButton->setEnabled(false); diff --git a/src/organizercore.cpp b/src/organizercore.cpp index f471ead1..0f6a1455 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -71,6 +71,8 @@ #include <tuple> #include <utility> +#include "bs_archive.h" + #include "organizerproxy.h" using namespace MOShared; @@ -1053,7 +1055,7 @@ bool OrganizerCore::previewFileWithAlternatives(QWidget* parent, QString fileNam // set up preview dialog PreviewDialog preview(fileName, parent); - auto addFunc = [&](int originId) { + auto addFunc = [&](int originId, std::wstring archiveName = L"") { FilesOrigin& origin = directoryStructure()->getOriginByID(originId); QString filePath = QDir::fromNativeSeparators(ToQString(origin.getPath())) + "/" + fileName; @@ -1066,14 +1068,33 @@ bool OrganizerCore::previewFileWithAlternatives(QWidget* parent, QString fileNam } else { preview.addVariant(ToQString(origin.getName()), wid); } + } else if (archiveName != L"") { + auto archiveFile = directoryStructure()->searchFile(archiveName); + if (archiveFile.get() != nullptr) { + try { + libbsarch::bs_archive archiveLoader; + archiveLoader.load_from_disk(archiveFile->getFullPath()); + libbsarch::memory_blob fileData = + archiveLoader.extract_to_memory(fileName.toStdWString()); + QByteArray convertedFileData((char*)(fileData.data), fileData.size); + QWidget* wid = m_PluginContainer->previewGenerator().genArchivePreview( + convertedFileData, filePath); + if (wid == nullptr) { + reportError(tr("failed to generate preview for %1").arg(filePath)); + } else { + preview.addVariant(ToQString(origin.getName()), wid); + } + } catch (std::exception& e) { + } + } } }; if (selectedOrigin == -1) { // don't bother with the vector of origins, just add them as they come - addFunc(file->getOrigin()); + addFunc(file->getOrigin(), file->isFromArchive() ? file->getArchive().name() : L""); for (const auto& alt : file->getAlternatives()) { - addFunc(alt.originID()); + addFunc(alt.originID(), alt.isFromArchive() ? alt.archive().name() : L""); } } else { std::vector<int> origins; diff --git a/src/previewgenerator.cpp b/src/previewgenerator.cpp index ba73c065..dad41c2f 100644 --- a/src/previewgenerator.cpp +++ b/src/previewgenerator.cpp @@ -35,12 +35,16 @@ PreviewGenerator::PreviewGenerator(const PluginContainer& pluginContainer) m_MaxSize = QGuiApplication::primaryScreen()->size() * 0.8; } -bool PreviewGenerator::previewSupported(const QString& fileExtension) const +bool PreviewGenerator::previewSupported(const QString& fileExtension, + const bool& isArchive) const { auto& previews = m_PluginContainer.plugins<IPluginPreview>(); for (auto* preview : previews) { if (preview->supportedExtensions().contains(fileExtension)) { - return true; + if (!isArchive) + return true; + if (preview->supportsArchives()) + return true; } } return false; @@ -58,3 +62,17 @@ QWidget* PreviewGenerator::genPreview(const QString& fileName) const } return nullptr; } + +QWidget* PreviewGenerator::genArchivePreview(const QByteArray& fileData, + const QString& fileName) const +{ + const QString ext = QFileInfo(fileName).suffix().toLower(); + auto& previews = m_PluginContainer.plugins<IPluginPreview>(); + for (auto* preview : previews) { + if (m_PluginContainer.isEnabled(preview) && + preview->supportedExtensions().contains(ext) && preview->supportsArchives()) { + return preview->genDataPreview(fileData, fileName, m_MaxSize); + } + } + return nullptr; +} diff --git a/src/previewgenerator.h b/src/previewgenerator.h index dd0d2cd4..15d652f6 100644 --- a/src/previewgenerator.h +++ b/src/previewgenerator.h @@ -33,10 +33,12 @@ class PreviewGenerator public: PreviewGenerator(const PluginContainer& pluginContainer); - bool previewSupported(const QString& fileExtension) const; + bool previewSupported(const QString& fileExtension, const bool& isArchive) const; QWidget* genPreview(const QString& fileName) const; + QWidget* genArchivePreview(const QByteArray& fileData, const QString& fileName) const; + private: const PluginContainer& m_PluginContainer; QSize m_MaxSize; |
