Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
qCWarning(logLibFilePreview) << "FilePreviewFactory: null preview instance provided for key compatibility check:" << key;
return false;
}

int index = FilePreviewFactory::previewToLoaderIndex.value(view, -1);

if (index == -1) {
Expand All @@ -80,3 +80,15 @@
qCDebug(logLibFilePreview) << "FilePreviewFactory: preview compatibility check for key:" << key << "result:" << suited;
return suited;
}

bool FilePreviewFactory::hasPluginForKey(const QString &key)

Check warning on line 84 in src/apps/dde-file-manager-preview/libdfm-preview/pluginInterface/filepreviewfactory.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'hasPluginForKey' is never used.

Check warning on line 84 in src/apps/dde-file-manager-preview/libdfm-preview/pluginInterface/filepreviewfactory.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

The function 'hasPluginForKey' is never used.
{
#ifndef QT_NO_LIBRARY
int index = loader()->indexOf(key);
bool exists = (index != -1);
qCDebug(logLibFilePreview) << "FilePreviewFactory: plugin existence check for key:" << key << "result:" << exists;
return exists;
#else
return false;
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class FilePreviewFactory
static QStringList keys();
static DFMBASE_NAMESPACE::AbstractBasePreview *create(const QString &key);
static bool isSuitedWithKey(const DFMBASE_NAMESPACE::AbstractBasePreview *view, const QString &key);
static bool hasPluginForKey(const QString &key);

static QMap<const DFMBASE_NAMESPACE::AbstractBasePreview *, int> previewToLoaderIndex;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,22 @@ void FilePreviewDialog::switchToPage(int index)
for (const QString &key : keyList) {
const QString &gKey = generalKey(key);

if (preview && (FilePreviewFactory::isSuitedWithKey(preview, key) || FilePreviewFactory::isSuitedWithKey(preview, gKey)) && !FileUtils::isDesktopFile(fileList.at(index))) {
// Check if we can reuse existing preview, prioritize exact key match over general key
bool canReusePreview = false;
if (preview && !FileUtils::isDesktopFile(fileList.at(index))) {
// First check exact key match
if (FilePreviewFactory::isSuitedWithKey(preview, key)) {
canReusePreview = true;
} else if (gKey != key) {
// Only use general key if no exact key plugin exists
// This prevents text/* from intercepting text/markdown when markdown-preview exists
if (!FilePreviewFactory::hasPluginForKey(key)) {
canReusePreview = FilePreviewFactory::isSuitedWithKey(preview, gKey);
}
}
}

if (canReusePreview) {
qCDebug(logLibFilePreview) << "FilePreviewDialog: reusing existing preview for key:" << key;
if (preview->setFileUrl(fileList.at(index))) {
preview->contentWidget()->updateGeometry();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(image-preview)
add_subdirectory(music-preview)
add_subdirectory(text-preview)
add_subdirectory(markdown-preview)
add_subdirectory(dciicon-preview)
add_subdirectory(pdf-preview)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.10)
project(dde-markdown-preview-plugin)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

FILE(GLOB_RECURSE MARKDOWNPREVIEW_FILES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/*.json"
"${GlobalFiles}"
)

set(BIN_NAME ${PROJECT_NAME})

find_package(Qt6 COMPONENTS Core REQUIRED)

add_library(${BIN_NAME}
SHARED
${MARKDOWNPREVIEW_FILES}
)

set_target_properties(${BIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${DFM_BUILD_PLUGIN_PREVIEW_DIR}/previews)

target_link_libraries(${BIN_NAME}
DFM6::base
DFM6::framework
)

#install library file
install(TARGETS
${BIN_NAME}
LIBRARY
DESTINATION
${DFM_PLUGIN_PREVIEW_DIR}
)

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/dde-markdown-preview-plugin.json DESTINATION ${DFM_BUILD_PLUGIN_PREVIEW_DIR}/previews)

install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dde-markdown-preview-plugin.json DESTINATION ${DFM_PLUGIN_PREVIEW_DIR})
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Keys" : ["text/markdown"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "markdownbrowser.h"

#include <QTextDocument>

Check warning on line 7 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QTextDocument> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 7 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QTextDocument> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDebug>

Check warning on line 8 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDebug> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 8 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QDebug> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDir>

Check warning on line 9 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDir> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 9 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QDir> not found. Please note: Cppcheck does not need standard library headers to get proper results.

using namespace plugin_filepreview;

MarkdownBrowser::MarkdownBrowser(QWidget *parent)
: QTextBrowser(parent)
{
setReadOnly(true);
setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard | Qt::LinksAccessibleByMouse);
setOpenExternalLinks(true);
setLineWrapMode(QTextBrowser::WidgetWidth);
setFixedSize(800, 500);
setFrameStyle(QFrame::NoFrame);
}

MarkdownBrowser::~MarkdownBrowser()
{
}

void MarkdownBrowser::setMarkdownContent(const QString &markdown, const QString &basePath)
{
fmDebug() << "Markdown preview: setting markdown content, base path:" << basePath;

// Set base path for resolving relative image paths
if (!basePath.isEmpty()) {
QDir baseDir(basePath);
if (baseDir.exists()) {
document()->setMetaInformation(QTextDocument::DocumentUrl, QUrl::fromLocalFile(basePath).toString());
setSearchPaths(QStringList() << basePath);
fmDebug() << "Markdown preview: search paths set to:" << basePath;
} else {
fmWarning() << "Markdown preview: base path does not exist:" << basePath;
}
}

// Set markdown content using QTextDocument
document()->setMarkdown(markdown);

// Move cursor to the start of the document to ensure top of content is visible
moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);

fmInfo() << "Markdown preview: content set successfully";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef MARKDOWNBROWSER_H
#define MARKDOWNBROWSER_H
#include "preview_plugin_global.h"

Check warning on line 7 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "preview_plugin_global.h" not found.

Check warning on line 7 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.h

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: "preview_plugin_global.h" not found.

#include <QTextBrowser>

Check warning on line 9 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QTextBrowser> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 9 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownbrowser.h

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QTextBrowser> not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace plugin_filepreview {
class MarkdownBrowser : public QTextBrowser
{
Q_OBJECT
public:
explicit MarkdownBrowser(QWidget *parent = nullptr);

virtual ~MarkdownBrowser() override;

void setMarkdownContent(const QString &markdown, const QString &basePath);
};
}
#endif // MARKDOWNBROWSER_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "markdowncontextwidget.h"
#include "markdownbrowser.h"

#include <DPlainTextEdit>

Check warning on line 8 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdowncontextwidget.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DPlainTextEdit> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 8 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdowncontextwidget.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <DPlainTextEdit> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <QVBoxLayout>

Check warning on line 10 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdowncontextwidget.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QVBoxLayout> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 10 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdowncontextwidget.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QVBoxLayout> not found. Please note: Cppcheck does not need standard library headers to get proper results.

using namespace plugin_filepreview;
DWIDGET_USE_NAMESPACE

MarkdownContextWidget::MarkdownContextWidget(QWidget *parent)
: QWidget(parent)
, m_browserWidget(new MarkdownBrowser(this))
{
DPlainTextEdit *titleWidget = new DPlainTextEdit(this);
titleWidget->setFixedHeight(30);
titleWidget->setFrameStyle(QFrame::NoFrame);
titleWidget->setReadOnly(true);
titleWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

QVBoxLayout *mainLay = new QVBoxLayout(this);
mainLay->addWidget(titleWidget);
mainLay->addWidget(m_browserWidget);
mainLay->setContentsMargins(0, 0, 0, 0);
mainLay->setSpacing(0);
}

MarkdownBrowser *MarkdownContextWidget::markdownBrowser() const
{
return m_browserWidget;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef MARKDOWNCONTEXTWIDGET_H
#define MARKDOWNCONTEXTWIDGET_H

#include <QWidget>

Check warning on line 8 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdowncontextwidget.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QWidget> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 8 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdowncontextwidget.h

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QWidget> not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace plugin_filepreview {
class MarkdownBrowser;
class MarkdownContextWidget : public QWidget
{
Q_OBJECT
public:
explicit MarkdownContextWidget(QWidget *parent = nullptr);
plugin_filepreview::MarkdownBrowser *markdownBrowser() const;

private:
plugin_filepreview::MarkdownBrowser *m_browserWidget { nullptr };
};
}
#endif // MARKDOWNCONTEXTWIDGET_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "markdownpreview.h"
#include "markdownbrowser.h"
#include "markdowncontextwidget.h"

#include <dfm-base/interfaces/fileinfo.h>

Check warning on line 9 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownpreview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <dfm-base/interfaces/fileinfo.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 9 in src/apps/dde-file-manager-preview/pluginpreviews/markdown-preview/markdownpreview.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <dfm-base/interfaces/fileinfo.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <QFile>
#include <QFileInfo>
#include <QTextStream>
#include <QDebug>

using namespace plugin_filepreview;
DFMBASE_USE_NAMESPACE

// 5MB maximum file size
static constexpr qint64 kMaxReadSize { 1024 * 1024 * 5 };

MarkdownPreview::MarkdownPreview(QObject *parent)
: AbstractBasePreview(parent)
{
fmInfo() << "Markdown preview: MarkdownPreview instance created";
}

MarkdownPreview::~MarkdownPreview()
{
fmInfo() << "Markdown preview: MarkdownPreview instance destroyed";
if (m_markdownBrowser) {
// Set parent to nullptr first to prevent recursive destruction issues
m_markdownBrowser->setParent(nullptr);
m_markdownBrowser->deleteLater();
m_markdownBrowser = nullptr;
}
}

bool MarkdownPreview::setFileUrl(const QUrl &url)
{
fmInfo() << "Markdown preview: setting file URL:" << url;

if (m_selectUrl == url) {
fmDebug() << "Markdown preview: URL unchanged, skipping:" << url;
return true;
}

if (!url.isLocalFile()) {
fmWarning() << "Markdown preview: URL is not a local file:" << url;
return false;
}

const QString filePath = url.toLocalFile();
if (!QFileInfo::exists(filePath)) {
fmWarning() << "Markdown preview: file does not exist:" << filePath;
return false;
}

QFileInfo fileInfo(filePath);
qint64 fileSize = fileInfo.size();

if (fileSize <= 0) {
fmWarning() << "Markdown preview: file is empty or cannot determine size:" << filePath;
return false;
}

fmDebug() << "Markdown preview: file size:" << fileSize << "bytes, will read up to:" << kMaxReadSize << "bytes";

QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
fmWarning() << "Markdown preview: failed to open file:" << filePath << "error:" << file.errorString();
return false;
}

// Limit read size to 5MB
qint64 readSize = qMin(fileSize, kMaxReadSize);
if (fileSize > kMaxReadSize) {
fmDebug() << "Markdown preview: file size exceeds limit, truncating to:" << kMaxReadSize << "bytes";
}

// Read file content
QByteArray data = file.read(readSize);
file.close();

if (data.isEmpty()) {
fmWarning() << "Markdown preview: failed to read file content:" << filePath;
return false;
}

// Convert to QString
const QString markdownContent = QString::fromUtf8(data);

// Create browser widget if not exists
if (!m_markdownBrowser) {
fmDebug() << "Markdown preview: creating new MarkdownContextWidget";
m_markdownBrowser = new MarkdownContextWidget;
}

// Set markdown content with base path for relative images
QString basePath = fileInfo.absolutePath();
m_markdownBrowser->markdownBrowser()->setMarkdownContent(markdownContent, basePath);

m_selectUrl = url;
m_titleStr = fileInfo.fileName();

fmInfo() << "Markdown preview: file loaded successfully:" << filePath << "title:" << m_titleStr;
Q_EMIT titleChanged();

return true;
}

QUrl MarkdownPreview::fileUrl() const
{
return m_selectUrl;
}

QWidget *MarkdownPreview::contentWidget() const
{
return m_markdownBrowser;
}

QString MarkdownPreview::title() const
{
return m_titleStr;
}

bool MarkdownPreview::showStatusBarSeparator() const
{
return false;
}
Loading
Loading