Plugin metasystem

This commit is contained in:
Jakub Melka 2020-11-17 18:28:34 +01:00
parent 1189d864f6
commit 4c410374db
17 changed files with 529 additions and 8 deletions

View File

@ -1,4 +1,4 @@
# Copyright (C) 2018-2019 Jakub Melka
# Copyright (C) 2018-2020 Jakub Melka
#
# This file is part of PdfForQt.
#
@ -18,17 +18,19 @@
TEMPLATE = subdirs
SUBDIRS += \
PdfForQtLib \
CodeGenerator \
JBIG2_Viewer \
PdfExampleGenerator \
PdfForQtLib \
PdfTool \
UnitTests \
PdfForQtViewer
PdfForQtViewer \
PdfForQtViewerPlugins
UnitTests.depends = PdfForQtLib
PdfForQtViewer.depends = PdfForQtLib
JBIG2_Viewer.depends = PdfForQtLib
PDFExampleGenerator.depends = PdfForQtLib
PdfExampleGenerator.depends = PdfForQtLib
CodeGenerator.depends = PdfForQtLib
PdfTool.depends = PdfForQtLib
PdfForQtViewerPlugins.depends = PdfForQtLib

View File

@ -69,6 +69,7 @@ SOURCES += \
sources/pdfdocument.cpp \
sources/pdfdocumentreader.cpp \
sources/pdfpattern.cpp \
sources/pdfplugin.cpp \
sources/pdfprogress.cpp \
sources/pdfsecurityhandler.cpp \
sources/pdfsignaturehandler.cpp \
@ -130,6 +131,7 @@ HEADERS += \
sources/pdfdocument.h \
sources/pdfdocumentreader.h \
sources/pdfpattern.h \
sources/pdfplugin.h \
sources/pdfprogress.h \
sources/pdfsecurityhandler.h \
sources/pdfsignaturehandler.h \

View File

@ -0,0 +1,54 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of PdfForQt.
//
// PdfForQt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PdfForQt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
#include "pdfplugin.h"
namespace pdf
{
PDFPlugin::PDFPlugin(QObject* parent) :
QObject(parent)
{
}
void PDFPlugin::setWidget(PDFWidget* widget)
{
Q_UNUSED(widget)
}
void PDFPlugin::setDocument(const PDFModifiedDocument& document)
{
Q_UNUSED(document)
}
PDFPluginInfo PDFPluginInfo::loadFromJson(const QJsonObject* json)
{
PDFPluginInfo result;
QJsonObject metadata = json->value("MetaData").toObject();
result.name = metadata.value(QLatin1String("Name")).toString();
result.author = metadata.value(QLatin1String("Author")).toString();
result.version = metadata.value(QLatin1String("Version")).toString();
result.license = metadata.value(QLatin1String("License")).toString();
result.description = metadata.value(QLatin1String("Description")).toString();
return result;
}
} // namespace pdf

View File

@ -0,0 +1,55 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of PdfForQt.
//
// PdfForQt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PdfForQt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
#ifndef PDFPLUGIN_H
#define PDFPLUGIN_H
#include "pdfdocument.h"
#include <QObject>
#include <QJsonObject>
namespace pdf
{
class PDFWidget;
struct PDFFORQTLIBSHARED_EXPORT PDFPluginInfo
{
QString name;
QString author;
QString version;
QString license;
QString description;
static PDFPluginInfo loadFromJson(const QJsonObject* json);
};
using PDFPluginInfos = std::vector<PDFPluginInfo>;
class PDFFORQTLIBSHARED_EXPORT PDFPlugin : public QObject
{
Q_OBJECT
public:
explicit PDFPlugin(QObject* parent);
virtual void setWidget(PDFWidget* widget);
virtual void setDocument(const PDFModifiedDocument& document);
};
} // namespace pdf
#endif // PDFPLUGIN_H

View File

@ -86,6 +86,10 @@ application.files = $$DESTDIR/PdfForQtViewer.exe
application.path = $$DESTDIR/install
INSTALLS += application
plugins.files = $$files($$DESTDIR/pdfplugins/*.dll)
plugins.path = $$DESTDIR/install/pdfplugins
INSTALLS += plugins
RESOURCES += \
pdfforqtviewer.qrc

View File

@ -51,5 +51,6 @@
<file>resources/result-ok.svg</file>
<file>resources/result-warning.svg</file>
<file>resources/signature.svg</file>
<file>resources/plugins.svg</file>
</qresource>
</RCC>

View File

@ -63,6 +63,7 @@
#include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QPrintDialog>
#include <QtConcurrent/QtConcurrent>
#include <QPluginLoader>
#ifdef Q_OS_WIN
#include "Windows.h"
@ -312,6 +313,48 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
updateUI(true);
onViewerSettingsChanged();
updateActionsAvailability();
loadPlugins();
}
void PDFViewerMainWindow::loadPlugins()
{
QDir directory(QApplication::applicationDirPath() + "/pdfplugins");
QStringList availablePlugins = directory.entryList(QStringList("*.dll"));
for (const QString& availablePlugin : availablePlugins)
{
QString pluginFileName = directory.absoluteFilePath(availablePlugin);
QPluginLoader loader(pluginFileName);
if (loader.load())
{
QJsonObject metaData = loader.metaData();
m_plugins.emplace_back(pdf::PDFPluginInfo::loadFromJson(&metaData));
if (!m_enabledPlugins.contains(m_plugins.back().name))
{
loader.unload();
continue;
}
pdf::PDFPlugin* plugin = qobject_cast<pdf::PDFPlugin*>(loader.instance());
if (plugin)
{
m_loadedPlugins.push_back(std::make_pair(m_plugins.back(), plugin));
}
}
}
auto comparator = [](const std::pair<pdf::PDFPluginInfo, pdf::PDFPlugin*>& l, const std::pair<pdf::PDFPluginInfo, pdf::PDFPlugin*>& r)
{
return l.first.name < r.first.name;
};
std::sort(m_loadedPlugins.begin(), m_loadedPlugins.end(), comparator);
for (const auto& plugin : m_loadedPlugins)
{
plugin.second->setWidget(m_pdfWidget);
}
}
PDFViewerMainWindow::~PDFViewerMainWindow()
@ -711,6 +754,11 @@ void PDFViewerMainWindow::readSettings()
{
m_formManager->setAppearanceFlags(m_settings->getSettings().m_formAppearanceFlags);
}
// Load allowed plugins
settings.beginGroup("Plugins");
m_enabledPlugins = settings.value("EnabledPlugins").toStringList();
settings.endGroup();
}
void PDFViewerMainWindow::readActionSettings()
@ -767,6 +815,11 @@ void PDFViewerMainWindow::writeSettings()
settings.setValue("RecentFileList", m_recentFileManager->getRecentFiles());
settings.endGroup();
// Save allowed plugins
settings.beginGroup("Plugins");
settings.setValue("EnabledPlugins", m_enabledPlugins);
settings.endGroup();
// Save trusted certificates
m_certificateStore.saveDefaultUserCertificates();
}
@ -1296,9 +1349,13 @@ void PDFViewerMainWindow::on_actionOptions_triggered()
PDFViewerSettingsDialog::OtherSettings otherSettings;
otherSettings.maximumRecentFileCount = m_recentFileManager->getRecentFilesLimit();
PDFViewerSettingsDialog dialog(m_settings->getSettings(), m_settings->getColorManagementSystemSettings(), otherSettings, m_certificateStore, getActions(), m_CMSManager, this);
PDFViewerSettingsDialog dialog(m_settings->getSettings(), m_settings->getColorManagementSystemSettings(),
otherSettings, m_certificateStore, getActions(), m_CMSManager,
m_enabledPlugins, m_plugins, this);
if (dialog.exec() == QDialog::Accepted)
{
const bool pluginsChanged = m_enabledPlugins != dialog.getEnabledPlugins();
m_settings->setSettings(dialog.getSettings());
m_settings->setColorManagementSystemSettings(dialog.getCMSSettings());
m_CMSManager->setSettings(m_settings->getColorManagementSystemSettings());
@ -1306,8 +1363,14 @@ void PDFViewerMainWindow::on_actionOptions_triggered()
m_textToSpeech->setSettings(m_settings);
m_formManager->setAppearanceFlags(m_settings->getSettings().m_formAppearanceFlags);
m_certificateStore = dialog.getCertificateStore();
m_enabledPlugins = dialog.getEnabledPlugins();
updateMagnifierToolSettings();
updateUndoRedoSettings();
if (pluginsChanged)
{
QMessageBox::information(this, tr("Plugins"), tr("Plugin on/off state has been changed. Please restart application to apply settings."));
}
}
}

View File

@ -31,6 +31,7 @@
#include "pdfannotation.h"
#include "pdfform.h"
#include "pdfundoredomanager.h"
#include "pdfplugin.h"
#include <QFuture>
#include <QTreeView>
@ -151,6 +152,8 @@ private:
void setPageLayout(pdf::PageLayout pageLayout);
void updateFileInfo(const QString& fileName);
void loadPlugins();
std::vector<QAction*> getRenderingOptionActions() const;
QList<QAction*> getActions() const;
@ -198,6 +201,9 @@ private:
pdf::PDFFormManager* m_formManager;
PDFTextToSpeech* m_textToSpeech;
PDFUndoRedoManager* m_undoRedoManager;
QStringList m_enabledPlugins;
pdf::PDFPluginInfos m_plugins;
std::vector<std::pair<pdf::PDFPluginInfo, pdf::PDFPlugin*>> m_loadedPlugins;
};
} // namespace pdfviewer

View File

@ -41,7 +41,9 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
const pdf::PDFCertificateStore& certificateStore,
QList<QAction*> actions,
pdf::PDFCMSManager* cmsManager,
QWidget *parent) :
const QStringList& enabledPlugins,
const pdf::PDFPluginInfos& plugins,
QWidget* parent) :
QDialog(parent),
ui(new Ui::PDFViewerSettingsDialog),
m_settings(settings),
@ -50,6 +52,8 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
m_certificateStore(certificateStore),
m_actions(),
m_isLoadingData(false),
m_enabledPlugins(enabledPlugins),
m_plugins(plugins),
m_networkAccessManager(nullptr),
m_downloadCertificatesFromEUTLReply(nullptr)
{
@ -68,6 +72,7 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
new QListWidgetItem(QIcon(":/resources/speech.svg"), tr("Speech"), ui->optionsPagesWidget, SpeechSettings);
new QListWidgetItem(QIcon(":/resources/form-settings.svg"), tr("Forms"), ui->optionsPagesWidget, FormSettings);
new QListWidgetItem(QIcon(":/resources/signature.svg"), tr("Signature"), ui->optionsPagesWidget, SignatureSettings);
new QListWidgetItem(QIcon(":/resources/plugins.svg"), tr("Plugins"), ui->optionsPagesWidget, PluginsSettings);
ui->renderingEngineComboBox->addItem(tr("Software"), static_cast<int>(pdf::RendererEngine::Software));
ui->renderingEngineComboBox->addItem(tr("Hardware accelerated (OpenGL)"), static_cast<int>(pdf::RendererEngine::OpenGL));
@ -151,11 +156,13 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
}
connect(ui->trustedCertificateStoreTableWidget, &QTableWidget::itemSelectionChanged, this, &PDFViewerSettingsDialog::updateTrustedCertificatesTableActions);
connect(ui->pluginsTableWidget, &QTableWidget::itemSelectionChanged, this, &PDFViewerSettingsDialog::updatePluginInformation);
ui->optionsPagesWidget->setCurrentRow(0);
adjustSize();
loadData();
loadActionShortcutsTable();
loadPluginsTable();
updateTrustedCertificatesTable();
updateTrustedCertificatesTableActions();
}
@ -215,6 +222,10 @@ void PDFViewerSettingsDialog::on_optionsPagesWidget_currentItemChanged(QListWidg
ui->stackedWidget->setCurrentWidget(ui->signaturePage);
break;
case PluginsSettings:
ui->stackedWidget->setCurrentWidget(ui->pluginsPage);
break;
default:
Q_ASSERT(false);
break;
@ -676,6 +687,59 @@ bool PDFViewerSettingsDialog::saveActionShortcutsTable()
return true;
}
void PDFViewerSettingsDialog::loadPluginsTable()
{
ui->pluginsTableWidget->setRowCount(int(m_plugins.size()));
ui->pluginsTableWidget->setColumnCount(5);
ui->pluginsTableWidget->setHorizontalHeaderLabels({ tr("Active"), tr("Name"), tr("Author"), tr("Version"), tr("License") });
ui->pluginsTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->pluginsTableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
for (int i = 0; i < m_plugins.size(); ++i)
{
const pdf::PDFPluginInfo& plugin = m_plugins[i];
QTableWidgetItem* activeItem = new QTableWidgetItem(QString());
activeItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
activeItem->setCheckState((m_enabledPlugins.contains(plugin.name)) ? Qt::Checked : Qt::Unchecked);
ui->pluginsTableWidget->setItem(i, 0, activeItem);
ui->pluginsTableWidget->setItem(i, 1, new QTableWidgetItem(plugin.name));
ui->pluginsTableWidget->setItem(i, 2, new QTableWidgetItem(plugin.author));
ui->pluginsTableWidget->setItem(i, 3, new QTableWidgetItem(plugin.version));
ui->pluginsTableWidget->setItem(i, 4, new QTableWidgetItem(plugin.license));
}
}
void PDFViewerSettingsDialog::savePluginsTable()
{
QStringList enabledPlugins;
for (int i = 0; i < m_plugins.size(); ++i)
{
bool enabled = ui->pluginsTableWidget->item(i, 0)->data(Qt::CheckStateRole).toInt() == Qt::Checked;
if (enabled)
{
enabledPlugins << m_plugins[i].name;
}
}
m_enabledPlugins = qMove(enabledPlugins);
}
void PDFViewerSettingsDialog::updatePluginInformation()
{
QModelIndexList rows = ui->pluginsTableWidget->selectionModel()->selectedRows();
if (rows.size() == 1)
{
ui->pluginDescriptionLabel->setText(m_plugins.at(rows.front().row()).description);
}
else
{
ui->pluginDescriptionLabel->setText(QString());
}
}
void PDFViewerSettingsDialog::setSpeechEngine(const QString& engine)
{
if (m_currentSpeechEngine == engine)
@ -725,6 +789,7 @@ void PDFViewerSettingsDialog::accept()
if (saveActionShortcutsTable())
{
savePluginsTable();
QDialog::accept();
}
}

View File

@ -19,6 +19,7 @@
#define PDFVIEWERSETTINGSDIALOG_H
#include "pdfviewersettings.h"
#include "pdfplugin.h"
#include <QDialog>
@ -59,6 +60,8 @@ public:
const pdf::PDFCertificateStore& certificateStore,
QList<QAction*> actions,
pdf::PDFCMSManager* cmsManager,
const QStringList& enabledPlugins,
const pdf::PDFPluginInfos& plugins,
QWidget* parent);
virtual ~PDFViewerSettingsDialog() override;
@ -77,13 +80,15 @@ public:
UISettings,
SpeechSettings,
FormSettings,
SignatureSettings
SignatureSettings,
PluginsSettings
};
const PDFViewerSettings::Settings& getSettings() const { return m_settings; }
const pdf::PDFCMSSettings& getCMSSettings() const { return m_cmsSettings; }
const OtherSettings& getOtherSettings() const { return m_otherSettings; }
const pdf::PDFCertificateStore& getCertificateStore() const { return m_certificateStore; }
const QStringList& getEnabledPlugins() const { return m_enabledPlugins; }
private slots:
void on_optionsPagesWidget_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous);
@ -103,6 +108,10 @@ private:
void loadActionShortcutsTable();
bool saveActionShortcutsTable();
void loadPluginsTable();
void savePluginsTable();
void updatePluginInformation();
void setSpeechEngine(const QString& engine);
/// Returns true, if dialog can be closed. If not, then message is displayed
@ -118,6 +127,8 @@ private:
QStringList m_textToSpeechEngines;
QString m_currentSpeechEngine;
pdf::PDFCertificateStore m_certificateStore;
QStringList m_enabledPlugins;
pdf::PDFPluginInfos m_plugins;
QNetworkAccessManager* m_networkAccessManager;
QNetworkReply* m_downloadCertificatesFromEUTLReply;
};

View File

@ -26,7 +26,7 @@
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
<number>11</number>
</property>
<widget class="QWidget" name="enginePage">
<layout class="QVBoxLayout" name="enginePageLayout">
@ -1330,6 +1330,58 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="pluginsPage">
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="pluginsGroupBox">
<property name="title">
<string>Plugins</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9" stretch="3,0,1">
<item>
<widget class="QTableWidget" name="pluginsTableWidget">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="pluginDescriptionLabel">
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="30mm"
height="30mm"
viewBox="0 0 30 30"
version="1.1"
id="svg8"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="plugins.svg">
<defs
id="defs2">
<inkscape:path-effect
effect="spiro"
id="path-effect831"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6"
inkscape:cx="142.64708"
inkscape:cy="113.44001"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="3840"
inkscape:window-height="2035"
inkscape:window-x="-13"
inkscape:window-y="-13"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Jakub Melka</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Vrstva 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-267)">
<path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 11.646391,283.58184 v 0 0"
id="path837"
inkscape:connector-curvature="0" />
<g
aria-label="🔌"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
id="text4540">
<path
d="m 23.50126,284.47675 q 1.016992,0.95498 1.835547,2.05879 0.830957,1.10381 1.413867,2.34404 0.58291,1.22784 0.892969,2.56729 0.310058,1.33945 0.310058,2.75332 v 1.78594 h -6.238379 v -1.78594 q 0,-1.5751 -0.669726,-2.92695 -0.657324,-1.33946 -1.785938,-2.41846 h -1.302246 q -0.347265,0.24805 -0.756543,0.38447 -0.396875,0.13643 -0.830957,0.13643 -0.545703,0 -1.029394,-0.19844 -0.483692,-0.19844 -0.868164,-0.58291 l -4.254004,-4.254 q -0.148828,0.0248 -0.3100587,0.0496 -0.1488281,0.0124 -0.2976563,0.0124 -0.6325195,0 -1.1906249,-0.23565 -0.5457032,-0.24804 -0.9673828,-0.65732 -0.4092774,-0.40928 -0.6449219,-0.96738 -0.2356445,-0.55811 -0.2356445,-1.19063 0,-0.47129 0.1364258,-0.90537 0.1364257,-0.44648 0.4092773,-0.83096 l -5.0105468,-5.02295 7.1313475,-7.13134 5.0105473,5.01054 q 0.384472,-0.26045 0.830957,-0.40927 0.446484,-0.14883 0.917773,-0.14883 0.63252,0 1.178223,0.24804 0.558105,0.23565 0.967382,0.64493 0.409278,0.40927 0.644922,0.96738 0.248047,0.5457 0.248047,1.17822 0,0.16123 -0.02481,0.32246 -0.0124,0.14883 -0.03721,0.29766 l 4.266407,4.26641 q 0.781347,0.78134 0.781347,1.88515 0,0.43408 -0.136426,0.84336 -0.136425,0.39688 -0.384472,0.74414 z m -7.094141,3.13779 q 0.248047,0 0.446485,-0.16123 0.173632,-0.13642 0.396875,-0.34726 0.223242,-0.21084 0.446484,-0.44649 0.235645,-0.23564 0.446484,-0.45888 0.21084,-0.22324 0.372071,-0.38448 l 3.199804,-3.1998 q 0.21084,-0.21084 0.359668,-0.38447 0.161231,-0.18604 0.161231,-0.5085 0,-0.37207 -0.260449,-0.63252 l -5.159375,-5.15937 q 0.198437,-0.19844 0.322461,-0.42168 0.124023,-0.23565 0.124023,-0.5209 0,-0.26045 -0.09922,-0.49609 -0.09922,-0.23565 -0.272851,-0.40928 -0.161231,-0.18604 -0.396875,-0.28526 -0.223242,-0.0992 -0.496094,-0.0992 -0.520898,0 -0.892969,0.37207 -1.612304,1.6123 -3.187402,3.1998 -1.575098,1.5875 -3.1998047,3.1874 -0.3720703,0.37207 -0.3720703,0.90537 0,0.26045 0.099219,0.48369 0.099219,0.22325 0.2728515,0.39688 0.1736328,0.17363 0.396875,0.27285 0.2356445,0.0992 0.4960937,0.0992 0.285254,0 0.5333008,-0.11162 0.260449,-0.12402 0.434082,-0.33486 l 5.159375,5.15937 q 0.285254,0.28525 0.669726,0.28525 z m 7.094141,6.58565 h 2.678906 q 0,-1.32705 -0.322461,-2.57969 -0.310058,-1.24023 -0.905371,-2.36885 -0.58291,-1.12861 -1.413867,-2.1208 -0.818555,-1.00459 -1.823145,-1.83554 l -1.785937,1.77353 q 0.806152,0.66973 1.463476,1.47588 0.657325,0.79375 1.128614,1.69912 0.471289,0.90537 0.719336,1.89756 0.260449,1.00459 0.260449,2.05879 z m -18.7151366,-19.60811 4.2664062,4.27881 0.8929687,-0.89297 -4.2788085,-4.2788 z m 4.4524413,-4.45244 -0.8929687,0.89297 4.278809,4.26641 0.880566,-0.89297 z m 8.2847653,8.90489 q 0.260449,0 0.446485,0.18603 0.186035,0.18604 0.186035,0.44648 0,0.26045 -0.186035,0.44649 l -3.199805,3.1998 q -0.186035,0.18604 -0.446484,0.18604 -0.26045,0 -0.446485,-0.18604 -0.186035,-0.18603 -0.186035,-0.44648 0,-0.26045 0.186035,-0.44648 l 3.199805,-3.19981 q 0.186035,-0.18603 0.446484,-0.18603 z m -2.046386,5.61826 q 0,-0.26045 0.186035,-0.44649 l 3.199804,-3.1998 q 0.186036,-0.18604 0.446485,-0.18604 0.260449,0 0.434082,0.18604 0.186035,0.18603 0.186035,0.44648 0,0.27285 -0.173633,0.44649 l -3.199805,3.1998 q -0.186035,0.18604 -0.446484,0.18604 -0.260449,0 -0.446484,-0.18604 -0.186035,-0.18603 -0.186035,-0.44648 z"
style="stroke-width:0.26458332"
id="path4545"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -0,0 +1,7 @@
{
"Name" : "Dimensions",
"Author" : "Jakub Melka",
"Version" : "1.0.0",
"License" : "LGPL v3",
"Description" : "Measure distances, area, perimeter in a document page."
}

View File

@ -0,0 +1,42 @@
# Copyright (C) 2020 Jakub Melka
#
# This file is part of PdfForQt.
#
# PdfForQt is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PdfForQt is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
TEMPLATE = lib
DEFINES += DIMENSIONPLUGIN_LIBRARY
LIBS += -L$$OUT_PWD/../..
LIBS += -lPDFForQtLib
QMAKE_CXXFLAGS += /std:c++latest /utf-8
INCLUDEPATH += $$PWD/../../PDFForQtLib/Sources
DESTDIR = $$OUT_PWD/../../pdfplugins
CONFIG += c++11
SOURCES += \
dimensionsplugin.cpp
HEADERS += \
dimensionsplugin.h
CONFIG += force_debug_info
DISTFILES += \
DimensionsPlugin.json

View File

@ -0,0 +1,12 @@
#include "dimensionsplugin.h"
namespace pdfplugin
{
DimensionsPlugin::DimensionsPlugin() :
pdf::PDFPlugin(nullptr)
{
}
}

View File

@ -0,0 +1,22 @@
#ifndef DIMENSIONSPLUGIN_H
#define DIMENSIONSPLUGIN_H
#include "pdfplugin.h"
#include <QObject>
namespace pdfplugin
{
class DimensionsPlugin : public pdf::PDFPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "PdfForQt.DimensionsPlugin" FILE "DimensionsPlugin.json")
public:
DimensionsPlugin();
};
} // namespace pdfplugin
#endif // DIMENSIONSPLUGIN_H

View File

@ -0,0 +1,24 @@
# Copyright (C) 2020 Jakub Melka
#
# This file is part of PdfForQt.
#
# PdfForQt is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PdfForQt is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
TEMPLATE = subdirs
SUBDIRS += \
DimensionsPlugin