annotate widgets/PropertyBox.cpp @ 10:8f5b812baaee

* Hook up SV file i/o. You can now save and load sessions. Some problems -- gain is not reloaded correctly for waveforms, reloaded panes are not properly reconnected to the panner, and no doubt plenty of others.
author Chris Cannam
date Tue, 17 Jan 2006 17:45:55 +0000
parents 37b110168acf
children 651e4e868bcc
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@5 5 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 #include "PropertyBox.h"
Chris@0 11
Chris@0 12 #include "base/PropertyContainer.h"
Chris@0 13
Chris@0 14 #include "AudioDial.h"
Chris@0 15
Chris@0 16 #include <QGridLayout>
Chris@0 17 #include <QHBoxLayout>
Chris@0 18 #include <QCheckBox>
Chris@0 19 #include <QComboBox>
Chris@0 20 #include <QLabel>
Chris@0 21
Chris@0 22 #include <cassert>
Chris@0 23 #include <iostream>
Chris@0 24
Chris@0 25 //#define DEBUG_PROPERTY_BOX 1
Chris@0 26
Chris@0 27 PropertyBox::PropertyBox(PropertyContainer *container) :
Chris@0 28 m_container(container)
Chris@0 29 {
Chris@0 30 #ifdef DEBUG_PROPERTY_BOX
Chris@0 31 std::cerr << "PropertyBox[" << this << "(\"" <<
Chris@0 32 container->getPropertyContainerName().toStdString() << "\")]::PropertyBox" << std::endl;
Chris@0 33 #endif
Chris@0 34
Chris@0 35 m_layout = new QGridLayout;
Chris@0 36 setLayout(m_layout);
Chris@0 37
Chris@0 38 PropertyContainer::PropertyList properties = container->getProperties();
Chris@0 39
Chris@0 40 blockSignals(true);
Chris@0 41
Chris@0 42 size_t i;
Chris@0 43
Chris@0 44 for (i = 0; i < properties.size(); ++i) {
Chris@0 45 updatePropertyEditor(properties[i]);
Chris@0 46 }
Chris@0 47
Chris@0 48 blockSignals(false);
Chris@0 49
Chris@0 50 m_layout->setRowStretch(m_layout->rowCount(), 10);
Chris@0 51
Chris@0 52 #ifdef DEBUG_PROPERTY_BOX
Chris@0 53 std::cerr << "PropertyBox[" << this << "]::PropertyBox returning" << std::endl;
Chris@0 54 #endif
Chris@0 55 }
Chris@0 56
Chris@0 57 PropertyBox::~PropertyBox()
Chris@0 58 {
Chris@0 59 #ifdef DEBUG_PROPERTY_BOX
Chris@0 60 std::cerr << "PropertyBox[" << this << "(\"" << m_container->getPropertyContainerName().toStdString() << "\")]::~PropertyBox" << std::endl;
Chris@0 61 #endif
Chris@0 62 }
Chris@0 63
Chris@0 64 void
Chris@0 65 PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name)
Chris@0 66 {
Chris@0 67 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@0 68 int row = m_layout->rowCount();
Chris@0 69
Chris@0 70 int min = 0, max = 0, value = 0;
Chris@0 71 value = m_container->getPropertyRangeAndValue(name, &min, &max);
Chris@0 72
Chris@0 73 bool have = (m_propertyControllers.find(name) !=
Chris@0 74 m_propertyControllers.end());
Chris@0 75
Chris@0 76 QString groupName = m_container->getPropertyGroupName(name);
Chris@0 77
Chris@0 78 #ifdef DEBUG_PROPERTY_BOX
Chris@0 79 std::cerr << "PropertyBox[" << this
Chris@0 80 << "(\"" << m_container->getPropertyContainerName().toStdString()
Chris@0 81 << "\")]";
Chris@0 82 std::cerr << "::updatePropertyEditor(\"" << name.toStdString() << "\"):";
Chris@0 83 std::cerr << " value " << value << ", have " << have << ", group \""
Chris@0 84 << groupName.toStdString() << "\"" << std::endl;
Chris@0 85 #endif
Chris@0 86
Chris@0 87 bool inGroup = (groupName != QString());
Chris@0 88
Chris@0 89 if (!have) {
Chris@0 90 if (inGroup) {
Chris@0 91 if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) {
Chris@0 92 #ifdef DEBUG_PROPERTY_BOX
Chris@0 93 std::cerr << "PropertyBox: adding label \"" << groupName.toStdString() << "\" and frame for group for \"" << name.toStdString() << "\"" << std::endl;
Chris@0 94 #endif
Chris@0 95 m_layout->addWidget(new QLabel(groupName, this), row, 0);
Chris@0 96 QFrame *frame = new QFrame(this);
Chris@0 97 m_layout->addWidget(frame, row, 1, 1, 2);
Chris@0 98 m_groupLayouts[groupName] = new QHBoxLayout;
Chris@0 99 m_groupLayouts[groupName]->setMargin(0);
Chris@0 100 frame->setLayout(m_groupLayouts[groupName]);
Chris@0 101 }
Chris@0 102 } else {
Chris@0 103 #ifdef DEBUG_PROPERTY_BOX
Chris@0 104 std::cerr << "PropertyBox: adding label \"" << name.toStdString() << "\"" << std::endl;
Chris@0 105 #endif
Chris@0 106 m_layout->addWidget(new QLabel(name, this), row, 0);
Chris@0 107 }
Chris@0 108 }
Chris@0 109
Chris@0 110 switch (type) {
Chris@0 111
Chris@0 112 case PropertyContainer::ToggleProperty:
Chris@0 113 {
Chris@0 114 QCheckBox *cb;
Chris@0 115
Chris@0 116 if (have) {
Chris@0 117 cb = dynamic_cast<QCheckBox *>(m_propertyControllers[name]);
Chris@0 118 assert(cb);
Chris@0 119 } else {
Chris@0 120 #ifdef DEBUG_PROPERTY_BOX
Chris@0 121 std::cerr << "PropertyBox: creating new checkbox" << std::endl;
Chris@0 122 #endif
Chris@0 123 cb = new QCheckBox();
Chris@0 124 cb->setObjectName(name);
Chris@0 125 connect(cb, SIGNAL(stateChanged(int)),
Chris@0 126 this, SLOT(propertyControllerChanged(int)));
Chris@0 127 if (inGroup) {
Chris@0 128 cb->setToolTip(name);
Chris@0 129 m_groupLayouts[groupName]->addWidget(cb);
Chris@0 130 } else {
Chris@0 131 m_layout->addWidget(cb, row, 1, 1, 2);
Chris@0 132 }
Chris@0 133 m_propertyControllers[name] = cb;
Chris@0 134 }
Chris@0 135
Chris@0 136 if (cb->isChecked() != (value > 0)) cb->setChecked(value > 0);
Chris@0 137 break;
Chris@0 138 }
Chris@0 139
Chris@0 140 case PropertyContainer::RangeProperty:
Chris@0 141 {
Chris@0 142 AudioDial *dial;
Chris@0 143
Chris@0 144 if (have) {
Chris@0 145 dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]);
Chris@0 146 assert(dial);
Chris@0 147 } else {
Chris@0 148 #ifdef DEBUG_PROPERTY_BOX
Chris@0 149 std::cerr << "PropertyBox: creating new dial" << std::endl;
Chris@0 150 #endif
Chris@0 151 dial = new AudioDial();
Chris@0 152 dial->setObjectName(name);
Chris@0 153 dial->setMinimum(min);
Chris@0 154 dial->setMaximum(max);
Chris@0 155 dial->setPageStep(1);
Chris@0 156 dial->setNotchesVisible(true);
Chris@0 157 connect(dial, SIGNAL(valueChanged(int)),
Chris@0 158 this, SLOT(propertyControllerChanged(int)));
Chris@0 159
Chris@0 160 if (inGroup) {
Chris@0 161 dial->setFixedWidth(24);
Chris@0 162 dial->setFixedHeight(24);
Chris@0 163 dial->setToolTip(name);
Chris@0 164 m_groupLayouts[groupName]->addWidget(dial);
Chris@0 165 } else {
Chris@0 166 dial->setFixedWidth(32);
Chris@0 167 dial->setFixedHeight(32);
Chris@0 168 m_layout->addWidget(dial, row, 1);
Chris@0 169 QLabel *label = new QLabel(this);
Chris@0 170 connect(dial, SIGNAL(valueChanged(int)),
Chris@0 171 label, SLOT(setNum(int)));
Chris@0 172 label->setNum(value);
Chris@0 173 m_layout->addWidget(label, row, 2);
Chris@0 174 }
Chris@0 175
Chris@0 176 m_propertyControllers[name] = dial;
Chris@0 177 }
Chris@0 178
Chris@0 179 if (dial->value() != value) dial->setValue(value);
Chris@0 180 break;
Chris@0 181 }
Chris@0 182
Chris@0 183 case PropertyContainer::ValueProperty:
Chris@0 184 {
Chris@0 185 QComboBox *cb;
Chris@0 186
Chris@0 187 if (have) {
Chris@0 188 cb = dynamic_cast<QComboBox *>(m_propertyControllers[name]);
Chris@0 189 assert(cb);
Chris@0 190 } else {
Chris@0 191 #ifdef DEBUG_PROPERTY_BOX
Chris@0 192 std::cerr << "PropertyBox: creating new combobox" << std::endl;
Chris@0 193 #endif
Chris@0 194
Chris@0 195 cb = new QComboBox();
Chris@0 196 cb->setObjectName(name);
Chris@0 197 for (int i = min; i <= max; ++i) {
Chris@0 198 cb->addItem(m_container->getPropertyValueLabel(name, i));
Chris@0 199 }
Chris@0 200 connect(cb, SIGNAL(activated(int)),
Chris@0 201 this, SLOT(propertyControllerChanged(int)));
Chris@0 202 if (inGroup) {
Chris@0 203 cb->setToolTip(name);
Chris@0 204 m_groupLayouts[groupName]->addWidget(cb);
Chris@0 205 } else {
Chris@0 206 m_layout->addWidget(cb, row, 1, 1, 2);
Chris@0 207 }
Chris@0 208 m_propertyControllers[name] = cb;
Chris@0 209 }
Chris@0 210
Chris@0 211 if (cb->currentIndex() != value) cb->setCurrentIndex(value);
Chris@0 212
Chris@0 213 #ifdef Q_WS_MAC
Chris@0 214 // Crashes on startup without this, for some reason
Chris@0 215 cb->setMinimumSize(QSize(10, 10));
Chris@0 216 #endif
Chris@0 217
Chris@0 218 break;
Chris@0 219 }
Chris@0 220
Chris@0 221 default:
Chris@0 222 break;
Chris@0 223 }
Chris@0 224 }
Chris@0 225
Chris@0 226 void
Chris@0 227 PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 228 {
Chris@0 229 if (pc != m_container) return;
Chris@0 230
Chris@0 231 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@0 232 size_t i;
Chris@0 233
Chris@0 234 blockSignals(true);
Chris@0 235
Chris@0 236 for (i = 0; i < properties.size(); ++i) {
Chris@0 237 updatePropertyEditor(properties[i]);
Chris@0 238 }
Chris@0 239
Chris@0 240 blockSignals(false);
Chris@0 241 }
Chris@0 242
Chris@0 243 void
Chris@0 244 PropertyBox::propertyControllerChanged(int value)
Chris@0 245 {
Chris@0 246 QObject *obj = sender();
Chris@0 247 QString name = obj->objectName();
Chris@0 248
Chris@0 249 // std::cerr << "PropertyBox::propertyControllerChanged(" << name.toStdString()
Chris@0 250 // << ", " << value << ")" << std::endl;
Chris@0 251
Chris@0 252 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@0 253
Chris@0 254 if (type != PropertyContainer::InvalidProperty) {
Chris@0 255 m_container->setProperty(name, value);
Chris@0 256 }
Chris@0 257
Chris@0 258 if (type == PropertyContainer::RangeProperty) {
Chris@0 259 AudioDial *dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]);
Chris@0 260 if (dial) {
Chris@0 261 dial->setToolTip(QString("%1: %2").arg(name).arg(value));
Chris@0 262 //!!! unfortunately this doesn't update an already-visible tooltip
Chris@0 263 }
Chris@0 264 }
Chris@0 265 }
Chris@0 266
Chris@0 267
Chris@0 268
Chris@0 269 #ifdef INCLUDE_MOCFILES
Chris@0 270 #include "PropertyBox.moc.cpp"
Chris@0 271 #endif
Chris@0 272