Skip to content
Snippets Groups Projects
qtpropertymanager.cpp 209 KiB
Newer Older
  emit decimalsChanged(property, data.decimals);
void QtPointFPropertyManager::initializeProperty(QtProperty *property) {
  d_ptr->m_values[property] = QtPointFPropertyManagerPrivate::Data();
  QtProperty *xProp = d_ptr->m_doublePropertyManager->addProperty();
  xProp->setPropertyName(tr("X"));
  d_ptr->m_doublePropertyManager->setDecimals(xProp, decimals(property));
  d_ptr->m_doublePropertyManager->setValue(xProp, 0);
  d_ptr->m_propertyToX[property] = xProp;
  d_ptr->m_xToProperty[xProp] = property;
  property->addSubProperty(xProp);
  QtProperty *yProp = d_ptr->m_doublePropertyManager->addProperty();
  yProp->setPropertyName(tr("Y"));
  d_ptr->m_doublePropertyManager->setDecimals(yProp, decimals(property));
  d_ptr->m_doublePropertyManager->setValue(yProp, 0);
  d_ptr->m_propertyToY[property] = yProp;
  d_ptr->m_yToProperty[yProp] = property;
  property->addSubProperty(yProp);
void QtPointFPropertyManager::uninitializeProperty(QtProperty *property) {
  QtProperty *xProp = d_ptr->m_propertyToX[property];
  if (xProp) {
    d_ptr->m_xToProperty.remove(xProp);
    delete xProp;
  }
  d_ptr->m_propertyToX.remove(property);
  QtProperty *yProp = d_ptr->m_propertyToY[property];
  if (yProp) {
    d_ptr->m_yToProperty.remove(yProp);
    delete yProp;
  }
  d_ptr->m_propertyToY.remove(property);
  d_ptr->m_values.remove(property);
}

// QtSizePropertyManager

class QtSizePropertyManagerPrivate {
  QtSizePropertyManager *q_ptr;
  Q_DECLARE_PUBLIC(QtSizePropertyManager)
public:
  void slotIntChanged(QtProperty *property, int value);
  void slotPropertyDestroyed(QtProperty *property);
  void setValue(QtProperty *property, const QSize &val);
  void setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal,
                const QSize &val);

  struct Data {
    Data()
        : val(QSize(0, 0)), minVal(QSize(0, 0)),
          maxVal(QSize(INT_MAX, INT_MAX)) {}
    QSize val;
    QSize minVal;
    QSize maxVal;
    QSize minimumValue() const { return minVal; }
    QSize maximumValue() const { return maxVal; }
    void setMinimumValue(const QSize &newMinVal) {
      setSizeMinimumData(this, newMinVal);
    }
    void setMaximumValue(const QSize &newMaxVal) {
      setSizeMaximumData(this, newMaxVal);
    }
  };

  typedef QMap<const QtProperty *, Data> PropertyValueMap;
  PropertyValueMap m_values;

  QtIntPropertyManager *m_intPropertyManager;

  QMap<const QtProperty *, QtProperty *> m_propertyToW;
  QMap<const QtProperty *, QtProperty *> m_propertyToH;
  QMap<const QtProperty *, QtProperty *> m_wToProperty;
  QMap<const QtProperty *, QtProperty *> m_hToProperty;
void QtSizePropertyManagerPrivate::slotIntChanged(QtProperty *property,
                                                  int value) {
  if (QtProperty *prop = m_wToProperty.value(property, nullptr)) {
    QSize s = m_values[prop].val;
    s.setWidth(value);
    q_ptr->setValue(prop, s);
  } else if (QtProperty *prop = m_hToProperty.value(property, nullptr)) {
    QSize s = m_values[prop].val;
    s.setHeight(value);
    q_ptr->setValue(prop, s);
  }
void QtSizePropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) {
  if (QtProperty *pointProp = m_wToProperty.value(property, nullptr)) {
    m_propertyToW[pointProp] = nullptr;
    m_wToProperty.remove(property);
  } else if (QtProperty *pointProp = m_hToProperty.value(property, nullptr)) {
    m_propertyToH[pointProp] = nullptr;
    m_hToProperty.remove(property);
  }
void QtSizePropertyManagerPrivate::setValue(QtProperty *property,
                                            const QSize &val) {
  m_intPropertyManager->setValue(m_propertyToW.value(property), val.width());
  m_intPropertyManager->setValue(m_propertyToH.value(property), val.height());
}

void QtSizePropertyManagerPrivate::setRange(QtProperty *property,
                                            const QSize &minVal,
                                            const QSize &maxVal,
                                            const QSize &val) {
  QtProperty *wProperty = m_propertyToW.value(property);
  QtProperty *hProperty = m_propertyToH.value(property);
  m_intPropertyManager->setRange(wProperty, minVal.width(), maxVal.width());
  m_intPropertyManager->setValue(wProperty, val.width());
  m_intPropertyManager->setRange(hProperty, minVal.height(), maxVal.height());
  m_intPropertyManager->setValue(hProperty, val.height());
}

/**
    \class QtSizePropertyManager

    \brief The QtSizePropertyManager provides and manages QSize properties.

    A size property has nested \e width and \e height
    subproperties. The top-level property's value can be retrieved
    using the value() function, and set using the setValue() slot.

    The subproperties are created by a QtIntPropertyManager object. This
    manager can be retrieved using the subIntPropertyManager() function. In
    order to provide editing widgets for the subproperties in a
    property browser widget, this manager must be associated with an
    editor factory.

    A size property also has a range of valid values defined by a
    minimum size and a maximum size. These sizes can be retrieved
    using the minimum() and the maximum() functions, and set using the
    setMinimum() and setMaximum() slots. Alternatively, the range can
    be defined in one go using the setRange() slot.

    In addition, QtSizePropertyManager provides the valueChanged() signal
    which is emitted whenever a property created by this manager
    changes, and the rangeChanged() signal which is emitted whenever
    such a property changes its range of valid sizes.

    \sa QtAbstractPropertyManager, QtIntPropertyManager, QtSizeFPropertyManager
*/

/**
    \fn void QtSizePropertyManager::valueChanged(QtProperty *property, const
   QSize &value)

    This signal is emitted whenever a property created by this manager
    changes its value, passing a pointer to the \a property and the new
    \a value as parameters.

    \sa setValue()
*/

/**
    \fn void QtSizePropertyManager::rangeChanged(QtProperty *property, const
   QSize &minimum, const QSize &maximum)

    This signal is emitted whenever a property created by this manager
    changes its range of valid sizes, passing a pointer to the \a
    property and the new \a minimum and \a maximum sizes.

    \sa setRange()
*/

/**
    Creates a manager with the given \a parent.
*/
QtSizePropertyManager::QtSizePropertyManager(QObject *parent)
    : QtAbstractPropertyManager(parent) {
  d_ptr = new QtSizePropertyManagerPrivate;
  d_ptr->q_ptr = this;
  d_ptr->m_intPropertyManager = new QtIntPropertyManager(this);
  connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
          this, SLOT(slotIntChanged(QtProperty *, int)));
  connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
          this, SLOT(slotPropertyDestroyed(QtProperty *)));
}

/**
    Destroys this manager, and all the properties it has created.
*/
QtSizePropertyManager::~QtSizePropertyManager() {
  clear();
  delete d_ptr;
}

/**
    Returns the manager that creates the nested \e width and \e height
    subproperties.

    In order to provide editing widgets for the \e width and \e height
    properties in a property browser widget, this manager must be
    associated with an editor factory.

    \sa QtAbstractPropertyBrowser::setFactoryForManager()
*/
QtIntPropertyManager *QtSizePropertyManager::subIntPropertyManager() const {
  return d_ptr->m_intPropertyManager;
}

/**
    Returns the given \a property's value.

    If the given \a property is not managed by this manager, this
    function returns an invalid size

    \sa setValue()
*/
QSize QtSizePropertyManager::value(const QtProperty *property) const {
  return getValue<QSize>(d_ptr->m_values, property);
}

/**
    Returns the given \a property's minimum size value.

    \sa setMinimum(), maximum(), setRange()
*/
QSize QtSizePropertyManager::minimum(const QtProperty *property) const {
  return getMinimum<QSize>(d_ptr->m_values, property);
}

/**
    Returns the given \a property's maximum size value.

    \sa setMaximum(), minimum(), setRange()
*/
QSize QtSizePropertyManager::maximum(const QtProperty *property) const {
  return getMaximum<QSize>(d_ptr->m_values, property);
QString QtSizePropertyManager::valueText(const QtProperty *property) const {
  const QtSizePropertyManagerPrivate::PropertyValueMap::const_iterator it =
      d_ptr->m_values.constFind(property);
  if (it == d_ptr->m_values.constEnd())
    return QString();
  const QSize v = it.value().val;
  return QString(tr("%1 x %2")
                     .arg(QString::number(v.width()))
                     .arg(QString::number(v.height())));
    \fn void QtSizePropertyManager::setValue(QtProperty *property, const QSize
   &value)

    Sets the value of the given \a property to \a value.

    If the specified \a value is not valid according to the given \a
    property's size range, the \a value is adjusted to the nearest
    valid value within the size range.

    \sa value(), setRange(), valueChanged()
*/
void QtSizePropertyManager::setValue(QtProperty *property, const QSize &val) {
  setValueInRange<const QSize &, QtSizePropertyManagerPrivate,
                  QtSizePropertyManager, const QSize>(
      this, d_ptr, &QtSizePropertyManager::propertyChanged,
      &QtSizePropertyManager::valueChanged, property, val,
      &QtSizePropertyManagerPrivate::setValue);
}

/**
    Sets the minimum size value for the given \a property to \a minVal.

    When setting the minimum size value, the maximum and current
    values are adjusted if necessary (ensuring that the size range
    remains valid and that the current value is within the range).

    \sa minimum(), setRange(), rangeChanged()
*/
void QtSizePropertyManager::setMinimum(QtProperty *property,
                                       const QSize &minVal) {
  setBorderValue<const QSize &, QtSizePropertyManagerPrivate,
                 QtSizePropertyManager, QSize,
                 QtSizePropertyManagerPrivate::Data>(
      this, d_ptr, &QtSizePropertyManager::propertyChanged,
      &QtSizePropertyManager::valueChanged,
      &QtSizePropertyManager::rangeChanged, property,
      &QtSizePropertyManagerPrivate::Data::minimumValue,
      &QtSizePropertyManagerPrivate::Data::setMinimumValue, minVal,
      &QtSizePropertyManagerPrivate::setRange);
}

/**
    Sets the maximum size value for the given \a property to \a maxVal.

    When setting the maximum size value, the minimum and current
    values are adjusted if necessary (ensuring that the size range
    remains valid and that the current value is within the range).

    \sa maximum(), setRange(), rangeChanged()
*/
void QtSizePropertyManager::setMaximum(QtProperty *property,
                                       const QSize &maxVal) {
  setBorderValue<const QSize &, QtSizePropertyManagerPrivate,
                 QtSizePropertyManager, QSize,
                 QtSizePropertyManagerPrivate::Data>(
      this, d_ptr, &QtSizePropertyManager::propertyChanged,
      &QtSizePropertyManager::valueChanged,
      &QtSizePropertyManager::rangeChanged, property,
      &QtSizePropertyManagerPrivate::Data::maximumValue,
      &QtSizePropertyManagerPrivate::Data::setMaximumValue, maxVal,
      &QtSizePropertyManagerPrivate::setRange);
    \fn void QtSizePropertyManager::setRange(QtProperty *property, const QSize
   &minimum, const QSize &maximum)

    Sets the range of valid values.

    This is a convenience function defining the range of valid values
    in one go; setting the \a minimum and \a maximum values for the
    given \a property with a single function call.

    When setting a new range, the current value is adjusted if
    necessary (ensuring that the value remains within the range).

    \sa  setMinimum(), setMaximum(), rangeChanged()
*/
void QtSizePropertyManager::setRange(QtProperty *property, const QSize &minVal,
                                     const QSize &maxVal) {
  setBorderValues<const QSize &, QtSizePropertyManagerPrivate,
                  QtSizePropertyManager, QSize>(
      this, d_ptr, &QtSizePropertyManager::propertyChanged,
      &QtSizePropertyManager::valueChanged,
      &QtSizePropertyManager::rangeChanged, property, minVal, maxVal,
      &QtSizePropertyManagerPrivate::setRange);
void QtSizePropertyManager::initializeProperty(QtProperty *property) {
  d_ptr->m_values[property] = QtSizePropertyManagerPrivate::Data();
  QtProperty *wProp = d_ptr->m_intPropertyManager->addProperty();
  wProp->setPropertyName(tr("Width"));
  d_ptr->m_intPropertyManager->setValue(wProp, 0);
  d_ptr->m_intPropertyManager->setMinimum(wProp, 0);
  d_ptr->m_propertyToW[property] = wProp;
  d_ptr->m_wToProperty[wProp] = property;
  property->addSubProperty(wProp);
  QtProperty *hProp = d_ptr->m_intPropertyManager->addProperty();
  hProp->setPropertyName(tr("Height"));
  d_ptr->m_intPropertyManager->setValue(hProp, 0);
  d_ptr->m_intPropertyManager->setMinimum(hProp, 0);
  d_ptr->m_propertyToH[property] = hProp;
  d_ptr->m_hToProperty[hProp] = property;
  property->addSubProperty(hProp);
void QtSizePropertyManager::uninitializeProperty(QtProperty *property) {
  QtProperty *wProp = d_ptr->m_propertyToW[property];
  if (wProp) {
    d_ptr->m_wToProperty.remove(wProp);
    delete wProp;
  }
  d_ptr->m_propertyToW.remove(property);
  QtProperty *hProp = d_ptr->m_propertyToH[property];
  if (hProp) {
    d_ptr->m_hToProperty.remove(hProp);
    delete hProp;
  }
  d_ptr->m_propertyToH.remove(property);
  d_ptr->m_values.remove(property);
}

// QtSizeFPropertyManager

class QtSizeFPropertyManagerPrivate {
  QtSizeFPropertyManager *q_ptr;
  Q_DECLARE_PUBLIC(QtSizeFPropertyManager)
public:
  void slotDoubleChanged(QtProperty *property, double value);
  void slotPropertyDestroyed(QtProperty *property);
  void setValue(QtProperty *property, const QSizeF &val);
  void setRange(QtProperty *property, const QSizeF &minVal,
                const QSizeF &maxVal, const QSizeF &val);

  struct Data {
    Data()
        : val(QSizeF(0, 0)), minVal(QSizeF(0, 0)),
          maxVal(QSizeF(INT_MAX, INT_MAX)), decimals(2) {}
    QSizeF val;
    QSizeF minVal;
    QSizeF maxVal;
    int decimals;
    QSizeF minimumValue() const { return minVal; }
    QSizeF maximumValue() const { return maxVal; }
    void setMinimumValue(const QSizeF &newMinVal) {
      setSizeMinimumData(this, newMinVal);
    }
    void setMaximumValue(const QSizeF &newMaxVal) {
      setSizeMaximumData(this, newMaxVal);
    }
  };
  typedef QMap<const QtProperty *, Data> PropertyValueMap;
  PropertyValueMap m_values;
  QtDoublePropertyManager *m_doublePropertyManager;
  QMap<const QtProperty *, QtProperty *> m_propertyToW;
  QMap<const QtProperty *, QtProperty *> m_propertyToH;
  QMap<const QtProperty *, QtProperty *> m_wToProperty;
  QMap<const QtProperty *, QtProperty *> m_hToProperty;
};

void QtSizeFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property,
                                                      double value) {
  if (QtProperty *prop = m_wToProperty.value(property, nullptr)) {
    QSizeF s = m_values[prop].val;
    s.setWidth(value);
    q_ptr->setValue(prop, s);
  } else if (QtProperty *prop = m_hToProperty.value(property, nullptr)) {
    QSizeF s = m_values[prop].val;
    s.setHeight(value);
    q_ptr->setValue(prop, s);
  }
}

void QtSizeFPropertyManagerPrivate::slotPropertyDestroyed(
    QtProperty *property) {
  if (QtProperty *pointProp = m_wToProperty.value(property, nullptr)) {
    m_propertyToW[pointProp] = nullptr;
    m_wToProperty.remove(property);
  } else if (QtProperty *pointProp = m_hToProperty.value(property, nullptr)) {
    m_propertyToH[pointProp] = nullptr;
    m_hToProperty.remove(property);
  }
}

void QtSizeFPropertyManagerPrivate::setValue(QtProperty *property,
                                             const QSizeF &val) {
  m_doublePropertyManager->setValue(m_propertyToW.value(property), val.width());
  m_doublePropertyManager->setValue(m_propertyToH.value(property),
                                    val.height());
}

void QtSizeFPropertyManagerPrivate::setRange(QtProperty *property,
                                             const QSizeF &minVal,
                                             const QSizeF &maxVal,
                                             const QSizeF &val) {
  m_doublePropertyManager->setRange(m_propertyToW[property], minVal.width(),
                                    maxVal.width());
  m_doublePropertyManager->setValue(m_propertyToW[property], val.width());
  m_doublePropertyManager->setRange(m_propertyToH[property], minVal.height(),
                                    maxVal.height());
  m_doublePropertyManager->setValue(m_propertyToH[property], val.height());
}

/**
    \class QtSizeFPropertyManager

    \brief The QtSizeFPropertyManager provides and manages QSizeF properties.

    A size property has nested \e width and \e height
    subproperties. The top-level property's value can be retrieved
    using the value() function, and set using the setValue() slot.

    The subproperties are created by a QtDoublePropertyManager object. This
    manager can be retrieved using the subDoublePropertyManager() function. In
    order to provide editing widgets for the subproperties in a
    property browser widget, this manager must be associated with an
    editor factory.

    A size property also has a range of valid values defined by a
    minimum size and a maximum size. These sizes can be retrieved
    using the minimum() and the maximum() functions, and set using the
    setMinimum() and setMaximum() slots. Alternatively, the range can
    be defined in one go using the setRange() slot.

    In addition, QtSizeFPropertyManager provides the valueChanged() signal
    which is emitted whenever a property created by this manager
    changes, and the rangeChanged() signal which is emitted whenever
    such a property changes its range of valid sizes.

    \sa QtAbstractPropertyManager, QtDoublePropertyManager,
   QtSizePropertyManager
    \fn void QtSizeFPropertyManager::valueChanged(QtProperty *property, const
   QSizeF &value)

    This signal is emitted whenever a property created by this manager
    changes its value, passing a pointer to the \a property and the new
    \a value as parameters.

    \sa setValue()
*/

/**
    \fn void QtSizeFPropertyManager::rangeChanged(QtProperty *property, const
   QSizeF &minimum, const QSizeF &maximum)

    This signal is emitted whenever a property created by this manager
    changes its range of valid sizes, passing a pointer to the \a
    property and the new \a minimum and \a maximum sizes.

    \sa setRange()
*/

/**
    \fn void QtSizeFPropertyManager::decimalsChanged(QtProperty *property, int
   prec)

    This signal is emitted whenever a property created by this manager
    changes its precision of value, passing a pointer to the
    \a property and the new \a prec value

    \sa setDecimals()
*/

/**
    Creates a manager with the given \a parent.
*/
QtSizeFPropertyManager::QtSizeFPropertyManager(QObject *parent)
    : QtAbstractPropertyManager(parent) {
  d_ptr = new QtSizeFPropertyManagerPrivate;
  d_ptr->q_ptr = this;
  d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this);
  connect(d_ptr->m_doublePropertyManager,
          SIGNAL(valueChanged(QtProperty *, double)), this,
          SLOT(slotDoubleChanged(QtProperty *, double)));
  connect(d_ptr->m_doublePropertyManager,
          SIGNAL(propertyDestroyed(QtProperty *)), this,
          SLOT(slotPropertyDestroyed(QtProperty *)));
}

/**
    Destroys this manager, and all the properties it has created.
*/
QtSizeFPropertyManager::~QtSizeFPropertyManager() {
  clear();
  delete d_ptr;
}

/**
    Returns the manager that creates the nested \e width and \e height
    subproperties.

    In order to provide editing widgets for the \e width and \e height
    properties in a property browser widget, this manager must be
    associated with an editor factory.

    \sa QtAbstractPropertyBrowser::setFactoryForManager()
*/
QtDoublePropertyManager *
QtSizeFPropertyManager::subDoublePropertyManager() const {
  return d_ptr->m_doublePropertyManager;
}

/**
    Returns the given \a property's value.

    If the given \a property is not managed by this manager, this
    function returns an invalid size

    \sa setValue()
*/
QSizeF QtSizeFPropertyManager::value(const QtProperty *property) const {
  return getValue<QSizeF>(d_ptr->m_values, property);
}

/**
    Returns the given \a property's precision, in decimals.

    \sa setDecimals()
*/
int QtSizeFPropertyManager::decimals(const QtProperty *property) const {
  return getData<int>(d_ptr->m_values,
                      &QtSizeFPropertyManagerPrivate::Data::decimals, property,
                      0);
}

/**
    Returns the given \a property's minimum size value.

    \sa setMinimum(), maximum(), setRange()
*/
QSizeF QtSizeFPropertyManager::minimum(const QtProperty *property) const {
  return getMinimum<QSizeF>(d_ptr->m_values, property);
}

/**
    Returns the given \a property's maximum size value.

    \sa setMaximum(), minimum(), setRange()
*/
QSizeF QtSizeFPropertyManager::maximum(const QtProperty *property) const {
  return getMaximum<QSizeF>(d_ptr->m_values, property);
QString QtSizeFPropertyManager::valueText(const QtProperty *property) const {
  const QtSizeFPropertyManagerPrivate::PropertyValueMap::const_iterator it =
      d_ptr->m_values.constFind(property);
  if (it == d_ptr->m_values.constEnd())
    return QString();
  const QSizeF v = it.value().val;
  const int dec = it.value().decimals;
  return QString(tr("%1 x %2")
                     .arg(QString::number(v.width(), 'f', dec))
                     .arg(QString::number(v.height(), 'f', dec)));
    \fn void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF
   &value)

    Sets the value of the given \a property to \a value.

    If the specified \a value is not valid according to the given \a
    property's size range, the \a value is adjusted to the nearest
    valid value within the size range.

    \sa value(), setRange(), valueChanged()
*/
void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF &val) {
  setValueInRange<const QSizeF &, QtSizeFPropertyManagerPrivate,
                  QtSizeFPropertyManager, QSizeF>(
      this, d_ptr, &QtSizeFPropertyManager::propertyChanged,
      &QtSizeFPropertyManager::valueChanged, property, val,
      &QtSizeFPropertyManagerPrivate::setValue);
}

/**
    \fn void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec)

    Sets the precision of the given \a property to \a prec.

    The valid decimal range is 0-13. The default is 2.

    \sa decimals()
*/
void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec) {
  const QtSizeFPropertyManagerPrivate::PropertyValueMap::iterator it =
      d_ptr->m_values.find(property);
  if (it == d_ptr->m_values.end())
    return;
  QtSizeFPropertyManagerPrivate::Data data = it.value();
  if (prec > 13)
    prec = 13;
  else if (prec < 0)
    prec = 0;
  if (data.decimals == prec)
    return;
  data.decimals = prec;
  d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToW[property],
                                              prec);
  d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToH[property],
                                              prec);
  it.value() = data;
  emit decimalsChanged(property, data.decimals);
}

/**
    Sets the minimum size value for the given \a property to \a minVal.

    When setting the minimum size value, the maximum and current
    values are adjusted if necessary (ensuring that the size range
    remains valid and that the current value is within the range).

    \sa minimum(), setRange(), rangeChanged()
*/
void QtSizeFPropertyManager::setMinimum(QtProperty *property,
                                        const QSizeF &minVal) {
  setBorderValue<const QSizeF &, QtSizeFPropertyManagerPrivate,
                 QtSizeFPropertyManager, QSizeF,
                 QtSizeFPropertyManagerPrivate::Data>(
      this, d_ptr, &QtSizeFPropertyManager::propertyChanged,
      &QtSizeFPropertyManager::valueChanged,
      &QtSizeFPropertyManager::rangeChanged, property,
      &QtSizeFPropertyManagerPrivate::Data::minimumValue,
      &QtSizeFPropertyManagerPrivate::Data::setMinimumValue, minVal,
      &QtSizeFPropertyManagerPrivate::setRange);
}

/**
    Sets the maximum size value for the given \a property to \a maxVal.

    When setting the maximum size value, the minimum and current
    values are adjusted if necessary (ensuring that the size range
    remains valid and that the current value is within the range).

    \sa maximum(), setRange(), rangeChanged()
*/
void QtSizeFPropertyManager::setMaximum(QtProperty *property,
                                        const QSizeF &maxVal) {
  setBorderValue<const QSizeF &, QtSizeFPropertyManagerPrivate,
                 QtSizeFPropertyManager, QSizeF,
                 QtSizeFPropertyManagerPrivate::Data>(
      this, d_ptr, &QtSizeFPropertyManager::propertyChanged,
      &QtSizeFPropertyManager::valueChanged,
      &QtSizeFPropertyManager::rangeChanged, property,
      &QtSizeFPropertyManagerPrivate::Data::maximumValue,
      &QtSizeFPropertyManagerPrivate::Data::setMaximumValue, maxVal,
      &QtSizeFPropertyManagerPrivate::setRange);
    \fn void QtSizeFPropertyManager::setRange(QtProperty *property, const QSizeF
   &minimum, const QSizeF &maximum)

    Sets the range of valid values.

    This is a convenience function defining the range of valid values
    in one go; setting the \a minimum and \a maximum values for the
    given \a property with a single function call.

    When setting a new range, the current value is adjusted if
    necessary (ensuring that the value remains within the range).

    \sa  setMinimum(), setMaximum(), rangeChanged()
*/
void QtSizeFPropertyManager::setRange(QtProperty *property,
                                      const QSizeF &minVal,
                                      const QSizeF &maxVal) {
  setBorderValues<const QSizeF &, QtSizeFPropertyManagerPrivate,
                  QtSizeFPropertyManager, QSizeF>(
      this, d_ptr, &QtSizeFPropertyManager::propertyChanged,
      &QtSizeFPropertyManager::valueChanged,
      &QtSizeFPropertyManager::rangeChanged, property, minVal, maxVal,
      &QtSizeFPropertyManagerPrivate::setRange);
void QtSizeFPropertyManager::initializeProperty(QtProperty *property) {
  d_ptr->m_values[property] = QtSizeFPropertyManagerPrivate::Data();
  QtProperty *wProp = d_ptr->m_doublePropertyManager->addProperty();
  wProp->setPropertyName(tr("Width"));
  d_ptr->m_doublePropertyManager->setDecimals(wProp, decimals(property));
  d_ptr->m_doublePropertyManager->setValue(wProp, 0);
  d_ptr->m_doublePropertyManager->setMinimum(wProp, 0);
  d_ptr->m_propertyToW[property] = wProp;
  d_ptr->m_wToProperty[wProp] = property;
  property->addSubProperty(wProp);
  QtProperty *hProp = d_ptr->m_doublePropertyManager->addProperty();
  hProp->setPropertyName(tr("Height"));
  d_ptr->m_doublePropertyManager->setDecimals(hProp, decimals(property));
  d_ptr->m_doublePropertyManager->setValue(hProp, 0);
  d_ptr->m_doublePropertyManager->setMinimum(hProp, 0);
  d_ptr->m_propertyToH[property] = hProp;
  d_ptr->m_hToProperty[hProp] = property;
  property->addSubProperty(hProp);
void QtSizeFPropertyManager::uninitializeProperty(QtProperty *property) {
  QtProperty *wProp = d_ptr->m_propertyToW[property];
  if (wProp) {
    d_ptr->m_wToProperty.remove(wProp);
    delete wProp;
  }
  d_ptr->m_propertyToW.remove(property);
  QtProperty *hProp = d_ptr->m_propertyToH[property];
  if (hProp) {
    d_ptr->m_hToProperty.remove(hProp);
    delete hProp;
  }
  d_ptr->m_propertyToH.remove(property);
  d_ptr->m_values.remove(property);
}

// QtRectPropertyManager

class QtRectPropertyManagerPrivate {
  QtRectPropertyManager *q_ptr;
  Q_DECLARE_PUBLIC(QtRectPropertyManager)
public:
  void slotIntChanged(QtProperty *property, int value);
  void slotPropertyDestroyed(QtProperty *property);
  void setConstraint(QtProperty *property, const QRect &constraint,
                     const QRect &val);

  struct Data {
    Data() : val(0, 0, 0, 0) {}
    QRect val;
    QRect constraint;
  };

  typedef QMap<const QtProperty *, Data> PropertyValueMap;
  PropertyValueMap m_values;

  QtIntPropertyManager *m_intPropertyManager;

  QMap<const QtProperty *, QtProperty *> m_propertyToX;
  QMap<const QtProperty *, QtProperty *> m_propertyToY;
  QMap<const QtProperty *, QtProperty *> m_propertyToW;
  QMap<const QtProperty *, QtProperty *> m_propertyToH;

  QMap<const QtProperty *, QtProperty *> m_xToProperty;
  QMap<const QtProperty *, QtProperty *> m_yToProperty;
  QMap<const QtProperty *, QtProperty *> m_wToProperty;
  QMap<const QtProperty *, QtProperty *> m_hToProperty;
void QtRectPropertyManagerPrivate::slotIntChanged(QtProperty *property,
                                                  int value) {
  if (QtProperty *prop = m_xToProperty.value(property, nullptr)) {
    QRect r = m_values[prop].val;
    r.moveLeft(value);
    q_ptr->setValue(prop, r);
  } else if (QtProperty *prop = m_yToProperty.value(property)) {
    QRect r = m_values[prop].val;
    r.moveTop(value);
    q_ptr->setValue(prop, r);
  } else if (QtProperty *prop = m_wToProperty.value(property, nullptr)) {
    Data data = m_values[prop];
    QRect r = data.val;
    r.setWidth(value);
    if (!data.constraint.isNull() &&
        data.constraint.x() + data.constraint.width() < r.x() + r.width()) {
      r.moveLeft(data.constraint.left() + data.constraint.width() - r.width());
    q_ptr->setValue(prop, r);
  } else if (QtProperty *prop = m_hToProperty.value(property, nullptr)) {
    Data data = m_values[prop];
    QRect r = data.val;
    r.setHeight(value);
    if (!data.constraint.isNull() &&
        data.constraint.y() + data.constraint.height() < r.y() + r.height()) {
      r.moveTop(data.constraint.top() + data.constraint.height() - r.height());
    q_ptr->setValue(prop, r);
  }
}

void QtRectPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) {
  if (QtProperty *pointProp = m_xToProperty.value(property, nullptr)) {
    m_propertyToX[pointProp] = nullptr;
    m_xToProperty.remove(property);
  } else if (QtProperty *pointProp = m_yToProperty.value(property, nullptr)) {
    m_propertyToY[pointProp] = nullptr;
    m_yToProperty.remove(property);
  } else if (QtProperty *pointProp = m_wToProperty.value(property, nullptr)) {
    m_propertyToW[pointProp] = nullptr;
    m_wToProperty.remove(property);
  } else if (QtProperty *pointProp = m_hToProperty.value(property, nullptr)) {
    m_propertyToH[pointProp] = nullptr;
    m_hToProperty.remove(property);
  }
}

void QtRectPropertyManagerPrivate::setConstraint(QtProperty *property,
                                                 const QRect &constraint,
                                                 const QRect &val) {
  const bool isNull = constraint.isNull();
  const int left = isNull ? INT_MIN : constraint.left();
  const int right = isNull ? INT_MAX : constraint.left() + constraint.width();
  const int top = isNull ? INT_MIN : constraint.top();
  const int bottom = isNull ? INT_MAX : constraint.top() + constraint.height();
  const int width = isNull ? INT_MAX : constraint.width();
  const int height = isNull ? INT_MAX : constraint.height();
  m_intPropertyManager->setRange(m_propertyToX[property], left, right);
  m_intPropertyManager->setRange(m_propertyToY[property], top, bottom);
  m_intPropertyManager->setRange(m_propertyToW[property], 0, width);
  m_intPropertyManager->setRange(m_propertyToH[property], 0, height);
  m_intPropertyManager->setValue(m_propertyToX[property], val.x());
  m_intPropertyManager->setValue(m_propertyToY[property], val.y());
  m_intPropertyManager->setValue(m_propertyToW[property], val.width());
  m_intPropertyManager->setValue(m_propertyToH[property], val.height());
}

/**
    \class QtRectPropertyManager

    \brief The QtRectPropertyManager provides and manages QRect properties.

    A rectangle property has nested \e x, \e y, \e width and \e height
    subproperties. The top-level property's value can be retrieved
    using the value() function, and set using the setValue() slot.

    The subproperties are created by a QtIntPropertyManager object. This
    manager can be retrieved using the subIntPropertyManager() function. In
    order to provide editing widgets for the subproperties in a
    property browser widget, this manager must be associated with an
    editor factory.

    A rectangle property also has a constraint rectangle which can be
    retrieved using the constraint() function, and set using the
    setConstraint() slot.

    In addition, QtRectPropertyManager provides the valueChanged() signal
    which is emitted whenever a property created by this manager
    changes, and the constraintChanged() signal which is emitted
    whenever such a property changes its constraint rectangle.

    \sa QtAbstractPropertyManager, QtIntPropertyManager, QtRectFPropertyManager
*/

/**
    \fn void QtRectPropertyManager::valueChanged(QtProperty *property, const
   QRect &value)

    This signal is emitted whenever a property created by this manager
    changes its value, passing a pointer to the \a property and the new
    \a value as parameters.

    \sa setValue()
*/

/**
    \fn void QtRectPropertyManager::constraintChanged(QtProperty *property,
   const QRect &constraint)

    This signal is emitted whenever property changes its constraint
    rectangle, passing a pointer to the \a property and the new \a
    constraint rectangle as parameters.

    \sa setConstraint()
*/

/**
    Creates a manager with the given \a parent.
*/
QtRectPropertyManager::QtRectPropertyManager(QObject *parent)
    : QtAbstractPropertyManager(parent) {
  d_ptr = new QtRectPropertyManagerPrivate;
  d_ptr->q_ptr = this;
  d_ptr->m_intPropertyManager = new QtIntPropertyManager(this);
  connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
          this, SLOT(slotIntChanged(QtProperty *, int)));
  connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
          this, SLOT(slotPropertyDestroyed(QtProperty *)));
}

/**
    Destroys this manager, and all the properties it has created.
*/
QtRectPropertyManager::~QtRectPropertyManager() {
  clear();
  delete d_ptr;
}

/**
    Returns the manager that creates the nested \e x, \e y, \e width
    and \e height subproperties.

    In order to provide editing widgets for the mentioned
    subproperties in a property browser widget, this manager must be
    associated with an editor factory.

    \sa QtAbstractPropertyBrowser::setFactoryForManager()
*/
QtIntPropertyManager *QtRectPropertyManager::subIntPropertyManager() const {
  return d_ptr->m_intPropertyManager;
}

/**
    Returns the given \a property's value.