annotate widgets/PropertyBox.cpp @ 333:e74b56f07c73

* Some work on correct alignment when moving panes during playback * Overhaul alignment for playback frame values (view manager now always refers to reference-timeline values, only the play source deals in playback model timeline values) * When making a selection, ensure the selection regions shown in other panes (and used for playback constraints if appropriate) are aligned correctly. This may be the coolest feature ever implemented in any program ever.
author Chris Cannam
date Thu, 22 Nov 2007 14:17:19 +0000
parents 3101c68a00c1
children 2f83b6e3b8ca 64e84e5efb76
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@128 21 #include "layer/Layer.h"
Chris@100 22 #include "base/UnitDatabase.h"
Chris@285 23 #include "base/ColourDatabase.h"
Chris@167 24 #include "base/RangeMapper.h"
Chris@0 25
Chris@63 26 #include "plugin/RealTimePluginFactory.h"
Chris@63 27 #include "plugin/RealTimePluginInstance.h"
Chris@71 28 #include "plugin/PluginXml.h"
Chris@63 29
Chris@0 30 #include "AudioDial.h"
Chris@33 31 #include "LEDButton.h"
Chris@0 32
Chris@189 33 #include "NotifyingCheckBox.h"
Chris@189 34 #include "NotifyingComboBox.h"
Chris@285 35 #include "ColourNameDialog.h"
Chris@189 36
Chris@0 37 #include <QGridLayout>
Chris@0 38 #include <QHBoxLayout>
Chris@33 39 #include <QVBoxLayout>
Chris@63 40 #include <QPushButton>
Chris@0 41 #include <QLabel>
Chris@33 42 #include <QFrame>
Chris@218 43 #include <QApplication>
Chris@285 44 #include <QColorDialog>
Chris@285 45 #include <QInputDialog>
Chris@0 46
Chris@0 47 #include <cassert>
Chris@0 48 #include <iostream>
Martin@46 49 #include <cmath>
Chris@0 50
Chris@287 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@0 59 std::cerr << "PropertyBox[" << this << "(\"" <<
Chris@0 60 container->getPropertyContainerName().toStdString() << "\")]::PropertyBox" << std::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@33 79 m_mainWidget->setLayout(m_layout);
Chris@0 80
Chris@34 81 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@0 82
Chris@0 83 blockSignals(true);
Chris@0 84
Chris@0 85 size_t i;
Chris@0 86
Chris@0 87 for (i = 0; i < properties.size(); ++i) {
Chris@0 88 updatePropertyEditor(properties[i]);
Chris@0 89 }
Chris@0 90
Chris@0 91 blockSignals(false);
Chris@0 92
Chris@0 93 m_layout->setRowStretch(m_layout->rowCount(), 10);
Chris@0 94
Chris@100 95 connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()),
Chris@100 96 this, SLOT(unitDatabaseChanged()));
Chris@100 97
Chris@285 98 connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()),
Chris@285 99 this, SLOT(colourDatabaseChanged()));
Chris@285 100
Chris@0 101 #ifdef DEBUG_PROPERTY_BOX
Chris@0 102 std::cerr << "PropertyBox[" << this << "]::PropertyBox returning" << std::endl;
Chris@0 103 #endif
Chris@0 104 }
Chris@0 105
Chris@0 106 PropertyBox::~PropertyBox()
Chris@0 107 {
Chris@0 108 #ifdef DEBUG_PROPERTY_BOX
Chris@33 109 std::cerr << "PropertyBox[" << this << "]::~PropertyBox" << std::endl;
Chris@0 110 #endif
Chris@0 111 }
Chris@0 112
Chris@0 113 void
Chris@34 114 PropertyBox::populateViewPlayFrame()
Chris@33 115 {
Chris@36 116 #ifdef DEBUG_PROPERTY_BOX
Chris@34 117 std::cerr << "PropertyBox(" << m_container << ")::populateViewPlayFrame" << std::endl;
Chris@36 118 #endif
Chris@34 119
Chris@34 120 if (m_viewPlayFrame) {
Chris@34 121 delete m_viewPlayFrame;
Chris@34 122 m_viewPlayFrame = 0;
Chris@34 123 }
Chris@34 124
Chris@34 125 if (!m_container) return;
Chris@34 126
Chris@34 127 Layer *layer = dynamic_cast<Layer *>(m_container);
Chris@34 128 if (layer) {
Chris@193 129 disconnect(layer, SIGNAL(modelReplaced()),
Chris@193 130 this, SLOT(populateViewPlayFrame()));
Chris@34 131 connect(layer, SIGNAL(modelReplaced()),
Chris@34 132 this, SLOT(populateViewPlayFrame()));
Chris@34 133 }
Chris@34 134
Chris@34 135 PlayParameters *params = m_container->getPlayParameters();
Chris@33 136 if (!params && !layer) return;
Chris@33 137
Chris@34 138 m_viewPlayFrame = new QFrame;
Chris@34 139 m_viewPlayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
Chris@34 140 m_mainBox->addWidget(m_viewPlayFrame);
Chris@34 141
Chris@34 142 QHBoxLayout *layout = new QHBoxLayout;
Chris@34 143 m_viewPlayFrame->setLayout(layout);
Chris@34 144
Chris@34 145 layout->setMargin(layout->margin() / 2);
Chris@34 146
Chris@36 147 #ifdef DEBUG_PROPERTY_BOX
Chris@34 148 std::cerr << "PropertyBox::populateViewPlayFrame: container " << m_container << " (name " << m_container->getPropertyContainerName().toStdString() << ") params " << params << std::endl;
Chris@36 149 #endif
Chris@36 150
Chris@33 151 if (layer) {
Chris@34 152 QLabel *showLabel = new QLabel(tr("Show"));
Chris@34 153 layout->addWidget(showLabel);
Chris@34 154 layout->setAlignment(showLabel, Qt::AlignVCenter);
Chris@34 155
Chris@185 156 m_showButton = new LEDButton(Qt::blue);
Chris@185 157 layout->addWidget(m_showButton);
Chris@185 158 connect(m_showButton, SIGNAL(stateChanged(bool)),
Chris@47 159 this, SIGNAL(showLayer(bool)));
Chris@189 160 connect(m_showButton, SIGNAL(mouseEntered()),
Chris@189 161 this, SLOT(mouseEnteredWidget()));
Chris@189 162 connect(m_showButton, SIGNAL(mouseLeft()),
Chris@189 163 this, SLOT(mouseLeftWidget()));
Chris@185 164 layout->setAlignment(m_showButton, Qt::AlignVCenter);
Chris@33 165 }
Chris@33 166
Chris@33 167 if (params) {
Chris@34 168
Chris@34 169 QLabel *playLabel = new QLabel(tr("Play"));
Chris@34 170 layout->addWidget(playLabel);
Chris@34 171 layout->setAlignment(playLabel, Qt::AlignVCenter);
Chris@34 172
Chris@189 173 m_playButton = new LEDButton(Qt::darkGreen);
Chris@189 174 m_playButton->setState(!params->isPlayMuted());
Chris@189 175 layout->addWidget(m_playButton);
Chris@189 176 connect(m_playButton, SIGNAL(stateChanged(bool)),
Chris@33 177 params, SLOT(setPlayAudible(bool)));
Chris@189 178 connect(m_playButton, SIGNAL(mouseEntered()),
Chris@189 179 this, SLOT(mouseEnteredWidget()));
Chris@189 180 connect(m_playButton, SIGNAL(mouseLeft()),
Chris@189 181 this, SLOT(mouseLeftWidget()));
Chris@34 182 connect(params, SIGNAL(playAudibleChanged(bool)),
Chris@189 183 m_playButton, SLOT(setState(bool)));
Chris@189 184 layout->setAlignment(m_playButton, Qt::AlignVCenter);
Chris@34 185
Chris@34 186 layout->insertStretch(-1, 10);
Chris@34 187
Chris@63 188 if (params->getPlayPluginId() != "") {
Chris@64 189 QPushButton *pluginButton = new QPushButton(QIcon(":icons/faders.png"), "");
Chris@64 190 pluginButton->setFixedWidth(24);
Chris@64 191 pluginButton->setFixedHeight(24);
Chris@63 192 layout->addWidget(pluginButton);
Chris@63 193 connect(pluginButton, SIGNAL(clicked()),
Chris@63 194 this, SLOT(editPlugin()));
Chris@63 195 }
Chris@63 196
Chris@34 197 AudioDial *gainDial = new AudioDial;
Chris@34 198 layout->addWidget(gainDial);
Chris@34 199 gainDial->setMeterColor(Qt::darkRed);
Chris@34 200 gainDial->setMinimum(-50);
Chris@34 201 gainDial->setMaximum(50);
Chris@34 202 gainDial->setPageStep(1);
Chris@34 203 gainDial->setFixedWidth(24);
Chris@34 204 gainDial->setFixedHeight(24);
Chris@34 205 gainDial->setNotchesVisible(false);
Chris@34 206 gainDial->setDefaultValue(0);
Chris@168 207 gainDial->setObjectName(tr("Playback Gain"));
Chris@167 208 gainDial->setRangeMapper(new LinearRangeMapper
Chris@167 209 (-50, 50, -25, 25, tr("dB")));
Chris@168 210 gainDial->setShowToolTip(true);
Chris@34 211 connect(gainDial, SIGNAL(valueChanged(int)),
Chris@34 212 this, SLOT(playGainDialChanged(int)));
Chris@34 213 connect(params, SIGNAL(playGainChanged(float)),
Chris@34 214 this, SLOT(playGainChanged(float)));
Chris@34 215 connect(this, SIGNAL(changePlayGain(float)),
Chris@34 216 params, SLOT(setPlayGain(float)));
Chris@34 217 connect(this, SIGNAL(changePlayGainDial(int)),
Chris@34 218 gainDial, SLOT(setValue(int)));
Chris@189 219 connect(gainDial, SIGNAL(mouseEntered()),
Chris@189 220 this, SLOT(mouseEnteredWidget()));
Chris@189 221 connect(gainDial, SIGNAL(mouseLeft()),
Chris@189 222 this, SLOT(mouseLeftWidget()));
Chris@34 223 layout->setAlignment(gainDial, Qt::AlignVCenter);
Chris@34 224
Chris@34 225 AudioDial *panDial = new AudioDial;
Chris@34 226 layout->addWidget(panDial);
Chris@34 227 panDial->setMeterColor(Qt::darkGreen);
Chris@34 228 panDial->setMinimum(-50);
Chris@34 229 panDial->setMaximum(50);
Chris@34 230 panDial->setPageStep(1);
Chris@34 231 panDial->setFixedWidth(24);
Chris@34 232 panDial->setFixedHeight(24);
Chris@34 233 panDial->setNotchesVisible(false);
Chris@57 234 panDial->setToolTip(tr("Playback Pan / Balance"));
Chris@34 235 panDial->setDefaultValue(0);
Chris@168 236 panDial->setObjectName(tr("Playback Pan / Balance"));
Chris@168 237 panDial->setShowToolTip(true);
Chris@34 238 connect(panDial, SIGNAL(valueChanged(int)),
Chris@34 239 this, SLOT(playPanDialChanged(int)));
Chris@34 240 connect(params, SIGNAL(playPanChanged(float)),
Chris@34 241 this, SLOT(playPanChanged(float)));
Chris@34 242 connect(this, SIGNAL(changePlayPan(float)),
Chris@34 243 params, SLOT(setPlayPan(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@34 250 layout->setAlignment(panDial, Qt::AlignVCenter);
Chris@34 251
Chris@34 252 } else {
Chris@34 253
Chris@34 254 layout->insertStretch(-1, 10);
Chris@33 255 }
Chris@33 256 }
Chris@33 257
Chris@33 258 void
Chris@197 259 PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name,
Chris@197 260 bool rangeChanged)
Chris@0 261 {
Chris@0 262 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@0 263 int row = m_layout->rowCount();
Chris@0 264
Chris@216 265 int min = 0, max = 0, value = 0, deflt = 0;
Chris@216 266 value = m_container->getPropertyRangeAndValue(name, &min, &max, &deflt);
Chris@0 267
Chris@0 268 bool have = (m_propertyControllers.find(name) !=
Chris@0 269 m_propertyControllers.end());
Chris@0 270
Chris@0 271 QString groupName = m_container->getPropertyGroupName(name);
Chris@87 272 QString propertyLabel = m_container->getPropertyLabel(name);
Chris@0 273
Chris@0 274 #ifdef DEBUG_PROPERTY_BOX
Chris@0 275 std::cerr << "PropertyBox[" << this
Chris@0 276 << "(\"" << m_container->getPropertyContainerName().toStdString()
Chris@0 277 << "\")]";
Chris@0 278 std::cerr << "::updatePropertyEditor(\"" << name.toStdString() << "\"):";
Chris@0 279 std::cerr << " value " << value << ", have " << have << ", group \""
Chris@0 280 << groupName.toStdString() << "\"" << std::endl;
Chris@0 281 #endif
Chris@0 282
Chris@0 283 bool inGroup = (groupName != QString());
Chris@0 284
Chris@0 285 if (!have) {
Chris@0 286 if (inGroup) {
Chris@0 287 if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) {
Chris@0 288 #ifdef DEBUG_PROPERTY_BOX
Chris@0 289 std::cerr << "PropertyBox: adding label \"" << groupName.toStdString() << "\" and frame for group for \"" << name.toStdString() << "\"" << std::endl;
Chris@0 290 #endif
Chris@33 291 m_layout->addWidget(new QLabel(groupName, m_mainWidget), row, 0);
Chris@33 292 QFrame *frame = new QFrame(m_mainWidget);
Chris@0 293 m_layout->addWidget(frame, row, 1, 1, 2);
Chris@0 294 m_groupLayouts[groupName] = new QHBoxLayout;
Chris@0 295 m_groupLayouts[groupName]->setMargin(0);
Chris@0 296 frame->setLayout(m_groupLayouts[groupName]);
Chris@0 297 }
Chris@0 298 } else {
Chris@0 299 #ifdef DEBUG_PROPERTY_BOX
Chris@87 300 std::cerr << "PropertyBox: adding label \"" << propertyLabel.toStdString() << "\"" << std::endl;
Chris@0 301 #endif
Chris@87 302 m_layout->addWidget(new QLabel(propertyLabel, m_mainWidget), row, 0);
Chris@0 303 }
Chris@0 304 }
Chris@0 305
Chris@0 306 switch (type) {
Chris@0 307
Chris@0 308 case PropertyContainer::ToggleProperty:
Chris@0 309 {
Chris@189 310 NotifyingCheckBox *cb;
Chris@0 311
Chris@0 312 if (have) {
Chris@189 313 cb = dynamic_cast<NotifyingCheckBox *>(m_propertyControllers[name]);
Chris@0 314 assert(cb);
Chris@0 315 } else {
Chris@0 316 #ifdef DEBUG_PROPERTY_BOX
Chris@0 317 std::cerr << "PropertyBox: creating new checkbox" << std::endl;
Chris@0 318 #endif
Chris@189 319 cb = new NotifyingCheckBox();
Chris@0 320 cb->setObjectName(name);
Chris@0 321 connect(cb, SIGNAL(stateChanged(int)),
Chris@0 322 this, SLOT(propertyControllerChanged(int)));
Chris@189 323 connect(cb, SIGNAL(mouseEntered()),
Chris@189 324 this, SLOT(mouseEnteredWidget()));
Chris@189 325 connect(cb, SIGNAL(mouseLeft()),
Chris@189 326 this, SLOT(mouseLeftWidget()));
Chris@0 327 if (inGroup) {
Chris@108 328 cb->setToolTip(propertyLabel);
Chris@0 329 m_groupLayouts[groupName]->addWidget(cb);
Chris@0 330 } else {
Chris@0 331 m_layout->addWidget(cb, row, 1, 1, 2);
Chris@0 332 }
Chris@0 333 m_propertyControllers[name] = cb;
Chris@0 334 }
Chris@0 335
Chris@55 336 if (cb->isChecked() != (value > 0)) {
Chris@55 337 cb->blockSignals(true);
Chris@55 338 cb->setChecked(value > 0);
Chris@55 339 cb->blockSignals(false);
Chris@55 340 }
Chris@0 341 break;
Chris@0 342 }
Chris@0 343
Chris@0 344 case PropertyContainer::RangeProperty:
Chris@0 345 {
Chris@0 346 AudioDial *dial;
Chris@0 347
Chris@0 348 if (have) {
Chris@0 349 dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]);
Chris@0 350 assert(dial);
Chris@197 351 if (rangeChanged) {
Chris@197 352 dial->blockSignals(true);
Chris@197 353 dial->setMinimum(min);
Chris@197 354 dial->setMaximum(max);
Chris@197 355 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
Chris@197 356 dial->blockSignals(false);
Chris@197 357 }
Chris@197 358
Chris@0 359 } else {
Chris@0 360 #ifdef DEBUG_PROPERTY_BOX
Chris@0 361 std::cerr << "PropertyBox: creating new dial" << std::endl;
Chris@0 362 #endif
Chris@0 363 dial = new AudioDial();
Chris@0 364 dial->setObjectName(name);
Chris@0 365 dial->setMinimum(min);
Chris@0 366 dial->setMaximum(max);
Chris@0 367 dial->setPageStep(1);
Chris@34 368 dial->setNotchesVisible((max - min) <= 12);
Chris@216 369 dial->setDefaultValue(deflt);
Chris@167 370 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
Chris@168 371 dial->setShowToolTip(true);
Chris@0 372 connect(dial, SIGNAL(valueChanged(int)),
Chris@0 373 this, SLOT(propertyControllerChanged(int)));
Chris@189 374 connect(dial, SIGNAL(mouseEntered()),
Chris@189 375 this, SLOT(mouseEnteredWidget()));
Chris@189 376 connect(dial, SIGNAL(mouseLeft()),
Chris@189 377 this, SLOT(mouseLeftWidget()));
Chris@0 378
Chris@0 379 if (inGroup) {
Chris@0 380 dial->setFixedWidth(24);
Chris@0 381 dial->setFixedHeight(24);
Chris@0 382 m_groupLayouts[groupName]->addWidget(dial);
Chris@0 383 } else {
Chris@0 384 dial->setFixedWidth(32);
Chris@0 385 dial->setFixedHeight(32);
Chris@0 386 m_layout->addWidget(dial, row, 1);
Chris@33 387 QLabel *label = new QLabel(m_mainWidget);
Chris@0 388 connect(dial, SIGNAL(valueChanged(int)),
Chris@0 389 label, SLOT(setNum(int)));
Chris@0 390 label->setNum(value);
Chris@0 391 m_layout->addWidget(label, row, 2);
Chris@0 392 }
Chris@0 393
Chris@0 394 m_propertyControllers[name] = dial;
Chris@0 395 }
Chris@0 396
Chris@55 397 if (dial->value() != value) {
Chris@55 398 dial->blockSignals(true);
Chris@55 399 dial->setValue(value);
Chris@55 400 dial->blockSignals(false);
Chris@55 401 }
Chris@0 402 break;
Chris@0 403 }
Chris@0 404
Chris@0 405 case PropertyContainer::ValueProperty:
Chris@100 406 case PropertyContainer::UnitsProperty:
Chris@285 407 case PropertyContainer::ColourProperty:
Chris@0 408 {
Chris@189 409 NotifyingComboBox *cb;
Chris@0 410
Chris@0 411 if (have) {
Chris@189 412 cb = dynamic_cast<NotifyingComboBox *>(m_propertyControllers[name]);
Chris@0 413 assert(cb);
Chris@0 414 } else {
Chris@0 415 #ifdef DEBUG_PROPERTY_BOX
Chris@0 416 std::cerr << "PropertyBox: creating new combobox" << std::endl;
Chris@0 417 #endif
Chris@0 418
Chris@189 419 cb = new NotifyingComboBox();
Chris@0 420 cb->setObjectName(name);
Chris@100 421 cb->setDuplicatesEnabled(false);
Chris@197 422 }
Chris@100 423
Chris@197 424 if (!have || rangeChanged) {
Chris@285 425
Chris@197 426 cb->blockSignals(true);
Chris@197 427 cb->clear();
Chris@285 428 cb->setEditable(false);
Chris@285 429
Chris@100 430 if (type == PropertyContainer::ValueProperty) {
Chris@285 431
Chris@100 432 for (int i = min; i <= max; ++i) {
Chris@100 433 cb->addItem(m_container->getPropertyValueLabel(name, i));
Chris@100 434 }
Chris@285 435
Chris@285 436 } else if (type == PropertyContainer::UnitsProperty) {
Chris@285 437
Chris@100 438 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
Chris@100 439 for (int i = 0; i < units.size(); ++i) {
Chris@100 440 cb->addItem(units[i]);
Chris@100 441 }
Chris@285 442
Chris@100 443 cb->setEditable(true);
Chris@285 444
Chris@285 445 } else { // ColourProperty
Chris@290 446
Chris@290 447 //!!! should be a proper colour combobox class that
Chris@290 448 // manages its own Add New Colour entry...
Chris@285 449
Chris@285 450 ColourDatabase *db = ColourDatabase::getInstance();
Chris@285 451 for (size_t i = 0; i < db->getColourCount(); ++i) {
Chris@285 452 QString name = db->getColourName(i);
Chris@287 453 cb->addItem(db->getExamplePixmap(i, QSize(12, 12)), name);
Chris@285 454 }
Chris@285 455 cb->addItem(tr("Add New Colour..."));
Chris@285 456 }
Chris@285 457
Chris@197 458 cb->blockSignals(false);
Chris@280 459 if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) {
Chris@280 460 cb->setMaxVisibleItems(cb->count());
Chris@280 461 }
Chris@197 462 }
Chris@100 463
Chris@197 464 if (!have) {
Chris@0 465 connect(cb, SIGNAL(activated(int)),
Chris@0 466 this, SLOT(propertyControllerChanged(int)));
Chris@189 467 connect(cb, SIGNAL(mouseEntered()),
Chris@189 468 this, SLOT(mouseEnteredWidget()));
Chris@189 469 connect(cb, SIGNAL(mouseLeft()),
Chris@189 470 this, SLOT(mouseLeftWidget()));
Chris@100 471
Chris@0 472 if (inGroup) {
Chris@108 473 cb->setToolTip(propertyLabel);
Chris@0 474 m_groupLayouts[groupName]->addWidget(cb);
Chris@0 475 } else {
Chris@0 476 m_layout->addWidget(cb, row, 1, 1, 2);
Chris@0 477 }
Chris@0 478 m_propertyControllers[name] = cb;
Chris@0 479 }
Chris@0 480
Chris@100 481 cb->blockSignals(true);
Chris@285 482 if (type == PropertyContainer::ValueProperty ||
Chris@285 483 type == PropertyContainer::ColourProperty) {
Chris@100 484 if (cb->currentIndex() != value) {
Chris@100 485 cb->setCurrentIndex(value);
Chris@100 486 }
Chris@100 487 } else {
Chris@100 488 QString unit = UnitDatabase::getInstance()->getUnitById(value);
Chris@100 489 if (cb->currentText() != unit) {
Chris@100 490 for (int i = 0; i < cb->count(); ++i) {
Chris@100 491 if (cb->itemText(i) == unit) {
Chris@100 492 cb->setCurrentIndex(i);
Chris@100 493 break;
Chris@100 494 }
Chris@100 495 }
Chris@100 496 }
Chris@100 497 }
Chris@100 498 cb->blockSignals(false);
Chris@0 499
Chris@0 500 #ifdef Q_WS_MAC
Chris@0 501 // Crashes on startup without this, for some reason
Chris@0 502 cb->setMinimumSize(QSize(10, 10));
Chris@0 503 #endif
Chris@0 504
Chris@0 505 break;
Chris@0 506 }
Chris@0 507
Chris@0 508 default:
Chris@0 509 break;
Chris@0 510 }
Chris@0 511 }
Chris@0 512
Chris@0 513 void
Chris@0 514 PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 515 {
Chris@0 516 if (pc != m_container) return;
Chris@0 517
Chris@55 518 #ifdef DEBUG_PROPERTY_BOX
Chris@55 519 std::cerr << "PropertyBox::propertyContainerPropertyChanged" << std::endl;
Chris@55 520 #endif
Chris@55 521
Chris@0 522 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@0 523 size_t i;
Chris@0 524
Chris@0 525 blockSignals(true);
Chris@0 526
Chris@0 527 for (i = 0; i < properties.size(); ++i) {
Chris@0 528 updatePropertyEditor(properties[i]);
Chris@0 529 }
Chris@0 530
Chris@0 531 blockSignals(false);
Chris@0 532 }
Chris@0 533
Chris@0 534 void
Chris@249 535 PropertyBox::propertyContainerPropertyRangeChanged(PropertyContainer *)
Chris@197 536 {
Chris@197 537 blockSignals(true);
Chris@197 538
Chris@197 539 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@197 540 for (size_t i = 0; i < properties.size(); ++i) {
Chris@197 541 updatePropertyEditor(properties[i], true);
Chris@197 542 }
Chris@197 543
Chris@197 544 blockSignals(false);
Chris@197 545 }
Chris@197 546
Chris@197 547 void
Chris@100 548 PropertyBox::unitDatabaseChanged()
Chris@100 549 {
Chris@100 550 blockSignals(true);
Chris@100 551
Chris@100 552 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@100 553 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 554 if (m_container->getPropertyType(properties[i]) ==
Chris@285 555 PropertyContainer::UnitsProperty) {
Chris@285 556 updatePropertyEditor(properties[i]);
Chris@285 557 }
Chris@285 558 }
Chris@285 559
Chris@285 560 blockSignals(false);
Chris@285 561 }
Chris@285 562
Chris@285 563 void
Chris@285 564 PropertyBox::colourDatabaseChanged()
Chris@285 565 {
Chris@285 566 blockSignals(true);
Chris@285 567
Chris@285 568 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@285 569 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 570 if (m_container->getPropertyType(properties[i]) ==
Chris@285 571 PropertyContainer::ColourProperty) {
Chris@285 572 updatePropertyEditor(properties[i], true);
Chris@285 573 }
Chris@100 574 }
Chris@100 575
Chris@100 576 blockSignals(false);
Chris@100 577 }
Chris@100 578
Chris@100 579 void
Chris@0 580 PropertyBox::propertyControllerChanged(int value)
Chris@0 581 {
Chris@0 582 QObject *obj = sender();
Chris@0 583 QString name = obj->objectName();
Chris@0 584
Chris@34 585 #ifdef DEBUG_PROPERTY_BOX
Chris@33 586 std::cerr << "PropertyBox::propertyControllerChanged(" << name.toStdString()
Chris@33 587 << ", " << value << ")" << std::endl;
Chris@34 588 #endif
Chris@0 589
Chris@0 590 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@100 591
Chris@100 592 if (type == PropertyContainer::UnitsProperty) {
Chris@285 593
Chris@189 594 NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj);
Chris@100 595 if (cb) {
Chris@100 596 QString unit = cb->currentText();
Chris@100 597 m_container->setPropertyWithCommand
Chris@100 598 (name, UnitDatabase::getInstance()->getUnitId(unit));
Chris@100 599 }
Chris@285 600
Chris@285 601 } else if (type == PropertyContainer::ColourProperty) {
Chris@285 602
Chris@285 603 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 604 addNewColour();
Chris@285 605 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 606 propertyContainerPropertyChanged(m_container);
Chris@285 607 return;
Chris@285 608 }
Chris@285 609 }
Chris@285 610 m_container->setPropertyWithCommand(name, value);
Chris@285 611
Chris@100 612 } else if (type != PropertyContainer::InvalidProperty) {
Chris@285 613
Chris@55 614 m_container->setPropertyWithCommand(name, value);
Chris@0 615 }
Chris@218 616
Chris@218 617 updateContextHelp(obj);
Chris@0 618 }
Chris@285 619
Chris@285 620 void
Chris@285 621 PropertyBox::addNewColour()
Chris@285 622 {
Chris@285 623 QColor newColour = QColorDialog::getColor();
Chris@285 624 if (!newColour.isValid()) return;
Chris@285 625
Chris@285 626 ColourNameDialog dialog(tr("Name New Colour"),
Chris@285 627 tr("Enter name for the new colour:"),
Chris@285 628 newColour, "", this);
Chris@285 629 dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
Chris@285 630 if (dialog.exec() == QDialog::Accepted) {
Chris@285 631 //!!! command
Chris@285 632 ColourDatabase *db = ColourDatabase::getInstance();
Chris@285 633 int index = db->addColour(newColour, dialog.getColourName());
Chris@285 634 db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
Chris@285 635 }
Chris@285 636 }
Chris@0 637
Chris@34 638 void
Chris@34 639 PropertyBox::playGainChanged(float gain)
Chris@34 640 {
Chris@34 641 int dialValue = lrint(log10(gain) * 20.0);
Chris@34 642 if (dialValue < -50) dialValue = -50;
Chris@34 643 if (dialValue > 50) dialValue = 50;
Chris@34 644 emit changePlayGainDial(dialValue);
Chris@34 645 }
Chris@34 646
Chris@34 647 void
Chris@34 648 PropertyBox::playGainDialChanged(int dialValue)
Chris@34 649 {
Chris@218 650 QObject *obj = sender();
Chris@34 651 float gain = pow(10, float(dialValue) / 20.0);
Chris@34 652 emit changePlayGain(gain);
Chris@218 653 updateContextHelp(obj);
Chris@34 654 }
Chris@34 655
Chris@34 656 void
Chris@34 657 PropertyBox::playPanChanged(float pan)
Chris@34 658 {
Chris@34 659 int dialValue = lrint(pan * 50.0);
Chris@34 660 if (dialValue < -50) dialValue = -50;
Chris@34 661 if (dialValue > 50) dialValue = 50;
Chris@34 662 emit changePlayPanDial(dialValue);
Chris@34 663 }
Chris@34 664
Chris@34 665 void
Chris@34 666 PropertyBox::playPanDialChanged(int dialValue)
Chris@34 667 {
Chris@218 668 QObject *obj = sender();
Chris@34 669 float pan = float(dialValue) / 50.0;
Chris@34 670 if (pan < -1.0) pan = -1.0;
Chris@34 671 if (pan > 1.0) pan = 1.0;
Chris@34 672 emit changePlayPan(pan);
Chris@218 673 updateContextHelp(obj);
Chris@34 674 }
Chris@0 675
Chris@63 676 void
Chris@63 677 PropertyBox::editPlugin()
Chris@63 678 {
Chris@63 679 //!!! should probably just emit and let something else do this
Chris@63 680
Chris@63 681 PlayParameters *params = m_container->getPlayParameters();
Chris@63 682 if (!params) return;
Chris@63 683
Chris@63 684 QString pluginId = params->getPlayPluginId();
Chris@63 685 QString configurationXml = params->getPlayPluginConfiguration();
Chris@63 686
Chris@63 687 RealTimePluginFactory *factory =
Chris@63 688 RealTimePluginFactory::instanceFor(pluginId);
Chris@63 689 if (!factory) return;
Chris@63 690
Chris@63 691 RealTimePluginInstance *instance =
Chris@63 692 factory->instantiatePlugin(pluginId, 0, 0, 48000, 1024, 1);
Chris@63 693 if (!instance) return;
Chris@63 694
Chris@71 695 PluginXml(instance).setParametersFromXml(configurationXml);
Chris@63 696
Chris@163 697 PluginParameterDialog *dialog = new PluginParameterDialog(instance);
Chris@64 698 connect(dialog, SIGNAL(pluginConfigurationChanged(QString)),
Chris@64 699 this, SLOT(pluginConfigurationChanged(QString)));
Chris@64 700
Chris@63 701 if (dialog->exec() == QDialog::Accepted) {
Chris@71 702 params->setPlayPluginConfiguration(PluginXml(instance).toXmlString());
Chris@64 703 } else {
Chris@64 704 // restore in case we mucked about with the configuration
Chris@64 705 // as a consequence of signals from the dialog
Chris@64 706 params->setPlayPluginConfiguration(configurationXml);
Chris@63 707 }
Chris@63 708
Chris@63 709 delete dialog;
Chris@63 710 delete instance;
Chris@63 711 }
Chris@63 712
Chris@64 713 void
Chris@64 714 PropertyBox::pluginConfigurationChanged(QString configurationXml)
Chris@64 715 {
Chris@64 716 PlayParameters *params = m_container->getPlayParameters();
Chris@64 717 if (!params) return;
Chris@64 718
Chris@64 719 params->setPlayPluginConfiguration(configurationXml);
Chris@64 720 }
Chris@185 721
Chris@185 722 void
Chris@185 723 PropertyBox::layerVisibilityChanged(bool visible)
Chris@185 724 {
Chris@185 725 if (m_showButton) m_showButton->setState(visible);
Chris@185 726 }
Chris@189 727
Chris@189 728 void
Chris@189 729 PropertyBox::mouseEnteredWidget()
Chris@189 730 {
Chris@218 731 updateContextHelp(sender());
Chris@218 732 }
Chris@218 733
Chris@218 734 void
Chris@218 735 PropertyBox::updateContextHelp(QObject *o)
Chris@218 736 {
Chris@218 737 QWidget *w = dynamic_cast<QWidget *>(o);
Chris@189 738 if (!w) return;
Chris@218 739
Chris@189 740 if (!m_container) return;
Chris@190 741 QString cname = m_container->getPropertyContainerName();
Chris@189 742 if (cname == "") return;
Chris@189 743
Chris@189 744 QString wname = w->objectName();
Chris@189 745
Chris@218 746 QString extraText;
Chris@218 747 AudioDial *dial = dynamic_cast<AudioDial *>(w);
Chris@218 748 if (dial) {
Chris@218 749 float mv = dial->mappedValue();
Chris@218 750 QString unit = "";
Chris@218 751 if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit();
Chris@218 752 if (unit != "") {
Chris@218 753 extraText = tr(" (current value: %1%2)").arg(mv).arg(unit);
Chris@218 754 } else {
Chris@218 755 extraText = tr(" (current value: %1)").arg(mv);
Chris@218 756 }
Chris@218 757 }
Chris@218 758
Chris@189 759 if (w == m_showButton) {
Chris@190 760 emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname));
Chris@189 761 } else if (w == m_playButton) {
Chris@190 762 emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname));
Chris@189 763 } else if (wname == "") {
Chris@189 764 return;
Chris@189 765 } else if (dynamic_cast<NotifyingCheckBox *>(w)) {
Chris@190 766 emit contextHelpChanged(tr("Toggle %1 property of %2")
Chris@189 767 .arg(wname).arg(cname));
Chris@189 768 } else {
Chris@218 769 emit contextHelpChanged(tr("Adjust %1 property of %2%3")
Chris@218 770 .arg(wname).arg(cname).arg(extraText));
Chris@189 771 }
Chris@189 772 }
Chris@189 773
Chris@189 774 void
Chris@189 775 PropertyBox::mouseLeftWidget()
Chris@189 776 {
Chris@218 777 if (!(QApplication::mouseButtons() & Qt::LeftButton)) {
Chris@218 778 emit contextHelpChanged("");
Chris@218 779 }
Chris@189 780 }
Chris@189 781
Chris@64 782