mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
219 lines
7.9 KiB
C++
219 lines
7.9 KiB
C++
#include "contentmediautils.h"
|
|
|
|
#include <QDebug>
|
|
#include <QSet>
|
|
#include <QFileInfo>
|
|
#include <QDir>
|
|
#include <QHash>
|
|
|
|
#include <notebookbackend/inotebookbackend.h>
|
|
#include <notebook/node.h>
|
|
|
|
#include <buffer/filetypehelper.h>
|
|
|
|
#include <vtextedit/markdownutils.h>
|
|
#include <vtextedit/textutils.h>
|
|
|
|
#include <utils/pathutils.h>
|
|
#include <utils/fileutils.h>
|
|
#include <core/file.h>
|
|
#include <core/exception.h>
|
|
|
|
using namespace vnotex;
|
|
|
|
void ContentMediaUtils::copyMediaFiles(Node *p_node,
|
|
INotebookBackend *p_backend,
|
|
const QString &p_destFilePath)
|
|
{
|
|
Q_ASSERT(p_node->hasContent());
|
|
auto file = p_node->getContentFile();
|
|
if (file->getContentType().isMarkdown()) {
|
|
copyMarkdownMediaFiles(file->read(),
|
|
PathUtils::parentDirPath(file->getContentPath()),
|
|
p_backend,
|
|
p_destFilePath);
|
|
}
|
|
}
|
|
|
|
void ContentMediaUtils::copyMediaFiles(const QString &p_filePath,
|
|
INotebookBackend *p_backend,
|
|
const QString &p_destFilePath)
|
|
{
|
|
const auto &fileType = FileTypeHelper::getInst().getFileType(p_filePath);
|
|
if (fileType.isMarkdown()) {
|
|
copyMarkdownMediaFiles(FileUtils::readTextFile(p_filePath),
|
|
PathUtils::parentDirPath(p_filePath),
|
|
p_backend,
|
|
p_destFilePath);
|
|
}
|
|
}
|
|
|
|
void ContentMediaUtils::copyMediaFiles(const File *p_file,
|
|
const QString &p_destFilePath)
|
|
{
|
|
if (p_file->getContentType().isMarkdown()) {
|
|
copyMarkdownMediaFiles(p_file->read(),
|
|
p_file->getResourcePath(),
|
|
nullptr,
|
|
p_destFilePath);
|
|
}
|
|
}
|
|
|
|
void ContentMediaUtils::copyMarkdownMediaFiles(const QString &p_content,
|
|
const QString &p_basePath,
|
|
INotebookBackend *p_backend,
|
|
const QString &p_destFilePath)
|
|
{
|
|
auto content = p_content;
|
|
|
|
// Images.
|
|
const auto images =
|
|
vte::MarkdownUtils::fetchImagesFromMarkdownText(content,
|
|
p_basePath,
|
|
vte::MarkdownLink::TypeFlag::LocalRelativeInternal);
|
|
|
|
QDir destDir(PathUtils::parentDirPath(p_destFilePath));
|
|
QSet<QString> handledImages;
|
|
QHash<QString, QString> renamedImages;
|
|
int lastPos = content.size();
|
|
for (const auto &link : images) {
|
|
Q_ASSERT(link.m_urlInLinkPos < lastPos);
|
|
lastPos = link.m_urlInLinkPos;
|
|
|
|
qDebug() << "link" << link.m_path << link.m_urlInLink;
|
|
|
|
if (handledImages.contains(link.m_path)) {
|
|
auto it = renamedImages.find(link.m_path);
|
|
if (it != renamedImages.end()) {
|
|
content.replace(link.m_urlInLinkPos, link.m_urlInLink.size(), it.value());
|
|
}
|
|
continue;
|
|
}
|
|
|
|
handledImages.insert(link.m_path);
|
|
|
|
if (!QFileInfo::exists(link.m_path)) {
|
|
qWarning() << "image of Markdown file does not exist" << link.m_path << link.m_urlInLink;
|
|
continue;
|
|
}
|
|
|
|
// Get the relative path of the image and apply it to the dest file path.
|
|
const auto decodedUrlInLink = vte::TextUtils::decodeUrl(link.m_urlInLink);
|
|
const auto oldDestFilePath = destDir.filePath(decodedUrlInLink);
|
|
destDir.mkpath(PathUtils::parentDirPath(oldDestFilePath));
|
|
auto destFilePath = p_backend ? p_backend->renameIfExistsCaseInsensitive(oldDestFilePath)
|
|
: FileUtils::renameIfExistsCaseInsensitive(oldDestFilePath);
|
|
if (oldDestFilePath != destFilePath) {
|
|
// Rename happens.
|
|
const auto oldFileName = PathUtils::fileName(oldDestFilePath);
|
|
const auto newFileName = PathUtils::fileName(destFilePath);
|
|
qWarning() << QString("image name conflicts when copy, renamed from (%1) to (%2)").arg(oldFileName, newFileName);
|
|
|
|
// Update the text content.
|
|
const auto encodedOldFileName = PathUtils::fileName(link.m_urlInLink);
|
|
const auto encodedNewFileName = vte::TextUtils::encodeUrl(newFileName);
|
|
auto newUrlInLink(link.m_urlInLink);
|
|
newUrlInLink.replace(newUrlInLink.size() - encodedOldFileName.size(),
|
|
encodedOldFileName.size(),
|
|
encodedNewFileName);
|
|
|
|
content.replace(link.m_urlInLinkPos, link.m_urlInLink.size(), newUrlInLink);
|
|
renamedImages.insert(link.m_path, newUrlInLink);
|
|
}
|
|
|
|
if (p_backend) {
|
|
p_backend->copyFile(link.m_path, destFilePath);
|
|
} else {
|
|
FileUtils::copyFile(link.m_path, destFilePath);
|
|
}
|
|
}
|
|
|
|
if (!renamedImages.isEmpty()) {
|
|
if (p_backend) {
|
|
p_backend->writeFile(p_destFilePath, content);
|
|
} else {
|
|
FileUtils::writeFile(p_destFilePath, content);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ContentMediaUtils::removeMediaFiles(Node *p_node)
|
|
{
|
|
Q_ASSERT(p_node->hasContent());
|
|
auto file = p_node->getContentFile();
|
|
if (file->getContentType().isMarkdown()) {
|
|
removeMarkdownMediaFiles(file.data(), p_node->getBackend());
|
|
}
|
|
}
|
|
|
|
void ContentMediaUtils::removeMarkdownMediaFiles(const File *p_file, INotebookBackend *p_backend)
|
|
{
|
|
auto content = p_file->read();
|
|
|
|
// Images.
|
|
const auto images =
|
|
vte::MarkdownUtils::fetchImagesFromMarkdownText(content,
|
|
p_file->getResourcePath(),
|
|
vte::MarkdownLink::TypeFlag::LocalRelativeInternal);
|
|
|
|
QSet<QString> handledImages;
|
|
for (const auto &link : images) {
|
|
if (handledImages.contains(link.m_path)) {
|
|
continue;
|
|
}
|
|
|
|
handledImages.insert(link.m_path);
|
|
|
|
if (!QFileInfo::exists(link.m_path)) {
|
|
qWarning() << "image of Markdown file does not exist" << link.m_path << link.m_urlInLink;
|
|
continue;
|
|
}
|
|
p_backend->removeFile(link.m_path);
|
|
}
|
|
}
|
|
|
|
void ContentMediaUtils::copyAttachment(Node *p_node,
|
|
INotebookBackend *p_backend,
|
|
const QString &p_destFilePath,
|
|
const QString &p_destAttachmentFolderPath)
|
|
{
|
|
Q_ASSERT(p_node->hasContent());
|
|
Q_ASSERT(!p_node->getAttachmentFolder().isEmpty());
|
|
|
|
// Copy the whole folder.
|
|
const auto srcAttachmentFolderPath = p_node->fetchAttachmentFolderPath();
|
|
try {
|
|
if (p_backend) {
|
|
p_backend->copyDir(srcAttachmentFolderPath, p_destAttachmentFolderPath);
|
|
} else {
|
|
FileUtils::copyDir(srcAttachmentFolderPath, p_destAttachmentFolderPath);
|
|
}
|
|
} catch (Exception &e) {
|
|
qWarning() << "failed to copy attachment folder" << srcAttachmentFolderPath << e.what();
|
|
return;
|
|
}
|
|
|
|
// Check if we need to modify links in content.
|
|
// FIXME: check the whole relative path.
|
|
if (p_node->getAttachmentFolder() == PathUtils::dirName(p_destAttachmentFolderPath)) {
|
|
return;
|
|
}
|
|
|
|
auto file = p_node->getContentFile();
|
|
if (file->getContentType().isMarkdown()) {
|
|
fixMarkdownLinks(srcAttachmentFolderPath, p_backend, p_destFilePath, p_destAttachmentFolderPath);
|
|
}
|
|
}
|
|
|
|
void ContentMediaUtils::fixMarkdownLinks(const QString &p_srcFolderPath,
|
|
INotebookBackend *p_backend,
|
|
const QString &p_destFilePath,
|
|
const QString &p_destFolderPath)
|
|
{
|
|
// TODO.
|
|
Q_UNUSED(p_srcFolderPath);
|
|
Q_UNUSED(p_backend);
|
|
Q_UNUSED(p_destFilePath);
|
|
Q_UNUSED(p_destFolderPath);
|
|
}
|