Qt Editor: Fix display and control of enum delegate parameters

qteditor
Sven Eberhardt 2016-06-08 00:37:48 -04:00
parent 5e4e6c9f7c
commit 0bb910814d
2 changed files with 81 additions and 53 deletions

View File

@ -237,9 +237,15 @@ C4PropertyDelegateLabelAndButtonWidget::C4PropertyDelegateLabelAndButtonWidget(Q
layout->setMargin(0);
layout->setSpacing(0);
label = new QLabel(this);
QPalette palette = label->palette();
palette.setColor(label->foregroundRole(), palette.color(QPalette::HighlightedText));
palette.setColor(label->backgroundRole(), palette.color(QPalette::Highlight));
label->setPalette(palette);
setPalette(palette);
layout->addWidget(label);
button = new QPushButton(QString(LoadResStr("IDS_CNS_MORE")), this);
layout->addWidget(button);
setAutoFillBackground(true);
}
C4PropertyDelegateDescendPath::C4PropertyDelegateDescendPath(const class C4PropertyDelegateFactory *factory, C4PropList *props)
@ -420,6 +426,12 @@ C4PropertyDelegateEnum::C4PropertyDelegateEnum(const C4PropertyDelegateFactory *
{
// Build enum options from C4Value definitions in script
if (!poptions && props) poptions = props->GetPropertyArray(P_Options);
C4String *default_option_key, *default_value_key = nullptr;
if (props)
{
default_option_key = props->GetPropertyStr(P_OptionKey);
default_value_key = props->GetPropertyStr(P_ValueKey);
}
if (poptions)
{
options.reserve(poptions->GetSize());
@ -432,13 +444,15 @@ C4PropertyDelegateEnum::C4PropertyDelegateEnum(const C4PropertyDelegateFactory *
option.name = props->GetPropertyStr(P_Name);
if (!option.name.Get()) option.name = ::Strings.RegString("???");
option.value_key = props->GetPropertyStr(P_ValueKey);
if (!option.value_key) option.value_key = default_value_key;
props->GetProperty(P_Value, &option.value);
option.type = C4V_Type(props->GetPropertyInt(P_Type, C4V_Any));
option.option_key = props->GetPropertyStr(P_OptionKey);
if (!option.option_key) option.option_key = default_option_key;
// Derive storage type from given elements in delegate definition
if (option.type != C4V_Any)
option.storage_type = Option::StorageByType;
else if (option.option_key.Get())
else if (option.option_key && option.value.GetType() != C4V_Nil)
option.storage_type = Option::StorageByKey;
else
option.storage_type = Option::StorageByValue;
@ -532,7 +546,7 @@ void C4PropertyDelegateEnum::UpdateEditorParameter(C4PropertyDelegateEnum::Edito
{
// Showing current selection: From last_val assigned in SetEditorData
parameter_val = editor->last_val;
if (option.value_key.Get())
if (option.value_key)
{
C4PropList *props = editor->last_val.getPropList();
if (props) props->GetPropertyByS(option.value_key.Get(), &parameter_val);
@ -551,7 +565,9 @@ void C4PropertyDelegateEnum::UpdateEditorParameter(C4PropertyDelegateEnum::Edito
if (editor->parameter_widget)
{
editor->layout->addWidget(editor->parameter_widget);
option.adelegate->SetEditorData(editor->parameter_widget, parameter_val, editor->last_get_path);
C4PropertyPath delegate_value_path = editor->last_get_path;
if (option.value_key) delegate_value_path = C4PropertyPath(delegate_value_path, option.value_key->GetCStr());
option.adelegate->SetEditorData(editor->parameter_widget, parameter_val, delegate_value_path);
// Forward editing signals
connect(option.adelegate, &C4PropertyDelegate::EditorValueChangedSignal, editor->parameter_widget, [this, editor](QWidget *changed_editor)
{
@ -583,6 +599,7 @@ void C4PropertyDelegateEnum::SetEditorData(QWidget *aeditor, const C4Value &val,
void C4PropertyDelegateEnum::SetModelData(QObject *aeditor, const C4PropertyPath &property_path) const
{
LogF("SetModelData %s", property_path.GetPath());
// Fetch value from editor
Editor *editor = static_cast<Editor*>(aeditor);
int32_t idx = editor->option_box->currentIndex();
@ -883,55 +900,39 @@ void C4PropertyDelegateShape::Paint(QPainter *painter, const QStyleOptionViewIte
/* Delegate factory: Create delegates based on the C4Value type */
C4PropertyDelegate *C4PropertyDelegateFactory::CreateDelegateByString(const C4String *str, C4PropList *props) const
C4PropertyDelegate *C4PropertyDelegateFactory::CreateDelegateByPropList(C4PropList *props) const
{
// safety
if (!str) return NULL;
// create default base types
if (str->GetData() == "int") return new C4PropertyDelegateInt(this, props);
if (str->GetData() == "array") return new C4PropertyDelegateArray(this, props);
if (str->GetData() == "proplist") return new C4PropertyDelegatePropList(this, props);
if (str->GetData() == "color") return new C4PropertyDelegateColor(this, props);
if (str->GetData() == "def") return new C4PropertyDelegateDef(this, props);
if (str->GetData() == "enum") return new C4PropertyDelegateEnum(this, props);
if (str->GetData() == "bool") return new C4PropertyDelegateBool(this, props);
if (str->GetData() == "has_effect") return new C4PropertyDelegateHasEffect(this, props);
if (str->GetData() == "c4valueenum") return new C4PropertyDelegateC4ValueEnum(this, props);
if (str->GetData() == "rect" || str->GetData() == "circle") return new C4PropertyDelegateShape(this, props);
if (str->GetData() == "any") return new C4PropertyDelegateC4ValueInput(this, props);
// unknown type
return NULL;
}
C4PropertyDelegate *C4PropertyDelegateFactory::CreateDelegateByValue(const C4Value &val) const
{
switch (val.GetType())
if (props)
{
case C4V_Nil:
return new C4PropertyDelegateC4ValueInput(this, NULL);
case C4V_Array:
return new C4PropertyDelegateEnum(this, NULL, val.getArray());
case C4V_PropList:
{
C4PropList *props = val._getPropList();
if (!props) break;
return CreateDelegateByString(props->GetPropertyStr(P_Type), props);
const C4String *str = props->GetPropertyStr(P_Type);
if (str)
{
// create default base types
if (str->GetData() == "int") return new C4PropertyDelegateInt(this, props);
if (str->GetData() == "array") return new C4PropertyDelegateArray(this, props);
if (str->GetData() == "proplist") return new C4PropertyDelegatePropList(this, props);
if (str->GetData() == "color") return new C4PropertyDelegateColor(this, props);
if (str->GetData() == "def") return new C4PropertyDelegateDef(this, props);
if (str->GetData() == "enum") return new C4PropertyDelegateEnum(this, props);
if (str->GetData() == "bool") return new C4PropertyDelegateBool(this, props);
if (str->GetData() == "has_effect") return new C4PropertyDelegateHasEffect(this, props);
if (str->GetData() == "c4valueenum") return new C4PropertyDelegateC4ValueEnum(this, props);
if (str->GetData() == "rect" || str->GetData() == "circle") return new C4PropertyDelegateShape(this, props);
if (str->GetData() == "any") return new C4PropertyDelegateC4ValueInput(this, props);
// unknown type
LogF("Invalid delegate type: %s.", str->GetCStr());
}
}
case C4V_String:
return CreateDelegateByString(val._getStr(), NULL);
default:
// Invalid delegte: No editor.
break;
}
return NULL;
// Default fallback
return new C4PropertyDelegateC4ValueInput(this, props);
}
C4PropertyDelegate *C4PropertyDelegateFactory::GetDelegateByValue(const C4Value &val) const
{
auto iter = delegates.find(val);
auto iter = delegates.find(val.getPropList());
if (iter != delegates.end()) return iter->second.get();
C4PropertyDelegate *new_delegate = CreateDelegateByValue(val);
delegates.insert(std::make_pair(val, std::unique_ptr<C4PropertyDelegate>(new_delegate)));
C4PropertyDelegate *new_delegate = CreateDelegateByPropList(val.getPropList());
delegates.insert(std::make_pair(val.getPropList(), std::unique_ptr<C4PropertyDelegate>(new_delegate)));
return new_delegate;
}
@ -1076,6 +1077,7 @@ C4ConsoleQtPropListModel::C4ConsoleQtPropListModel(C4PropertyDelegateFactory *de
{
header_font.setBold(true);
connect(this, &C4ConsoleQtPropListModel::ProplistChanged, this, &C4ConsoleQtPropListModel::UpdateSelection, Qt::QueuedConnection);
layout_valid = false;
}
C4ConsoleQtPropListModel::~C4ConsoleQtPropListModel()
@ -1087,11 +1089,19 @@ bool C4ConsoleQtPropListModel::AddPropertyGroup(C4PropList *add_proplist, int32_
const char *editor_prop_prefix = "EditorProp_";
auto new_properties = add_proplist->GetSortedLocalProperties(editor_prop_prefix, target_proplist);
if (!new_properties.size()) return false;
if (property_groups.size() == group_index) property_groups.resize(group_index + 1);
if (property_groups.size() == group_index)
{
layout_valid = false;
property_groups.resize(group_index + 1);
}
PropertyGroup &properties = property_groups[group_index];
C4PropListStatic *proplist_static = add_proplist->IsStatic();
properties.name = name;
properties.props.resize(new_properties.size());
if (properties.props.size() != new_properties.size())
{
layout_valid = false;
properties.props.resize(new_properties.size());
}
for (int32_t i = 0; i < new_properties.size(); ++i)
{
Property *prop = &properties.props[i];
@ -1215,11 +1225,16 @@ void C4ConsoleQtPropListModel::UpdateValue(bool select_default)
break;
}
// Update model range
property_groups.resize(num_groups);
if (num_groups != property_groups.size())
{
layout_valid = false;
property_groups.resize(num_groups);
}
QModelIndex topLeft = index(0, 0, QModelIndex());
QModelIndex bottomRight = index(rowCount() - 1, columnCount() - 1, QModelIndex());
emit dataChanged(topLeft, bottomRight);
emit layoutChanged();
if (!layout_valid) emit layoutChanged();
layout_valid = true;
// Initial selection
if (select_default) emit ProplistChanged(default_selection_group, default_selection_index);
}
@ -1318,9 +1333,17 @@ int32_t C4ConsoleQtPropListModel::UpdateValuePropList(C4PropList *target_proplis
int32_t C4ConsoleQtPropListModel::UpdateValueArray(C4ValueArray *target_array, int32_t *default_selection_group, int32_t *default_selection_index)
{
if (property_groups.empty()) property_groups.resize(1);
if (property_groups.empty())
{
layout_valid = false;
property_groups.resize(1);
}
PropertyGroup &properties = property_groups[0];
properties.props.resize(target_array->GetSize());
if (properties.props.size() != target_array->GetSize())
{
layout_valid = false;
properties.props.resize(target_array->GetSize());
}
C4PropertyDelegate *item_delegate = delegate_factory->GetDelegateByValue(info_proplist);
for (int32_t i = 0; i < properties.props.size(); ++i)
{

View File

@ -326,14 +326,13 @@ class C4PropertyDelegateFactory : public QStyledItemDelegate
{
Q_OBJECT
mutable std::map<C4Value, std::unique_ptr<C4PropertyDelegate> > delegates;
mutable std::map<C4PropList *, std::unique_ptr<C4PropertyDelegate> > delegates;
mutable QWidget *current_editor;
mutable C4PropertyDelegate *current_editor_delegate;
mutable C4Value last_edited_value;
class C4ConsoleQtPropListModel *property_model;
C4PropertyDelegate *CreateDelegateByString(const C4String *str, C4PropList *props=NULL) const;
C4PropertyDelegate *CreateDelegateByValue(const C4Value &val) const;
C4PropertyDelegate *CreateDelegateByPropList(C4PropList *props) const;
C4PropertyDelegate *GetDelegateByIndex(const QModelIndex &index) const;
public:
C4PropertyDelegateFactory() : current_editor(nullptr), property_model(nullptr) { }
@ -406,6 +405,11 @@ public:
TargetStackEntry(const C4PropertyPath &path, const C4Value &value, const C4Value &info_proplist)
: path(path), value(value), info_proplist(info_proplist) {}
};
struct EditedPath // Information about how to find currently edited element (to restore after model update)
{
C4PropertyPath target_path;
int32_t major_index, minor_index;
};
private:
C4Value target_value; // Target value for which properties are listed (either proplist or array)
C4Value base_proplist; // Parent-most value, i.e. object or effect selected in editor through
@ -416,6 +420,7 @@ private:
QFont header_font;
C4PropertyDelegateFactory *delegate_factory;
QItemSelectionModel *selection_model;
bool layout_valid; // set to false when property numbers change
public:
C4ConsoleQtPropListModel(C4PropertyDelegateFactory *delegate_factory);
~C4ConsoleQtPropListModel();