RKComponent (and related classes) draft:

Key classes:

RKComponentProperty
something used as input, and output. Several types of this may exist, each offering different values. The more interesting application is using them as input-suppliers for components. RKComponentProperty should probably also do input verification. Basically, an RKComponentProperty is the GUI-independent portion of a GUI-settable value. Mockups:

class RKComponentPropertyBase : public QObject {
public signals:
/** property has changed its value. Any connected RKComponentPropertys/RKComponents should update their state
@param property A pointer to the changed property for easy reference */
	void valueChanged (RKComponentPropertyBase *property);
public slots:
/** the (Qt-)slot in which (by default) the (RKComponent-)property is notified, when a property it depends on has changed. Generally you should reimplement this function to add special handling for the properties you know about. */
	virtual void governorValueChanged (RKComponentPropertyBase *property);
public:
	enum RKComponentPropertyTypes {
		0: RKComponentPropertyBase,
		1: RKComponentPropertyBool,
		2: RKComponentPropertyInt,
		3: RKComponentPropertyDouble,
		4: RKComponentPropertyRObject,
		5: RKComponentPropertyRObjectList,
		1000: RKComponentPropertyUser	/**< for user expansion */
	};
/** constructor. Pass a valid QObject as parent so the property will be auto-destructed when no longer needed */
	RKComponentPropertyBase (QObject *parent);
/** destructor */
	virtual ~RKComponentPropertyBase ();
/** supplies the current value. Since more than one value may be supplied, modifier can be used to select a value. Default implementation only has  a single string, however. */
	virtual QString value (const QString &modifier=QString::null);
/** set the value in string form.
@returns false if the value is illegal (in the base class, all strings are legal) */
	virtual bool setValue (const QString &string);
/** do not set the value, only check, whether it is legal */
	virtual bool isValid (const QString &string);
/** current setting valid? */
	bool isValid ();
/** set to required: will only be satisfied if it holds a valid value. Else: satisfied if valid *or empty* */
	void setRequired ();
/** see setRequired () */
	bool isSatisfied ();
/** for RTTI. see RKComponentPropertyTypes */
	virtual int type ();
/** connect this property to a governor property (given as argument). If reconcile_requirements, the requirements of both properties are reconciled to the least common denominator. The dependent property will be notified on all changes made in the governing property, so it can update its value. 
Generally with few exceptions, you can only connect to properties that are either of the same class as this property, or of an extended class. Maybe in the future we will add some sophisticated converters allowing to connect vastly different types of properties in a meaningful way.
If you specify a modifier, only the sub-value indicated by the modifier will be retrieved from the governing property on governorValueChanged. In this case reconcile_requirements is ignored. */
	virtual void connectGovernor (RKComponentPropertyBase *governor, const QString &modifier=QString::null, bool reconcile_requirements=true);
private:
	bool valid;
	bool required;
/** if we're only interested in a specific sub-information of the governor-property, we need to remember the corresponding modifier */
	QString governor_modifier;
};

/** special type of RKComponentProperty, that is based on a bool setting */
class RKComponentPropertyBool : public RKComponentPropertyBase {
public:
/** param value_true string value if true/on
param value_false string value if false/off
param default value to use, if invalid string value was set */
	RKComponentPropertyBool (const QString &value_true, const QString &value_false, bool default);
/** sets the bool value. Also takes care of notifying dependent components */
	void setValue (bool value);
/** current value as bool */
	bool boolValue ();
/** reimplemented from RKComponentPropertyBase. Modifier "true" returns value if true. Modifier "false" returns value if false. Modifier QString::null returns current value. */
	QString value (const QString &modifier=QString::null);
/** reimplemented from RKComponentPropertyBase to convert to bool value according to current settings */
	bool setValue (const QString &value);
/** reimplemented from RKComponentPropertyBase to test whether conversion to bool value is possible according to current settings */
	bool isValid (const QString &value);
};

class RKComponentPropertyInt;		// min, max
class RKComponentPropertyDouble;		// min, max

/** special type of RKComponentProperty, that prepresents an RObject
//TODO: this property should auto-connect to RKModificationTracker, to be safe when the object gets deleted/changed
class RKComponentPropertyRObject : public RKComponentPropertyBase {
public:
	void setClassFilter (const QString &classes);
	void setTypeFilter (const QString &types);
	void setDimensionFilter (int dimensionality, int min_length=-1, int max_length=-1);
	bool setValue (RObject *object);
	bool isValid (RObject *object);
	RObject *objectValue ();
/** reimplemented from RKComponentPropertyBase. Modifier "label" returns label. Modifier "shortname" returns short name. Modifier QString::null returns full name. */
	QString value (const QString &modifier=QString::null);
/** reimplemented from RKComponentPropertyBase to convert to RObject, if possible with current constraints */
	bool setValue (const QString &value);
/** reimplemented from RKComponentPropertyBase to test whether conversion to RObject, is possible with current constraints */
	bool isValid (const QString &value);
};

/** extension of RKComponentPropertyRObject, allowing to hold several RObjects at once. */
class RKComponentPropertyRObjectList : public RKComponentPropertyRObject {
public:
	void setListLength (int min_length, int min_length_if_any=-1, int max_length=-1);
	bool addValue (RObject *object);
	void removeValue (RObject *object);
	bool isValid (RObject *object);
/** reimplemented from RKComponentPropertyBase to return the first RObject in the list */
	RObject *objectValue ();
	QValueList<RObject *> objectList ();
/** reimplemented from RKComponentPropertyBase. Modifier "label" returns label. Modifier "shortname" returns short name. Modifier QString::null returns full name. */
	QString value (const QString &modifier=QString::null);
/** reimplemented from RKComponentPropertyBase to convert to list of RObject, if possible with current constraints */
	bool setValue (const QString &value);
/** reimplemented from RKComponentPropertyBase to test whether conversion to list of RObject, is possible with current constraints */
	bool isValid (const QString &value);
};

/** special type of RKComponentProperty used to contain R code. All stand-alone RKComponents have this. The great thing about this, is that code can be made available to embedding RKComponents by just fetching the component.code.preprocess (or .calculate, .printout, .cleanup) value */
class RKComponentPropertyCode : public RKComponentPropertyBase {
public:
/** the preprocess code */
	QString preprocess ();
/** the calculate code */
	QString calculate ();
/** the printout code */		// TODO, maybe we can abstract this away. A component should _either_ do calculation _or_ printout, hence it could all be calculate () only, as well.
	QString printout ();
/** the cleanup code */
	QString cleanup ();
};

RKComponentPropertys are attached to and owned by RKComponents (those that use it as output)

/** abstract base class of all RKComponents, including component widgets */
class RKComponent : public QWidget {
public slots:
/** generally the valueChanged () signal of all RKComponentPropertys directly owned by this component should be connected to this (Qt-)slot, so the component can update itself accordingly */
	void propertyValueChanged (RKComponentPropertyBase *property);
public:
/** standard property controlling visibility */
	RKComponentPropertyBool *visibilityProperty ();
/** standard property controlling enabledness */
	RKComponentPropertyBool *enablednessProperty ();
/** standard property controlling requiredness */
	RKComponentPropertyBool *requirednessProperty ();

/** The parent of this component. Should be notified, whenever isSatisfied () or isReady ()-state changed. */
	RKComponent *parent ();
	bool isSatisfied ();
	bool isReady ();
/** Locate the component.subcomponent.property.value described by modifier and return its value as a string. Especially useful as a callback in code templates! Recursively walks subcomponents/properties until the requested value is found. */
	QString fetchStringValue (const QString &modifier);
private:
/** also notifies the parent, if applicable */
	void setSatisfied (bool satisfied);
	void setReady (bool ready);
};

/** "regular" components, described in XML format */
class RKStandardComponent : public RKComponent {
};

/** wrapper class for "external" components, i.e. components implemented in stand-alone applets */
class RKExternalComponent : public RKComponent {
};

/** (long-term): A special RKComponent doing some sort of logic conversion. It's used to connect to one or more governing properties, process/convert the value of those properties in some way, and provide one (or more) output properties.
//TODO: how will these be programmed? Hopefully we will soon have a better picture on what logic elements are actually commonly needed */
class RKLogicComponent;

// TODO: do we need this at all?
/** describes the external interface provided by an RKComponent. This means a list of all properties that can be used as input for this component. Used for matching/mapping external RKComponentPropertys to RKComponentPropertys inside this component */
class RKComponentInterface {
};



Initialization steps in creating an RKComponent:
On top level: probably a call to setUpdatesEnabled (false) should be done!
	- create Subcomponents (depth first is important!)
		- ...
	- create RKComponentProperty's
	- initialize
		- set initial values in RKComponentProperty's
			(- updates GUI)
			(- may trigger changes in subcomponents)
		- connect RKComponentPropertys within this component and to subcomponents (those are already fully connected!)
			- connect
			- retrieve values from governing properties
				(- may trigger further changes in this, and subcomponents)
	- return to parent
On top level: probably a call to setUpdatesEnabled (true); update () should be done!

/** A helper class used to build and initialize an RKComponent. Most importantly this will keep track of the properties yet to be connected. Used at least by RKStandardComponent. */
class RKComponentBuilder {
public:
	RKComponentBuilder (RKComponent *parent);
	~RKComponentBuilder ();
	void buildElement (const QDomElement &element);
	void makeConnections ();
private:
	RKComponent *parent;
	struct RKComponentPropertyConnection {
		QString governor_property;
		QString client_property;
		bool reconcile;
	};
	QValueList <RKComponentPropertyConnection *> connection_list;
};


Implementation plan:
0) Create new directory component. Most of what's in plugin now will be migrated there.
1) Create main RKComponentProperty classes (full API, basic implementation)
2) Create an initial implementation of RKStandardComponent, copying heavily from RKPlugin (little code will remain in RKPlugin at the end)
3) Create a few first RKComponentWidgets, copying from RKPluginWidgets, but using RKComponentProperty's internally, and deriving from RKComponent
4) Test and get basic functionality working
5) Finish migration
