-
Notifications
You must be signed in to change notification settings - Fork 48
ParameterGenerator
Parameter generator is a code generation tool that simplifies the manipulation with code. In many places plain data objects are used.
Let's have a look how parameters are transfered from ui to execution:
- First Ui notifies ui thread about changes in parameters with a signal
- Ui thread gets data from ui and packs it into data structure
- Several data structures are then repacked to form the data block for calculation thread
- This data structure is transfered to Calculation Thread and accepted ans used there.
- Most probably Calculation Thread will call some Сore code with the same parameters.
If one wants to change or add one parameter he will have to change a lot of places. To aviod this we will have to generate either Ui form parameter class of vica versa.
Similar tools to look at (Could happen it will be enough)
- Autogen - http://www.gnu.org/software/autogen/
This generator is able to generate complicated classes for plain objects (POCO as analog - http://en.wikipedia.org/wiki/Plain_Old_Java_Object). It allows the following features:
- Getters and setters
- Trivial Constructors
- Visitor pattern
- Reflection
- Stream and console printing
- Aggregation
- Generator reads config file and searches for a variety of descriptions of the poco objects
- Reads the POCO structures descriptions constructed from fields, see below.
- Checks structure integrity, for all referenced classes to be defined.
- Consults config to see what outputs should be generated
- Generates the output
We want to support so far 3 types of fields:
- Simple data fields that have Qt Ui directly corresponding to them
- Boolean field (QCheckBox and QRadioButton)
- Integer field (QSpinBox)
- Double field (QDoubleSpinBox)
- Integer (enum) field (QComboBox)
- String field (QLineEdit)
- Collections (!)
- Common Data types from core 1.1. Vector2dd 1.1. Vector3dd
- Other POCO object fields
Let's for example have a look at integer field. This type of field is predefined. This type of field has predefined a corresponding ui - QSpinBox It also has some properties.
- Name
- Minimum value
- Maximum value
- Default value
- Comment (corresponds to tooltip in Widget)
Same for double field.
For boolean or string field:
- Name
- Default value
- Widget type (QCheckBox or QRadioButton). If omitted, QCheckBox is used.
- Comment (corresponds to tooltip in Widget)
Enum field has also list of specific names and comments for the enum elements
There are several sources of the plain object data information
The plain object can be generated form the qt .ui file (not implemented yet)
Some simple form for very simple primitive classes (not implemented yet)
We can generate this class form the simple xml description All we need is a name of class and the list of the fields, for each of them we need its type and its default value. For example the following XML can be used
As you can see sometimes it is possible to include one class fields into the other, also it is possible to rename the fields and exclude some of them
POCO objects can appear as a result of config file processing as in current implementation of paramGenerator
Class can optionally switch on and off
- Default constructor
- getters/setters vs. public fields
Example()
{
DefaultSetter setter;
accept(setter);
}
This type accessors are for easy interfacing other languages without overloading functions and exposing all parameters in runtime.
enum ParameterId {
PARAMETER_INT_FIELD,
PARAMETER_DOUBLE_FIELD,
PARAMETER_BOOL_FIELD,
};
bool setParameteri(ParameterId parameterName, int value);
bool setParameterd(ParameterId parameterName, double value);
int getParameteri(ParameterId parameterName);
double getParameterd(ParameterId parameterName);
Each class stores a static list of the fields with corresponding properties ParameterGenerator#--Fields and some properties dependent on the generated class such as the offset to the field. Reflection allows to have better visitor classes giving them the ability to serialize into the binary formats
/tools/generatorConcept/reflection.h
This example is in template format ParameterGenerator#- Patterns
$forall fields {
20
${number}
70
17
${name}
140
${number}
58
23
${comment}
}
Generator will change it's way of code generation. Before that it used сout to generate code. It was an ugly way, because the generated code structure was obscure. Now we propose the way that is similar to the HTML is generated - (http://en.wikipedia.org/wiki/Template_engine_%28web%29) It's not necessary to make templates as separate strings, it's just about simplifying the understanding of what is currently generated
See example below:
class Example
{
public:
/* Section with default values */
$forall fields {const static ${type} |${name}@uc_DEFAULT = |${defaultValue}; }
/* Section with fields names */
$forall fields {const static char * |${name}@uc_NAME; }
/* Section with variables */
$forall fields {
// ${comment}
${type} m${name}@cc;
}
/* Section with getters */
$forall fields {
${type} get${name}@cc() const
{
return m${name}@cc;
}
}
/* Section with setters */
$forall fields {
void get${name}@cc( const ${type} &value)
{
m${name}@cc = value;
}
}
/* visitor pattern */
template
void accept(VisitorType &visitor)
{
$forall fields {
visitor.visit(m${name}@cc, ${name}@uc_DEFAULT , ${name}@uc_NAME);
}
}
};
As you can see above we have several default visitors.
- Default setter
- Stream printer
- QSettings getter and setter
- XML getter and setter
class DefaultSetter
{
public:
void visit(int &intField, int defaultValue, const char */*fieldName*/)
{
intField = defaultValue;
};
void visit(double &doubleField, double defaultValue, const char */*fieldName*/)
{
doubleField = defaultValue;
};
void visit(bool &boolField, bool defaultValue, const char * /*fieldName*/)
{
boolField = defaultValue;
};
};
class PrinterVisitor
{
public:
ostream &out;
PrinterVisitor(ostream &_out) : out(_out) {}
void visit(int &intField, int /* defaultValue */, const char *fieldName)
{
out << fieldName << " = " << intField << endl;
};
void visit(double &doubleField, double /* defaultValue */, const char *fieldName)
{
out << fieldName << " = " << doubleField << endl;
};
void visit(bool &boolField, bool /* defaultValue */, const char *fieldName)
{
out << fieldName << " = " << boolField << endl;
};
};
- Visitors design is overcomplicated, writer visitor don't need default field.
- Signals and slots so far are not clear