annotate widgets/PropertyBox.cpp @ 1160:a429b2acb45d 3.0-integration

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