mirror of
https://invent.kde.org/graphics/okular
synced 2024-11-05 18:34:53 +00:00
860 lines
32 KiB
C++
860 lines
32 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2006 Pino Toscano <pino@kde.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "annotationwidgets.h"
|
|
|
|
// qt/kde includes
|
|
#include <KColorButton>
|
|
#include <KComboBox>
|
|
#include <KFontRequester>
|
|
#include <KFormat>
|
|
#include <KLocalizedString>
|
|
#include <KMessageBox>
|
|
#include <KMessageWidget>
|
|
#include <QCheckBox>
|
|
#include <QDebug>
|
|
#include <QFileDialog>
|
|
#include <QFormLayout>
|
|
#include <QGroupBox>
|
|
#include <QGuiApplication>
|
|
#include <QIcon>
|
|
#include <QLabel>
|
|
#include <QLayout>
|
|
#include <QList>
|
|
#include <QMimeDatabase>
|
|
#include <QPair>
|
|
#include <QSize>
|
|
#include <QSpinBox>
|
|
#include <QVariant>
|
|
|
|
#include "core/annotations.h"
|
|
#include "core/annotations_p.h"
|
|
#include "core/document.h"
|
|
#include "core/document_p.h"
|
|
#include "core/page_p.h"
|
|
#include "gui/guiutils.h"
|
|
#include "gui/pagepainter.h"
|
|
|
|
#define FILEATTACH_ICONSIZE 48
|
|
|
|
PixmapPreviewSelector::PixmapPreviewSelector(QWidget *parent, PreviewPosition position)
|
|
: QWidget(parent)
|
|
, m_previewPosition(position)
|
|
{
|
|
QVBoxLayout *mainlay = new QVBoxLayout(this);
|
|
mainlay->setContentsMargins(0, 0, 0, 0);
|
|
QHBoxLayout *toplay = new QHBoxLayout(this);
|
|
toplay->setContentsMargins(0, 0, 0, 0);
|
|
mainlay->addLayout(toplay);
|
|
m_comboItems = new KComboBox(this);
|
|
toplay->addWidget(m_comboItems);
|
|
m_stampPushButton = new QPushButton(QIcon::fromTheme(QStringLiteral("document-open")), QString(), this);
|
|
m_stampPushButton->setVisible(false);
|
|
m_stampPushButton->setToolTip(i18nc("@info:tooltip", "Select a custom stamp symbol from file"));
|
|
toplay->addWidget(m_stampPushButton);
|
|
m_iconLabel = new QLabel(this);
|
|
switch (m_previewPosition) {
|
|
case Side:
|
|
toplay->addWidget(m_iconLabel);
|
|
break;
|
|
case Below:
|
|
mainlay->addWidget(m_iconLabel);
|
|
mainlay->setAlignment(m_iconLabel, Qt::AlignHCenter);
|
|
break;
|
|
}
|
|
m_iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
m_iconLabel->setAlignment(Qt::AlignCenter);
|
|
m_iconLabel->setFrameStyle(QFrame::StyledPanel);
|
|
setPreviewSize(32);
|
|
|
|
setFocusPolicy(Qt::TabFocus);
|
|
setFocusProxy(m_comboItems);
|
|
|
|
connect(m_comboItems, QOverload<const QString &>::of(&QComboBox::currentIndexChanged), this, &PixmapPreviewSelector::iconComboChanged);
|
|
connect(m_comboItems, &QComboBox::editTextChanged, this, &PixmapPreviewSelector::iconComboChanged);
|
|
connect(m_stampPushButton, &QPushButton::clicked, this, &PixmapPreviewSelector::selectCustomStamp);
|
|
}
|
|
|
|
PixmapPreviewSelector::~PixmapPreviewSelector()
|
|
{
|
|
}
|
|
|
|
void PixmapPreviewSelector::setIcon(const QString &icon)
|
|
{
|
|
int id = m_comboItems->findData(QVariant(icon), Qt::UserRole, Qt::MatchFixedString);
|
|
if (id == -1) {
|
|
id = m_comboItems->findText(icon, Qt::MatchFixedString);
|
|
}
|
|
if (id > -1) {
|
|
m_comboItems->setCurrentIndex(id);
|
|
} else if (m_comboItems->isEditable()) {
|
|
m_comboItems->addItem(icon, QVariant(icon));
|
|
m_comboItems->setCurrentIndex(m_comboItems->findText(icon, Qt::MatchFixedString));
|
|
}
|
|
}
|
|
|
|
QString PixmapPreviewSelector::icon() const
|
|
{
|
|
return m_icon;
|
|
}
|
|
|
|
void PixmapPreviewSelector::addItem(const QString &item, const QString &id)
|
|
{
|
|
m_comboItems->addItem(item, QVariant(id));
|
|
setIcon(m_icon);
|
|
}
|
|
|
|
void PixmapPreviewSelector::setPreviewSize(int size)
|
|
{
|
|
m_previewSize = size;
|
|
switch (m_previewPosition) {
|
|
case Side:
|
|
m_iconLabel->setFixedSize(m_previewSize + 8, m_previewSize + 8);
|
|
break;
|
|
case Below:
|
|
m_iconLabel->setFixedSize(3 * m_previewSize + 8, m_previewSize + 8);
|
|
break;
|
|
}
|
|
iconComboChanged(m_icon);
|
|
}
|
|
|
|
int PixmapPreviewSelector::previewSize() const
|
|
{
|
|
return m_previewSize;
|
|
}
|
|
|
|
void PixmapPreviewSelector::setEditable(bool editable)
|
|
{
|
|
m_comboItems->setEditable(editable);
|
|
m_stampPushButton->setVisible(editable);
|
|
}
|
|
|
|
void PixmapPreviewSelector::iconComboChanged(const QString &icon)
|
|
{
|
|
int id = m_comboItems->findText(icon, Qt::MatchFixedString);
|
|
if (id >= 0) {
|
|
m_icon = m_comboItems->itemData(id).toString();
|
|
} else {
|
|
m_icon = icon;
|
|
}
|
|
|
|
QPixmap pixmap = Okular::AnnotationUtils::loadStamp(m_icon, m_previewSize);
|
|
const QRect cr = m_iconLabel->contentsRect();
|
|
if (pixmap.width() > cr.width() || pixmap.height() > cr.height()) {
|
|
pixmap = pixmap.scaled(cr.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
}
|
|
m_iconLabel->setPixmap(pixmap);
|
|
|
|
Q_EMIT iconChanged(m_icon);
|
|
}
|
|
|
|
void PixmapPreviewSelector::selectCustomStamp()
|
|
{
|
|
const QString customStampFile = QFileDialog::getOpenFileName(this, i18nc("@title:window file chooser", "Select custom stamp symbol"), QString(), i18n("*.ico *.png *.xpm *.svg *.svgz | Icon Files (*.ico *.png *.xpm *.svg *.svgz)"));
|
|
if (!customStampFile.isEmpty()) {
|
|
QPixmap pixmap = Okular::AnnotationUtils::loadStamp(customStampFile, m_previewSize);
|
|
if (pixmap.isNull()) {
|
|
KMessageBox::error(this, xi18nc("@info", "Could not load the file <filename>%1</filename>", customStampFile), i18nc("@title:window", "Invalid file"));
|
|
} else {
|
|
m_comboItems->setEditText(customStampFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
AnnotationWidget *AnnotationWidgetFactory::widgetFor(Okular::Annotation *ann)
|
|
{
|
|
switch (ann->subType()) {
|
|
case Okular::Annotation::AStamp:
|
|
return new StampAnnotationWidget(ann);
|
|
break;
|
|
case Okular::Annotation::AText:
|
|
return new TextAnnotationWidget(ann);
|
|
break;
|
|
case Okular::Annotation::ALine:
|
|
return new LineAnnotationWidget(ann);
|
|
break;
|
|
case Okular::Annotation::AHighlight:
|
|
return new HighlightAnnotationWidget(ann);
|
|
break;
|
|
case Okular::Annotation::AInk:
|
|
return new InkAnnotationWidget(ann);
|
|
break;
|
|
case Okular::Annotation::AGeom:
|
|
return new GeomAnnotationWidget(ann);
|
|
break;
|
|
case Okular::Annotation::AFileAttachment:
|
|
return new FileAttachmentAnnotationWidget(ann);
|
|
break;
|
|
case Okular::Annotation::ACaret:
|
|
return new CaretAnnotationWidget(ann);
|
|
break;
|
|
// shut up gcc
|
|
default:;
|
|
}
|
|
// cases not covered yet: return a generic widget
|
|
return new AnnotationWidget(ann);
|
|
}
|
|
|
|
AnnotationWidget::AnnotationWidget(Okular::Annotation *ann)
|
|
: m_typeEditable(true)
|
|
, m_ann(ann)
|
|
{
|
|
}
|
|
|
|
AnnotationWidget::~AnnotationWidget()
|
|
{
|
|
}
|
|
|
|
Okular::Annotation::SubType AnnotationWidget::annotationType() const
|
|
{
|
|
return m_ann->subType();
|
|
}
|
|
|
|
QWidget *AnnotationWidget::appearanceWidget()
|
|
{
|
|
if (m_appearanceWidget) {
|
|
return m_appearanceWidget;
|
|
}
|
|
|
|
m_appearanceWidget = createAppearanceWidget();
|
|
return m_appearanceWidget;
|
|
}
|
|
|
|
QWidget *AnnotationWidget::extraWidget()
|
|
{
|
|
if (m_extraWidget) {
|
|
return m_extraWidget;
|
|
}
|
|
|
|
m_extraWidget = createExtraWidget();
|
|
return m_extraWidget;
|
|
}
|
|
|
|
void AnnotationWidget::applyChanges()
|
|
{
|
|
if (m_colorBn) {
|
|
m_ann->style().setColor(m_colorBn->color());
|
|
}
|
|
if (m_opacity) {
|
|
m_ann->style().setOpacity((double)m_opacity->value() / 100.0);
|
|
}
|
|
}
|
|
|
|
QWidget *AnnotationWidget::createAppearanceWidget()
|
|
{
|
|
QWidget *widget = new QWidget();
|
|
QFormLayout *formlayout = new QFormLayout(widget);
|
|
formlayout->setLabelAlignment(Qt::AlignRight);
|
|
formlayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
|
|
|
createStyleWidget(formlayout);
|
|
|
|
return widget;
|
|
}
|
|
|
|
void AnnotationWidget::createStyleWidget(QFormLayout *formlayout)
|
|
{
|
|
Q_UNUSED(formlayout);
|
|
}
|
|
|
|
void AnnotationWidget::addColorButton(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
m_colorBn = new KColorButton(widget);
|
|
m_colorBn->setColor(m_ann->style().color());
|
|
formlayout->addRow(i18n("&Color:"), m_colorBn);
|
|
connect(m_colorBn, &KColorButton::changed, this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void AnnotationWidget::addOpacitySpinBox(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
m_opacity = new QSpinBox(widget);
|
|
m_opacity->setRange(0, 100);
|
|
m_opacity->setValue((int)(m_ann->style().opacity() * 100));
|
|
m_opacity->setSuffix(i18nc("Suffix for the opacity level, eg '80%'", "%"));
|
|
formlayout->addRow(i18n("&Opacity:"), m_opacity);
|
|
connect(m_opacity, QOverload<int>::of(&QSpinBox::valueChanged), this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void AnnotationWidget::addVerticalSpacer(QFormLayout *formlayout)
|
|
{
|
|
formlayout->addItem(new QSpacerItem(0, 5, QSizePolicy::Fixed, QSizePolicy::Fixed));
|
|
}
|
|
|
|
QWidget *AnnotationWidget::createExtraWidget()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
TextAnnotationWidget::TextAnnotationWidget(Okular::Annotation *ann)
|
|
: AnnotationWidget(ann)
|
|
{
|
|
m_textAnn = static_cast<Okular::TextAnnotation *>(ann);
|
|
}
|
|
|
|
void TextAnnotationWidget::createStyleWidget(QFormLayout *formlayout)
|
|
{
|
|
QWidget *widget = qobject_cast<QWidget *>(formlayout->parent());
|
|
|
|
if (m_textAnn->textType() == Okular::TextAnnotation::Linked) {
|
|
createPopupNoteStyleUi(widget, formlayout);
|
|
} else if (m_textAnn->textType() == Okular::TextAnnotation::InPlace) {
|
|
if (isTypewriter()) {
|
|
createTypewriterStyleUi(widget, formlayout);
|
|
} else {
|
|
createInlineNoteStyleUi(widget, formlayout);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TextAnnotationWidget::applyChanges()
|
|
{
|
|
AnnotationWidget::applyChanges();
|
|
if (m_textAnn->textType() == Okular::TextAnnotation::Linked) {
|
|
Q_ASSERT(m_pixmapSelector);
|
|
m_textAnn->setTextIcon(m_pixmapSelector->icon());
|
|
} else if (m_textAnn->textType() == Okular::TextAnnotation::InPlace) {
|
|
Q_ASSERT(m_fontReq);
|
|
m_textAnn->setTextFont(m_fontReq->font());
|
|
if (!isTypewriter()) {
|
|
Q_ASSERT(m_textAlign && m_spinWidth);
|
|
m_textAnn->setInplaceAlignment(m_textAlign->currentIndex());
|
|
m_textAnn->style().setWidth(m_spinWidth->value());
|
|
} else {
|
|
Q_ASSERT(m_textColorBn);
|
|
m_textAnn->setTextColor(m_textColorBn->color());
|
|
}
|
|
}
|
|
}
|
|
|
|
void AnnotationWidget::setAnnotTypeEditable(bool editable)
|
|
{
|
|
m_typeEditable = editable;
|
|
}
|
|
|
|
void TextAnnotationWidget::createPopupNoteStyleUi(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
addColorButton(widget, formlayout);
|
|
addOpacitySpinBox(widget, formlayout);
|
|
addVerticalSpacer(formlayout);
|
|
addPixmapSelector(widget, formlayout);
|
|
}
|
|
|
|
void TextAnnotationWidget::createInlineNoteStyleUi(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
addColorButton(widget, formlayout);
|
|
addOpacitySpinBox(widget, formlayout);
|
|
addVerticalSpacer(formlayout);
|
|
addFontRequester(widget, formlayout);
|
|
addTextAlignComboBox(widget, formlayout);
|
|
addVerticalSpacer(formlayout);
|
|
addWidthSpinBox(widget, formlayout);
|
|
}
|
|
|
|
void TextAnnotationWidget::createTypewriterStyleUi(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
addFontRequester(widget, formlayout);
|
|
addTextColorButton(widget, formlayout);
|
|
}
|
|
|
|
void TextAnnotationWidget::addPixmapSelector(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
m_pixmapSelector = new PixmapPreviewSelector(widget);
|
|
formlayout->addRow(i18n("Icon:"), m_pixmapSelector);
|
|
m_pixmapSelector->addItem(i18n("Comment"), QStringLiteral("Comment"));
|
|
m_pixmapSelector->addItem(i18n("Help"), QStringLiteral("Help"));
|
|
m_pixmapSelector->addItem(i18n("Insert"), QStringLiteral("Insert"));
|
|
m_pixmapSelector->addItem(i18n("Key"), QStringLiteral("Key"));
|
|
m_pixmapSelector->addItem(i18n("New paragraph"), QStringLiteral("NewParagraph"));
|
|
m_pixmapSelector->addItem(i18n("Note"), QStringLiteral("Note"));
|
|
m_pixmapSelector->addItem(i18n("Paragraph"), QStringLiteral("Paragraph"));
|
|
m_pixmapSelector->setIcon(m_textAnn->textIcon());
|
|
connect(m_pixmapSelector, &PixmapPreviewSelector::iconChanged, this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void TextAnnotationWidget::addFontRequester(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
m_fontReq = new KFontRequester(widget);
|
|
formlayout->addRow(i18n("Font:"), m_fontReq);
|
|
m_fontReq->setFont(m_textAnn->textFont());
|
|
connect(m_fontReq, &KFontRequester::fontSelected, this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void TextAnnotationWidget::addTextColorButton(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
m_textColorBn = new KColorButton(widget);
|
|
m_textColorBn->setColor(m_textAnn->textColor());
|
|
formlayout->addRow(i18n("Text &color:"), m_textColorBn);
|
|
connect(m_textColorBn, &KColorButton::changed, this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void TextAnnotationWidget::addTextAlignComboBox(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
m_textAlign = new KComboBox(widget);
|
|
formlayout->addRow(i18n("&Align:"), m_textAlign);
|
|
m_textAlign->addItem(i18n("Left"));
|
|
m_textAlign->addItem(i18n("Center"));
|
|
m_textAlign->addItem(i18n("Right"));
|
|
m_textAlign->setCurrentIndex(m_textAnn->inplaceAlignment());
|
|
connect(m_textAlign, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void TextAnnotationWidget::addWidthSpinBox(QWidget *widget, QFormLayout *formlayout)
|
|
{
|
|
m_spinWidth = new QDoubleSpinBox(widget);
|
|
formlayout->addRow(i18n("Border &width:"), m_spinWidth);
|
|
m_spinWidth->setRange(0, 100);
|
|
m_spinWidth->setValue(m_textAnn->style().width());
|
|
m_spinWidth->setSingleStep(0.1);
|
|
connect(m_spinWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
const QList<QPair<QString, QString>> &StampAnnotationWidget::defaultStamps()
|
|
{
|
|
static const QList<QPair<QString, QString>> defaultStampsList = {{i18n("Approved"), QStringLiteral("Approved")},
|
|
{i18n("As Is"), QStringLiteral("AsIs")},
|
|
{i18n("Confidential"), QStringLiteral("Confidential")},
|
|
{i18n("Departmental"), QStringLiteral("Departmental")},
|
|
{i18n("Draft"), QStringLiteral("Draft")},
|
|
{i18n("Experimental"), QStringLiteral("Experimental")},
|
|
{i18n("Expired"), QStringLiteral("Expired")},
|
|
{i18n("Final"), QStringLiteral("Final")},
|
|
{i18n("For Comment"), QStringLiteral("ForComment")},
|
|
{i18n("For Public Release"), QStringLiteral("ForPublicRelease")},
|
|
{i18n("Not Approved"), QStringLiteral("NotApproved")},
|
|
{i18n("Not For Public Release"), QStringLiteral("NotForPublicRelease")},
|
|
{i18n("Sold"), QStringLiteral("Sold")},
|
|
{i18n("Top Secret"), QStringLiteral("TopSecret")},
|
|
{i18n("Bookmark"), QStringLiteral("bookmark-new")},
|
|
{i18n("Information"), QStringLiteral("help-about")},
|
|
{i18n("KDE"), QStringLiteral("kde")},
|
|
{i18n("Okular"), QStringLiteral("okular")}};
|
|
|
|
return defaultStampsList;
|
|
}
|
|
|
|
StampAnnotationWidget::StampAnnotationWidget(Okular::Annotation *ann)
|
|
: AnnotationWidget(ann)
|
|
, m_pixmapSelector(nullptr)
|
|
{
|
|
m_stampAnn = static_cast<Okular::StampAnnotation *>(ann);
|
|
}
|
|
|
|
void StampAnnotationWidget::createStyleWidget(QFormLayout *formlayout)
|
|
{
|
|
QWidget *widget = qobject_cast<QWidget *>(formlayout->parent());
|
|
|
|
addOpacitySpinBox(widget, formlayout);
|
|
addVerticalSpacer(formlayout);
|
|
|
|
m_pixmapSelector = new PixmapPreviewSelector(widget, PixmapPreviewSelector::Below);
|
|
formlayout->addRow(i18n("Stamp symbol:"), m_pixmapSelector);
|
|
m_pixmapSelector->setEditable(true);
|
|
|
|
for (const QPair<QString, QString> &pair : defaultStamps()) {
|
|
m_pixmapSelector->addItem(pair.first, pair.second);
|
|
}
|
|
|
|
m_pixmapSelector->setIcon(m_stampAnn->stampIconName());
|
|
m_pixmapSelector->setPreviewSize(64);
|
|
|
|
connect(m_pixmapSelector, &PixmapPreviewSelector::iconChanged, this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void StampAnnotationWidget::applyChanges()
|
|
{
|
|
AnnotationWidget::applyChanges();
|
|
m_stampAnn->setStampIconName(m_pixmapSelector->icon());
|
|
}
|
|
|
|
LineAnnotationWidget::LineAnnotationWidget(Okular::Annotation *ann)
|
|
: AnnotationWidget(ann)
|
|
{
|
|
m_lineAnn = static_cast<Okular::LineAnnotation *>(ann);
|
|
if (m_lineAnn->linePoints().count() == 2) {
|
|
m_lineType = 0; // line
|
|
} else if (m_lineAnn->lineClosed()) {
|
|
m_lineType = 1; // polygon
|
|
} else {
|
|
m_lineType = 2; // polyline
|
|
}
|
|
}
|
|
|
|
void LineAnnotationWidget::createStyleWidget(QFormLayout *formlayout)
|
|
{
|
|
QWidget *widget = qobject_cast<QWidget *>(formlayout->parent());
|
|
|
|
addColorButton(widget, formlayout);
|
|
addOpacitySpinBox(widget, formlayout);
|
|
|
|
m_spinSize = new QDoubleSpinBox(widget);
|
|
m_spinSize->setRange(1, 100);
|
|
m_spinSize->setValue(m_lineAnn->style().width());
|
|
|
|
connect(m_spinSize, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LineAnnotationWidget::dataChanged);
|
|
|
|
// Straight line
|
|
if (m_lineType == 0) {
|
|
addVerticalSpacer(formlayout);
|
|
formlayout->addRow(i18n("&Width:"), m_spinSize);
|
|
|
|
// Line Term Styles
|
|
addVerticalSpacer(formlayout);
|
|
m_startStyleCombo = new QComboBox(widget);
|
|
formlayout->addRow(i18n("Line start:"), m_startStyleCombo);
|
|
m_endStyleCombo = new QComboBox(widget);
|
|
formlayout->addRow(i18n("Line end:"), m_endStyleCombo);
|
|
// FIXME: Where does the tooltip goes??
|
|
|
|
const QList<QPair<Okular::LineAnnotation::TermStyle, QString>> termStyles {{Okular::LineAnnotation::Square, i18n("Square")},
|
|
{Okular::LineAnnotation::Circle, i18n("Circle")},
|
|
{Okular::LineAnnotation::Diamond, i18n("Diamond")},
|
|
{Okular::LineAnnotation::OpenArrow, i18n("Open Arrow")},
|
|
{Okular::LineAnnotation::ClosedArrow, i18n("Closed Arrow")},
|
|
{Okular::LineAnnotation::None, i18n("None")},
|
|
{Okular::LineAnnotation::Butt, i18n("Butt")},
|
|
{Okular::LineAnnotation::ROpenArrow, i18n("Right Open Arrow")},
|
|
{Okular::LineAnnotation::RClosedArrow, i18n("Right Closed Arrow")},
|
|
{Okular::LineAnnotation::Slash, i18n("Slash")}};
|
|
for (const auto &item : termStyles) {
|
|
const QIcon icon = endStyleIcon(item.first, QGuiApplication::palette().color(QPalette::WindowText));
|
|
m_startStyleCombo->addItem(icon, item.second);
|
|
m_endStyleCombo->addItem(icon, item.second);
|
|
}
|
|
|
|
m_startStyleCombo->setCurrentIndex(m_lineAnn->lineStartStyle());
|
|
m_endStyleCombo->setCurrentIndex(m_lineAnn->lineEndStyle());
|
|
|
|
// Leaders lengths
|
|
addVerticalSpacer(formlayout);
|
|
m_spinLL = new QDoubleSpinBox(widget);
|
|
formlayout->addRow(i18n("Leader line length:"), m_spinLL);
|
|
m_spinLLE = new QDoubleSpinBox(widget);
|
|
formlayout->addRow(i18n("Leader line extensions length:"), m_spinLLE);
|
|
|
|
m_spinLL->setRange(-500, 500);
|
|
m_spinLL->setValue(m_lineAnn->lineLeadingForwardPoint());
|
|
m_spinLLE->setRange(0, 500);
|
|
m_spinLLE->setValue(m_lineAnn->lineLeadingBackwardPoint());
|
|
|
|
connect(m_startStyleCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LineAnnotationWidget::dataChanged);
|
|
connect(m_endStyleCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LineAnnotationWidget::dataChanged);
|
|
connect(m_spinLL, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LineAnnotationWidget::dataChanged);
|
|
connect(m_spinLLE, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LineAnnotationWidget::dataChanged);
|
|
} else if (m_lineType == 1) // Polygon
|
|
{
|
|
QHBoxLayout *colorlay = new QHBoxLayout();
|
|
m_useColor = new QCheckBox(i18n("Enabled"), widget);
|
|
colorlay->addWidget(m_useColor);
|
|
m_innerColor = new KColorButton(widget);
|
|
colorlay->addWidget(m_innerColor);
|
|
formlayout->addRow(i18n("Shape fill:"), colorlay);
|
|
|
|
m_innerColor->setColor(m_lineAnn->lineInnerColor());
|
|
if (m_lineAnn->lineInnerColor().isValid()) {
|
|
m_useColor->setChecked(true);
|
|
} else {
|
|
m_innerColor->setEnabled(false);
|
|
}
|
|
|
|
addVerticalSpacer(formlayout);
|
|
formlayout->addRow(i18n("&Width:"), m_spinSize);
|
|
|
|
connect(m_innerColor, &KColorButton::changed, this, &AnnotationWidget::dataChanged);
|
|
connect(m_useColor, &QAbstractButton::toggled, this, &AnnotationWidget::dataChanged);
|
|
connect(m_useColor, &QCheckBox::toggled, m_innerColor, &KColorButton::setEnabled);
|
|
}
|
|
}
|
|
|
|
void LineAnnotationWidget::applyChanges()
|
|
{
|
|
AnnotationWidget::applyChanges();
|
|
if (m_lineType == 0) {
|
|
Q_ASSERT(m_spinLL && m_spinLLE && m_startStyleCombo && m_endStyleCombo);
|
|
m_lineAnn->setLineLeadingForwardPoint(m_spinLL->value());
|
|
m_lineAnn->setLineLeadingBackwardPoint(m_spinLLE->value());
|
|
m_lineAnn->setLineStartStyle((Okular::LineAnnotation::TermStyle)m_startStyleCombo->currentIndex());
|
|
m_lineAnn->setLineEndStyle((Okular::LineAnnotation::TermStyle)m_endStyleCombo->currentIndex());
|
|
} else if (m_lineType == 1) {
|
|
Q_ASSERT(m_useColor && m_innerColor);
|
|
if (!m_useColor->isChecked()) {
|
|
m_lineAnn->setLineInnerColor(QColor());
|
|
} else {
|
|
m_lineAnn->setLineInnerColor(m_innerColor->color());
|
|
}
|
|
}
|
|
Q_ASSERT(m_spinSize);
|
|
m_lineAnn->style().setWidth(m_spinSize->value());
|
|
}
|
|
|
|
QIcon LineAnnotationWidget::endStyleIcon(Okular::LineAnnotation::TermStyle endStyle, const QColor &lineColor)
|
|
{
|
|
const int iconSize {48};
|
|
QImage image {iconSize, iconSize, QImage::Format_ARGB32};
|
|
image.fill(qRgba(0, 0, 0, 0));
|
|
Okular::LineAnnotation prototype;
|
|
prototype.setLinePoints({{0, 0.5}, {0.65, 0.5}});
|
|
prototype.setLineStartStyle(Okular::LineAnnotation::TermStyle::None);
|
|
prototype.setLineEndStyle(endStyle);
|
|
prototype.style().setWidth(4);
|
|
prototype.style().setColor(lineColor);
|
|
prototype.style().setLineStyle(Okular::Annotation::LineStyle::Solid);
|
|
prototype.setBoundingRectangle({0, 0, 1, 1});
|
|
LineAnnotPainter linepainter {&prototype, QSize {iconSize, iconSize}, 1, QTransform()};
|
|
linepainter.draw(image);
|
|
return QIcon(QPixmap::fromImage(image));
|
|
}
|
|
|
|
InkAnnotationWidget::InkAnnotationWidget(Okular::Annotation *ann)
|
|
: AnnotationWidget(ann)
|
|
{
|
|
m_inkAnn = static_cast<Okular::InkAnnotation *>(ann);
|
|
}
|
|
|
|
void InkAnnotationWidget::createStyleWidget(QFormLayout *formlayout)
|
|
{
|
|
QWidget *widget = qobject_cast<QWidget *>(formlayout->parent());
|
|
|
|
addColorButton(widget, formlayout);
|
|
addOpacitySpinBox(widget, formlayout);
|
|
|
|
addVerticalSpacer(formlayout);
|
|
|
|
m_spinSize = new QDoubleSpinBox(widget);
|
|
formlayout->addRow(i18n("&Width:"), m_spinSize);
|
|
|
|
m_spinSize->setRange(1, 100);
|
|
m_spinSize->setValue(m_inkAnn->style().width());
|
|
|
|
connect(m_spinSize, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void InkAnnotationWidget::applyChanges()
|
|
{
|
|
AnnotationWidget::applyChanges();
|
|
m_inkAnn->style().setWidth(m_spinSize->value());
|
|
}
|
|
|
|
HighlightAnnotationWidget::HighlightAnnotationWidget(Okular::Annotation *ann)
|
|
: AnnotationWidget(ann)
|
|
{
|
|
m_hlAnn = static_cast<Okular::HighlightAnnotation *>(ann);
|
|
}
|
|
|
|
void HighlightAnnotationWidget::createStyleWidget(QFormLayout *formlayout)
|
|
{
|
|
QWidget *widget = qobject_cast<QWidget *>(formlayout->parent());
|
|
|
|
m_typeCombo = new KComboBox(widget);
|
|
m_typeCombo->setVisible(m_typeEditable);
|
|
if (m_typeEditable) {
|
|
formlayout->addRow(i18n("Type:"), m_typeCombo);
|
|
}
|
|
m_typeCombo->addItem(i18n("Highlight"));
|
|
m_typeCombo->addItem(i18n("Squiggle"));
|
|
m_typeCombo->addItem(i18n("Underline"));
|
|
m_typeCombo->addItem(i18n("Strike out"));
|
|
m_typeCombo->setCurrentIndex(m_hlAnn->highlightType());
|
|
|
|
addVerticalSpacer(formlayout);
|
|
addColorButton(widget, formlayout);
|
|
addOpacitySpinBox(widget, formlayout);
|
|
|
|
connect(m_typeCombo, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void HighlightAnnotationWidget::applyChanges()
|
|
{
|
|
AnnotationWidget::applyChanges();
|
|
m_hlAnn->setHighlightType((Okular::HighlightAnnotation::HighlightType)m_typeCombo->currentIndex());
|
|
}
|
|
|
|
GeomAnnotationWidget::GeomAnnotationWidget(Okular::Annotation *ann)
|
|
: AnnotationWidget(ann)
|
|
{
|
|
m_geomAnn = static_cast<Okular::GeomAnnotation *>(ann);
|
|
}
|
|
|
|
void GeomAnnotationWidget::createStyleWidget(QFormLayout *formlayout)
|
|
{
|
|
QWidget *widget = qobject_cast<QWidget *>(formlayout->parent());
|
|
|
|
m_typeCombo = new KComboBox(widget);
|
|
m_typeCombo->setVisible(m_typeEditable);
|
|
if (m_typeEditable) {
|
|
formlayout->addRow(i18n("Type:"), m_typeCombo);
|
|
}
|
|
addVerticalSpacer(formlayout);
|
|
addColorButton(widget, formlayout);
|
|
addOpacitySpinBox(widget, formlayout);
|
|
QHBoxLayout *colorlay = new QHBoxLayout();
|
|
m_useColor = new QCheckBox(i18n("Enabled"), widget);
|
|
colorlay->addWidget(m_useColor);
|
|
m_innerColor = new KColorButton(widget);
|
|
colorlay->addWidget(m_innerColor);
|
|
formlayout->addRow(i18n("Shape fill:"), colorlay);
|
|
addVerticalSpacer(formlayout);
|
|
m_spinSize = new QDoubleSpinBox(widget);
|
|
formlayout->addRow(i18n("&Width:"), m_spinSize);
|
|
|
|
m_typeCombo->addItem(i18n("Rectangle"));
|
|
m_typeCombo->addItem(i18n("Ellipse"));
|
|
m_typeCombo->setCurrentIndex(m_geomAnn->geometricalType());
|
|
m_innerColor->setColor(m_geomAnn->geometricalInnerColor());
|
|
if (m_geomAnn->geometricalInnerColor().isValid()) {
|
|
m_useColor->setChecked(true);
|
|
} else {
|
|
m_innerColor->setEnabled(false);
|
|
}
|
|
m_spinSize->setRange(0, 100);
|
|
m_spinSize->setValue(m_geomAnn->style().width());
|
|
|
|
connect(m_typeCombo, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &AnnotationWidget::dataChanged);
|
|
connect(m_innerColor, &KColorButton::changed, this, &AnnotationWidget::dataChanged);
|
|
connect(m_useColor, &QAbstractButton::toggled, this, &AnnotationWidget::dataChanged);
|
|
connect(m_useColor, &QCheckBox::toggled, m_innerColor, &KColorButton::setEnabled);
|
|
connect(m_spinSize, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void GeomAnnotationWidget::applyChanges()
|
|
{
|
|
AnnotationWidget::applyChanges();
|
|
m_geomAnn->setGeometricalType((Okular::GeomAnnotation::GeomType)m_typeCombo->currentIndex());
|
|
if (!m_useColor->isChecked()) {
|
|
m_geomAnn->setGeometricalInnerColor(QColor());
|
|
} else {
|
|
m_geomAnn->setGeometricalInnerColor(m_innerColor->color());
|
|
}
|
|
m_geomAnn->style().setWidth(m_spinSize->value());
|
|
}
|
|
|
|
FileAttachmentAnnotationWidget::FileAttachmentAnnotationWidget(Okular::Annotation *ann)
|
|
: AnnotationWidget(ann)
|
|
, m_pixmapSelector(nullptr)
|
|
{
|
|
m_attachAnn = static_cast<Okular::FileAttachmentAnnotation *>(ann);
|
|
}
|
|
|
|
void FileAttachmentAnnotationWidget::createStyleWidget(QFormLayout *formlayout)
|
|
{
|
|
QWidget *widget = qobject_cast<QWidget *>(formlayout->parent());
|
|
|
|
addOpacitySpinBox(widget, formlayout);
|
|
|
|
m_pixmapSelector = new PixmapPreviewSelector(widget);
|
|
formlayout->addRow(i18n("File attachment symbol:"), m_pixmapSelector);
|
|
m_pixmapSelector->setEditable(true);
|
|
|
|
m_pixmapSelector->addItem(i18nc("Symbol for file attachment annotations", "Graph"), QStringLiteral("graph"));
|
|
m_pixmapSelector->addItem(i18nc("Symbol for file attachment annotations", "Push Pin"), QStringLiteral("pushpin"));
|
|
m_pixmapSelector->addItem(i18nc("Symbol for file attachment annotations", "Paperclip"), QStringLiteral("paperclip"));
|
|
m_pixmapSelector->addItem(i18nc("Symbol for file attachment annotations", "Tag"), QStringLiteral("tag"));
|
|
m_pixmapSelector->setIcon(m_attachAnn->fileIconName());
|
|
|
|
connect(m_pixmapSelector, &PixmapPreviewSelector::iconChanged, this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
QWidget *FileAttachmentAnnotationWidget::createExtraWidget()
|
|
{
|
|
QWidget *widget = new QWidget();
|
|
widget->setWindowTitle(i18nc("'File' as normal file, that can be opened, saved, etc..", "File"));
|
|
|
|
Okular::EmbeddedFile *ef = m_attachAnn->embeddedFile();
|
|
const int size = ef->size();
|
|
const QString sizeString = size <= 0 ? i18nc("Not available size", "N/A") : KFormat().formatByteSize(size);
|
|
const QString descString = ef->description().isEmpty() ? i18n("No description available.") : ef->description();
|
|
|
|
QHBoxLayout *mainLay = new QHBoxLayout(widget);
|
|
QFormLayout *lay = new QFormLayout();
|
|
mainLay->addLayout(lay);
|
|
|
|
QLabel *tmplabel = new QLabel(ef->name(), widget);
|
|
tmplabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
|
lay->addRow(i18n("Name:"), tmplabel);
|
|
|
|
tmplabel = new QLabel(sizeString, widget);
|
|
tmplabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
|
lay->addRow(i18n("&Width:"), tmplabel);
|
|
|
|
tmplabel = new QLabel(widget);
|
|
tmplabel->setTextFormat(Qt::PlainText);
|
|
tmplabel->setWordWrap(true);
|
|
tmplabel->setText(descString);
|
|
tmplabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
|
lay->addRow(i18n("Description:"), tmplabel);
|
|
|
|
QMimeDatabase db;
|
|
QMimeType mime = db.mimeTypeForFile(ef->name(), QMimeDatabase::MatchExtension);
|
|
if (mime.isValid()) {
|
|
tmplabel = new QLabel(widget);
|
|
tmplabel->setPixmap(QIcon::fromTheme(mime.iconName()).pixmap(FILEATTACH_ICONSIZE, FILEATTACH_ICONSIZE));
|
|
tmplabel->setFixedSize(FILEATTACH_ICONSIZE, FILEATTACH_ICONSIZE);
|
|
QVBoxLayout *tmpLayout = new QVBoxLayout(widget);
|
|
tmpLayout->setAlignment(Qt::AlignTop);
|
|
mainLay->addLayout(tmpLayout);
|
|
tmpLayout->addWidget(tmplabel);
|
|
}
|
|
|
|
return widget;
|
|
}
|
|
|
|
void FileAttachmentAnnotationWidget::applyChanges()
|
|
{
|
|
AnnotationWidget::applyChanges();
|
|
m_attachAnn->setFileIconName(m_pixmapSelector->icon());
|
|
}
|
|
|
|
static QString caretSymbolToIcon(Okular::CaretAnnotation::CaretSymbol symbol)
|
|
{
|
|
switch (symbol) {
|
|
case Okular::CaretAnnotation::None:
|
|
return QStringLiteral("caret-none");
|
|
case Okular::CaretAnnotation::P:
|
|
return QStringLiteral("caret-p");
|
|
}
|
|
return QString();
|
|
}
|
|
|
|
static Okular::CaretAnnotation::CaretSymbol caretSymbolFromIcon(const QString &icon)
|
|
{
|
|
if (icon == QLatin1String("caret-none")) {
|
|
return Okular::CaretAnnotation::None;
|
|
} else if (icon == QLatin1String("caret-p")) {
|
|
return Okular::CaretAnnotation::P;
|
|
}
|
|
return Okular::CaretAnnotation::None;
|
|
}
|
|
|
|
CaretAnnotationWidget::CaretAnnotationWidget(Okular::Annotation *ann)
|
|
: AnnotationWidget(ann)
|
|
, m_pixmapSelector(nullptr)
|
|
{
|
|
m_caretAnn = static_cast<Okular::CaretAnnotation *>(ann);
|
|
}
|
|
|
|
void CaretAnnotationWidget::createStyleWidget(QFormLayout *formlayout)
|
|
{
|
|
QWidget *widget = qobject_cast<QWidget *>(formlayout->parent());
|
|
|
|
addColorButton(widget, formlayout);
|
|
addOpacitySpinBox(widget, formlayout);
|
|
|
|
m_pixmapSelector = new PixmapPreviewSelector(widget);
|
|
formlayout->addRow(i18n("Caret symbol:"), m_pixmapSelector);
|
|
|
|
m_pixmapSelector->addItem(i18nc("Symbol for caret annotations", "None"), QStringLiteral("caret-none"));
|
|
m_pixmapSelector->addItem(i18nc("Symbol for caret annotations", "P"), QStringLiteral("caret-p"));
|
|
m_pixmapSelector->setIcon(caretSymbolToIcon(m_caretAnn->caretSymbol()));
|
|
|
|
connect(m_pixmapSelector, &PixmapPreviewSelector::iconChanged, this, &AnnotationWidget::dataChanged);
|
|
}
|
|
|
|
void CaretAnnotationWidget::applyChanges()
|
|
{
|
|
AnnotationWidget::applyChanges();
|
|
m_caretAnn->setCaretSymbol(caretSymbolFromIcon(m_pixmapSelector->icon()));
|
|
}
|
|
|
|
#include "moc_annotationwidgets.cpp"
|