1 /*
2 SPDX-FileCopyrightText: 2006 Tobias Koenig <tokoe@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "annotationpopup.h"
8
9 #include <KLocalizedString>
10 #include <QIcon>
11 #include <QMenu>
12
13 #include "annotationpropertiesdialog.h"
14
15 #include "core/annotations.h"
16 #include "core/document.h"
17 #include "guiutils.h"
18 #include "okmenutitle.h"
19
20 Q_DECLARE_METATYPE(AnnotationPopup::AnnotPagePair)
21
22 namespace
23 {
annotationHasFileAttachment(Okular::Annotation * annotation)24 bool annotationHasFileAttachment(Okular::Annotation *annotation)
25 {
26 return (annotation->subType() == Okular::Annotation::AFileAttachment || annotation->subType() == Okular::Annotation::ARichMedia);
27 }
28
embeddedFileFromAnnotation(Okular::Annotation * annotation)29 Okular::EmbeddedFile *embeddedFileFromAnnotation(Okular::Annotation *annotation)
30 {
31 if (annotation->subType() == Okular::Annotation::AFileAttachment) {
32 const Okular::FileAttachmentAnnotation *fileAttachAnnot = static_cast<Okular::FileAttachmentAnnotation *>(annotation);
33 return fileAttachAnnot->embeddedFile();
34 } else if (annotation->subType() == Okular::Annotation::ARichMedia) {
35 const Okular::RichMediaAnnotation *richMediaAnnot = static_cast<Okular::RichMediaAnnotation *>(annotation);
36 return richMediaAnnot->embeddedFile();
37 } else {
38 return nullptr;
39 }
40 }
41
42 }
43
AnnotationPopup(Okular::Document * document,MenuMode mode,QWidget * parent)44 AnnotationPopup::AnnotationPopup(Okular::Document *document, MenuMode mode, QWidget *parent)
45 : mParent(parent)
46 , mDocument(document)
47 , mMenuMode(mode)
48 {
49 }
50
addAnnotation(Okular::Annotation * annotation,int pageNumber)51 void AnnotationPopup::addAnnotation(Okular::Annotation *annotation, int pageNumber)
52 {
53 AnnotPagePair pair(annotation, pageNumber);
54 if (!mAnnotations.contains(pair))
55 mAnnotations.append(pair);
56 }
57
exec(const QPoint point)58 void AnnotationPopup::exec(const QPoint point)
59 {
60 if (mAnnotations.isEmpty())
61 return;
62
63 QMenu menu(mParent);
64
65 addActionsToMenu(&menu);
66
67 menu.exec(point.isNull() ? QCursor::pos() : point);
68 }
69
addActionsToMenu(QMenu * menu)70 void AnnotationPopup::addActionsToMenu(QMenu *menu)
71 {
72 QAction *action = nullptr;
73
74 if (mMenuMode == SingleAnnotationMode) {
75 const bool onlyOne = (mAnnotations.count() == 1);
76
77 const AnnotPagePair &pair = mAnnotations.at(0);
78
79 menu->addAction(new OKMenuTitle(menu, i18np("Annotation", "%1 Annotations", mAnnotations.count())));
80
81 action = menu->addAction(QIcon::fromTheme(QStringLiteral("comment")), i18n("&Open Pop-up Note"));
82 action->setEnabled(onlyOne);
83 connect(action, &QAction::triggered, menu, [this, pair] { doOpenAnnotationWindow(pair); });
84
85 action = menu->addAction(QIcon::fromTheme(QStringLiteral("list-remove")), i18n("&Delete"));
86 action->setEnabled(mDocument->isAllowed(Okular::AllowNotes));
87 connect(action, &QAction::triggered, menu, [this] {
88 for (const AnnotPagePair &pair : qAsConst(mAnnotations)) {
89 doRemovePageAnnotation(pair);
90 }
91 });
92
93 for (const AnnotPagePair &pair : qAsConst(mAnnotations)) {
94 if (!mDocument->canRemovePageAnnotation(pair.annotation))
95 action->setEnabled(false);
96 }
97
98 action = menu->addAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("&Properties"));
99 action->setEnabled(onlyOne);
100 connect(action, &QAction::triggered, menu, [this, pair] { doOpenPropertiesDialog(pair); });
101
102 if (onlyOne && annotationHasFileAttachment(pair.annotation)) {
103 const Okular::EmbeddedFile *embeddedFile = embeddedFileFromAnnotation(pair.annotation);
104 if (embeddedFile) {
105 const QString saveText = i18nc("%1 is the name of the file to save", "&Save '%1'...", embeddedFile->name());
106
107 menu->addSeparator();
108 action = menu->addAction(QIcon::fromTheme(QStringLiteral("document-save")), saveText);
109 connect(action, &QAction::triggered, menu, [this, pair] { doSaveEmbeddedFile(pair); });
110 }
111 }
112 } else {
113 for (const AnnotPagePair &pair : qAsConst(mAnnotations)) {
114 menu->addAction(new OKMenuTitle(menu, GuiUtils::captionForAnnotation(pair.annotation)));
115
116 action = menu->addAction(QIcon::fromTheme(QStringLiteral("comment")), i18n("&Open Pop-up Note"));
117 connect(action, &QAction::triggered, menu, [this, pair] { doOpenAnnotationWindow(pair); });
118
119 action = menu->addAction(QIcon::fromTheme(QStringLiteral("list-remove")), i18n("&Delete"));
120 action->setEnabled(mDocument->isAllowed(Okular::AllowNotes) && mDocument->canRemovePageAnnotation(pair.annotation));
121 connect(action, &QAction::triggered, menu, [this, pair] { doRemovePageAnnotation(pair); });
122
123 action = menu->addAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("&Properties"));
124 connect(action, &QAction::triggered, menu, [this, pair] { doOpenPropertiesDialog(pair); });
125
126 if (annotationHasFileAttachment(pair.annotation)) {
127 const Okular::EmbeddedFile *embeddedFile = embeddedFileFromAnnotation(pair.annotation);
128 if (embeddedFile) {
129 const QString saveText = i18nc("%1 is the name of the file to save", "&Save '%1'...", embeddedFile->name());
130
131 menu->addSeparator();
132 action = menu->addAction(QIcon::fromTheme(QStringLiteral("document-save")), saveText);
133 connect(action, &QAction::triggered, menu, [this, pair] { doSaveEmbeddedFile(pair); });
134 }
135 }
136 }
137 }
138 }
139
doRemovePageAnnotation(AnnotPagePair pair)140 void AnnotationPopup::doRemovePageAnnotation(AnnotPagePair pair)
141 {
142 if (pair.pageNumber != -1) {
143 mDocument->removePageAnnotation(pair.pageNumber, pair.annotation);
144 }
145 }
146
doOpenAnnotationWindow(AnnotPagePair pair)147 void AnnotationPopup::doOpenAnnotationWindow(AnnotPagePair pair)
148 {
149 emit openAnnotationWindow(pair.annotation, pair.pageNumber);
150 }
151
doOpenPropertiesDialog(AnnotPagePair pair)152 void AnnotationPopup::doOpenPropertiesDialog(AnnotPagePair pair)
153 {
154 if (pair.pageNumber != -1) {
155 AnnotsPropertiesDialog propdialog(mParent, mDocument, pair.pageNumber, pair.annotation);
156 propdialog.exec();
157 }
158 }
159
doSaveEmbeddedFile(AnnotPagePair pair)160 void AnnotationPopup::doSaveEmbeddedFile(AnnotPagePair pair)
161 {
162 Okular::EmbeddedFile *embeddedFile = embeddedFileFromAnnotation(pair.annotation);
163 GuiUtils::saveEmbeddedFile(embeddedFile, mParent);
164 }
165