annotate widgets/PropertyBox.cpp @ 454:e2a40fdadd8c

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