comparison widgets/PropertyBox.cpp @ 1216:dc2af6616c83

Merge from branch 3.0-integration
author Chris Cannam
date Fri, 13 Jan 2017 10:29:50 +0000
parents d421df27e184
children 312f99a9f2aa
comparison
equal deleted inserted replaced
1048:e8102ff5573b 1216:dc2af6616c83
18 18
19 #include "base/PropertyContainer.h" 19 #include "base/PropertyContainer.h"
20 #include "base/PlayParameters.h" 20 #include "base/PlayParameters.h"
21 #include "base/PlayParameterRepository.h" 21 #include "base/PlayParameterRepository.h"
22 #include "layer/Layer.h" 22 #include "layer/Layer.h"
23 #include "layer/ColourDatabase.h"
24 #include "base/UnitDatabase.h" 23 #include "base/UnitDatabase.h"
25 #include "base/RangeMapper.h" 24 #include "base/RangeMapper.h"
26 25
27 #include "AudioDial.h" 26 #include "AudioDial.h"
28 #include "LEDButton.h" 27 #include "LEDButton.h"
29 #include "IconLoader.h" 28 #include "IconLoader.h"
29 #include "LevelPanWidget.h"
30 #include "LevelPanToolButton.h"
31 #include "WidgetScale.h"
30 32
31 #include "NotifyingCheckBox.h" 33 #include "NotifyingCheckBox.h"
32 #include "NotifyingComboBox.h" 34 #include "NotifyingComboBox.h"
33 #include "NotifyingPushButton.h" 35 #include "NotifyingPushButton.h"
34 #include "ColourNameDialog.h" 36 #include "NotifyingToolButton.h"
37 #include "ColourComboBox.h"
38 #include "ColourMapComboBox.h"
35 39
36 #include <QGridLayout> 40 #include <QGridLayout>
37 #include <QHBoxLayout> 41 #include <QHBoxLayout>
38 #include <QVBoxLayout> 42 #include <QVBoxLayout>
39 #include <QPushButton> 43 #include <QPushButton>
44 #include <QToolButton>
40 #include <QLabel> 45 #include <QLabel>
41 #include <QFrame> 46 #include <QFrame>
42 #include <QApplication> 47 #include <QApplication>
43 #include <QColorDialog> 48 #include <QColorDialog>
44 #include <QInputDialog> 49 #include <QInputDialog>
61 #endif 66 #endif
62 67
63 m_mainBox = new QVBoxLayout; 68 m_mainBox = new QVBoxLayout;
64 setLayout(m_mainBox); 69 setLayout(m_mainBox);
65 70
71 #ifdef Q_OS_MAC
72 QMargins mm = m_mainBox->contentsMargins();
73 QMargins mmhalf(mm.left()/2, mm.top()/3, mm.right()/2, mm.bottom()/3);
74 m_mainBox->setContentsMargins(mmhalf);
75 #endif
76
66 // m_nameWidget = new QLabel; 77 // m_nameWidget = new QLabel;
67 // m_mainBox->addWidget(m_nameWidget); 78 // m_mainBox->addWidget(m_nameWidget);
68 // m_nameWidget->setText(container->objectName()); 79 // m_nameWidget->setText(container->objectName());
69 80
70 m_mainWidget = new QWidget; 81 m_mainWidget = new QWidget;
94 105
95 m_layout->setRowStretch(m_layout->rowCount(), 10); 106 m_layout->setRowStretch(m_layout->rowCount(), 10);
96 107
97 connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()), 108 connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()),
98 this, SLOT(unitDatabaseChanged())); 109 this, SLOT(unitDatabaseChanged()));
99
100 connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()),
101 this, SLOT(colourDatabaseChanged()));
102 110
103 #ifdef DEBUG_PROPERTY_BOX 111 #ifdef DEBUG_PROPERTY_BOX
104 cerr << "PropertyBox[" << this << "]::PropertyBox returning" << endl; 112 cerr << "PropertyBox[" << this << "]::PropertyBox returning" << endl;
105 #endif 113 #endif
106 } 114 }
139 147
140 m_viewPlayFrame = new QFrame; 148 m_viewPlayFrame = new QFrame;
141 m_viewPlayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); 149 m_viewPlayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
142 m_mainBox->addWidget(m_viewPlayFrame); 150 m_mainBox->addWidget(m_viewPlayFrame);
143 151
144 QHBoxLayout *layout = new QHBoxLayout; 152 QGridLayout *layout = new QGridLayout;
145 m_viewPlayFrame->setLayout(layout); 153 m_viewPlayFrame->setLayout(layout);
146 154
147 layout->setMargin(layout->margin() / 2); 155 layout->setMargin(layout->margin() / 2);
148 156
149 #ifdef DEBUG_PROPERTY_BOX 157 #ifdef DEBUG_PROPERTY_BOX
150 SVDEBUG << "PropertyBox::populateViewPlayFrame: container " << m_container << " (name " << m_container->getPropertyContainerName() << ") params " << params << endl; 158 SVDEBUG << "PropertyBox::populateViewPlayFrame: container " << m_container << " (name " << m_container->getPropertyContainerName() << ") params " << params << endl;
151 #endif 159 #endif
152 160
153 if (layer) { 161 QSize buttonSize = WidgetScale::scaleQSize(QSize(26, 26));
154 QLabel *showLabel = new QLabel(tr("Show")); 162 int col = 0;
155 layout->addWidget(showLabel); 163
156 layout->setAlignment(showLabel, Qt::AlignVCenter);
157
158 m_showButton = new LEDButton(Qt::blue);
159 layout->addWidget(m_showButton);
160 connect(m_showButton, SIGNAL(stateChanged(bool)),
161 this, SIGNAL(showLayer(bool)));
162 connect(m_showButton, SIGNAL(mouseEntered()),
163 this, SLOT(mouseEnteredWidget()));
164 connect(m_showButton, SIGNAL(mouseLeft()),
165 this, SLOT(mouseLeftWidget()));
166 layout->setAlignment(m_showButton, Qt::AlignVCenter);
167 }
168
169 if (params) { 164 if (params) {
170 165
171 QLabel *playLabel = new QLabel(tr("Play")); 166 m_playButton = new NotifyingToolButton;
172 layout->addWidget(playLabel); 167 m_playButton->setCheckable(true);
173 layout->setAlignment(playLabel, Qt::AlignVCenter); 168 m_playButton->setIcon(IconLoader().load("speaker"));
174 169 m_playButton->setToolTip(tr("Click to toggle playback"));
175 m_playButton = new LEDButton(Qt::darkGreen); 170 m_playButton->setChecked(!params->isPlayMuted());
176 m_playButton->setState(!params->isPlayMuted()); 171 m_playButton->setFixedSize(buttonSize);
177 layout->addWidget(m_playButton); 172 connect(m_playButton, SIGNAL(toggled(bool)),
178 connect(m_playButton, SIGNAL(stateChanged(bool)),
179 this, SLOT(playAudibleButtonChanged(bool))); 173 this, SLOT(playAudibleButtonChanged(bool)));
180 connect(m_playButton, SIGNAL(mouseEntered()), 174 connect(m_playButton, SIGNAL(mouseEntered()),
181 this, SLOT(mouseEnteredWidget())); 175 this, SLOT(mouseEnteredWidget()));
182 connect(m_playButton, SIGNAL(mouseLeft()), 176 connect(m_playButton, SIGNAL(mouseLeft()),
183 this, SLOT(mouseLeftWidget())); 177 this, SLOT(mouseLeftWidget()));
184 connect(params, SIGNAL(playAudibleChanged(bool)), 178 connect(params, SIGNAL(playAudibleChanged(bool)),
185 this, SLOT(playAudibleChanged(bool))); 179 this, SLOT(playAudibleChanged(bool)));
186 layout->setAlignment(m_playButton, Qt::AlignVCenter); 180
187 181 LevelPanToolButton *levelPan = new LevelPanToolButton;
188 layout->insertStretch(-1, 10); 182 levelPan->setFixedSize(buttonSize);
183 levelPan->setImageSize((buttonSize.height() * 3) / 4);
184 layout->addWidget(levelPan, 0, col++, Qt::AlignCenter);
185 connect(levelPan, SIGNAL(levelChanged(float)),
186 this, SLOT(playGainControlChanged(float)));
187 connect(levelPan, SIGNAL(panChanged(float)),
188 this, SLOT(playPanControlChanged(float)));
189 connect(params, SIGNAL(playGainChanged(float)),
190 levelPan, SLOT(setLevel(float)));
191 connect(params, SIGNAL(playPanChanged(float)),
192 levelPan, SLOT(setPan(float)));
193 connect(levelPan, SIGNAL(mouseEntered()),
194 this, SLOT(mouseEnteredWidget()));
195 connect(levelPan, SIGNAL(mouseLeft()),
196 this, SLOT(mouseLeftWidget()));
197
198 layout->addWidget(m_playButton, 0, col++, Qt::AlignCenter);
189 199
190 if (params->getPlayClipId() != "") { 200 if (params->getPlayClipId() != "") {
191 QPushButton *playParamButton = 201 QToolButton *playParamButton = new QToolButton;
192 new QPushButton(QIcon(":icons/faders.png"), ""); 202 playParamButton->setObjectName("playParamButton");
193 playParamButton->setFixedWidth(24); 203 playParamButton->setIcon(IconLoader().load("faders"));
194 playParamButton->setFixedHeight(24); 204 playParamButton->setFixedSize(buttonSize);
195 layout->addWidget(playParamButton); 205 layout->addWidget(playParamButton, 0, col++, Qt::AlignCenter);
196 connect(playParamButton, SIGNAL(clicked()), 206 connect(playParamButton, SIGNAL(clicked()),
197 this, SLOT(editPlayParameters())); 207 this, SLOT(editPlayParameters()));
198 } 208 connect(playParamButton, SIGNAL(mouseEntered()),
199 209 this, SLOT(mouseEnteredWidget()));
200 AudioDial *gainDial = new AudioDial; 210 connect(playParamButton, SIGNAL(mouseLeft()),
201 layout->addWidget(gainDial); 211 this, SLOT(mouseLeftWidget()));
202 gainDial->setMeterColor(Qt::darkRed); 212 }
203 gainDial->setMinimum(-50); 213 }
204 gainDial->setMaximum(50); 214
205 gainDial->setPageStep(1); 215 layout->setColumnStretch(col++, 10);
206 gainDial->setFixedWidth(24); 216
207 gainDial->setFixedHeight(24); 217 if (layer) {
208 gainDial->setNotchesVisible(false); 218
209 gainDial->setDefaultValue(0); 219 QLabel *showLabel = new QLabel(tr("Show"));
210 gainDial->setObjectName(tr("Playback Gain")); 220 layout->addWidget(showLabel, 0, col++, Qt::AlignVCenter | Qt::AlignRight);
211 gainDial->setRangeMapper(new LinearRangeMapper 221
212 (-50, 50, -25, 25, tr("dB"))); 222 m_showButton = new LEDButton(palette().highlight().color());
213 gainDial->setShowToolTip(true); 223 layout->addWidget(m_showButton, 0, col++, Qt::AlignVCenter | Qt::AlignLeft);
214 connect(gainDial, SIGNAL(valueChanged(int)), 224 connect(m_showButton, SIGNAL(stateChanged(bool)),
215 this, SLOT(playGainDialChanged(int))); 225 this, SIGNAL(showLayer(bool)));
216 connect(params, SIGNAL(playGainChanged(float)), 226 connect(m_showButton, SIGNAL(mouseEntered()),
217 this, SLOT(playGainChanged(float)));
218 connect(this, SIGNAL(changePlayGainDial(int)),
219 gainDial, SLOT(setValue(int)));
220 connect(gainDial, SIGNAL(mouseEntered()),
221 this, SLOT(mouseEnteredWidget())); 227 this, SLOT(mouseEnteredWidget()));
222 connect(gainDial, SIGNAL(mouseLeft()), 228 connect(m_showButton, SIGNAL(mouseLeft()),
223 this, SLOT(mouseLeftWidget())); 229 this, SLOT(mouseLeftWidget()));
224 playGainChanged(params->getPlayGain());
225 layout->setAlignment(gainDial, Qt::AlignVCenter);
226
227 AudioDial *panDial = new AudioDial;
228 layout->addWidget(panDial);
229 panDial->setMeterColor(Qt::darkGreen);
230 panDial->setMinimum(-50);
231 panDial->setMaximum(50);
232 panDial->setPageStep(1);
233 panDial->setFixedWidth(24);
234 panDial->setFixedHeight(24);
235 panDial->setNotchesVisible(false);
236 panDial->setToolTip(tr("Playback Pan / Balance"));
237 panDial->setDefaultValue(0);
238 panDial->setObjectName(tr("Playback Pan / Balance"));
239 panDial->setShowToolTip(true);
240 connect(panDial, SIGNAL(valueChanged(int)),
241 this, SLOT(playPanDialChanged(int)));
242 connect(params, SIGNAL(playPanChanged(float)),
243 this, SLOT(playPanChanged(float)));
244 connect(this, SIGNAL(changePlayPanDial(int)),
245 panDial, SLOT(setValue(int)));
246 connect(panDial, SIGNAL(mouseEntered()),
247 this, SLOT(mouseEnteredWidget()));
248 connect(panDial, SIGNAL(mouseLeft()),
249 this, SLOT(mouseLeftWidget()));
250 playPanChanged(params->getPlayPan());
251 layout->setAlignment(panDial, Qt::AlignVCenter);
252
253 } else {
254
255 layout->insertStretch(-1, 10);
256 } 230 }
257 } 231 }
258 232
259 void 233 void
260 PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name, 234 PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name,
280 cerr << "::updatePropertyEditor(\"" << name << "\"):"; 254 cerr << "::updatePropertyEditor(\"" << name << "\"):";
281 cerr << " value " << value << ", have " << have << ", group \"" 255 cerr << " value " << value << ", have " << have << ", group \""
282 << groupName << "\"" << endl; 256 << groupName << "\"" << endl;
283 #endif 257 #endif
284 258
285 bool inGroup = (groupName != QString()); 259 QString groupLabel = groupName;
286 260 if (groupName == QString()) {
261 groupName = "ungrouped: " + name; // not tr(), this is internal id
262 groupLabel = propertyLabel;
263 }
264
287 if (!have) { 265 if (!have) {
288 if (inGroup) { 266 if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) {
289 if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) { 267 QWidget *labelWidget = new QLabel(groupLabel, m_mainWidget);
290 #ifdef DEBUG_PROPERTY_BOX 268 m_layout->addWidget(labelWidget, row, 0);
291 cerr << "PropertyBox: adding label \"" << groupName << "\" and frame for group for \"" << name << "\"" << endl; 269 QWidget *frame = new QWidget(m_mainWidget);
292 #endif 270 frame->setMinimumSize(WidgetScale::scaleQSize(QSize(1, 24)));
293 m_layout->addWidget(new QLabel(groupName, m_mainWidget), row, 0); 271 m_groupLayouts[groupName] = new QGridLayout;
294 QFrame *frame = new QFrame(m_mainWidget); 272 #ifdef Q_OS_MAC
295 m_layout->addWidget(frame, row, 1, 1, 2); 273 // Seems to be plenty of whitespace already
296 m_groupLayouts[groupName] = new QGridLayout; 274 m_groupLayouts[groupName]->setContentsMargins(0, 0, 0, 0);
297 m_groupLayouts[groupName]->setMargin(0); 275 #else
298 frame->setLayout(m_groupLayouts[groupName]); 276 // Need a bit of padding on the left
299 } 277 m_groupLayouts[groupName]->setContentsMargins
300 } else { 278 (WidgetScale::scalePixelSize(10), 0, 0, 0);
301 #ifdef DEBUG_PROPERTY_BOX 279 #endif
302 cerr << "PropertyBox: adding label \"" << propertyLabel << "\"" << endl; 280 frame->setLayout(m_groupLayouts[groupName]);
303 #endif 281 m_layout->addWidget(frame, row, 1, 1, 2);
304 m_layout->addWidget(new QLabel(propertyLabel, m_mainWidget), row, 0); 282 m_layout->setColumnStretch(1, 10);
305 } 283 }
306 } 284 }
307 285
286 QGridLayout *groupLayout = m_groupLayouts[groupName];
287
288 #ifdef DEBUG_PROPERTY_BOX
289 cerr << "groupName becomes \"" << groupName << "\", groupLabel = \""
290 << groupLabel << "\", groupLayout = " << groupLayout << endl;
291 #endif
292
293 assert(groupLayout);
294
295 QWidget *existing = m_propertyControllers[name];
296
308 switch (type) { 297 switch (type) {
309 298
310 case PropertyContainer::ToggleProperty: 299 case PropertyContainer::ToggleProperty:
311 { 300 {
312 QAbstractButton *button = 0; 301 QAbstractButton *button;
313 302
314 if (have) { 303 if (!(button = qobject_cast<QAbstractButton *>(existing))) {
315 button = dynamic_cast<QAbstractButton *>(m_propertyControllers[name]);
316 assert(button);
317 } else {
318 #ifdef DEBUG_PROPERTY_BOX 304 #ifdef DEBUG_PROPERTY_BOX
319 cerr << "PropertyBox: creating new checkbox" << endl; 305 cerr << "PropertyBox: creating new checkbox" << endl;
320 #endif 306 #endif
321 if (iconName != "") { 307 if (iconName != "") {
322 button = new NotifyingPushButton(); 308 button = new NotifyingPushButton();
323 button->setCheckable(true); 309 button->setCheckable(true);
324 QIcon icon(IconLoader().load(iconName)); 310 QIcon icon(IconLoader().load(iconName));
325 button->setIcon(icon); 311 button->setIcon(icon);
326 button->setObjectName(name); 312 button->setObjectName(name);
327 button->setFixedSize(QSize(18, 18)); 313 button->setFixedSize(WidgetScale::scaleQSize(QSize(18, 18)));
328 } else { 314 } else {
329 button = new NotifyingCheckBox(); 315 button = new NotifyingCheckBox();
330 button->setObjectName(name); 316 button->setObjectName(name);
331 } 317 }
332 connect(button, SIGNAL(toggled(bool)), 318 connect(button, SIGNAL(toggled(bool)),
333 this, SLOT(propertyControllerChanged(bool))); 319 this, SLOT(propertyControllerChanged(bool)));
334 connect(button, SIGNAL(mouseEntered()), 320 connect(button, SIGNAL(mouseEntered()),
335 this, SLOT(mouseEnteredWidget())); 321 this, SLOT(mouseEnteredWidget()));
336 connect(button, SIGNAL(mouseLeft()), 322 connect(button, SIGNAL(mouseLeft()),
337 this, SLOT(mouseLeftWidget())); 323 this, SLOT(mouseLeftWidget()));
338 if (inGroup) { 324 button->setToolTip(propertyLabel);
339 button->setToolTip(propertyLabel); 325
340 m_groupLayouts[groupName]->addWidget 326 if (existing) {
341 (button, 0, m_groupLayouts[groupName]->columnCount()); 327 groupLayout->replaceWidget(existing, button);
342 } else { 328 delete existing;
343 m_layout->addWidget(button, row, 1, 1, 2); 329 } else {
344 } 330 groupLayout->addWidget(button, 0, groupLayout->columnCount());
331 }
332
345 m_propertyControllers[name] = button; 333 m_propertyControllers[name] = button;
346 } 334 }
347 335
348 if (button->isChecked() != (value > 0)) { 336 if (button->isChecked() != (value > 0)) {
349 button->blockSignals(true); 337 button->blockSignals(true);
355 343
356 case PropertyContainer::RangeProperty: 344 case PropertyContainer::RangeProperty:
357 { 345 {
358 AudioDial *dial; 346 AudioDial *dial;
359 347
360 if (have) { 348 if ((dial = qobject_cast<AudioDial *>(existing))) {
361 dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]);
362 assert(dial);
363 if (rangeChanged) { 349 if (rangeChanged) {
364 dial->blockSignals(true); 350 dial->blockSignals(true);
365 dial->setMinimum(min); 351 dial->setMinimum(min);
366 dial->setMaximum(max); 352 dial->setMaximum(max);
367 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name)); 353 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
368 dial->blockSignals(false); 354 dial->blockSignals(false);
369 } 355 }
370 356 } else {
371 } else {
372 #ifdef DEBUG_PROPERTY_BOX 357 #ifdef DEBUG_PROPERTY_BOX
373 cerr << "PropertyBox: creating new dial" << endl; 358 cerr << "PropertyBox: creating new dial" << endl;
374 #endif 359 #endif
375 dial = new AudioDial(); 360 dial = new AudioDial();
376 dial->setObjectName(name); 361 dial->setObjectName(name);
377 dial->setMinimum(min); 362 dial->setMinimum(min);
378 dial->setMaximum(max); 363 dial->setMaximum(max);
379 dial->setPageStep(1); 364 dial->setPageStep(1);
380 dial->setNotchesVisible((max - min) <= 12); 365 dial->setNotchesVisible((max - min) <= 12);
366 // important to set the range mapper before the default,
367 // because the range mapper is used to map the default
368 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
381 dial->setDefaultValue(deflt); 369 dial->setDefaultValue(deflt);
382 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
383 dial->setShowToolTip(true); 370 dial->setShowToolTip(true);
384 connect(dial, SIGNAL(valueChanged(int)), 371 connect(dial, SIGNAL(valueChanged(int)),
385 this, SLOT(propertyControllerChanged(int))); 372 this, SLOT(propertyControllerChanged(int)));
386 connect(dial, SIGNAL(mouseEntered()), 373 connect(dial, SIGNAL(mouseEntered()),
387 this, SLOT(mouseEnteredWidget())); 374 this, SLOT(mouseEnteredWidget()));
388 connect(dial, SIGNAL(mouseLeft()), 375 connect(dial, SIGNAL(mouseLeft()),
389 this, SLOT(mouseLeftWidget())); 376 this, SLOT(mouseLeftWidget()));
390 377
391 if (inGroup) { 378 dial->setFixedWidth(WidgetScale::scalePixelSize(24));
392 dial->setFixedWidth(24); 379 dial->setFixedHeight(WidgetScale::scalePixelSize(24));
393 dial->setFixedHeight(24); 380
394 m_groupLayouts[groupName]->addWidget 381 if (existing) {
395 (dial, 0, m_groupLayouts[groupName]->columnCount()); 382 groupLayout->replaceWidget(existing, dial);
396 } else { 383 delete existing;
397 dial->setFixedWidth(32); 384 } else {
398 dial->setFixedHeight(32); 385 groupLayout->addWidget(dial, 0, groupLayout->columnCount());
399 m_layout->addWidget(dial, row, 1); 386 }
400 QLabel *label = new QLabel(m_mainWidget);
401 connect(dial, SIGNAL(valueChanged(int)),
402 label, SLOT(setNum(int)));
403 label->setNum(value);
404 m_layout->addWidget(label, row, 2);
405 }
406 387
407 m_propertyControllers[name] = dial; 388 m_propertyControllers[name] = dial;
408 } 389 }
409 390
410 if (dial->value() != value) { 391 if (dial->value() != value) {
413 dial->blockSignals(false); 394 dial->blockSignals(false);
414 } 395 }
415 break; 396 break;
416 } 397 }
417 398
399 case PropertyContainer::ColourProperty:
400 {
401 ColourComboBox *cb;
402
403 if (!(cb = qobject_cast<ColourComboBox *>(existing))) {
404
405 #ifdef DEBUG_PROPERTY_BOX
406 cerr << "PropertyBox: creating new colour combobox" << endl;
407 #endif
408 cb = new ColourComboBox(true);
409 cb->setObjectName(name);
410
411 connect(cb, SIGNAL(colourChanged(int)),
412 this, SLOT(propertyControllerChanged(int)));
413 connect(cb, SIGNAL(mouseEntered()),
414 this, SLOT(mouseEnteredWidget()));
415 connect(cb, SIGNAL(mouseLeft()),
416 this, SLOT(mouseLeftWidget()));
417
418 cb->setToolTip(propertyLabel);
419
420 if (existing) {
421 groupLayout->replaceWidget(existing, cb);
422 delete existing;
423 } else {
424 groupLayout->addWidget(cb, 0, groupLayout->columnCount());
425 }
426
427 m_propertyControllers[name] = cb;
428 }
429
430 if (cb->currentIndex() != value) {
431 cb->blockSignals(true);
432 cb->setCurrentIndex(value);
433 cb->blockSignals(false);
434 }
435
436 break;
437 }
438
439 case PropertyContainer::ColourMapProperty:
440 {
441 ColourMapComboBox *cb;
442
443 if (!(cb = qobject_cast<ColourMapComboBox *>(existing))) {
444 #ifdef DEBUG_PROPERTY_BOX
445 cerr << "PropertyBox: creating new colourmap combobox" << endl;
446 #endif
447 cb = new ColourMapComboBox(false);
448 cb->setObjectName(name);
449
450 connect(cb, SIGNAL(colourMapChanged(int)),
451 this, SLOT(propertyControllerChanged(int)));
452 connect(cb, SIGNAL(mouseEntered()),
453 this, SLOT(mouseEnteredWidget()));
454 connect(cb, SIGNAL(mouseLeft()),
455 this, SLOT(mouseLeftWidget()));
456
457 cb->setToolTip(propertyLabel);
458
459 if (existing) {
460 groupLayout->replaceWidget(existing, cb);
461 delete existing;
462 } else {
463 groupLayout->addWidget(cb, 0, groupLayout->columnCount());
464 }
465
466 m_propertyControllers[name] = cb;
467 }
468
469 if (cb->currentIndex() != value) {
470 cb->blockSignals(true);
471 cb->setCurrentIndex(value);
472 cb->blockSignals(false);
473 }
474
475 break;
476 }
477
418 case PropertyContainer::ValueProperty: 478 case PropertyContainer::ValueProperty:
419 case PropertyContainer::UnitsProperty: 479 case PropertyContainer::UnitsProperty:
420 case PropertyContainer::ColourProperty:
421 { 480 {
422 NotifyingComboBox *cb; 481 NotifyingComboBox *cb;
423 482
424 if (have) { 483 if (!(cb = qobject_cast<NotifyingComboBox *>(existing))) {
425 cb = dynamic_cast<NotifyingComboBox *>(m_propertyControllers[name]);
426 assert(cb);
427 } else {
428 #ifdef DEBUG_PROPERTY_BOX 484 #ifdef DEBUG_PROPERTY_BOX
429 cerr << "PropertyBox: creating new combobox" << endl; 485 cerr << "PropertyBox: creating new combobox" << endl;
430 #endif 486 #endif
431
432 cb = new NotifyingComboBox(); 487 cb = new NotifyingComboBox();
433 cb->setObjectName(name); 488 cb->setObjectName(name);
434 cb->setDuplicatesEnabled(false); 489 cb->setDuplicatesEnabled(false);
435 } 490 }
436 491
441 cb->setEditable(false); 496 cb->setEditable(false);
442 497
443 if (type == PropertyContainer::ValueProperty) { 498 if (type == PropertyContainer::ValueProperty) {
444 499
445 for (int i = min; i <= max; ++i) { 500 for (int i = min; i <= max; ++i) {
446 cb->addItem(m_container->getPropertyValueLabel(name, i)); 501
502 QString label = m_container->getPropertyValueLabel(name, i);
503 QString iname = m_container->getPropertyValueIconName(name, i);
504
505 if (iname != "") {
506 QIcon icon(IconLoader().load(iname));
507 cb->addItem(icon, label);
508 } else {
509 cb->addItem(label);
510 }
447 } 511 }
448 512
449 } else if (type == PropertyContainer::UnitsProperty) { 513 } else { // PropertyContainer::UnitsProperty
450 514
451 QStringList units = UnitDatabase::getInstance()->getKnownUnits(); 515 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
452 for (int i = 0; i < units.size(); ++i) { 516 for (int i = 0; i < units.size(); ++i) {
453 cb->addItem(units[i]); 517 cb->addItem(units[i]);
454 } 518 }
455 519
456 cb->setEditable(true); 520 cb->setEditable(true);
457
458 } else { // ColourProperty
459
460 //!!! should be a proper colour combobox class that
461 // manages its own Add New Colour entry...
462
463 ColourDatabase *db = ColourDatabase::getInstance();
464 for (int i = 0; i < db->getColourCount(); ++i) {
465 QString name = db->getColourName(i);
466 cb->addItem(db->getExamplePixmap(i, QSize(12, 12)), name);
467 }
468 cb->addItem(tr("Add New Colour..."));
469 }
470
471 cb->blockSignals(false);
472 if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) {
473 cb->setMaxVisibleItems(cb->count());
474 } 521 }
475 } 522 }
476 523
477 if (!have) { 524 if (!have) {
478 connect(cb, SIGNAL(activated(int)), 525 connect(cb, SIGNAL(activated(int)),
480 connect(cb, SIGNAL(mouseEntered()), 527 connect(cb, SIGNAL(mouseEntered()),
481 this, SLOT(mouseEnteredWidget())); 528 this, SLOT(mouseEnteredWidget()));
482 connect(cb, SIGNAL(mouseLeft()), 529 connect(cb, SIGNAL(mouseLeft()),
483 this, SLOT(mouseLeftWidget())); 530 this, SLOT(mouseLeftWidget()));
484 531
485 if (inGroup) { 532 cb->setToolTip(propertyLabel);
486 cb->setToolTip(propertyLabel); 533 groupLayout->addWidget(cb, 0, groupLayout->columnCount());
487 m_groupLayouts[groupName]->addWidget
488 (cb, 0, m_groupLayouts[groupName]->columnCount());
489 } else {
490 m_layout->addWidget(cb, row, 1, 1, 2);
491 }
492 m_propertyControllers[name] = cb; 534 m_propertyControllers[name] = cb;
493 } 535 } else if (existing != cb) {
536 groupLayout->replaceWidget(existing, cb);
537 delete existing;
538 }
494 539
495 cb->blockSignals(true); 540 cb->blockSignals(true);
496 if (type == PropertyContainer::ValueProperty || 541 if (type == PropertyContainer::ValueProperty) {
497 type == PropertyContainer::ColourProperty) {
498 if (cb->currentIndex() != value) { 542 if (cb->currentIndex() != value) {
499 cb->setCurrentIndex(value); 543 cb->setCurrentIndex(value);
500 } 544 }
501 } else { 545 } else {
502 QString unit = UnitDatabase::getInstance()->getUnitById(value); 546 QString unit = UnitDatabase::getInstance()->getUnitById(value);
509 } 553 }
510 } 554 }
511 } 555 }
512 cb->blockSignals(false); 556 cb->blockSignals(false);
513 557
514 #ifdef Q_OS_MAC
515 // Crashes on startup without this, for some reason
516 cb->setMinimumSize(QSize(10, 10));
517 #endif
518
519 break; 558 break;
520 } 559 }
521 560
522 case PropertyContainer::InvalidProperty: 561 case PropertyContainer::InvalidProperty:
523 default: 562 default:
581 620
582 blockSignals(false); 621 blockSignals(false);
583 } 622 }
584 623
585 void 624 void
586 PropertyBox::colourDatabaseChanged()
587 {
588 blockSignals(true);
589
590 PropertyContainer::PropertyList properties = m_container->getProperties();
591 for (size_t i = 0; i < properties.size(); ++i) {
592 if (m_container->getPropertyType(properties[i]) ==
593 PropertyContainer::ColourProperty) {
594 updatePropertyEditor(properties[i], true);
595 }
596 }
597
598 blockSignals(false);
599 }
600
601 void
602 PropertyBox::propertyControllerChanged(bool on) 625 PropertyBox::propertyControllerChanged(bool on)
603 { 626 {
604 propertyControllerChanged(on ? 1 : 0); 627 propertyControllerChanged(on ? 1 : 0);
605 } 628 }
606 629
618 641
619 Command *c = 0; 642 Command *c = 0;
620 643
621 if (type == PropertyContainer::UnitsProperty) { 644 if (type == PropertyContainer::UnitsProperty) {
622 645
623 NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj); 646 NotifyingComboBox *cb = qobject_cast<NotifyingComboBox *>(obj);
624 if (cb) { 647 if (cb) {
625 QString unit = cb->currentText(); 648 QString unit = cb->currentText();
626 c = m_container->getSetPropertyCommand 649 c = m_container->getSetPropertyCommand
627 (name, UnitDatabase::getInstance()->getUnitId(unit)); 650 (name, UnitDatabase::getInstance()->getUnitId(unit));
628 } 651 }
629 652
630 } else if (type == PropertyContainer::ColourProperty) {
631
632 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
633 addNewColour();
634 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
635 propertyContainerPropertyChanged(m_container);
636 return;
637 }
638 }
639 c = m_container->getSetPropertyCommand(name, value);
640
641 } else if (type != PropertyContainer::InvalidProperty) { 653 } else if (type != PropertyContainer::InvalidProperty) {
642 654
643 c = m_container->getSetPropertyCommand(name, value); 655 c = m_container->getSetPropertyCommand(name, value);
644 } 656 }
645 657
647 659
648 updateContextHelp(obj); 660 updateContextHelp(obj);
649 } 661 }
650 662
651 void 663 void
652 PropertyBox::addNewColour()
653 {
654 QColor newColour = QColorDialog::getColor();
655 if (!newColour.isValid()) return;
656
657 ColourNameDialog dialog(tr("Name New Colour"),
658 tr("Enter a name for the new colour:"),
659 newColour, newColour.name(), this);
660 dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
661 if (dialog.exec() == QDialog::Accepted) {
662 //!!! command
663 ColourDatabase *db = ColourDatabase::getInstance();
664 int index = db->addColour(newColour, dialog.getColourName());
665 db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
666 }
667 }
668
669 void
670 PropertyBox::playAudibleChanged(bool audible) 664 PropertyBox::playAudibleChanged(bool audible)
671 { 665 {
672 m_playButton->setState(audible); 666 m_playButton->setChecked(audible);
673 } 667 }
674 668
675 void 669 void
676 PropertyBox::playAudibleButtonChanged(bool audible) 670 PropertyBox::playAudibleButtonChanged(bool audible)
677 { 671 {
683 new PlayParameterRepository::EditCommand(params); 677 new PlayParameterRepository::EditCommand(params);
684 command->setPlayAudible(audible); 678 command->setPlayAudible(audible);
685 CommandHistory::getInstance()->addCommand(command, true, true); 679 CommandHistory::getInstance()->addCommand(command, true, true);
686 } 680 }
687 } 681 }
688 682
689 void 683 void
690 PropertyBox::playGainChanged(float gain) 684 PropertyBox::playGainControlChanged(float gain)
691 {
692 int dialValue = int(lrint(log10(gain) * 20.0));
693 if (dialValue < -50) dialValue = -50;
694 if (dialValue > 50) dialValue = 50;
695 emit changePlayGainDial(dialValue);
696 }
697
698 void
699 PropertyBox::playGainDialChanged(int dialValue)
700 { 685 {
701 QObject *obj = sender(); 686 QObject *obj = sender();
702 687
703 PlayParameters *params = m_container->getPlayParameters(); 688 PlayParameters *params = m_container->getPlayParameters();
704 if (!params) return; 689 if (!params) return;
705
706 float gain = float(pow(10, float(dialValue) / 20.0));
707 690
708 if (params->getPlayGain() != gain) { 691 if (params->getPlayGain() != gain) {
709 PlayParameterRepository::EditCommand *command = 692 PlayParameterRepository::EditCommand *command =
710 new PlayParameterRepository::EditCommand(params); 693 new PlayParameterRepository::EditCommand(params);
711 command->setPlayGain(gain); 694 command->setPlayGain(gain);
712 CommandHistory::getInstance()->addCommand(command, true, true); 695 CommandHistory::getInstance()->addCommand(command, true, true);
713 } 696 }
714 697
715 updateContextHelp(obj); 698 updateContextHelp(obj);
716 } 699 }
717 700
718 void 701 void
719 PropertyBox::playPanChanged(float pan) 702 PropertyBox::playPanControlChanged(float pan)
720 {
721 int dialValue = int(lrint(pan * 50.0));
722 if (dialValue < -50) dialValue = -50;
723 if (dialValue > 50) dialValue = 50;
724 emit changePlayPanDial(dialValue);
725 }
726
727 void
728 PropertyBox::playPanDialChanged(int dialValue)
729 { 703 {
730 QObject *obj = sender(); 704 QObject *obj = sender();
731 705
732 PlayParameters *params = m_container->getPlayParameters(); 706 PlayParameters *params = m_container->getPlayParameters();
733 if (!params) return; 707 if (!params) return;
734
735 float pan = float(dialValue) / 50.f;
736 if (pan < -1.f) pan = -1.f;
737 if (pan > 1.f) pan = 1.f;
738 708
739 if (params->getPlayPan() != pan) { 709 if (params->getPlayPan() != pan) {
740 PlayParameterRepository::EditCommand *command = 710 PlayParameterRepository::EditCommand *command =
741 new PlayParameterRepository::EditCommand(params); 711 new PlayParameterRepository::EditCommand(params);
742 command->setPlayPan(pan); 712 command->setPlayPan(pan);
818 } 788 }
819 789
820 void 790 void
821 PropertyBox::updateContextHelp(QObject *o) 791 PropertyBox::updateContextHelp(QObject *o)
822 { 792 {
823 QWidget *w = dynamic_cast<QWidget *>(o); 793 QWidget *w = qobject_cast<QWidget *>(o);
824 if (!w) return; 794 if (!w) return;
825 795
826 if (!m_container) return; 796 if (!m_container) return;
827 QString cname = m_container->getPropertyContainerName(); 797 QString cname = m_container->getPropertyContainerName();
828 if (cname == "") return; 798 if (cname == "") return;
829 799
800 LevelPanToolButton *lp = qobject_cast<LevelPanToolButton *>(w);
801 if (lp) {
802 emit contextHelpChanged(tr("Adjust playback level and pan of %1").arg(cname));
803 return;
804 }
805
830 QString wname = w->objectName(); 806 QString wname = w->objectName();
831 807
808 if (wname == "playParamButton") {
809 PlayParameters *params = m_container->getPlayParameters();
810 if (params) {
811 emit contextHelpChanged
812 (tr("Change sound used for playback (currently \"%1\")")
813 .arg(params->getPlayClipId()));
814 return;
815 }
816 }
817
832 QString extraText; 818 QString extraText;
833 AudioDial *dial = dynamic_cast<AudioDial *>(w); 819
820 AudioDial *dial = qobject_cast<AudioDial *>(w);
834 if (dial) { 821 if (dial) {
835 double mv = dial->mappedValue(); 822 double mv = dial->mappedValue();
836 QString unit = ""; 823 QString unit = "";
837 if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit(); 824 if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit();
838 if (unit != "") { 825 if (unit != "") {
846 emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname)); 833 emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname));
847 } else if (w == m_playButton) { 834 } else if (w == m_playButton) {
848 emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname)); 835 emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname));
849 } else if (wname == "") { 836 } else if (wname == "") {
850 return; 837 return;
851 } else if (dynamic_cast<QAbstractButton *>(w)) { 838 } else if (qobject_cast<QAbstractButton *>(w)) {
852 emit contextHelpChanged(tr("Toggle %1 property of %2") 839 emit contextHelpChanged(tr("Toggle %1 property of %2")
853 .arg(wname).arg(cname)); 840 .arg(wname).arg(cname));
854 } else { 841 } else {
855 emit contextHelpChanged(tr("Adjust %1 property of %2%3") 842 emit contextHelpChanged(tr("Adjust %1 property of %2%3")
856 .arg(wname).arg(cname).arg(extraText)); 843 .arg(wname).arg(cname).arg(extraText));