Chris@58: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@59: Sonic Visualiser Chris@59: An audio file viewer and annotation editor. Chris@59: Centre for Digital Music, Queen Mary, University of London. Chris@182: This file copyright 2006 Chris Cannam and QMUL. Chris@0: Chris@59: This program is free software; you can redistribute it and/or Chris@59: modify it under the terms of the GNU General Public License as Chris@59: published by the Free Software Foundation; either version 2 of the Chris@59: License, or (at your option) any later version. See the file Chris@59: COPYING included with this distribution for more information. Chris@0: */ Chris@0: Chris@0: #include "PropertyBox.h" Chris@63: #include "PluginParameterDialog.h" Chris@0: Chris@0: #include "base/PropertyContainer.h" Chris@33: #include "base/PlayParameters.h" Chris@377: #include "base/PlayParameterRepository.h" Chris@128: #include "layer/Layer.h" Chris@376: #include "layer/ColourDatabase.h" Chris@100: #include "base/UnitDatabase.h" Chris@167: #include "base/RangeMapper.h" Chris@0: Chris@63: #include "plugin/RealTimePluginFactory.h" Chris@63: #include "plugin/RealTimePluginInstance.h" Chris@71: #include "plugin/PluginXml.h" Chris@63: Chris@0: #include "AudioDial.h" Chris@33: #include "LEDButton.h" Chris@335: #include "IconLoader.h" Chris@0: Chris@189: #include "NotifyingCheckBox.h" Chris@189: #include "NotifyingComboBox.h" Chris@335: #include "NotifyingPushButton.h" Chris@285: #include "ColourNameDialog.h" Chris@189: Chris@0: #include Chris@0: #include Chris@33: #include Chris@63: #include Chris@0: #include Chris@33: #include Chris@218: #include Chris@285: #include Chris@285: #include Chris@0: Chris@0: #include Chris@0: #include Martin@46: #include Chris@0: Chris@456: //#define DEBUG_PROPERTY_BOX 1 Chris@0: Chris@0: PropertyBox::PropertyBox(PropertyContainer *container) : Chris@185: m_container(container), Chris@189: m_showButton(0), Chris@189: m_playButton(0) Chris@0: { Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox[" << this << "(\"" << Chris@456: container->getPropertyContainerName().toStdString() << "\" at " << container << ")]::PropertyBox" << std::endl; Chris@0: #endif Chris@0: Chris@34: m_mainBox = new QVBoxLayout; Chris@34: setLayout(m_mainBox); Chris@33: Chris@107: // m_nameWidget = new QLabel; Chris@107: // m_mainBox->addWidget(m_nameWidget); Chris@107: // m_nameWidget->setText(container->objectName()); Chris@107: Chris@34: m_mainWidget = new QWidget; Chris@34: m_mainBox->addWidget(m_mainWidget); Chris@107: m_mainBox->insertStretch(2, 10); Chris@33: Chris@34: m_viewPlayFrame = 0; Chris@34: populateViewPlayFrame(); Chris@33: Chris@0: m_layout = new QGridLayout; Chris@34: m_layout->setMargin(0); Chris@33: m_mainWidget->setLayout(m_layout); Chris@0: Chris@34: PropertyContainer::PropertyList properties = m_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@100: connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()), Chris@100: this, SLOT(unitDatabaseChanged())); Chris@100: Chris@285: connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()), Chris@285: this, SLOT(colourDatabaseChanged())); Chris@285: 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@33: std::cerr << "PropertyBox[" << this << "]::~PropertyBox" << std::endl; Chris@0: #endif Chris@0: } Chris@0: Chris@0: void Chris@34: PropertyBox::populateViewPlayFrame() Chris@33: { Chris@36: #ifdef DEBUG_PROPERTY_BOX Chris@34: std::cerr << "PropertyBox(" << m_container << ")::populateViewPlayFrame" << std::endl; Chris@36: #endif Chris@34: Chris@34: if (m_viewPlayFrame) { Chris@34: delete m_viewPlayFrame; Chris@34: m_viewPlayFrame = 0; Chris@34: } Chris@34: Chris@34: if (!m_container) return; Chris@34: Chris@34: Layer *layer = dynamic_cast(m_container); Chris@34: if (layer) { Chris@193: disconnect(layer, SIGNAL(modelReplaced()), Chris@193: this, SLOT(populateViewPlayFrame())); Chris@34: connect(layer, SIGNAL(modelReplaced()), Chris@34: this, SLOT(populateViewPlayFrame())); Chris@34: } Chris@34: Chris@34: PlayParameters *params = m_container->getPlayParameters(); Chris@33: if (!params && !layer) return; Chris@33: Chris@34: m_viewPlayFrame = new QFrame; Chris@34: m_viewPlayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); Chris@34: m_mainBox->addWidget(m_viewPlayFrame); Chris@34: Chris@34: QHBoxLayout *layout = new QHBoxLayout; Chris@34: m_viewPlayFrame->setLayout(layout); Chris@34: Chris@34: layout->setMargin(layout->margin() / 2); Chris@34: Chris@36: #ifdef DEBUG_PROPERTY_BOX Chris@34: std::cerr << "PropertyBox::populateViewPlayFrame: container " << m_container << " (name " << m_container->getPropertyContainerName().toStdString() << ") params " << params << std::endl; Chris@36: #endif Chris@36: Chris@33: if (layer) { Chris@34: QLabel *showLabel = new QLabel(tr("Show")); Chris@34: layout->addWidget(showLabel); Chris@34: layout->setAlignment(showLabel, Qt::AlignVCenter); Chris@34: Chris@185: m_showButton = new LEDButton(Qt::blue); Chris@185: layout->addWidget(m_showButton); Chris@185: connect(m_showButton, SIGNAL(stateChanged(bool)), Chris@47: this, SIGNAL(showLayer(bool))); Chris@189: connect(m_showButton, SIGNAL(mouseEntered()), Chris@189: this, SLOT(mouseEnteredWidget())); Chris@189: connect(m_showButton, SIGNAL(mouseLeft()), Chris@189: this, SLOT(mouseLeftWidget())); Chris@185: layout->setAlignment(m_showButton, Qt::AlignVCenter); Chris@33: } Chris@33: Chris@33: if (params) { Chris@34: Chris@34: QLabel *playLabel = new QLabel(tr("Play")); Chris@34: layout->addWidget(playLabel); Chris@34: layout->setAlignment(playLabel, Qt::AlignVCenter); Chris@34: Chris@189: m_playButton = new LEDButton(Qt::darkGreen); Chris@189: m_playButton->setState(!params->isPlayMuted()); Chris@189: layout->addWidget(m_playButton); Chris@189: connect(m_playButton, SIGNAL(stateChanged(bool)), Chris@377: this, SLOT(playAudibleButtonChanged(bool))); Chris@189: connect(m_playButton, SIGNAL(mouseEntered()), Chris@189: this, SLOT(mouseEnteredWidget())); Chris@189: connect(m_playButton, SIGNAL(mouseLeft()), Chris@189: this, SLOT(mouseLeftWidget())); Chris@34: connect(params, SIGNAL(playAudibleChanged(bool)), Chris@377: this, SLOT(playAudibleChanged(bool))); Chris@189: layout->setAlignment(m_playButton, Qt::AlignVCenter); Chris@34: Chris@34: layout->insertStretch(-1, 10); Chris@34: Chris@63: if (params->getPlayPluginId() != "") { Chris@64: QPushButton *pluginButton = new QPushButton(QIcon(":icons/faders.png"), ""); Chris@64: pluginButton->setFixedWidth(24); Chris@64: pluginButton->setFixedHeight(24); Chris@63: layout->addWidget(pluginButton); Chris@63: connect(pluginButton, SIGNAL(clicked()), Chris@63: this, SLOT(editPlugin())); Chris@63: } Chris@63: Chris@34: AudioDial *gainDial = new AudioDial; Chris@34: layout->addWidget(gainDial); Chris@34: gainDial->setMeterColor(Qt::darkRed); Chris@34: gainDial->setMinimum(-50); Chris@34: gainDial->setMaximum(50); Chris@34: gainDial->setPageStep(1); Chris@34: gainDial->setFixedWidth(24); Chris@34: gainDial->setFixedHeight(24); Chris@34: gainDial->setNotchesVisible(false); Chris@34: gainDial->setDefaultValue(0); Chris@168: gainDial->setObjectName(tr("Playback Gain")); Chris@167: gainDial->setRangeMapper(new LinearRangeMapper Chris@167: (-50, 50, -25, 25, tr("dB"))); Chris@168: gainDial->setShowToolTip(true); Chris@34: connect(gainDial, SIGNAL(valueChanged(int)), Chris@34: this, SLOT(playGainDialChanged(int))); Chris@34: connect(params, SIGNAL(playGainChanged(float)), Chris@34: this, SLOT(playGainChanged(float))); Chris@34: connect(this, SIGNAL(changePlayGainDial(int)), Chris@34: gainDial, SLOT(setValue(int))); Chris@189: connect(gainDial, SIGNAL(mouseEntered()), Chris@189: this, SLOT(mouseEnteredWidget())); Chris@189: connect(gainDial, SIGNAL(mouseLeft()), Chris@189: this, SLOT(mouseLeftWidget())); Chris@377: playGainChanged(params->getPlayGain()); Chris@34: layout->setAlignment(gainDial, Qt::AlignVCenter); Chris@34: Chris@34: AudioDial *panDial = new AudioDial; Chris@34: layout->addWidget(panDial); Chris@34: panDial->setMeterColor(Qt::darkGreen); Chris@34: panDial->setMinimum(-50); Chris@34: panDial->setMaximum(50); Chris@34: panDial->setPageStep(1); Chris@34: panDial->setFixedWidth(24); Chris@34: panDial->setFixedHeight(24); Chris@34: panDial->setNotchesVisible(false); Chris@57: panDial->setToolTip(tr("Playback Pan / Balance")); Chris@34: panDial->setDefaultValue(0); Chris@168: panDial->setObjectName(tr("Playback Pan / Balance")); Chris@168: panDial->setShowToolTip(true); Chris@34: connect(panDial, SIGNAL(valueChanged(int)), Chris@34: this, SLOT(playPanDialChanged(int))); Chris@34: connect(params, SIGNAL(playPanChanged(float)), Chris@34: this, SLOT(playPanChanged(float))); Chris@34: connect(this, SIGNAL(changePlayPanDial(int)), Chris@34: panDial, SLOT(setValue(int))); Chris@189: connect(panDial, SIGNAL(mouseEntered()), Chris@189: this, SLOT(mouseEnteredWidget())); Chris@189: connect(panDial, SIGNAL(mouseLeft()), Chris@189: this, SLOT(mouseLeftWidget())); Chris@377: playPanChanged(params->getPlayPan()); Chris@34: layout->setAlignment(panDial, Qt::AlignVCenter); Chris@34: Chris@34: } else { Chris@34: Chris@34: layout->insertStretch(-1, 10); Chris@33: } Chris@33: } Chris@33: Chris@33: void Chris@197: PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name, Chris@197: bool rangeChanged) Chris@0: { Chris@0: PropertyContainer::PropertyType type = m_container->getPropertyType(name); Chris@0: int row = m_layout->rowCount(); Chris@0: Chris@216: int min = 0, max = 0, value = 0, deflt = 0; Chris@216: value = m_container->getPropertyRangeAndValue(name, &min, &max, &deflt); 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@87: QString propertyLabel = m_container->getPropertyLabel(name); Chris@335: QString iconName = m_container->getPropertyIconName(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@33: m_layout->addWidget(new QLabel(groupName, m_mainWidget), row, 0); Chris@33: QFrame *frame = new QFrame(m_mainWidget); 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@87: std::cerr << "PropertyBox: adding label \"" << propertyLabel.toStdString() << "\"" << std::endl; Chris@0: #endif Chris@87: m_layout->addWidget(new QLabel(propertyLabel, m_mainWidget), row, 0); Chris@0: } Chris@0: } Chris@0: Chris@0: switch (type) { Chris@0: Chris@0: case PropertyContainer::ToggleProperty: Chris@0: { Chris@335: QAbstractButton *button = 0; Chris@0: Chris@0: if (have) { Chris@335: button = dynamic_cast(m_propertyControllers[name]); Chris@335: assert(button); Chris@0: } else { Chris@0: #ifdef DEBUG_PROPERTY_BOX Chris@0: std::cerr << "PropertyBox: creating new checkbox" << std::endl; Chris@0: #endif Chris@335: if (iconName != "") { Chris@335: button = new NotifyingPushButton(); Chris@335: button->setCheckable(true); Chris@335: QIcon icon(IconLoader().load(iconName)); Chris@335: button->setIcon(icon); Chris@335: button->setObjectName(name); Chris@335: button->setFixedSize(QSize(18, 18)); Chris@335: } else { Chris@335: button = new NotifyingCheckBox(); Chris@335: button->setObjectName(name); Chris@335: } Chris@335: connect(button, SIGNAL(toggled(bool)), Chris@335: this, SLOT(propertyControllerChanged(bool))); Chris@335: connect(button, SIGNAL(mouseEntered()), Chris@189: this, SLOT(mouseEnteredWidget())); Chris@335: connect(button, SIGNAL(mouseLeft()), Chris@189: this, SLOT(mouseLeftWidget())); Chris@0: if (inGroup) { Chris@335: button->setToolTip(propertyLabel); Chris@335: m_groupLayouts[groupName]->addWidget(button); Chris@0: } else { Chris@335: m_layout->addWidget(button, row, 1, 1, 2); Chris@0: } Chris@335: m_propertyControllers[name] = button; Chris@0: } Chris@0: Chris@335: if (button->isChecked() != (value > 0)) { Chris@335: button->blockSignals(true); Chris@335: button->setChecked(value > 0); Chris@335: button->blockSignals(false); Chris@55: } 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@197: if (rangeChanged) { Chris@197: dial->blockSignals(true); Chris@197: dial->setMinimum(min); Chris@197: dial->setMaximum(max); Chris@197: dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name)); Chris@197: dial->blockSignals(false); Chris@197: } Chris@197: 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@34: dial->setNotchesVisible((max - min) <= 12); Chris@216: dial->setDefaultValue(deflt); Chris@167: dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name)); Chris@168: dial->setShowToolTip(true); Chris@0: connect(dial, SIGNAL(valueChanged(int)), Chris@0: this, SLOT(propertyControllerChanged(int))); Chris@189: connect(dial, SIGNAL(mouseEntered()), Chris@189: this, SLOT(mouseEnteredWidget())); Chris@189: connect(dial, SIGNAL(mouseLeft()), Chris@189: this, SLOT(mouseLeftWidget())); Chris@0: Chris@0: if (inGroup) { Chris@0: dial->setFixedWidth(24); Chris@0: dial->setFixedHeight(24); 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@33: QLabel *label = new QLabel(m_mainWidget); 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@55: if (dial->value() != value) { Chris@55: dial->blockSignals(true); Chris@55: dial->setValue(value); Chris@55: dial->blockSignals(false); Chris@55: } Chris@0: break; Chris@0: } Chris@0: Chris@0: case PropertyContainer::ValueProperty: Chris@100: case PropertyContainer::UnitsProperty: Chris@285: case PropertyContainer::ColourProperty: Chris@0: { Chris@189: NotifyingComboBox *cb; Chris@0: Chris@0: if (have) { Chris@189: 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@189: cb = new NotifyingComboBox(); Chris@0: cb->setObjectName(name); Chris@100: cb->setDuplicatesEnabled(false); Chris@197: } Chris@100: Chris@197: if (!have || rangeChanged) { Chris@285: Chris@197: cb->blockSignals(true); Chris@197: cb->clear(); Chris@285: cb->setEditable(false); Chris@285: Chris@100: if (type == PropertyContainer::ValueProperty) { Chris@285: Chris@100: for (int i = min; i <= max; ++i) { Chris@100: cb->addItem(m_container->getPropertyValueLabel(name, i)); Chris@100: } Chris@285: Chris@285: } else if (type == PropertyContainer::UnitsProperty) { Chris@285: Chris@100: QStringList units = UnitDatabase::getInstance()->getKnownUnits(); Chris@100: for (int i = 0; i < units.size(); ++i) { Chris@100: cb->addItem(units[i]); Chris@100: } Chris@285: Chris@100: cb->setEditable(true); Chris@285: Chris@285: } else { // ColourProperty Chris@290: Chris@290: //!!! should be a proper colour combobox class that Chris@290: // manages its own Add New Colour entry... Chris@285: Chris@285: ColourDatabase *db = ColourDatabase::getInstance(); Chris@285: for (size_t i = 0; i < db->getColourCount(); ++i) { Chris@285: QString name = db->getColourName(i); Chris@287: cb->addItem(db->getExamplePixmap(i, QSize(12, 12)), name); Chris@285: } Chris@285: cb->addItem(tr("Add New Colour...")); Chris@285: } Chris@285: Chris@197: cb->blockSignals(false); Chris@280: if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) { Chris@280: cb->setMaxVisibleItems(cb->count()); Chris@280: } Chris@197: } Chris@100: Chris@197: if (!have) { Chris@0: connect(cb, SIGNAL(activated(int)), Chris@0: this, SLOT(propertyControllerChanged(int))); Chris@189: connect(cb, SIGNAL(mouseEntered()), Chris@189: this, SLOT(mouseEnteredWidget())); Chris@189: connect(cb, SIGNAL(mouseLeft()), Chris@189: this, SLOT(mouseLeftWidget())); Chris@100: Chris@0: if (inGroup) { Chris@108: cb->setToolTip(propertyLabel); 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@100: cb->blockSignals(true); Chris@285: if (type == PropertyContainer::ValueProperty || Chris@285: type == PropertyContainer::ColourProperty) { Chris@100: if (cb->currentIndex() != value) { Chris@100: cb->setCurrentIndex(value); Chris@100: } Chris@100: } else { Chris@100: QString unit = UnitDatabase::getInstance()->getUnitById(value); Chris@100: if (cb->currentText() != unit) { Chris@100: for (int i = 0; i < cb->count(); ++i) { Chris@100: if (cb->itemText(i) == unit) { Chris@100: cb->setCurrentIndex(i); Chris@100: break; Chris@100: } Chris@100: } Chris@100: } Chris@100: } Chris@100: cb->blockSignals(false); 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@55: #ifdef DEBUG_PROPERTY_BOX Chris@55: std::cerr << "PropertyBox::propertyContainerPropertyChanged" << std::endl; Chris@55: #endif Chris@55: 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@249: PropertyBox::propertyContainerPropertyRangeChanged(PropertyContainer *) Chris@197: { Chris@197: blockSignals(true); Chris@197: Chris@197: PropertyContainer::PropertyList properties = m_container->getProperties(); Chris@197: for (size_t i = 0; i < properties.size(); ++i) { Chris@197: updatePropertyEditor(properties[i], true); Chris@197: } Chris@197: Chris@197: blockSignals(false); Chris@197: } Chris@197: Chris@197: void Chris@100: PropertyBox::unitDatabaseChanged() Chris@100: { Chris@454: std::cerr << "PropertyBox[" << this << "]: unitDatabaseChanged" << std::endl; Chris@100: blockSignals(true); Chris@100: Chris@456: // std::cerr << "my container is " << m_container << std::endl; Chris@456: // std::cerr << "my container's name is... " << std::endl; Chris@456: // std::cerr << m_container->objectName().toStdString() << std::endl; Chris@456: Chris@100: PropertyContainer::PropertyList properties = m_container->getProperties(); Chris@100: for (size_t i = 0; i < properties.size(); ++i) { Chris@285: if (m_container->getPropertyType(properties[i]) == Chris@285: PropertyContainer::UnitsProperty) { Chris@285: updatePropertyEditor(properties[i]); Chris@285: } Chris@285: } Chris@285: Chris@285: blockSignals(false); Chris@285: } Chris@285: Chris@285: void Chris@285: PropertyBox::colourDatabaseChanged() Chris@285: { Chris@285: blockSignals(true); Chris@285: Chris@285: PropertyContainer::PropertyList properties = m_container->getProperties(); Chris@285: for (size_t i = 0; i < properties.size(); ++i) { Chris@285: if (m_container->getPropertyType(properties[i]) == Chris@285: PropertyContainer::ColourProperty) { Chris@285: updatePropertyEditor(properties[i], true); Chris@285: } Chris@100: } Chris@100: Chris@100: blockSignals(false); Chris@100: } Chris@100: Chris@100: void Chris@335: PropertyBox::propertyControllerChanged(bool on) Chris@335: { Chris@335: propertyControllerChanged(on ? 1 : 0); Chris@335: } Chris@335: Chris@335: void Chris@0: PropertyBox::propertyControllerChanged(int value) Chris@0: { Chris@0: QObject *obj = sender(); Chris@0: QString name = obj->objectName(); Chris@0: Chris@34: #ifdef DEBUG_PROPERTY_BOX Chris@33: std::cerr << "PropertyBox::propertyControllerChanged(" << name.toStdString() Chris@33: << ", " << value << ")" << std::endl; Chris@34: #endif Chris@0: Chris@0: PropertyContainer::PropertyType type = m_container->getPropertyType(name); Chris@100: Chris@376: Command *c = 0; Chris@376: Chris@100: if (type == PropertyContainer::UnitsProperty) { Chris@285: Chris@189: NotifyingComboBox *cb = dynamic_cast(obj); Chris@100: if (cb) { Chris@100: QString unit = cb->currentText(); Chris@376: c = m_container->getSetPropertyCommand Chris@100: (name, UnitDatabase::getInstance()->getUnitId(unit)); Chris@100: } Chris@285: Chris@285: } else if (type == PropertyContainer::ColourProperty) { Chris@285: Chris@285: if (value == int(ColourDatabase::getInstance()->getColourCount())) { Chris@285: addNewColour(); Chris@285: if (value == int(ColourDatabase::getInstance()->getColourCount())) { Chris@285: propertyContainerPropertyChanged(m_container); Chris@285: return; Chris@285: } Chris@285: } Chris@376: c = m_container->getSetPropertyCommand(name, value); Chris@285: Chris@100: } else if (type != PropertyContainer::InvalidProperty) { Chris@285: Chris@376: c = m_container->getSetPropertyCommand(name, value); Chris@0: } Chris@376: Chris@376: if (c) CommandHistory::getInstance()->addCommand(c, true, true); Chris@218: Chris@218: updateContextHelp(obj); Chris@0: } Chris@285: Chris@285: void Chris@285: PropertyBox::addNewColour() Chris@285: { Chris@285: QColor newColour = QColorDialog::getColor(); Chris@285: if (!newColour.isValid()) return; Chris@285: Chris@285: ColourNameDialog dialog(tr("Name New Colour"), Chris@361: tr("Enter a name for the new colour:"), Chris@361: newColour, newColour.name(), this); Chris@285: dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour")); Chris@285: if (dialog.exec() == QDialog::Accepted) { Chris@285: //!!! command Chris@285: ColourDatabase *db = ColourDatabase::getInstance(); Chris@285: int index = db->addColour(newColour, dialog.getColourName()); Chris@285: db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked()); Chris@285: } Chris@285: } Chris@377: Chris@377: void Chris@377: PropertyBox::playAudibleChanged(bool audible) Chris@377: { Chris@377: m_playButton->setState(audible); Chris@377: } Chris@377: Chris@377: void Chris@377: PropertyBox::playAudibleButtonChanged(bool audible) Chris@377: { Chris@377: PlayParameters *params = m_container->getPlayParameters(); Chris@377: if (!params) return; Chris@377: Chris@377: if (params->isPlayAudible() != audible) { Chris@377: PlayParameterRepository::EditCommand *command = Chris@377: new PlayParameterRepository::EditCommand(params); Chris@377: command->setPlayAudible(audible); Chris@377: CommandHistory::getInstance()->addCommand(command, true, true); Chris@377: } Chris@377: } Chris@0: Chris@34: void Chris@34: PropertyBox::playGainChanged(float gain) Chris@34: { Chris@34: int dialValue = lrint(log10(gain) * 20.0); Chris@34: if (dialValue < -50) dialValue = -50; Chris@34: if (dialValue > 50) dialValue = 50; Chris@34: emit changePlayGainDial(dialValue); Chris@34: } Chris@34: Chris@34: void Chris@34: PropertyBox::playGainDialChanged(int dialValue) Chris@34: { Chris@218: QObject *obj = sender(); Chris@377: Chris@377: PlayParameters *params = m_container->getPlayParameters(); Chris@377: if (!params) return; Chris@377: Chris@34: float gain = pow(10, float(dialValue) / 20.0); Chris@377: Chris@377: if (params->getPlayGain() != gain) { Chris@377: PlayParameterRepository::EditCommand *command = Chris@377: new PlayParameterRepository::EditCommand(params); Chris@377: command->setPlayGain(gain); Chris@377: CommandHistory::getInstance()->addCommand(command, true, true); Chris@377: } Chris@377: Chris@218: updateContextHelp(obj); Chris@34: } Chris@34: Chris@34: void Chris@34: PropertyBox::playPanChanged(float pan) Chris@34: { Chris@34: int dialValue = lrint(pan * 50.0); Chris@34: if (dialValue < -50) dialValue = -50; Chris@34: if (dialValue > 50) dialValue = 50; Chris@34: emit changePlayPanDial(dialValue); Chris@34: } Chris@34: Chris@34: void Chris@34: PropertyBox::playPanDialChanged(int dialValue) Chris@34: { Chris@218: QObject *obj = sender(); Chris@377: Chris@377: PlayParameters *params = m_container->getPlayParameters(); Chris@377: if (!params) return; Chris@377: Chris@34: float pan = float(dialValue) / 50.0; Chris@34: if (pan < -1.0) pan = -1.0; Chris@34: if (pan > 1.0) pan = 1.0; Chris@377: Chris@377: if (params->getPlayPan() != pan) { Chris@377: PlayParameterRepository::EditCommand *command = Chris@377: new PlayParameterRepository::EditCommand(params); Chris@377: command->setPlayPan(pan); Chris@377: CommandHistory::getInstance()->addCommand(command, true, true); Chris@377: } Chris@377: Chris@218: updateContextHelp(obj); Chris@34: } Chris@0: Chris@63: void Chris@63: PropertyBox::editPlugin() Chris@63: { Chris@63: //!!! should probably just emit and let something else do this Chris@63: Chris@63: PlayParameters *params = m_container->getPlayParameters(); Chris@63: if (!params) return; Chris@63: Chris@63: QString pluginId = params->getPlayPluginId(); Chris@63: QString configurationXml = params->getPlayPluginConfiguration(); Chris@377: Chris@377: PlayParameterRepository::EditCommand *command = Chris@377: new PlayParameterRepository::EditCommand(params); Chris@63: Chris@63: RealTimePluginFactory *factory = Chris@63: RealTimePluginFactory::instanceFor(pluginId); Chris@63: if (!factory) return; Chris@63: Chris@63: RealTimePluginInstance *instance = Chris@63: factory->instantiatePlugin(pluginId, 0, 0, 48000, 1024, 1); Chris@63: if (!instance) return; Chris@63: Chris@71: PluginXml(instance).setParametersFromXml(configurationXml); Chris@63: Chris@163: PluginParameterDialog *dialog = new PluginParameterDialog(instance); Chris@64: connect(dialog, SIGNAL(pluginConfigurationChanged(QString)), Chris@64: this, SLOT(pluginConfigurationChanged(QString))); Chris@64: Chris@63: if (dialog->exec() == QDialog::Accepted) { Chris@377: QString newConfiguration = PluginXml(instance).toXmlString(); Chris@377: command->setPlayPluginConfiguration(newConfiguration); Chris@377: CommandHistory::getInstance()->addCommand(command, true); Chris@64: } else { Chris@377: delete command; Chris@64: // restore in case we mucked about with the configuration Chris@64: // as a consequence of signals from the dialog Chris@64: params->setPlayPluginConfiguration(configurationXml); Chris@63: } Chris@63: Chris@63: delete dialog; Chris@63: delete instance; Chris@63: } Chris@63: Chris@64: void Chris@64: PropertyBox::pluginConfigurationChanged(QString configurationXml) Chris@64: { Chris@64: PlayParameters *params = m_container->getPlayParameters(); Chris@64: if (!params) return; Chris@64: Chris@64: params->setPlayPluginConfiguration(configurationXml); Chris@64: } Chris@185: Chris@185: void Chris@185: PropertyBox::layerVisibilityChanged(bool visible) Chris@185: { Chris@185: if (m_showButton) m_showButton->setState(visible); Chris@185: } Chris@189: Chris@189: void Chris@189: PropertyBox::mouseEnteredWidget() Chris@189: { Chris@218: updateContextHelp(sender()); Chris@218: } Chris@218: Chris@218: void Chris@218: PropertyBox::updateContextHelp(QObject *o) Chris@218: { Chris@218: QWidget *w = dynamic_cast(o); Chris@189: if (!w) return; Chris@218: Chris@189: if (!m_container) return; Chris@190: QString cname = m_container->getPropertyContainerName(); Chris@189: if (cname == "") return; Chris@189: Chris@189: QString wname = w->objectName(); Chris@189: Chris@218: QString extraText; Chris@218: AudioDial *dial = dynamic_cast(w); Chris@218: if (dial) { Chris@218: float mv = dial->mappedValue(); Chris@218: QString unit = ""; Chris@218: if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit(); Chris@218: if (unit != "") { Chris@218: extraText = tr(" (current value: %1%2)").arg(mv).arg(unit); Chris@218: } else { Chris@218: extraText = tr(" (current value: %1)").arg(mv); Chris@218: } Chris@218: } Chris@218: Chris@189: if (w == m_showButton) { Chris@190: emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname)); Chris@189: } else if (w == m_playButton) { Chris@190: emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname)); Chris@189: } else if (wname == "") { Chris@189: return; Chris@335: } else if (dynamic_cast(w)) { Chris@190: emit contextHelpChanged(tr("Toggle %1 property of %2") Chris@189: .arg(wname).arg(cname)); Chris@189: } else { Chris@218: emit contextHelpChanged(tr("Adjust %1 property of %2%3") Chris@218: .arg(wname).arg(cname).arg(extraText)); Chris@189: } Chris@189: } Chris@189: Chris@189: void Chris@189: PropertyBox::mouseLeftWidget() Chris@189: { Chris@218: if (!(QApplication::mouseButtons() & Qt::LeftButton)) { Chris@218: emit contextHelpChanged(""); Chris@218: } Chris@189: } Chris@189: Chris@64: