annotate widgets/PropertyBox.cpp @ 959:2633a1d73e39

Address #1214, layer import produces wrong layer type. We needed a more principled approach to making sure the format gets updated properly and the dialog elements are consistent (basically separating making the dialog elements consistent from subsequently updating the format). This change should provide that, though there may be gotchas still.
author Chris Cannam
date Tue, 12 May 2015 12:31:37 +0100
parents 4a578a360011
children 98827470ada2 66da6f009edd
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@59 9 This program is free software; you can redistribute it and/or
Chris@59 10 modify it under the terms of the GNU General Public License as
Chris@59 11 published by the Free Software Foundation; either version 2 of the
Chris@59 12 License, or (at your option) any later version. See the file
Chris@59 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "PropertyBox.h"
Chris@63 17 #include "PluginParameterDialog.h"
Chris@0 18
Chris@0 19 #include "base/PropertyContainer.h"
Chris@33 20 #include "base/PlayParameters.h"
Chris@377 21 #include "base/PlayParameterRepository.h"
Chris@128 22 #include "layer/Layer.h"
Chris@376 23 #include "layer/ColourDatabase.h"
Chris@100 24 #include "base/UnitDatabase.h"
Chris@167 25 #include "base/RangeMapper.h"
Chris@0 26
Chris@0 27 #include "AudioDial.h"
Chris@33 28 #include "LEDButton.h"
Chris@335 29 #include "IconLoader.h"
Chris@0 30
Chris@189 31 #include "NotifyingCheckBox.h"
Chris@189 32 #include "NotifyingComboBox.h"
Chris@335 33 #include "NotifyingPushButton.h"
Chris@285 34 #include "ColourNameDialog.h"
Chris@189 35
Chris@0 36 #include <QGridLayout>
Chris@0 37 #include <QHBoxLayout>
Chris@33 38 #include <QVBoxLayout>
Chris@63 39 #include <QPushButton>
Chris@0 40 #include <QLabel>
Chris@33 41 #include <QFrame>
Chris@218 42 #include <QApplication>
Chris@285 43 #include <QColorDialog>
Chris@285 44 #include <QInputDialog>
Chris@769 45 #include <QDir>
Chris@0 46
Chris@0 47 #include <cassert>
Chris@0 48 #include <iostream>
Martin@46 49 #include <cmath>
Chris@0 50
Chris@456 51 //#define DEBUG_PROPERTY_BOX 1
Chris@0 52
Chris@0 53 PropertyBox::PropertyBox(PropertyContainer *container) :
Chris@185 54 m_container(container),
Chris@189 55 m_showButton(0),
Chris@189 56 m_playButton(0)
Chris@0 57 {
Chris@0 58 #ifdef DEBUG_PROPERTY_BOX
Chris@682 59 cerr << "PropertyBox[" << this << "(\"" <<
Chris@682 60 container->getPropertyContainerName() << "\" at " << container << ")]::PropertyBox" << endl;
Chris@0 61 #endif
Chris@0 62
Chris@34 63 m_mainBox = new QVBoxLayout;
Chris@34 64 setLayout(m_mainBox);
Chris@33 65
Chris@107 66 // m_nameWidget = new QLabel;
Chris@107 67 // m_mainBox->addWidget(m_nameWidget);
Chris@107 68 // m_nameWidget->setText(container->objectName());
Chris@107 69
Chris@34 70 m_mainWidget = new QWidget;
Chris@34 71 m_mainBox->addWidget(m_mainWidget);
Chris@107 72 m_mainBox->insertStretch(2, 10);
Chris@33 73
Chris@34 74 m_viewPlayFrame = 0;
Chris@34 75 populateViewPlayFrame();
Chris@33 76
Chris@0 77 m_layout = new QGridLayout;
Chris@34 78 m_layout->setMargin(0);
Chris@833 79 m_layout->setHorizontalSpacing(2);
Chris@833 80 m_layout->setVerticalSpacing(1);
Chris@33 81 m_mainWidget->setLayout(m_layout);
Chris@0 82
Chris@34 83 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@0 84
Chris@0 85 blockSignals(true);
Chris@0 86
Chris@0 87 size_t i;
Chris@0 88
Chris@0 89 for (i = 0; i < properties.size(); ++i) {
Chris@0 90 updatePropertyEditor(properties[i]);
Chris@0 91 }
Chris@0 92
Chris@0 93 blockSignals(false);
Chris@0 94
Chris@0 95 m_layout->setRowStretch(m_layout->rowCount(), 10);
Chris@0 96
Chris@100 97 connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()),
Chris@100 98 this, SLOT(unitDatabaseChanged()));
Chris@100 99
Chris@285 100 connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()),
Chris@285 101 this, SLOT(colourDatabaseChanged()));
Chris@285 102
Chris@0 103 #ifdef DEBUG_PROPERTY_BOX
Chris@682 104 cerr << "PropertyBox[" << this << "]::PropertyBox returning" << endl;
Chris@0 105 #endif
Chris@0 106 }
Chris@0 107
Chris@0 108 PropertyBox::~PropertyBox()
Chris@0 109 {
Chris@0 110 #ifdef DEBUG_PROPERTY_BOX
Chris@682 111 cerr << "PropertyBox[" << this << "]::~PropertyBox" << endl;
Chris@0 112 #endif
Chris@0 113 }
Chris@0 114
Chris@0 115 void
Chris@34 116 PropertyBox::populateViewPlayFrame()
Chris@33 117 {
Chris@36 118 #ifdef DEBUG_PROPERTY_BOX
Chris@729 119 cerr << "PropertyBox[" << this << ":" << m_container << "]::populateViewPlayFrame" << endl;
Chris@36 120 #endif
Chris@34 121
Chris@34 122 if (m_viewPlayFrame) {
Chris@34 123 delete m_viewPlayFrame;
Chris@34 124 m_viewPlayFrame = 0;
Chris@34 125 }
Chris@34 126
Chris@34 127 if (!m_container) return;
Chris@34 128
Chris@34 129 Layer *layer = dynamic_cast<Layer *>(m_container);
Chris@34 130 if (layer) {
Chris@193 131 disconnect(layer, SIGNAL(modelReplaced()),
Chris@193 132 this, SLOT(populateViewPlayFrame()));
Chris@34 133 connect(layer, SIGNAL(modelReplaced()),
Chris@34 134 this, SLOT(populateViewPlayFrame()));
Chris@34 135 }
Chris@34 136
Chris@34 137 PlayParameters *params = m_container->getPlayParameters();
Chris@33 138 if (!params && !layer) return;
Chris@33 139
Chris@34 140 m_viewPlayFrame = new QFrame;
Chris@34 141 m_viewPlayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
Chris@34 142 m_mainBox->addWidget(m_viewPlayFrame);
Chris@34 143
Chris@34 144 QHBoxLayout *layout = new QHBoxLayout;
Chris@34 145 m_viewPlayFrame->setLayout(layout);
Chris@34 146
Chris@34 147 layout->setMargin(layout->margin() / 2);
Chris@34 148
Chris@36 149 #ifdef DEBUG_PROPERTY_BOX
Chris@587 150 SVDEBUG << "PropertyBox::populateViewPlayFrame: container " << m_container << " (name " << m_container->getPropertyContainerName() << ") params " << params << endl;
Chris@36 151 #endif
Chris@36 152
Chris@33 153 if (layer) {
Chris@34 154 QLabel *showLabel = new QLabel(tr("Show"));
Chris@34 155 layout->addWidget(showLabel);
Chris@34 156 layout->setAlignment(showLabel, Qt::AlignVCenter);
Chris@34 157
Chris@185 158 m_showButton = new LEDButton(Qt::blue);
Chris@185 159 layout->addWidget(m_showButton);
Chris@185 160 connect(m_showButton, SIGNAL(stateChanged(bool)),
Chris@47 161 this, SIGNAL(showLayer(bool)));
Chris@189 162 connect(m_showButton, SIGNAL(mouseEntered()),
Chris@189 163 this, SLOT(mouseEnteredWidget()));
Chris@189 164 connect(m_showButton, SIGNAL(mouseLeft()),
Chris@189 165 this, SLOT(mouseLeftWidget()));
Chris@185 166 layout->setAlignment(m_showButton, Qt::AlignVCenter);
Chris@33 167 }
Chris@33 168
Chris@33 169 if (params) {
Chris@34 170
Chris@34 171 QLabel *playLabel = new QLabel(tr("Play"));
Chris@34 172 layout->addWidget(playLabel);
Chris@34 173 layout->setAlignment(playLabel, Qt::AlignVCenter);
Chris@34 174
Chris@189 175 m_playButton = new LEDButton(Qt::darkGreen);
Chris@189 176 m_playButton->setState(!params->isPlayMuted());
Chris@189 177 layout->addWidget(m_playButton);
Chris@189 178 connect(m_playButton, SIGNAL(stateChanged(bool)),
Chris@377 179 this, SLOT(playAudibleButtonChanged(bool)));
Chris@189 180 connect(m_playButton, SIGNAL(mouseEntered()),
Chris@189 181 this, SLOT(mouseEnteredWidget()));
Chris@189 182 connect(m_playButton, SIGNAL(mouseLeft()),
Chris@189 183 this, SLOT(mouseLeftWidget()));
Chris@34 184 connect(params, SIGNAL(playAudibleChanged(bool)),
Chris@377 185 this, SLOT(playAudibleChanged(bool)));
Chris@189 186 layout->setAlignment(m_playButton, Qt::AlignVCenter);
Chris@34 187
Chris@34 188 layout->insertStretch(-1, 10);
Chris@34 189
Chris@769 190 if (params->getPlayClipId() != "") {
Chris@769 191 QPushButton *playParamButton =
Chris@769 192 new QPushButton(QIcon(":icons/faders.png"), "");
Chris@769 193 playParamButton->setFixedWidth(24);
Chris@769 194 playParamButton->setFixedHeight(24);
Chris@769 195 layout->addWidget(playParamButton);
Chris@769 196 connect(playParamButton, SIGNAL(clicked()),
Chris@769 197 this, SLOT(editPlayParameters()));
Chris@63 198 }
Chris@63 199
Chris@34 200 AudioDial *gainDial = new AudioDial;
Chris@34 201 layout->addWidget(gainDial);
Chris@34 202 gainDial->setMeterColor(Qt::darkRed);
Chris@34 203 gainDial->setMinimum(-50);
Chris@34 204 gainDial->setMaximum(50);
Chris@34 205 gainDial->setPageStep(1);
Chris@34 206 gainDial->setFixedWidth(24);
Chris@34 207 gainDial->setFixedHeight(24);
Chris@34 208 gainDial->setNotchesVisible(false);
Chris@34 209 gainDial->setDefaultValue(0);
Chris@168 210 gainDial->setObjectName(tr("Playback Gain"));
Chris@167 211 gainDial->setRangeMapper(new LinearRangeMapper
Chris@167 212 (-50, 50, -25, 25, tr("dB")));
Chris@168 213 gainDial->setShowToolTip(true);
Chris@34 214 connect(gainDial, SIGNAL(valueChanged(int)),
Chris@34 215 this, SLOT(playGainDialChanged(int)));
Chris@34 216 connect(params, SIGNAL(playGainChanged(float)),
Chris@34 217 this, SLOT(playGainChanged(float)));
Chris@34 218 connect(this, SIGNAL(changePlayGainDial(int)),
Chris@34 219 gainDial, SLOT(setValue(int)));
Chris@189 220 connect(gainDial, SIGNAL(mouseEntered()),
Chris@189 221 this, SLOT(mouseEnteredWidget()));
Chris@189 222 connect(gainDial, SIGNAL(mouseLeft()),
Chris@189 223 this, SLOT(mouseLeftWidget()));
Chris@377 224 playGainChanged(params->getPlayGain());
Chris@34 225 layout->setAlignment(gainDial, Qt::AlignVCenter);
Chris@34 226
Chris@34 227 AudioDial *panDial = new AudioDial;
Chris@34 228 layout->addWidget(panDial);
Chris@34 229 panDial->setMeterColor(Qt::darkGreen);
Chris@34 230 panDial->setMinimum(-50);
Chris@34 231 panDial->setMaximum(50);
Chris@34 232 panDial->setPageStep(1);
Chris@34 233 panDial->setFixedWidth(24);
Chris@34 234 panDial->setFixedHeight(24);
Chris@34 235 panDial->setNotchesVisible(false);
Chris@57 236 panDial->setToolTip(tr("Playback Pan / Balance"));
Chris@34 237 panDial->setDefaultValue(0);
Chris@168 238 panDial->setObjectName(tr("Playback Pan / Balance"));
Chris@168 239 panDial->setShowToolTip(true);
Chris@34 240 connect(panDial, SIGNAL(valueChanged(int)),
Chris@34 241 this, SLOT(playPanDialChanged(int)));
Chris@34 242 connect(params, SIGNAL(playPanChanged(float)),
Chris@34 243 this, SLOT(playPanChanged(float)));
Chris@34 244 connect(this, SIGNAL(changePlayPanDial(int)),
Chris@34 245 panDial, SLOT(setValue(int)));
Chris@189 246 connect(panDial, SIGNAL(mouseEntered()),
Chris@189 247 this, SLOT(mouseEnteredWidget()));
Chris@189 248 connect(panDial, SIGNAL(mouseLeft()),
Chris@189 249 this, SLOT(mouseLeftWidget()));
Chris@377 250 playPanChanged(params->getPlayPan());
Chris@34 251 layout->setAlignment(panDial, Qt::AlignVCenter);
Chris@34 252
Chris@34 253 } else {
Chris@34 254
Chris@34 255 layout->insertStretch(-1, 10);
Chris@33 256 }
Chris@33 257 }
Chris@33 258
Chris@33 259 void
Chris@197 260 PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name,
Chris@197 261 bool rangeChanged)
Chris@0 262 {
Chris@0 263 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@0 264 int row = m_layout->rowCount();
Chris@0 265
Chris@216 266 int min = 0, max = 0, value = 0, deflt = 0;
Chris@216 267 value = m_container->getPropertyRangeAndValue(name, &min, &max, &deflt);
Chris@0 268
Chris@0 269 bool have = (m_propertyControllers.find(name) !=
Chris@0 270 m_propertyControllers.end());
Chris@0 271
Chris@0 272 QString groupName = m_container->getPropertyGroupName(name);
Chris@87 273 QString propertyLabel = m_container->getPropertyLabel(name);
Chris@335 274 QString iconName = m_container->getPropertyIconName(name);
Chris@0 275
Chris@0 276 #ifdef DEBUG_PROPERTY_BOX
Chris@682 277 cerr << "PropertyBox[" << this
Chris@683 278 << "(\"" << m_container->getPropertyContainerName()
Chris@0 279 << "\")]";
Chris@682 280 cerr << "::updatePropertyEditor(\"" << name << "\"):";
Chris@682 281 cerr << " value " << value << ", have " << have << ", group \""
Chris@682 282 << groupName << "\"" << endl;
Chris@0 283 #endif
Chris@0 284
Chris@0 285 bool inGroup = (groupName != QString());
Chris@0 286
Chris@0 287 if (!have) {
Chris@0 288 if (inGroup) {
Chris@0 289 if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) {
Chris@0 290 #ifdef DEBUG_PROPERTY_BOX
Chris@682 291 cerr << "PropertyBox: adding label \"" << groupName << "\" and frame for group for \"" << name << "\"" << endl;
Chris@0 292 #endif
Chris@33 293 m_layout->addWidget(new QLabel(groupName, m_mainWidget), row, 0);
Chris@33 294 QFrame *frame = new QFrame(m_mainWidget);
Chris@0 295 m_layout->addWidget(frame, row, 1, 1, 2);
Chris@493 296 m_groupLayouts[groupName] = new QGridLayout;
Chris@0 297 m_groupLayouts[groupName]->setMargin(0);
Chris@0 298 frame->setLayout(m_groupLayouts[groupName]);
Chris@0 299 }
Chris@0 300 } else {
Chris@0 301 #ifdef DEBUG_PROPERTY_BOX
Chris@682 302 cerr << "PropertyBox: adding label \"" << propertyLabel << "\"" << endl;
Chris@0 303 #endif
Chris@87 304 m_layout->addWidget(new QLabel(propertyLabel, m_mainWidget), row, 0);
Chris@0 305 }
Chris@0 306 }
Chris@0 307
Chris@0 308 switch (type) {
Chris@0 309
Chris@0 310 case PropertyContainer::ToggleProperty:
Chris@0 311 {
Chris@335 312 QAbstractButton *button = 0;
Chris@0 313
Chris@0 314 if (have) {
Chris@335 315 button = dynamic_cast<QAbstractButton *>(m_propertyControllers[name]);
Chris@335 316 assert(button);
Chris@0 317 } else {
Chris@0 318 #ifdef DEBUG_PROPERTY_BOX
Chris@682 319 cerr << "PropertyBox: creating new checkbox" << endl;
Chris@0 320 #endif
Chris@335 321 if (iconName != "") {
Chris@335 322 button = new NotifyingPushButton();
Chris@335 323 button->setCheckable(true);
Chris@335 324 QIcon icon(IconLoader().load(iconName));
Chris@335 325 button->setIcon(icon);
Chris@335 326 button->setObjectName(name);
Chris@335 327 button->setFixedSize(QSize(18, 18));
Chris@335 328 } else {
Chris@335 329 button = new NotifyingCheckBox();
Chris@335 330 button->setObjectName(name);
Chris@335 331 }
Chris@335 332 connect(button, SIGNAL(toggled(bool)),
Chris@335 333 this, SLOT(propertyControllerChanged(bool)));
Chris@335 334 connect(button, SIGNAL(mouseEntered()),
Chris@189 335 this, SLOT(mouseEnteredWidget()));
Chris@335 336 connect(button, SIGNAL(mouseLeft()),
Chris@189 337 this, SLOT(mouseLeftWidget()));
Chris@0 338 if (inGroup) {
Chris@335 339 button->setToolTip(propertyLabel);
Chris@493 340 m_groupLayouts[groupName]->addWidget
Chris@493 341 (button, 0, m_groupLayouts[groupName]->columnCount());
Chris@0 342 } else {
Chris@335 343 m_layout->addWidget(button, row, 1, 1, 2);
Chris@0 344 }
Chris@335 345 m_propertyControllers[name] = button;
Chris@0 346 }
Chris@0 347
Chris@335 348 if (button->isChecked() != (value > 0)) {
Chris@335 349 button->blockSignals(true);
Chris@335 350 button->setChecked(value > 0);
Chris@335 351 button->blockSignals(false);
Chris@55 352 }
Chris@0 353 break;
Chris@0 354 }
Chris@0 355
Chris@0 356 case PropertyContainer::RangeProperty:
Chris@0 357 {
Chris@0 358 AudioDial *dial;
Chris@0 359
Chris@0 360 if (have) {
Chris@0 361 dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]);
Chris@0 362 assert(dial);
Chris@197 363 if (rangeChanged) {
Chris@197 364 dial->blockSignals(true);
Chris@197 365 dial->setMinimum(min);
Chris@197 366 dial->setMaximum(max);
Chris@197 367 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
Chris@197 368 dial->blockSignals(false);
Chris@197 369 }
Chris@197 370
Chris@0 371 } else {
Chris@0 372 #ifdef DEBUG_PROPERTY_BOX
Chris@682 373 cerr << "PropertyBox: creating new dial" << endl;
Chris@0 374 #endif
Chris@0 375 dial = new AudioDial();
Chris@0 376 dial->setObjectName(name);
Chris@0 377 dial->setMinimum(min);
Chris@0 378 dial->setMaximum(max);
Chris@0 379 dial->setPageStep(1);
Chris@34 380 dial->setNotchesVisible((max - min) <= 12);
Chris@216 381 dial->setDefaultValue(deflt);
Chris@167 382 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
Chris@168 383 dial->setShowToolTip(true);
Chris@0 384 connect(dial, SIGNAL(valueChanged(int)),
Chris@0 385 this, SLOT(propertyControllerChanged(int)));
Chris@189 386 connect(dial, SIGNAL(mouseEntered()),
Chris@189 387 this, SLOT(mouseEnteredWidget()));
Chris@189 388 connect(dial, SIGNAL(mouseLeft()),
Chris@189 389 this, SLOT(mouseLeftWidget()));
Chris@0 390
Chris@0 391 if (inGroup) {
Chris@0 392 dial->setFixedWidth(24);
Chris@0 393 dial->setFixedHeight(24);
Chris@493 394 m_groupLayouts[groupName]->addWidget
Chris@493 395 (dial, 0, m_groupLayouts[groupName]->columnCount());
Chris@0 396 } else {
Chris@0 397 dial->setFixedWidth(32);
Chris@0 398 dial->setFixedHeight(32);
Chris@0 399 m_layout->addWidget(dial, row, 1);
Chris@33 400 QLabel *label = new QLabel(m_mainWidget);
Chris@0 401 connect(dial, SIGNAL(valueChanged(int)),
Chris@0 402 label, SLOT(setNum(int)));
Chris@0 403 label->setNum(value);
Chris@0 404 m_layout->addWidget(label, row, 2);
Chris@0 405 }
Chris@0 406
Chris@0 407 m_propertyControllers[name] = dial;
Chris@0 408 }
Chris@0 409
Chris@55 410 if (dial->value() != value) {
Chris@55 411 dial->blockSignals(true);
Chris@55 412 dial->setValue(value);
Chris@55 413 dial->blockSignals(false);
Chris@55 414 }
Chris@0 415 break;
Chris@0 416 }
Chris@0 417
Chris@0 418 case PropertyContainer::ValueProperty:
Chris@100 419 case PropertyContainer::UnitsProperty:
Chris@285 420 case PropertyContainer::ColourProperty:
Chris@0 421 {
Chris@189 422 NotifyingComboBox *cb;
Chris@0 423
Chris@0 424 if (have) {
Chris@189 425 cb = dynamic_cast<NotifyingComboBox *>(m_propertyControllers[name]);
Chris@0 426 assert(cb);
Chris@0 427 } else {
Chris@0 428 #ifdef DEBUG_PROPERTY_BOX
Chris@682 429 cerr << "PropertyBox: creating new combobox" << endl;
Chris@0 430 #endif
Chris@0 431
Chris@189 432 cb = new NotifyingComboBox();
Chris@0 433 cb->setObjectName(name);
Chris@100 434 cb->setDuplicatesEnabled(false);
Chris@197 435 }
Chris@100 436
Chris@197 437 if (!have || rangeChanged) {
Chris@285 438
Chris@197 439 cb->blockSignals(true);
Chris@197 440 cb->clear();
Chris@285 441 cb->setEditable(false);
Chris@285 442
Chris@100 443 if (type == PropertyContainer::ValueProperty) {
Chris@285 444
Chris@100 445 for (int i = min; i <= max; ++i) {
Chris@100 446 cb->addItem(m_container->getPropertyValueLabel(name, i));
Chris@100 447 }
Chris@285 448
Chris@285 449 } else if (type == PropertyContainer::UnitsProperty) {
Chris@285 450
Chris@100 451 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
Chris@100 452 for (int i = 0; i < units.size(); ++i) {
Chris@100 453 cb->addItem(units[i]);
Chris@100 454 }
Chris@285 455
Chris@100 456 cb->setEditable(true);
Chris@285 457
Chris@285 458 } else { // ColourProperty
Chris@290 459
Chris@290 460 //!!! should be a proper colour combobox class that
Chris@290 461 // manages its own Add New Colour entry...
Chris@285 462
Chris@285 463 ColourDatabase *db = ColourDatabase::getInstance();
Chris@769 464 for (int i = 0; i < db->getColourCount(); ++i) {
Chris@285 465 QString name = db->getColourName(i);
Chris@287 466 cb->addItem(db->getExamplePixmap(i, QSize(12, 12)), name);
Chris@285 467 }
Chris@285 468 cb->addItem(tr("Add New Colour..."));
Chris@285 469 }
Chris@285 470
Chris@197 471 cb->blockSignals(false);
Chris@280 472 if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) {
Chris@280 473 cb->setMaxVisibleItems(cb->count());
Chris@280 474 }
Chris@197 475 }
Chris@100 476
Chris@197 477 if (!have) {
Chris@0 478 connect(cb, SIGNAL(activated(int)),
Chris@0 479 this, SLOT(propertyControllerChanged(int)));
Chris@189 480 connect(cb, SIGNAL(mouseEntered()),
Chris@189 481 this, SLOT(mouseEnteredWidget()));
Chris@189 482 connect(cb, SIGNAL(mouseLeft()),
Chris@189 483 this, SLOT(mouseLeftWidget()));
Chris@100 484
Chris@0 485 if (inGroup) {
Chris@108 486 cb->setToolTip(propertyLabel);
Chris@493 487 m_groupLayouts[groupName]->addWidget
Chris@493 488 (cb, 0, m_groupLayouts[groupName]->columnCount());
Chris@0 489 } else {
Chris@0 490 m_layout->addWidget(cb, row, 1, 1, 2);
Chris@0 491 }
Chris@0 492 m_propertyControllers[name] = cb;
Chris@0 493 }
Chris@0 494
Chris@100 495 cb->blockSignals(true);
Chris@285 496 if (type == PropertyContainer::ValueProperty ||
Chris@285 497 type == PropertyContainer::ColourProperty) {
Chris@100 498 if (cb->currentIndex() != value) {
Chris@100 499 cb->setCurrentIndex(value);
Chris@100 500 }
Chris@100 501 } else {
Chris@100 502 QString unit = UnitDatabase::getInstance()->getUnitById(value);
Chris@100 503 if (cb->currentText() != unit) {
Chris@100 504 for (int i = 0; i < cb->count(); ++i) {
Chris@100 505 if (cb->itemText(i) == unit) {
Chris@100 506 cb->setCurrentIndex(i);
Chris@100 507 break;
Chris@100 508 }
Chris@100 509 }
Chris@100 510 }
Chris@100 511 }
Chris@100 512 cb->blockSignals(false);
Chris@0 513
Chris@681 514 #ifdef Q_OS_MAC
Chris@0 515 // Crashes on startup without this, for some reason
Chris@0 516 cb->setMinimumSize(QSize(10, 10));
Chris@0 517 #endif
Chris@0 518
Chris@0 519 break;
Chris@0 520 }
Chris@0 521
Chris@807 522 case PropertyContainer::InvalidProperty:
Chris@0 523 default:
Chris@0 524 break;
Chris@0 525 }
Chris@0 526 }
Chris@0 527
Chris@0 528 void
Chris@0 529 PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 530 {
Chris@0 531 if (pc != m_container) return;
Chris@0 532
Chris@55 533 #ifdef DEBUG_PROPERTY_BOX
Chris@587 534 SVDEBUG << "PropertyBox::propertyContainerPropertyChanged" << endl;
Chris@55 535 #endif
Chris@55 536
Chris@0 537 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@0 538 size_t i;
Chris@0 539
Chris@0 540 blockSignals(true);
Chris@0 541
Chris@0 542 for (i = 0; i < properties.size(); ++i) {
Chris@0 543 updatePropertyEditor(properties[i]);
Chris@0 544 }
Chris@0 545
Chris@0 546 blockSignals(false);
Chris@0 547 }
Chris@0 548
Chris@0 549 void
Chris@249 550 PropertyBox::propertyContainerPropertyRangeChanged(PropertyContainer *)
Chris@197 551 {
Chris@197 552 blockSignals(true);
Chris@197 553
Chris@197 554 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@197 555 for (size_t i = 0; i < properties.size(); ++i) {
Chris@197 556 updatePropertyEditor(properties[i], true);
Chris@197 557 }
Chris@197 558
Chris@197 559 blockSignals(false);
Chris@197 560 }
Chris@197 561
Chris@197 562 void
Chris@100 563 PropertyBox::unitDatabaseChanged()
Chris@100 564 {
Chris@729 565 #ifdef DEBUG_PROPERTY_BOX
Chris@682 566 cerr << "PropertyBox[" << this << "]: unitDatabaseChanged" << endl;
Chris@729 567 #endif
Chris@100 568 blockSignals(true);
Chris@100 569
Chris@682 570 // cerr << "my container is " << m_container << endl;
Chris@682 571 // cerr << "my container's name is... " << endl;
Chris@682 572 // cerr << m_container->objectName() << endl;
Chris@456 573
Chris@100 574 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@100 575 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 576 if (m_container->getPropertyType(properties[i]) ==
Chris@285 577 PropertyContainer::UnitsProperty) {
Chris@285 578 updatePropertyEditor(properties[i]);
Chris@285 579 }
Chris@285 580 }
Chris@285 581
Chris@285 582 blockSignals(false);
Chris@285 583 }
Chris@285 584
Chris@285 585 void
Chris@285 586 PropertyBox::colourDatabaseChanged()
Chris@285 587 {
Chris@285 588 blockSignals(true);
Chris@285 589
Chris@285 590 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@285 591 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 592 if (m_container->getPropertyType(properties[i]) ==
Chris@285 593 PropertyContainer::ColourProperty) {
Chris@285 594 updatePropertyEditor(properties[i], true);
Chris@285 595 }
Chris@100 596 }
Chris@100 597
Chris@100 598 blockSignals(false);
Chris@100 599 }
Chris@100 600
Chris@100 601 void
Chris@335 602 PropertyBox::propertyControllerChanged(bool on)
Chris@335 603 {
Chris@335 604 propertyControllerChanged(on ? 1 : 0);
Chris@335 605 }
Chris@335 606
Chris@335 607 void
Chris@0 608 PropertyBox::propertyControllerChanged(int value)
Chris@0 609 {
Chris@0 610 QObject *obj = sender();
Chris@0 611 QString name = obj->objectName();
Chris@0 612
Chris@34 613 #ifdef DEBUG_PROPERTY_BOX
Chris@587 614 SVDEBUG << "PropertyBox::propertyControllerChanged(" << name << ", " << value << ")" << endl;
Chris@34 615 #endif
Chris@0 616
Chris@0 617 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@100 618
Chris@376 619 Command *c = 0;
Chris@376 620
Chris@100 621 if (type == PropertyContainer::UnitsProperty) {
Chris@285 622
Chris@189 623 NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj);
Chris@100 624 if (cb) {
Chris@100 625 QString unit = cb->currentText();
Chris@376 626 c = m_container->getSetPropertyCommand
Chris@100 627 (name, UnitDatabase::getInstance()->getUnitId(unit));
Chris@100 628 }
Chris@285 629
Chris@285 630 } else if (type == PropertyContainer::ColourProperty) {
Chris@285 631
Chris@285 632 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 633 addNewColour();
Chris@285 634 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 635 propertyContainerPropertyChanged(m_container);
Chris@285 636 return;
Chris@285 637 }
Chris@285 638 }
Chris@376 639 c = m_container->getSetPropertyCommand(name, value);
Chris@285 640
Chris@100 641 } else if (type != PropertyContainer::InvalidProperty) {
Chris@285 642
Chris@376 643 c = m_container->getSetPropertyCommand(name, value);
Chris@0 644 }
Chris@376 645
Chris@376 646 if (c) CommandHistory::getInstance()->addCommand(c, true, true);
Chris@218 647
Chris@218 648 updateContextHelp(obj);
Chris@0 649 }
Chris@285 650
Chris@285 651 void
Chris@285 652 PropertyBox::addNewColour()
Chris@285 653 {
Chris@285 654 QColor newColour = QColorDialog::getColor();
Chris@285 655 if (!newColour.isValid()) return;
Chris@285 656
Chris@285 657 ColourNameDialog dialog(tr("Name New Colour"),
Chris@361 658 tr("Enter a name for the new colour:"),
Chris@361 659 newColour, newColour.name(), this);
Chris@285 660 dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
Chris@285 661 if (dialog.exec() == QDialog::Accepted) {
Chris@285 662 //!!! command
Chris@285 663 ColourDatabase *db = ColourDatabase::getInstance();
Chris@285 664 int index = db->addColour(newColour, dialog.getColourName());
Chris@285 665 db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
Chris@285 666 }
Chris@285 667 }
Chris@377 668
Chris@377 669 void
Chris@377 670 PropertyBox::playAudibleChanged(bool audible)
Chris@377 671 {
Chris@377 672 m_playButton->setState(audible);
Chris@377 673 }
Chris@377 674
Chris@377 675 void
Chris@377 676 PropertyBox::playAudibleButtonChanged(bool audible)
Chris@377 677 {
Chris@377 678 PlayParameters *params = m_container->getPlayParameters();
Chris@377 679 if (!params) return;
Chris@377 680
Chris@377 681 if (params->isPlayAudible() != audible) {
Chris@377 682 PlayParameterRepository::EditCommand *command =
Chris@377 683 new PlayParameterRepository::EditCommand(params);
Chris@377 684 command->setPlayAudible(audible);
Chris@377 685 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 686 }
Chris@377 687 }
Chris@0 688
Chris@34 689 void
Chris@34 690 PropertyBox::playGainChanged(float gain)
Chris@34 691 {
Chris@908 692 int dialValue = int(lrint(log10(gain) * 20.0));
Chris@34 693 if (dialValue < -50) dialValue = -50;
Chris@34 694 if (dialValue > 50) dialValue = 50;
Chris@34 695 emit changePlayGainDial(dialValue);
Chris@34 696 }
Chris@34 697
Chris@34 698 void
Chris@34 699 PropertyBox::playGainDialChanged(int dialValue)
Chris@34 700 {
Chris@218 701 QObject *obj = sender();
Chris@377 702
Chris@377 703 PlayParameters *params = m_container->getPlayParameters();
Chris@377 704 if (!params) return;
Chris@377 705
Chris@908 706 float gain = float(pow(10, float(dialValue) / 20.0));
Chris@377 707
Chris@377 708 if (params->getPlayGain() != gain) {
Chris@377 709 PlayParameterRepository::EditCommand *command =
Chris@377 710 new PlayParameterRepository::EditCommand(params);
Chris@377 711 command->setPlayGain(gain);
Chris@377 712 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 713 }
Chris@377 714
Chris@218 715 updateContextHelp(obj);
Chris@34 716 }
Chris@34 717
Chris@34 718 void
Chris@34 719 PropertyBox::playPanChanged(float pan)
Chris@34 720 {
Chris@908 721 int dialValue = int(lrint(pan * 50.0));
Chris@34 722 if (dialValue < -50) dialValue = -50;
Chris@34 723 if (dialValue > 50) dialValue = 50;
Chris@34 724 emit changePlayPanDial(dialValue);
Chris@34 725 }
Chris@34 726
Chris@34 727 void
Chris@34 728 PropertyBox::playPanDialChanged(int dialValue)
Chris@34 729 {
Chris@218 730 QObject *obj = sender();
Chris@377 731
Chris@377 732 PlayParameters *params = m_container->getPlayParameters();
Chris@377 733 if (!params) return;
Chris@377 734
Chris@908 735 float pan = float(dialValue) / 50.f;
Chris@908 736 if (pan < -1.f) pan = -1.f;
Chris@908 737 if (pan > 1.f) pan = 1.f;
Chris@377 738
Chris@377 739 if (params->getPlayPan() != pan) {
Chris@377 740 PlayParameterRepository::EditCommand *command =
Chris@377 741 new PlayParameterRepository::EditCommand(params);
Chris@377 742 command->setPlayPan(pan);
Chris@377 743 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 744 }
Chris@377 745
Chris@218 746 updateContextHelp(obj);
Chris@34 747 }
Chris@769 748
Chris@63 749 void
Chris@769 750 PropertyBox::editPlayParameters()
Chris@63 751 {
Chris@63 752 PlayParameters *params = m_container->getPlayParameters();
Chris@63 753 if (!params) return;
Chris@63 754
Chris@769 755 QString clip = params->getPlayClipId();
Chris@377 756
Chris@377 757 PlayParameterRepository::EditCommand *command =
Chris@377 758 new PlayParameterRepository::EditCommand(params);
Chris@63 759
Chris@769 760 QInputDialog *dialog = new QInputDialog(this);
Chris@63 761
Chris@769 762 QDir dir(":/samples");
Chris@769 763 QStringList clipFiles = dir.entryList(QStringList() << "*.wav", QDir::Files);
Chris@63 764
Chris@769 765 QStringList clips;
Chris@769 766 foreach (QString str, clipFiles) {
Chris@769 767 clips.push_back(str.replace(".wav", ""));
Chris@769 768 }
Chris@769 769 dialog->setComboBoxItems(clips);
Chris@63 770
Chris@769 771 dialog->setLabelText(tr("Set playback clip:"));
Chris@769 772
Chris@769 773 QComboBox *cb = dialog->findChild<QComboBox *>();
Chris@779 774 if (cb) {
Chris@779 775 for (int i = 0; i < cb->count(); ++i) {
Chris@779 776 if (cb->itemText(i) == clip) {
Chris@779 777 cb->setCurrentIndex(i);
Chris@779 778 }
Chris@779 779 }
Chris@779 780 }
Chris@769 781
Chris@769 782 connect(dialog, SIGNAL(textValueChanged(QString)),
Chris@769 783 this, SLOT(playClipChanged(QString)));
Chris@64 784
Chris@63 785 if (dialog->exec() == QDialog::Accepted) {
Chris@769 786 QString newClip = dialog->textValue();
Chris@769 787 command->setPlayClipId(newClip);
Chris@377 788 CommandHistory::getInstance()->addCommand(command, true);
Chris@64 789 } else {
Chris@377 790 delete command;
Chris@64 791 // restore in case we mucked about with the configuration
Chris@64 792 // as a consequence of signals from the dialog
Chris@769 793 params->setPlayClipId(clip);
Chris@63 794 }
Chris@63 795
Chris@63 796 delete dialog;
Chris@63 797 }
Chris@63 798
Chris@64 799 void
Chris@769 800 PropertyBox::playClipChanged(QString id)
Chris@64 801 {
Chris@64 802 PlayParameters *params = m_container->getPlayParameters();
Chris@64 803 if (!params) return;
Chris@64 804
Chris@769 805 params->setPlayClipId(id);
Chris@64 806 }
Chris@769 807
Chris@185 808 void
Chris@185 809 PropertyBox::layerVisibilityChanged(bool visible)
Chris@185 810 {
Chris@185 811 if (m_showButton) m_showButton->setState(visible);
Chris@185 812 }
Chris@189 813
Chris@189 814 void
Chris@189 815 PropertyBox::mouseEnteredWidget()
Chris@189 816 {
Chris@218 817 updateContextHelp(sender());
Chris@218 818 }
Chris@218 819
Chris@218 820 void
Chris@218 821 PropertyBox::updateContextHelp(QObject *o)
Chris@218 822 {
Chris@218 823 QWidget *w = dynamic_cast<QWidget *>(o);
Chris@189 824 if (!w) return;
Chris@218 825
Chris@189 826 if (!m_container) return;
Chris@190 827 QString cname = m_container->getPropertyContainerName();
Chris@189 828 if (cname == "") return;
Chris@189 829
Chris@189 830 QString wname = w->objectName();
Chris@189 831
Chris@218 832 QString extraText;
Chris@218 833 AudioDial *dial = dynamic_cast<AudioDial *>(w);
Chris@218 834 if (dial) {
Chris@908 835 double mv = dial->mappedValue();
Chris@218 836 QString unit = "";
Chris@218 837 if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit();
Chris@218 838 if (unit != "") {
Chris@218 839 extraText = tr(" (current value: %1%2)").arg(mv).arg(unit);
Chris@218 840 } else {
Chris@218 841 extraText = tr(" (current value: %1)").arg(mv);
Chris@218 842 }
Chris@218 843 }
Chris@218 844
Chris@189 845 if (w == m_showButton) {
Chris@190 846 emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname));
Chris@189 847 } else if (w == m_playButton) {
Chris@190 848 emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname));
Chris@189 849 } else if (wname == "") {
Chris@189 850 return;
Chris@335 851 } else if (dynamic_cast<QAbstractButton *>(w)) {
Chris@190 852 emit contextHelpChanged(tr("Toggle %1 property of %2")
Chris@189 853 .arg(wname).arg(cname));
Chris@189 854 } else {
Chris@218 855 emit contextHelpChanged(tr("Adjust %1 property of %2%3")
Chris@218 856 .arg(wname).arg(cname).arg(extraText));
Chris@189 857 }
Chris@189 858 }
Chris@189 859
Chris@189 860 void
Chris@189 861 PropertyBox::mouseLeftWidget()
Chris@189 862 {
Chris@218 863 if (!(QApplication::mouseButtons() & Qt::LeftButton)) {
Chris@218 864 emit contextHelpChanged("");
Chris@218 865 }
Chris@189 866 }
Chris@189 867
Chris@64 868