* 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/filetypehelper.cpp \
$$PWD/nodebufferprovider.cpp \
$$PWD/pdfbuffer.cpp \
$$PWD/pdfbufferfactory.cpp \
$$PWD/textbuffer.cpp \
$$PWD/textbufferfactory.cpp
$$PWD/textbufferfactory.cpp \
$$PWD/urlbasedbufferprovider.cpp
HEADERS += \
$$PWD/bufferprovider.h \
@ -18,5 +21,8 @@ HEADERS += \
$$PWD/markdownbufferfactory.h \
$$PWD/filetypehelper.h \
$$PWD/nodebufferprovider.h \
$$PWD/pdfbuffer.h \
$$PWD/pdfbufferfactory.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
{
// TODO: support non-local URLs.
QFileInfo info(getContentPath());
if (!info.exists() || m_lastModified != info.lastModified()) {
return true;

View File

@ -75,6 +75,22 @@ void FileTypeHelper::setupBuiltInTypes()
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;
type.m_type = FileType::Others;

View File

@ -15,6 +15,7 @@ namespace vnotex
{
Markdown = 0,
Text,
Pdf,
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/markdownbufferfactory.h>
#include <buffer/textbufferfactory.h>
#include <buffer/pdfbufferfactory.h>
#include <buffer/buffer.h>
#include <buffer/nodebufferprovider.h>
#include <buffer/filebufferprovider.h>
@ -52,6 +53,10 @@ void BufferMgr::initBufferServer()
// Text.
auto textFactory = QSharedPointer<TextBufferFactory>::create();
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)

View File

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

View File

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

View File

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

View File

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

View File

@ -3,6 +3,7 @@
#include <QDebug>
#include <core/markdowneditorconfig.h>
#include <core/pdfviewerconfig.h>
#include <core/configmgr.h>
#include <utils/utils.h>
#include <utils/fileutils.h>
@ -16,7 +17,9 @@ using namespace vnotex;
HtmlTemplateHelper::Template HtmlTemplateHelper::s_markdownViewerTemplate;
QString WebGlobalOptions::toJavascriptObject() const
HtmlTemplateHelper::Template HtmlTemplateHelper::s_pdfViewerTemplate;
QString MarkdownWebGlobalOptions::toJavascriptObject() const
{
return QStringLiteral("window.vxOptions = {\n")
+ 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_opts.toJavascriptObject());
@ -187,7 +190,7 @@ void HtmlTemplateHelper::updateMarkdownViewerTemplate(const MarkdownEditorConfig
s_markdownViewerTemplate.m_revision = p_config.revision();
Paras paras;
MarkdownParas paras;
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
paras.m_webStyleSheetFile = themeMgr.getFile(Theme::File::WebStyleSheet);
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);
}
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 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);
{
WebGlobalOptions opts;
MarkdownWebGlobalOptions opts;
opts.m_webPlantUml = p_config.getWebPlantUml();
opts.m_plantUmlWebService = p_config.getPlantUmlWebService();
opts.m_webGraphviz = p_config.getWebGraphviz();
@ -242,8 +246,8 @@ QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorC
return htmlTemplate;
}
QString HtmlTemplateHelper::generateExportTemplate(const MarkdownEditorConfig &p_config,
bool p_addOutlinePanel)
QString HtmlTemplateHelper::generateMarkdownExportTemplate(const MarkdownEditorConfig &p_config,
bool p_addOutlinePanel)
{
auto exportResource = p_config.getExportResource();
const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(exportResource.m_template);
@ -251,7 +255,7 @@ QString HtmlTemplateHelper::generateExportTemplate(const MarkdownEditorConfig &p
try {
htmlTemplate = FileUtils::readTextFile(templateFile);
} 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();
}
@ -322,3 +326,38 @@ QString HtmlTemplateHelper::errorPage()
return VNoteX::tr("Failed to load HTML template. Check the logs for details. "
"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
{
class MarkdownEditorConfig;
class PdfViewerConfig;
struct WebResource;
// Global options to be passed to Web side at the very beginning.
struct WebGlobalOptions
// Global options to be passed to Web side at the very beginning for Markdown.
struct MarkdownWebGlobalOptions
{
bool m_webPlantUml = true;
@ -67,7 +68,7 @@ namespace vnotex
class HtmlTemplateHelper
{
public:
struct Paras
struct MarkdownParas
{
QString m_webStyleSheetFile;
@ -90,14 +91,16 @@ namespace vnotex
HtmlTemplateHelper() = delete;
// For Markdown.
static const QString &getMarkdownViewerTemplate();
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,
bool p_addOutlinePanel);
static QString generateMarkdownExportTemplate(const MarkdownEditorConfig &p_config,
bool p_addOutlinePanel);
// For common HTML content manipulation.
static void fillTitle(QString &p_template, const QString &p_title);
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);
private:
static QString errorPage();
// For PdfViewer.
static const QString &getPdfViewerTemplate();
static void updatePdfViewerTemplate(const PdfViewerConfig &p_config, bool p_force = false);
static const QString &getPdfViewerTemplatePath();
private:
struct Template
{
int m_revision = -1;
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_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",
"log"
]
},
{
"name" : "PDF",
"suffixes" : [
"pdf"
]
}
],
"shortcut_leader_key" : "Ctrl+G",
@ -268,12 +274,13 @@
"scripts" : [
"web/js/qwebchannel.js",
"web/js/eventemitter.js",
"web/js/vxcore.js",
"web/js/utils.js",
"web/js/nodelinemapper.js",
"web/js/lrucache.js",
"web/js/graphcache.js",
"web/js/graphpreviewer.js",
"web/js/vnotex.js",
"web/js/markdownviewercore.js",
"web/js/vxworker.js",
"web/js/graphrenderer.js",
"web/js/svg-to-image.js",
@ -472,6 +479,43 @@
"edit_view_mode" : "editonly",
"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" : {
"hosts" : [
],

View File

@ -16,6 +16,7 @@
<file>docs/zh_CN/features_tips.txt</file>
<file>web/markdown-viewer-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/globalstyles.css</file>
<file>web/css/markdownit.css</file>
@ -29,7 +30,9 @@
<file>web/js/lrucache.js</file>
<file>web/js/graphcache.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/graphrenderer.js</file>
<file>web/js/markdownviewer.js</file>
@ -80,6 +83,13 @@
<file>web/js/markjs.js</file>
<file>web/js/mind-elixir/MindElixir.min.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.dic</file>
<file>themes/native/text-editor.theme</file>

View File

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

View File

@ -12,7 +12,7 @@ class EasyAccess {
// The repeat token from user input.
this.repeatToken = 0;
window.vnotex.on('ready', () => {
window.vxcore.on('ready', () => {
this.setupMouseMove();
this.setupViNavigation();
this.setupZoomOnWheel();
@ -22,7 +22,7 @@ class EasyAccess {
setupMouseMove() {
window.addEventListener('mousedown', (e) => {
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.
if (e.buttons == 1
&& isCtrl
@ -99,7 +99,7 @@ class EasyAccess {
shift = !!e.shiftKey;
ctrl = !!e.ctrlKey;
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) {
// Skip Ctrl, Shift, Alt, Supper.
case 16:
@ -332,7 +332,7 @@ class EasyAccess {
if (accepted) {
e.preventDefault();
} 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;
// positive value is ignored.
jumpTitle(forward, relativeLevel, repeat) {
let headings = window.vnotex.nodeLineMapper.headingNodes;
let headings = window.vxcore.nodeLineMapper.headingNodes;
if (headings.length == 0) {
return;
}
let currentHeadingIdx = window.vnotex.nodeLineMapper.currentHeadingIndex();
let currentHeadingIdx = window.vxcore.nodeLineMapper.currentHeadingIndex();
if (currentHeadingIdx == -1) {
// At the beginning, before any headings.
if (relativeLevel < 0 || !forward) {
@ -403,19 +403,19 @@ class EasyAccess {
return;
}
window.vnotex.nodeLineMapper.scrollToNode(headings[targetIdx], false, false);
window.vxcore.nodeLineMapper.scrollToNode(headings[targetIdx], false, false);
window.setTimeout(function() {
window.vnotex.nodeLineMapper.updateCurrentHeading();
window.vxcore.nodeLineMapper.updateCurrentHeading();
}, 1000);
};
setupZoomOnWheel() {
window.addEventListener('wheel', (e) => {
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 (e.deltaY != 0) {
window.vnotex.zoom(e.deltaY < 0);
window.vxcore.zoom(e.deltaY < 0);
}
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 {
constructor(p_vnotex, p_container) {
this.vnotex = p_vnotex;
constructor(p_vxcore, p_container) {
this.vxcore = p_vxcore;
// Preview will take place here.
this.container = p_container;
@ -36,21 +36,21 @@ class GraphPreviewer {
this.initOnFirstPreview();
if (p_lang === 'flow' || p_lang === 'flowchart') {
this.vnotex.getWorker('flowchartjs').renderText(this.container,
this.vxcore.getWorker('flowchartjs').renderText(this.container,
p_text,
this.flowchartJsIdx++,
(graphDiv) => {
this.processGraph(p_id, p_timeStamp, graphDiv);
});
} else if (p_lang === 'wavedrom') {
this.vnotex.getWorker('wavedrom').renderText(this.container,
this.vxcore.getWorker('wavedrom').renderText(this.container,
p_text,
this.waveDromIdx++,
(graphDiv) => {
this.processGraph(p_id, p_timeStamp, graphDiv);
});
} else if (p_lang === 'mermaid') {
this.vnotex.getWorker('mermaid').renderText(this.container,
this.vxcore.getWorker('mermaid').renderText(this.container,
p_text,
this.mermaidIdx++,
(graphDiv) => {
@ -66,7 +66,7 @@ class GraphPreviewer {
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;
} else if (p_lang === 'dot' || p_lang === 'graphviz') {
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);
};
};
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;
} else if (p_lang === 'mathjax') {
this.renderMath(p_id, p_timeStamp, p_text, null);
@ -104,7 +104,7 @@ class GraphPreviewer {
if (this.firstPreview) {
this.firstPreview = false;
let contentStyle = window.getComputedStyle(this.vnotex.contentContainer);
let contentStyle = window.getComputedStyle(this.vxcore.contentContainer);
this.currentColor = contentStyle.getPropertyValue('color');
console.log('currentColor', this.currentColor);
}
@ -121,7 +121,7 @@ class GraphPreviewer {
previewer.processSvgAsPng(id, timeStamp, p_svgNode, p_dataSetter);
};
};
this.vnotex.getWorker('mathjax').renderText(this.container,
this.vxcore.getWorker('mathjax').renderText(this.container,
p_text,
func(this, p_id, p_timeStamp));
}
@ -237,7 +237,7 @@ class GraphPreviewer {
base64: p_base64,
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) {
@ -249,6 +249,6 @@ class GraphPreviewer {
base64: p_base64,
needScale: p_needScale
};
this.vnotex.setMathPreviewData(previewData);
this.vxcore.setMathPreviewData(previewData);
}
}

View File

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

View File

@ -21,12 +21,12 @@ class Graphviz extends GraphRenderer {
}
registerInternal() {
this.vnotex.on('basicMarkdownRendered', () => {
this.vxcore.on('basicMarkdownRendered', () => {
this.reset();
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;
if (!this.useWeb) {
this.extraScripts = [];
@ -138,7 +138,7 @@ class Graphviz extends GraphRenderer {
};
let callback = func(this, p_node);
this.vnotex.renderGraph(this.id,
this.vxcore.renderGraph(this.id,
this.nextLocalGraphIndex++,
this.format,
'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.viewImageClass = 'vx-image-view-image';
window.vnotex.on('ready', () => {
window.vxcore.on('ready', () => {
this.viewBoxContainer = document.getElementById('vx-image-view-box');
this.viewBox = document.getElementById('vx-image-view');
this.closeButton = document.getElementById('vx-image-view-close');

View File

@ -244,10 +244,10 @@ class MarkdownIt extends VxWorker {
}
registerInternal() {
this.vnotex.on('markdownTextUpdated', (p_text) => {
this.render(this.vnotex.contentContainer,
this.vxcore.on('markdownTextUpdated', (p_text) => {
this.render(this.vxcore.contentContainer,
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.
markdownRenderFinished() {
window.vxImageViewer.setupForAllImages(this.lastContainerNode);
this.vnotex.setBasicMarkdownRendered();
this.vxcore.setBasicMarkdownRendered();
}
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.
adapter.textUpdated.connect(function(p_text) {
window.vnotex.setMarkdownText(p_text);
window.vxcore.setMarkdownText(p_text);
});
adapter.editLineNumberUpdated.connect(function(p_lineNumber) {
window.vnotex.scrollToLine(p_lineNumber);
window.vxcore.scrollToLine(p_lineNumber);
});
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) {
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) {
window.vnotex.previewMath(p_id, p_timeStamp, p_text);
window.vxcore.previewMath(p_id, p_timeStamp, p_text);
});
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) {
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) {
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) {
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) {
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) {
window.vnotex.findText(p_texts, p_options, p_currentMatchLine);
window.vxcore.findText(p_texts, p_options, p_currentMatchLine);
});
adapter.contentRequested.connect(function() {
window.vnotex.saveContent();
window.vxcore.saveContent();
});
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');
if (window.vnotex.initialized) {
window.vnotex.kickOffMarkdown();
if (window.vxcore.initialized) {
window.vxcore.kickOffMarkdown();
}
});
window.vnotex.on('ready', function() {
window.vxcore.on('ready', function() {
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.
Maintain a list of workers for different tasks.
Main:
- initialized()
- ready()
Markdown scenario:
Markdown events:
- markdownTextUpdated(p_text)
- basicMarkdownRendered()
- fullMarkdownRendered()
*/
class VNoteX extends EventEmitter {
class MarkdownViewerCore extends VXCore {
constructor() {
super();
this.kickedOff = false;
this.initialized = false;
// Registered workers.
// name -> worker.
this.workers = new Map();
@ -33,58 +21,48 @@ class VNoteX extends EventEmitter {
this.numOfMuteScroll = 0;
this.os = VNoteX.detectOS();
this.turndown = null;
this.sectionNumberBaseLevel = 2;
// Dict mapping from {id, index} to callback for renderGraph().
this.renderGraphCallbacks = {}
}
window.addEventListener('load', () => {
console.log('window load finished');
initOnLoad() {
// Init DOM nodes.
this.contentContainer = document.getElementById('vx-content');
this.inplacePreviewContainer = document.getElementById('vx-inplace-preview');
// Init DOM nodes.
this.contentContainer = document.getElementById('vx-content');
this.inplacePreviewContainer = document.getElementById('vx-inplace-preview');
this.nodeLineMapper = new NodeLineMapper(this, this.contentContainer);
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;
if (this.sectionNumberBaseLevel > 3) {
console.warn('only support section number base level less than 3', this.sectionNumberBaseLevel);
this.sectionNumberBaseLevel = 3;
}
this.setContentContainerOption('vx-constrain-image-width',
window.vxOptions.constrainImageWidthEnabled || !window.vxOptions.scrollable);
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.setContentContainerOption('vx-constrain-image-width',
window.vxOptions.constrainImageWidthEnabled || !window.vxOptions.scrollable);
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');
});
this.setBodySize(window.vxOptions.bodyWidth, window.vxOptions.bodyHeight);
document.body.style.height = '800';
}
setContentContainerOption(p_class, p_enabled) {
@ -369,20 +347,6 @@ class VNoteX extends EventEmitter {
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() {
MathJax.startup.defaultReady();
MathJax.startup.promise.then(() => {
window.vnotex.getWorker('mathjax').setMathJaxReady();
window.vxcore.getWorker('mathjax').setMathJaxReady();
});
}
},
@ -42,11 +42,11 @@ class MathJaxRenderer extends VxWorker {
}
registerInternal() {
this.vnotex.on('basicMarkdownRendered', () => {
this.render(this.vnotex.contentContainer, 'tex-to-render');
this.vxcore.on('basicMarkdownRendered', () => {
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) {
@ -74,7 +74,7 @@ class MathJaxRenderer extends VxWorker {
this.nodesToRender = [];
// 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);
// 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() {
this.vnotex.on('basicMarkdownRendered', () => {
this.vxcore.on('basicMarkdownRendered', () => {
this.reset();
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;
if (!this.useWeb) {
@ -139,7 +139,7 @@ class PlantUml extends GraphRenderer {
// A helper function to render PlantUml via local JAR.
renderLocal(p_format, p_text, p_callback) {
this.vnotex.renderGraph(this.id,
this.vxcore.renderGraph(this.id,
this.nextLocalGraphIndex++,
p_format,
'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() {
this.vnotex.on('basicMarkdownRendered', () => {
this.renderCodeNodes(this.vnotex.contentContainer);
this.vxcore.on('basicMarkdownRendered', () => {
this.renderCodeNodes(this.vxcore.contentContainer);
});
}
@ -30,7 +30,7 @@ class PrismRenderer extends VxWorker {
this.initialized = true;
let markdownIt = this.vnotex.getWorker('markdownit');
let markdownIt = this.vxcore.getWorker('markdownit');
Prism.plugins.filterHighlightAll.add((p_env) => {
return !markdownIt.langsToSkipHighlight.has(p_env.language);
});
@ -58,7 +58,7 @@ class PrismRenderer extends VxWorker {
renderCodeNodes(p_node) {
this.initialize();
let codeNodes = this.vnotex.getWorker('markdownit').getCodeNodes(null);
let codeNodes = this.vxcore.getWorker('markdownit').getCodeNodes(null);
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 {
constructor() {
this.name = '';
this.vnotex = null;
this.vxcore = null;
if (!window.vxWorkerId) {
window.vxWorkerId = 1;
@ -11,8 +11,8 @@ class VxWorker {
}
// Called when registering this worker.
register(p_vnotex) {
this.vnotex = p_vnotex;
register(p_vxcore) {
this.vxcore = p_vxcore;
this.registerInternal();
}
@ -23,6 +23,6 @@ class VxWorker {
finishWork() {
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;
HtmlTemplateHelper::Paras paras;
HtmlTemplateHelper::MarkdownParas paras;
paras.m_webStyleSheetFile = p_option.m_renderingStyleFile;
paras.m_highlightStyleSheetFile = p_option.m_syntaxHighlightStyleFile;
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;
m_exportHtmlTemplate = HtmlTemplateHelper::generateExportTemplate(config, addOutlinePanel);
m_exportHtmlTemplate = HtmlTemplateHelper::generateMarkdownExportTemplate(config, addOutlinePanel);
}
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 "textviewwindowhelper.h"
#include "editors/markdownviewer.h"
#include "editors/editormarkdownvieweradapter.h"
#include "editors/markdownvieweradapter.h"
#include "editors/previewhelper.h"
#include "dialogs/deleteconfirmdialog.h"
#include "outlineprovider.h"
@ -193,10 +193,10 @@ void MarkdownViewWindow::setModified(bool p_modified)
void MarkdownViewWindow::handleEditorConfigChange()
{
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &markdownEditorConfig = editorConfig.getMarkdownEditorConfig();
if (updateConfigRevision()) {
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &markdownEditorConfig = editorConfig.getMarkdownEditorConfig();
updatePreviewHelperFromConfig(markdownEditorConfig);
HtmlTemplateHelper::updateMarkdownViewerTemplate(markdownEditorConfig);
@ -439,7 +439,7 @@ void MarkdownViewWindow::setupViewer()
HtmlTemplateHelper::updateMarkdownViewerTemplate(markdownEditorConfig);
auto adapter = new EditorMarkdownViewerAdapter(nullptr, this);
auto adapter = new MarkdownViewerAdapter(this);
m_viewer = new MarkdownViewer(adapter,
this,
VNoteX::getInst().getThemeMgr().getBaseBackground(),
@ -544,7 +544,6 @@ void MarkdownViewWindow::syncViewerFromBuffer(bool p_syncPositionFromEditMode)
}
auto buffer = getBuffer();
adapter()->setBuffer(buffer);
if (buffer) {
int lineNumber = -1;
if (p_syncPositionFromEditMode) {
@ -624,10 +623,10 @@ void MarkdownViewWindow::setBufferRevisionAfterInvalidation(int p_bufferRevision
}
}
EditorMarkdownViewerAdapter *MarkdownViewWindow::adapter() const
MarkdownViewerAdapter *MarkdownViewWindow::adapter() const
{
if (m_viewer) {
return dynamic_cast<EditorMarkdownViewerAdapter *>(m_viewer->adapter());
return m_viewer->adapter();
}
return nullptr;

View File

@ -23,7 +23,7 @@ namespace vnotex
{
class MarkdownEditor;
class MarkdownViewer;
class EditorMarkdownViewerAdapter;
class MarkdownViewerAdapter;
class PreviewHelper;
struct Outline;
class EditorConfig;
@ -141,7 +141,7 @@ namespace vnotex
// call this function to tell us now the latest buffer revision.
void setBufferRevisionAfterInvalidation(int p_bufferRevision);
EditorMarkdownViewerAdapter *adapter() const;
MarkdownViewerAdapter *adapter() const;
// Get the position to sync from editor.
// 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()
{
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &textEditorConfig = editorConfig.getTextEditorConfig();
if (updateConfigRevision()) {
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const auto &textEditorConfig = editorConfig.getTextEditorConfig();
auto config = createTextEditorConfig(editorConfig, textEditorConfig);
m_editor->setConfig(config);

View File

@ -156,6 +156,12 @@ void ViewWindow::handleBufferChanged(const QSharedPointer<FileOpenParameters> &p
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)
{
Q_ASSERT(p_buffer);

View File

@ -167,7 +167,7 @@ namespace vnotex
protected slots:
// 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.
virtual void handleTypeAction(TypeAction p_action);

View File

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