annotate widgets/PropertyBox.cpp @ 378:22b72f0f6a4e

* More work to abstract out interactive components used in the data library, so that it does not need to depend on QtGui.
author Chris Cannam
date Fri, 14 Mar 2008 17:14:21 +0000
parents 0bcb449d15f4
children e2a40fdadd8c
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@287 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@100 561 blockSignals(true);
Chris@100 562
Chris@100 563 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@100 564 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 565 if (m_container->getPropertyType(properties[i]) ==
Chris@285 566 PropertyContainer::UnitsProperty) {
Chris@285 567 updatePropertyEditor(properties[i]);
Chris@285 568 }
Chris@285 569 }
Chris@285 570
Chris@285 571 blockSignals(false);
Chris@285 572 }
Chris@285 573
Chris@285 574 void
Chris@285 575 PropertyBox::colourDatabaseChanged()
Chris@285 576 {
Chris@285 577 blockSignals(true);
Chris@285 578
Chris@285 579 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@285 580 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 581 if (m_container->getPropertyType(properties[i]) ==
Chris@285 582 PropertyContainer::ColourProperty) {
Chris@285 583 updatePropertyEditor(properties[i], true);
Chris@285 584 }
Chris@100 585 }
Chris@100 586
Chris@100 587 blockSignals(false);
Chris@100 588 }
Chris@100 589
Chris@100 590 void
Chris@335 591 PropertyBox::propertyControllerChanged(bool on)
Chris@335 592 {
Chris@335 593 propertyControllerChanged(on ? 1 : 0);
Chris@335 594 }
Chris@335 595
Chris@335 596 void
Chris@0 597 PropertyBox::propertyControllerChanged(int value)
Chris@0 598 {
Chris@0 599 QObject *obj = sender();
Chris@0 600 QString name = obj->objectName();
Chris@0 601
Chris@34 602 #ifdef DEBUG_PROPERTY_BOX
Chris@33 603 std::cerr << "PropertyBox::propertyControllerChanged(" << name.toStdString()
Chris@33 604 << ", " << value << ")" << std::endl;
Chris@34 605 #endif
Chris@0 606
Chris@0 607 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@100 608
Chris@376 609 Command *c = 0;
Chris@376 610
Chris@100 611 if (type == PropertyContainer::UnitsProperty) {
Chris@285 612
Chris@189 613 NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj);
Chris@100 614 if (cb) {
Chris@100 615 QString unit = cb->currentText();
Chris@376 616 c = m_container->getSetPropertyCommand
Chris@100 617 (name, UnitDatabase::getInstance()->getUnitId(unit));
Chris@100 618 }
Chris@285 619
Chris@285 620 } else if (type == PropertyContainer::ColourProperty) {
Chris@285 621
Chris@285 622 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 623 addNewColour();
Chris@285 624 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 625 propertyContainerPropertyChanged(m_container);
Chris@285 626 return;
Chris@285 627 }
Chris@285 628 }
Chris@376 629 c = m_container->getSetPropertyCommand(name, value);
Chris@285 630
Chris@100 631 } else if (type != PropertyContainer::InvalidProperty) {
Chris@285 632
Chris@376 633 c = m_container->getSetPropertyCommand(name, value);
Chris@0 634 }
Chris@376 635
Chris@376 636 if (c) CommandHistory::getInstance()->addCommand(c, true, true);
Chris@218 637
Chris@218 638 updateContextHelp(obj);
Chris@0 639 }
Chris@285 640
Chris@285 641 void
Chris@285 642 PropertyBox::addNewColour()
Chris@285 643 {
Chris@285 644 QColor newColour = QColorDialog::getColor();
Chris@285 645 if (!newColour.isValid()) return;
Chris@285 646
Chris@285 647 ColourNameDialog dialog(tr("Name New Colour"),
Chris@361 648 tr("Enter a name for the new colour:"),
Chris@361 649 newColour, newColour.name(), this);
Chris@285 650 dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
Chris@285 651 if (dialog.exec() == QDialog::Accepted) {
Chris@285 652 //!!! command
Chris@285 653 ColourDatabase *db = ColourDatabase::getInstance();
Chris@285 654 int index = db->addColour(newColour, dialog.getColourName());
Chris@285 655 db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
Chris@285 656 }
Chris@285 657 }
Chris@377 658
Chris@377 659 void
Chris@377 660 PropertyBox::playAudibleChanged(bool audible)
Chris@377 661 {
Chris@377 662 m_playButton->setState(audible);
Chris@377 663 }
Chris@377 664
Chris@377 665 void
Chris@377 666 PropertyBox::playAudibleButtonChanged(bool audible)
Chris@377 667 {
Chris@377 668 PlayParameters *params = m_container->getPlayParameters();
Chris@377 669 if (!params) return;
Chris@377 670
Chris@377 671 if (params->isPlayAudible() != audible) {
Chris@377 672 PlayParameterRepository::EditCommand *command =
Chris@377 673 new PlayParameterRepository::EditCommand(params);
Chris@377 674 command->setPlayAudible(audible);
Chris@377 675 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 676 }
Chris@377 677 }
Chris@0 678
Chris@34 679 void
Chris@34 680 PropertyBox::playGainChanged(float gain)
Chris@34 681 {
Chris@34 682 int dialValue = lrint(log10(gain) * 20.0);
Chris@34 683 if (dialValue < -50) dialValue = -50;
Chris@34 684 if (dialValue > 50) dialValue = 50;
Chris@34 685 emit changePlayGainDial(dialValue);
Chris@34 686 }
Chris@34 687
Chris@34 688 void
Chris@34 689 PropertyBox::playGainDialChanged(int dialValue)
Chris@34 690 {
Chris@218 691 QObject *obj = sender();
Chris@377 692
Chris@377 693 PlayParameters *params = m_container->getPlayParameters();
Chris@377 694 if (!params) return;
Chris@377 695
Chris@34 696 float gain = pow(10, float(dialValue) / 20.0);
Chris@377 697
Chris@377 698 if (params->getPlayGain() != gain) {
Chris@377 699 PlayParameterRepository::EditCommand *command =
Chris@377 700 new PlayParameterRepository::EditCommand(params);
Chris@377 701 command->setPlayGain(gain);
Chris@377 702 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 703 }
Chris@377 704
Chris@218 705 updateContextHelp(obj);
Chris@34 706 }
Chris@34 707
Chris@34 708 void
Chris@34 709 PropertyBox::playPanChanged(float pan)
Chris@34 710 {
Chris@34 711 int dialValue = lrint(pan * 50.0);
Chris@34 712 if (dialValue < -50) dialValue = -50;
Chris@34 713 if (dialValue > 50) dialValue = 50;
Chris@34 714 emit changePlayPanDial(dialValue);
Chris@34 715 }
Chris@34 716
Chris@34 717 void
Chris@34 718 PropertyBox::playPanDialChanged(int dialValue)
Chris@34 719 {
Chris@218 720 QObject *obj = sender();
Chris@377 721
Chris@377 722 PlayParameters *params = m_container->getPlayParameters();
Chris@377 723 if (!params) return;
Chris@377 724
Chris@34 725 float pan = float(dialValue) / 50.0;
Chris@34 726 if (pan < -1.0) pan = -1.0;
Chris@34 727 if (pan > 1.0) pan = 1.0;
Chris@377 728
Chris@377 729 if (params->getPlayPan() != pan) {
Chris@377 730 PlayParameterRepository::EditCommand *command =
Chris@377 731 new PlayParameterRepository::EditCommand(params);
Chris@377 732 command->setPlayPan(pan);
Chris@377 733 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 734 }
Chris@377 735
Chris@218 736 updateContextHelp(obj);
Chris@34 737 }
Chris@0 738
Chris@63 739 void
Chris@63 740 PropertyBox::editPlugin()
Chris@63 741 {
Chris@63 742 //!!! should probably just emit and let something else do this
Chris@63 743
Chris@63 744 PlayParameters *params = m_container->getPlayParameters();
Chris@63 745 if (!params) return;
Chris@63 746
Chris@63 747 QString pluginId = params->getPlayPluginId();
Chris@63 748 QString configurationXml = params->getPlayPluginConfiguration();
Chris@377 749
Chris@377 750 PlayParameterRepository::EditCommand *command =
Chris@377 751 new PlayParameterRepository::EditCommand(params);
Chris@63 752
Chris@63 753 RealTimePluginFactory *factory =
Chris@63 754 RealTimePluginFactory::instanceFor(pluginId);
Chris@63 755 if (!factory) return;
Chris@63 756
Chris@63 757 RealTimePluginInstance *instance =
Chris@63 758 factory->instantiatePlugin(pluginId, 0, 0, 48000, 1024, 1);
Chris@63 759 if (!instance) return;
Chris@63 760
Chris@71 761 PluginXml(instance).setParametersFromXml(configurationXml);
Chris@63 762
Chris@163 763 PluginParameterDialog *dialog = new PluginParameterDialog(instance);
Chris@64 764 connect(dialog, SIGNAL(pluginConfigurationChanged(QString)),
Chris@64 765 this, SLOT(pluginConfigurationChanged(QString)));
Chris@64 766
Chris@63 767 if (dialog->exec() == QDialog::Accepted) {
Chris@377 768 QString newConfiguration = PluginXml(instance).toXmlString();
Chris@377 769 command->setPlayPluginConfiguration(newConfiguration);
Chris@377 770 CommandHistory::getInstance()->addCommand(command, true);
Chris@64 771 } else {
Chris@377 772 delete command;
Chris@64 773 // restore in case we mucked about with the configuration
Chris@64 774 // as a consequence of signals from the dialog
Chris@64 775 params->setPlayPluginConfiguration(configurationXml);
Chris@63 776 }
Chris@63 777
Chris@63 778 delete dialog;
Chris@63 779 delete instance;
Chris@63 780 }
Chris@63 781
Chris@64 782 void
Chris@64 783 PropertyBox::pluginConfigurationChanged(QString configurationXml)
Chris@64 784 {
Chris@64 785 PlayParameters *params = m_container->getPlayParameters();
Chris@64 786 if (!params) return;
Chris@64 787
Chris@64 788 params->setPlayPluginConfiguration(configurationXml);
Chris@64 789 }
Chris@185 790
Chris@185 791 void
Chris@185 792 PropertyBox::layerVisibilityChanged(bool visible)
Chris@185 793 {
Chris@185 794 if (m_showButton) m_showButton->setState(visible);
Chris@185 795 }
Chris@189 796
Chris@189 797 void
Chris@189 798 PropertyBox::mouseEnteredWidget()
Chris@189 799 {
Chris@218 800 updateContextHelp(sender());
Chris@218 801 }
Chris@218 802
Chris@218 803 void
Chris@218 804 PropertyBox::updateContextHelp(QObject *o)
Chris@218 805 {
Chris@218 806 QWidget *w = dynamic_cast<QWidget *>(o);
Chris@189 807 if (!w) return;
Chris@218 808
Chris@189 809 if (!m_container) return;
Chris@190 810 QString cname = m_container->getPropertyContainerName();
Chris@189 811 if (cname == "") return;
Chris@189 812
Chris@189 813 QString wname = w->objectName();
Chris@189 814
Chris@218 815 QString extraText;
Chris@218 816 AudioDial *dial = dynamic_cast<AudioDial *>(w);
Chris@218 817 if (dial) {
Chris@218 818 float mv = dial->mappedValue();
Chris@218 819 QString unit = "";
Chris@218 820 if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit();
Chris@218 821 if (unit != "") {
Chris@218 822 extraText = tr(" (current value: %1%2)").arg(mv).arg(unit);
Chris@218 823 } else {
Chris@218 824 extraText = tr(" (current value: %1)").arg(mv);
Chris@218 825 }
Chris@218 826 }
Chris@218 827
Chris@189 828 if (w == m_showButton) {
Chris@190 829 emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname));
Chris@189 830 } else if (w == m_playButton) {
Chris@190 831 emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname));
Chris@189 832 } else if (wname == "") {
Chris@189 833 return;
Chris@335 834 } else if (dynamic_cast<QAbstractButton *>(w)) {
Chris@190 835 emit contextHelpChanged(tr("Toggle %1 property of %2")
Chris@189 836 .arg(wname).arg(cname));
Chris@189 837 } else {
Chris@218 838 emit contextHelpChanged(tr("Adjust %1 property of %2%3")
Chris@218 839 .arg(wname).arg(cname).arg(extraText));
Chris@189 840 }
Chris@189 841 }
Chris@189 842
Chris@189 843 void
Chris@189 844 PropertyBox::mouseLeftWidget()
Chris@189 845 {
Chris@218 846 if (!(QApplication::mouseButtons() & Qt::LeftButton)) {
Chris@218 847 emit contextHelpChanged("");
Chris@218 848 }
Chris@189 849 }
Chris@189 850
Chris@64 851