diff --git a/src/core/buffer/buffer.pri b/src/core/buffer/buffer.pri index c5c5ffec..9d965a3e 100644 --- a/src/core/buffer/buffer.pri +++ b/src/core/buffer/buffer.pri @@ -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 diff --git a/src/core/buffer/bufferprovider.cpp b/src/core/buffer/bufferprovider.cpp index 86216668..cc2d0f14 100644 --- a/src/core/buffer/bufferprovider.cpp +++ b/src/core/buffer/bufferprovider.cpp @@ -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; diff --git a/src/core/buffer/filetypehelper.cpp b/src/core/buffer/filetypehelper.cpp index f9a81cc8..fd0023d9 100644 --- a/src/core/buffer/filetypehelper.cpp +++ b/src/core/buffer/filetypehelper.cpp @@ -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; diff --git a/src/core/buffer/filetypehelper.h b/src/core/buffer/filetypehelper.h index fb78d3fa..59655692 100644 --- a/src/core/buffer/filetypehelper.h +++ b/src/core/buffer/filetypehelper.h @@ -15,6 +15,7 @@ namespace vnotex { Markdown = 0, Text, + Pdf, Others }; diff --git a/src/core/buffer/pdfbuffer.cpp b/src/core/buffer/pdfbuffer.cpp new file mode 100644 index 00000000..1a6c353e --- /dev/null +++ b/src/core/buffer/pdfbuffer.cpp @@ -0,0 +1,17 @@ +#include "pdfbuffer.h" + +#include + +using namespace vnotex; + +PdfBuffer::PdfBuffer(const BufferParameters &p_parameters, + QObject *p_parent) + : Buffer(p_parameters, p_parent) +{ +} + +ViewWindow *PdfBuffer::createViewWindowInternal(const QSharedPointer &p_paras, QWidget *p_parent) +{ + Q_UNUSED(p_paras); + return new PdfViewWindow(p_parent); +} diff --git a/src/core/buffer/pdfbuffer.h b/src/core/buffer/pdfbuffer.h new file mode 100644 index 00000000..573629ae --- /dev/null +++ b/src/core/buffer/pdfbuffer.h @@ -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 &p_paras, + QWidget *p_parent) Q_DECL_OVERRIDE; + + }; +} // ns vnotex + +#endif // PDFBUFFER_H diff --git a/src/core/buffer/pdfbufferfactory.cpp b/src/core/buffer/pdfbufferfactory.cpp new file mode 100644 index 00000000..c2562770 --- /dev/null +++ b/src/core/buffer/pdfbufferfactory.cpp @@ -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::create(p_parameters.m_provider); + return new PdfBuffer(paras, p_parent); +} + +bool PdfBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const +{ + return dynamic_cast(p_buffer) != nullptr; +} diff --git a/src/core/buffer/pdfbufferfactory.h b/src/core/buffer/pdfbufferfactory.h new file mode 100644 index 00000000..fd08142d --- /dev/null +++ b/src/core/buffer/pdfbufferfactory.h @@ -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 diff --git a/src/core/buffer/urlbasedbufferprovider.cpp b/src/core/buffer/urlbasedbufferprovider.cpp new file mode 100644 index 00000000..0aa6ef89 --- /dev/null +++ b/src/core/buffer/urlbasedbufferprovider.cpp @@ -0,0 +1,3 @@ +#include "urlbasedbufferprovider.h" + +using namespace vnotex; diff --git a/src/core/buffer/urlbasedbufferprovider.h b/src/core/buffer/urlbasedbufferprovider.h new file mode 100644 index 00000000..a1d8965d --- /dev/null +++ b/src/core/buffer/urlbasedbufferprovider.h @@ -0,0 +1,132 @@ +#ifndef URLBASEDBUFFERPROVIDER_H +#define URLBASEDBUFFERPROVIDER_H + +#include "bufferprovider.h" + +#include + +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 &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(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 getFile() const Q_DECL_OVERRIDE { + return m_provider->getFile(); + } + + private: + QSharedPointer m_provider; + }; +} + +#endif // URLBASEDBUFFERPROVIDER_H diff --git a/src/core/buffermgr.cpp b/src/core/buffermgr.cpp index 9b250df1..eac6defe 100644 --- a/src/core/buffermgr.cpp +++ b/src/core/buffermgr.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,10 @@ void BufferMgr::initBufferServer() // Text. auto textFactory = QSharedPointer::create(); m_bufferServer->registerItem(helper.getFileType(FileType::Text).m_typeName, textFactory); + + // Pdf. + auto pdfFactory = QSharedPointer::create(); + m_bufferServer->registerItem(helper.getFileType(FileType::Pdf).m_typeName, pdfFactory); } void BufferMgr::open(Node *p_node, const QSharedPointer &p_paras) diff --git a/src/core/configmgr.cpp b/src/core/configmgr.cpp index 10531a5f..bb2b5753 100644 --- a/src/core/configmgr.cpp +++ b/src/core/configmgr.cpp @@ -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"; diff --git a/src/core/core.pri b/src/core/core.pri index a4a0690a..3da141de 100644 --- a/src/core/core.pri +++ b/src/core/core.pri @@ -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 \ diff --git a/src/core/editorconfig.cpp b/src/core/editorconfig.cpp index c1c06803..a7d187fd 100644 --- a/src/core/editorconfig.cpp +++ b/src/core/editorconfig.cpp @@ -5,6 +5,7 @@ #include "texteditorconfig.h" #include "markdowneditorconfig.h" +#include "pdfviewerconfig.h" #include @@ -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; diff --git a/src/core/editorconfig.h b/src/core/editorconfig.h index 70dade79..4819b44e 100644 --- a/src/core/editorconfig.h +++ b/src/core/editorconfig.h @@ -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 m_markdownEditorConfig; + QScopedPointer m_pdfViewerConfig; + bool m_spellCheckAutoDetectLanguageEnabled = false; QString m_spellCheckDefaultDictionary; diff --git a/src/core/htmltemplatehelper.cpp b/src/core/htmltemplatehelper.cpp index d661cb4c..5272010a 100644 --- a/src/core/htmltemplatehelper.cpp +++ b/src/core/htmltemplatehelper.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -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); +} diff --git a/src/core/htmltemplatehelper.h b/src/core/htmltemplatehelper.h index 9eba5d02..1078ce63 100644 --- a/src/core/htmltemplatehelper.h +++ b/src/core/htmltemplatehelper.h @@ -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; }; } diff --git a/src/core/pdfviewerconfig.cpp b/src/core/pdfviewerconfig.cpp new file mode 100644 index 00000000..4b16e48a --- /dev/null +++ b/src/core/pdfviewerconfig.cpp @@ -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; +} diff --git a/src/core/pdfviewerconfig.h b/src/core/pdfviewerconfig.h new file mode 100644 index 00000000..6f67d9d0 --- /dev/null +++ b/src/core/pdfviewerconfig.h @@ -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 diff --git a/src/data/core/vnotex.json b/src/data/core/vnotex.json index 0273b1bd..0295e869 100644 --- a/src/data/core/vnotex.json +++ b/src/data/core/vnotex.json @@ -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" : [ ], diff --git a/src/data/extra/extra.qrc b/src/data/extra/extra.qrc index f167f2a6..f9675e01 100644 --- a/src/data/extra/extra.qrc +++ b/src/data/extra/extra.qrc @@ -16,6 +16,7 @@ docs/zh_CN/features_tips.txt web/markdown-viewer-template.html web/markdown-export-template.html + web/pdf-viewer-template.html web/css/user.css web/css/globalstyles.css web/css/markdownit.css @@ -29,7 +30,9 @@ web/js/lrucache.js web/js/graphcache.js web/js/graphpreviewer.js - web/js/vnotex.js + web/js/markdownviewercore.js + web/js/pdfviewercore.js + web/js/vxcore.js web/js/vxworker.js web/js/graphrenderer.js web/js/markdownviewer.js @@ -80,6 +83,13 @@ web/js/markjs.js web/js/mind-elixir/MindElixir.min.js web/js/mind-elixir/painter.js + web/js/pdf.js/pdf.worker.min.js + web/js/pdf.js/pdf.min.js + web/js/pdf.js/pdf_viewer.js + web/js/pdf.js/pdf_viewer.css + web/js/pdf.js/images/shadow.png + web/js/pdf.js/images/loading-icon.gif + web/js/pdfviewer.js dicts/en_US.aff dicts/en_US.dic themes/native/text-editor.theme diff --git a/src/data/extra/web/js/crosscopy.js b/src/data/extra/web/js/crosscopy.js index ca376afb..384848cf 100644 --- a/src/data/extra/web/js/crosscopy.js +++ b/src/data/extra/web/js/crosscopy.js @@ -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. diff --git a/src/data/extra/web/js/easyaccess.js b/src/data/extra/web/js/easyaccess.js index f4843cfa..9382552c 100644 --- a/src/data/extra/web/js/easyaccess.js +++ b/src/data/extra/web/js/easyaccess.js @@ -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(); } diff --git a/src/data/extra/web/js/flowchartjs.js b/src/data/extra/web/js/flowchartjs.js index 1218be25..b1985963 100644 --- a/src/data/extra/web/js/flowchartjs.js +++ b/src/data/extra/web/js/flowchartjs.js @@ -110,4 +110,4 @@ class FlowchartJs extends GraphRenderer { } } -window.vnotex.registerWorker(new FlowchartJs()); +window.vxcore.registerWorker(new FlowchartJs()); diff --git a/src/data/extra/web/js/graphpreviewer.js b/src/data/extra/web/js/graphpreviewer.js index 226c7bf3..67f26313 100644 --- a/src/data/extra/web/js/graphpreviewer.js +++ b/src/data/extra/web/js/graphpreviewer.js @@ -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); } } diff --git a/src/data/extra/web/js/graphrenderer.js b/src/data/extra/web/js/graphrenderer.js index a33022f6..1b695d73 100644 --- a/src/data/extra/web/js/graphrenderer.js +++ b/src/data/extra/web/js/graphrenderer.js @@ -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(); } diff --git a/src/data/extra/web/js/graphviz.js b/src/data/extra/web/js/graphviz.js index 062211ff..4e2a2c6a 100644 --- a/src/data/extra/web/js/graphviz.js +++ b/src/data/extra/web/js/graphviz.js @@ -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()); diff --git a/src/data/extra/web/js/imageviewer.js b/src/data/extra/web/js/imageviewer.js index 4428dd6c..fde6a1c8 100644 --- a/src/data/extra/web/js/imageviewer.js +++ b/src/data/extra/web/js/imageviewer.js @@ -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'); diff --git a/src/data/extra/web/js/markdownit.js b/src/data/extra/web/js/markdownit.js index ae6e80c2..4dec505f 100644 --- a/src/data/extra/web/js/markdownit.js +++ b/src/data/extra/web/js/markdownit.js @@ -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)); diff --git a/src/data/extra/web/js/markdownviewer.js b/src/data/extra/web/js/markdownviewer.js index f9462ad0..ed829ae9 100644 --- a/src/data/extra/web/js/markdownviewer.js +++ b/src/data/extra/web/js/markdownviewer.js @@ -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(); } }); diff --git a/src/data/extra/web/js/vnotex.js b/src/data/extra/web/js/markdownviewercore.js similarity index 77% rename from src/data/extra/web/js/vnotex.js rename to src/data/extra/web/js/markdownviewercore.js index 4833e951..7cc013a3 100644 --- a/src/data/extra/web/js/vnotex.js +++ b/src/data/extra/web/js/markdownviewercore.js @@ -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(); diff --git a/src/data/extra/web/js/mathjax.js b/src/data/extra/web/js/mathjax.js index 7db3e313..5379e4e3 100644 --- a/src/data/extra/web/js/mathjax.js +++ b/src/data/extra/web/js/mathjax.js @@ -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()); diff --git a/src/data/extra/web/js/mermaid.js b/src/data/extra/web/js/mermaid.js index becdd137..e477aa01 100644 --- a/src/data/extra/web/js/mermaid.js +++ b/src/data/extra/web/js/mermaid.js @@ -122,4 +122,4 @@ class Mermaid extends GraphRenderer { } } -window.vnotex.registerWorker(new Mermaid()); +window.vxcore.registerWorker(new Mermaid()); diff --git a/src/data/extra/web/js/pdf.js/README.md b/src/data/extra/web/js/pdf.js/README.md new file mode 100644 index 00000000..adab26fa --- /dev/null +++ b/src/data/extra/web/js/pdf.js/README.md @@ -0,0 +1,3 @@ +https://github.com/mozilla/pdf.js +Legacy version: https://unpkg.com/pdfjs-dist/ +v3.1.81 diff --git a/src/data/extra/web/js/pdf.js/images/loading-icon.gif b/src/data/extra/web/js/pdf.js/images/loading-icon.gif new file mode 100644 index 00000000..1c72ebb5 Binary files /dev/null and b/src/data/extra/web/js/pdf.js/images/loading-icon.gif differ diff --git a/src/data/extra/web/js/pdf.js/images/shadow.png b/src/data/extra/web/js/pdf.js/images/shadow.png new file mode 100644 index 00000000..a00061ac Binary files /dev/null and b/src/data/extra/web/js/pdf.js/images/shadow.png differ diff --git a/src/data/extra/web/js/pdf.js/pdf.min.js b/src/data/extra/web/js/pdf.js/pdf.min.js new file mode 100644 index 00000000..ef6fa63e --- /dev/null +++ b/src/data/extra/web/js/pdf.js/pdf.min.js @@ -0,0 +1,22 @@ +/** + * @licstart The following is the entire license notice for the + * JavaScript code in this page + * + * Copyright 2022 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @licend The above is the entire license notice for the + * JavaScript code in this page + */ +!function webpackUniversalModuleDefinition(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("pdfjs-dist/build/pdf",[],e):"object"==typeof exports?exports["pdfjs-dist/build/pdf"]=e():t["pdfjs-dist/build/pdf"]=t.pdfjsLib=e()}(globalThis,(()=>(()=>{var __webpack_modules__=[,(t,e,i)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.VerbosityLevel=e.Util=e.UnknownErrorException=e.UnexpectedResponseException=e.UNSUPPORTED_FEATURES=e.TextRenderingMode=e.StreamType=e.RenderingIntentFlag=e.PermissionFlag=e.PasswordResponses=e.PasswordException=e.PageActionEventType=e.OPS=e.MissingPDFException=e.LINE_FACTOR=e.LINE_DESCENT_FACTOR=e.InvalidPDFException=e.ImageKind=e.IDENTITY_MATRIX=e.FormatError=e.FontType=e.FeatureTest=e.FONT_IDENTITY_MATRIX=e.DocumentActionEventType=e.CMapCompressionType=e.BaseException=e.BASELINE_FACTOR=e.AnnotationType=e.AnnotationStateModelType=e.AnnotationReviewState=e.AnnotationReplyType=e.AnnotationMode=e.AnnotationMarkedState=e.AnnotationFlag=e.AnnotationFieldFlag=e.AnnotationEditorType=e.AnnotationEditorPrefix=e.AnnotationEditorParamsType=e.AnnotationBorderStyleType=e.AnnotationActionEventType=e.AbortException=void 0;e.arrayByteLength=arrayByteLength;e.arraysToBytes=function arraysToBytes(t){const e=t.length;if(1===e&&t[0]instanceof Uint8Array)return t[0];let i=0;for(let s=0;se});t.promise=new Promise((function(i,s){t.resolve=function(t){e=!0;i(t)};t.reject=function(t){e=!0;s(t)}}));return t};e.createValidAbsoluteUrl=function createValidAbsoluteUrl(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(!t)return null;try{if(i&&"string"==typeof t){if(i.addDefaultProtocol&&t.startsWith("www.")){const e=t.match(/\./g);e&&e.length>=2&&(t=`http://${t}`)}if(i.tryConvertEncoding)try{t=stringToUTF8String(t)}catch(t){}}const s=e?new URL(t,e):new URL(t);if(_isValidProtocol(s))return s}catch(t){}return null};e.getModificationDate=function getModificationDate(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:new Date;const e=[t.getUTCFullYear().toString(),(t.getUTCMonth()+1).toString().padStart(2,"0"),t.getUTCDate().toString().padStart(2,"0"),t.getUTCHours().toString().padStart(2,"0"),t.getUTCMinutes().toString().padStart(2,"0"),t.getUTCSeconds().toString().padStart(2,"0")];return e.join("")};e.getVerbosityLevel=function getVerbosityLevel(){return r};e.info=function info(t){r>=s.INFOS&&console.log(`Info: ${t}`)};e.isArrayBuffer=function isArrayBuffer(t){return"object"==typeof t&&null!==t&&void 0!==t.byteLength};e.isArrayEqual=function isArrayEqual(t,e){if(t.length!==e.length)return!1;for(let i=0,s=t.length;i>24&255,t>>16&255,t>>8&255,255&t)};e.stringToBytes=stringToBytes;e.stringToPDFString=function stringToPDFString(t){if(t[0]>="ï"){let e;"þ"===t[0]&&"ÿ"===t[1]?e="utf-16be":"ÿ"===t[0]&&"þ"===t[1]?e="utf-16le":"ï"===t[0]&&"»"===t[1]&&"¿"===t[2]&&(e="utf-8");if(e)try{const i=new TextDecoder(e,{fatal:!0}),s=stringToBytes(t);return i.decode(s)}catch(t){warn(`stringToPDFString: "${t}".`)}}const e=[];for(let i=0,s=t.length;i=s.WARNINGS&&console.log(`Warning: ${t}`)}function unreachable(t){throw new Error(t)}function _isValidProtocol(t){if(!t)return!1;switch(t.protocol){case"http:":case"https:":case"ftp:":case"mailto:":case"tel:":return!0;default:return!1}}function shadow(t,e,i){let s=arguments.length>3&&void 0!==arguments[3]&&arguments[3];Object.defineProperty(t,e,{value:i,enumerable:!s,configurable:!0,writable:!1});return i}const a=function BaseExceptionClosure(){function BaseException(t,e){this.constructor===BaseException&&unreachable("Cannot initialize BaseException.");this.message=t;this.name=e}BaseException.prototype=new Error;BaseException.constructor=BaseException;return BaseException}();e.BaseException=a;e.PasswordException=class PasswordException extends a{constructor(t,e){super(t,"PasswordException");this.code=e}};e.UnknownErrorException=class UnknownErrorException extends a{constructor(t,e){super(t,"UnknownErrorException");this.details=e}};e.InvalidPDFException=class InvalidPDFException extends a{constructor(t){super(t,"InvalidPDFException")}};e.MissingPDFException=class MissingPDFException extends a{constructor(t){super(t,"MissingPDFException")}};e.UnexpectedResponseException=class UnexpectedResponseException extends a{constructor(t,e){super(t,"UnexpectedResponseException");this.status=e}};e.FormatError=class FormatError extends a{constructor(t){super(t,"FormatError")}};e.AbortException=class AbortException extends a{constructor(t){super(t,"AbortException")}};function stringToBytes(t){"string"!=typeof t&&unreachable("Invalid argument for stringToBytes");const e=t.length,i=new Uint8Array(e);for(let s=0;st.toString(16).padStart(2,"0")));class Util{static makeHexColor(t,e,i){return`#${n[t]}${n[e]}${n[i]}`}static scaleMinMax(t,e){let i;if(t[0]){if(t[0]<0){i=e[0];e[0]=e[1];e[1]=i}e[0]*=t[0];e[1]*=t[0];if(t[3]<0){i=e[2];e[2]=e[3];e[3]=i}e[2]*=t[3];e[3]*=t[3]}else{i=e[0];e[0]=e[2];e[2]=i;i=e[1];e[1]=e[3];e[3]=i;if(t[1]<0){i=e[2];e[2]=e[3];e[3]=i}e[2]*=t[1];e[3]*=t[1];if(t[2]<0){i=e[0];e[0]=e[1];e[1]=i}e[0]*=t[2];e[1]*=t[2]}e[0]+=t[4];e[1]+=t[4];e[2]+=t[5];e[3]+=t[5]}static transform(t,e){return[t[0]*e[0]+t[2]*e[1],t[1]*e[0]+t[3]*e[1],t[0]*e[2]+t[2]*e[3],t[1]*e[2]+t[3]*e[3],t[0]*e[4]+t[2]*e[5]+t[4],t[1]*e[4]+t[3]*e[5]+t[5]]}static applyTransform(t,e){return[t[0]*e[0]+t[1]*e[2]+e[4],t[0]*e[1]+t[1]*e[3]+e[5]]}static applyInverseTransform(t,e){const i=e[0]*e[3]-e[1]*e[2];return[(t[0]*e[3]-t[1]*e[2]+e[2]*e[5]-e[4]*e[3])/i,(-t[0]*e[1]+t[1]*e[0]+e[4]*e[1]-e[5]*e[0])/i]}static getAxialAlignedBoundingBox(t,e){const i=Util.applyTransform(t,e),s=Util.applyTransform(t.slice(2,4),e),r=Util.applyTransform([t[0],t[3]],e),a=Util.applyTransform([t[2],t[1]],e);return[Math.min(i[0],s[0],r[0],a[0]),Math.min(i[1],s[1],r[1],a[1]),Math.max(i[0],s[0],r[0],a[0]),Math.max(i[1],s[1],r[1],a[1])]}static inverseTransform(t){const e=t[0]*t[3]-t[1]*t[2];return[t[3]/e,-t[1]/e,-t[2]/e,t[0]/e,(t[2]*t[5]-t[4]*t[3])/e,(t[4]*t[1]-t[5]*t[0])/e]}static singularValueDecompose2dScale(t){const e=[t[0],t[2],t[1],t[3]],i=t[0]*e[0]+t[1]*e[2],s=t[0]*e[1]+t[1]*e[3],r=t[2]*e[0]+t[3]*e[2],a=t[2]*e[1]+t[3]*e[3],n=(i+a)/2,o=Math.sqrt((i+a)**2-4*(i*a-r*s))/2,l=n+o||1,c=n-o||1;return[Math.sqrt(l),Math.sqrt(c)]}static normalizeRect(t){const e=t.slice(0);if(t[0]>t[2]){e[0]=t[2];e[2]=t[0]}if(t[1]>t[3]){e[1]=t[3];e[3]=t[1]}return e}static intersect(t,e){const i=Math.max(Math.min(t[0],t[2]),Math.min(e[0],e[2])),s=Math.min(Math.max(t[0],t[2]),Math.max(e[0],e[2]));if(i>s)return null;const r=Math.max(Math.min(t[1],t[3]),Math.min(e[1],e[3])),a=Math.min(Math.max(t[1],t[3]),Math.max(e[1],e[3]));return r>a?null:[i,r,s,a]}static bezierBoundingBox(t,e,i,s,r,a,n,o){const l=[],c=[[],[]];let d,h,u,p,f,g,m,v;for(let c=0;c<2;++c){if(0===c){h=6*t-12*i+6*r;d=-3*t+9*i-9*r+3*n;u=3*i-3*t}else{h=6*e-12*s+6*a;d=-3*e+9*s-9*a+3*o;u=3*s-3*e}if(Math.abs(d)<1e-12){if(Math.abs(h)<1e-12)continue;p=-u/h;0{"use strict";var s=i(3);!function checkNodeBtoa(){!globalThis.btoa&&s.isNodeJS&&(globalThis.btoa=function(t){return Buffer.from(t,"binary").toString("base64")})}();!function checkNodeAtob(){!globalThis.atob&&s.isNodeJS&&(globalThis.atob=function(t){return Buffer.from(t,"base64").toString("binary")})}();!function checkDOMMatrix(){!globalThis.DOMMatrix&&s.isNodeJS&&(globalThis.DOMMatrix=require("canvas").DOMMatrix)}();!function checkReadableStream(){!globalThis.ReadableStream&&s.isNodeJS&&(globalThis.ReadableStream=require("web-streams-polyfill/dist/ponyfill.js").ReadableStream)}();!function checkArrayAt(){Array.prototype.at||i(4)}();!function checkTypedArrayAt(){Uint8Array.prototype.at||i(78)}();!function checkStructuredClone(){globalThis.structuredClone||i(88)}()},(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});e.isNodeJS=void 0;const i=!("object"!=typeof process||process+""!="[object process]"||process.versions.nw||process.versions.electron&&process.type&&"browser"!==process.type);e.isNodeJS=i},(t,e,i)=>{i(5);var s=i(77);t.exports=s("Array","at")},(t,e,i)=>{"use strict";var s=i(6),r=i(43),a=i(67),n=i(65),o=i(72);s({target:"Array",proto:!0},{at:function at(t){var e=r(this),i=a(e),s=n(t),o=s>=0?s:i+s;return o<0||o>=i?void 0:e[o]}});o("at")},(t,e,i)=>{var s=i(7),r=i(8).f,a=i(47),n=i(51),o=i(41),l=i(59),c=i(71);t.exports=function(t,e){var i,d,h,u,p,f=t.target,g=t.global,m=t.stat;if(i=g?s:m?s[f]||o(f,{}):(s[f]||{}).prototype)for(d in e){u=e[d];h=t.dontCallGetSet?(p=r(i,d))&&p.value:i[d];if(!c(g?d:f+(m?".":"#")+d,t.forced)&&void 0!==h){if(typeof u==typeof h)continue;l(u,h)}(t.sham||h&&h.sham)&&a(u,"sham",!0);n(i,d,u,t)}}},t=>{var check=function(t){return t&&t.Math==Math&&t};t.exports=check("object"==typeof globalThis&&globalThis)||check("object"==typeof window&&window)||check("object"==typeof self&&self)||check("object"==typeof global&&global)||function(){return this}()||Function("return this")()},(t,e,i)=>{var s=i(9),r=i(11),a=i(13),n=i(14),o=i(15),l=i(21),c=i(42),d=i(45),h=Object.getOwnPropertyDescriptor;e.f=s?h:function getOwnPropertyDescriptor(t,e){t=o(t);e=l(e);if(d)try{return h(t,e)}catch(t){}if(c(t,e))return n(!r(a.f,t,e),t[e])}},(t,e,i)=>{var s=i(10);t.exports=!s((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},t=>{t.exports=function(t){try{return!!t()}catch(t){return!0}}},(t,e,i)=>{var s=i(12),r=Function.prototype.call;t.exports=s?r.bind(r):function(){return r.apply(r,arguments)}},(t,e,i)=>{var s=i(10);t.exports=!s((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},(t,e)=>{"use strict";var i={}.propertyIsEnumerable,s=Object.getOwnPropertyDescriptor,r=s&&!i.call({1:2},1);e.f=r?function propertyIsEnumerable(t){var e=s(this,t);return!!e&&e.enumerable}:i},t=>{t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},(t,e,i)=>{var s=i(16),r=i(19);t.exports=function(t){return s(r(t))}},(t,e,i)=>{var s=i(17),r=i(10),a=i(18),n=Object,o=s("".split);t.exports=r((function(){return!n("z").propertyIsEnumerable(0)}))?function(t){return"String"==a(t)?o(t,""):n(t)}:n},(t,e,i)=>{var s=i(12),r=Function.prototype,a=r.call,n=s&&r.bind.bind(a,a);t.exports=s?n:function(t){return function(){return a.apply(t,arguments)}}},(t,e,i)=>{var s=i(17),r=s({}.toString),a=s("".slice);t.exports=function(t){return a(r(t),8,-1)}},(t,e,i)=>{var s=i(20),r=TypeError;t.exports=function(t){if(s(t))throw r("Can't call method on "+t);return t}},t=>{t.exports=function(t){return null==t}},(t,e,i)=>{var s=i(22),r=i(26);t.exports=function(t){var e=s(t,"string");return r(e)?e:e+""}},(t,e,i)=>{var s=i(11),r=i(23),a=i(26),n=i(33),o=i(36),l=i(37),c=TypeError,d=l("toPrimitive");t.exports=function(t,e){if(!r(t)||a(t))return t;var i,l=n(t,d);if(l){void 0===e&&(e="default");i=s(l,t,e);if(!r(i)||a(i))return i;throw c("Can't convert object to primitive value")}void 0===e&&(e="number");return o(t,e)}},(t,e,i)=>{var s=i(24),r=i(25),a=r.all;t.exports=r.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:s(t)||t===a}:function(t){return"object"==typeof t?null!==t:s(t)}},(t,e,i)=>{var s=i(25),r=s.all;t.exports=s.IS_HTMLDDA?function(t){return"function"==typeof t||t===r}:function(t){return"function"==typeof t}},t=>{var e="object"==typeof document&&document.all,i=void 0===e&&void 0!==e;t.exports={all:e,IS_HTMLDDA:i}},(t,e,i)=>{var s=i(27),r=i(24),a=i(28),n=i(29),o=Object;t.exports=n?function(t){return"symbol"==typeof t}:function(t){var e=s("Symbol");return r(e)&&a(e.prototype,o(t))}},(t,e,i)=>{var s=i(7),r=i(24),aFunction=function(t){return r(t)?t:void 0};t.exports=function(t,e){return arguments.length<2?aFunction(s[t]):s[t]&&s[t][e]}},(t,e,i)=>{var s=i(17);t.exports=s({}.isPrototypeOf)},(t,e,i)=>{var s=i(30);t.exports=s&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},(t,e,i)=>{var s=i(31),r=i(10);t.exports=!!Object.getOwnPropertySymbols&&!r((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&s&&s<41}))},(t,e,i)=>{var s,r,a=i(7),n=i(32),o=a.process,l=a.Deno,c=o&&o.versions||l&&l.version,d=c&&c.v8;d&&(r=(s=d.split("."))[0]>0&&s[0]<4?1:+(s[0]+s[1]));!r&&n&&(!(s=n.match(/Edge\/(\d+)/))||s[1]>=74)&&(s=n.match(/Chrome\/(\d+)/))&&(r=+s[1]);t.exports=r},(t,e,i)=>{var s=i(27);t.exports=s("navigator","userAgent")||""},(t,e,i)=>{var s=i(34),r=i(20);t.exports=function(t,e){var i=t[e];return r(i)?void 0:s(i)}},(t,e,i)=>{var s=i(24),r=i(35),a=TypeError;t.exports=function(t){if(s(t))return t;throw a(r(t)+" is not a function")}},t=>{var e=String;t.exports=function(t){try{return e(t)}catch(t){return"Object"}}},(t,e,i)=>{var s=i(11),r=i(24),a=i(23),n=TypeError;t.exports=function(t,e){var i,o;if("string"===e&&r(i=t.toString)&&!a(o=s(i,t)))return o;if(r(i=t.valueOf)&&!a(o=s(i,t)))return o;if("string"!==e&&r(i=t.toString)&&!a(o=s(i,t)))return o;throw n("Can't convert object to primitive value")}},(t,e,i)=>{var s=i(7),r=i(38),a=i(42),n=i(44),o=i(30),l=i(29),c=r("wks"),d=s.Symbol,h=d&&d.for,u=l?d:d&&d.withoutSetter||n;t.exports=function(t){if(!a(c,t)||!o&&"string"!=typeof c[t]){var e="Symbol."+t;o&&a(d,t)?c[t]=d[t]:c[t]=l&&h?h(e):u(e)}return c[t]}},(t,e,i)=>{var s=i(39),r=i(40);(t.exports=function(t,e){return r[t]||(r[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.26.1",mode:s?"pure":"global",copyright:"© 2014-2022 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.26.1/LICENSE",source:"https://github.com/zloirock/core-js"})},t=>{t.exports=!1},(t,e,i)=>{var s=i(7),r=i(41),a="__core-js_shared__",n=s[a]||r(a,{});t.exports=n},(t,e,i)=>{var s=i(7),r=Object.defineProperty;t.exports=function(t,e){try{r(s,t,{value:e,configurable:!0,writable:!0})}catch(i){s[t]=e}return e}},(t,e,i)=>{var s=i(17),r=i(43),a=s({}.hasOwnProperty);t.exports=Object.hasOwn||function hasOwn(t,e){return a(r(t),e)}},(t,e,i)=>{var s=i(19),r=Object;t.exports=function(t){return r(s(t))}},(t,e,i)=>{var s=i(17),r=0,a=Math.random(),n=s(1..toString);t.exports=function(t){return"Symbol("+(void 0===t?"":t)+")_"+n(++r+a,36)}},(t,e,i)=>{var s=i(9),r=i(10),a=i(46);t.exports=!s&&!r((function(){return 7!=Object.defineProperty(a("div"),"a",{get:function(){return 7}}).a}))},(t,e,i)=>{var s=i(7),r=i(23),a=s.document,n=r(a)&&r(a.createElement);t.exports=function(t){return n?a.createElement(t):{}}},(t,e,i)=>{var s=i(9),r=i(48),a=i(14);t.exports=s?function(t,e,i){return r.f(t,e,a(1,i))}:function(t,e,i){t[e]=i;return t}},(t,e,i)=>{var s=i(9),r=i(45),a=i(49),n=i(50),o=i(21),l=TypeError,c=Object.defineProperty,d=Object.getOwnPropertyDescriptor,h="enumerable",u="configurable",p="writable";e.f=s?a?function defineProperty(t,e,i){n(t);e=o(e);n(i);if("function"==typeof t&&"prototype"===e&&"value"in i&&p in i&&!i.writable){var s=d(t,e);if(s&&s.writable){t[e]=i.value;i={configurable:u in i?i.configurable:s.configurable,enumerable:h in i?i.enumerable:s.enumerable,writable:!1}}}return c(t,e,i)}:c:function defineProperty(t,e,i){n(t);e=o(e);n(i);if(r)try{return c(t,e,i)}catch(t){}if("get"in i||"set"in i)throw l("Accessors not supported");"value"in i&&(t[e]=i.value);return t}},(t,e,i)=>{var s=i(9),r=i(10);t.exports=s&&r((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype}))},(t,e,i)=>{var s=i(23),r=String,a=TypeError;t.exports=function(t){if(s(t))return t;throw a(r(t)+" is not an object")}},(t,e,i)=>{var s=i(24),r=i(48),a=i(52),n=i(41);t.exports=function(t,e,i,o){o||(o={});var l=o.enumerable,c=void 0!==o.name?o.name:e;s(i)&&a(i,c,o);if(o.global)l?t[e]=i:n(e,i);else{try{o.unsafe?t[e]&&(l=!0):delete t[e]}catch(t){}l?t[e]=i:r.f(t,e,{value:i,enumerable:!1,configurable:!o.nonConfigurable,writable:!o.nonWritable})}return t}},(t,e,i)=>{var s=i(10),r=i(24),a=i(42),n=i(9),o=i(53).CONFIGURABLE,l=i(54),c=i(55),d=c.enforce,h=c.get,u=Object.defineProperty,p=n&&!s((function(){return 8!==u((function(){}),"length",{value:8}).length})),f=String(String).split("String"),g=t.exports=function(t,e,i){"Symbol("===String(e).slice(0,7)&&(e="["+String(e).replace(/^Symbol\(([^)]*)\)/,"$1")+"]");i&&i.getter&&(e="get "+e);i&&i.setter&&(e="set "+e);(!a(t,"name")||o&&t.name!==e)&&(n?u(t,"name",{value:e,configurable:!0}):t.name=e);p&&i&&a(i,"arity")&&t.length!==i.arity&&u(t,"length",{value:i.arity});try{i&&a(i,"constructor")&&i.constructor?n&&u(t,"prototype",{writable:!1}):t.prototype&&(t.prototype=void 0)}catch(t){}var s=d(t);a(s,"source")||(s.source=f.join("string"==typeof e?e:""));return t};Function.prototype.toString=g((function toString(){return r(this)&&h(this).source||l(this)}),"toString")},(t,e,i)=>{var s=i(9),r=i(42),a=Function.prototype,n=s&&Object.getOwnPropertyDescriptor,o=r(a,"name"),l=o&&"something"===function something(){}.name,c=o&&(!s||s&&n(a,"name").configurable);t.exports={EXISTS:o,PROPER:l,CONFIGURABLE:c}},(t,e,i)=>{var s=i(17),r=i(24),a=i(40),n=s(Function.toString);r(a.inspectSource)||(a.inspectSource=function(t){return n(t)});t.exports=a.inspectSource},(t,e,i)=>{var s,r,a,n=i(56),o=i(7),l=i(23),c=i(47),d=i(42),h=i(40),u=i(57),p=i(58),f="Object already initialized",g=o.TypeError,m=o.WeakMap;if(n||h.state){var v=h.state||(h.state=new m);v.get=v.get;v.has=v.has;v.set=v.set;s=function(t,e){if(v.has(t))throw g(f);e.facade=t;v.set(t,e);return e};r=function(t){return v.get(t)||{}};a=function(t){return v.has(t)}}else{var _=u("state");p[_]=!0;s=function(t,e){if(d(t,_))throw g(f);e.facade=t;c(t,_,e);return e};r=function(t){return d(t,_)?t[_]:{}};a=function(t){return d(t,_)}}t.exports={set:s,get:r,has:a,enforce:function(t){return a(t)?r(t):s(t,{})},getterFor:function(t){return function(e){var i;if(!l(e)||(i=r(e)).type!==t)throw g("Incompatible receiver, "+t+" required");return i}}}},(t,e,i)=>{var s=i(7),r=i(24),a=s.WeakMap;t.exports=r(a)&&/native code/.test(String(a))},(t,e,i)=>{var s=i(38),r=i(44),a=s("keys");t.exports=function(t){return a[t]||(a[t]=r(t))}},t=>{t.exports={}},(t,e,i)=>{var s=i(42),r=i(60),a=i(8),n=i(48);t.exports=function(t,e,i){for(var o=r(e),l=n.f,c=a.f,d=0;d{var s=i(27),r=i(17),a=i(61),n=i(70),o=i(50),l=r([].concat);t.exports=s("Reflect","ownKeys")||function ownKeys(t){var e=a.f(o(t)),i=n.f;return i?l(e,i(t)):e}},(t,e,i)=>{var s=i(62),r=i(69).concat("length","prototype");e.f=Object.getOwnPropertyNames||function getOwnPropertyNames(t){return s(t,r)}},(t,e,i)=>{var s=i(17),r=i(42),a=i(15),n=i(63).indexOf,o=i(58),l=s([].push);t.exports=function(t,e){var i,s=a(t),c=0,d=[];for(i in s)!r(o,i)&&r(s,i)&&l(d,i);for(;e.length>c;)r(s,i=e[c++])&&(~n(d,i)||l(d,i));return d}},(t,e,i)=>{var s=i(15),r=i(64),a=i(67),createMethod=function(t){return function(e,i,n){var o,l=s(e),c=a(l),d=r(n,c);if(t&&i!=i){for(;c>d;)if((o=l[d++])!=o)return!0}else for(;c>d;d++)if((t||d in l)&&l[d]===i)return t||d||0;return!t&&-1}};t.exports={includes:createMethod(!0),indexOf:createMethod(!1)}},(t,e,i)=>{var s=i(65),r=Math.max,a=Math.min;t.exports=function(t,e){var i=s(t);return i<0?r(i+e,0):a(i,e)}},(t,e,i)=>{var s=i(66);t.exports=function(t){var e=+t;return e!=e||0===e?0:s(e)}},t=>{var e=Math.ceil,i=Math.floor;t.exports=Math.trunc||function trunc(t){var s=+t;return(s>0?i:e)(s)}},(t,e,i)=>{var s=i(68);t.exports=function(t){return s(t.length)}},(t,e,i)=>{var s=i(65),r=Math.min;t.exports=function(t){return t>0?r(s(t),9007199254740991):0}},t=>{t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},(t,e)=>{e.f=Object.getOwnPropertySymbols},(t,e,i)=>{var s=i(10),r=i(24),a=/#|\.prototype\./,isForced=function(t,e){var i=o[n(t)];return i==c||i!=l&&(r(e)?s(e):!!e)},n=isForced.normalize=function(t){return String(t).replace(a,".").toLowerCase()},o=isForced.data={},l=isForced.NATIVE="N",c=isForced.POLYFILL="P";t.exports=isForced},(t,e,i)=>{var s=i(37),r=i(73),a=i(48).f,n=s("unscopables"),o=Array.prototype;null==o[n]&&a(o,n,{configurable:!0,value:r(null)});t.exports=function(t){o[n][t]=!0}},(t,e,i)=>{var s,r=i(50),a=i(74),n=i(69),o=i(58),l=i(76),c=i(46),d=i(57),h=d("IE_PROTO"),EmptyConstructor=function(){},scriptTag=function(t){return" + + + + +
+
+
+ + diff --git a/src/export/webviewexporter.cpp b/src/export/webviewexporter.cpp index ce547db1..9635f36b 100644 --- a/src/export/webviewexporter.cpp +++ b/src/export/webviewexporter.cpp @@ -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) { diff --git a/src/widgets/editors/editormarkdownvieweradapter.cpp b/src/widgets/editors/editormarkdownvieweradapter.cpp deleted file mode 100644 index 0f49d555..00000000 --- a/src/widgets/editors/editormarkdownvieweradapter.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "editormarkdownvieweradapter.h" - -#include - -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; -} diff --git a/src/widgets/editors/editormarkdownvieweradapter.h b/src/widgets/editors/editormarkdownvieweradapter.h deleted file mode 100644 index 3bf2b618..00000000 --- a/src/widgets/editors/editormarkdownvieweradapter.h +++ /dev/null @@ -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 diff --git a/src/widgets/editors/pdfviewer.cpp b/src/widgets/editors/pdfviewer.cpp new file mode 100644 index 00000000..17e73718 --- /dev/null +++ b/src/widgets/editors/pdfviewer.cpp @@ -0,0 +1,28 @@ +#include "pdfviewer.h" + +#include + +#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; +} diff --git a/src/widgets/editors/pdfviewer.h b/src/widgets/editors/pdfviewer.h new file mode 100644 index 00000000..789518f4 --- /dev/null +++ b/src/widgets/editors/pdfviewer.h @@ -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 diff --git a/src/widgets/editors/pdfvieweradapter.cpp b/src/widgets/editors/pdfvieweradapter.cpp new file mode 100644 index 00000000..484560d8 --- /dev/null +++ b/src/widgets/editors/pdfvieweradapter.cpp @@ -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(); + } +} diff --git a/src/widgets/editors/pdfvieweradapter.h b/src/widgets/editors/pdfvieweradapter.h new file mode 100644 index 00000000..2b48f0ad --- /dev/null +++ b/src/widgets/editors/pdfvieweradapter.h @@ -0,0 +1,40 @@ +#ifndef PDFVIEWERADAPTER_H +#define PDFVIEWERADAPTER_H + +#include +#include +#include + +#include + +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> m_pendingActions; + }; +} + +#endif // PDFVIEWERADAPTER_H diff --git a/src/widgets/markdownviewwindow.cpp b/src/widgets/markdownviewwindow.cpp index 4bbb8ada..4a1d8090 100644 --- a/src/widgets/markdownviewwindow.cpp +++ b/src/widgets/markdownviewwindow.cpp @@ -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(m_viewer->adapter()); + return m_viewer->adapter(); } return nullptr; diff --git a/src/widgets/markdownviewwindow.h b/src/widgets/markdownviewwindow.h index 1e6f8087..eecbbe72 100644 --- a/src/widgets/markdownviewwindow.h +++ b/src/widgets/markdownviewwindow.h @@ -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. diff --git a/src/widgets/pdfviewwindow.cpp b/src/widgets/pdfviewwindow.cpp new file mode 100644 index 00000000..27451177 --- /dev/null +++ b/src/widgets/pdfviewwindow.cpp @@ -0,0 +1,166 @@ +#include "pdfviewwindow.h" + +#include +#include +#include +#include +#include +#include +#include + +#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 &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 &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(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; +} diff --git a/src/widgets/pdfviewwindow.h b/src/widgets/pdfviewwindow.h new file mode 100644 index 00000000..d73523de --- /dev/null +++ b/src/widgets/pdfviewwindow.h @@ -0,0 +1,73 @@ +#ifndef PDFVIEWWINDOW_H +#define PDFVIEWWINDOW_H + +#include "viewwindow.h" + +#include + +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 &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 &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 diff --git a/src/widgets/textviewwindow.cpp b/src/widgets/textviewwindow.cpp index 1b30562d..5deb9dbc 100644 --- a/src/widgets/textviewwindow.cpp +++ b/src/widgets/textviewwindow.cpp @@ -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); diff --git a/src/widgets/viewwindow.cpp b/src/widgets/viewwindow.cpp index 5169aa93..b75f8ab6 100644 --- a/src/widgets/viewwindow.cpp +++ b/src/widgets/viewwindow.cpp @@ -156,6 +156,12 @@ void ViewWindow::handleBufferChanged(const QSharedPointer &p emit bufferChanged(); } +void ViewWindow::handleBufferChangedInternal(const QSharedPointer &p_paras) +{ + Q_UNUSED(p_paras); + syncEditorFromBuffer(); +} + void ViewWindow::attachToBuffer(Buffer *p_buffer, const QSharedPointer &p_paras) { Q_ASSERT(p_buffer); diff --git a/src/widgets/viewwindow.h b/src/widgets/viewwindow.h index 853a9585..2154e019 100644 --- a/src/widgets/viewwindow.h +++ b/src/widgets/viewwindow.h @@ -167,7 +167,7 @@ namespace vnotex protected slots: // Handle current buffer change. - virtual void handleBufferChangedInternal(const QSharedPointer &p_paras) = 0; + virtual void handleBufferChangedInternal(const QSharedPointer &p_paras); // Handle all kinds of type action. virtual void handleTypeAction(TypeAction p_action); diff --git a/src/widgets/widgets.pri b/src/widgets/widgets.pri index 1240f494..c545ea83 100644 --- a/src/widgets/widgets.pri +++ b/src/widgets/widgets.pri @@ -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 \