mirror of
https://invent.kde.org/graphics/okular
synced 2024-10-02 14:14:10 +00:00
7d53ef7c74
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.
199 lines
7.4 KiB
C++
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);
|
|
}
|