Signature plugin: selection

This commit is contained in:
Jakub Melka 2022-04-02 16:29:31 +02:00
parent f5881b897d
commit 5d8e2818a2
7 changed files with 233 additions and 4 deletions

View File

@ -19,6 +19,7 @@
#include "ui_pdfpagecontenteditorwidget.h"
#include "pdfwidgetutils.h"
#include "pdfpagecontentelements.h"
#include "pdfutils.h"
#include <QAction>
#include <QToolButton>
@ -26,10 +27,12 @@
namespace pdf
{
PDFPageContentEditorWidget::PDFPageContentEditorWidget(QWidget *parent) :
PDFPageContentEditorWidget::PDFPageContentEditorWidget(QWidget* parent) :
QDockWidget(parent),
ui(new Ui::PDFPageContentEditorWidget),
m_toolBoxColumnCount(6)
m_toolBoxColumnCount(6),
m_scene(nullptr),
m_selectionChangeEnabled(true)
{
ui->setupUi(this);
@ -76,6 +79,7 @@ PDFPageContentEditorWidget::PDFPageContentEditorWidget(QWidget *parent) :
connect(&m_actionMapper, &QSignalMapper::mappedObject, this, &PDFPageContentEditorWidget::onActionTriggerRequest);
connect(&m_operationMapper, &QSignalMapper::mappedInt, this, &PDFPageContentEditorWidget::operationTriggered);
connect(ui->itemsListWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &PDFPageContentEditorWidget::onItemSelectionChanged);
}
PDFPageContentEditorWidget::~PDFPageContentEditorWidget()
@ -126,6 +130,56 @@ QToolButton* PDFPageContentEditorWidget::getToolButtonForOperation(int operation
return qobject_cast<QToolButton*>(m_operationMapper.mapping(operation));
}
void PDFPageContentEditorWidget::updateItemsInListWidget()
{
ui->itemsListWidget->setUpdatesEnabled(false);
if (m_scene)
{
std::set<PDFInteger> presentElementIds;
std::set<PDFInteger> elementIds = m_scene->getElementIds();
// Remove items which are not here
for (int i = 0; i < ui->itemsListWidget->count();)
{
QListWidgetItem* item = ui->itemsListWidget->item(i);
const PDFInteger elementId = item->data(Qt::UserRole).toLongLong();
if (!elementIds.count(elementId))
{
delete ui->itemsListWidget->takeItem(i);
}
else
{
presentElementIds.insert(elementId);
++i;
}
}
// Add items which are here
for (PDFInteger elementId : elementIds)
{
if (presentElementIds.count(elementId))
{
continue;
}
const PDFPageContentElement* element = m_scene->getElementById(elementId);
Q_ASSERT(element);
QListWidgetItem* item = new QListWidgetItem(element->getDescription());
item->setData(Qt::UserRole, elementId);
ui->itemsListWidget->addItem(item);
}
}
else
{
ui->itemsListWidget->clear();
}
ui->itemsListWidget->setUpdatesEnabled(true);
}
void PDFPageContentEditorWidget::onActionTriggerRequest(QObject* actionObject)
{
QAction* action = qobject_cast<QAction*>(actionObject);
@ -146,4 +200,55 @@ void PDFPageContentEditorWidget::onActionChanged()
button->setEnabled(action->isEnabled());
}
void PDFPageContentEditorWidget::onItemSelectionChanged()
{
if (m_selectionChangeEnabled)
{
emit itemSelectionChangedByUser();
}
}
PDFPageContentScene* PDFPageContentEditorWidget::scene() const
{
return m_scene;
}
void PDFPageContentEditorWidget::setScene(PDFPageContentScene* newScene)
{
if (m_scene != newScene)
{
m_scene = newScene;
updateItemsInListWidget();
}
}
std::set<PDFInteger> PDFPageContentEditorWidget::getSelection() const
{
std::set<PDFInteger> result;
for (int i = 0; i < ui->itemsListWidget->count(); ++i)
{
QListWidgetItem* item = ui->itemsListWidget->item(i);
if (item->isSelected())
{
const PDFInteger elementId = item->data(Qt::UserRole).toLongLong();
result.insert(elementId);
}
}
return result;
}
void PDFPageContentEditorWidget::setSelection(const std::set<PDFInteger>& selection)
{
pdf::PDFTemporaryValueChange guard(&m_selectionChangeEnabled, false);
for (int i = 0; i < ui->itemsListWidget->count(); ++i)
{
QListWidgetItem* item = ui->itemsListWidget->item(i);
const PDFInteger elementId = item->data(Qt::UserRole).toLongLong();
item->setSelected(selection.count(elementId));
}
}
} // namespace pdf

View File

@ -23,6 +23,8 @@
#include <QDockWidget>
#include <QSignalMapper>
#include <set>
class QToolButton;
namespace Ui
@ -32,6 +34,7 @@ class PDFPageContentEditorWidget;
namespace pdf
{
class PDFPageContentScene;
class PDF4QTLIBSHARED_EXPORT PDFPageContentEditorWidget : public QDockWidget
{
@ -46,18 +49,31 @@ public:
QToolButton* getToolButtonForOperation(int operation) const;
/// Update items in list widget
void updateItemsInListWidget();
PDFPageContentScene* scene() const;
void setScene(PDFPageContentScene* newScene);
std::set<PDFInteger> getSelection() const;
void setSelection(const std::set<PDFInteger>& selection);
signals:
void operationTriggered(int operation);
void itemSelectionChangedByUser();
private:
void onActionTriggerRequest(QObject* actionObject);
void onActionChanged();
void onItemSelectionChanged();
Ui::PDFPageContentEditorWidget* ui;
QSignalMapper m_actionMapper;
QSignalMapper m_operationMapper;
int m_toolBoxColumnCount;
QSize m_toolButtonIconSize;
PDFPageContentScene* m_scene;
bool m_selectionChangeEnabled;
};
} // namespace pdf

View File

@ -170,7 +170,11 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QListView" name="listView"/>
<widget class="QListWidget" name="itemsListWidget">
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>

View File

@ -207,6 +207,11 @@ void PDFPageContentElement::performRectangleSetSize(QRectF& rectangle, QSizeF si
rectangle.translate(0, offset);
}
QString PDFPageContentElement::formatDescription(const QString& description) const
{
return PDFTranslationContext::tr("#%1: %2").arg(getElementId()).arg(description);
}
const QPen& PDFPageContentStyledElement::getPen() const
{
return m_pen;
@ -314,6 +319,11 @@ void PDFPageContentElementRectangle::setSize(QSizeF size)
performRectangleSetSize(m_rectangle, size);
}
QString PDFPageContentElementRectangle::getDescription() const
{
return formatDescription(isRounded() ? PDFTranslationContext::tr("Rounded rectangle") : PDFTranslationContext::tr("Rectangle"));
}
PDFPageContentScene::PDFPageContentScene(QObject* parent) :
QObject(parent),
m_firstFreeId(1),
@ -790,6 +800,7 @@ void PDFPageContentScene::updateMouseCursor(const MouseEventInfo& info, PDFReal
void PDFPageContentScene::onSelectionChanged()
{
emit sceneChanged(true);
emit selectionChanged();
}
PDFWidget* PDFPageContentScene::widget() const
@ -835,6 +846,26 @@ std::set<PDFInteger> PDFPageContentScene::getElementIds() const
return result;
}
std::set<PDFInteger> PDFPageContentScene::getSelectedElementIds() const
{
std::set<PDFInteger> result;
for (const auto& element : m_elements)
{
if (m_manipulator.isSelected(element->getElementId()))
{
result.insert(element->getElementId());
}
}
return result;
}
void PDFPageContentScene::setSelectedElementIds(const std::set<PDFInteger>& selectedElementIds)
{
m_manipulator.selectNew(selectedElementIds);
}
void PDFPageContentScene::removeElementsById(const std::vector<PDFInteger>& selection)
{
const size_t oldSize = m_elements.size();
@ -1000,6 +1031,11 @@ void PDFPageContentElementLine::setSize(QSizeF size)
m_line.setPoints(p1, p2);
}
QString PDFPageContentElementLine::getDescription() const
{
return formatDescription(PDFTranslationContext::tr("Line"));
}
PDFPageContentElementLine::LineGeometry PDFPageContentElementLine::getGeometry() const
{
return m_geometry;
@ -1110,6 +1146,11 @@ void PDFPageContentSvgElement::setSize(QSizeF size)
performRectangleSetSize(m_rectangle, size);
}
QString PDFPageContentSvgElement::getDescription() const
{
return formatDescription(PDFTranslationContext::tr("SVG image"));
}
const QByteArray& PDFPageContentSvgElement::getContent() const
{
return m_content;
@ -1207,6 +1248,11 @@ void PDFPageContentElementDot::setSize(QSizeF size)
Q_UNUSED(size);
}
QString PDFPageContentElementDot::getDescription() const
{
return formatDescription(PDFTranslationContext::tr("Dot"));
}
QPointF PDFPageContentElementDot::getPoint() const
{
return m_point;
@ -1297,6 +1343,11 @@ void PDFPageContentElementFreehandCurve::setSize(QSizeF size)
Q_UNUSED(size);
}
QString PDFPageContentElementFreehandCurve::getDescription() const
{
return formatDescription(PDFTranslationContext::tr("Freehand curve"));
}
QPainterPath PDFPageContentElementFreehandCurve::getCurve() const
{
return m_curve;
@ -2304,6 +2355,11 @@ void PDFPageContentElementTextBox::setSize(QSizeF size)
performRectangleSetSize(m_rectangle, size);
}
QString PDFPageContentElementTextBox::getDescription() const
{
return formatDescription(PDFTranslationContext::tr("Text box '%1'").arg(getText()));
}
const QString& PDFPageContentElementTextBox::getText() const
{
return m_text;

View File

@ -71,6 +71,9 @@ public:
/// nothing for elements, which does not support it.
virtual void setSize(QSizeF size) = 0;
/// Returns description of the element
virtual QString getDescription() const = 0;
PDFInteger getPageIndex() const;
void setPageIndex(PDFInteger newPageIndex);
@ -108,6 +111,8 @@ protected:
void performRectangleSetSize(QRectF& rectangle, QSizeF size);
QString formatDescription(const QString& description) const;
PDFInteger m_elementId = -1;
PDFInteger m_pageIndex = -1;
};
@ -155,6 +160,7 @@ public:
virtual void performManipulation(uint mode, const QPointF& offset) override;
virtual QRectF getBoundingBox() const override;
virtual void setSize(QSizeF size);
virtual QString getDescription() const override;
private:
bool m_rounded = false;
@ -188,6 +194,7 @@ public:
virtual void performManipulation(uint mode, const QPointF& offset) override;
virtual QRectF getBoundingBox() const override;
virtual void setSize(QSizeF size);
virtual QString getDescription() const override;
LineGeometry getGeometry() const;
void setGeometry(LineGeometry newGeometry);
@ -220,6 +227,7 @@ public:
virtual void performManipulation(uint mode, const QPointF& offset) override;
virtual QRectF getBoundingBox() const override;
virtual void setSize(QSizeF size);
virtual QString getDescription() const override;
QPointF getPoint() const;
void setPoint(QPointF newPoint);
@ -248,6 +256,7 @@ public:
virtual void performManipulation(uint mode, const QPointF& offset) override;
virtual QRectF getBoundingBox() const override;
virtual void setSize(QSizeF size);
virtual QString getDescription() const override;
QPainterPath getCurve() const;
void setCurve(QPainterPath newCurve);
@ -282,6 +291,7 @@ public:
virtual void performManipulation(uint mode, const QPointF& offset) override;
virtual QRectF getBoundingBox() const override;
virtual void setSize(QSizeF size);
virtual QString getDescription() const override;
const QByteArray& getContent() const;
void setContent(const QByteArray& newContent);
@ -318,6 +328,7 @@ public:
virtual void performManipulation(uint mode, const QPointF& offset) override;
virtual QRectF getBoundingBox() const override;
virtual void setSize(QSizeF size);
virtual QString getDescription() const override;
const QString& getText() const;
void setText(const QString& newText);
@ -489,6 +500,12 @@ public:
/// Returns set of all element ids
std::set<PDFInteger> getElementIds() const;
/// Returns set of selected element ids
std::set<PDFInteger> getSelectedElementIds() const;
/// Set selected items
void setSelectedElementIds(const std::set<PDFInteger>& selectedElementIds);
/// Removes elements specified in selection
/// \param selection Items to be removed
void removeElementsById(const std::vector<PDFInteger>& selection);
@ -528,6 +545,8 @@ signals:
/// This signal is emitted when scene has changed (including graphics)
void sceneChanged(bool graphicsOnly);
void selectionChanged();
private:
struct MouseEventInfo

View File

@ -17,6 +17,7 @@
#include "signatureplugin.h"
#include "pdfdrawwidget.h"
#include "pdfutils.h"
#include "pdfpagecontenteditorwidget.h"
#include <QAction>
@ -31,7 +32,8 @@ SignaturePlugin::SignaturePlugin() :
m_actions({ }),
m_tools({ }),
m_editorWidget(nullptr),
m_scene(nullptr)
m_scene(nullptr),
m_sceneSelectionChangeEnabled(true)
{
}
@ -143,6 +145,7 @@ void SignaturePlugin::setWidget(pdf::PDFWidget* widget)
m_widget->getDrawWidgetProxy()->registerDrawInterface(&m_scene);
m_scene.setWidget(m_widget);
connect(&m_scene, &pdf::PDFPageContentScene::sceneChanged, this, &SignaturePlugin::onSceneChanged);
connect(&m_scene, &pdf::PDFPageContentScene::selectionChanged, this, &SignaturePlugin::onSceneSelectionChanged);
connect(clearAction, &QAction::triggered, &m_scene, &pdf::PDFPageContentScene::clear);
connect(activateAction, &QAction::triggered, this, &SignaturePlugin::setActive);
@ -179,9 +182,30 @@ void SignaturePlugin::onSceneChanged(bool graphicsOnly)
updateActions();
}
if (m_editorWidget)
{
m_editorWidget->updateItemsInListWidget();
}
updateGraphics();
}
void SignaturePlugin::onSceneSelectionChanged()
{
if (m_editorWidget && m_sceneSelectionChangeEnabled)
{
m_editorWidget->setSelection(m_scene.getSelectedElementIds());
}
}
void SignaturePlugin::onWidgetSelectionChanged()
{
Q_ASSERT(m_editorWidget);
pdf::PDFTemporaryValueChange guard(&m_sceneSelectionChangeEnabled, false);
m_scene.setSelectedElementIds(m_editorWidget->getSelection());
}
void SignaturePlugin::setActive(bool active)
{
if (m_scene.isActive() != active)
@ -276,7 +300,9 @@ void SignaturePlugin::updateDockWidget()
m_dataExchangeInterface->getMainWindow()->addDockWidget(Qt::RightDockWidgetArea, m_editorWidget, Qt::Vertical);
m_editorWidget->setFloating(false);
m_editorWidget->setWindowTitle(tr("Signature Toolbox"));
m_editorWidget->setScene(&m_scene);
connect(m_editorWidget, &pdf::PDFPageContentEditorWidget::operationTriggered, &m_scene, &pdf::PDFPageContentScene::performOperation);
connect(m_editorWidget, &pdf::PDFPageContentEditorWidget::itemSelectionChangedByUser, this, &SignaturePlugin::onWidgetSelectionChanged);
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::AlignTop))->setIcon(QIcon(":/resources/pce-align-top.svg"));
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::AlignCenterVertically))->setIcon(QIcon(":/resources/pce-align-v-center.svg"));

View File

@ -49,6 +49,8 @@ public:
private:
void onSceneChanged(bool graphicsOnly);
void onSceneSelectionChanged();
void onWidgetSelectionChanged();
enum Action
{
@ -103,6 +105,7 @@ private:
pdf::PDFPageContentEditorWidget* m_editorWidget;
pdf::PDFPageContentScene m_scene;
bool m_sceneSelectionChangeEnabled;
};
} // namespace pdfplugin