PDF4QT/CodeGenerator/codegenerator.h

450 lines
14 KiB
C
Raw Normal View History

2020-03-11 20:09:14 +01:00
// Copyright (C) 2020 Jakub Melka
//
// This file is part of PdfForQt.
//
// PdfForQt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PdfForQt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
#ifndef CODEGENERATOR_H
#define CODEGENERATOR_H
#include <QObject>
#include <QMetaEnum>
#include <QMetaObject>
#include <QDomDocument>
#include <QDomElement>
#include <QObjectList>
2020-03-14 14:29:25 +01:00
#include <QComboBox>
2020-03-11 20:09:14 +01:00
namespace codegen
{
2020-03-21 16:36:27 +01:00
struct CodeGeneratorParameters
{
bool header = false;
int indent = 0;
QString className;
bool isFirstItem = false;
bool isLastItem = false;
};
2020-03-11 20:09:14 +01:00
class Serializer
{
public:
static QObject* load(const QDomElement& element, QObject* parent);
static void store(QObject* object, QDomElement& element);
2020-03-14 14:29:25 +01:00
static QObject* clone(QObject* object, QObject* parent);
2020-03-11 20:09:14 +01:00
template<typename T>
static inline QString convertEnumToString(T enumValue)
{
QMetaEnum metaEnum = QMetaEnum::fromType<T>();
Q_ASSERT(metaEnum.isValid());
return metaEnum.valueToKey(enumValue);
}
template<typename T>
static inline void convertStringToEnum(const QString enumString, T& value)
{
QMetaEnum metaEnum = QMetaEnum::fromType<T>();
Q_ASSERT(metaEnum.isValid());
bool ok = false;
value = static_cast<T>(metaEnum.keyToValue(enumString.toLatin1().data(), &ok));
if (!ok)
{
// Set default value, if something fails.
value = T();
}
}
2020-03-14 14:29:25 +01:00
template<typename T>
static inline void fillComboBox(QComboBox* comboBox, T value)
{
QMetaEnum metaEnum = QMetaEnum::fromType<T>();
Q_ASSERT(metaEnum.isValid());
const int keyCount = metaEnum.keyCount();
comboBox->setUpdatesEnabled(false);
comboBox->clear();
for (int i = 0; i < keyCount; ++i)
{
comboBox->addItem(metaEnum.key(i), metaEnum.value(i));
}
comboBox->setCurrentIndex(comboBox->findData(int(value)));
comboBox->setUpdatesEnabled(true);
}
2020-03-11 20:09:14 +01:00
};
class GeneratedFunction;
class GeneratedCodeStorage : public QObject
{
Q_OBJECT
private:
using BaseClass = QObject;
public:
Q_INVOKABLE GeneratedCodeStorage(QObject* parent);
Q_PROPERTY(QObjectList functions READ getFunctions WRITE setFunctions)
QObjectList getFunctions() const;
void setFunctions(const QObjectList& functions);
GeneratedFunction* addFunction(const QString& name);
2020-03-14 14:29:25 +01:00
GeneratedFunction* addFunction(GeneratedFunction* function);
void removeFunction(GeneratedFunction* function);
2020-03-11 20:09:14 +01:00
2020-03-21 16:36:27 +01:00
void generateCode(QTextStream& stream, CodeGeneratorParameters& parameters) const;
2020-03-11 20:09:14 +01:00
private:
QObjectList m_functions;
};
2020-03-14 14:29:25 +01:00
class GeneratedBase : public QObject
2020-03-11 20:09:14 +01:00
{
Q_OBJECT
private:
using BaseClass = QObject;
2020-03-14 14:29:25 +01:00
public:
using BaseClass::BaseClass;
enum class FieldType
{
Name,
ItemType,
DataType,
Value,
Description
};
enum DataType
{
_void,
_PDFNull,
_bool,
_PDFInteger,
_PDFReal,
_PDFObjectReference,
2020-03-19 18:17:08 +01:00
_PDFObject,
2020-03-14 14:29:25 +01:00
_QString,
_QPointF,
_QRectF,
2020-03-19 18:17:08 +01:00
_QColor,
2020-03-22 18:19:52 +01:00
_QVariant,
2020-03-26 19:34:12 +01:00
_QPolygonF,
2020-03-28 11:22:08 +01:00
_QDateTime,
_QLocale,
2020-05-02 18:04:25 +02:00
_QByteArray,
2020-04-05 16:01:09 +02:00
_Polygons,
2020-03-23 19:10:22 +01:00
_TextAnnotationIcon,
2020-03-25 18:53:24 +01:00
_LinkHighlightMode,
_TextAlignment,
2020-03-28 14:25:32 +01:00
_AnnotationLineEnding,
2020-04-06 19:58:46 +02:00
_AnnotationBorderStyle,
2020-04-07 20:59:39 +02:00
_FileAttachmentIcon,
2020-04-06 19:58:46 +02:00
_Stamp
2020-03-14 14:29:25 +01:00
};
Q_ENUM(DataType)
Q_PROPERTY(QObjectList items READ getItems WRITE setItems)
virtual bool hasField(FieldType fieldType) const = 0;
virtual QVariant readField(FieldType fieldType) const = 0;
virtual void writeField(FieldType fieldType, QVariant value) = 0;
virtual void fillComboBox(QComboBox* comboBox, FieldType fieldType) = 0;
virtual bool canHaveSubitems() const = 0;
2020-03-15 18:53:44 +01:00
virtual QStringList getCaptions() const = 0;
virtual GeneratedBase* appendItem() = 0;
2020-03-21 16:36:27 +01:00
enum class Pass
{
Enter,
Leave
};
void generateSourceCode(QTextStream& stream, CodeGeneratorParameters& parameters) const;
void applyFunctor(std::function<void(const GeneratedBase*, Pass)>& functor) const;
2020-03-15 18:53:44 +01:00
enum class Operation
{
Delete,
MoveUp,
MoveDown,
NewSibling,
NewChild
};
GeneratedBase* getParent() { return qobject_cast<GeneratedBase*>(parent()); }
const GeneratedBase* getParent() const { return qobject_cast<const GeneratedBase*>(parent()); }
bool canPerformOperation(Operation operation) const;
void performOperation(Operation operation);
2020-03-14 14:29:25 +01:00
QObjectList getItems() const;
void setItems(const QObjectList& items);
void addItem(QObject* object);
void removeItem(QObject* object);
void clearItems();
2020-03-21 16:36:27 +01:00
protected:
virtual void generateSourceCodeImpl(QTextStream& stream, CodeGeneratorParameters& parameters, Pass pass) const;
QString getCppType(DataType type) const;
QStringList getFormattedTextWithLayout(QString firstPrefix, QString prefix, QString text, int indent) const;
QStringList getFormattedTextBlock(QString firstPrefix, QString prefix, QStringList texts, int indent) const;
2020-03-14 14:29:25 +01:00
private:
QObjectList m_items;
};
class GeneratedParameter : public GeneratedBase
{
Q_OBJECT
private:
using BaseClass = GeneratedBase;
public:
Q_INVOKABLE GeneratedParameter(QObject* parent);
Q_PROPERTY(QString parameterName READ getParameterName WRITE setParameterName)
Q_PROPERTY(DataType parameterType READ getParameterDataType WRITE setParameterDataType)
Q_PROPERTY(QString parameterDescription READ getParameterDescription WRITE setParameterDescription)
virtual bool hasField(FieldType fieldType) const override;
virtual QVariant readField(FieldType fieldType) const override;
virtual void writeField(FieldType fieldType, QVariant value) override;
virtual void fillComboBox(QComboBox* comboBox, FieldType fieldType) override;
virtual bool canHaveSubitems() const override;
2020-03-15 18:53:44 +01:00
virtual QStringList getCaptions() const override;
virtual GeneratedBase* appendItem() override;
2020-03-14 14:29:25 +01:00
QString getParameterName() const;
void setParameterName(const QString& parameterName);
DataType getParameterDataType() const;
void setParameterDataType(const DataType& parameterDataType);
QString getParameterDescription() const;
void setParameterDescription(const QString& parameterDescription);
private:
QString m_parameterName;
DataType m_parameterDataType = _void;
QString m_parameterDescription;
};
class GeneratedPDFObject : public GeneratedBase
{
Q_OBJECT
private:
using BaseClass = GeneratedBase;
public:
enum ObjectType
{
Object,
ArraySimple,
ArrayComplex,
Dictionary,
DictionaryItemSimple,
DictionaryItemComplex
};
Q_ENUM(ObjectType)
Q_INVOKABLE GeneratedPDFObject(QObject* parent);
Q_PROPERTY(QString dictionaryItemName READ getDictionaryItemName WRITE setDictionaryItemName)
Q_PROPERTY(ObjectType objectType READ getObjectType WRITE setObjectType)
Q_PROPERTY(QString value READ getValue WRITE setValue)
virtual bool hasField(FieldType fieldType) const override;
virtual QVariant readField(FieldType fieldType) const override;
virtual void writeField(FieldType fieldType, QVariant value) override;
virtual void fillComboBox(QComboBox* comboBox, FieldType fieldType) override;
virtual bool canHaveSubitems() const override;
2020-03-15 18:53:44 +01:00
virtual QStringList getCaptions() const override;
virtual GeneratedBase* appendItem() override;
2020-03-14 14:29:25 +01:00
QString getValue() const;
void setValue(const QString& value);
ObjectType getObjectType() const;
void setObjectType(ObjectType objectType);
QString getDictionaryItemName() const;
void setDictionaryItemName(const QString& dictionaryItemName);
2020-03-21 16:36:27 +01:00
protected:
virtual void generateSourceCodeImpl(QTextStream& stream, CodeGeneratorParameters& parameters, Pass pass) const override;
2020-03-14 14:29:25 +01:00
private:
QString m_dictionaryItemName;
ObjectType m_objectType = Object;
QString m_value;
};
class GeneratedAction : public GeneratedBase
{
Q_OBJECT
private:
using BaseClass = GeneratedBase;
public:
enum ActionType
{
Parameters,
CreateObject,
Code
};
Q_ENUM(ActionType)
Q_INVOKABLE GeneratedAction(QObject* parent);
Q_PROPERTY(ActionType actionType READ getActionType WRITE setActionType)
Q_PROPERTY(QString variableName READ getVariableName WRITE setVariableName)
Q_PROPERTY(DataType variableType READ getVariableType WRITE setVariableType)
Q_PROPERTY(QString code READ getCode WRITE setCode)
virtual bool hasField(FieldType fieldType) const override;
virtual QVariant readField(FieldType fieldType) const override;
virtual void writeField(FieldType fieldType, QVariant value) override;
virtual void fillComboBox(QComboBox* comboBox, FieldType fieldType) override;
virtual bool canHaveSubitems() const override;
2020-03-15 18:53:44 +01:00
virtual QStringList getCaptions() const override;
virtual GeneratedBase* appendItem() override;
2020-03-14 14:29:25 +01:00
ActionType getActionType() const;
void setActionType(ActionType actionType);
QString getVariableName() const;
void setVariableName(const QString& variableName);
DataType getVariableType() const;
void setVariableType(DataType variableType);
QString getCode() const;
void setCode(const QString& code);
2020-03-21 16:36:27 +01:00
protected:
virtual void generateSourceCodeImpl(QTextStream& stream, CodeGeneratorParameters& parameters, Pass pass) const override;
2020-03-14 14:29:25 +01:00
private:
ActionType m_actionType;
QString m_variableName;
DataType m_variableType = _void;
QString m_code;
};
class GeneratedFunction : public GeneratedBase
{
Q_OBJECT
private:
using BaseClass = GeneratedBase;
2020-03-11 20:09:14 +01:00
public:
enum FunctionType
{
2020-03-21 18:18:08 +01:00
Structure,
2020-03-11 20:09:14 +01:00
Annotations,
2020-03-23 19:10:22 +01:00
ColorSpace,
2020-05-02 18:04:25 +02:00
Actions,
Forms
2020-03-11 20:09:14 +01:00
};
Q_ENUM(FunctionType)
Q_INVOKABLE GeneratedFunction(QObject* parent);
2020-03-14 14:29:25 +01:00
Q_PROPERTY(FunctionType functionType READ getFunctionType WRITE setFunctionType)
2020-03-11 20:09:14 +01:00
Q_PROPERTY(QString functionName READ getFunctionName WRITE setFunctionName)
Q_PROPERTY(QString functionDescription READ getFunctionDescription WRITE setFunctionDescription)
2020-03-14 14:29:25 +01:00
Q_PROPERTY(DataType returnType READ getReturnType WRITE setReturnType)
virtual bool hasField(FieldType fieldType) const override;
virtual QVariant readField(FieldType fieldType) const override;
virtual void writeField(FieldType fieldType, QVariant value) override;
virtual void fillComboBox(QComboBox* comboBox, FieldType fieldType) override;
virtual bool canHaveSubitems() const override;
2020-03-15 18:53:44 +01:00
virtual QStringList getCaptions() const override;
virtual GeneratedBase* appendItem() override;
2020-03-11 20:09:14 +01:00
QString getFunctionTypeString() const;
void setFunctionTypeString(const QString& string);
FunctionType getFunctionType() const;
void setFunctionType(const FunctionType& functionType);
QString getFunctionName() const;
void setFunctionName(const QString& functionName);
QString getFunctionDescription() const;
void setFunctionDescription(const QString& functionDescription);
2020-03-14 14:29:25 +01:00
DataType getReturnType() const;
void setReturnType(DataType returnType);
/// Create a clone of this function
GeneratedFunction* clone(QObject* parent);
2020-03-21 16:36:27 +01:00
void generateCode(QTextStream& stream, CodeGeneratorParameters& parameters) const;
2020-03-11 20:09:14 +01:00
private:
FunctionType m_functionType = FunctionType::Annotations;
QString m_functionName;
QString m_functionDescription;
2020-03-14 14:29:25 +01:00
DataType m_returnType = _void;
2020-03-11 20:09:14 +01:00
};
class CodeGenerator : public QObject
{
Q_OBJECT
private:
using BaseClass = QObject;
public:
CodeGenerator(QObject* parent = nullptr);
void initialize();
2020-03-14 14:29:25 +01:00
QObjectList getFunctions() const { return m_storage->getFunctions(); }
2020-03-11 20:09:14 +01:00
GeneratedFunction* addFunction(const QString& name) { return m_storage->addFunction(name); }
2020-03-14 14:29:25 +01:00
GeneratedFunction* addFunction(GeneratedFunction* function) { return m_storage->addFunction(function); }
void removeFunction(GeneratedFunction* function) { m_storage->removeFunction(function); }
2020-03-11 20:09:14 +01:00
void load(const QDomDocument& document);
void store(QDomDocument& document);
2020-03-21 16:36:27 +01:00
void generateCode(QString headerName, QString sourceName) const;
2020-03-11 20:09:14 +01:00
private:
2020-03-21 16:36:27 +01:00
QString generateHeader(int indent) const;
QString generateSource(QString className, int indent) const;
2020-03-11 20:09:14 +01:00
GeneratedCodeStorage* m_storage = nullptr;
};
} // namespace codegen
Q_DECLARE_METATYPE(codegen::GeneratedCodeStorage*)
Q_DECLARE_METATYPE(codegen::GeneratedFunction*)
#endif // CODEGENERATOR_H