annotate widgets/PropertyBox.cpp @ 349:369a197737c7

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