From 3e2f351c0e1b2e11e85218d408e8e2daaa238b96 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sun, 29 Nov 2020 18:36:59 +0100 Subject: [PATCH] Mapper commiting --- PdfForQtLib/sources/pdfdocumentbuilder.cpp | 4 +- PdfForQtLib/sources/pdfencoding.cpp | 2 +- PdfForQtLib/sources/pdfencoding.h | 2 +- PdfForQtLib/sources/pdfobjecteditormodel.cpp | 83 +++++ PdfForQtLib/sources/pdfobjecteditormodel.h | 28 +- PdfForQtLib/sources/pdfobjecteditorwidget.cpp | 336 +++++++++++++++++- PdfForQtLib/sources/pdfobjecteditorwidget.h | 24 +- .../sources/pdfobjecteditorwidget_impl.h | 153 ++++++-- 8 files changed, 577 insertions(+), 55 deletions(-) diff --git a/PdfForQtLib/sources/pdfdocumentbuilder.cpp b/PdfForQtLib/sources/pdfdocumentbuilder.cpp index 870727f..fe35d1f 100644 --- a/PdfForQtLib/sources/pdfdocumentbuilder.cpp +++ b/PdfForQtLib/sources/pdfdocumentbuilder.cpp @@ -283,7 +283,7 @@ PDFObjectFactory& PDFObjectFactory::operator<<(AnnotationBorderStyle style) PDFObjectFactory& PDFObjectFactory::operator<<(const QDateTime& dateTime) { - addObject(PDFObject::createString(PDFEncoding::converDateTimeToString(dateTime))); + addObject(PDFObject::createString(PDFEncoding::convertDateTimeToString(dateTime))); return *this; } @@ -527,7 +527,7 @@ PDFObjectFactory& PDFObjectFactory::operator<<(WrapAnnotationColor color) PDFObjectFactory& PDFObjectFactory::operator<<(WrapCurrentDateTime) { - addObject(PDFObject::createString(PDFEncoding::converDateTimeToString(QDateTime::currentDateTime()))); + addObject(PDFObject::createString(PDFEncoding::convertDateTimeToString(QDateTime::currentDateTime()))); return *this; } diff --git a/PdfForQtLib/sources/pdfencoding.cpp b/PdfForQtLib/sources/pdfencoding.cpp index 6f468d0..141afcb 100644 --- a/PdfForQtLib/sources/pdfencoding.cpp +++ b/PdfForQtLib/sources/pdfencoding.cpp @@ -2308,7 +2308,7 @@ QDateTime PDFEncoding::convertToDateTime(const QByteArray& stream) return QDateTime(); } -QByteArray PDFEncoding::converDateTimeToString(QDateTime dateTime) +QByteArray PDFEncoding::convertDateTimeToString(QDateTime dateTime) { QDateTime utcDateTime = dateTime.toUTC(); QString convertedDateTime = QString("D:%1").arg(utcDateTime.toString("yyyyMMddhhmmss")); diff --git a/PdfForQtLib/sources/pdfencoding.h b/PdfForQtLib/sources/pdfencoding.h index b5f070c..4d5ed1c 100644 --- a/PdfForQtLib/sources/pdfencoding.h +++ b/PdfForQtLib/sources/pdfencoding.h @@ -105,7 +105,7 @@ public: /// Convert date/time to string according to PDF Reference 1.7, Chapter 3.8.1. /// If date is invalid, empty byte array is returned. /// \param dateTime Date and time to be converted - static QByteArray converDateTimeToString(QDateTime dateTime); + static QByteArray convertDateTimeToString(QDateTime dateTime); /// Returns conversion table for particular encoding /// \param encoding Encoding diff --git a/PdfForQtLib/sources/pdfobjecteditormodel.cpp b/PdfForQtLib/sources/pdfobjecteditormodel.cpp index e60b875..bdc7d57 100644 --- a/PdfForQtLib/sources/pdfobjecteditormodel.cpp +++ b/PdfForQtLib/sources/pdfobjecteditormodel.cpp @@ -101,6 +101,12 @@ bool PDFObjectEditorAbstractModel::queryAttribute(size_t index, Question questio case Question::IsAttributeEditable: return queryAttribute(index, Question::HasAttribute) && !attribute.attributeFlags.testFlag(PDFObjectEditorModelAttribute::Readonly); + case Question::IsSelector: + return attribute.attributeFlags.type == ObjectEditorAttributeType::Selector; + + case Question::IsPersisted: + return !queryAttribute(index, Question::IsSelector) && !attribute.dictionaryAttribute.isEmpty(); + default: break; } @@ -113,6 +119,45 @@ bool PDFObjectEditorAbstractModel::getSelectorValue(size_t index) const return m_attributes.at(index).selectorAttributeValue; } +void PDFObjectEditorAbstractModel::setSelectorValue(size_t index, bool value) +{ + m_attributes.at(index).selectorAttributeValue = value; +} + +std::vector PDFObjectEditorAbstractModel::getSelectorAttributes() const +{ + std::vector result; + result.reserve(8); // Estimate maximal number of selectors + + const size_t count = getAttributeCount(); + for (size_t i = 0; i < count; ++i) + { + if (queryAttribute(i, Question::IsSelector)) + { + result.push_back(i); + } + } + + return result; +} + +std::vector PDFObjectEditorAbstractModel::getSelectorDependentAttributes(size_t selector) const +{ + std::vector result; + result.reserve(16); // Estimate maximal number of selector's attributes + + const size_t count = getAttributeCount(); + for (size_t i = 0; i < count; ++i) + { + if (m_attributes.at(i).selectorAttribute == selector) + { + result.push_back(i); + } + } + + return result; +} + PDFObject PDFObjectEditorAbstractModel::getValue(size_t index) const { const QByteArrayList& dictionaryAttribute = m_attributes.at(index).dictionaryAttribute; @@ -147,6 +192,44 @@ PDFObject PDFObjectEditorAbstractModel::getDefaultValue(size_t index) const return m_attributes.at(index).defaultValue; } +void PDFObjectEditorAbstractModel::setEditedObject(PDFObject object) +{ + if (m_editedObject != object) + { + m_editedObject = qMove(object); + emit editedObjectChanged(); + } +} + +PDFObject PDFObjectEditorAbstractModel::writeAttributeValueToObject(size_t attribute, PDFObject object, PDFObject value) const +{ + Q_ASSERT(queryAttribute(attribute, Question::IsPersisted)); + + PDFObjectFactory factory; + factory.beginDictionary(); + + const QByteArrayList& dictionaryAttribute = m_attributes.at(index).dictionaryAttribute; + const int pathDepth = dictionaryAttribute.size() - 1; + for (int i = 0; i < pathDepth; ++i) + { + factory.beginDictionaryItem(dictionaryAttribute[i]); + factory.beginDictionary(); + } + + factory.beginDictionaryItem(dictionaryAttribute.back()); + factory << qMove(value); + factory.endDictionaryItem(); + + for (int i = 0; i < pathDepth; ++i) + { + factory.endDictionary(); + factory.endDictionaryItem(); + } + + factory.endDictionaryItem(); + return PDFObjectManipulator::merge(qMove(object), factory.takeObject(), PDFObjectManipulator::RemoveNullObjects); +} + size_t PDFObjectEditorAbstractModel::createAttribute(ObjectEditorAttributeType type, QByteArray attributeName, QString category, diff --git a/PdfForQtLib/sources/pdfobjecteditormodel.h b/PdfForQtLib/sources/pdfobjecteditormodel.h index 8b50855..ac46d46 100644 --- a/PdfForQtLib/sources/pdfobjecteditormodel.h +++ b/PdfForQtLib/sources/pdfobjecteditormodel.h @@ -128,19 +128,41 @@ public: enum class Question { - IsMapped, - HasAttribute, - IsAttributeEditable + IsMapped, ///< Is attribute mapped in gui? + IsSelector, ///< Is attribute's role a selector for other attributes? + IsPersisted, ///< Is attribute persisted to edited object? + HasAttribute, ///< Does current object has given attribute? + IsAttributeEditable ///< Is current attribute editable (this implies previous flag) ? }; bool queryAttribute(size_t index, Question question) const; bool getSelectorValue(size_t index) const; + void setSelectorValue(size_t index, bool value); + + /// Returns vector of attributes, which are of type selector + std::vector getSelectorAttributes() const; + + /// Returns vector of attributes, which are turned on/off + /// by this selector. + std::vector getSelectorDependentAttributes(size_t selector) const; + PDFObject getValue(size_t index) const; PDFObject getDefaultValue(size_t index) const; + PDFObject getEditedObject() const { return m_editedObject; } + void setEditedObject(PDFObject object); + + /// Writes attribute value to the object. + /// \param attribute Attribute + /// \param object Old object + /// \param value Value + PDFObject writeAttributeValueToObject(size_t attribute, PDFObject object, PDFObject value) const; const PDFObjectStorage* getStorage() const { return m_storage; } +signals: + void editedObjectChanged(); + protected: size_t createAttribute(ObjectEditorAttributeType type, QByteArray attributeName, diff --git a/PdfForQtLib/sources/pdfobjecteditorwidget.cpp b/PdfForQtLib/sources/pdfobjecteditorwidget.cpp index 1df3760..fba76ba 100644 --- a/PdfForQtLib/sources/pdfobjecteditorwidget.cpp +++ b/PdfForQtLib/sources/pdfobjecteditorwidget.cpp @@ -18,6 +18,7 @@ #include "pdfobjecteditorwidget.h" #include "pdfobjecteditorwidget_impl.h" #include "pdfdocumentbuilder.h" +#include "pdfencoding.h" #include #include @@ -29,11 +30,14 @@ #include #include #include +#include +#include +#include namespace pdf { -PDFObjectEditorWidget::PDFObjectEditorWidget(PDFObjectEditorAbstractModel* model, QWidget* parent) : +PDFObjectEditorWidget::PDFObjectEditorWidget(EditObjectType type, QWidget* parent) : BaseClass(parent), m_mapper(nullptr), m_tabWidget(nullptr) @@ -42,15 +46,29 @@ PDFObjectEditorWidget::PDFObjectEditorWidget(PDFObjectEditorAbstractModel* model m_tabWidget = new QTabWidget(this); layout->addWidget(m_tabWidget); + PDFObjectEditorAbstractModel* model = nullptr; + switch (type) + { + case EditObjectType::Annotation: + model = new PDFObjectEditorAnnotationsModel(this); + break; + + default: + Q_ASSERT(false); + break; + } + Q_ASSERT(model); + m_mapper = new PDFObjectEditorWidgetMapper(model, this); m_mapper->initialize(m_tabWidget); } PDFObjectEditorWidgetMapper::PDFObjectEditorWidgetMapper(PDFObjectEditorAbstractModel* model, QObject* parent) : BaseClass(parent), - m_model(model) + m_model(model), + m_isCommitingDisabled(false) { - + connect(model, &PDFObjectEditorAbstractModel::editedObjectChanged, this, &PDFObjectEditorWidgetMapper::onEditedObjectChanged); } void PDFObjectEditorWidgetMapper::initialize(QTabWidget* tabWidget) @@ -99,6 +117,78 @@ void PDFObjectEditorWidgetMapper::initialize(QTabWidget* tabWidget) } } +void PDFObjectEditorWidgetMapper::onEditedObjectChanged() +{ + if (!m_isCommitingDisabled) + { + loadWidgets(); + } +} + +void PDFObjectEditorWidgetMapper::onCommitRequested(size_t attribute) +{ + if (m_isCommitingDisabled) + { + // Jakub Melka: Commit is disabled + return; + } + + PDFTemporaryValueChange guard(&m_isCommitingDisabled, true); + + // We will create a new object using several steps. We merge + // the resulting object with old one (so data, that are not + // edited, will remain). Steps: + // 1) If object is selector attribute, and it is turned on, + // set default values to selector's attributes and set + // selector value. + // 2) If object is selector attributem and it is turned off, + // set null values to selector's attributes and set selector + // value. + // 3) For ordinary attributes, commit new value of the attribute + // to the object. + // 4) Iterate each attribute, and if it doesn't exist, then set + // it to null in the object. If it exists, and it is constant, + // then add constant to the object. + // 5) Set final object as new object + + PDFObject object = m_model->getEditedObject(); + + // Steps 1) and 2) + if (m_model->queryAttribute(attribute, PDFObjectEditorAbstractModel::Question::IsSelector)) + { + const bool isChecked = m_adapters[attribute]->getValue().getBool(); + m_model->setSelectorValue(attribute, isChecked); + + std::vector dependentAttributes = m_model->getSelectorDependentAttributes(attribute); + if (isChecked) + { + for (size_t dependentAttribute : dependentAttributes) + { + object = m_model->writeAttributeValueToObject(dependentAttribute, object, m_model->getDefaultValue(dependentAttribute)); + } + } + else + { + for (size_t dependentAttribute : dependentAttributes) + { + object = m_model->writeAttributeValueToObject(dependentAttribute, object, PDFObject()); + } + } + } + else + { + // Step 3) - normal attribute + object = m_model->writeAttributeValueToObject(attribute, object, m_adapters[attribute]->getValue()); + } + + // Step 4) + s + + m_model->setEditedObject(object); + + loadWidgets(); +} + void PDFObjectEditorWidgetMapper::createMappedAdapter(QGroupBox* groupBox, QGridLayout* layout, size_t attribute) { auto setAdapter = [this, attribute](PDFObjectEditorMappedWidgetAdapter* adapter) @@ -156,6 +246,7 @@ void PDFObjectEditorWidgetMapper::createMappedAdapter(QGroupBox* groupBox, QGrid QLabel* label = new QLabel(groupBox); QPushButton* pushButton = new QPushButton(groupBox); + pushButton->setText(tr("Rectangle")); pushButton->setFlat(true); layout->addWidget(label, row, 0); @@ -165,16 +256,84 @@ void PDFObjectEditorWidgetMapper::createMappedAdapter(QGroupBox* groupBox, QGrid break; } + case ObjectEditorAttributeType::DateTime: + { + int row = layout->rowCount(); + + QLabel* label = new QLabel(groupBox); + QDateTimeEdit* dateTimeEdit = new QDateTimeEdit(groupBox); + + layout->addWidget(label, row, 0); + layout->addWidget(dateTimeEdit, row, 1); + + setAdapter(new PDFObjectEditorMappedDateTimeAdapter(label, dateTimeEdit, m_model, attribute, this)); + break; + } + + case ObjectEditorAttributeType::Flags: + { + int row = layout->rowCount(); + int column = 0; + + std::vector> flagCheckboxes; + const PDFObjectEditorModelAttributeEnumItems& flagItems = m_model->getAttributeEnumItems(attribute); + flagCheckboxes.reserve(flagItems.size()); + + for (const PDFObjectEditorModelAttributeEnumItem& flagItem : flagItems) + { + if (column == 2) + { + row++; + column = 0; + } + + QCheckBox* checkBox = new QCheckBox(flagItem.name, groupBox); + layout->addWidget(checkBox, row, column); + flagCheckboxes.emplace_back(flagItem.flags, checkBox); + + ++column; + } + + setAdapter(new PDFObjectEditorMappedFlagsAdapter(qMove(flagCheckboxes), m_model, attribute, this)); + break; + } + + case ObjectEditorAttributeType::Selector: + case ObjectEditorAttributeType::Boolean: + { + int row = layout->rowCount(); + + QLabel* label = new QLabel(groupBox); + QCheckBox* checkBox = new QCheckBox(groupBox); + + layout->addWidget(label, row, 0); + layout->addWidget(checkBox, row, 1); + + setAdapter(new PDFObjectEditorMappedCheckBoxAdapter(label, checkBox, m_model, attribute, this)); + break; + } + + case ObjectEditorAttributeType::Color: + { + int row = layout->rowCount(); + + QLabel* label = new QLabel(groupBox); + QPushButton* pushButton = new QPushButton(groupBox); + pushButton->setText(tr("Color")); + pushButton->setFlat(true); + + layout->addWidget(label, row, 0); + layout->addWidget(pushButton, row, 1); + + setAdapter(new PDFObjectEditorMappedColorAdapter(label, pushButton, m_model, attribute, this)); + break; + } + default: Q_ASSERT(false); } -x - /* - DateTime, ///< Date/time - Flags, ///< Flags - Selector, ///< Selector attribute, it is not persisted - Color, ///< Color - Boolean, ///< Check box*/ + + connect(m_adapters[attribute], &PDFObjectEditorMappedWidgetAdapter::commitRequested, this, &PDFObjectEditorWidgetMapper::onCommitRequested); } PDFObjectEditorWidgetMapper::Category* PDFObjectEditorWidgetMapper::getOrCreateCategory(QString categoryName) @@ -334,7 +493,7 @@ PDFObjectEditorMappedRectangleAdapter::PDFObjectEditorMappedRectangleAdapter(QLa QPushButton* pushButton, PDFObjectEditorAbstractModel* model, size_t attribute, - QObject* parent): + QObject* parent) : BaseClass(model, attribute, parent), m_label(label), m_pushButton(pushButton) @@ -352,4 +511,159 @@ void PDFObjectEditorMappedRectangleAdapter::setValue(PDFObject object) m_rectangle = qMove(object); } +PDFObjectEditorMappedDateTimeAdapter::PDFObjectEditorMappedDateTimeAdapter(QLabel* label, + QDateTimeEdit* dateTimeEdit, + PDFObjectEditorAbstractModel* model, + size_t attribute, + QObject* parent) : + BaseClass(model, attribute, parent), + m_label(label), + m_dateTimeEdit(dateTimeEdit) +{ + initLabel(label); + + connect(dateTimeEdit, &QDateTimeEdit::editingFinished, this, [this, attribute](){ emit commitRequested(attribute); }); +} + +PDFObject PDFObjectEditorMappedDateTimeAdapter::getValue() const +{ + QDateTime dateTime = m_dateTimeEdit->dateTime(); + + if (dateTime.isValid()) + { + return PDFObject::createString(PDFEncoding::convertDateTimeToString(dateTime)); + } + + return PDFObject(); +} + +void PDFObjectEditorMappedDateTimeAdapter::setValue(PDFObject object) +{ + PDFDocumentDataLoaderDecorator loader(m_model->getStorage()); + QByteArray string = loader.readString(object); + + QDateTime dateTime = PDFEncoding::convertToDateTime(string); + m_dateTimeEdit->setDateTime(dateTime); +} + +PDFObjectEditorMappedFlagsAdapter::PDFObjectEditorMappedFlagsAdapter(std::vector> flagCheckBoxes, + PDFObjectEditorAbstractModel* model, + size_t attribute, + QObject* parent) : + BaseClass(model, attribute, parent), + m_flagCheckBoxes(qMove(flagCheckBoxes)) +{ + for (const auto& item : m_flagCheckBoxes) + { + QCheckBox* checkBox = item.second; + connect(checkBox, &QCheckBox::clicked, this, [this, attribute](){ emit commitRequested(attribute); }); + } +} + +PDFObject PDFObjectEditorMappedFlagsAdapter::getValue() const +{ + uint32_t flags = 0; + + for (const auto& item : m_flagCheckBoxes) + { + if (item.second->isChecked()) + { + flags = flags | item.first; + } + } + + return PDFObject::createInteger(PDFInteger(flags)); +} + +void PDFObjectEditorMappedFlagsAdapter::setValue(PDFObject object) +{ + PDFDocumentDataLoaderDecorator loader(m_model->getStorage()); + uint32_t flags = static_cast(loader.readInteger(object, 0)); + + for (const auto& item : m_flagCheckBoxes) + { + const bool checked = flags & item.first; + item.second->setChecked(checked); + } +} + +PDFObjectEditorMappedCheckBoxAdapter::PDFObjectEditorMappedCheckBoxAdapter(QLabel* label, + QCheckBox* checkBox, + PDFObjectEditorAbstractModel* model, + size_t attribute, + QObject* parent) : + BaseClass(model, attribute, parent), + m_label(label), + m_checkBox(checkBox) +{ + initLabel(label); + connect(checkBox, &QCheckBox::clicked, this, [this, attribute](){ emit commitRequested(attribute); }); +} + +PDFObject PDFObjectEditorMappedCheckBoxAdapter::getValue() const +{ + return PDFObject::createBool(m_checkBox->isChecked()); +} + +void PDFObjectEditorMappedCheckBoxAdapter::setValue(PDFObject object) +{ + PDFDocumentDataLoaderDecorator loader(m_model->getStorage()); + m_checkBox->setChecked(loader.readBoolean(object, false)); +} + + +PDFObjectEditorMappedColorAdapter::PDFObjectEditorMappedColorAdapter(QLabel* label, + QPushButton* pushButton, + PDFObjectEditorAbstractModel* model, + size_t attribute, + QObject* parent) : + BaseClass(model, attribute, parent), + m_label(label), + m_pushButton(pushButton), + m_color(Qt::black) +{ + initLabel(label); +} + +PDFObject PDFObjectEditorMappedColorAdapter::getValue() const +{ + PDFObjectFactory factory; + factory << m_color; + return factory.takeObject(); +} + +void PDFObjectEditorMappedColorAdapter::setValue(PDFObject object) +{ + m_color = Qt::black; + + PDFDocumentDataLoaderDecorator loader(m_model->getStorage()); + std::vector colors = loader.readNumberArray(object, { }); + + if (colors.size() == 3) + { + const PDFReal red = qBound(0.0, colors[0], 1.0); + const PDFReal green = qBound(0.0, colors[1], 1.0); + const PDFReal blue = qBound(0.0, colors[2], 1.0); + m_color = QColor::fromRgbF(red, green, blue); + } +} + +PDFEditObjectDialog::PDFEditObjectDialog(EditObjectType type, QWidget* parent) : + BaseClass(parent), + m_widget(nullptr), + m_buttonBox(nullptr) +{ + QVBoxLayout* layout = new QVBoxLayout(this); + layout->setContentsMargins(QMargins()); + + m_widget = new PDFObjectEditorWidget(type, this); + layout->addWidget(m_widget); + + m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this); + layout->addWidget(m_buttonBox); + + connect(m_buttonBox, &QDialogButtonBox::accepted, this, &PDFEditObjectDialog::accept); + connect(m_buttonBox, &QDialogButtonBox::rejected, this, &PDFEditObjectDialog::reject); +} + } // namespace pdf diff --git a/PdfForQtLib/sources/pdfobjecteditorwidget.h b/PdfForQtLib/sources/pdfobjecteditorwidget.h index c88b8b9..a2a2bc0 100644 --- a/PdfForQtLib/sources/pdfobjecteditorwidget.h +++ b/PdfForQtLib/sources/pdfobjecteditorwidget.h @@ -21,13 +21,20 @@ #include "pdfobjecteditormodel.h" #include +#include class QTabWidget; +class QDialogButtonBox; namespace pdf { class PDFObjectEditorWidgetMapper; +enum class EditObjectType +{ + Annotation +}; + class PDFObjectEditorWidget : public QWidget { Q_OBJECT @@ -36,13 +43,28 @@ private: using BaseClass = QWidget; public: - explicit PDFObjectEditorWidget(PDFObjectEditorAbstractModel* model, QWidget* parent); + explicit PDFObjectEditorWidget(EditObjectType type, QWidget* parent); private: PDFObjectEditorWidgetMapper* m_mapper; QTabWidget* m_tabWidget; }; +class PDFEditObjectDialog : public QDialog +{ + Q_OBJECT + +private: + using BaseClass = QDialog; + +public: + explicit PDFEditObjectDialog(EditObjectType type, QWidget* parent); + +private: + PDFObjectEditorWidget* m_widget; + QDialogButtonBox* m_buttonBox; +}; + } // namespace pdf #endif // PDFOBJECTEDITORWIDGET_H diff --git a/PdfForQtLib/sources/pdfobjecteditorwidget_impl.h b/PdfForQtLib/sources/pdfobjecteditorwidget_impl.h index 7da3044..6f0c274 100644 --- a/PdfForQtLib/sources/pdfobjecteditorwidget_impl.h +++ b/PdfForQtLib/sources/pdfobjecteditorwidget_impl.h @@ -28,6 +28,8 @@ class QGridLayout; class QLineEdit; class QTextBrowser; class QPushButton; +class QDateTimeEdit; +class QCheckBox; namespace pdf { @@ -59,6 +61,46 @@ protected: size_t m_attribute; }; +class PDFObjectEditorWidgetMapper : public QObject +{ + Q_OBJECT + +private: + using BaseClass = QObject; + +public: + explicit PDFObjectEditorWidgetMapper(PDFObjectEditorAbstractModel* model, QObject* parent); + + void initialize(QTabWidget* tabWidget); + +private: + struct Subcategory + { + QString name; + std::vector attributes; + }; + + struct Category + { + QString name; + std::vector subcategories; + QWidget* page = nullptr; + + Subcategory* getOrCreateSubcategory(QString name); + }; + + void loadWidgets(); + void onEditedObjectChanged(); + void onCommitRequested(size_t attribute); + void createMappedAdapter(QGroupBox* groupBox, QGridLayout* layout, size_t attribute); + Category* getOrCreateCategory(QString categoryName); + + PDFObjectEditorAbstractModel* m_model; + std::vector m_categories; + std::map m_adapters; + bool m_isCommitingDisabled; +}; + class PDFObjectEditorMappedComboBoxAdapter : public PDFObjectEditorMappedWidgetAdapter { Q_OBJECT @@ -113,42 +155,6 @@ private: QTextBrowser* m_textBrowser; }; -class PDFObjectEditorWidgetMapper : public QObject -{ - Q_OBJECT - -private: - using BaseClass = QObject; - -public: - explicit PDFObjectEditorWidgetMapper(PDFObjectEditorAbstractModel* model, QObject* parent); - - void initialize(QTabWidget* tabWidget); - -private: - struct Subcategory - { - QString name; - std::vector attributes; - }; - - struct Category - { - QString name; - std::vector subcategories; - QWidget* page = nullptr; - - Subcategory* getOrCreateSubcategory(QString name); - }; - - void createMappedAdapter(QGroupBox* groupBox, QGridLayout* layout, size_t attribute); - Category* getOrCreateCategory(QString categoryName); - - PDFObjectEditorAbstractModel* m_model; - std::vector m_categories; - std::map m_adapters; -}; - class PDFObjectEditorMappedRectangleAdapter : public PDFObjectEditorMappedWidgetAdapter { Q_OBJECT @@ -168,6 +174,81 @@ private: PDFObject m_rectangle; }; +class PDFObjectEditorMappedDateTimeAdapter : public PDFObjectEditorMappedWidgetAdapter +{ + Q_OBJECT + +private: + using BaseClass = PDFObjectEditorMappedWidgetAdapter; + +public: + explicit PDFObjectEditorMappedDateTimeAdapter(QLabel* label, QDateTimeEdit* dateTimeEdit, PDFObjectEditorAbstractModel* model, size_t attribute, QObject* parent); + + virtual PDFObject getValue() const override; + virtual void setValue(PDFObject object) override; + +private: + QLabel* m_label; + QDateTimeEdit* m_dateTimeEdit; +}; + +class PDFObjectEditorMappedFlagsAdapter : public PDFObjectEditorMappedWidgetAdapter +{ + Q_OBJECT + +private: + using BaseClass = PDFObjectEditorMappedWidgetAdapter; + +public: + explicit PDFObjectEditorMappedFlagsAdapter(std::vector> flagCheckBoxes, + PDFObjectEditorAbstractModel* model, + size_t attribute, + QObject* parent); + + virtual PDFObject getValue() const override; + virtual void setValue(PDFObject object) override; + +private: + std::vector> m_flagCheckBoxes; +}; + +class PDFObjectEditorMappedCheckBoxAdapter : public PDFObjectEditorMappedWidgetAdapter +{ + Q_OBJECT + +private: + using BaseClass = PDFObjectEditorMappedWidgetAdapter; + +public: + explicit PDFObjectEditorMappedCheckBoxAdapter(QLabel* label, QCheckBox* checkBox, PDFObjectEditorAbstractModel* model, size_t attribute, QObject* parent); + + virtual PDFObject getValue() const override; + virtual void setValue(PDFObject object) override; + +private: + QLabel* m_label; + QCheckBox* m_checkBox; +}; + +class PDFObjectEditorMappedColorAdapter : public PDFObjectEditorMappedWidgetAdapter +{ + Q_OBJECT + +private: + using BaseClass = PDFObjectEditorMappedWidgetAdapter; + +public: + explicit PDFObjectEditorMappedColorAdapter(QLabel* label, QPushButton* pushButton, PDFObjectEditorAbstractModel* model, size_t attribute, QObject* parent); + + virtual PDFObject getValue() const override; + virtual void setValue(PDFObject object) override; + +private: + QLabel* m_label; + QPushButton* m_pushButton; + QColor m_color; +}; + } // namespace pdf #endif // PDFOBJECTEDITORWIDGET_IMPL_H