Chris@0: /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@0: A waveform viewer and audio annotation editor. Chris@0: Chris Cannam, Queen Mary University of London, 2005 Chris@0: Chris@0: This is experimental software. Not for distribution. Chris@0: */ Chris@0: Chris@0: #include "PropertyBox.h" Chris@0: Chris@0: #include "base/PropertyContainer.h" Chris@0: Chris@0: #include "AudioDial.h" Chris@0: Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: Chris@0: #include Chris@0: #include Chris@0: Chris@0: //#define DEBUG_PROPERTY_BOX 1 Chris@0: Chris@0: PropertyBox::PropertyBox(PropertyContainer *container) : Chris@0: m_container(container) Chris@0: { Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox[" << this << "(\"" << Chris@0: container->getPropertyContainerName().toStdString() << "\")]::PropertyBox" << std::endl; Chris@0: #endif Chris@0: Chris@0: m_layout = new QGridLayout; Chris@0: setLayout(m_layout); Chris@0: Chris@0: PropertyContainer::PropertyList properties = container->getProperties(); Chris@0: Chris@0: blockSignals(true); Chris@0: Chris@0: size_t i; Chris@0: Chris@0: for (i = 0; i < properties.size(); ++i) { Chris@0: updatePropertyEditor(properties[i]); Chris@0: } Chris@0: Chris@0: blockSignals(false); Chris@0: Chris@0: m_layout->setRowStretch(m_layout->rowCount(), 10); Chris@0: Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox[" << this << "]::PropertyBox returning" << std::endl; Chris@0: #endif Chris@0: } Chris@0: Chris@0: PropertyBox::~PropertyBox() Chris@0: { Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox[" << this << "(\"" << m_container->getPropertyContainerName().toStdString() << "\")]::~PropertyBox" << std::endl; Chris@0: #endif Chris@0: } Chris@0: Chris@0: void Chris@0: PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name) Chris@0: { Chris@0: PropertyContainer::PropertyType type = m_container->getPropertyType(name); Chris@0: int row = m_layout->rowCount(); Chris@0: Chris@0: int min = 0, max = 0, value = 0; Chris@0: value = m_container->getPropertyRangeAndValue(name, &min, &max); Chris@0: Chris@0: bool have = (m_propertyControllers.find(name) != Chris@0: m_propertyControllers.end()); Chris@0: Chris@0: QString groupName = m_container->getPropertyGroupName(name); Chris@0: Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox[" << this Chris@0: << "(\"" << m_container->getPropertyContainerName().toStdString() Chris@0: << "\")]"; Chris@0: std::cerr << "::updatePropertyEditor(\"" << name.toStdString() << "\"):"; Chris@0: std::cerr << " value " << value << ", have " << have << ", group \"" Chris@0: << groupName.toStdString() << "\"" << std::endl; Chris@0: #endif Chris@0: Chris@0: bool inGroup = (groupName != QString()); Chris@0: Chris@0: if (!have) { Chris@0: if (inGroup) { Chris@0: if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) { Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox: adding label \"" << groupName.toStdString() << "\" and frame for group for \"" << name.toStdString() << "\"" << std::endl; Chris@0: #endif Chris@0: m_layout->addWidget(new QLabel(groupName, this), row, 0); Chris@0: QFrame *frame = new QFrame(this); Chris@0: m_layout->addWidget(frame, row, 1, 1, 2); Chris@0: m_groupLayouts[groupName] = new QHBoxLayout; Chris@0: m_groupLayouts[groupName]->setMargin(0); Chris@0: frame->setLayout(m_groupLayouts[groupName]); Chris@0: } Chris@0: } else { Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox: adding label \"" << name.toStdString() << "\"" << std::endl; Chris@0: #endif Chris@0: m_layout->addWidget(new QLabel(name, this), row, 0); Chris@0: } Chris@0: } Chris@0: Chris@0: switch (type) { Chris@0: Chris@0: case PropertyContainer::ToggleProperty: Chris@0: { Chris@0: QCheckBox *cb; Chris@0: Chris@0: if (have) { Chris@0: cb = dynamic_cast(m_propertyControllers[name]); Chris@0: assert(cb); Chris@0: } else { Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox: creating new checkbox" << std::endl; Chris@0: #endif Chris@0: cb = new QCheckBox(); Chris@0: cb->setObjectName(name); Chris@0: connect(cb, SIGNAL(stateChanged(int)), Chris@0: this, SLOT(propertyControllerChanged(int))); Chris@0: if (inGroup) { Chris@0: cb->setToolTip(name); Chris@0: m_groupLayouts[groupName]->addWidget(cb); Chris@0: } else { Chris@0: m_layout->addWidget(cb, row, 1, 1, 2); Chris@0: } Chris@0: m_propertyControllers[name] = cb; Chris@0: } Chris@0: Chris@0: if (cb->isChecked() != (value > 0)) cb->setChecked(value > 0); Chris@0: break; Chris@0: } Chris@0: Chris@0: case PropertyContainer::RangeProperty: Chris@0: { Chris@0: AudioDial *dial; Chris@0: Chris@0: if (have) { Chris@0: dial = dynamic_cast(m_propertyControllers[name]); Chris@0: assert(dial); Chris@0: } else { Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox: creating new dial" << std::endl; Chris@0: #endif Chris@0: dial = new AudioDial(); Chris@0: dial->setObjectName(name); Chris@0: dial->setMinimum(min); Chris@0: dial->setMaximum(max); Chris@0: dial->setPageStep(1); Chris@0: dial->setNotchesVisible(true); Chris@0: connect(dial, SIGNAL(valueChanged(int)), Chris@0: this, SLOT(propertyControllerChanged(int))); Chris@0: Chris@0: if (inGroup) { Chris@0: dial->setFixedWidth(24); Chris@0: dial->setFixedHeight(24); Chris@0: dial->setToolTip(name); Chris@0: m_groupLayouts[groupName]->addWidget(dial); Chris@0: } else { Chris@0: dial->setFixedWidth(32); Chris@0: dial->setFixedHeight(32); Chris@0: m_layout->addWidget(dial, row, 1); Chris@0: QLabel *label = new QLabel(this); Chris@0: connect(dial, SIGNAL(valueChanged(int)), Chris@0: label, SLOT(setNum(int))); Chris@0: label->setNum(value); Chris@0: m_layout->addWidget(label, row, 2); Chris@0: } Chris@0: Chris@0: m_propertyControllers[name] = dial; Chris@0: } Chris@0: Chris@0: if (dial->value() != value) dial->setValue(value); Chris@0: break; Chris@0: } Chris@0: Chris@0: case PropertyContainer::ValueProperty: Chris@0: { Chris@0: QComboBox *cb; Chris@0: Chris@0: if (have) { Chris@0: cb = dynamic_cast(m_propertyControllers[name]); Chris@0: assert(cb); Chris@0: } else { Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox: creating new combobox" << std::endl; Chris@0: #endif Chris@0: Chris@0: cb = new QComboBox(); Chris@0: cb->setObjectName(name); Chris@0: for (int i = min; i <= max; ++i) { Chris@0: cb->addItem(m_container->getPropertyValueLabel(name, i)); Chris@0: } Chris@0: connect(cb, SIGNAL(activated(int)), Chris@0: this, SLOT(propertyControllerChanged(int))); Chris@0: if (inGroup) { Chris@0: cb->setToolTip(name); Chris@0: m_groupLayouts[groupName]->addWidget(cb); Chris@0: } else { Chris@0: m_layout->addWidget(cb, row, 1, 1, 2); Chris@0: } Chris@0: m_propertyControllers[name] = cb; Chris@0: } Chris@0: Chris@0: if (cb->currentIndex() != value) cb->setCurrentIndex(value); Chris@0: Chris@0: #ifdef Q_WS_MAC Chris@0: // Crashes on startup without this, for some reason Chris@0: cb->setMinimumSize(QSize(10, 10)); Chris@0: #endif Chris@0: Chris@0: break; Chris@0: } Chris@0: Chris@0: default: Chris@0: break; Chris@0: } Chris@0: } Chris@0: Chris@0: void Chris@0: PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc) Chris@0: { Chris@0: if (pc != m_container) return; Chris@0: Chris@0: PropertyContainer::PropertyList properties = m_container->getProperties(); Chris@0: size_t i; Chris@0: Chris@0: blockSignals(true); Chris@0: Chris@0: for (i = 0; i < properties.size(); ++i) { Chris@0: updatePropertyEditor(properties[i]); Chris@0: } Chris@0: Chris@0: blockSignals(false); Chris@0: } Chris@0: Chris@0: void Chris@0: PropertyBox::propertyControllerChanged(int value) Chris@0: { Chris@0: QObject *obj = sender(); Chris@0: QString name = obj->objectName(); Chris@0: Chris@0: // std::cerr << "PropertyBox::propertyControllerChanged(" << name.toStdString() Chris@0: // << ", " << value << ")" << std::endl; Chris@0: Chris@0: PropertyContainer::PropertyType type = m_container->getPropertyType(name); Chris@0: Chris@0: if (type != PropertyContainer::InvalidProperty) { Chris@0: m_container->setProperty(name, value); Chris@0: } Chris@0: Chris@0: if (type == PropertyContainer::RangeProperty) { Chris@0: AudioDial *dial = dynamic_cast(m_propertyControllers[name]); Chris@0: if (dial) { Chris@0: dial->setToolTip(QString("%1: %2").arg(name).arg(value)); Chris@0: //!!! unfortunately this doesn't update an already-visible tooltip Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: Chris@0: Chris@0: #ifdef INCLUDE_MOCFILES Chris@0: #include "PropertyBox.moc.cpp" Chris@0: #endif Chris@0: