Editor plugin: Style of text and paths

This commit is contained in:
Jakub Melka 2024-06-22 17:43:41 +02:00
parent 1ffd5c6a16
commit ba0dd9e891
6 changed files with 400 additions and 4 deletions

View File

@ -49,6 +49,10 @@ EditorPlugin::EditorPlugin() :
m_scene.setIsPageContentDrawSuppressed(true);
}
// TODO: When text is edited, old text remains
// TODO: Color of the text is unchanged
// TODO: Moznost nastavit fill / stroke bool
void EditorPlugin::setWidget(pdf::PDFWidget* widget)
{
Q_ASSERT(!m_widget);
@ -189,7 +193,14 @@ bool EditorPlugin::save()
{
pdf::PDFTemporaryValueChange guard(&m_isSaving, true);
if (QMessageBox::question(m_dataExchangeInterface->getMainWindow(), tr("Confirm Changes"), tr("The changes to the page content will be written to the document. Do you want to continue?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
auto answer = QMessageBox::question(m_dataExchangeInterface->getMainWindow(), tr("Confirm Changes"), tr("The changes to the page content will be written to the document. Do you want to continue?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel);
if (answer == QMessageBox::Cancel)
{
return false;
}
if (answer == QMessageBox::Yes)
{
pdf::PDFDocumentModifier modifier(m_document);
@ -590,6 +601,7 @@ void EditorPlugin::onSetActive(bool active)
if (!active && !save())
{
updateActions();
m_actions[Activate]->setChecked(true);
return;
}

View File

@ -1985,7 +1985,8 @@ PDFEncodedText PDFSimpleFont::encodeText(const QString& text) const
bool isFound = false;
for (size_t i = 0; i < encodingTable->size(); ++i)
{
if (unicode == (*encodingTable)[static_cast<unsigned char>(i)])
if (unicode == (*encodingTable)[static_cast<unsigned char>(i)] &&
m_glyphIndices[i] != GID())
{
isFound = true;
converted = static_cast<unsigned char>(i);

View File

@ -98,7 +98,7 @@ struct PDFOverprintMode
/// Represents graphic state of the PDF (holding current graphic state parameters).
/// Please see PDF Reference 1.7, Chapter 4.3 "Graphic State"
class PDFPageContentProcessorState
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentProcessorState
{
public:
explicit PDFPageContentProcessorState();

View File

@ -27,6 +27,7 @@
#include <QFileDialog>
#include <QImageReader>
#include <QStandardPaths>
#include <QColorDialog>
namespace pdf
{
@ -37,6 +38,48 @@ PDFPageContentEditorEditedItemSettings::PDFPageContentEditorEditedItemSettings(Q
{
ui->setupUi(this);
connect(ui->loadImageButton, &QPushButton::clicked, this, &PDFPageContentEditorEditedItemSettings::selectImage);
for (const QString& colorName : QColor::colorNames())
{
QColor color(colorName);
QIcon icon = getIconForColor(color);
ui->penColorCombo->addItem(icon, colorName, color);
ui->brushColorCombo->addItem(icon, colorName, color);
}
ui->penStyleCombo->addItem(tr("None"), int(Qt::NoPen));
ui->penStyleCombo->addItem(tr("Solid"), int(Qt::SolidLine));
ui->penStyleCombo->addItem(tr("Dashed"), int(Qt::DashLine));
ui->penStyleCombo->addItem(tr("Dotted"), int(Qt::DotLine));
ui->penStyleCombo->addItem(tr("Dash-dot"), int(Qt::DashDotLine));
ui->penStyleCombo->addItem(tr("Dash-dot-dot"), int(Qt::DashDotDotLine));
ui->brushStyleCombo->addItem(tr("None"), int(Qt::NoBrush));
ui->brushStyleCombo->addItem(tr("Solid"), int(Qt::SolidPattern));
connect(ui->selectPenColorButton, &QToolButton::clicked, this, &PDFPageContentEditorEditedItemSettings::onSelectPenColorButtonClicked);
connect(ui->selectBrushColorButton, &QToolButton::clicked, this, &PDFPageContentEditorEditedItemSettings::onSelectBrushColorButtonClicked);
connect(ui->penWidthEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &PDFPageContentEditorEditedItemSettings::onPenWidthChanged);
connect(ui->penStyleCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PDFPageContentEditorEditedItemSettings::onPenStyleChanged);
connect(ui->brushStyleCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PDFPageContentEditorEditedItemSettings::onBrushStyleChanged);
connect(ui->penColorCombo->lineEdit(), &QLineEdit::editingFinished, this, &PDFPageContentEditorEditedItemSettings::onPenColorComboTextChanged);
connect(ui->penColorCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PDFPageContentEditorEditedItemSettings::onPenColorComboIndexChanged);
connect(ui->brushColorCombo->lineEdit(), &QLineEdit::editingFinished, this, &PDFPageContentEditorEditedItemSettings::onBrushColorComboTextChanged);
connect(ui->brushColorCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PDFPageContentEditorEditedItemSettings::onBrushColorComboIndexChanged);
}
QIcon PDFPageContentEditorEditedItemSettings::getIconForColor(QColor color) const
{
QIcon icon;
QSize iconSize = PDFWidgetUtils::scaleDPI(this, QSize(16, 16));
QPixmap pixmap(iconSize.width(), iconSize.height());
pixmap.fill(color);
icon.addPixmap(pixmap);
return icon;
}
PDFPageContentEditorEditedItemSettings::~PDFPageContentEditorEditedItemSettings()
@ -67,6 +110,11 @@ void PDFPageContentEditorEditedItemSettings::loadFromElement(PDFPageContentEleme
ui->plainTextEdit->setPlainText(text);
}
if (editedElement->getElement()->asText() || editedElement->getElement()->asPath())
{
ui->tabWidget->addTab(ui->styleTab, tr("Style"));
}
QTransform matrix = editedElement->getElement()->getTransform();
PDFTransformationDecomposition decomposedTransformation = PDFPainterHelper::decomposeTransform(matrix);
@ -78,6 +126,101 @@ void PDFPageContentEditorEditedItemSettings::loadFromElement(PDFPageContentEleme
ui->translateInYEdit->setValue(decomposedTransformation.translateY);
ui->tabWidget->addTab(ui->transformationTab, tr("Transformation"));
// Style
const PDFEditedPageContentElement* element = editedElement->getElement();
StyleFeatures features = None;
if (element->asPath())
{
features.setFlag(Pen);
features.setFlag(PenColor);
features.setFlag(Brush);
}
if (element->asText())
{
features.setFlag(PenColor);
}
const bool hasPen = features.testFlag(Pen);
const bool hasPenColor = features.testFlag(PenColor);
const bool hasBrush = features.testFlag(Brush);
ui->penWidthEdit->setEnabled(hasPen);
ui->penWidthLabel->setEnabled(hasPen);
ui->penStyleCombo->setEnabled(hasPen);
ui->penStyleLabel->setEnabled(hasPen);
ui->penColorCombo->setEnabled(hasPenColor);
ui->penColorLabel->setEnabled(hasPenColor);
ui->selectPenColorButton->setEnabled(hasPenColor);
ui->brushStyleLabel->setEnabled(hasBrush);
ui->brushStyleCombo->setEnabled(hasBrush);
ui->brushColorCombo->setEnabled(hasBrush);
ui->brushColorLabel->setEnabled(hasBrush);
ui->selectBrushColorButton->setEnabled(hasBrush);
const PDFPageContentProcessorState& graphicState = element->getState();
QPen pen = pdf::PDFPainterHelper::createPenFromState(&graphicState, graphicState.getAlphaStroking());
QBrush brush = pdf::PDFPainterHelper::createBrushFromState(&graphicState, graphicState.getAlphaFilling());
setPen(pen, true);
setBrush(brush, true);
}
void PDFPageContentEditorEditedItemSettings::setPen(const QPen& pen, bool forceUpdate)
{
if (m_pen != pen || forceUpdate)
{
m_pen = pen;
ui->penWidthEdit->setValue(pen.widthF());
ui->penStyleCombo->setCurrentIndex(ui->penStyleCombo->findData(int(pen.style())));
setColorToComboBox(ui->penColorCombo, pen.color());
}
}
void PDFPageContentEditorEditedItemSettings::setBrush(const QBrush& brush, bool forceUpdate)
{
if (m_brush != brush || forceUpdate)
{
m_brush = brush;
ui->brushStyleCombo->setCurrentIndex(ui->brushStyleCombo->findData(int(brush.style())));
setColorToComboBox(ui->brushColorCombo, brush.color());
}
}
void PDFPageContentEditorEditedItemSettings::setColorToComboBox(QComboBox* comboBox, QColor color)
{
if (!color.isValid())
{
return;
}
QString name = color.name(QColor::HexArgb);
int index = comboBox->findData(color, Qt::UserRole, Qt::MatchExactly);
if (index == -1)
{
// Jakub Melka: try to find text (color name)
index = comboBox->findText(name);
}
if (index != -1)
{
comboBox->setCurrentIndex(index);
}
else
{
comboBox->addItem(getIconForColor(color), name, color);
comboBox->setCurrentIndex(comboBox->count() - 1);
}
}
void PDFPageContentEditorEditedItemSettings::saveToElement(PDFPageContentElementEdited* editedElement)
@ -103,6 +246,16 @@ void PDFPageContentEditorEditedItemSettings::saveToElement(PDFPageContentElement
QTransform transform = PDFPainterHelper::composeTransform(decomposedTransformation);
editedElement->getElement()->setTransform(transform);
if (editedElement->getElement()->asText() || editedElement->getElement()->asPath())
{
PDFPageContentProcessorState graphicState = editedElement->getElement()->getState();
PDFPainterHelper::applyPenToGraphicState(&graphicState, m_pen);
PDFPainterHelper::applyBrushToGraphicState(&graphicState, m_brush);
editedElement->getElement()->setState(graphicState);
}
}
static int PDF_gcd(int a, int b)
@ -185,4 +338,109 @@ void PDFPageContentEditorEditedItemSettings::selectImage()
}
}
void PDFPageContentEditorEditedItemSettings::setPenColor(QColor color)
{
if (color.isValid())
{
m_pen.setColor(color);
setColorToComboBox(ui->penColorCombo, color);
}
}
void PDFPageContentEditorEditedItemSettings::onSelectPenColorButtonClicked()
{
QColor color = QColorDialog::getColor(m_pen.color(), this, tr("Select Color for Pen"), QColorDialog::ShowAlphaChannel);
setPenColor(color);
}
void PDFPageContentEditorEditedItemSettings::setBrushColor(QColor color)
{
if (color.isValid() && m_brush.color() != color)
{
m_brush.setColor(color);
setColorToComboBox(ui->brushColorCombo, color);
}
}
const QBrush& PDFPageContentEditorEditedItemSettings::getBrush() const
{
return m_brush;
}
const QPen& PDFPageContentEditorEditedItemSettings::getPen() const
{
return m_pen;
}
void PDFPageContentEditorEditedItemSettings::onSelectBrushColorButtonClicked()
{
QColor color = QColorDialog::getColor(m_pen.color(), this, tr("Select Color for Brush"), QColorDialog::ShowAlphaChannel);
setBrushColor(color);
}
void PDFPageContentEditorEditedItemSettings::onPenWidthChanged(double value)
{
m_pen.setWidthF(value);
}
void PDFPageContentEditorEditedItemSettings::onPenStyleChanged()
{
Qt::PenStyle penStyle = static_cast<Qt::PenStyle>(ui->penStyleCombo->currentData().toInt());
m_pen.setStyle(penStyle);
}
void PDFPageContentEditorEditedItemSettings::onBrushStyleChanged()
{
Qt::BrushStyle brushStyle = static_cast<Qt::BrushStyle>(ui->brushStyleCombo->currentData().toInt());
m_brush.setStyle(brushStyle);
}
void PDFPageContentEditorEditedItemSettings::onPenColorComboTextChanged()
{
QColor color(ui->penColorCombo->currentText());
if (color.isValid())
{
setColorToComboBox(ui->penColorCombo, color);
m_pen.setColor(color);
}
else if (ui->penColorCombo->currentIndex() != -1)
{
ui->penColorCombo->setEditText(ui->penColorCombo->itemText(ui->penColorCombo->currentIndex()));
}
}
void PDFPageContentEditorEditedItemSettings::onPenColorComboIndexChanged()
{
const int index = ui->penColorCombo->currentIndex();
QColor color = ui->penColorCombo->itemData(index, Qt::UserRole).value<QColor>();
if (color.isValid() && m_pen.color() != color)
{
m_pen.setColor(color);
}
}
void PDFPageContentEditorEditedItemSettings::onBrushColorComboTextChanged()
{
QColor color(ui->brushColorCombo->currentText());
if (color.isValid())
{
setColorToComboBox(ui->brushColorCombo, color);
m_brush.setColor(color);
}
else if (ui->brushColorCombo->currentIndex() != -1)
{
ui->brushColorCombo->setEditText(ui->brushColorCombo->itemText(ui->brushColorCombo->currentIndex()));
}
}
void PDFPageContentEditorEditedItemSettings::onBrushColorComboIndexChanged()
{
const int index = ui->brushColorCombo->currentIndex();
QColor color = ui->brushColorCombo->itemData(index, Qt::UserRole).value<QColor>();
if (color.isValid())
{
m_brush.setColor(color);
}
}
} // namespace pdf

View File

@ -19,8 +19,13 @@
#define PDFPAGECONTENTEDITOREDITEDITEMSETTINGS_H
#include <QDialog>
#include <QPen>
#include <QBrush>
namespace Ui {
class QComboBox;
namespace Ui
{
class PDFPageContentEditorEditedItemSettings;
}
@ -39,12 +44,45 @@ public:
void loadFromElement(PDFPageContentElementEdited* editedElement);
void saveToElement(PDFPageContentElementEdited* editedElement);
void setPen(const QPen& pen, bool forceUpdate);
void setBrush(const QBrush& brush, bool forceUpdate);
const QPen& getPen() const;
const QBrush& getBrush() const;
private:
void onSelectPenColorButtonClicked();
void onSelectBrushColorButtonClicked();
void onPenWidthChanged(double value);
void onPenStyleChanged();
void onBrushStyleChanged();
void onPenColorComboTextChanged();
void onPenColorComboIndexChanged();
void onBrushColorComboTextChanged();
void onBrushColorComboIndexChanged();
void setImage(QImage image);
void selectImage();
enum StyleFeature
{
None = 0,
Pen = 1 << 0,
PenColor = 1 << 1,
Brush = 1 << 2
};
Q_DECLARE_FLAGS(StyleFeatures, StyleFeature)
void setColorToComboBox(QComboBox* comboBox, QColor color);
QIcon getIconForColor(QColor color) const;
void setPenColor(QColor color);
void setBrushColor(QColor color);
Ui::PDFPageContentEditorEditedItemSettings* ui;
QImage m_image;
QPen m_pen;
QBrush m_brush;
};
} // namespace pdf

View File

@ -138,6 +138,93 @@
<attribute name="title">
<string>Style</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QComboBox" name="penColorCombo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="penStyleLabel">
<property name="text">
<string>Pen Style</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QDoubleSpinBox" name="penWidthEdit"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="brushColorLabel">
<property name="text">
<string>Brush Color</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QToolButton" name="selectBrushColorButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="selectPenColorButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QComboBox" name="penStyleCombo"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="penWidthLabel">
<property name="text">
<string>Pen Width</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="brushStyleLabel">
<property name="text">
<string>Brush Style</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="penColorLabel">
<property name="text">
<string>Pen Color</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QComboBox" name="brushStyleCombo"/>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="brushColorCombo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="transformationTab">
<attribute name="title">