From fd9eb032b6df5eafa89a60a515963ba7d4652f24 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Fri, 23 Mar 2018 17:48:00 +0100 Subject: Added file preview in conflicts tab in the mod information dialog. The preview is not working for the lower file list for some reason but I left the setup of the context menu and all in case somebody else can figure out what I'm missing. --- src/mainwindow.cpp | 2 +- src/modinfodialog.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/modinfodialog.h | 8 ++++- src/modinfodialog.ui | 6 ++++ 4 files changed, 110 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index faa4b880..d9d83231 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2450,7 +2450,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, } } else { modInfo->saveMeta(); - ModInfoDialog dialog(modInfo, m_OrganizerCore.directoryStructure(), modInfo->hasFlag(ModInfo::FLAG_FOREIGN), this); + ModInfoDialog dialog(modInfo, m_OrganizerCore.directoryStructure(), modInfo->hasFlag(ModInfo::FLAG_FOREIGN), &m_OrganizerCore, &m_PluginContainer,this); connect(&dialog, SIGNAL(nexusLinkActivated(QString)), this, SLOT(nexusLinkActivated(QString))); connect(&dialog, SIGNAL(downloadRequest(QString)), &m_OrganizerCore, SLOT(downloadRequestedNXM(QString))); connect(&dialog, SIGNAL(modOpen(QString, int)), this, SLOT(displayModInformation(QString, int)), Qt::QueuedConnection); diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index ccd2a122..f2042d15 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -30,6 +30,10 @@ along with Mod Organizer. If not, see . #include "questionboxmemory.h" #include "settings.h" #include "categories.h" +#include "organizercore.h" +#include "pluginlistsortproxy.h" +#include "previewgenerator.h" +#include "previewdialog.h" #include #include @@ -66,11 +70,12 @@ static bool operator<(const ModFileListWidget &LHS, const ModFileListWidget &RHS } -ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directory, bool unmanaged, QWidget *parent) +ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directory, bool unmanaged, OrganizerCore *organizerCore, PluginContainer *pluginContainer, QWidget *parent) : TutorableDialog("ModInfoDialog", parent), ui(new Ui::ModInfoDialog), m_ModInfo(modInfo), m_ThumbnailMapper(this), m_RequestStarted(false), m_DeleteAction(nullptr), m_RenameAction(nullptr), m_OpenAction(nullptr), - m_Directory(directory), m_Origin(nullptr) + m_Directory(directory), m_Origin(nullptr), + m_OrganizerCore(organizerCore), m_PluginContainer(pluginContainer) { ui->setupUi(this); this->setWindowTitle(modInfo->name()); @@ -1198,6 +1203,69 @@ void ModInfoDialog::unhideConflictFile() } +void ModInfoDialog::previewDataFile() +{ + QString fileName = QDir::fromNativeSeparators(m_ConflictsContextItem->data(0, Qt::UserRole).toString()); + + // what we have is an absolute path to the file in its actual location (for the primary origin) + // what we want is the path relative to the virtual data directory + + // we need to look in the virtual directory for the file to make sure the info is up to date. + + // check if the file comes from the actual data folder instead of a mod + QDir gameDirectory = m_OrganizerCore->managedGame()->dataDirectory().absolutePath(); + QString relativePath = gameDirectory.relativeFilePath(fileName); + QDir direRelativePath = gameDirectory.relativeFilePath(fileName); + // if the file is on a different drive the dirRelativePath will actually be an absolute path so we make sure that is not the case + if (!direRelativePath.isAbsolute() && !relativePath.startsWith("..")) { + fileName = relativePath; + } + else { + // crude: we search for the next slash after the base mod directory to skip everything up to the data-relative directory + int offset = m_OrganizerCore->settings().getModDirectory().size() + 1; + offset = fileName.indexOf("/", offset); + fileName = fileName.mid(offset + 1); + } + + + + const FileEntry::Ptr file = m_OrganizerCore->directoryStructure()->searchFile(ToWString(fileName), nullptr); + + if (file.get() == nullptr) { + reportError(tr("file not found: %1").arg(fileName)); + return; + } + + // set up preview dialog + PreviewDialog preview(fileName); + auto addFunc = [&](int originId) { + FilesOrigin &origin = m_OrganizerCore->directoryStructure()->getOriginByID(originId); + QString filePath = QDir::fromNativeSeparators(ToQString(origin.getPath())) + "/" + fileName; + if (QFile::exists(filePath)) { + // it's very possible the file doesn't exist, because it's inside an archive. we don't support that + QWidget *wid = m_PluginContainer->previewGenerator().genPreview(filePath); + if (wid == nullptr) { + reportError(tr("failed to generate preview for %1").arg(filePath)); + } + else { + preview.addVariant(ToQString(origin.getName()), wid); + } + } + }; + + addFunc(file->getOrigin()); + for (auto alt : file->getAlternatives()) { + addFunc(alt.first); + } + if (preview.numVariants() > 0) { + preview.exec(); + } + else { + QMessageBox::information(this, tr("Sorry"), tr("Sorry, can't preview anything. This function currently does not support extracting from bsas.")); + } +} + + void ModInfoDialog::on_overwriteTree_customContextMenuRequested(const QPoint &pos) { m_ConflictsContextItem = ui->overwriteTree->itemAt(pos.x(), pos.y()); @@ -1211,11 +1279,37 @@ void ModInfoDialog::on_overwriteTree_customContextMenuRequested(const QPoint &po } else { menu.addAction(tr("Hide"), this, SLOT(hideConflictFile())); } + + QString fileName = m_ConflictsContextItem->data(0, Qt::UserRole).toString(); + if (m_PluginContainer->previewGenerator().previewSupported(QFileInfo(fileName).suffix())) { + menu.addAction(tr("Preview"), this, SLOT(previewDataFile())); + } + menu.exec(ui->overwriteTree->mapToGlobal(pos)); } } } +void ModInfoDialog::on_overwrittenTree_customContextMenuRequested(const QPoint &pos) +{ + //For some reason the m_ConflictsContextItem does not pick up valid data from the overwrittenTree. + //TODO: find out what is going wrong. + /*m_ConflictsContextItem = ui->overwrittenTree->itemAt(pos.x(), pos.y()); + + if (m_ConflictsContextItem != nullptr) { + if (!m_ConflictsContextItem->data(1, Qt::UserRole + 2).toBool()) { + QMenu menu; + + QString fileName = m_ConflictsContextItem->data(0, Qt::UserRole).toString(); + if (m_PluginContainer->previewGenerator().previewSupported(QFileInfo(fileName).suffix())) { + menu.addAction(tr("Preview"), this, SLOT(previewDataFile())); + } + + menu.exec(ui->overwrittenTree->mapToGlobal(pos)); + } + }*/ +} + void ModInfoDialog::on_overwrittenTree_itemDoubleClicked(QTreeWidgetItem *item, int) { diff --git a/src/modinfodialog.h b/src/modinfodialog.h index e7c70762..ab878cf9 100644 --- a/src/modinfodialog.h +++ b/src/modinfodialog.h @@ -24,6 +24,7 @@ along with Mod Organizer. If not, see . #include "modinfo.h" #include "tutorabledialog.h" #include "plugincontainer.h" +#include "organizercore.h" #include #include @@ -77,7 +78,7 @@ public: * @param modInfo info structure about the mod to display * @param parent parend widget **/ - explicit ModInfoDialog(ModInfo::Ptr modInfo, const MOShared::DirectoryEntry *directory, bool unmanaged, QWidget *parent = 0); + explicit ModInfoDialog(ModInfo::Ptr modInfo, const MOShared::DirectoryEntry *directory, bool unmanaged, OrganizerCore *organizerCore, PluginContainer *pluginContainer,QWidget *parent = 0); ~ModInfoDialog(); /** @@ -156,6 +157,7 @@ private slots: void hideConflictFile(); void unhideConflictFile(); + void previewDataFile(); void thumbnailClicked(const QString &fileName); void linkClicked(const QUrl &url); @@ -186,6 +188,7 @@ private slots: void on_overwriteTree_itemDoubleClicked(QTreeWidgetItem *item, int column); void on_overwrittenTree_itemDoubleClicked(QTreeWidgetItem *item, int column); void on_overwriteTree_customContextMenuRequested(const QPoint &pos); + void on_overwrittenTree_customContextMenuRequested(const QPoint &pos); void on_fileTree_customContextMenuRequested(const QPoint &pos); void on_refreshButton_clicked(); @@ -209,6 +212,9 @@ private: QSignalMapper m_ThumbnailMapper; QString m_RootPath; + OrganizerCore *m_OrganizerCore; + PluginContainer *m_PluginContainer; + QFileSystemModel *m_FileSystemModel; QTreeView *m_FileTree; QModelIndexList m_FileSelection; diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui index b5331424..05415445 100644 --- a/src/modinfodialog.ui +++ b/src/modinfodialog.ui @@ -489,6 +489,9 @@ Most mods do not have optional esps, so chances are good you are looking at an e + + Qt::CustomContextMenu + Qt::ElideLeft @@ -498,6 +501,9 @@ Most mods do not have optional esps, so chances are good you are looking at an e true + + 2 + 365 -- cgit v1.3.1