annotate widgets/PropertyBox.cpp @ 1024:3bce4c45b681 spectrogram-minor-refactor

Rearrange cache update calculations so as to use the actual painted width returned by paint functions (though they only ever return the same width as requested, at this point)
author Chris Cannam
date Mon, 25 Jan 2016 15:52:26 +0000
parents 3f7cdfc56dce
children c02c51ae5238 5c3333fb70b3
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@34 215 gainDial->setDefaultValue(0);
Chris@168 216 gainDial->setObjectName(tr("Playback Gain"));
Chris@167 217 gainDial->setRangeMapper(new LinearRangeMapper
Chris@167 218 (-50, 50, -25, 25, tr("dB")));
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@216 387 dial->setDefaultValue(deflt);
Chris@167 388 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
Chris@168 389 dial->setShowToolTip(true);
Chris@0 390 connect(dial, SIGNAL(valueChanged(int)),
Chris@0 391 this, SLOT(propertyControllerChanged(int)));
Chris@189 392 connect(dial, SIGNAL(mouseEntered()),
Chris@189 393 this, SLOT(mouseEnteredWidget()));
Chris@189 394 connect(dial, SIGNAL(mouseLeft()),
Chris@189 395 this, SLOT(mouseLeftWidget()));
Chris@0 396
Chris@0 397 if (inGroup) {
Chris@0 398 dial->setFixedWidth(24);
Chris@0 399 dial->setFixedHeight(24);
Chris@493 400 m_groupLayouts[groupName]->addWidget
Chris@493 401 (dial, 0, m_groupLayouts[groupName]->columnCount());
Chris@0 402 } else {
Chris@0 403 dial->setFixedWidth(32);
Chris@0 404 dial->setFixedHeight(32);
Chris@0 405 m_layout->addWidget(dial, row, 1);
Chris@33 406 QLabel *label = new QLabel(m_mainWidget);
Chris@0 407 connect(dial, SIGNAL(valueChanged(int)),
Chris@0 408 label, SLOT(setNum(int)));
Chris@0 409 label->setNum(value);
Chris@0 410 m_layout->addWidget(label, row, 2);
Chris@0 411 }
Chris@0 412
Chris@0 413 m_propertyControllers[name] = dial;
Chris@0 414 }
Chris@0 415
Chris@55 416 if (dial->value() != value) {
Chris@55 417 dial->blockSignals(true);
Chris@55 418 dial->setValue(value);
Chris@55 419 dial->blockSignals(false);
Chris@55 420 }
Chris@0 421 break;
Chris@0 422 }
Chris@0 423
Chris@0 424 case PropertyContainer::ValueProperty:
Chris@100 425 case PropertyContainer::UnitsProperty:
Chris@285 426 case PropertyContainer::ColourProperty:
Chris@0 427 {
Chris@189 428 NotifyingComboBox *cb;
Chris@0 429
Chris@0 430 if (have) {
Chris@189 431 cb = dynamic_cast<NotifyingComboBox *>(m_propertyControllers[name]);
Chris@0 432 assert(cb);
Chris@0 433 } else {
Chris@0 434 #ifdef DEBUG_PROPERTY_BOX
Chris@682 435 cerr << "PropertyBox: creating new combobox" << endl;
Chris@0 436 #endif
Chris@0 437
Chris@189 438 cb = new NotifyingComboBox();
Chris@0 439 cb->setObjectName(name);
Chris@100 440 cb->setDuplicatesEnabled(false);
Chris@197 441 }
Chris@100 442
Chris@197 443 if (!have || rangeChanged) {
Chris@285 444
Chris@197 445 cb->blockSignals(true);
Chris@197 446 cb->clear();
Chris@285 447 cb->setEditable(false);
Chris@285 448
Chris@100 449 if (type == PropertyContainer::ValueProperty) {
Chris@285 450
Chris@100 451 for (int i = min; i <= max; ++i) {
Chris@862 452
Chris@862 453 QString label = m_container->getPropertyValueLabel(name, i);
Chris@862 454 QString iname = m_container->getPropertyValueIconName(name, i);
Chris@862 455
Chris@862 456 if (iname != "") {
Chris@862 457 QIcon icon(IconLoader().load(iname));
Chris@862 458 cb->addItem(icon, label);
Chris@862 459 } else {
Chris@862 460 cb->addItem(label);
Chris@862 461 }
Chris@100 462 }
Chris@285 463
Chris@285 464 } else if (type == PropertyContainer::UnitsProperty) {
Chris@285 465
Chris@100 466 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
Chris@100 467 for (int i = 0; i < units.size(); ++i) {
Chris@100 468 cb->addItem(units[i]);
Chris@100 469 }
Chris@285 470
Chris@100 471 cb->setEditable(true);
Chris@285 472
Chris@285 473 } else { // ColourProperty
Chris@290 474
Chris@290 475 //!!! should be a proper colour combobox class that
Chris@290 476 // manages its own Add New Colour entry...
Chris@285 477
Chris@285 478 ColourDatabase *db = ColourDatabase::getInstance();
Chris@769 479 for (int i = 0; i < db->getColourCount(); ++i) {
Chris@285 480 QString name = db->getColourName(i);
Chris@287 481 cb->addItem(db->getExamplePixmap(i, QSize(12, 12)), name);
Chris@285 482 }
Chris@285 483 cb->addItem(tr("Add New Colour..."));
Chris@285 484 }
Chris@285 485
Chris@197 486 cb->blockSignals(false);
Chris@280 487 if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) {
Chris@280 488 cb->setMaxVisibleItems(cb->count());
Chris@280 489 }
Chris@197 490 }
Chris@100 491
Chris@197 492 if (!have) {
Chris@0 493 connect(cb, SIGNAL(activated(int)),
Chris@0 494 this, SLOT(propertyControllerChanged(int)));
Chris@189 495 connect(cb, SIGNAL(mouseEntered()),
Chris@189 496 this, SLOT(mouseEnteredWidget()));
Chris@189 497 connect(cb, SIGNAL(mouseLeft()),
Chris@189 498 this, SLOT(mouseLeftWidget()));
Chris@100 499
Chris@0 500 if (inGroup) {
Chris@108 501 cb->setToolTip(propertyLabel);
Chris@493 502 m_groupLayouts[groupName]->addWidget
Chris@493 503 (cb, 0, m_groupLayouts[groupName]->columnCount());
Chris@0 504 } else {
Chris@0 505 m_layout->addWidget(cb, row, 1, 1, 2);
Chris@0 506 }
Chris@0 507 m_propertyControllers[name] = cb;
Chris@0 508 }
Chris@0 509
Chris@100 510 cb->blockSignals(true);
Chris@285 511 if (type == PropertyContainer::ValueProperty ||
Chris@285 512 type == PropertyContainer::ColourProperty) {
Chris@100 513 if (cb->currentIndex() != value) {
Chris@100 514 cb->setCurrentIndex(value);
Chris@100 515 }
Chris@100 516 } else {
Chris@100 517 QString unit = UnitDatabase::getInstance()->getUnitById(value);
Chris@100 518 if (cb->currentText() != unit) {
Chris@100 519 for (int i = 0; i < cb->count(); ++i) {
Chris@100 520 if (cb->itemText(i) == unit) {
Chris@100 521 cb->setCurrentIndex(i);
Chris@100 522 break;
Chris@100 523 }
Chris@100 524 }
Chris@100 525 }
Chris@100 526 }
Chris@100 527 cb->blockSignals(false);
Chris@0 528
Chris@681 529 #ifdef Q_OS_MAC
Chris@982 530 // Crashes on startup without this, for some reason; also
Chris@982 531 // prevents combo boxes from getting weirdly squished
Chris@982 532 // vertically
Chris@982 533 cb->setMinimumSize(QSize(10, cb->font().pixelSize() * 2));
Chris@0 534 #endif
Chris@0 535
Chris@0 536 break;
Chris@0 537 }
Chris@0 538
Chris@807 539 case PropertyContainer::InvalidProperty:
Chris@0 540 default:
Chris@0 541 break;
Chris@0 542 }
Chris@0 543 }
Chris@0 544
Chris@0 545 void
Chris@0 546 PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 547 {
Chris@0 548 if (pc != m_container) return;
Chris@0 549
Chris@55 550 #ifdef DEBUG_PROPERTY_BOX
Chris@587 551 SVDEBUG << "PropertyBox::propertyContainerPropertyChanged" << endl;
Chris@55 552 #endif
Chris@55 553
Chris@0 554 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@0 555 size_t i;
Chris@0 556
Chris@0 557 blockSignals(true);
Chris@0 558
Chris@0 559 for (i = 0; i < properties.size(); ++i) {
Chris@0 560 updatePropertyEditor(properties[i]);
Chris@0 561 }
Chris@0 562
Chris@0 563 blockSignals(false);
Chris@0 564 }
Chris@0 565
Chris@0 566 void
Chris@249 567 PropertyBox::propertyContainerPropertyRangeChanged(PropertyContainer *)
Chris@197 568 {
Chris@197 569 blockSignals(true);
Chris@197 570
Chris@197 571 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@197 572 for (size_t i = 0; i < properties.size(); ++i) {
Chris@197 573 updatePropertyEditor(properties[i], true);
Chris@197 574 }
Chris@197 575
Chris@197 576 blockSignals(false);
Chris@197 577 }
Chris@197 578
Chris@197 579 void
Chris@100 580 PropertyBox::unitDatabaseChanged()
Chris@100 581 {
Chris@729 582 #ifdef DEBUG_PROPERTY_BOX
Chris@682 583 cerr << "PropertyBox[" << this << "]: unitDatabaseChanged" << endl;
Chris@729 584 #endif
Chris@100 585 blockSignals(true);
Chris@100 586
Chris@682 587 // cerr << "my container is " << m_container << endl;
Chris@682 588 // cerr << "my container's name is... " << endl;
Chris@682 589 // cerr << m_container->objectName() << endl;
Chris@456 590
Chris@100 591 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@100 592 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 593 if (m_container->getPropertyType(properties[i]) ==
Chris@285 594 PropertyContainer::UnitsProperty) {
Chris@285 595 updatePropertyEditor(properties[i]);
Chris@285 596 }
Chris@285 597 }
Chris@285 598
Chris@285 599 blockSignals(false);
Chris@285 600 }
Chris@285 601
Chris@285 602 void
Chris@285 603 PropertyBox::colourDatabaseChanged()
Chris@285 604 {
Chris@285 605 blockSignals(true);
Chris@285 606
Chris@285 607 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@285 608 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 609 if (m_container->getPropertyType(properties[i]) ==
Chris@285 610 PropertyContainer::ColourProperty) {
Chris@285 611 updatePropertyEditor(properties[i], true);
Chris@285 612 }
Chris@100 613 }
Chris@100 614
Chris@100 615 blockSignals(false);
Chris@100 616 }
Chris@100 617
Chris@100 618 void
Chris@335 619 PropertyBox::propertyControllerChanged(bool on)
Chris@335 620 {
Chris@335 621 propertyControllerChanged(on ? 1 : 0);
Chris@335 622 }
Chris@335 623
Chris@335 624 void
Chris@0 625 PropertyBox::propertyControllerChanged(int value)
Chris@0 626 {
Chris@0 627 QObject *obj = sender();
Chris@0 628 QString name = obj->objectName();
Chris@0 629
Chris@34 630 #ifdef DEBUG_PROPERTY_BOX
Chris@587 631 SVDEBUG << "PropertyBox::propertyControllerChanged(" << name << ", " << value << ")" << endl;
Chris@34 632 #endif
Chris@0 633
Chris@0 634 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@100 635
Chris@376 636 Command *c = 0;
Chris@376 637
Chris@100 638 if (type == PropertyContainer::UnitsProperty) {
Chris@285 639
Chris@189 640 NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj);
Chris@100 641 if (cb) {
Chris@100 642 QString unit = cb->currentText();
Chris@376 643 c = m_container->getSetPropertyCommand
Chris@100 644 (name, UnitDatabase::getInstance()->getUnitId(unit));
Chris@100 645 }
Chris@285 646
Chris@285 647 } else if (type == PropertyContainer::ColourProperty) {
Chris@285 648
Chris@285 649 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 650 addNewColour();
Chris@285 651 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 652 propertyContainerPropertyChanged(m_container);
Chris@285 653 return;
Chris@285 654 }
Chris@285 655 }
Chris@376 656 c = m_container->getSetPropertyCommand(name, value);
Chris@285 657
Chris@100 658 } else if (type != PropertyContainer::InvalidProperty) {
Chris@285 659
Chris@376 660 c = m_container->getSetPropertyCommand(name, value);
Chris@0 661 }
Chris@376 662
Chris@376 663 if (c) CommandHistory::getInstance()->addCommand(c, true, true);
Chris@218 664
Chris@218 665 updateContextHelp(obj);
Chris@0 666 }
Chris@285 667
Chris@285 668 void
Chris@285 669 PropertyBox::addNewColour()
Chris@285 670 {
Chris@285 671 QColor newColour = QColorDialog::getColor();
Chris@285 672 if (!newColour.isValid()) return;
Chris@285 673
Chris@285 674 ColourNameDialog dialog(tr("Name New Colour"),
Chris@361 675 tr("Enter a name for the new colour:"),
Chris@361 676 newColour, newColour.name(), this);
Chris@285 677 dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
Chris@285 678 if (dialog.exec() == QDialog::Accepted) {
Chris@285 679 //!!! command
Chris@285 680 ColourDatabase *db = ColourDatabase::getInstance();
Chris@285 681 int index = db->addColour(newColour, dialog.getColourName());
Chris@285 682 db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
Chris@285 683 }
Chris@285 684 }
Chris@377 685
Chris@377 686 void
Chris@377 687 PropertyBox::playAudibleChanged(bool audible)
Chris@377 688 {
Chris@377 689 m_playButton->setState(audible);
Chris@377 690 }
Chris@377 691
Chris@377 692 void
Chris@377 693 PropertyBox::playAudibleButtonChanged(bool audible)
Chris@377 694 {
Chris@377 695 PlayParameters *params = m_container->getPlayParameters();
Chris@377 696 if (!params) return;
Chris@377 697
Chris@377 698 if (params->isPlayAudible() != audible) {
Chris@377 699 PlayParameterRepository::EditCommand *command =
Chris@377 700 new PlayParameterRepository::EditCommand(params);
Chris@377 701 command->setPlayAudible(audible);
Chris@377 702 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 703 }
Chris@377 704 }
Chris@0 705
Chris@34 706 void
Chris@34 707 PropertyBox::playGainChanged(float gain)
Chris@34 708 {
Chris@908 709 int dialValue = int(lrint(log10(gain) * 20.0));
Chris@34 710 if (dialValue < -50) dialValue = -50;
Chris@34 711 if (dialValue > 50) dialValue = 50;
Chris@34 712 emit changePlayGainDial(dialValue);
Chris@34 713 }
Chris@34 714
Chris@34 715 void
Chris@34 716 PropertyBox::playGainDialChanged(int dialValue)
Chris@34 717 {
Chris@218 718 QObject *obj = sender();
Chris@377 719
Chris@377 720 PlayParameters *params = m_container->getPlayParameters();
Chris@377 721 if (!params) return;
Chris@377 722
Chris@908 723 float gain = float(pow(10, float(dialValue) / 20.0));
Chris@377 724
Chris@377 725 if (params->getPlayGain() != gain) {
Chris@377 726 PlayParameterRepository::EditCommand *command =
Chris@377 727 new PlayParameterRepository::EditCommand(params);
Chris@377 728 command->setPlayGain(gain);
Chris@377 729 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 730 }
Chris@377 731
Chris@218 732 updateContextHelp(obj);
Chris@34 733 }
Chris@34 734
Chris@34 735 void
Chris@34 736 PropertyBox::playPanChanged(float pan)
Chris@34 737 {
Chris@908 738 int dialValue = int(lrint(pan * 50.0));
Chris@34 739 if (dialValue < -50) dialValue = -50;
Chris@34 740 if (dialValue > 50) dialValue = 50;
Chris@34 741 emit changePlayPanDial(dialValue);
Chris@34 742 }
Chris@34 743
Chris@34 744 void
Chris@34 745 PropertyBox::playPanDialChanged(int dialValue)
Chris@34 746 {
Chris@218 747 QObject *obj = sender();
Chris@377 748
Chris@377 749 PlayParameters *params = m_container->getPlayParameters();
Chris@377 750 if (!params) return;
Chris@377 751
Chris@908 752 float pan = float(dialValue) / 50.f;
Chris@908 753 if (pan < -1.f) pan = -1.f;
Chris@908 754 if (pan > 1.f) pan = 1.f;
Chris@377 755
Chris@377 756 if (params->getPlayPan() != pan) {
Chris@377 757 PlayParameterRepository::EditCommand *command =
Chris@377 758 new PlayParameterRepository::EditCommand(params);
Chris@377 759 command->setPlayPan(pan);
Chris@377 760 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 761 }
Chris@377 762
Chris@218 763 updateContextHelp(obj);
Chris@34 764 }
Chris@769 765
Chris@63 766 void
Chris@769 767 PropertyBox::editPlayParameters()
Chris@63 768 {
Chris@63 769 PlayParameters *params = m_container->getPlayParameters();
Chris@63 770 if (!params) return;
Chris@63 771
Chris@769 772 QString clip = params->getPlayClipId();
Chris@377 773
Chris@377 774 PlayParameterRepository::EditCommand *command =
Chris@377 775 new PlayParameterRepository::EditCommand(params);
Chris@63 776
Chris@769 777 QInputDialog *dialog = new QInputDialog(this);
Chris@63 778
Chris@769 779 QDir dir(":/samples");
Chris@769 780 QStringList clipFiles = dir.entryList(QStringList() << "*.wav", QDir::Files);
Chris@63 781
Chris@769 782 QStringList clips;
Chris@769 783 foreach (QString str, clipFiles) {
Chris@769 784 clips.push_back(str.replace(".wav", ""));
Chris@769 785 }
Chris@769 786 dialog->setComboBoxItems(clips);
Chris@63 787
Chris@769 788 dialog->setLabelText(tr("Set playback clip:"));
Chris@769 789
Chris@769 790 QComboBox *cb = dialog->findChild<QComboBox *>();
Chris@779 791 if (cb) {
Chris@779 792 for (int i = 0; i < cb->count(); ++i) {
Chris@779 793 if (cb->itemText(i) == clip) {
Chris@779 794 cb->setCurrentIndex(i);
Chris@779 795 }
Chris@779 796 }
Chris@779 797 }
Chris@769 798
Chris@769 799 connect(dialog, SIGNAL(textValueChanged(QString)),
Chris@769 800 this, SLOT(playClipChanged(QString)));
Chris@64 801
Chris@63 802 if (dialog->exec() == QDialog::Accepted) {
Chris@769 803 QString newClip = dialog->textValue();
Chris@769 804 command->setPlayClipId(newClip);
Chris@377 805 CommandHistory::getInstance()->addCommand(command, true);
Chris@64 806 } else {
Chris@377 807 delete command;
Chris@64 808 // restore in case we mucked about with the configuration
Chris@64 809 // as a consequence of signals from the dialog
Chris@769 810 params->setPlayClipId(clip);
Chris@63 811 }
Chris@63 812
Chris@63 813 delete dialog;
Chris@63 814 }
Chris@63 815
Chris@64 816 void
Chris@769 817 PropertyBox::playClipChanged(QString id)
Chris@64 818 {
Chris@64 819 PlayParameters *params = m_container->getPlayParameters();
Chris@64 820 if (!params) return;
Chris@64 821
Chris@769 822 params->setPlayClipId(id);
Chris@64 823 }
Chris@769 824
Chris@185 825 void
Chris@185 826 PropertyBox::layerVisibilityChanged(bool visible)
Chris@185 827 {
Chris@185 828 if (m_showButton) m_showButton->setState(visible);
Chris@185 829 }
Chris@189 830
Chris@189 831 void
Chris@189 832 PropertyBox::mouseEnteredWidget()
Chris@189 833 {
Chris@218 834 updateContextHelp(sender());
Chris@218 835 }
Chris@218 836
Chris@218 837 void
Chris@218 838 PropertyBox::updateContextHelp(QObject *o)
Chris@218 839 {
Chris@218 840 QWidget *w = dynamic_cast<QWidget *>(o);
Chris@189 841 if (!w) return;
Chris@218 842
Chris@189 843 if (!m_container) return;
Chris@190 844 QString cname = m_container->getPropertyContainerName();
Chris@189 845 if (cname == "") return;
Chris@189 846
Chris@189 847 QString wname = w->objectName();
Chris@189 848
Chris@218 849 QString extraText;
Chris@218 850 AudioDial *dial = dynamic_cast<AudioDial *>(w);
Chris@218 851 if (dial) {
Chris@908 852 double mv = dial->mappedValue();
Chris@218 853 QString unit = "";
Chris@218 854 if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit();
Chris@218 855 if (unit != "") {
Chris@218 856 extraText = tr(" (current value: %1%2)").arg(mv).arg(unit);
Chris@218 857 } else {
Chris@218 858 extraText = tr(" (current value: %1)").arg(mv);
Chris@218 859 }
Chris@218 860 }
Chris@218 861
Chris@189 862 if (w == m_showButton) {
Chris@190 863 emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname));
Chris@189 864 } else if (w == m_playButton) {
Chris@190 865 emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname));
Chris@189 866 } else if (wname == "") {
Chris@189 867 return;
Chris@335 868 } else if (dynamic_cast<QAbstractButton *>(w)) {
Chris@190 869 emit contextHelpChanged(tr("Toggle %1 property of %2")
Chris@189 870 .arg(wname).arg(cname));
Chris@189 871 } else {
Chris@218 872 emit contextHelpChanged(tr("Adjust %1 property of %2%3")
Chris@218 873 .arg(wname).arg(cname).arg(extraText));
Chris@189 874 }
Chris@189 875 }
Chris@189 876
Chris@189 877 void
Chris@189 878 PropertyBox::mouseLeftWidget()
Chris@189 879 {
Chris@218 880 if (!(QApplication::mouseButtons() & Qt::LeftButton)) {
Chris@218 881 emit contextHelpChanged("");
Chris@218 882 }
Chris@189 883 }
Chris@189 884
Chris@64 885