forked from Mirrors/openclonk
Editor: Add Copy+Paste functionality for properties
parent
c965c24ee2
commit
568088aedb
|
@ -271,6 +271,14 @@ QWidget *C4PropertyDelegateInt::CreateEditor(const C4PropertyDelegateFactory *pa
|
|||
return editor;
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateInt::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Check int type and limits
|
||||
if (val.GetType() != C4V_Int) return false;
|
||||
int32_t ival = val._getInt();
|
||||
return (ival >= min && ival <= max);
|
||||
}
|
||||
|
||||
|
||||
/* String delegate */
|
||||
|
||||
|
@ -318,6 +326,13 @@ QString C4PropertyDelegateString::GetDisplayString(const C4Value &v, C4Object *o
|
|||
return QString(s ? s->GetCStr() : "");
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateString::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Check string type
|
||||
if (val.GetType() != C4V_String) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Delegate editor: Text left and button right */
|
||||
|
||||
|
@ -420,11 +435,8 @@ C4PropertyDelegateArray::C4PropertyDelegateArray(const class C4PropertyDelegateF
|
|||
}
|
||||
}
|
||||
|
||||
QString C4PropertyDelegateArray::GetDisplayString(const C4Value &v, C4Object *obj, bool short_names) const
|
||||
void C4PropertyDelegateArray::ResolveElementDelegate() const
|
||||
{
|
||||
C4ValueArray *arr = v.getArray();
|
||||
if (!arr) return QString(LoadResStr("IDS_CNS_INVALID"));
|
||||
int32_t n = v._getArray()->GetSize();
|
||||
if (!element_delegate)
|
||||
{
|
||||
C4Value element_delegate_value;
|
||||
|
@ -432,6 +444,14 @@ QString C4PropertyDelegateArray::GetDisplayString(const C4Value &v, C4Object *ob
|
|||
if (info_proplist) info_proplist->GetProperty(P_Elements, &element_delegate_value);
|
||||
element_delegate = factory->GetDelegateByValue(element_delegate_value);
|
||||
}
|
||||
}
|
||||
|
||||
QString C4PropertyDelegateArray::GetDisplayString(const C4Value &v, C4Object *obj, bool short_names) const
|
||||
{
|
||||
C4ValueArray *arr = v.getArray();
|
||||
if (!arr) return QString(LoadResStr("IDS_CNS_INVALID"));
|
||||
int32_t n = v._getArray()->GetSize();
|
||||
ResolveElementDelegate();
|
||||
if (max_array_display && n)
|
||||
{
|
||||
QString result = "[";
|
||||
|
@ -456,6 +476,24 @@ QString C4PropertyDelegateArray::GetDisplayString(const C4Value &v, C4Object *ob
|
|||
}
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateArray::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Check array type and all contents
|
||||
C4ValueArray *arr = val.getArray();
|
||||
if (!arr) return false;
|
||||
int32_t n = arr->GetSize();
|
||||
if (n)
|
||||
{
|
||||
ResolveElementDelegate();
|
||||
for (int32_t i = 0; i < arr->GetSize(); ++i)
|
||||
{
|
||||
C4Value item = arr->GetItem(i);
|
||||
if (!element_delegate->IsPasteValid(item)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Proplist descend delegate */
|
||||
|
||||
|
@ -509,6 +547,32 @@ QString C4PropertyDelegatePropList::GetDisplayString(const C4Value &v, C4Object
|
|||
return result;
|
||||
}
|
||||
|
||||
bool C4PropertyDelegatePropList::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Check proplist type
|
||||
C4PropList *pval = val.getPropList();
|
||||
if (!pval) return false;
|
||||
// Are there restrictions on allowed properties?
|
||||
C4PropList *info_proplist = this->info_proplist.getPropList();
|
||||
C4PropList *info_editorprops = info_proplist ? info_proplist->GetPropertyPropList(P_EditorProps) : nullptr;
|
||||
if (!info_editorprops) return true; // No restrictions: Allow everything
|
||||
// Otherwise all types properties must be valid for paste
|
||||
// (Extra properties are OK)
|
||||
std::vector< C4String * > properties = info_editorprops->GetUnsortedProperties(nullptr, nullptr);
|
||||
for (C4String *prop_name : properties)
|
||||
{
|
||||
if (prop_name == &::Strings.P[P_Prototype]) continue;
|
||||
C4Value child_delegate_val;
|
||||
if (!info_editorprops->GetPropertyByS(prop_name, &child_delegate_val)) continue;
|
||||
C4PropertyDelegate *child_delegate = factory->GetDelegateByValue(child_delegate_val);
|
||||
if (!child_delegate) continue;
|
||||
C4Value child_val;
|
||||
pval->GetPropertyByS(prop_name, &child_val);
|
||||
if (!child_delegate->IsPasteValid(child_val)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Color delegate */
|
||||
|
||||
|
@ -577,6 +641,13 @@ QColor C4PropertyDelegateColor::GetDisplayBackgroundColor(const C4Value &val, cl
|
|||
return static_cast<uint32_t>(val.getInt()) & 0xffffff;
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateColor::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Color is always int
|
||||
if (val.GetType() != C4V_Int) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Enum delegate combo box item delegate */
|
||||
|
||||
|
@ -1268,6 +1339,29 @@ bool C4PropertyDelegateEnum::Paint(QPainter *painter, const QStyleOptionViewItem
|
|||
return false;
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateEnum::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Must be a valid selection
|
||||
int32_t option_idx = GetOptionByValue(val);
|
||||
if (option_idx < 0) return false;
|
||||
const Option &option = options[option_idx];
|
||||
// Check validity for parameter
|
||||
EnsureOptionDelegateResolved(option);
|
||||
if (!option.adelegate) return true; // No delegate? Then any value is OK.
|
||||
C4Value parameter_val;
|
||||
if (option.value_key.Get())
|
||||
{
|
||||
C4PropList *vp = val.getPropList();
|
||||
if (!vp) return false;
|
||||
vp->GetPropertyByS(option.value_key, ¶meter_val); // if this fails, check parameter against nil
|
||||
}
|
||||
else
|
||||
{
|
||||
parameter_val = val;
|
||||
}
|
||||
return option.adelegate->IsPasteValid(parameter_val);
|
||||
}
|
||||
|
||||
|
||||
/* Definition delegate */
|
||||
|
||||
|
@ -1277,7 +1371,7 @@ C4PropertyDelegateDef::C4PropertyDelegateDef(const C4PropertyDelegateFactory *fa
|
|||
// nil is always an option
|
||||
AddConstOption(empty_name ? empty_name.Get() : ::Strings.RegString("nil"), C4VNull);
|
||||
// Collect sorted definitions
|
||||
C4String *filter_property = props ? props->GetPropertyStr(P_Filter) : nullptr;
|
||||
filter_property = props ? props->GetPropertyStr(P_Filter) : nullptr;
|
||||
if (filter_property)
|
||||
{
|
||||
// With filter just create a flat list
|
||||
|
@ -1317,6 +1411,22 @@ void C4PropertyDelegateDef::AddDefinitions(C4ConsoleQtDefinitionListModel *def_l
|
|||
}
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateDef::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Must be a definition or nil
|
||||
if (val.GetType() == C4V_Nil) return true;
|
||||
C4Def *def = val.getDef();
|
||||
if (!def) return false;
|
||||
// Check filter
|
||||
if (filter_property)
|
||||
{
|
||||
C4Value prop_val;
|
||||
if (!def->GetPropertyByS(filter_property, &prop_val)) return false;
|
||||
if (!prop_val) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Object delegate */
|
||||
|
||||
|
@ -1412,6 +1522,22 @@ QString C4PropertyDelegateObject::GetDisplayString(const C4Value &v, class C4Obj
|
|||
}
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateObject::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Must be an object or nil
|
||||
if (val.GetType() == C4V_Nil) return true;
|
||||
C4Object *obj = val.getObj();
|
||||
if (!obj) return false;
|
||||
// Check filter
|
||||
if (filter)
|
||||
{
|
||||
C4Value prop_val;
|
||||
if (!obj->GetPropertyByS(filter, &prop_val)) return false;
|
||||
if (!prop_val) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Sound delegate */
|
||||
|
||||
|
@ -1444,6 +1570,14 @@ C4PropertyDelegateSound::C4PropertyDelegateSound(const C4PropertyDelegateFactory
|
|||
}
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateSound::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Must be nil or a string
|
||||
if (val.GetType() == C4V_Nil) return true;
|
||||
if (val.GetType() != C4V_String) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Boolean delegate */
|
||||
|
||||
|
@ -1464,6 +1598,13 @@ bool C4PropertyDelegateBool::GetPropertyValue(const C4Value &container, C4String
|
|||
return success;
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateBool::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Must be a boolean
|
||||
if (val.GetType() != C4V_Bool) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Has-effect delegate */
|
||||
|
||||
|
@ -1582,13 +1723,11 @@ QWidget *C4PropertyDelegateC4ValueInput::CreateEditor(const class C4PropertyDele
|
|||
/* Areas shown in viewport */
|
||||
|
||||
C4PropertyDelegateShape::C4PropertyDelegateShape(const class C4PropertyDelegateFactory *factory, C4PropList *props)
|
||||
: C4PropertyDelegate(factory, props), clr(0xffff0000), can_move_center(false)
|
||||
: C4PropertyDelegate(factory, props), clr(0xffff0000)
|
||||
{
|
||||
if (props)
|
||||
{
|
||||
shape_type = props->GetPropertyStr(P_Type);
|
||||
clr = props->GetPropertyInt(P_Color) | 0xff000000;
|
||||
can_move_center = props->GetPropertyBool(P_CanMoveCenter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1616,29 +1755,126 @@ bool C4PropertyDelegateShape::Paint(QPainter *painter, const QStyleOptionViewIte
|
|||
// Draw shape in right corner
|
||||
inner_rect.adjust(inner_rect.width() - inner_rect.height(), 0, 0, 0);
|
||||
}
|
||||
if (shape_type && shape_type->GetData() == "point")
|
||||
{
|
||||
|
||||
QPoint ctr = inner_rect.center();
|
||||
int r = inner_rect.height() * 7 / 20;
|
||||
painter->drawLine(ctr + QPoint(-r, -r), ctr + QPoint(+r, +r));
|
||||
painter->drawLine(ctr + QPoint(+r, -r), ctr + QPoint(-r, +r));
|
||||
painter->drawEllipse(inner_rect);
|
||||
}
|
||||
else if (shape_type && shape_type->GetData() == "circle")
|
||||
{
|
||||
painter->drawEllipse(inner_rect);
|
||||
if (can_move_center) painter->drawPoint(inner_rect.center());
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->drawRect(inner_rect);
|
||||
}
|
||||
// Paint by shape type
|
||||
DoPaint(painter, inner_rect);
|
||||
// Done painting
|
||||
painter->restore();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Areas shown in viewport: Rectangle */
|
||||
|
||||
C4PropertyDelegateRect::C4PropertyDelegateRect(const class C4PropertyDelegateFactory *factory, C4PropList *props)
|
||||
: C4PropertyDelegateShape(factory, props)
|
||||
{
|
||||
if (props)
|
||||
{
|
||||
storage = props->GetPropertyStr(P_Storage);
|
||||
}
|
||||
}
|
||||
|
||||
void C4PropertyDelegateRect::DoPaint(QPainter *painter, const QRect &inner_rect) const
|
||||
{
|
||||
painter->drawRect(inner_rect);
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateRect::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Check storage as prop list
|
||||
if (storage)
|
||||
{
|
||||
// Proplist-stored rect must have defined properties
|
||||
C4PropertyName def_property_names[2][4] = { { P_x, P_y, P_wdt, P_hgt },{ P_X, P_Y, P_Wdt, P_Hgt } };
|
||||
C4PropertyName *property_names = nullptr;
|
||||
if (storage->GetData() == "proplist")
|
||||
{
|
||||
property_names = def_property_names[0];
|
||||
}
|
||||
else if (storage->GetData() == "Proplist")
|
||||
{
|
||||
property_names = def_property_names[1];
|
||||
}
|
||||
if (property_names)
|
||||
{
|
||||
C4PropList *val_proplist = val.getPropList();
|
||||
if (!val_proplist) return false;
|
||||
for (int32_t i = 0; i < 4; ++i)
|
||||
{
|
||||
C4Value propval;
|
||||
if (!val_proplist->GetProperty(property_names[i], &propval)) return false;
|
||||
if (propval.GetType() != C4V_Int) return false;
|
||||
}
|
||||
// extra properties are OK
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Check storage as array: Expect array with four elements. Width and height non-negative.
|
||||
C4ValueArray *val_arr = val.getArray();
|
||||
if (!val_arr || val_arr->GetSize() != 4) return false;
|
||||
for (int32_t i = 0; i < 4; ++i) if (val_arr->GetItem(i).GetType() != C4V_Int) return false;
|
||||
if (val_arr->GetItem(2)._getInt() < 0) return false;
|
||||
if (val_arr->GetItem(3)._getInt() < 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Areas shown in viewport: Circle */
|
||||
|
||||
C4PropertyDelegateCircle::C4PropertyDelegateCircle(const class C4PropertyDelegateFactory *factory, C4PropList *props)
|
||||
: C4PropertyDelegateShape(factory, props)
|
||||
{
|
||||
if (props)
|
||||
{
|
||||
can_move_center = props->GetPropertyBool(P_CanMoveCenter);
|
||||
}
|
||||
}
|
||||
|
||||
void C4PropertyDelegateCircle::DoPaint(QPainter *painter, const QRect &inner_rect) const
|
||||
{
|
||||
painter->drawEllipse(inner_rect);
|
||||
if (can_move_center) painter->drawPoint(inner_rect.center());
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateCircle::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Circle radius stored as single non-negative int
|
||||
if (!can_move_center) return (val.GetType() == C4V_Int) && (val.getInt() >= 0);
|
||||
// Circle+Center stored as array with three elements (radius, x, y)
|
||||
C4ValueArray *val_arr = val.getArray();
|
||||
if (!val_arr || val_arr->GetSize() != 3) return false;
|
||||
for (int32_t i = 0; i < 3; ++i) if (val_arr->GetItem(i).GetType() != C4V_Int) return false;
|
||||
if (val_arr->GetItem(0)._getInt() < 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Areas shown in viewport: Point */
|
||||
|
||||
C4PropertyDelegatePoint::C4PropertyDelegatePoint(const class C4PropertyDelegateFactory *factory, C4PropList *props)
|
||||
: C4PropertyDelegateShape(factory, props)
|
||||
{
|
||||
}
|
||||
|
||||
void C4PropertyDelegatePoint::DoPaint(QPainter *painter, const QRect &inner_rect) const
|
||||
{
|
||||
QPoint ctr = inner_rect.center();
|
||||
int r = inner_rect.height() * 7 / 20;
|
||||
painter->drawLine(ctr + QPoint(-r, -r), ctr + QPoint(+r, +r));
|
||||
painter->drawLine(ctr + QPoint(+r, -r), ctr + QPoint(-r, +r));
|
||||
painter->drawEllipse(inner_rect);
|
||||
}
|
||||
|
||||
bool C4PropertyDelegatePoint::IsPasteValid(const C4Value &val) const
|
||||
{
|
||||
// Point stored as array with two elements
|
||||
C4ValueArray *val_arr = val.getArray();
|
||||
if (!val_arr || val_arr->GetSize() != 2) return false;
|
||||
for (int32_t i = 0; i < 2; ++i) if (val_arr->GetItem(i).GetType() != C4V_Int) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Delegate factory: Create delegates based on the C4Value type */
|
||||
|
||||
C4PropertyDelegate *C4PropertyDelegateFactory::CreateDelegateByPropList(C4PropList *props) const
|
||||
|
@ -1661,7 +1897,9 @@ C4PropertyDelegate *C4PropertyDelegateFactory::CreateDelegateByPropList(C4PropLi
|
|||
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" || str->GetData() == "point") return new C4PropertyDelegateShape(this, props);
|
||||
if (str->GetData() == "rect") return new C4PropertyDelegateRect(this, props);
|
||||
if (str->GetData() == "circle") return new C4PropertyDelegateCircle(this, props);
|
||||
if (str->GetData() == "point") return new C4PropertyDelegatePoint(this, props);
|
||||
if (str->GetData() == "any") return new C4PropertyDelegateC4ValueInput(this, props);
|
||||
// unknown type
|
||||
LogF("Invalid delegate type: %s.", str->GetCStr());
|
||||
|
@ -1813,6 +2051,110 @@ bool C4PropertyDelegateFactory::CheckCurrentEditor(C4PropertyDelegate *d, QWidge
|
|||
return true;
|
||||
}
|
||||
|
||||
static const QString property_mime_type("application/OpenClonkProperty");
|
||||
|
||||
void C4PropertyDelegateFactory::CopyToClipboard(const QModelIndex &index)
|
||||
{
|
||||
// Re-resolve property. May have shifted while the menu was open
|
||||
C4ConsoleQtPropListModel::Property *prop = property_model->GetPropByIndex(index);
|
||||
C4PropertyDelegate *d = GetDelegateByIndex(index);
|
||||
if (!prop || !d) return;
|
||||
// Get data to copy
|
||||
C4Value val;
|
||||
d->GetPropertyValue(prop->parent_value, prop->key, index.row(), &val);
|
||||
StdStrBuf data_str(val.GetDataString(99999));
|
||||
// Copy it as an internal mime type and text
|
||||
// Presence of the internal type shows that this is a copied property so it can be safely evaluate without sync problems
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->clear();
|
||||
std::unique_ptr<QMimeData> data(new QMimeData());
|
||||
data->setData(property_mime_type, QByteArray(data_str.getData(), data_str.getSize()));
|
||||
data->setText(data_str.getData());
|
||||
clipboard->setMimeData(data.release());
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateFactory::PasteFromClipboard(const QModelIndex &index, bool check_only)
|
||||
{
|
||||
// Re-resolve property. May have shifted while the menu was open
|
||||
C4ConsoleQtPropListModel::Property *prop = property_model->GetPropByIndex(index);
|
||||
C4PropertyDelegate *d = GetDelegateByIndex(index);
|
||||
if (!prop || !d) return false;
|
||||
// Check value to paste
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
const QMimeData *data = clipboard->mimeData();
|
||||
if (!data) return false; // empty clipboard
|
||||
// Prefer copied property; fall back to text
|
||||
StdStrBuf str_data;
|
||||
if (data->hasFormat(property_mime_type))
|
||||
{
|
||||
QByteArray prop_data = data->data(property_mime_type);
|
||||
str_data.Copy(prop_data);
|
||||
// Check data type
|
||||
C4Value val = ::AulExec.DirectExec(&::ScriptEngine, str_data.getData(), "paste check", false, nullptr, false);
|
||||
if (!d->IsPasteValid(val)) return false;
|
||||
}
|
||||
else if (data->hasText())
|
||||
{
|
||||
// Text can always be pasted.
|
||||
// Cannot perform a type check here because a function may have been copied that affects sync.
|
||||
QString text = data->text();
|
||||
str_data.Copy(text.toUtf8());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown data type in clipboard. Cannot paste.
|
||||
return false;
|
||||
}
|
||||
if (check_only) return true;
|
||||
// Alright, paste!
|
||||
d->GetPathForProperty(prop).SetProperty(str_data.getData());
|
||||
}
|
||||
|
||||
bool C4PropertyDelegateFactory::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
|
||||
{
|
||||
// Custom context menu on item
|
||||
// I would like to use the regular context menu functions of Qt on the parent widget
|
||||
// but something is eating the right-click event before it triggers a context event.
|
||||
// So just hack it on right click.
|
||||
// Button check
|
||||
if (event->type() == QEvent::Type::MouseButtonPress)
|
||||
{
|
||||
QMouseEvent *mev = static_cast<QMouseEvent *>(event);
|
||||
if (mev->button() == Qt::MouseButton::RightButton)
|
||||
{
|
||||
// Item check
|
||||
C4ConsoleQtPropListModel::Property *prop = property_model->GetPropByIndex(index);
|
||||
C4PropertyDelegate *d = GetDelegateByIndex(index);
|
||||
if (d && prop)
|
||||
{
|
||||
// Context menu on a valid property: Show copy+paste menu
|
||||
QMenu *context = new QMenu(const_cast<QWidget *>(option.widget));
|
||||
QAction *copy_action = new QAction(LoadResStr("IDS_DLG_COPY"), context);
|
||||
QAction *paste_action = new QAction(LoadResStr("IDS_DLG_PASTE"), context);
|
||||
QModelIndex index_copy(index);
|
||||
connect(copy_action, &QAction::triggered, this, [this, index_copy]() {
|
||||
this->CopyToClipboard(index_copy);
|
||||
});
|
||||
connect(paste_action, &QAction::triggered, this, [this, index_copy]() {
|
||||
this->PasteFromClipboard(index_copy, false);
|
||||
});
|
||||
paste_action->setEnabled(PasteFromClipboard(index_copy, true)); // Paste grayed out if not valid
|
||||
context->addAction(copy_action);
|
||||
context->addAction(paste_action);
|
||||
context->popup(mev->globalPos());
|
||||
context->connect(context, &QMenu::aboutToHide, context, &QWidget::deleteLater);
|
||||
// It's easier to see which item is affected when it's selected
|
||||
QItemSelectionModel *sel_model = property_model->GetSelectionModel();
|
||||
QItemSelection new_sel;
|
||||
new_sel.select(model->index(index.row(), 0, index.parent()), index);
|
||||
sel_model->select(new_sel, QItemSelectionModel::SelectionFlag::SelectCurrent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QStyledItemDelegate::editorEvent(event, model, option, index);
|
||||
}
|
||||
|
||||
|
||||
/* Proplist table view */
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ public:
|
|||
C4PropertyPath GetPathForProperty(const C4PropertyPath &parent_path, const char *default_subpath) const;
|
||||
C4String *GetNameStr() const { return name.Get(); }
|
||||
const C4Value &GetCreationProps() const { return creation_props; }
|
||||
virtual bool IsPasteValid(const C4Value &val) const = 0;
|
||||
|
||||
signals:
|
||||
void EditorValueChangedSignal(QWidget *editor) const;
|
||||
|
@ -117,6 +118,7 @@ public:
|
|||
void SetEditorData(QWidget *editor, const C4Value &val, 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, bool is_child) const override;
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
class C4PropertyDelegateStringEditor : public QLineEdit
|
||||
|
@ -137,6 +139,7 @@ public:
|
|||
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, bool is_child) const override;
|
||||
QString GetDisplayString(const C4Value &v, C4Object *obj, bool short_names) const override;
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
// Editor: Text displaying value plus a button that opens an extended editor
|
||||
|
@ -175,10 +178,13 @@ class C4PropertyDelegateArray : public C4PropertyDelegateDescendPath
|
|||
private:
|
||||
int32_t max_array_display;
|
||||
mutable C4PropertyDelegate *element_delegate; // lazy eval
|
||||
|
||||
void ResolveElementDelegate() const;
|
||||
public:
|
||||
C4PropertyDelegateArray(const class C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
|
||||
QString GetDisplayString(const C4Value &v, C4Object *obj, bool short_names) const override;
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
class C4PropertyDelegatePropList : public C4PropertyDelegateDescendPath
|
||||
|
@ -189,6 +195,7 @@ public:
|
|||
C4PropertyDelegatePropList(const class C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
|
||||
QString GetDisplayString(const C4Value &v, C4Object *obj, bool short_names) const override;
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
class C4PropertyDelegateColor : public C4PropertyDelegate
|
||||
|
@ -204,6 +211,7 @@ public:
|
|||
QString GetDisplayString(const C4Value &v, C4Object *obj, bool short_names) const override;
|
||||
QColor GetDisplayTextColor(const C4Value &val, class C4Object *obj) const override;
|
||||
QColor GetDisplayBackgroundColor(const C4Value &val, class C4Object *obj) const override;
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
// Display delegate for deep combo box. Handles the help tooltip showing.
|
||||
|
@ -350,6 +358,7 @@ public:
|
|||
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;
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
|
||||
private:
|
||||
QModelIndex GetModelIndexByID(QStandardItemModel *model, QStandardItem *parent_item, int32_t id, const QModelIndex &parent) const;
|
||||
|
@ -365,8 +374,11 @@ public slots:
|
|||
// Select a definition
|
||||
class C4PropertyDelegateDef : public C4PropertyDelegateEnum
|
||||
{
|
||||
private:
|
||||
C4RefCntPointer<C4String> filter_property;
|
||||
public:
|
||||
C4PropertyDelegateDef(const C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
|
||||
private:
|
||||
void AddDefinitions(class C4ConsoleQtDefinitionListModel *def_list_model, QModelIndex parent, C4String *group);
|
||||
|
@ -386,6 +398,7 @@ public:
|
|||
|
||||
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection, bool is_child) const override;
|
||||
QString GetDisplayString(const C4Value &v, class C4Object *obj, bool short_names) const override;
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
// Select a sound
|
||||
|
@ -393,6 +406,7 @@ class C4PropertyDelegateSound : public C4PropertyDelegateEnum
|
|||
{
|
||||
public:
|
||||
C4PropertyDelegateSound(const C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
protected:
|
||||
C4StyledItemDelegateWithButton::ButtonType GetOptionComboBoxButtonType() const override { return C4StyledItemDelegateWithButton::BT_PlaySound; }
|
||||
};
|
||||
|
@ -404,6 +418,7 @@ public:
|
|||
C4PropertyDelegateBool(const class C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
|
||||
bool GetPropertyValue(const C4Value &container, C4String *key, int32_t index, C4Value *out_val) const override;
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
// true or false depending on whether effect is present
|
||||
|
@ -422,6 +437,7 @@ class C4PropertyDelegateC4ValueEnum : public C4PropertyDelegateEnum
|
|||
{
|
||||
public:
|
||||
C4PropertyDelegateC4ValueEnum(const C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
bool IsPasteValid(const C4Value &val) const override { return true; }
|
||||
};
|
||||
|
||||
class C4PropertyDelegateC4ValueInputEditor : public QWidget // TODO: Merge with C4PropertyDelegateLabelAndButtonWidget
|
||||
|
@ -449,17 +465,17 @@ public:
|
|||
void SetEditorData(QWidget *editor, const C4Value &val, 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, bool is_child) const override;
|
||||
bool IsPasteValid(const C4Value &val) const override { return true; }
|
||||
};
|
||||
|
||||
// areas shown in viewport
|
||||
class C4PropertyDelegateShape : public C4PropertyDelegate
|
||||
{
|
||||
C4RefCntPointer<C4String> shape_type;
|
||||
uint32_t clr;
|
||||
bool can_move_center;
|
||||
|
||||
virtual void DoPaint(QPainter *painter, const QRect &inner_rect) const = 0;
|
||||
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, class C4ConsoleQtShape *prop_shape) const override;
|
||||
QWidget *CreateEditor(const class C4PropertyDelegateFactory *parent_delegate, QWidget *parent, const QStyleOptionViewItem &option, bool by_selection, bool is_child) const override { return nullptr; }
|
||||
|
@ -470,6 +486,34 @@ public:
|
|||
QString GetDisplayString(const C4Value &v, class C4Object *obj, bool short_names) const override { return QString(); }
|
||||
};
|
||||
|
||||
class C4PropertyDelegateRect : public C4PropertyDelegateShape
|
||||
{
|
||||
C4RefCntPointer<C4String> storage;
|
||||
|
||||
void DoPaint(QPainter *painter, const QRect &inner_rect) const override;
|
||||
public:
|
||||
C4PropertyDelegateRect(const class C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
class C4PropertyDelegateCircle : public C4PropertyDelegateShape
|
||||
{
|
||||
bool can_move_center;
|
||||
|
||||
void DoPaint(QPainter *painter, const QRect &inner_rect) const override;
|
||||
public:
|
||||
C4PropertyDelegateCircle(const class C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
class C4PropertyDelegatePoint : public C4PropertyDelegateShape
|
||||
{
|
||||
void DoPaint(QPainter *painter, const QRect &inner_rect) const override;
|
||||
public:
|
||||
C4PropertyDelegatePoint(const class C4PropertyDelegateFactory *factory, C4PropList *props);
|
||||
bool IsPasteValid(const C4Value &val) const override;
|
||||
};
|
||||
|
||||
class C4PropertyDelegateFactory : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -501,6 +545,8 @@ public:
|
|||
private:
|
||||
void EditorValueChanged(QWidget *editor);
|
||||
void EditingDone(QWidget *editor);
|
||||
void CopyToClipboard(const QModelIndex &index);
|
||||
bool PasteFromClipboard(const QModelIndex &index, bool check_only);
|
||||
|
||||
protected:
|
||||
// Model callbacks forwarded to actual delegates
|
||||
|
@ -511,6 +557,7 @@ protected:
|
|||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
|
||||
};
|
||||
|
||||
// Delegate for the name column of the property window
|
||||
|
@ -594,6 +641,7 @@ public:
|
|||
~C4ConsoleQtPropListModel();
|
||||
|
||||
void SetSelectionModel(QItemSelectionModel *m) { selection_model = m; }
|
||||
QItemSelectionModel *GetSelectionModel() const { return selection_model; }
|
||||
|
||||
bool AddPropertyGroup(C4PropList *add_proplist, int32_t group_index, QString name, C4PropList *ignore_overridden, C4Object *base_object, C4String *default_selection, int32_t *default_selection_index);
|
||||
void SetBasePropList(C4PropList *new_proplist); // Clear stack and select new proplist
|
||||
|
|
Loading…
Reference in New Issue