Qt Editor: Fix shape delegates as parameters to enum delegates

qteditor
Sven Eberhardt 2016-07-18 19:24:53 -04:00
parent 68358c0f87
commit 42e142b4d7
2 changed files with 130 additions and 38 deletions

View File

@ -122,6 +122,7 @@ C4PropertyDelegate::C4PropertyDelegate(const C4PropertyDelegateFactory *factory,
// Resolve getter+setter callback names
if (props)
{
creation_props = C4VPropList(props);
name = props->GetPropertyStr(P_Name);
set_function = props->GetPropertyStr(P_Set);
set_function_is_global = props->GetPropertyBool(P_Global);
@ -217,7 +218,7 @@ void C4PropertyDelegateInt::SetEditorData(QWidget *editor, const C4Value &val, c
spinBox->setValue(val.getInt());
}
void C4PropertyDelegateInt::SetModelData(QObject *editor, const C4PropertyPath &property_path) const
void C4PropertyDelegateInt::SetModelData(QObject *editor, const C4PropertyPath &property_path, C4ConsoleQtShape *prop_shape) const
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->interpretText();
@ -248,7 +249,7 @@ void C4PropertyDelegateString::SetEditorData(QWidget *editor, const C4Value &val
line_edit->setText(QString(s ? s->GetCStr() : ""));
}
void C4PropertyDelegateString::SetModelData(QObject *editor, const C4PropertyPath &property_path) const
void C4PropertyDelegateString::SetModelData(QObject *editor, const C4PropertyPath &property_path, C4ConsoleQtShape *prop_shape) const
{
Editor *line_edit = static_cast<Editor*>(editor);
// Only set model data when pressing Enter explicitely; not just when leaving
@ -485,7 +486,7 @@ void C4PropertyDelegateColor::SetEditorData(QWidget *aeditor, const C4Value &val
editor->last_value = val;
}
void C4PropertyDelegateColor::SetModelData(QObject *aeditor, const C4PropertyPath &property_path) const
void C4PropertyDelegateColor::SetModelData(QObject *aeditor, const C4PropertyPath &property_path, C4ConsoleQtShape *prop_shape) const
{
Editor *editor = static_cast<Editor *>(aeditor);
property_path.SetProperty(editor->last_value);
@ -638,6 +639,22 @@ bool C4DeepQComboBox::eventFilter(QObject *obj, QEvent *event)
return false;
}
void C4PropertyDelegateEnumEditor::paintEvent(QPaintEvent *ev)
{
// Draw self
QWidget::paintEvent(ev);
// Draw shape widget
if (paint_parameter_delegate && parameter_widget)
{
QPainter p(this);
QStyleOptionViewItem view_item;
view_item.rect.setTopLeft(parameter_widget->mapToParent(parameter_widget->rect().topLeft()));
view_item.rect.setBottomRight(parameter_widget->mapToParent(parameter_widget->rect().bottomRight()));
paint_parameter_delegate->Paint(&p, view_item, last_parameter_val);
//p.fillRect(view_item.rect, QColor("red"));
}
}
C4PropertyDelegateEnum::C4PropertyDelegateEnum(const C4PropertyDelegateFactory *factory, C4PropList *props, const C4ValueArray *poptions)
: C4PropertyDelegate(factory, props)
{
@ -797,6 +814,7 @@ void C4PropertyDelegateEnum::UpdateEditorParameter(C4PropertyDelegateEnum::Edito
editor->parameter_widget->deleteLater();
editor->parameter_widget = NULL;
}
editor->paint_parameter_delegate = nullptr;
int32_t idx = editor->option_box->GetCurrentSelectionIndex();
if (idx < 0 || idx >= options.size()) return;
const Option &option = options[idx];
@ -846,6 +864,22 @@ void C4PropertyDelegateEnum::UpdateEditorParameter(C4PropertyDelegateEnum::Edito
if (changed_editor == editor->parameter_widget) emit EditingDoneSignal(editor);
});
}
else
{
// If the parameter widget is a shape display, show a dummy widget displaying the shape instead
const C4PropertyDelegateShape *shape_delegate = option.adelegate->GetDirectShapeDelegate();
if (shape_delegate)
{
// dummy widget that is not rendered. shape rendering is forwarded through own paint function
editor->parameter_widget = new QWidget(editor);
editor->layout->addWidget(editor->parameter_widget);
editor->parameter_widget->setAttribute(Qt::WA_NoSystemBackground);
editor->parameter_widget->setAttribute(Qt::WA_TranslucentBackground);
editor->parameter_widget->setAttribute(Qt::WA_TransparentForMouseEvents);
editor->paint_parameter_delegate = shape_delegate;
editor->last_parameter_val = parameter_val;
}
}
}
}
@ -882,7 +916,7 @@ void C4PropertyDelegateEnum::SetEditorData(QWidget *aeditor, const C4Value &val,
editor->updating = false;
}
void C4PropertyDelegateEnum::SetModelData(QObject *aeditor, const C4PropertyPath &property_path) const
void C4PropertyDelegateEnum::SetModelData(QObject *aeditor, const C4PropertyPath &property_path, C4ConsoleQtShape *prop_shape) const
{
// Fetch value from editor
Editor *editor = static_cast<Editor*>(aeditor);
@ -902,13 +936,13 @@ void C4PropertyDelegateEnum::SetModelData(QObject *aeditor, const C4PropertyPath
// Value from a parameter or directly from the enum?
if (option.adelegate)
{
// Default value on enum change
if (editor->option_changed) SetOptionValue(use_path, option);
// Default value on enum change (on main path; not use_path because the default value is always givne as the whole proplist)
if (editor->option_changed) SetOptionValue(property_path, option);
// Value from a parameter.
// Using a setter function?
if (option.adelegate->GetSetFunction())
use_path = C4PropertyPath(use_path, option.adelegate->GetSetFunction(), C4PropertyPath::PPT_SetFunction);
option.adelegate->SetModelData(editor->parameter_widget, use_path);
option.adelegate->SetModelData(editor->parameter_widget, use_path, prop_shape);
}
else
{
@ -1001,7 +1035,7 @@ QString C4PropertyDelegateEnum::GetDisplayString(const C4Value &v, class C4Objec
}
}
const C4PropertyDelegateShape *C4PropertyDelegateEnum::GetShapeDelegate(const C4Value &val) const
const C4PropertyDelegateShape *C4PropertyDelegateEnum::GetShapeDelegate(C4Value &val, C4PropertyPath *shape_path) const
{
// Does this delegate own a shape? Forward decision into selected option.
int32_t option_idx = GetOptionByValue(val);
@ -1009,13 +1043,37 @@ const C4PropertyDelegateShape *C4PropertyDelegateEnum::GetShapeDelegate(const C4
const Option &option = options[option_idx];
EnsureOptionDelegateResolved(option);
if (!option.adelegate) return nullptr;
C4Value param_val = val;
if (option.value_key.Get())
{
*shape_path = C4PropertyPath(*shape_path, option.value_key->GetCStr());
C4PropList *vp = val.getPropList();
if (vp) vp->GetPropertyByS(option.value_key, &param_val);
if (vp) vp->GetPropertyByS(option.value_key, &val);
}
return option.adelegate->GetShapeDelegate(param_val);
return option.adelegate->GetShapeDelegate(val, shape_path);
}
bool C4PropertyDelegateEnum::Paint(QPainter *painter, const QStyleOptionViewItem &option, const C4Value &val) const
{
// Custom painting: Forward to selected child delegate
int32_t option_idx = GetOptionByValue(val);
if (option_idx < 0) return false;
const Option &selected_option = options[option_idx];
EnsureOptionDelegateResolved(selected_option);
if (!selected_option.adelegate) return nullptr;
if (selected_option.adelegate->HasCustomPaint())
{
QStyleOptionViewItem parameter_option = QStyleOptionViewItem(option);
parameter_option.rect.adjust(parameter_option.rect.width()/2, 0, 0, 0);
C4Value parameter_val = val;
if (selected_option.value_key.Get())
{
C4PropList *vp = val.getPropList();
if (vp) vp->GetPropertyByS(selected_option.value_key, &parameter_val);
}
selected_option.adelegate->Paint(painter, parameter_option, parameter_val);
}
// Always return false to draw self using the standard method
return false;
}
C4PropertyDelegateDef::C4PropertyDelegateDef(const C4PropertyDelegateFactory *factory, C4PropList *props)
@ -1249,7 +1307,7 @@ void C4PropertyDelegateC4ValueInput::SetEditorData(QWidget *aeditor, const C4Val
}
}
void C4PropertyDelegateC4ValueInput::SetModelData(QObject *aeditor, const C4PropertyPath &property_path) const
void C4PropertyDelegateC4ValueInput::SetModelData(QObject *aeditor, const C4PropertyPath &property_path, C4ConsoleQtShape *prop_shape) const
{
// Only set model data when pressing Enter explicitely; not just when leaving
Editor *editor = static_cast<Editor *>(aeditor);
@ -1294,13 +1352,12 @@ C4PropertyDelegateShape::C4PropertyDelegateShape(const class C4PropertyDelegateF
}
}
void C4PropertyDelegateShape::SetModelData(QObject *editor, const C4PropertyPath &property_path) const
void C4PropertyDelegateShape::SetModelData(QObject *editor, const C4PropertyPath &property_path, C4ConsoleQtShape *prop_shape) const
{
C4ConsoleQtShape *shape = static_cast<C4ConsoleQtShape *>(editor);
property_path.SetProperty(shape->GetValue());
if (prop_shape) property_path.SetProperty(prop_shape->GetValue());
}
void C4PropertyDelegateShape::Paint(QPainter *painter, const QStyleOptionViewItem &option, const C4Value &val) const
bool C4PropertyDelegateShape::Paint(QPainter *painter, const QStyleOptionViewItem &option, const C4Value &val) const
{
// Background color
if (option.state & QStyle::State_Selected)
@ -1324,6 +1381,7 @@ void C4PropertyDelegateShape::Paint(QPainter *painter, const QStyleOptionViewIte
painter->drawRect(inner_rect);
}
painter->restore();
return true;
}
@ -1419,7 +1477,7 @@ void C4PropertyDelegateFactory::setModelData(QWidget *editor, QAbstractItemModel
void C4PropertyDelegateFactory::SetPropertyData(const C4PropertyDelegate *d, QObject *editor, C4ConsoleQtPropListModel::Property *editor_prop) const
{
// Set according to delegate
d->SetModelData(editor, d->GetPathForProperty(editor_prop));
d->SetModelData(editor, d->GetPathForProperty(editor_prop), editor_prop->shape.Get());
}
QWidget *C4PropertyDelegateFactory::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
@ -1478,8 +1536,7 @@ void C4PropertyDelegateFactory::paint(QPainter *painter, const QStyleOptionViewI
{
C4Value val;
d->GetPropertyValue(prop->parent_value, prop->key, index.row(), &val);
d->Paint(painter, option, val);
return;
if (d->Paint(painter, option, val)) return;
}
// Otherwise use default paint implementation
QStyledItemDelegate::paint(painter, option, index);
@ -1567,19 +1624,25 @@ bool C4ConsoleQtPropListModel::AddPropertyGroup(C4PropList *add_proplist, int32_
C4Value v_target_proplist = C4VPropList(target_proplist);
prop->delegate->GetPropertyValue(v_target_proplist, prop->key, 0, &v);
// Connect editable shape to property
const C4PropertyDelegateShape *new_shape_delegate = prop->delegate->GetShapeDelegate(v);
if (new_shape_delegate != prop->shape_delegate)
C4PropertyPath new_shape_property_path(prop->property_path, prop->key->GetCStr());
const C4PropertyDelegateShape *new_shape_delegate = prop->delegate->GetShapeDelegate(v, &new_shape_property_path);
if (new_shape_delegate != prop->shape_delegate || !(prop->shape_property_path == new_shape_property_path))
{
prop->shape_delegate = new_shape_delegate;
prop->shape_property_path = new_shape_property_path;
if (new_shape_delegate)
{
C4ConsoleQtShape *shape = ::Console.EditCursor.GetShapes()->CreateShape(base_effect_object ? base_effect_object : target_proplist->GetObject(), published_prop, v);
C4ConsoleQtShape *shape = ::Console.EditCursor.GetShapes()->CreateShape(base_effect_object ? base_effect_object : target_proplist->GetObject(), new_shape_delegate->GetCreationProps().getPropList(), v);
C4PropertyDelegateFactory *factory = this->delegate_factory;
connect(shape, &C4ConsoleQtShape::ShapeDragged, new_shape_delegate, [factory, new_shape_delegate, shape, prop]() {
factory->SetPropertyData(new_shape_delegate, shape, prop);
new_shape_delegate->SetModelData(nullptr, prop->shape_property_path, shape);
});
prop->shape.Set(shape);
}
else
{
prop->shape.Clear();
}
}
}
return true;

View File

@ -62,6 +62,8 @@ public:
void SetProperty(const char *set_string) const;
void SetProperty(const C4Value &to_val) const;
void DoCall(const char *call_string) const; // Perform a script call where %s is replaced by the current path
bool operator ==(const C4PropertyPath &v) const { return path == v.path; }
};
class C4PropertyDelegate : public QObject
@ -70,6 +72,7 @@ class C4PropertyDelegate : public QObject
protected:
const class C4PropertyDelegateFactory *factory;
C4Value creation_props;
C4RefCntPointer<C4String> set_function, async_get_function, name;
bool set_function_is_global;
@ -78,7 +81,7 @@ public:
virtual ~C4PropertyDelegate() { }
virtual void SetEditorData(QWidget *editor, const C4Value &val, const C4PropertyPath &property_path) const {};
virtual void SetModelData(QObject *editor, const C4PropertyPath &property_path) const {};
virtual void SetModelData(QObject *editor, const C4PropertyPath &property_path, class C4ConsoleQtShape *prop_shape) const {};
virtual QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const = 0;
virtual void UpdateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option) const;
virtual bool GetPropertyValue(const C4Value &container, C4String *key, int32_t index, C4Value *out_val) const;
@ -88,11 +91,13 @@ public:
virtual QColor GetDisplayBackgroundColor(const C4Value &val, class C4Object *obj) const;
const char *GetSetFunction() const { return set_function.Get() ? set_function->GetCStr() : nullptr; } // get name of setter function for this property
bool IsGlobalSetFunction() const { return set_function_is_global; }
virtual const class C4PropertyDelegateShape *GetShapeDelegate(const C4Value &val) const { return nullptr; }
virtual const class C4PropertyDelegateShape *GetShapeDelegate(C4Value &val, C4PropertyPath *shape_path) const { return nullptr; }
virtual const class C4PropertyDelegateShape *GetDirectShapeDelegate() const { return nullptr; }
virtual bool HasCustomPaint() const { return false; }
virtual void Paint(QPainter *painter, const QStyleOptionViewItem &option, const C4Value &val) const { }
virtual bool Paint(QPainter *painter, const QStyleOptionViewItem &option, const C4Value &val) const { return false; }
C4PropertyPath GetPathForProperty(struct C4ConsoleQtPropListModelProperty *editor_prop) const;
C4String *GetNameStr() const { return name.Get(); }
const C4Value &GetCreationProps() const { return creation_props; }
signals:
void EditorValueChangedSignal(QWidget *editor) const;
@ -107,7 +112,7 @@ public:
C4PropertyDelegateInt(const class C4PropertyDelegateFactory *factory, C4PropList *props);
void SetEditorData(QWidget *editor, const C4Value &val, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path, class C4ConsoleQtShape *prop_shape) const override;
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const override;
};
@ -126,7 +131,7 @@ public:
C4PropertyDelegateString(const class C4PropertyDelegateFactory *factory, C4PropList *props);
void SetEditorData(QWidget *editor, const C4Value &val, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path, class C4ConsoleQtShape *prop_shape) const override;
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const override;
QString GetDisplayString(const C4Value &v, C4Object *obj) const override;
};
@ -191,7 +196,7 @@ public:
C4PropertyDelegateColor(const class C4PropertyDelegateFactory *factory, C4PropList *props);
void SetEditorData(QWidget *editor, const C4Value &val, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path, class C4ConsoleQtShape *prop_shape) const override;
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const override;
QString GetDisplayString(const C4Value &v, C4Object *obj) const override;
QColor GetDisplayTextColor(const C4Value &val, class C4Object *obj) const override;
@ -237,17 +242,36 @@ class C4PropertyDelegateEnumEditor : public QWidget
public:
C4Value last_val;
C4Value last_parameter_val; // Resolved parameter of last_val - assigned for shape parameters only
int32_t last_selection_index;
C4PropertyPath last_get_path;
C4DeepQComboBox *option_box;
QHBoxLayout *layout;
QWidget *parameter_widget;
bool updating, option_changed;
const C4PropertyDelegate *paint_parameter_delegate; // Delegate to draw over the parameter_widget if it's an empty transparent QWidget (for shape delegates)
C4PropertyDelegateEnumEditor(QWidget *parent)
: QWidget(parent), last_selection_index(-1), option_box(NULL), layout(NULL), parameter_widget(NULL), updating(false), option_changed(false) { }
: QWidget(parent), last_selection_index(-1), option_box(NULL), layout(NULL), parameter_widget(NULL),
updating(false), option_changed(false), paint_parameter_delegate(nullptr) { }
void paintEvent(QPaintEvent *) override;
};
// widget shown if a shape delegate is a child of an enum delegate
/*class C4PropertyDelegateEnumShapeParameterDisplayWidget : QWidget
{
Q_OBJECT
const C4PropertyDelegateShape *shape_delegate;
public:
C4PropertyDelegateEnumShapeParameterDisplayWidget(QWidget *parent, const C4PropertyDelegateShape *shape_delegate)
: shape_delegate(shape_delegate);
virtual void paintEvent(QPaintEvent *);
};*/
class C4PropertyDelegateEnum : public C4PropertyDelegate
{
Q_OBJECT
@ -292,10 +316,12 @@ public:
void AddConstOption(C4String *name, const C4Value &val, C4String *group=nullptr);
void SetEditorData(QWidget *editor, const C4Value &val, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path, class C4ConsoleQtShape *prop_shape) const override;
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const override;
QString GetDisplayString(const C4Value &val, class C4Object *obj) const override;
const class C4PropertyDelegateShape *GetShapeDelegate(const C4Value &val) const override; // Forward to parameter of selected option
const class C4PropertyDelegateShape *GetShapeDelegate(C4Value &val, C4PropertyPath *shape_path) const override; // Forward to parameter of selected option
bool HasCustomPaint() const override { return true; }
bool Paint(QPainter *painter, const QStyleOptionViewItem &option, const C4Value &val) const override;
private:
QModelIndex GetModelIndexByID(QStandardItemModel *model, QStandardItem *parent_item, int32_t id, const QModelIndex &parent) const;
@ -384,7 +410,7 @@ public:
C4PropertyDelegateC4ValueInput(const C4PropertyDelegateFactory *factory, C4PropList *props) : C4PropertyDelegate(factory, props) { }
void SetEditorData(QWidget *editor, const C4Value &val, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path) const override;
void SetModelData(QObject *editor, const C4PropertyPath &property_path, class C4ConsoleQtShape *prop_shape) const override;
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const override;
};
@ -393,16 +419,18 @@ class C4PropertyDelegateShape : public C4PropertyDelegate
{
C4RefCntPointer<C4String> shape_type;
uint32_t clr;
bool can_move_center;
bool can_move_center;
public:
C4PropertyDelegateShape(const class C4PropertyDelegateFactory *factory, C4PropList *props);
void SetEditorData(QWidget *editor, const C4Value &val, const C4PropertyPath &property_path) const override { } // TODO maybe implement update?
void SetModelData(QObject *editor, const C4PropertyPath &property_path) const override;
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const override { return NULL; }
const C4PropertyDelegateShape *GetShapeDelegate(const C4Value &val) const override { return this; }
void SetModelData(QObject *editor, const C4PropertyPath &property_path, class C4ConsoleQtShape *prop_shape) const override;
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection) const override { return nullptr; }
const C4PropertyDelegateShape *GetShapeDelegate(C4Value &val, C4PropertyPath *shape_path) const override { return this; }
const C4PropertyDelegateShape *GetDirectShapeDelegate() const override { return this; }
bool HasCustomPaint() const override { return true; }
void Paint(QPainter *painter, const QStyleOptionViewItem &option, const C4Value &val) const override;
bool Paint(QPainter *painter, const QStyleOptionViewItem &option, const C4Value &val) const override;
QString GetDisplayString(const C4Value &v, class C4Object *obj) const override { return QString(); }
};
class C4PropertyDelegateFactory : public QStyledItemDelegate
@ -465,6 +493,7 @@ struct C4ConsoleQtPropListModelProperty
// Each property may be connected to one shape shown in the viewport for editing
C4ConsoleQtShapeHolder shape;
const C4PropertyDelegate *shape_delegate;
C4PropertyPath shape_property_path;
C4ConsoleQtPropListModelProperty() : delegate(nullptr), about_to_edit(false), group_idx(-1), shape_delegate(nullptr) {}
};