okular/part/annotationpopup.cpp
Kai Uwe Broulik 7d53ef7c74 Allow copying annotation text to clipboard
Adds a "Copy Text to Clipboard" context menu which copies the
annotation text to the clipboard as plain text.

When an annotation is selected in "Browse" mode, its text is copied.
2023-04-30 08:11:16 +00:00

199 lines
7.4 KiB
C++

/*
SPDX-FileCopyrightText: 2006 Tobias Koenig <tokoe@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "annotationpopup.h"
#include <KLocalizedString>
#include <QApplication>
#include <QClipboard>
#include <QIcon>
#include <QMenu>
#include "annotationpropertiesdialog.h"
#include "core/annotations.h"
#include "core/document.h"
#include "gui/guiutils.h"
#include "okmenutitle.h"
Q_DECLARE_METATYPE(AnnotationPopup::AnnotPagePair)
namespace
{
bool annotationHasFileAttachment(Okular::Annotation *annotation)
{
return (annotation->subType() == Okular::Annotation::AFileAttachment || annotation->subType() == Okular::Annotation::ARichMedia);
}
Okular::EmbeddedFile *embeddedFileFromAnnotation(Okular::Annotation *annotation)
{
if (annotation->subType() == Okular::Annotation::AFileAttachment) {
const Okular::FileAttachmentAnnotation *fileAttachAnnot = static_cast<Okular::FileAttachmentAnnotation *>(annotation);
return fileAttachAnnot->embeddedFile();
} else if (annotation->subType() == Okular::Annotation::ARichMedia) {
const Okular::RichMediaAnnotation *richMediaAnnot = static_cast<Okular::RichMediaAnnotation *>(annotation);
return richMediaAnnot->embeddedFile();
} else {
return nullptr;
}
}
}
AnnotationPopup::AnnotationPopup(Okular::Document *document, MenuMode mode, QWidget *parent)
: mParent(parent)
, mDocument(document)
, mMenuMode(mode)
{
}
void AnnotationPopup::addAnnotation(Okular::Annotation *annotation, int pageNumber)
{
AnnotPagePair pair(annotation, pageNumber);
if (!mAnnotations.contains(pair)) {
mAnnotations.append(pair);
}
}
void AnnotationPopup::exec(const QPoint point)
{
if (mAnnotations.isEmpty()) {
return;
}
QMenu menu(mParent);
addActionsToMenu(&menu);
menu.exec(point.isNull() ? QCursor::pos() : point);
}
void AnnotationPopup::addActionsToMenu(QMenu *menu)
{
QAction *action = nullptr;
if (mMenuMode == SingleAnnotationMode) {
const bool onlyOne = (mAnnotations.count() == 1);
const AnnotPagePair &pair = mAnnotations.at(0);
menu->addAction(new OKMenuTitle(menu, i18np("Annotation", "%1 Annotations", mAnnotations.count())));
action = menu->addAction(QIcon::fromTheme(QStringLiteral("comment")), i18n("&Open Pop-up Note"));
action->setEnabled(onlyOne);
connect(action, &QAction::triggered, menu, [this, pair] { doOpenAnnotationWindow(pair); });
if (!pair.annotation->contents().isEmpty()) {
action = menu->addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18n("Copy Text to Clipboard"));
const bool copyAllowed = mDocument->isAllowed(Okular::AllowCopy);
if (!copyAllowed) {
action->setEnabled(false);
action->setText(i18n("Copy forbidden by DRM"));
}
connect(action, &QAction::triggered, menu, [this, pair] { doCopyAnnotation(pair); });
}
action = menu->addAction(QIcon::fromTheme(QStringLiteral("list-remove")), i18n("&Delete"));
action->setEnabled(mDocument->isAllowed(Okular::AllowNotes));
connect(action, &QAction::triggered, menu, [this] {
for (const AnnotPagePair &pair : qAsConst(mAnnotations)) {
doRemovePageAnnotation(pair);
}
});
for (const AnnotPagePair &pair : qAsConst(mAnnotations)) {
if (!mDocument->canRemovePageAnnotation(pair.annotation)) {
action->setEnabled(false);
}
}
action = menu->addAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("&Properties"));
action->setEnabled(onlyOne);
connect(action, &QAction::triggered, menu, [this, pair] { doOpenPropertiesDialog(pair); });
if (onlyOne && annotationHasFileAttachment(pair.annotation)) {
const Okular::EmbeddedFile *embeddedFile = embeddedFileFromAnnotation(pair.annotation);
if (embeddedFile) {
const QString saveText = i18nc("%1 is the name of the file to save", "&Save '%1'...", embeddedFile->name());
menu->addSeparator();
action = menu->addAction(QIcon::fromTheme(QStringLiteral("document-save")), saveText);
connect(action, &QAction::triggered, menu, [this, pair] { doSaveEmbeddedFile(pair); });
}
}
} else {
for (const AnnotPagePair &pair : qAsConst(mAnnotations)) {
menu->addAction(new OKMenuTitle(menu, GuiUtils::captionForAnnotation(pair.annotation)));
action = menu->addAction(QIcon::fromTheme(QStringLiteral("comment")), i18n("&Open Pop-up Note"));
connect(action, &QAction::triggered, menu, [this, pair] { doOpenAnnotationWindow(pair); });
if (!pair.annotation->contents().isEmpty()) {
action = menu->addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18n("Copy Text to Clipboard"));
const bool copyAllowed = mDocument->isAllowed(Okular::AllowCopy);
if (!copyAllowed) {
action->setEnabled(false);
action->setText(i18n("Copy forbidden by DRM"));
}
connect(action, &QAction::triggered, menu, [this, pair] { doCopyAnnotation(pair); });
}
action = menu->addAction(QIcon::fromTheme(QStringLiteral("list-remove")), i18n("&Delete"));
action->setEnabled(mDocument->isAllowed(Okular::AllowNotes) && mDocument->canRemovePageAnnotation(pair.annotation));
connect(action, &QAction::triggered, menu, [this, pair] { doRemovePageAnnotation(pair); });
action = menu->addAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("&Properties"));
connect(action, &QAction::triggered, menu, [this, pair] { doOpenPropertiesDialog(pair); });
if (annotationHasFileAttachment(pair.annotation)) {
const Okular::EmbeddedFile *embeddedFile = embeddedFileFromAnnotation(pair.annotation);
if (embeddedFile) {
const QString saveText = i18nc("%1 is the name of the file to save", "&Save '%1'...", embeddedFile->name());
menu->addSeparator();
action = menu->addAction(QIcon::fromTheme(QStringLiteral("document-save")), saveText);
connect(action, &QAction::triggered, menu, [this, pair] { doSaveEmbeddedFile(pair); });
}
}
}
}
}
void AnnotationPopup::doCopyAnnotation(AnnotPagePair pair)
{
const QString text = pair.annotation->contents();
if (!text.isEmpty()) {
QClipboard *cb = QApplication::clipboard();
cb->setText(text, QClipboard::Clipboard);
}
}
void AnnotationPopup::doRemovePageAnnotation(AnnotPagePair pair)
{
if (pair.pageNumber != -1) {
mDocument->removePageAnnotation(pair.pageNumber, pair.annotation);
}
}
void AnnotationPopup::doOpenAnnotationWindow(AnnotPagePair pair)
{
Q_EMIT openAnnotationWindow(pair.annotation, pair.pageNumber);
}
void AnnotationPopup::doOpenPropertiesDialog(AnnotPagePair pair)
{
if (pair.pageNumber != -1) {
AnnotsPropertiesDialog propdialog(mParent, mDocument, pair.pageNumber, pair.annotation);
propdialog.exec();
}
}
void AnnotationPopup::doSaveEmbeddedFile(AnnotPagePair pair)
{
Okular::EmbeddedFile *embeddedFile = embeddedFileFromAnnotation(pair.annotation);
GuiUtils::saveEmbeddedFile(embeddedFile, mParent);
}