#include "WPropertyEditor.h" #include "UICommon.h" #include "WDraggableSpinBox.h" #include "WIntegralSpinBox.h" #include "WResourceSelector.h" #include "WColorPicker.h" #include "WVectorEditor.h" #include "WAnimParamsEditor.h" #include #include #include #include #include #include #include #include static const QString gskNullProperty = "[NULL]"; static const QString gskUnsupportedType = "Invalid property type"; WPropertyEditor::WPropertyEditor(QWidget *pParent, CPropertyBase *pProperty) : QWidget(pParent) { mUI.PropertyName = new QLabel(gskNullProperty, this); mUI.EditorWidget = nullptr; mUI.Layout = new QHBoxLayout(this); mUI.Layout->addWidget(mUI.PropertyName); mUI.Layout->setContentsMargins(0,0,0,0); setLayout(mUI.Layout); mpProperty = nullptr; SetProperty(pProperty); } WPropertyEditor::~WPropertyEditor() { } void WPropertyEditor::resizeEvent(QResizeEvent *pEvent) { CreateLabelText(); } void WPropertyEditor::SetProperty(CPropertyBase *pProperty) { if (pProperty) { bool IsNewProperty = ((!mpProperty) || (pProperty->Template() != mpProperty->Template())); mpProperty = pProperty; if (IsNewProperty) CreateEditor(); else UpdateEditor(); } else { delete mUI.EditorWidget; mUI.EditorWidget = nullptr; mpProperty = pProperty; mUI.PropertyName->setText(gskNullProperty); } } void WPropertyEditor::CreateEditor() { // Clear existing edit widget (if any) delete mUI.EditorWidget; // Set name mUI.PropertyName->setText(TO_QSTRING(mpProperty->Name())); mUI.PropertyName->setToolTip(TO_QSTRING(mpProperty->Name())); // Set editor widget switch (mpProperty->Type()) { // Bool - QCheckBox case eBoolProperty: { CBoolProperty *pBoolCast = static_cast(mpProperty); QCheckBox *pCheckBox = new QCheckBox(this); pCheckBox->setChecked(pBoolCast->Get()); mUI.EditorWidget = pCheckBox; break; } // Byte - WIntegralSpinBox case eByteProperty: { CByteProperty *pByteCast = static_cast(mpProperty); QSpinBox *pSpinBox = new WIntegralSpinBox(this); pSpinBox->setRange(-128, 128); pSpinBox->setFocusPolicy(Qt::StrongFocus); pSpinBox->setContextMenuPolicy(Qt::NoContextMenu); pSpinBox->setValue(pByteCast->Get()); mUI.EditorWidget = pSpinBox; break; } // Short - WIntegralSpinBox case eShortProperty: { CShortProperty *pShortCast = static_cast(mpProperty); QSpinBox *pSpinBox = new WIntegralSpinBox(this); pSpinBox->setRange(-32768, 32767); pSpinBox->setFocusPolicy(Qt::StrongFocus); pSpinBox->setContextMenuPolicy(Qt::NoContextMenu); pSpinBox->setValue(pShortCast->Get()); mUI.EditorWidget = pSpinBox; break; } // Long - WIntegralSpinBox case eLongProperty: { CLongProperty *pLongCast = static_cast(mpProperty); QSpinBox *pSpinBox = new WIntegralSpinBox(this); pSpinBox->setRange(-2147483648, 2147483647); pSpinBox->setFocusPolicy(Qt::StrongFocus); pSpinBox->setContextMenuPolicy(Qt::NoContextMenu); pSpinBox->setValue(pLongCast->Get()); mUI.EditorWidget = pSpinBox; break; } // Enum - QComboBox case eEnumProperty: { CEnumProperty *pEnumCast = static_cast(mpProperty); CEnumTemplate *pTemplate = static_cast(pEnumCast->Template()); QComboBox *pComboBox = new QComboBox(this); for (u32 iEnum = 0; iEnum < pTemplate->NumEnumerators(); iEnum++) { TString name = pTemplate->EnumeratorName(iEnum); pComboBox->addItem(TO_QSTRING(name)); } u32 index = pEnumCast->Get(); if (index < pTemplate->NumEnumerators()) pComboBox->setCurrentIndex(index); pComboBox->setFocusPolicy(Qt::StrongFocus); pComboBox->setContextMenuPolicy(Qt::NoContextMenu); mUI.EditorWidget = pComboBox; break; } // Bitfield - QGroupBox containing QCheckBoxes case eBitfieldProperty: { CBitfieldProperty *pBitfieldCast = static_cast(mpProperty); CBitfieldTemplate *pTemplate = static_cast(pBitfieldCast->Template()); long value = pBitfieldCast->Get(); QGroupBox *pGroupBox = new QGroupBox(this); QVBoxLayout *pBitfieldLayout = new QVBoxLayout(pGroupBox); pBitfieldLayout->setContentsMargins(5,5,5,5); pGroupBox->setLayout(pBitfieldLayout); pGroupBox->setTitle(TO_QSTRING(pBitfieldCast->Name())); mUI.PropertyName->hide(); for (u32 iFlag = 0; iFlag < pTemplate->NumFlags(); iFlag++) { TString flagName = pTemplate->FlagName(iFlag); long mask = pTemplate->FlagMask(iFlag); QCheckBox *pCheckBox = new QCheckBox(TO_QSTRING(flagName), pGroupBox); pCheckBox->setChecked((value & mask) != 0); pBitfieldLayout->addWidget(pCheckBox); } mUI.EditorWidget = pGroupBox; break; } // Float - WDraggableSpinBox case eFloatProperty: { CFloatProperty *pFloatCast = static_cast(mpProperty); WDraggableSpinBox *pDraggableSpinBox = new WDraggableSpinBox(this); pDraggableSpinBox->setDecimals(4); pDraggableSpinBox->setFocusPolicy(Qt::StrongFocus); pDraggableSpinBox->setContextMenuPolicy(Qt::NoContextMenu); pDraggableSpinBox->setValue(pFloatCast->Get()); mUI.EditorWidget = pDraggableSpinBox; break; } // String - QLineEdit case eStringProperty: { CStringProperty *pStringCast = static_cast(mpProperty); QLineEdit *pLineEdit = new QLineEdit(this); pLineEdit->setText(TO_QSTRING(pStringCast->Get())); pLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); //pLineEdit->setCursorPosition(0); mUI.EditorWidget = pLineEdit; break; } // Vector3 - WVectorEditor (inside QGroupBox) case eVector3Property: { CVector3Property *pVector3Cast = static_cast(mpProperty); QGroupBox *pGroupBox = new QGroupBox(this); WVectorEditor *pVectorEditor = new WVectorEditor(pGroupBox); QVBoxLayout *pGroupLayout = new QVBoxLayout(pGroupBox); pGroupLayout->addWidget(pVectorEditor); pGroupLayout->setContentsMargins(0,0,0,0); pGroupBox->setLayout(pGroupLayout); pGroupBox->setTitle(TO_QSTRING(mpProperty->Name())); pVectorEditor->SetValue(pVector3Cast->Get()); pVectorEditor->SetOrientation(Qt::Vertical); mUI.PropertyName->hide(); mUI.EditorWidget = pGroupBox; break; } // Color - WColorPicker case eColorProperty: { CColorProperty *pColorCast = static_cast(mpProperty); WColorPicker *pColorPicker = new WColorPicker(this); CColor color = pColorCast->Get(); QColor qcolor = QColor(color.r, color.g, color.b, color.a); pColorPicker->setColor(qcolor); mUI.EditorWidget = pColorPicker; break; } // File - WResourceSelector case eFileProperty: { CFileProperty *pFileCast = static_cast(mpProperty); WResourceSelector *pResourceSelector = new WResourceSelector(this); pResourceSelector->AdjustPreviewToParent(true); pResourceSelector->SetAllowedExtensions(pFileCast->AllowedExtensions()); pResourceSelector->SetResource(pFileCast->Get()); mUI.EditorWidget = pResourceSelector; break; } // Struct - QGroupBox case eStructProperty: { CPropertyStruct *pStructCast = static_cast(mpProperty); QGroupBox *pGroupBox = new QGroupBox(this); QVBoxLayout *pStructLayout = new QVBoxLayout(pGroupBox); pStructLayout->setContentsMargins(5,5,5,5); pGroupBox->setLayout(pStructLayout); pGroupBox->setTitle(TO_QSTRING(pStructCast->Name())); mUI.PropertyName->hide(); for (u32 p = 0; p < pStructCast->Count(); p++) { WPropertyEditor *pEditor = new WPropertyEditor(pGroupBox, pStructCast->PropertyByIndex(p)); pStructLayout->addWidget(pEditor); } mUI.EditorWidget = pGroupBox; break; } // AnimParams - WAnimParamsEditor case eAnimParamsProperty: { CAnimParamsProperty *pAnimCast = static_cast(mpProperty); CAnimationParameters params = pAnimCast->Get(); WAnimParamsEditor *pEditor = new WAnimParamsEditor(params, this); pEditor->SetTitle(TO_QSTRING(pAnimCast->Name())); mUI.PropertyName->hide(); mUI.EditorWidget = pEditor; break; } // Invalid case eInvalidProperty: default: mUI.EditorWidget = new QLabel(gskUnsupportedType, this); break; } // For some reason setting a minimum size on group boxes flattens it... if ((mpProperty->Type() != eStructProperty) && (mpProperty->Type() != eBitfieldProperty) && (mpProperty->Type() != eVector3Property) && (mpProperty->Type() != eAnimParamsProperty)) { mUI.EditorWidget->setMinimumHeight(21); mUI.EditorWidget->setMaximumHeight(21); } mUI.Layout->addWidget(mUI.EditorWidget, 0); CreateLabelText(); } void WPropertyEditor::UpdateEditor() { switch (mpProperty->Type()) { case eBoolProperty: { CBoolProperty *pBoolCast = static_cast(mpProperty); QCheckBox *pCheckBox = static_cast(mUI.EditorWidget); pCheckBox->setChecked(pBoolCast->Get()); break; } case eByteProperty: { CByteProperty *pByteCast = static_cast(mpProperty); QSpinBox *pSpinBox = static_cast(mUI.EditorWidget); pSpinBox->setValue(pByteCast->Get()); break; } case eShortProperty: { CShortProperty *pShortCast = static_cast(mpProperty); QSpinBox *pSpinBox = static_cast(mUI.EditorWidget); pSpinBox->setValue(pShortCast->Get()); break; } case eLongProperty: { CLongProperty *pLongCast = static_cast(mpProperty); QSpinBox *pSpinBox = static_cast(mUI.EditorWidget); pSpinBox->setValue(pLongCast->Get()); break; } case eEnumProperty: { CEnumProperty *pEnumCast = static_cast(mpProperty); QComboBox *pComboBox = static_cast(mUI.EditorWidget); pComboBox->setCurrentIndex(pEnumCast->Get()); break; } case eBitfieldProperty: { CBitfieldProperty *pBitfieldCast = static_cast(mpProperty); CBitfieldTemplate *pTemplate = static_cast(pBitfieldCast->Template()); QGroupBox *pGroupBox = static_cast(mUI.EditorWidget); QObjectList ChildList = pGroupBox->children(); long value = pBitfieldCast->Get(); u32 propNum = 0; foreach (QObject *pObj, ChildList) { if (pObj != pGroupBox->layout()) { u32 mask = pTemplate->FlagMask(propNum); QCheckBox *pCheckBox = static_cast(pObj); pCheckBox->setChecked((value & mask) != 0); propNum++; } } break; } case eFloatProperty: { CFloatProperty *pFloatCast = static_cast(mpProperty); WDraggableSpinBox *pDraggableSpinBox = static_cast(mUI.EditorWidget); pDraggableSpinBox->setValue(pFloatCast->Get()); break; } case eStringProperty: { CStringProperty *pStringCast = static_cast(mpProperty); QLineEdit *pLineEdit = static_cast(mUI.EditorWidget); pLineEdit->setText(TO_QSTRING(pStringCast->Get())); pLineEdit->setCursorPosition(0); break; } case eVector3Property: { CVector3Property *pVector3Cast = static_cast(mpProperty); QGroupBox *pGroupBox = static_cast(mUI.EditorWidget); WVectorEditor *pVectorEditor = static_cast(pGroupBox->children().first()); pVectorEditor->SetValue(pVector3Cast->Get()); break; } case eColorProperty: { CColorProperty *pColorCast = static_cast(mpProperty); WColorPicker *pColorPicker = static_cast(mUI.EditorWidget); CColor color = pColorCast->Get(); QColor qcolor = QColor(color.r, color.g, color.b, color.a); pColorPicker->setColor(qcolor); break; } case eFileProperty: { CFileProperty *pFileCast = static_cast(mpProperty); WResourceSelector *pResourceSelector = static_cast(mUI.EditorWidget); pResourceSelector->SetAllowedExtensions(pFileCast->AllowedExtensions()); pResourceSelector->SetResource(pFileCast->Get()); break; } case eStructProperty: { CPropertyStruct *pStructCast = static_cast(mpProperty); QGroupBox *pGroupBox = static_cast(mUI.EditorWidget); QObjectList ChildList = pGroupBox->children(); u32 PropNum = 0; foreach (QObject *pObj, ChildList) { if (pObj != pGroupBox->layout()) { CPropertyBase *pProp = pStructCast->PropertyByIndex(PropNum); static_cast(pObj)->SetProperty(pProp); PropNum++; } } break; } case eAnimParamsProperty: { CAnimParamsProperty *pAnimCast = static_cast(mpProperty); WAnimParamsEditor *pEditor = static_cast(mUI.EditorWidget); pEditor->SetParameters(pAnimCast->Get()); break; } } } void WPropertyEditor::CreateLabelText() { mUI.PropertyName->setText(TO_QSTRING(mpProperty->Name())); QFontMetrics metrics(mUI.PropertyName->font()); QString text = metrics.elidedText(TO_QSTRING(mpProperty->Name()), Qt::ElideRight, mUI.PropertyName->width()); mUI.PropertyName->setText(text); }