* Draft: feature/pdf_view (#2268)

* build base code

* simple run successful

* add save session

* add pdfjs resource

* simple pdf viewer

Co-authored-by: chendapao <feloxx@163.com>
This commit is contained in:
Le Tan 2022-12-17 18:52:37 +08:00 committed by GitHub
parent 7f27745303
commit 7f2cfe4f52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
63 changed files with 10326 additions and 224 deletions

View File

@ -6,8 +6,11 @@ SOURCES += \
$$PWD/markdownbufferfactory.cpp \ $$PWD/markdownbufferfactory.cpp \
$$PWD/filetypehelper.cpp \ $$PWD/filetypehelper.cpp \
$$PWD/nodebufferprovider.cpp \ $$PWD/nodebufferprovider.cpp \
$$PWD/pdfbuffer.cpp \
$$PWD/pdfbufferfactory.cpp \
$$PWD/textbuffer.cpp \ $$PWD/textbuffer.cpp \
$$PWD/textbufferfactory.cpp $$PWD/textbufferfactory.cpp \
$$PWD/urlbasedbufferprovider.cpp
HEADERS += \ HEADERS += \
$$PWD/bufferprovider.h \ $$PWD/bufferprovider.h \
@ -18,5 +21,8 @@ HEADERS += \
$$PWD/markdownbufferfactory.h \ $$PWD/markdownbufferfactory.h \
$$PWD/filetypehelper.h \ $$PWD/filetypehelper.h \
$$PWD/nodebufferprovider.h \ $$PWD/nodebufferprovider.h \
$$PWD/pdfbuffer.h \
$$PWD/pdfbufferfactory.h \
$$PWD/textbuffer.h \ $$PWD/textbuffer.h \
$$PWD/textbufferfactory.h $$PWD/textbufferfactory.h \
$$PWD/urlbasedbufferprovider.h

View File

@ -16,6 +16,7 @@ QDateTime BufferProvider::getLastModifiedFromFile() const
bool BufferProvider::checkFileChangedOutside() const bool BufferProvider::checkFileChangedOutside() const
{ {
// TODO: support non-local URLs.
QFileInfo info(getContentPath()); QFileInfo info(getContentPath());
if (!info.exists() || m_lastModified != info.lastModified()) { if (!info.exists() || m_lastModified != info.lastModified()) {
return true; return true;

View File

@ -75,6 +75,22 @@ void FileTypeHelper::setupBuiltInTypes()
m_fileTypes.push_back(type); m_fileTypes.push_back(type);
} }
{
FileType type;
type.m_type = FileType::Pdf;
type.m_typeName = QStringLiteral("PDF");
type.m_displayName = Buffer::tr("Portable Document Format");
auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName);
if (suffixes && !suffixes->isEmpty()) {
type.m_suffixes = *suffixes;
} else {
type.m_suffixes << QStringLiteral("pdf");
}
m_fileTypes.push_back(type);
}
{ {
FileType type; FileType type;
type.m_type = FileType::Others; type.m_type = FileType::Others;

View File

@ -15,6 +15,7 @@ namespace vnotex
{ {
Markdown = 0, Markdown = 0,
Text, Text,
Pdf,
Others Others
}; };

View File

@ -0,0 +1,17 @@
#include "pdfbuffer.h"
#include <widgets/pdfviewwindow.h>
using namespace vnotex;
PdfBuffer::PdfBuffer(const BufferParameters &p_parameters,
QObject *p_parent)
: Buffer(p_parameters, p_parent)
{
}
ViewWindow *PdfBuffer::createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent)
{
Q_UNUSED(p_paras);
return new PdfViewWindow(p_parent);
}

View File

@ -0,0 +1,22 @@
#ifndef PDFBUFFER_H
#define PDFBUFFER_H
#include "buffer.h"
namespace vnotex
{
class PdfBuffer : public Buffer
{
Q_OBJECT
public:
PdfBuffer(const BufferParameters &p_parameters,
QObject *p_parent = nullptr);
protected:
ViewWindow *createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras,
QWidget *p_parent) Q_DECL_OVERRIDE;
};
} // ns vnotex
#endif // PDFBUFFER_H

View File

@ -0,0 +1,19 @@
#include "pdfbufferfactory.h"
#include "pdfbuffer.h"
#include "urlbasedbufferprovider.h"
using namespace vnotex;
Buffer *PdfBufferFactory::createBuffer(const BufferParameters &p_parameters,
QObject *p_parent)
{
BufferParameters paras;
paras.m_provider = QSharedPointer<UrlBasedBufferProvider>::create(p_parameters.m_provider);
return new PdfBuffer(paras, p_parent);
}
bool PdfBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const
{
return dynamic_cast<const PdfBuffer *>(p_buffer) != nullptr;
}

View File

@ -0,0 +1,19 @@
#ifndef PDFBUFFERFACTORY_H
#define PDFBUFFERFACTORY_H
#include "ibufferfactory.h"
namespace vnotex
{
// Buffer factory for Pdf file.
class PdfBufferFactory : public IBufferFactory
{
public:
Buffer *createBuffer(const BufferParameters &p_parameters,
QObject *p_parent) Q_DECL_OVERRIDE;
bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE;
};
} // vnotex
#endif // PDFBUFFERFACTORY_H

View File

@ -0,0 +1,3 @@
#include "urlbasedbufferprovider.h"
using namespace vnotex;

View File

@ -0,0 +1,132 @@
#ifndef URLBASEDBUFFERPROVIDER_H
#define URLBASEDBUFFERPROVIDER_H
#include "bufferprovider.h"
#include <QSharedPointer>
namespace vnotex
{
// A wrapper provider to provide URL-based buffer (instead of content-based).
class UrlBasedBufferProvider : public BufferProvider
{
Q_OBJECT
public:
// Will own @p_provider.
UrlBasedBufferProvider(const QSharedPointer<BufferProvider> &p_provider, QObject *p_parent = nullptr)
: BufferProvider(p_parent),
m_provider(p_provider)
{
}
Buffer::ProviderType getType() const Q_DECL_OVERRIDE {
return m_provider->getType();
}
bool match(const Node *p_node) const Q_DECL_OVERRIDE {
return m_provider->match(p_node);
}
bool match(const QString &p_filePath) const Q_DECL_OVERRIDE {
return m_provider->match(p_filePath);
}
QString getName() const Q_DECL_OVERRIDE {
return m_provider->getName();
}
QString getPath() const Q_DECL_OVERRIDE {
return m_provider->getPath();
}
QString getContentPath() const Q_DECL_OVERRIDE {
return m_provider->getContentPath();
}
QString getResourcePath() const Q_DECL_OVERRIDE {
return m_provider->getResourcePath();
}
void write(const QString &p_content) Q_DECL_OVERRIDE {
Q_UNUSED(p_content);
}
QString read() const Q_DECL_OVERRIDE {
const_cast<UrlBasedBufferProvider *>(this)->m_lastModified = getLastModifiedFromFile();
return QString();
}
QString fetchImageFolderPath() Q_DECL_OVERRIDE {
return m_provider->fetchImageFolderPath();
}
bool isChildOf(const Node *p_node) const Q_DECL_OVERRIDE {
return m_provider->isChildOf(p_node);
}
Node *getNode() const Q_DECL_OVERRIDE {
return m_provider->getNode();
}
QString getAttachmentFolder() const Q_DECL_OVERRIDE {
return m_provider->getAttachmentFolder();
}
QString fetchAttachmentFolderPath() Q_DECL_OVERRIDE {
return m_provider->fetchAttachmentFolderPath();
}
QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) Q_DECL_OVERRIDE {
return m_provider->addAttachment(p_destFolderPath, p_files);
}
QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE {
return m_provider->newAttachmentFile(p_destFolderPath, p_name);
}
QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE {
return m_provider->newAttachmentFolder(p_destFolderPath, p_name);
}
QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE {
return m_provider->renameAttachment(p_path, p_name);
}
void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE {
m_provider->removeAttachment(p_paths);
}
QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE {
return m_provider->insertImage(p_srcImagePath, p_imageFileName);
}
QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE {
return m_provider->insertImage(p_image, p_imageFileName);
}
void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE {
m_provider->removeImage(p_imagePath);
}
bool isAttachmentSupported() const Q_DECL_OVERRIDE {
return m_provider->isAttachmentSupported();
}
bool isTagSupported() const Q_DECL_OVERRIDE {
return m_provider->isTagSupported();
}
bool isReadOnly() const Q_DECL_OVERRIDE {
return true;
}
QSharedPointer<File> getFile() const Q_DECL_OVERRIDE {
return m_provider->getFile();
}
private:
QSharedPointer<BufferProvider> m_provider;
};
}
#endif // URLBASEDBUFFERPROVIDER_H

View File

@ -7,6 +7,7 @@
#include <buffer/filetypehelper.h> #include <buffer/filetypehelper.h>
#include <buffer/markdownbufferfactory.h> #include <buffer/markdownbufferfactory.h>
#include <buffer/textbufferfactory.h> #include <buffer/textbufferfactory.h>
#include <buffer/pdfbufferfactory.h>
#include <buffer/buffer.h> #include <buffer/buffer.h>
#include <buffer/nodebufferprovider.h> #include <buffer/nodebufferprovider.h>
#include <buffer/filebufferprovider.h> #include <buffer/filebufferprovider.h>
@ -52,6 +53,10 @@ void BufferMgr::initBufferServer()
// Text. // Text.
auto textFactory = QSharedPointer<TextBufferFactory>::create(); auto textFactory = QSharedPointer<TextBufferFactory>::create();
m_bufferServer->registerItem(helper.getFileType(FileType::Text).m_typeName, textFactory); m_bufferServer->registerItem(helper.getFileType(FileType::Text).m_typeName, textFactory);
// Pdf.
auto pdfFactory = QSharedPointer<PdfBufferFactory>::create();
m_bufferServer->registerItem(helper.getFileType(FileType::Pdf).m_typeName, pdfFactory);
} }
void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_paras) void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_paras)

View File

@ -25,7 +25,7 @@
using namespace vnotex; using namespace vnotex;
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG
// #define VX_DEBUG_WEB #define VX_DEBUG_WEB
#endif #endif
const QString ConfigMgr::c_orgName = "VNote"; const QString ConfigMgr::c_orgName = "VNote";

View File

@ -24,6 +24,7 @@ SOURCES += \
$$PWD/logger.cpp \ $$PWD/logger.cpp \
$$PWD/mainconfig.cpp \ $$PWD/mainconfig.cpp \
$$PWD/markdowneditorconfig.cpp \ $$PWD/markdowneditorconfig.cpp \
$$PWD/pdfviewerconfig.cpp \
$$PWD/quickaccesshelper.cpp \ $$PWD/quickaccesshelper.cpp \
$$PWD/singleinstanceguard.cpp \ $$PWD/singleinstanceguard.cpp \
$$PWD/templatemgr.cpp \ $$PWD/templatemgr.cpp \
@ -54,6 +55,7 @@ HEADERS += \
$$PWD/mainconfig.h \ $$PWD/mainconfig.h \
$$PWD/markdowneditorconfig.h \ $$PWD/markdowneditorconfig.h \
$$PWD/noncopyable.h \ $$PWD/noncopyable.h \
$$PWD/pdfviewerconfig.h \
$$PWD/quickaccesshelper.h \ $$PWD/quickaccesshelper.h \
$$PWD/singleinstanceguard.h \ $$PWD/singleinstanceguard.h \
$$PWD/iconfig.h \ $$PWD/iconfig.h \

View File

@ -5,6 +5,7 @@
#include "texteditorconfig.h" #include "texteditorconfig.h"
#include "markdowneditorconfig.h" #include "markdowneditorconfig.h"
#include "pdfviewerconfig.h"
#include <vtextedit/viconfig.h> #include <vtextedit/viconfig.h>
@ -41,7 +42,8 @@ QJsonObject EditorConfig::ImageHostItem::toJson() const
EditorConfig::EditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig) EditorConfig::EditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig)
: IConfig(p_mgr, p_topConfig), : IConfig(p_mgr, p_topConfig),
m_textEditorConfig(new TextEditorConfig(p_mgr, p_topConfig)), m_textEditorConfig(new TextEditorConfig(p_mgr, p_topConfig)),
m_markdownEditorConfig(new MarkdownEditorConfig(p_mgr, p_topConfig, m_textEditorConfig)) m_markdownEditorConfig(new MarkdownEditorConfig(p_mgr, p_topConfig, m_textEditorConfig)),
m_pdfViewerConfig(new PdfViewerConfig(p_mgr, p_topConfig))
{ {
m_sessionName = QStringLiteral("editor"); m_sessionName = QStringLiteral("editor");
} }
@ -65,6 +67,7 @@ void EditorConfig::init(const QJsonObject &p_app,
m_textEditorConfig->init(appObj, userObj); m_textEditorConfig->init(appObj, userObj);
m_markdownEditorConfig->init(appObj, userObj); m_markdownEditorConfig->init(appObj, userObj);
m_pdfViewerConfig->init(appObj, userObj);
} }
void EditorConfig::loadCore(const QJsonObject &p_app, const QJsonObject &p_user) void EditorConfig::loadCore(const QJsonObject &p_app, const QJsonObject &p_user)
@ -148,6 +151,7 @@ QJsonObject EditorConfig::toJson() const
QJsonObject obj; QJsonObject obj;
obj[m_textEditorConfig->getSessionName()] = m_textEditorConfig->toJson(); obj[m_textEditorConfig->getSessionName()] = m_textEditorConfig->toJson();
obj[m_markdownEditorConfig->getSessionName()] = m_markdownEditorConfig->toJson(); obj[m_markdownEditorConfig->getSessionName()] = m_markdownEditorConfig->toJson();
obj[m_pdfViewerConfig->getSessionName()] = m_pdfViewerConfig->toJson();
obj[QStringLiteral("core")] = saveCore(); obj[QStringLiteral("core")] = saveCore();
obj[QStringLiteral("image_host")] = saveImageHost(); obj[QStringLiteral("image_host")] = saveImageHost();
@ -178,6 +182,16 @@ const MarkdownEditorConfig &EditorConfig::getMarkdownEditorConfig() const
return *m_markdownEditorConfig; return *m_markdownEditorConfig;
} }
PdfViewerConfig &EditorConfig::getPdfViewerConfig()
{
return *m_pdfViewerConfig;
}
const PdfViewerConfig &EditorConfig::getPdfViewerConfig() const
{
return *m_pdfViewerConfig;
}
int EditorConfig::getToolBarIconSize() const int EditorConfig::getToolBarIconSize() const
{ {
return m_toolBarIconSize; return m_toolBarIconSize;

View File

@ -19,6 +19,7 @@ namespace vnotex
{ {
class TextEditorConfig; class TextEditorConfig;
class MarkdownEditorConfig; class MarkdownEditorConfig;
class PdfViewerConfig;
class EditorConfig : public IConfig class EditorConfig : public IConfig
{ {
@ -105,6 +106,9 @@ namespace vnotex
MarkdownEditorConfig &getMarkdownEditorConfig(); MarkdownEditorConfig &getMarkdownEditorConfig();
const MarkdownEditorConfig &getMarkdownEditorConfig() const; const MarkdownEditorConfig &getMarkdownEditorConfig() const;
PdfViewerConfig &getPdfViewerConfig();
const PdfViewerConfig &getPdfViewerConfig() const;
void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE; void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE;
QJsonObject toJson() const Q_DECL_OVERRIDE; QJsonObject toJson() const Q_DECL_OVERRIDE;
@ -176,6 +180,8 @@ namespace vnotex
QScopedPointer<MarkdownEditorConfig> m_markdownEditorConfig; QScopedPointer<MarkdownEditorConfig> m_markdownEditorConfig;
QScopedPointer<PdfViewerConfig> m_pdfViewerConfig;
bool m_spellCheckAutoDetectLanguageEnabled = false; bool m_spellCheckAutoDetectLanguageEnabled = false;
QString m_spellCheckDefaultDictionary; QString m_spellCheckDefaultDictionary;

View File

@ -3,6 +3,7 @@
#include <QDebug> #include <QDebug>
#include <core/markdowneditorconfig.h> #include <core/markdowneditorconfig.h>
#include <core/pdfviewerconfig.h>
#include <core/configmgr.h> #include <core/configmgr.h>
#include <utils/utils.h> #include <utils/utils.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
@ -16,7 +17,9 @@ using namespace vnotex;
HtmlTemplateHelper::Template HtmlTemplateHelper::s_markdownViewerTemplate; HtmlTemplateHelper::Template HtmlTemplateHelper::s_markdownViewerTemplate;
QString WebGlobalOptions::toJavascriptObject() const HtmlTemplateHelper::Template HtmlTemplateHelper::s_pdfViewerTemplate;
QString MarkdownWebGlobalOptions::toJavascriptObject() const
{ {
return QStringLiteral("window.vxOptions = {\n") return QStringLiteral("window.vxOptions = {\n")
+ QString("webPlantUml: %1,\n").arg(Utils::boolToString(m_webPlantUml)) + QString("webPlantUml: %1,\n").arg(Utils::boolToString(m_webPlantUml))
@ -101,7 +104,7 @@ static void fillThemeStyles(QString &p_template, const QString &p_webStyleSheetF
} }
} }
static void fillGlobalOptions(QString &p_template, const WebGlobalOptions &p_opts) static void fillGlobalOptions(QString &p_template, const MarkdownWebGlobalOptions &p_opts)
{ {
p_template.replace(QStringLiteral("/* VX_GLOBAL_OPTIONS_PLACEHOLDER */"), p_template.replace(QStringLiteral("/* VX_GLOBAL_OPTIONS_PLACEHOLDER */"),
p_opts.toJavascriptObject()); p_opts.toJavascriptObject());
@ -187,7 +190,7 @@ void HtmlTemplateHelper::updateMarkdownViewerTemplate(const MarkdownEditorConfig
s_markdownViewerTemplate.m_revision = p_config.revision(); s_markdownViewerTemplate.m_revision = p_config.revision();
Paras paras; MarkdownParas paras;
const auto &themeMgr = VNoteX::getInst().getThemeMgr(); const auto &themeMgr = VNoteX::getInst().getThemeMgr();
paras.m_webStyleSheetFile = themeMgr.getFile(Theme::File::WebStyleSheet); paras.m_webStyleSheetFile = themeMgr.getFile(Theme::File::WebStyleSheet);
paras.m_highlightStyleSheetFile = themeMgr.getFile(Theme::File::HighlightStyleSheet); paras.m_highlightStyleSheetFile = themeMgr.getFile(Theme::File::HighlightStyleSheet);
@ -195,7 +198,8 @@ void HtmlTemplateHelper::updateMarkdownViewerTemplate(const MarkdownEditorConfig
s_markdownViewerTemplate.m_template = generateMarkdownViewerTemplate(p_config, paras); s_markdownViewerTemplate.m_template = generateMarkdownViewerTemplate(p_config, paras);
} }
QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, const Paras &p_paras) QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config,
const MarkdownParas &p_paras)
{ {
const auto &viewerResource = p_config.getViewerResource(); const auto &viewerResource = p_config.getViewerResource();
const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template); const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template);
@ -212,7 +216,7 @@ QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorC
fillThemeStyles(htmlTemplate, p_paras.m_webStyleSheetFile, p_paras.m_highlightStyleSheetFile); fillThemeStyles(htmlTemplate, p_paras.m_webStyleSheetFile, p_paras.m_highlightStyleSheetFile);
{ {
WebGlobalOptions opts; MarkdownWebGlobalOptions opts;
opts.m_webPlantUml = p_config.getWebPlantUml(); opts.m_webPlantUml = p_config.getWebPlantUml();
opts.m_plantUmlWebService = p_config.getPlantUmlWebService(); opts.m_plantUmlWebService = p_config.getPlantUmlWebService();
opts.m_webGraphviz = p_config.getWebGraphviz(); opts.m_webGraphviz = p_config.getWebGraphviz();
@ -242,8 +246,8 @@ QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorC
return htmlTemplate; return htmlTemplate;
} }
QString HtmlTemplateHelper::generateExportTemplate(const MarkdownEditorConfig &p_config, QString HtmlTemplateHelper::generateMarkdownExportTemplate(const MarkdownEditorConfig &p_config,
bool p_addOutlinePanel) bool p_addOutlinePanel)
{ {
auto exportResource = p_config.getExportResource(); auto exportResource = p_config.getExportResource();
const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(exportResource.m_template); const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(exportResource.m_template);
@ -251,7 +255,7 @@ QString HtmlTemplateHelper::generateExportTemplate(const MarkdownEditorConfig &p
try { try {
htmlTemplate = FileUtils::readTextFile(templateFile); htmlTemplate = FileUtils::readTextFile(templateFile);
} catch (Exception &p_e) { } catch (Exception &p_e) {
qWarning() << "failed to read export HTML template" << templateFile << p_e.what(); qWarning() << "failed to read Markdown export HTML template" << templateFile << p_e.what();
return errorPage(); return errorPage();
} }
@ -322,3 +326,38 @@ QString HtmlTemplateHelper::errorPage()
return VNoteX::tr("Failed to load HTML template. Check the logs for details. " return VNoteX::tr("Failed to load HTML template. Check the logs for details. "
"Try deleting the user configuration file and the default configuration file."); "Try deleting the user configuration file and the default configuration file.");
} }
const QString &HtmlTemplateHelper::getPdfViewerTemplate()
{
return s_pdfViewerTemplate.m_template;
}
const QString &HtmlTemplateHelper::getPdfViewerTemplatePath()
{
return s_pdfViewerTemplate.m_templatePath;
}
void HtmlTemplateHelper::updatePdfViewerTemplate(const PdfViewerConfig &p_config, bool p_force)
{
if (!p_force && p_config.revision() == s_markdownViewerTemplate.m_revision) {
return;
}
s_pdfViewerTemplate.m_revision = p_config.revision();
generatePdfViewerTemplate(p_config, s_pdfViewerTemplate);
}
void HtmlTemplateHelper::generatePdfViewerTemplate(const PdfViewerConfig &p_config, Template& p_template)
{
const auto &viewerResource = p_config.getViewerResource();
p_template.m_templatePath = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template);
try {
p_template.m_template = FileUtils::readTextFile(p_template.m_templatePath);
} catch (Exception &p_e) {
qWarning() << "failed to read HTML template" << p_template.m_templatePath << p_e.what();
p_template.m_template = errorPage();
return;
}
fillResources(p_template.m_template, viewerResource);
}

View File

@ -6,10 +6,11 @@
namespace vnotex namespace vnotex
{ {
class MarkdownEditorConfig; class MarkdownEditorConfig;
class PdfViewerConfig;
struct WebResource; struct WebResource;
// Global options to be passed to Web side at the very beginning. // Global options to be passed to Web side at the very beginning for Markdown.
struct WebGlobalOptions struct MarkdownWebGlobalOptions
{ {
bool m_webPlantUml = true; bool m_webPlantUml = true;
@ -67,7 +68,7 @@ namespace vnotex
class HtmlTemplateHelper class HtmlTemplateHelper
{ {
public: public:
struct Paras struct MarkdownParas
{ {
QString m_webStyleSheetFile; QString m_webStyleSheetFile;
@ -90,14 +91,16 @@ namespace vnotex
HtmlTemplateHelper() = delete; HtmlTemplateHelper() = delete;
// For Markdown.
static const QString &getMarkdownViewerTemplate(); static const QString &getMarkdownViewerTemplate();
static void updateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, bool p_force = false); static void updateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, bool p_force = false);
static QString generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, const Paras &p_paras); static QString generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, const MarkdownParas &p_paras);
static QString generateExportTemplate(const MarkdownEditorConfig &p_config, static QString generateMarkdownExportTemplate(const MarkdownEditorConfig &p_config,
bool p_addOutlinePanel); bool p_addOutlinePanel);
// For common HTML content manipulation.
static void fillTitle(QString &p_template, const QString &p_title); static void fillTitle(QString &p_template, const QString &p_title);
static void fillStyleContent(QString &p_template, const QString &p_styles); static void fillStyleContent(QString &p_template, const QString &p_styles);
@ -110,17 +113,27 @@ namespace vnotex
static void fillOutlinePanel(QString &p_template, WebResource &p_exportResource, bool p_addOutlinePanel); static void fillOutlinePanel(QString &p_template, WebResource &p_exportResource, bool p_addOutlinePanel);
private: // For PdfViewer.
static QString errorPage(); static const QString &getPdfViewerTemplate();
static void updatePdfViewerTemplate(const PdfViewerConfig &p_config, bool p_force = false);
static const QString &getPdfViewerTemplatePath();
private:
struct Template struct Template
{ {
int m_revision = -1; int m_revision = -1;
QString m_template; QString m_template;
QString m_templatePath;
}; };
// Template for MarkdownViewer. static QString errorPage();
static void generatePdfViewerTemplate(const PdfViewerConfig &p_config, Template& p_template);
static Template s_markdownViewerTemplate; static Template s_markdownViewerTemplate;
static Template s_pdfViewerTemplate;
}; };
} }

View File

@ -0,0 +1,61 @@
#include "pdfviewerconfig.h"
#include "mainconfig.h"
#define READSTR(key) readString(appObj, userObj, (key))
#define READBOOL(key) readBool(appObj, userObj, (key))
#define READINT(key) readInt(appObj, userObj, (key))
using namespace vnotex;
PdfViewerConfig::PdfViewerConfig(ConfigMgr *p_mgr, IConfig *p_topConfig)
: IConfig(p_mgr, p_topConfig)
{
m_sessionName = QStringLiteral("pdf_viewer");
}
void PdfViewerConfig::init(const QJsonObject &p_app,
const QJsonObject &p_user)
{
const auto appObj = p_app.value(m_sessionName).toObject();
const auto userObj = p_user.value(m_sessionName).toObject();
loadViewerResource(appObj, userObj);
}
QJsonObject PdfViewerConfig::toJson() const
{
QJsonObject obj;
obj[QStringLiteral("viewer_resource")] = saveViewerResource();
return obj;
}
void PdfViewerConfig::loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user)
{
const QString name(QStringLiteral("viewer_resource"));
if (MainConfig::isVersionChanged()) {
bool needOverride = p_app[QStringLiteral("override_viewer_resource")].toBool();
if (needOverride) {
qInfo() << "override \"viewer_resource\" in user configuration due to version change";
m_viewerResource.init(p_app[name].toObject());
return;
}
}
if (p_user.contains(name)) {
m_viewerResource.init(p_user[name].toObject());
} else {
m_viewerResource.init(p_app[name].toObject());
}
}
QJsonObject PdfViewerConfig::saveViewerResource() const
{
return m_viewerResource.toJson();
}
const WebResource &PdfViewerConfig::getViewerResource() const
{
return m_viewerResource;
}

View File

@ -0,0 +1,31 @@
#ifndef PDFVIEWERCONFIG_H
#define PDFVIEWERCONFIG_H
#include "iconfig.h"
#include "webresource.h"
namespace vnotex
{
class PdfViewerConfig : public IConfig
{
public:
PdfViewerConfig(ConfigMgr *p_mgr, IConfig *p_topConfig);
void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE;
QJsonObject toJson() const Q_DECL_OVERRIDE;
const WebResource &getViewerResource() const;
private:
friend class MainConfig;
void loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user);
QJsonObject saveViewerResource() const;
WebResource m_viewerResource;
};
}
#endif // PDFVIEWERCONFIG_H

View File

@ -88,6 +88,12 @@
"text", "text",
"log" "log"
] ]
},
{
"name" : "PDF",
"suffixes" : [
"pdf"
]
} }
], ],
"shortcut_leader_key" : "Ctrl+G", "shortcut_leader_key" : "Ctrl+G",
@ -268,12 +274,13 @@
"scripts" : [ "scripts" : [
"web/js/qwebchannel.js", "web/js/qwebchannel.js",
"web/js/eventemitter.js", "web/js/eventemitter.js",
"web/js/vxcore.js",
"web/js/utils.js", "web/js/utils.js",
"web/js/nodelinemapper.js", "web/js/nodelinemapper.js",
"web/js/lrucache.js", "web/js/lrucache.js",
"web/js/graphcache.js", "web/js/graphcache.js",
"web/js/graphpreviewer.js", "web/js/graphpreviewer.js",
"web/js/vnotex.js", "web/js/markdownviewercore.js",
"web/js/vxworker.js", "web/js/vxworker.js",
"web/js/graphrenderer.js", "web/js/graphrenderer.js",
"web/js/svg-to-image.js", "web/js/svg-to-image.js",
@ -472,6 +479,43 @@
"edit_view_mode" : "editonly", "edit_view_mode" : "editonly",
"rich_paste_by_default" : true "rich_paste_by_default" : true
}, },
"pdf_viewer" : {
"override_viewer_resource" : true,
"viewer_resource" : {
"template" : "web/pdf-viewer-template.html",
"resources" : [
{
"name" : "built_in",
"enabled" : true,
"scripts" : [
"web/js/qwebchannel.js",
"web/js/eventemitter.js",
"web/js/utils.js",
"web/js/vxcore.js",
"web/js/pdfviewercore.js"
]
},
{
"name" : "pdf.js",
"enabled" : true,
"scripts" : [
"web/js/pdf.js/pdf.min.js",
"web/js/pdf.js/pdf_viewer.js"
],
"styles" : [
"web/js/pdf.js/pdf_viewer.css"
]
},
{
"name" : "pdf_viewer",
"enabled" : true,
"scripts" : [
"web/js/pdfviewer.js"
]
}
]
}
},
"image_host" : { "image_host" : {
"hosts" : [ "hosts" : [
], ],

View File

@ -16,6 +16,7 @@
<file>docs/zh_CN/features_tips.txt</file> <file>docs/zh_CN/features_tips.txt</file>
<file>web/markdown-viewer-template.html</file> <file>web/markdown-viewer-template.html</file>
<file>web/markdown-export-template.html</file> <file>web/markdown-export-template.html</file>
<file>web/pdf-viewer-template.html</file>
<file>web/css/user.css</file> <file>web/css/user.css</file>
<file>web/css/globalstyles.css</file> <file>web/css/globalstyles.css</file>
<file>web/css/markdownit.css</file> <file>web/css/markdownit.css</file>
@ -29,7 +30,9 @@
<file>web/js/lrucache.js</file> <file>web/js/lrucache.js</file>
<file>web/js/graphcache.js</file> <file>web/js/graphcache.js</file>
<file>web/js/graphpreviewer.js</file> <file>web/js/graphpreviewer.js</file>
<file>web/js/vnotex.js</file> <file>web/js/markdownviewercore.js</file>
<file>web/js/pdfviewercore.js</file>
<file>web/js/vxcore.js</file>
<file>web/js/vxworker.js</file> <file>web/js/vxworker.js</file>
<file>web/js/graphrenderer.js</file> <file>web/js/graphrenderer.js</file>
<file>web/js/markdownviewer.js</file> <file>web/js/markdownviewer.js</file>
@ -80,6 +83,13 @@
<file>web/js/markjs.js</file> <file>web/js/markjs.js</file>
<file>web/js/mind-elixir/MindElixir.min.js</file> <file>web/js/mind-elixir/MindElixir.min.js</file>
<file>web/js/mind-elixir/painter.js</file> <file>web/js/mind-elixir/painter.js</file>
<file>web/js/pdf.js/pdf.worker.min.js</file>
<file>web/js/pdf.js/pdf.min.js</file>
<file>web/js/pdf.js/pdf_viewer.js</file>
<file>web/js/pdf.js/pdf_viewer.css</file>
<file>web/js/pdf.js/images/shadow.png</file>
<file>web/js/pdf.js/images/loading-icon.gif</file>
<file>web/js/pdfviewer.js</file>
<file>dicts/en_US.aff</file> <file>dicts/en_US.aff</file>
<file>dicts/en_US.dic</file> <file>dicts/en_US.dic</file>
<file>themes/native/text-editor.theme</file> <file>themes/native/text-editor.theme</file>

View File

@ -213,7 +213,7 @@ class CrossCopy {
// Check if we need to fix the encoding. // Check if we need to fix the encoding.
// Win needs only space-encoded. // Win needs only space-encoded.
if (window.vnotex.os === "Windows") { if (window.vxcore.os === "Windows") {
let decodedUrl = decodeURI(img.src); let decodedUrl = decodeURI(img.src);
if (decodedUrl.length != img.src.length) { if (decodedUrl.length != img.src.length) {
// May need other encoding. // May need other encoding.

View File

@ -12,7 +12,7 @@ class EasyAccess {
// The repeat token from user input. // The repeat token from user input.
this.repeatToken = 0; this.repeatToken = 0;
window.vnotex.on('ready', () => { window.vxcore.on('ready', () => {
this.setupMouseMove(); this.setupMouseMove();
this.setupViNavigation(); this.setupViNavigation();
this.setupZoomOnWheel(); this.setupZoomOnWheel();
@ -22,7 +22,7 @@ class EasyAccess {
setupMouseMove() { setupMouseMove() {
window.addEventListener('mousedown', (e) => { window.addEventListener('mousedown', (e) => {
e = e || window.event; e = e || window.event;
let isCtrl = window.vnotex.os === 'Mac' ? e.metaKey : e.ctrlKey; let isCtrl = window.vxcore.os === 'Mac' ? e.metaKey : e.ctrlKey;
// Left button and Ctrl key. // Left button and Ctrl key.
if (e.buttons == 1 if (e.buttons == 1
&& isCtrl && isCtrl
@ -99,7 +99,7 @@ class EasyAccess {
shift = !!e.shiftKey; shift = !!e.shiftKey;
ctrl = !!e.ctrlKey; ctrl = !!e.ctrlKey;
meta = !!e.metaKey; meta = !!e.metaKey;
let isCtrl = window.vnotex.os === 'Mac' ? e.metaKey : e.ctrlKey; let isCtrl = window.vxcore.os === 'Mac' ? e.metaKey : e.ctrlKey;
switch (key) { switch (key) {
// Skip Ctrl, Shift, Alt, Supper. // Skip Ctrl, Shift, Alt, Supper.
case 16: case 16:
@ -332,7 +332,7 @@ class EasyAccess {
if (accepted) { if (accepted) {
e.preventDefault(); e.preventDefault();
} else { } else {
window.vnotex.setKeyPress(key, ctrl, shift, meta); window.vxcore.setKeyPress(key, ctrl, shift, meta);
} }
}); });
} }
@ -342,12 +342,12 @@ class EasyAccess {
// negative value for upper level; // negative value for upper level;
// positive value is ignored. // positive value is ignored.
jumpTitle(forward, relativeLevel, repeat) { jumpTitle(forward, relativeLevel, repeat) {
let headings = window.vnotex.nodeLineMapper.headingNodes; let headings = window.vxcore.nodeLineMapper.headingNodes;
if (headings.length == 0) { if (headings.length == 0) {
return; return;
} }
let currentHeadingIdx = window.vnotex.nodeLineMapper.currentHeadingIndex(); let currentHeadingIdx = window.vxcore.nodeLineMapper.currentHeadingIndex();
if (currentHeadingIdx == -1) { if (currentHeadingIdx == -1) {
// At the beginning, before any headings. // At the beginning, before any headings.
if (relativeLevel < 0 || !forward) { if (relativeLevel < 0 || !forward) {
@ -403,19 +403,19 @@ class EasyAccess {
return; return;
} }
window.vnotex.nodeLineMapper.scrollToNode(headings[targetIdx], false, false); window.vxcore.nodeLineMapper.scrollToNode(headings[targetIdx], false, false);
window.setTimeout(function() { window.setTimeout(function() {
window.vnotex.nodeLineMapper.updateCurrentHeading(); window.vxcore.nodeLineMapper.updateCurrentHeading();
}, 1000); }, 1000);
}; };
setupZoomOnWheel() { setupZoomOnWheel() {
window.addEventListener('wheel', (e) => { window.addEventListener('wheel', (e) => {
e = e || window.event; e = e || window.event;
let isCtrl = window.vnotex.os === 'Mac' ? e.metaKey : e.ctrlKey; let isCtrl = window.vxcore.os === 'Mac' ? e.metaKey : e.ctrlKey;
if (isCtrl) { if (isCtrl) {
if (e.deltaY != 0) { if (e.deltaY != 0) {
window.vnotex.zoom(e.deltaY < 0); window.vxcore.zoom(e.deltaY < 0);
} }
e.preventDefault(); e.preventDefault();
} }

View File

@ -110,4 +110,4 @@ class FlowchartJs extends GraphRenderer {
} }
} }
window.vnotex.registerWorker(new FlowchartJs()); window.vxcore.registerWorker(new FlowchartJs());

View File

@ -1,6 +1,6 @@
class GraphPreviewer { class GraphPreviewer {
constructor(p_vnotex, p_container) { constructor(p_vxcore, p_container) {
this.vnotex = p_vnotex; this.vxcore = p_vxcore;
// Preview will take place here. // Preview will take place here.
this.container = p_container; this.container = p_container;
@ -36,21 +36,21 @@ class GraphPreviewer {
this.initOnFirstPreview(); this.initOnFirstPreview();
if (p_lang === 'flow' || p_lang === 'flowchart') { if (p_lang === 'flow' || p_lang === 'flowchart') {
this.vnotex.getWorker('flowchartjs').renderText(this.container, this.vxcore.getWorker('flowchartjs').renderText(this.container,
p_text, p_text,
this.flowchartJsIdx++, this.flowchartJsIdx++,
(graphDiv) => { (graphDiv) => {
this.processGraph(p_id, p_timeStamp, graphDiv); this.processGraph(p_id, p_timeStamp, graphDiv);
}); });
} else if (p_lang === 'wavedrom') { } else if (p_lang === 'wavedrom') {
this.vnotex.getWorker('wavedrom').renderText(this.container, this.vxcore.getWorker('wavedrom').renderText(this.container,
p_text, p_text,
this.waveDromIdx++, this.waveDromIdx++,
(graphDiv) => { (graphDiv) => {
this.processGraph(p_id, p_timeStamp, graphDiv); this.processGraph(p_id, p_timeStamp, graphDiv);
}); });
} else if (p_lang === 'mermaid') { } else if (p_lang === 'mermaid') {
this.vnotex.getWorker('mermaid').renderText(this.container, this.vxcore.getWorker('mermaid').renderText(this.container,
p_text, p_text,
this.mermaidIdx++, this.mermaidIdx++,
(graphDiv) => { (graphDiv) => {
@ -66,7 +66,7 @@ class GraphPreviewer {
previewer.setGraphPreviewData(id, timeStamp, p_format, p_data, false, true); previewer.setGraphPreviewData(id, timeStamp, p_format, p_data, false, true);
}; };
}; };
this.vnotex.getWorker('plantuml').renderText(p_text, func(this, p_id, p_timeStamp)); this.vxcore.getWorker('plantuml').renderText(p_text, func(this, p_id, p_timeStamp));
return; return;
} else if (p_lang === 'dot' || p_lang === 'graphviz') { } else if (p_lang === 'dot' || p_lang === 'graphviz') {
let func = function(p_previewer, p_id, p_timeStamp) { let func = function(p_previewer, p_id, p_timeStamp) {
@ -77,7 +77,7 @@ class GraphPreviewer {
previewer.setGraphPreviewData(id, timeStamp, 'svg', p_svgNode.outerHTML, false, true); previewer.setGraphPreviewData(id, timeStamp, 'svg', p_svgNode.outerHTML, false, true);
}; };
}; };
this.vnotex.getWorker('graphviz').renderText(p_text, func(this, p_id, p_timeStamp)); this.vxcore.getWorker('graphviz').renderText(p_text, func(this, p_id, p_timeStamp));
return; return;
} else if (p_lang === 'mathjax') { } else if (p_lang === 'mathjax') {
this.renderMath(p_id, p_timeStamp, p_text, null); this.renderMath(p_id, p_timeStamp, p_text, null);
@ -104,7 +104,7 @@ class GraphPreviewer {
if (this.firstPreview) { if (this.firstPreview) {
this.firstPreview = false; this.firstPreview = false;
let contentStyle = window.getComputedStyle(this.vnotex.contentContainer); let contentStyle = window.getComputedStyle(this.vxcore.contentContainer);
this.currentColor = contentStyle.getPropertyValue('color'); this.currentColor = contentStyle.getPropertyValue('color');
console.log('currentColor', this.currentColor); console.log('currentColor', this.currentColor);
} }
@ -121,7 +121,7 @@ class GraphPreviewer {
previewer.processSvgAsPng(id, timeStamp, p_svgNode, p_dataSetter); previewer.processSvgAsPng(id, timeStamp, p_svgNode, p_dataSetter);
}; };
}; };
this.vnotex.getWorker('mathjax').renderText(this.container, this.vxcore.getWorker('mathjax').renderText(this.container,
p_text, p_text,
func(this, p_id, p_timeStamp)); func(this, p_id, p_timeStamp));
} }
@ -237,7 +237,7 @@ class GraphPreviewer {
base64: p_base64, base64: p_base64,
needScale: p_needScale needScale: p_needScale
}; };
this.vnotex.setGraphPreviewData(previewData); this.vxcore.setGraphPreviewData(previewData);
} }
setMathPreviewData(p_id, p_timeStamp, p_format = '', p_data = '', p_base64 = false, p_needScale = false) { setMathPreviewData(p_id, p_timeStamp, p_format = '', p_data = '', p_base64 = false, p_needScale = false) {
@ -249,6 +249,6 @@ class GraphPreviewer {
base64: p_base64, base64: p_base64,
needScale: p_needScale needScale: p_needScale
}; };
this.vnotex.setMathPreviewData(previewData); this.vxcore.setMathPreviewData(previewData);
} }
} }

View File

@ -28,12 +28,12 @@ class GraphRenderer extends VxWorker {
} }
registerInternal() { registerInternal() {
this.vnotex.on('basicMarkdownRendered', () => { this.vxcore.on('basicMarkdownRendered', () => {
this.reset(); this.reset();
this.renderCodeNodes(); this.renderCodeNodes();
}); });
this.vnotex.getWorker('markdownit').addLangsToSkipHighlight(this.langs); this.vxcore.getWorker('markdownit').addLangsToSkipHighlight(this.langs);
} }
// Return ture if we could continue. // Return ture if we could continue.
@ -79,7 +79,7 @@ class GraphRenderer extends VxWorker {
// Interface 2. // Interface 2.
// Get code nodes from markdownIt directly. // Get code nodes from markdownIt directly.
renderCodeNodes() { renderCodeNodes() {
this.nodesToRender = this.vnotex.getWorker('markdownit').getCodeNodes(this.langs); this.nodesToRender = this.vxcore.getWorker('markdownit').getCodeNodes(this.langs);
this.numOfRenderedNodes = 0; this.numOfRenderedNodes = 0;
this.doRender(); this.doRender();
} }

View File

@ -21,12 +21,12 @@ class Graphviz extends GraphRenderer {
} }
registerInternal() { registerInternal() {
this.vnotex.on('basicMarkdownRendered', () => { this.vxcore.on('basicMarkdownRendered', () => {
this.reset(); this.reset();
this.renderCodeNodes(window.vxOptions.transformSvgToPngEnabled ? 'png' : 'svg'); this.renderCodeNodes(window.vxOptions.transformSvgToPngEnabled ? 'png' : 'svg');
}); });
this.vnotex.getWorker('markdownit').addLangsToSkipHighlight(this.langs); this.vxcore.getWorker('markdownit').addLangsToSkipHighlight(this.langs);
this.useWeb = window.vxOptions.webGraphviz; this.useWeb = window.vxOptions.webGraphviz;
if (!this.useWeb) { if (!this.useWeb) {
this.extraScripts = []; this.extraScripts = [];
@ -138,7 +138,7 @@ class Graphviz extends GraphRenderer {
}; };
let callback = func(this, p_node); let callback = func(this, p_node);
this.vnotex.renderGraph(this.id, this.vxcore.renderGraph(this.id,
this.nextLocalGraphIndex++, this.nextLocalGraphIndex++,
this.format, this.format,
'dot', 'dot',
@ -174,4 +174,4 @@ class Graphviz extends GraphRenderer {
} }
} }
window.vnotex.registerWorker(new Graphviz()); window.vxcore.registerWorker(new Graphviz());

View File

@ -4,7 +4,7 @@ class ImageViewer {
this.viewBoxOffsetToMouse = { x: 0, y: 0 } this.viewBoxOffsetToMouse = { x: 0, y: 0 }
this.viewImageClass = 'vx-image-view-image'; this.viewImageClass = 'vx-image-view-image';
window.vnotex.on('ready', () => { window.vxcore.on('ready', () => {
this.viewBoxContainer = document.getElementById('vx-image-view-box'); this.viewBoxContainer = document.getElementById('vx-image-view-box');
this.viewBox = document.getElementById('vx-image-view'); this.viewBox = document.getElementById('vx-image-view');
this.closeButton = document.getElementById('vx-image-view-close'); this.closeButton = document.getElementById('vx-image-view-close');

View File

@ -244,10 +244,10 @@ class MarkdownIt extends VxWorker {
} }
registerInternal() { registerInternal() {
this.vnotex.on('markdownTextUpdated', (p_text) => { this.vxcore.on('markdownTextUpdated', (p_text) => {
this.render(this.vnotex.contentContainer, this.render(this.vxcore.contentContainer,
p_text, p_text,
'window.vnotex.getWorker(\'markdownit\').markdownRenderFinished();'); 'window.vxcore.getWorker(\'markdownit\').markdownRenderFinished();');
}); });
} }
@ -307,7 +307,7 @@ class MarkdownIt extends VxWorker {
// Will be called when basic markdown is rendered. // Will be called when basic markdown is rendered.
markdownRenderFinished() { markdownRenderFinished() {
window.vxImageViewer.setupForAllImages(this.lastContainerNode); window.vxImageViewer.setupForAllImages(this.lastContainerNode);
this.vnotex.setBasicMarkdownRendered(); this.vxcore.setBasicMarkdownRendered();
} }
getCodeNodes(p_langs) { getCodeNodes(p_langs) {
@ -342,4 +342,4 @@ class MarkdownIt extends VxWorker {
} }
} }
window.vnotex.registerWorker(new MarkdownIt(null)); window.vxcore.registerWorker(new MarkdownIt(null));

View File

@ -8,65 +8,65 @@ new QWebChannel(qt.webChannelTransport,
// Connect signals from CPP side. // Connect signals from CPP side.
adapter.textUpdated.connect(function(p_text) { adapter.textUpdated.connect(function(p_text) {
window.vnotex.setMarkdownText(p_text); window.vxcore.setMarkdownText(p_text);
}); });
adapter.editLineNumberUpdated.connect(function(p_lineNumber) { adapter.editLineNumberUpdated.connect(function(p_lineNumber) {
window.vnotex.scrollToLine(p_lineNumber); window.vxcore.scrollToLine(p_lineNumber);
}); });
adapter.anchorScrollRequested.connect(function(p_anchor) { adapter.anchorScrollRequested.connect(function(p_anchor) {
window.vnotex.scrollToAnchor(p_anchor); window.vxcore.scrollToAnchor(p_anchor);
}); });
adapter.graphPreviewRequested.connect(function(p_id, p_timeStamp, p_lang, p_text) { adapter.graphPreviewRequested.connect(function(p_id, p_timeStamp, p_lang, p_text) {
window.vnotex.previewGraph(p_id, p_timeStamp, p_lang, p_text); window.vxcore.previewGraph(p_id, p_timeStamp, p_lang, p_text);
}); });
adapter.mathPreviewRequested.connect(function(p_id, p_timeStamp, p_text) { adapter.mathPreviewRequested.connect(function(p_id, p_timeStamp, p_text) {
window.vnotex.previewMath(p_id, p_timeStamp, p_text); window.vxcore.previewMath(p_id, p_timeStamp, p_text);
}); });
adapter.scrollRequested.connect(function(p_up) { adapter.scrollRequested.connect(function(p_up) {
window.vnotex.scroll(p_up); window.vxcore.scroll(p_up);
}); });
adapter.htmlToMarkdownRequested.connect(function(p_id, p_timeStamp, p_html) { adapter.htmlToMarkdownRequested.connect(function(p_id, p_timeStamp, p_html) {
window.vnotex.htmlToMarkdown(p_id, p_timeStamp, p_html); window.vxcore.htmlToMarkdown(p_id, p_timeStamp, p_html);
}); });
adapter.highlightCodeBlockRequested.connect(function(p_idx, p_timeStamp, p_text) { adapter.highlightCodeBlockRequested.connect(function(p_idx, p_timeStamp, p_text) {
window.vnotex.highlightCodeBlock(p_idx, p_timeStamp, p_text); window.vxcore.highlightCodeBlock(p_idx, p_timeStamp, p_text);
}); });
adapter.parseStyleSheetRequested.connect(function(p_id, p_styleSheet) { adapter.parseStyleSheetRequested.connect(function(p_id, p_styleSheet) {
window.vnotex.parseStyleSheet(p_id, p_styleSheet); window.vxcore.parseStyleSheet(p_id, p_styleSheet);
}); });
adapter.crossCopyRequested.connect(function(p_id, p_timeStamp, p_target, p_baseUrl, p_html) { adapter.crossCopyRequested.connect(function(p_id, p_timeStamp, p_target, p_baseUrl, p_html) {
window.vnotex.crossCopy(p_id, p_timeStamp, p_target, p_baseUrl, p_html); window.vxcore.crossCopy(p_id, p_timeStamp, p_target, p_baseUrl, p_html);
}); });
adapter.findTextRequested.connect(function(p_texts, p_options, p_currentMatchLine) { adapter.findTextRequested.connect(function(p_texts, p_options, p_currentMatchLine) {
window.vnotex.findText(p_texts, p_options, p_currentMatchLine); window.vxcore.findText(p_texts, p_options, p_currentMatchLine);
}); });
adapter.contentRequested.connect(function() { adapter.contentRequested.connect(function() {
window.vnotex.saveContent(); window.vxcore.saveContent();
}); });
adapter.graphRenderDataReady.connect(function(p_id, p_index, p_format, p_data) { adapter.graphRenderDataReady.connect(function(p_id, p_index, p_format, p_data) {
window.vnotex.graphRenderDataReady(p_id, p_index, p_format, p_data); window.vxcore.graphRenderDataReady(p_id, p_index, p_format, p_data);
}); });
console.log('QWebChannel has been set up'); console.log('QWebChannel has been set up');
if (window.vnotex.initialized) { if (window.vxcore.initialized) {
window.vnotex.kickOffMarkdown(); window.vxcore.kickOffMarkdown();
} }
}); });
window.vnotex.on('ready', function() { window.vxcore.on('ready', function() {
if (window.vxMarkdownAdapter) { if (window.vxMarkdownAdapter) {
window.vnotex.kickOffMarkdown(); window.vxcore.kickOffMarkdown();
} }
}); });

View File

@ -1,25 +1,13 @@
/* /*
The main object that will be provided to all scripts in VNoteX. Markdown events:
Maintain a list of workers for different tasks.
Main:
- initialized()
- ready()
Markdown scenario:
- markdownTextUpdated(p_text) - markdownTextUpdated(p_text)
- basicMarkdownRendered() - basicMarkdownRendered()
- fullMarkdownRendered() - fullMarkdownRendered()
*/ */
class VNoteX extends EventEmitter { class MarkdownViewerCore extends VXCore {
constructor() { constructor() {
super(); super();
this.kickedOff = false;
this.initialized = false;
// Registered workers.
// name -> worker. // name -> worker.
this.workers = new Map(); this.workers = new Map();
@ -33,58 +21,48 @@ class VNoteX extends EventEmitter {
this.numOfMuteScroll = 0; this.numOfMuteScroll = 0;
this.os = VNoteX.detectOS();
this.turndown = null; this.turndown = null;
this.sectionNumberBaseLevel = 2; this.sectionNumberBaseLevel = 2;
// Dict mapping from {id, index} to callback for renderGraph(). // Dict mapping from {id, index} to callback for renderGraph().
this.renderGraphCallbacks = {} this.renderGraphCallbacks = {}
}
window.addEventListener('load', () => { initOnLoad() {
console.log('window load finished'); // Init DOM nodes.
this.contentContainer = document.getElementById('vx-content');
this.inplacePreviewContainer = document.getElementById('vx-inplace-preview');
// Init DOM nodes. this.nodeLineMapper = new NodeLineMapper(this, this.contentContainer);
this.contentContainer = document.getElementById('vx-content');
this.inplacePreviewContainer = document.getElementById('vx-inplace-preview');
this.nodeLineMapper = new NodeLineMapper(this, this.contentContainer); this.graphPreviewer = new GraphPreviewer(this, this.inplacePreviewContainer);
this.graphPreviewer = new GraphPreviewer(this, this.inplacePreviewContainer); this.crossCopyer = new CrossCopy(this);
this.crossCopyer = new CrossCopy(this); this.searcher = new MarkJs(this, this.contentContainer);
this.searcher = new MarkJs(this, this.contentContainer); this.sectionNumberBaseLevel = window.vxOptions.sectionNumberBaseLevel;
if (this.sectionNumberBaseLevel > 3) {
console.warn('only support section number base level less than 3', this.sectionNumberBaseLevel);
this.sectionNumberBaseLevel = 3;
}
this.sectionNumberBaseLevel = window.vxOptions.sectionNumberBaseLevel; this.setContentContainerOption('vx-constrain-image-width',
if (this.sectionNumberBaseLevel > 3) { window.vxOptions.constrainImageWidthEnabled || !window.vxOptions.scrollable);
console.warn('only support section number base level less than 3', this.sectionNumberBaseLevel); this.setContentContainerOption('vx-image-align-center',
this.sectionNumberBaseLevel = 3; window.vxOptions.imageAlignCenterEnabled);
} this.setContentContainerOption('vx-indent-first-line',
window.vxOptions.indentFirstLineEnabled);
this.setContentContainerOption('line-numbers',
window.vxOptions.codeBlockLineNumberEnabled);
this.setBodyOption('vx-transparent-background',
window.vxOptions.transparentBackgroundEnabled);
this.setContentContainerOption('vx-nonscrollable',
!window.vxOptions.scrollable);
this.setContentContainerOption('vx-constrain-image-width', this.setBodySize(window.vxOptions.bodyWidth, window.vxOptions.bodyHeight);
window.vxOptions.constrainImageWidthEnabled || !window.vxOptions.scrollable); document.body.style.height = '800';
this.setContentContainerOption('vx-image-align-center',
window.vxOptions.imageAlignCenterEnabled);
this.setContentContainerOption('vx-indent-first-line',
window.vxOptions.indentFirstLineEnabled);
this.setContentContainerOption('line-numbers',
window.vxOptions.codeBlockLineNumberEnabled);
this.setBodyOption('vx-transparent-background',
window.vxOptions.transparentBackgroundEnabled);
this.setContentContainerOption('vx-nonscrollable',
!window.vxOptions.scrollable);
this.setBodySize(window.vxOptions.bodyWidth, window.vxOptions.bodyHeight);
document.body.style.height = '800';
this.initialized = true;
// Signal out.
this.emit('initialized');
this.emit('ready');
});
} }
setContentContainerOption(p_class, p_enabled) { setContentContainerOption(p_class, p_enabled) {
@ -369,20 +347,6 @@ class VNoteX extends EventEmitter {
delete this.renderGraphCallbacks[key]; delete this.renderGraphCallbacks[key];
} }
} }
static detectOS() {
let osName="Unknown OS";
if (navigator.appVersion.indexOf("Win")!=-1) {
osName="Windows";
} else if (navigator.appVersion.indexOf("Mac")!=-1) {
osName="MacOS";
} else if (navigator.appVersion.indexOf("X11")!=-1) {
osName="UNIX";
} else if (navigator.appVersion.indexOf("Linux")!=-1) {
osName="Linux";
}
return osName
}
} }
window.vnotex = new VNoteX(); window.vxcore = new MarkdownViewerCore();

View File

@ -12,7 +12,7 @@ window.MathJax = {
ready: function() { ready: function() {
MathJax.startup.defaultReady(); MathJax.startup.defaultReady();
MathJax.startup.promise.then(() => { MathJax.startup.promise.then(() => {
window.vnotex.getWorker('mathjax').setMathJaxReady(); window.vxcore.getWorker('mathjax').setMathJaxReady();
}); });
} }
}, },
@ -42,11 +42,11 @@ class MathJaxRenderer extends VxWorker {
} }
registerInternal() { registerInternal() {
this.vnotex.on('basicMarkdownRendered', () => { this.vxcore.on('basicMarkdownRendered', () => {
this.render(this.vnotex.contentContainer, 'tex-to-render'); this.render(this.vxcore.contentContainer, 'tex-to-render');
}); });
this.vnotex.getWorker('markdownit').addLangsToSkipHighlight(this.langs); this.vxcore.getWorker('markdownit').addLangsToSkipHighlight(this.langs);
} }
initialize(p_callback) { initialize(p_callback) {
@ -74,7 +74,7 @@ class MathJaxRenderer extends VxWorker {
this.nodesToRender = []; this.nodesToRender = [];
// Transform extra class nodes. // Transform extra class nodes.
let extraNodes = this.vnotex.getWorker('markdownit').getCodeNodes(this.langs); let extraNodes = this.vxcore.getWorker('markdownit').getCodeNodes(this.langs);
this.transformExtraNodes(p_node, p_className, extraNodes); this.transformExtraNodes(p_node, p_className, extraNodes);
// Collect nodes to render. // Collect nodes to render.
@ -192,4 +192,4 @@ class MathJaxRenderer extends VxWorker {
} }
} }
window.vnotex.registerWorker(new MathJaxRenderer()); window.vxcore.registerWorker(new MathJaxRenderer());

View File

@ -122,4 +122,4 @@ class Mermaid extends GraphRenderer {
} }
} }
window.vnotex.registerWorker(new Mermaid()); window.vxcore.registerWorker(new Mermaid());

View File

@ -0,0 +1,3 @@
https://github.com/mozilla/pdf.js
Legacy version: https://unpkg.com/pdfjs-dist/
v3.1.81

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

22
src/data/extra/web/js/pdf.js/pdf.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
/* Main script file for PdfViewer. */
new QWebChannel(qt.webChannelTransport,
function(p_channel) {
let adapter = p_channel.objects.vxAdapter;
// Export the adapter globally.
window.vxAdapter = adapter;
// Connect signals from CPP side.
adapter.urlUpdated.connect(function(p_url) {
window.vxcore.loadPdf(p_url);
});
console.log('QWebChannel has been set up');
if (window.vxcore.initialized) {
window.vxAdapter.setReady(true);
}
});
pdfjsLib.GlobalWorkerOptions.workerSrc = window.vxcore.workerSrc;
window.vxcore.on('ready', function() {
if (window.vxAdapter) {
window.vxAdapter.setReady(true);
}
});

View File

@ -0,0 +1,55 @@
class PdfViewerCore extends VXCore {
constructor() {
super();
const scriptFolderPath = Utils.parentFolder(document.currentScript.src);
this.workerSrc = scriptFolderPath + '/pdf.js/pdf.worker.min.js';
}
initOnLoad() {
this.container = document.getElementById('vx-viewer-container');
}
loadPdf(p_url) {
const eventBus = new pdfjsViewer.EventBus();
// (Optionally) enable hyperlinks within PDF files.
const pdfLinkService = new pdfjsViewer.PDFLinkService({
eventBus,
});
// (Optionally) enable find controller.
const pdfFindController = new pdfjsViewer.PDFFindController({
eventBus,
linkService: pdfLinkService,
});
const pdfViewer = new pdfjsViewer.PDFViewer({
container: this.container,
eventBus,
linkService: pdfLinkService,
findController: pdfFindController,
});
pdfLinkService.setViewer(pdfViewer);
eventBus.on("pagesinit", function () {
// We can use pdfViewer now, e.g. let's change default scale.
pdfViewer.currentScaleValue = "page-width";
});
// Loading document.
const loadingTask = pdfjsLib.getDocument({
url: p_url,
enableXfa: true,
});
(async function () {
const pdfDocument = await loadingTask.promise;
// Document loaded, specifying document for the viewer and
// the (optional) linkService.
pdfViewer.setDocument(pdfDocument);
pdfLinkService.setDocument(pdfDocument, null);
})();
}
}
window.vxcore = new PdfViewerCore();

View File

@ -21,12 +21,12 @@ class PlantUml extends GraphRenderer {
} }
registerInternal() { registerInternal() {
this.vnotex.on('basicMarkdownRendered', () => { this.vxcore.on('basicMarkdownRendered', () => {
this.reset(); this.reset();
this.renderCodeNodes(window.vxOptions.transformSvgToPngEnabled ? 'png' : 'svg'); this.renderCodeNodes(window.vxOptions.transformSvgToPngEnabled ? 'png' : 'svg');
}); });
this.vnotex.getWorker('markdownit').addLangsToSkipHighlight(this.langs); this.vxcore.getWorker('markdownit').addLangsToSkipHighlight(this.langs);
this.useWeb = window.vxOptions.webPlantUml; this.useWeb = window.vxOptions.webPlantUml;
if (!this.useWeb) { if (!this.useWeb) {
@ -139,7 +139,7 @@ class PlantUml extends GraphRenderer {
// A helper function to render PlantUml via local JAR. // A helper function to render PlantUml via local JAR.
renderLocal(p_format, p_text, p_callback) { renderLocal(p_format, p_text, p_callback) {
this.vnotex.renderGraph(this.id, this.vxcore.renderGraph(this.id,
this.nextLocalGraphIndex++, this.nextLocalGraphIndex++,
p_format, p_format,
'puml', 'puml',
@ -175,4 +175,4 @@ class PlantUml extends GraphRenderer {
} }
} }
window.vnotex.registerWorker(new PlantUml()); window.vxcore.registerWorker(new PlantUml());

View File

@ -18,8 +18,8 @@ class PrismRenderer extends VxWorker {
} }
registerInternal() { registerInternal() {
this.vnotex.on('basicMarkdownRendered', () => { this.vxcore.on('basicMarkdownRendered', () => {
this.renderCodeNodes(this.vnotex.contentContainer); this.renderCodeNodes(this.vxcore.contentContainer);
}); });
} }
@ -30,7 +30,7 @@ class PrismRenderer extends VxWorker {
this.initialized = true; this.initialized = true;
let markdownIt = this.vnotex.getWorker('markdownit'); let markdownIt = this.vxcore.getWorker('markdownit');
Prism.plugins.filterHighlightAll.add((p_env) => { Prism.plugins.filterHighlightAll.add((p_env) => {
return !markdownIt.langsToSkipHighlight.has(p_env.language); return !markdownIt.langsToSkipHighlight.has(p_env.language);
}); });
@ -58,7 +58,7 @@ class PrismRenderer extends VxWorker {
renderCodeNodes(p_node) { renderCodeNodes(p_node) {
this.initialize(); this.initialize();
let codeNodes = this.vnotex.getWorker('markdownit').getCodeNodes(null); let codeNodes = this.vxcore.getWorker('markdownit').getCodeNodes(null);
this.doRender(p_node, codeNodes); this.doRender(p_node, codeNodes);
} }
@ -104,4 +104,4 @@ class PrismRenderer extends VxWorker {
} }
} }
window.vnotex.registerWorker(new PrismRenderer()); window.vxcore.registerWorker(new PrismRenderer());

View File

@ -0,0 +1,46 @@
/*
The main object that will be provided to all scripts in VNoteX.
TODO: Maintain a list of workers.
Events:
- initialized()
- ready()
*/
class VXCore extends EventEmitter {
constructor() {
super();
this.kickedOff = false;
this.initialized = false;
this.os = VXCore.detectOS();
window.addEventListener('load', () => {
console.log('window load finished');
this.initOnLoad();
this.initialized = true;
// Signal out.
this.emit('initialized');
this.emit('ready');
});
}
static detectOS() {
let osName="Unknown OS";
if (navigator.appVersion.indexOf("Win")!=-1) {
osName="Windows";
} else if (navigator.appVersion.indexOf("Mac")!=-1) {
osName="MacOS";
} else if (navigator.appVersion.indexOf("X11")!=-1) {
osName="UNIX";
} else if (navigator.appVersion.indexOf("Linux")!=-1) {
osName="Linux";
}
return osName
}
}

View File

@ -2,7 +2,7 @@
class VxWorker { class VxWorker {
constructor() { constructor() {
this.name = ''; this.name = '';
this.vnotex = null; this.vxcore = null;
if (!window.vxWorkerId) { if (!window.vxWorkerId) {
window.vxWorkerId = 1; window.vxWorkerId = 1;
@ -11,8 +11,8 @@ class VxWorker {
} }
// Called when registering this worker. // Called when registering this worker.
register(p_vnotex) { register(p_vxcore) {
this.vnotex = p_vnotex; this.vxcore = p_vxcore;
this.registerInternal(); this.registerInternal();
} }
@ -23,6 +23,6 @@ class VxWorker {
finishWork() { finishWork() {
console.log('worker finished', this.name); console.log('worker finished', this.name);
this.vnotex.finishWorker(this.name); this.vxcore.finishWorker(this.name);
} }
} }

View File

@ -77,4 +77,4 @@ class WaveDromRenderer extends GraphRenderer {
} }
} }
window.vnotex.registerWorker(new WaveDromRenderer()); window.vxcore.registerWorker(new WaveDromRenderer());

View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>VNoteX PDF Viewer</title>
<!-- VX_STYLES_PLACEHOLDER -->
<style>
body {
margin: 0;
padding: 0;
}
#vx-viewer-container {
overflow: auto;
position: absolute;
width: 100%;
height: 100%;
}
</style>
<script type="text/javascript">
/* VX_GLOBAL_OPTIONS_PLACEHOLDER */
</script>
<!-- VX_SCRIPTS_PLACEHOLDER -->
</head>
<body>
<div id="vx-viewer-container">
<div id="vx-viewer" class="pdfViewer"></div>
</div>
</body>
</html>

View File

@ -285,7 +285,7 @@ void WebViewExporter::prepare(const ExportOption &p_option)
qDebug() << "export page body size" << pageBodySize; qDebug() << "export page body size" << pageBodySize;
HtmlTemplateHelper::Paras paras; HtmlTemplateHelper::MarkdownParas paras;
paras.m_webStyleSheetFile = p_option.m_renderingStyleFile; paras.m_webStyleSheetFile = p_option.m_renderingStyleFile;
paras.m_highlightStyleSheetFile = p_option.m_syntaxHighlightStyleFile; paras.m_highlightStyleSheetFile = p_option.m_syntaxHighlightStyleFile;
paras.m_transparentBackgroundEnabled = p_option.m_useTransparentBg; paras.m_transparentBackgroundEnabled = p_option.m_useTransparentBg;
@ -300,7 +300,7 @@ void WebViewExporter::prepare(const ExportOption &p_option)
{ {
const bool addOutlinePanel = p_option.m_targetFormat == ExportFormat::HTML && p_option.m_htmlOption.m_addOutlinePanel; const bool addOutlinePanel = p_option.m_targetFormat == ExportFormat::HTML && p_option.m_htmlOption.m_addOutlinePanel;
m_exportHtmlTemplate = HtmlTemplateHelper::generateExportTemplate(config, addOutlinePanel); m_exportHtmlTemplate = HtmlTemplateHelper::generateMarkdownExportTemplate(config, addOutlinePanel);
} }
if (useWkhtmltopdf) { if (useWkhtmltopdf) {

View File

@ -1,17 +0,0 @@
#include "editormarkdownvieweradapter.h"
#include <buffer/buffer.h>
using namespace vnotex;
EditorMarkdownViewerAdapter::EditorMarkdownViewerAdapter(Buffer *p_buffer,
QObject *p_parent)
: MarkdownViewerAdapter(p_parent),
m_buffer(p_buffer)
{
}
void EditorMarkdownViewerAdapter::setBuffer(Buffer *p_buffer)
{
m_buffer = p_buffer;
}

View File

@ -1,25 +0,0 @@
#ifndef EDITORMARKDOWNVIEWERADAPTER_H
#define EDITORMARKDOWNVIEWERADAPTER_H
#include "markdownvieweradapter.h"
namespace vnotex
{
class Buffer;
class EditorMarkdownViewerAdapter : public MarkdownViewerAdapter
{
Q_OBJECT
public:
EditorMarkdownViewerAdapter(Buffer *p_buffer, QObject *p_parent = nullptr);
void setBuffer(Buffer *p_buffer);
public slots:
private:
Buffer *m_buffer = nullptr;
};
}
#endif // EDITORMARKDOWNVIEWERADAPTER_H

View File

@ -0,0 +1,28 @@
#include "pdfviewer.h"
#include <QWebChannel>
#include "pdfvieweradapter.h"
#include "previewhelper.h"
using namespace vnotex;
PdfViewer::PdfViewer(PdfViewerAdapter *p_adapter,
const QColor &p_background,
qreal p_zoomFactor,
QWidget *p_parent)
: WebViewer(p_background, p_zoomFactor, p_parent),
m_adapter(p_adapter)
{
m_adapter->setParent(this);
auto channel = new QWebChannel(this);
channel->registerObject(QStringLiteral("vxAdapter"), m_adapter);
page()->setWebChannel(channel);
}
PdfViewerAdapter *PdfViewer::adapter() const
{
return m_adapter;
}

View File

@ -0,0 +1,27 @@
#ifndef PDFVIEWER_H
#define PDFVIEWER_H
#include "../webviewer.h"
namespace vnotex
{
class PdfViewerAdapter;
class PdfViewer : public WebViewer
{
Q_OBJECT
public:
PdfViewer(PdfViewerAdapter *p_adapter,
const QColor &p_background,
qreal p_zoomFactor,
QWidget *p_parent = nullptr);
PdfViewerAdapter *adapter() const;
private:
// Managed by QObject.
PdfViewerAdapter *m_adapter = nullptr;
};
}
#endif // PDFVIEWER_H

View File

@ -0,0 +1,34 @@
#include "pdfvieweradapter.h"
using namespace vnotex;
PdfViewerAdapter::PdfViewerAdapter(QObject *p_parent)
: QObject(p_parent)
{
}
void PdfViewerAdapter::setUrl(const QString &p_url)
{
if (m_viewerReady) {
emit urlUpdated(p_url);
} else {
m_pendingActions.append([this, p_url]() {
emit urlUpdated(p_url);
});
}
}
void PdfViewerAdapter::setReady(bool p_ready)
{
if (m_viewerReady == p_ready) {
return;
}
m_viewerReady = p_ready;
if (m_viewerReady) {
for (auto &act : m_pendingActions) {
act();
}
m_pendingActions.clear();
}
}

View File

@ -0,0 +1,40 @@
#ifndef PDFVIEWERADAPTER_H
#define PDFVIEWERADAPTER_H
#include <QObject>
#include <QString>
#include <QJsonObject>
#include <core/global.h>
namespace vnotex
{
// Adapter and interface between CPP and JS for PDF.
class PdfViewerAdapter : public QObject
{
Q_OBJECT
public:
explicit PdfViewerAdapter(QObject *p_parent = nullptr);
~PdfViewerAdapter() = default;
void setUrl(const QString &p_url);
// Functions to be called from web side.
public slots:
void setReady(bool p_ready);
// Signals to be connected at web side.
signals:
void urlUpdated(const QString &p_url);
private:
// Whether web side viewer is ready to handle url update.
bool m_viewerReady = false;
// Pending actions for the viewer once it is ready.
QVector<std::function<void()>> m_pendingActions;
};
}
#endif // PDFVIEWERADAPTER_H

View File

@ -34,7 +34,7 @@
#include "editors/markdowneditor.h" #include "editors/markdowneditor.h"
#include "textviewwindowhelper.h" #include "textviewwindowhelper.h"
#include "editors/markdownviewer.h" #include "editors/markdownviewer.h"
#include "editors/editormarkdownvieweradapter.h" #include "editors/markdownvieweradapter.h"
#include "editors/previewhelper.h" #include "editors/previewhelper.h"
#include "dialogs/deleteconfirmdialog.h" #include "dialogs/deleteconfirmdialog.h"
#include "outlineprovider.h" #include "outlineprovider.h"
@ -193,10 +193,10 @@ void MarkdownViewWindow::setModified(bool p_modified)
void MarkdownViewWindow::handleEditorConfigChange() void MarkdownViewWindow::handleEditorConfigChange()
{ {
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &markdownEditorConfig = editorConfig.getMarkdownEditorConfig();
if (updateConfigRevision()) { if (updateConfigRevision()) {
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &markdownEditorConfig = editorConfig.getMarkdownEditorConfig();
updatePreviewHelperFromConfig(markdownEditorConfig); updatePreviewHelperFromConfig(markdownEditorConfig);
HtmlTemplateHelper::updateMarkdownViewerTemplate(markdownEditorConfig); HtmlTemplateHelper::updateMarkdownViewerTemplate(markdownEditorConfig);
@ -439,7 +439,7 @@ void MarkdownViewWindow::setupViewer()
HtmlTemplateHelper::updateMarkdownViewerTemplate(markdownEditorConfig); HtmlTemplateHelper::updateMarkdownViewerTemplate(markdownEditorConfig);
auto adapter = new EditorMarkdownViewerAdapter(nullptr, this); auto adapter = new MarkdownViewerAdapter(this);
m_viewer = new MarkdownViewer(adapter, m_viewer = new MarkdownViewer(adapter,
this, this,
VNoteX::getInst().getThemeMgr().getBaseBackground(), VNoteX::getInst().getThemeMgr().getBaseBackground(),
@ -544,7 +544,6 @@ void MarkdownViewWindow::syncViewerFromBuffer(bool p_syncPositionFromEditMode)
} }
auto buffer = getBuffer(); auto buffer = getBuffer();
adapter()->setBuffer(buffer);
if (buffer) { if (buffer) {
int lineNumber = -1; int lineNumber = -1;
if (p_syncPositionFromEditMode) { if (p_syncPositionFromEditMode) {
@ -624,10 +623,10 @@ void MarkdownViewWindow::setBufferRevisionAfterInvalidation(int p_bufferRevision
} }
} }
EditorMarkdownViewerAdapter *MarkdownViewWindow::adapter() const MarkdownViewerAdapter *MarkdownViewWindow::adapter() const
{ {
if (m_viewer) { if (m_viewer) {
return dynamic_cast<EditorMarkdownViewerAdapter *>(m_viewer->adapter()); return m_viewer->adapter();
} }
return nullptr; return nullptr;

View File

@ -23,7 +23,7 @@ namespace vnotex
{ {
class MarkdownEditor; class MarkdownEditor;
class MarkdownViewer; class MarkdownViewer;
class EditorMarkdownViewerAdapter; class MarkdownViewerAdapter;
class PreviewHelper; class PreviewHelper;
struct Outline; struct Outline;
class EditorConfig; class EditorConfig;
@ -141,7 +141,7 @@ namespace vnotex
// call this function to tell us now the latest buffer revision. // call this function to tell us now the latest buffer revision.
void setBufferRevisionAfterInvalidation(int p_bufferRevision); void setBufferRevisionAfterInvalidation(int p_bufferRevision);
EditorMarkdownViewerAdapter *adapter() const; MarkdownViewerAdapter *adapter() const;
// Get the position to sync from editor. // Get the position to sync from editor.
// Return -1 for an invalid position. // Return -1 for an invalid position.

View File

@ -0,0 +1,166 @@
#include "pdfviewwindow.h"
#include <core/vnotex.h>
#include <core/thememgr.h>
#include <core/htmltemplatehelper.h>
#include <core/configmgr.h>
#include <core/editorconfig.h>
#include <core/pdfviewerconfig.h>
#include <utils/pathutils.h>
#include "editors/pdfviewer.h"
#include "editors/pdfvieweradapter.h"
using namespace vnotex;
PdfViewWindow::PdfViewWindow(QWidget *p_parent)
: ViewWindow(p_parent)
{
m_mode = ViewWindowMode::Read;
setupUI();
}
void PdfViewWindow::setupUI()
{
setupViewer();
setCentralWidget(m_viewer);
}
void PdfViewWindow::setupViewer()
{
Q_ASSERT(!m_viewer);
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &pdfViewerConfig = editorConfig.getPdfViewerConfig();
updateConfigRevision();
HtmlTemplateHelper::updatePdfViewerTemplate(pdfViewerConfig);
auto adapter = new PdfViewerAdapter(nullptr);
m_viewer = new PdfViewer(adapter,
VNoteX::getInst().getThemeMgr().getBaseBackground(),
1.0,
this);
}
QString PdfViewWindow::getLatestContent() const
{
return NULL;
}
QString PdfViewWindow::selectedText() const
{
return QString();
}
void PdfViewWindow::setMode(ViewWindowMode p_mode)
{
Q_UNUSED(p_mode);
Q_ASSERT(false);
}
void PdfViewWindow::openTwice(const QSharedPointer<FileOpenParameters> &p_paras)
{
Q_UNUSED(p_paras);
}
ViewWindowSession PdfViewWindow::saveSession() const
{
auto session = ViewWindow::saveSession();
session.m_lineNumber = 1;
return session;
}
void PdfViewWindow::applySnippet(const QString &p_name)
{
Q_UNUSED(p_name);
}
void PdfViewWindow::applySnippet()
{
}
void PdfViewWindow::fetchWordCountInfo(const std::function<void(const WordCountInfo &)> &p_callback) const
{
Q_UNUSED(p_callback);
}
void PdfViewWindow::handleEditorConfigChange()
{
if (updateConfigRevision()) {
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &pdfViewerConfig = editorConfig.getPdfViewerConfig();
HtmlTemplateHelper::updatePdfViewerTemplate(pdfViewerConfig);
}
}
void PdfViewWindow::setModified(bool p_modified)
{
Q_UNUSED(p_modified);
}
void PdfViewWindow::print()
{
}
void PdfViewWindow::syncEditorFromBuffer()
{
auto buffer = getBuffer();
if (buffer) {
m_viewer->setHtml(HtmlTemplateHelper::getPdfViewerTemplate(),
PathUtils::pathToUrl(HtmlTemplateHelper::getPdfViewerTemplatePath()));
const auto url = PathUtils::pathToUrl(buffer->getContentPath());
adapter()->setUrl(url.toString(QUrl::EncodeSpaces));
} else {
m_viewer->setHtml("");
adapter()->setUrl("");
}
}
void PdfViewWindow::syncEditorFromBufferContent()
{
}
void PdfViewWindow::scrollUp()
{
}
void PdfViewWindow::scrollDown()
{
}
void PdfViewWindow::zoom(bool p_zoomIn)
{
Q_UNUSED(p_zoomIn);
}
PdfViewerAdapter *PdfViewWindow::adapter() const
{
if (m_viewer) {
return dynamic_cast<PdfViewerAdapter *>(m_viewer->adapter());
}
return nullptr;
}
bool PdfViewWindow::updateConfigRevision()
{
bool changed = false;
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
if (m_editorConfigRevision != editorConfig.revision()) {
changed = true;
m_editorConfigRevision = editorConfig.revision();
}
if (m_viewerConfigRevision != editorConfig.getPdfViewerConfig().revision()) {
changed = true;
m_viewerConfigRevision = editorConfig.getPdfViewerConfig().revision();
}
return changed;
}

View File

@ -0,0 +1,73 @@
#ifndef PDFVIEWWINDOW_H
#define PDFVIEWWINDOW_H
#include "viewwindow.h"
#include <QScopedPointer>
class QWebEngineView;
namespace vnotex
{
class PdfViewer;
class PdfViewerAdapter;
class EditorConfig;
class PdfViewWindow : public ViewWindow
{
Q_OBJECT
public:
explicit PdfViewWindow(QWidget *p_parent = nullptr);
QString getLatestContent() const Q_DECL_OVERRIDE;
QString selectedText() const Q_DECL_OVERRIDE;
void setMode(ViewWindowMode p_mode) Q_DECL_OVERRIDE;
void openTwice(const QSharedPointer<FileOpenParameters> &p_paras) Q_DECL_OVERRIDE;
ViewWindowSession saveSession() const Q_DECL_OVERRIDE;
void applySnippet(const QString &p_name) Q_DECL_OVERRIDE;
void applySnippet() Q_DECL_OVERRIDE;
void fetchWordCountInfo(const std::function<void(const WordCountInfo &)> &p_callback) const Q_DECL_OVERRIDE;
public slots:
void handleEditorConfigChange() Q_DECL_OVERRIDE;
protected slots:
void setModified(bool p_modified) Q_DECL_OVERRIDE;
void print() Q_DECL_OVERRIDE;
protected:
void syncEditorFromBuffer() Q_DECL_OVERRIDE;
void syncEditorFromBufferContent() Q_DECL_OVERRIDE;
void scrollUp() Q_DECL_OVERRIDE;
void scrollDown() Q_DECL_OVERRIDE;
void zoom(bool p_zoomIn) Q_DECL_OVERRIDE;
private:
void setupUI();
void setupViewer();
PdfViewerAdapter *adapter() const;
bool updateConfigRevision();
// Managed by QObject.
PdfViewer *m_viewer = nullptr;
int m_viewerConfigRevision = 0;
};
}
#endif // PDFVIEWWINDOW_H

View File

@ -135,10 +135,10 @@ void TextViewWindow::setModified(bool p_modified)
void TextViewWindow::handleEditorConfigChange() void TextViewWindow::handleEditorConfigChange()
{ {
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &textEditorConfig = editorConfig.getTextEditorConfig();
if (updateConfigRevision()) { if (updateConfigRevision()) {
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &textEditorConfig = editorConfig.getTextEditorConfig();
auto config = createTextEditorConfig(editorConfig, textEditorConfig); auto config = createTextEditorConfig(editorConfig, textEditorConfig);
m_editor->setConfig(config); m_editor->setConfig(config);

View File

@ -156,6 +156,12 @@ void ViewWindow::handleBufferChanged(const QSharedPointer<FileOpenParameters> &p
emit bufferChanged(); emit bufferChanged();
} }
void ViewWindow::handleBufferChangedInternal(const QSharedPointer<FileOpenParameters> &p_paras)
{
Q_UNUSED(p_paras);
syncEditorFromBuffer();
}
void ViewWindow::attachToBuffer(Buffer *p_buffer, const QSharedPointer<FileOpenParameters> &p_paras) void ViewWindow::attachToBuffer(Buffer *p_buffer, const QSharedPointer<FileOpenParameters> &p_paras)
{ {
Q_ASSERT(p_buffer); Q_ASSERT(p_buffer);

View File

@ -167,7 +167,7 @@ namespace vnotex
protected slots: protected slots:
// Handle current buffer change. // Handle current buffer change.
virtual void handleBufferChangedInternal(const QSharedPointer<FileOpenParameters> &p_paras) = 0; virtual void handleBufferChangedInternal(const QSharedPointer<FileOpenParameters> &p_paras);
// Handle all kinds of type action. // Handle all kinds of type action.
virtual void handleTypeAction(TypeAction p_action); virtual void handleTypeAction(TypeAction p_action);

View File

@ -44,7 +44,6 @@ SOURCES += \
$$PWD/dialogs/viewtagsdialog.cpp \ $$PWD/dialogs/viewtagsdialog.cpp \
$$PWD/dockwidgethelper.cpp \ $$PWD/dockwidgethelper.cpp \
$$PWD/dragdropareaindicator.cpp \ $$PWD/dragdropareaindicator.cpp \
$$PWD/editors/editormarkdownvieweradapter.cpp \
$$PWD/editors/graphhelper.cpp \ $$PWD/editors/graphhelper.cpp \
$$PWD/editors/graphvizhelper.cpp \ $$PWD/editors/graphvizhelper.cpp \
$$PWD/editors/markdowneditor.cpp \ $$PWD/editors/markdowneditor.cpp \
@ -52,6 +51,8 @@ SOURCES += \
$$PWD/editors/markdowntablehelper.cpp \ $$PWD/editors/markdowntablehelper.cpp \
$$PWD/editors/markdownviewer.cpp \ $$PWD/editors/markdownviewer.cpp \
$$PWD/editors/markdownvieweradapter.cpp \ $$PWD/editors/markdownvieweradapter.cpp \
$$PWD/editors/pdfviewer.cpp \
$$PWD/editors/pdfvieweradapter.cpp \
$$PWD/editors/plantumlhelper.cpp \ $$PWD/editors/plantumlhelper.cpp \
$$PWD/editors/previewhelper.cpp \ $$PWD/editors/previewhelper.cpp \
$$PWD/editors/statuswidget.cpp \ $$PWD/editors/statuswidget.cpp \
@ -81,6 +82,7 @@ SOURCES += \
$$PWD/outlinepopup.cpp \ $$PWD/outlinepopup.cpp \
$$PWD/outlineprovider.cpp \ $$PWD/outlineprovider.cpp \
$$PWD/outlineviewer.cpp \ $$PWD/outlineviewer.cpp \
$$PWD/pdfviewwindow.cpp \
$$PWD/propertydefs.cpp \ $$PWD/propertydefs.cpp \
$$PWD/quickselector.cpp \ $$PWD/quickselector.cpp \
$$PWD/searchinfoprovider.cpp \ $$PWD/searchinfoprovider.cpp \
@ -177,7 +179,6 @@ HEADERS += \
$$PWD/dialogs/viewtagsdialog.h \ $$PWD/dialogs/viewtagsdialog.h \
$$PWD/dockwidgethelper.h \ $$PWD/dockwidgethelper.h \
$$PWD/dragdropareaindicator.h \ $$PWD/dragdropareaindicator.h \
$$PWD/editors/editormarkdownvieweradapter.h \
$$PWD/editors/graphhelper.h \ $$PWD/editors/graphhelper.h \
$$PWD/editors/graphvizhelper.h \ $$PWD/editors/graphvizhelper.h \
$$PWD/editors/markdowneditor.h \ $$PWD/editors/markdowneditor.h \
@ -185,6 +186,8 @@ HEADERS += \
$$PWD/editors/markdowntablehelper.h \ $$PWD/editors/markdowntablehelper.h \
$$PWD/editors/markdownviewer.h \ $$PWD/editors/markdownviewer.h \
$$PWD/editors/markdownvieweradapter.h \ $$PWD/editors/markdownvieweradapter.h \
$$PWD/editors/pdfviewer.h \
$$PWD/editors/pdfvieweradapter.h \
$$PWD/editors/plantumlhelper.h \ $$PWD/editors/plantumlhelper.h \
$$PWD/editors/previewhelper.h \ $$PWD/editors/previewhelper.h \
$$PWD/editors/statuswidget.h \ $$PWD/editors/statuswidget.h \
@ -216,6 +219,7 @@ HEADERS += \
$$PWD/outlinepopup.h \ $$PWD/outlinepopup.h \
$$PWD/outlineprovider.h \ $$PWD/outlineprovider.h \
$$PWD/outlineviewer.h \ $$PWD/outlineviewer.h \
$$PWD/pdfviewwindow.h \
$$PWD/propertydefs.h \ $$PWD/propertydefs.h \
$$PWD/quickselector.h \ $$PWD/quickselector.h \
$$PWD/searchinfoprovider.h \ $$PWD/searchinfoprovider.h \