okular/part/annotationwidgets.cpp

861 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;
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, &QComboBox::currentIndexChanged, this, [this](int index) { iconComboChanged(m_comboItems->itemText(index)); });
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"