diff --git a/PdfForQtLib/PdfForQtLib.pro b/PdfForQtLib/PdfForQtLib.pro
index 9d1fd5e..3288f0a 100644
--- a/PdfForQtLib/PdfForQtLib.pro
+++ b/PdfForQtLib/PdfForQtLib.pro
@@ -43,6 +43,7 @@ DESTDIR = $$OUT_PWD/..
SOURCES += \
sources/pdfaction.cpp \
+ sources/pdfadvancedtools.cpp \
sources/pdfannotation.cpp \
sources/pdfblendfunction.cpp \
sources/pdfccittfaxdecoder.cpp \
@@ -101,6 +102,7 @@ SOURCES += \
HEADERS += \
sources/pdfaction.h \
+ sources/pdfadvancedtools.h \
sources/pdfannotation.h \
sources/pdfblendfunction.h \
sources/pdfccittfaxdecoder.h \
diff --git a/PdfForQtLib/sources/pdfadvancedtools.cpp b/PdfForQtLib/sources/pdfadvancedtools.cpp
new file mode 100644
index 0000000..782ff75
--- /dev/null
+++ b/PdfForQtLib/sources/pdfadvancedtools.cpp
@@ -0,0 +1,65 @@
+// 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 .
+
+#include "pdfadvancedtools.h"
+
+#include
+
+namespace pdf
+{
+
+PDFCreateStickyNoteTool::PDFCreateStickyNoteTool(PDFDrawWidgetProxy* proxy, PDFToolManager* toolManager, QActionGroup* actionGroup, QObject* parent) :
+ BaseClass(proxy, parent),
+ m_toolManager(toolManager),
+ m_actionGroup(actionGroup),
+ m_pickTool(nullptr)
+{
+ m_pickTool = new PDFPickTool(proxy, PDFPickTool::Mode::Points, this);
+ addTool(m_pickTool);
+ connect(m_pickTool, &PDFPickTool::pointPicked, this, &PDFCreateStickyNoteTool::onPointPicked);
+ connect(m_actionGroup, &QActionGroup::triggered, this, &PDFCreateStickyNoteTool::onActionTriggered);
+
+ updateActions();
+}
+
+void PDFCreateStickyNoteTool::updateActions()
+{
+ BaseClass::updateActions();
+
+ if (m_actionGroup)
+ {
+ const bool isEnabled = getDocument() && getDocument()->getStorage().getSecurityHandler()->isAllowed(PDFSecurityHandler::Permission::Modify);
+ m_actionGroup->setEnabled(isEnabled);
+
+ if (!isActive() && m_actionGroup->checkedAction())
+ {
+ m_actionGroup->checkedAction()->setChecked(false);
+ }
+ }
+}
+
+void PDFCreateStickyNoteTool::onActionTriggered(QAction* action)
+{
+ setActive(action && action->isChecked());
+}
+
+void PDFCreateStickyNoteTool::onPointPicked(PDFInteger pageIndex, QPointF pagePoint)
+{
+
+}
+
+} // namespace pdf
diff --git a/PdfForQtLib/sources/pdfadvancedtools.h b/PdfForQtLib/sources/pdfadvancedtools.h
new file mode 100644
index 0000000..8ce2cf8
--- /dev/null
+++ b/PdfForQtLib/sources/pdfadvancedtools.h
@@ -0,0 +1,56 @@
+// 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 .
+
+#ifndef PDFADVANCEDTOOLS_H
+#define PDFADVANCEDTOOLS_H
+
+#include "pdfwidgettool.h"
+#include "pdfannotation.h"
+
+class QActionGroup;
+
+namespace pdf
+{
+
+/// Tool that creates 'sticky note' annotations. Multiple types of sticky
+/// notes are available, user can select a type of sticky note. When
+/// user select a point, popup window appears and user can enter a text.
+class PDFFORQTLIBSHARED_EXPORT PDFCreateStickyNoteTool : public PDFWidgetTool
+{
+ Q_OBJECT
+
+private:
+ using BaseClass = PDFWidgetTool;
+
+public:
+ explicit PDFCreateStickyNoteTool(PDFDrawWidgetProxy* proxy, PDFToolManager* toolManager, QActionGroup* actionGroup, QObject* parent);
+
+protected:
+ virtual void updateActions() override;
+
+private:
+ void onActionTriggered(QAction* action);
+ void onPointPicked(PDFInteger pageIndex, QPointF pagePoint);
+
+ PDFToolManager* m_toolManager;
+ QActionGroup* m_actionGroup;
+ PDFPickTool* m_pickTool;
+};
+
+} // namespace pdf
+
+#endif // PDFADVANCEDTOOLS_H
diff --git a/PdfForQtLib/sources/pdfannotation.cpp b/PdfForQtLib/sources/pdfannotation.cpp
index 2f9a63d..ce9029b 100644
--- a/PdfForQtLib/sources/pdfannotation.cpp
+++ b/PdfForQtLib/sources/pdfannotation.cpp
@@ -1960,35 +1960,7 @@ void PDFTextAnnotation::draw(AnnotationDrawParameters& parameters) const
QFont font = QApplication::font();
font.setPixelSize(16.0);
- QString text = "?";
- if (m_iconName == "Comment")
- {
- text = QString::fromUtf16(u"\U0001F4AC");
- }
- else if (m_iconName == "Help")
- {
- text = "?";
- }
- else if (m_iconName == "Insert")
- {
- text = QString::fromUtf16(u"\u2380");
- }
- else if (m_iconName == "Key")
- {
- text = QString::fromUtf16(u"\U0001F511");
- }
- else if (m_iconName == "NewParagraph")
- {
- text = QString::fromUtf16(u"\u2606");
- }
- else if (m_iconName == "Note")
- {
- text = QString::fromUtf16(u"\u266A");
- }
- else if (m_iconName == "Paragraph")
- {
- text = QString::fromUtf16(u"\u00B6");
- }
+ QString text = getTextForIcon(m_iconName);
QPainterPath textPath;
textPath.addText(0.0, 0.0, font, text);
@@ -2006,6 +1978,71 @@ PDFTextAnnotation::Flags PDFTextAnnotation::getEffectiveFlags() const
return getFlags() | NoZoom | NoRotate;
}
+QIcon PDFTextAnnotation::createIcon(QString key, QSize size)
+{
+ QIcon icon;
+
+ QPixmap pixmap(size);
+ pixmap.fill(Qt::transparent);
+
+ QRect rectangle(QPoint(0, 0), size);
+ rectangle.adjust(1, 1, -1, -1);
+
+ QPainter painter(&pixmap);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setRenderHint(QPainter::TextAntialiasing);
+
+ QString text = getTextForIcon(key);
+
+ QFont font = QApplication::font();
+ font.setPixelSize(size.height() * 0.75);
+
+ QPainterPath textPath;
+ textPath.addText(0.0, 0.0, font, text);
+ QRectF textBoundingRect = textPath.boundingRect();
+ QPointF offset = rectangle.center() - textBoundingRect.center();
+ textPath.translate(offset);
+ painter.fillPath(textPath, QBrush(Qt::black, Qt::SolidPattern));
+ painter.end();
+
+ icon.addPixmap(qMove(pixmap));
+ return icon;
+}
+
+QString PDFTextAnnotation::getTextForIcon(const QString& key)
+{
+ QString text = "?";
+ if (key == "Comment")
+ {
+ text = QString::fromUtf16(u"\U0001F4AC");
+ }
+ else if (key == "Help")
+ {
+ text = "?";
+ }
+ else if (key == "Insert")
+ {
+ text = QString::fromUtf16(u"\u2380");
+ }
+ else if (key == "Key")
+ {
+ text = QString::fromUtf16(u"\U0001F511");
+ }
+ else if (key == "NewParagraph")
+ {
+ text = QString::fromUtf16(u"\u2606");
+ }
+ else if (key == "Note")
+ {
+ text = QString::fromUtf16(u"\u266A");
+ }
+ else if (key == "Paragraph")
+ {
+ text = QString::fromUtf16(u"\u00B6");
+ }
+ return text;
+}
+
void PDFLineAnnotation::draw(AnnotationDrawParameters& parameters) const
{
QLineF line = getLine();
diff --git a/PdfForQtLib/sources/pdfannotation.h b/PdfForQtLib/sources/pdfannotation.h
index 3895693..2eb9a00 100644
--- a/PdfForQtLib/sources/pdfannotation.h
+++ b/PdfForQtLib/sources/pdfannotation.h
@@ -742,7 +742,7 @@ enum class TextAnnotationIcon
/// as if flag NoZoom and NoRotate were set). When this annotation is opened,
/// it displays popup window containing the text of the note, font and size
/// is implementation dependent by viewer application.
-class PDFTextAnnotation : public PDFMarkupAnnotation
+class PDFFORQTLIBSHARED_EXPORT PDFTextAnnotation : public PDFMarkupAnnotation
{
public:
inline explicit PDFTextAnnotation() = default;
@@ -757,9 +757,13 @@ public:
const QString& getState() const { return m_state; }
const QString& getStateModel() const { return m_stateModel; }
+ static QIcon createIcon(QString key, QSize size);
+
private:
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
+ static QString getTextForIcon(const QString& key);
+
bool m_open = false;
QByteArray m_iconName;
QString m_state;
diff --git a/PdfForQtViewer/pdfviewermainwindow.cpp b/PdfForQtViewer/pdfviewermainwindow.cpp
index 9fdd0bb..56336c9 100644
--- a/PdfForQtViewer/pdfviewermainwindow.cpp
+++ b/PdfForQtViewer/pdfviewermainwindow.cpp
@@ -40,6 +40,7 @@
#include "pdfwidgetutils.h"
#include "pdfdocumentwriter.h"
#include "pdfsignaturehandler.h"
+#include "pdfadvancedtools.h"
#include
#include
@@ -65,6 +66,7 @@
#include
#include
#include
+#include
#ifdef Q_OS_WIN
#include "Windows.h"
@@ -92,6 +94,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
m_progress(new pdf::PDFProgress(this)),
m_taskbarButton(new QWinTaskbarButton(this)),
m_progressTaskbarIndicator(nullptr),
+ m_insertStickyNoteGroup(nullptr),
m_futureWatcher(nullptr),
m_progressDialog(nullptr),
m_isBusy(false),
@@ -174,6 +177,24 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
m_pageNumberSpinBox->setAlignment(Qt::AlignCenter);
connect(m_pageNumberSpinBox, &QSpinBox::editingFinished, this, &PDFViewerMainWindow::onPageNumberSpinboxEditingFinished);
+ m_insertStickyNoteGroup = new QActionGroup(this);
+ m_insertStickyNoteGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional);
+ m_insertStickyNoteGroup->addAction(ui->actionStickyNoteComment);
+ m_insertStickyNoteGroup->addAction(ui->actionStickyNoteHelp);
+ m_insertStickyNoteGroup->addAction(ui->actionStickyNoteInsert);
+ m_insertStickyNoteGroup->addAction(ui->actionStickyNoteKey);
+ m_insertStickyNoteGroup->addAction(ui->actionStickyNoteNewParagraph);
+ m_insertStickyNoteGroup->addAction(ui->actionStickyNoteNote);
+ m_insertStickyNoteGroup->addAction(ui->actionStickyNoteParagraph);
+
+ ui->actionStickyNoteComment->setIcon(pdf::PDFTextAnnotation::createIcon("Comment", iconSize));
+ ui->actionStickyNoteHelp->setIcon(pdf::PDFTextAnnotation::createIcon("Help", iconSize));
+ ui->actionStickyNoteInsert->setIcon(pdf::PDFTextAnnotation::createIcon("Insert", iconSize));
+ ui->actionStickyNoteKey->setIcon(pdf::PDFTextAnnotation::createIcon("Key", iconSize));
+ ui->actionStickyNoteNewParagraph->setIcon(pdf::PDFTextAnnotation::createIcon("NewParagraph", iconSize));
+ ui->actionStickyNoteNote->setIcon(pdf::PDFTextAnnotation::createIcon("Note", iconSize));
+ ui->actionStickyNoteParagraph->setIcon(pdf::PDFTextAnnotation::createIcon("Paragraph", iconSize));
+
// Page control
ui->mainToolBar->addSeparator();
ui->mainToolBar->addAction(actionGoToDocumentStart);
@@ -209,6 +230,28 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
ui->mainToolBar->addAction(ui->actionMagnifier);
ui->mainToolBar->addAction(ui->actionScreenshot);
ui->mainToolBar->addAction(ui->actionExtractImage);
+ ui->mainToolBar->addSeparator();
+
+ // Special tools
+ QToolButton* insertStickyNoteButton = new QToolButton(ui->mainToolBar);
+ insertStickyNoteButton->setPopupMode(QToolButton::MenuButtonPopup);
+ insertStickyNoteButton->setMenu(new QMenu(insertStickyNoteButton));
+ QList insertStickyNotesActions = m_insertStickyNoteGroup->actions();
+ auto onInsertStickyNotesActionTriggered = [insertStickyNoteButton](QAction* action)
+ {
+ if (action)
+ {
+ insertStickyNoteButton->setDefaultAction(action);
+ }
+ };
+ connect(m_insertStickyNoteGroup, &QActionGroup::triggered, insertStickyNoteButton, onInsertStickyNotesActionTriggered);
+ for (QAction* action : insertStickyNotesActions)
+ {
+ insertStickyNoteButton->menu()->addAction(action);
+ }
+ insertStickyNoteButton->setDefaultAction(insertStickyNotesActions.front());
+ ui->mainToolBar->addWidget(insertStickyNoteButton);
+ ui->mainToolBar->addSeparator();
connect(ui->actionZoom_In, &QAction::triggered, this, [this] { m_pdfWidget->getDrawWidgetProxy()->performOperation(pdf::PDFDrawWidgetProxy::ZoomIn); });
connect(ui->actionZoom_Out, &QAction::triggered, this, [this] { m_pdfWidget->getDrawWidgetProxy()->performOperation(pdf::PDFDrawWidgetProxy::ZoomOut); });
@@ -280,6 +323,10 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
updateMagnifierToolSettings();
connect(m_toolManager, &pdf::PDFToolManager::messageDisplayRequest, statusBar(), &QStatusBar::showMessage);
+ // Add special tools
+ pdf::PDFCreateStickyNoteTool* createStickyNoteTool = new pdf::PDFCreateStickyNoteTool(m_pdfWidget->getDrawWidgetProxy(), m_toolManager, m_insertStickyNoteGroup, this);
+ m_toolManager->addTool(createStickyNoteTool);
+
m_annotationManager = new pdf::PDFWidgetAnnotationManager(m_pdfWidget->getDrawWidgetProxy(), this);
connect(m_annotationManager, &pdf::PDFWidgetAnnotationManager::actionTriggered, this, &PDFViewerMainWindow::onActionTriggered);
m_pdfWidget->setAnnotationManager(m_annotationManager);
diff --git a/PdfForQtViewer/pdfviewermainwindow.h b/PdfForQtViewer/pdfviewermainwindow.h
index c3177f7..0fd3c68 100644
--- a/PdfForQtViewer/pdfviewermainwindow.h
+++ b/PdfForQtViewer/pdfviewermainwindow.h
@@ -159,6 +159,8 @@ private:
int adjustDpiX(int value);
+ QIcon createStickyNoteIcon(QString key) const;
+
struct AsyncReadingResult
{
pdf::PDFDocumentPointer document;
@@ -188,6 +190,7 @@ private:
PDFFileInfo m_fileInfo;
pdf::PDFCertificateStore m_certificateStore;
std::vector m_signatures;
+ QActionGroup* m_insertStickyNoteGroup;
QFuture m_future;
QFutureWatcher* m_futureWatcher;
diff --git a/PdfForQtViewer/pdfviewermainwindow.ui b/PdfForQtViewer/pdfviewermainwindow.ui
index adc8b64..e025d75 100644
--- a/PdfForQtViewer/pdfviewermainwindow.ui
+++ b/PdfForQtViewer/pdfviewermainwindow.ui
@@ -130,9 +130,28 @@
+
+
@@ -549,6 +568,62 @@
Save
+
+
+ true
+
+
+ Comment
+
+
+
+
+ true
+
+
+ Help
+
+
+
+
+ true
+
+
+ Insert
+
+
+
+
+ true
+
+
+ Key
+
+
+
+
+ true
+
+
+ New Paragraph
+
+
+
+
+ true
+
+
+ Note
+
+
+
+
+ true
+
+
+ Paragraph
+
+