annotate widgets/PropertyBox.cpp @ 561:aced8ec09bc8

* Complete the overhaul of CSV file import; now you can pick the purpose for each column in the file, and SV should do the rest. The most significant practical improvement here is that we can now handle files in which time and duration do not necessarily appear in known columns.
author Chris Cannam
date Mon, 19 Jul 2010 17:08:56 +0000
parents 4afdcecbd62e
children 1fe7951a61e8
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@456 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@456 63 container->getPropertyContainerName().toStdString() << "\" at " << container << ")]::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@493 296 m_groupLayouts[groupName] = new QGridLayout;
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@493 340 m_groupLayouts[groupName]->addWidget
Chris@493 341 (button, 0, m_groupLayouts[groupName]->columnCount());
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@493 394 m_groupLayouts[groupName]->addWidget
Chris@493 395 (dial, 0, m_groupLayouts[groupName]->columnCount());
Chris@0 396 } else {
Chris@0 397 dial->setFixedWidth(32);
Chris@0 398 dial->setFixedHeight(32);
Chris@0 399 m_layout->addWidget(dial, row, 1);
Chris@33 400 QLabel *label = new QLabel(m_mainWidget);
Chris@0 401 connect(dial, SIGNAL(valueChanged(int)),
Chris@0 402 label, SLOT(setNum(int)));
Chris@0 403 label->setNum(value);
Chris@0 404 m_layout->addWidget(label, row, 2);
Chris@0 405 }
Chris@0 406
Chris@0 407 m_propertyControllers[name] = dial;
Chris@0 408 }
Chris@0 409
Chris@55 410 if (dial->value() != value) {
Chris@55 411 dial->blockSignals(true);
Chris@55 412 dial->setValue(value);
Chris@55 413 dial->blockSignals(false);
Chris@55 414 }
Chris@0 415 break;
Chris@0 416 }
Chris@0 417
Chris@0 418 case PropertyContainer::ValueProperty:
Chris@100 419 case PropertyContainer::UnitsProperty:
Chris@285 420 case PropertyContainer::ColourProperty:
Chris@0 421 {
Chris@189 422 NotifyingComboBox *cb;
Chris@0 423
Chris@0 424 if (have) {
Chris@189 425 cb = dynamic_cast<NotifyingComboBox *>(m_propertyControllers[name]);
Chris@0 426 assert(cb);
Chris@0 427 } else {
Chris@0 428 #ifdef DEBUG_PROPERTY_BOX
Chris@0 429 std::cerr << "PropertyBox: creating new combobox" << std::endl;
Chris@0 430 #endif
Chris@0 431
Chris@189 432 cb = new NotifyingComboBox();
Chris@0 433 cb->setObjectName(name);
Chris@100 434 cb->setDuplicatesEnabled(false);
Chris@197 435 }
Chris@100 436
Chris@197 437 if (!have || rangeChanged) {
Chris@285 438
Chris@197 439 cb->blockSignals(true);
Chris@197 440 cb->clear();
Chris@285 441 cb->setEditable(false);
Chris@285 442
Chris@100 443 if (type == PropertyContainer::ValueProperty) {
Chris@285 444
Chris@100 445 for (int i = min; i <= max; ++i) {
Chris@100 446 cb->addItem(m_container->getPropertyValueLabel(name, i));
Chris@100 447 }
Chris@285 448
Chris@285 449 } else if (type == PropertyContainer::UnitsProperty) {
Chris@285 450
Chris@100 451 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
Chris@100 452 for (int i = 0; i < units.size(); ++i) {
Chris@100 453 cb->addItem(units[i]);
Chris@100 454 }
Chris@285 455
Chris@100 456 cb->setEditable(true);
Chris@285 457
Chris@285 458 } else { // ColourProperty
Chris@290 459
Chris@290 460 //!!! should be a proper colour combobox class that
Chris@290 461 // manages its own Add New Colour entry...
Chris@285 462
Chris@285 463 ColourDatabase *db = ColourDatabase::getInstance();
Chris@285 464 for (size_t i = 0; i < db->getColourCount(); ++i) {
Chris@285 465 QString name = db->getColourName(i);
Chris@287 466 cb->addItem(db->getExamplePixmap(i, QSize(12, 12)), name);
Chris@285 467 }
Chris@285 468 cb->addItem(tr("Add New Colour..."));
Chris@285 469 }
Chris@285 470
Chris@197 471 cb->blockSignals(false);
Chris@280 472 if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) {
Chris@280 473 cb->setMaxVisibleItems(cb->count());
Chris@280 474 }
Chris@197 475 }
Chris@100 476
Chris@197 477 if (!have) {
Chris@0 478 connect(cb, SIGNAL(activated(int)),
Chris@0 479 this, SLOT(propertyControllerChanged(int)));
Chris@189 480 connect(cb, SIGNAL(mouseEntered()),
Chris@189 481 this, SLOT(mouseEnteredWidget()));
Chris@189 482 connect(cb, SIGNAL(mouseLeft()),
Chris@189 483 this, SLOT(mouseLeftWidget()));
Chris@100 484
Chris@0 485 if (inGroup) {
Chris@108 486 cb->setToolTip(propertyLabel);
Chris@493 487 m_groupLayouts[groupName]->addWidget
Chris@493 488 (cb, 0, m_groupLayouts[groupName]->columnCount());
Chris@0 489 } else {
Chris@0 490 m_layout->addWidget(cb, row, 1, 1, 2);
Chris@0 491 }
Chris@0 492 m_propertyControllers[name] = cb;
Chris@0 493 }
Chris@0 494
Chris@100 495 cb->blockSignals(true);
Chris@285 496 if (type == PropertyContainer::ValueProperty ||
Chris@285 497 type == PropertyContainer::ColourProperty) {
Chris@100 498 if (cb->currentIndex() != value) {
Chris@100 499 cb->setCurrentIndex(value);
Chris@100 500 }
Chris@100 501 } else {
Chris@100 502 QString unit = UnitDatabase::getInstance()->getUnitById(value);
Chris@100 503 if (cb->currentText() != unit) {
Chris@100 504 for (int i = 0; i < cb->count(); ++i) {
Chris@100 505 if (cb->itemText(i) == unit) {
Chris@100 506 cb->setCurrentIndex(i);
Chris@100 507 break;
Chris@100 508 }
Chris@100 509 }
Chris@100 510 }
Chris@100 511 }
Chris@100 512 cb->blockSignals(false);
Chris@0 513
Chris@0 514 #ifdef Q_WS_MAC
Chris@0 515 // Crashes on startup without this, for some reason
Chris@0 516 cb->setMinimumSize(QSize(10, 10));
Chris@0 517 #endif
Chris@0 518
Chris@0 519 break;
Chris@0 520 }
Chris@0 521
Chris@0 522 default:
Chris@0 523 break;
Chris@0 524 }
Chris@0 525 }
Chris@0 526
Chris@0 527 void
Chris@0 528 PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 529 {
Chris@0 530 if (pc != m_container) return;
Chris@0 531
Chris@55 532 #ifdef DEBUG_PROPERTY_BOX
Chris@55 533 std::cerr << "PropertyBox::propertyContainerPropertyChanged" << std::endl;
Chris@55 534 #endif
Chris@55 535
Chris@0 536 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@0 537 size_t i;
Chris@0 538
Chris@0 539 blockSignals(true);
Chris@0 540
Chris@0 541 for (i = 0; i < properties.size(); ++i) {
Chris@0 542 updatePropertyEditor(properties[i]);
Chris@0 543 }
Chris@0 544
Chris@0 545 blockSignals(false);
Chris@0 546 }
Chris@0 547
Chris@0 548 void
Chris@249 549 PropertyBox::propertyContainerPropertyRangeChanged(PropertyContainer *)
Chris@197 550 {
Chris@197 551 blockSignals(true);
Chris@197 552
Chris@197 553 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@197 554 for (size_t i = 0; i < properties.size(); ++i) {
Chris@197 555 updatePropertyEditor(properties[i], true);
Chris@197 556 }
Chris@197 557
Chris@197 558 blockSignals(false);
Chris@197 559 }
Chris@197 560
Chris@197 561 void
Chris@100 562 PropertyBox::unitDatabaseChanged()
Chris@100 563 {
Chris@454 564 std::cerr << "PropertyBox[" << this << "]: unitDatabaseChanged" << std::endl;
Chris@100 565 blockSignals(true);
Chris@100 566
Chris@456 567 // std::cerr << "my container is " << m_container << std::endl;
Chris@456 568 // std::cerr << "my container's name is... " << std::endl;
Chris@456 569 // std::cerr << m_container->objectName().toStdString() << std::endl;
Chris@456 570
Chris@100 571 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@100 572 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 573 if (m_container->getPropertyType(properties[i]) ==
Chris@285 574 PropertyContainer::UnitsProperty) {
Chris@285 575 updatePropertyEditor(properties[i]);
Chris@285 576 }
Chris@285 577 }
Chris@285 578
Chris@285 579 blockSignals(false);
Chris@285 580 }
Chris@285 581
Chris@285 582 void
Chris@285 583 PropertyBox::colourDatabaseChanged()
Chris@285 584 {
Chris@285 585 blockSignals(true);
Chris@285 586
Chris@285 587 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@285 588 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 589 if (m_container->getPropertyType(properties[i]) ==
Chris@285 590 PropertyContainer::ColourProperty) {
Chris@285 591 updatePropertyEditor(properties[i], true);
Chris@285 592 }
Chris@100 593 }
Chris@100 594
Chris@100 595 blockSignals(false);
Chris@100 596 }
Chris@100 597
Chris@100 598 void
Chris@335 599 PropertyBox::propertyControllerChanged(bool on)
Chris@335 600 {
Chris@335 601 propertyControllerChanged(on ? 1 : 0);
Chris@335 602 }
Chris@335 603
Chris@335 604 void
Chris@0 605 PropertyBox::propertyControllerChanged(int value)
Chris@0 606 {
Chris@0 607 QObject *obj = sender();
Chris@0 608 QString name = obj->objectName();
Chris@0 609
Chris@34 610 #ifdef DEBUG_PROPERTY_BOX
Chris@33 611 std::cerr << "PropertyBox::propertyControllerChanged(" << name.toStdString()
Chris@33 612 << ", " << value << ")" << std::endl;
Chris@34 613 #endif
Chris@0 614
Chris@0 615 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@100 616
Chris@376 617 Command *c = 0;
Chris@376 618
Chris@100 619 if (type == PropertyContainer::UnitsProperty) {
Chris@285 620
Chris@189 621 NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj);
Chris@100 622 if (cb) {
Chris@100 623 QString unit = cb->currentText();
Chris@376 624 c = m_container->getSetPropertyCommand
Chris@100 625 (name, UnitDatabase::getInstance()->getUnitId(unit));
Chris@100 626 }
Chris@285 627
Chris@285 628 } else if (type == PropertyContainer::ColourProperty) {
Chris@285 629
Chris@285 630 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 631 addNewColour();
Chris@285 632 if (value == int(ColourDatabase::getInstance()->getColourCount())) {
Chris@285 633 propertyContainerPropertyChanged(m_container);
Chris@285 634 return;
Chris@285 635 }
Chris@285 636 }
Chris@376 637 c = m_container->getSetPropertyCommand(name, value);
Chris@285 638
Chris@100 639 } else if (type != PropertyContainer::InvalidProperty) {
Chris@285 640
Chris@376 641 c = m_container->getSetPropertyCommand(name, value);
Chris@0 642 }
Chris@376 643
Chris@376 644 if (c) CommandHistory::getInstance()->addCommand(c, true, true);
Chris@218 645
Chris@218 646 updateContextHelp(obj);
Chris@0 647 }
Chris@285 648
Chris@285 649 void
Chris@285 650 PropertyBox::addNewColour()
Chris@285 651 {
Chris@285 652 QColor newColour = QColorDialog::getColor();
Chris@285 653 if (!newColour.isValid()) return;
Chris@285 654
Chris@285 655 ColourNameDialog dialog(tr("Name New Colour"),
Chris@361 656 tr("Enter a name for the new colour:"),
Chris@361 657 newColour, newColour.name(), this);
Chris@285 658 dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
Chris@285 659 if (dialog.exec() == QDialog::Accepted) {
Chris@285 660 //!!! command
Chris@285 661 ColourDatabase *db = ColourDatabase::getInstance();
Chris@285 662 int index = db->addColour(newColour, dialog.getColourName());
Chris@285 663 db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
Chris@285 664 }
Chris@285 665 }
Chris@377 666
Chris@377 667 void
Chris@377 668 PropertyBox::playAudibleChanged(bool audible)
Chris@377 669 {
Chris@377 670 m_playButton->setState(audible);
Chris@377 671 }
Chris@377 672
Chris@377 673 void
Chris@377 674 PropertyBox::playAudibleButtonChanged(bool audible)
Chris@377 675 {
Chris@377 676 PlayParameters *params = m_container->getPlayParameters();
Chris@377 677 if (!params) return;
Chris@377 678
Chris@377 679 if (params->isPlayAudible() != audible) {
Chris@377 680 PlayParameterRepository::EditCommand *command =
Chris@377 681 new PlayParameterRepository::EditCommand(params);
Chris@377 682 command->setPlayAudible(audible);
Chris@377 683 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 684 }
Chris@377 685 }
Chris@0 686
Chris@34 687 void
Chris@34 688 PropertyBox::playGainChanged(float gain)
Chris@34 689 {
Chris@34 690 int dialValue = lrint(log10(gain) * 20.0);
Chris@34 691 if (dialValue < -50) dialValue = -50;
Chris@34 692 if (dialValue > 50) dialValue = 50;
Chris@34 693 emit changePlayGainDial(dialValue);
Chris@34 694 }
Chris@34 695
Chris@34 696 void
Chris@34 697 PropertyBox::playGainDialChanged(int dialValue)
Chris@34 698 {
Chris@218 699 QObject *obj = sender();
Chris@377 700
Chris@377 701 PlayParameters *params = m_container->getPlayParameters();
Chris@377 702 if (!params) return;
Chris@377 703
Chris@34 704 float gain = pow(10, float(dialValue) / 20.0);
Chris@377 705
Chris@377 706 if (params->getPlayGain() != gain) {
Chris@377 707 PlayParameterRepository::EditCommand *command =
Chris@377 708 new PlayParameterRepository::EditCommand(params);
Chris@377 709 command->setPlayGain(gain);
Chris@377 710 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 711 }
Chris@377 712
Chris@218 713 updateContextHelp(obj);
Chris@34 714 }
Chris@34 715
Chris@34 716 void
Chris@34 717 PropertyBox::playPanChanged(float pan)
Chris@34 718 {
Chris@34 719 int dialValue = lrint(pan * 50.0);
Chris@34 720 if (dialValue < -50) dialValue = -50;
Chris@34 721 if (dialValue > 50) dialValue = 50;
Chris@34 722 emit changePlayPanDial(dialValue);
Chris@34 723 }
Chris@34 724
Chris@34 725 void
Chris@34 726 PropertyBox::playPanDialChanged(int dialValue)
Chris@34 727 {
Chris@218 728 QObject *obj = sender();
Chris@377 729
Chris@377 730 PlayParameters *params = m_container->getPlayParameters();
Chris@377 731 if (!params) return;
Chris@377 732
Chris@34 733 float pan = float(dialValue) / 50.0;
Chris@34 734 if (pan < -1.0) pan = -1.0;
Chris@34 735 if (pan > 1.0) pan = 1.0;
Chris@377 736
Chris@377 737 if (params->getPlayPan() != pan) {
Chris@377 738 PlayParameterRepository::EditCommand *command =
Chris@377 739 new PlayParameterRepository::EditCommand(params);
Chris@377 740 command->setPlayPan(pan);
Chris@377 741 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 742 }
Chris@377 743
Chris@218 744 updateContextHelp(obj);
Chris@34 745 }
Chris@0 746
Chris@63 747 void
Chris@63 748 PropertyBox::editPlugin()
Chris@63 749 {
Chris@63 750 //!!! should probably just emit and let something else do this
Chris@63 751
Chris@63 752 PlayParameters *params = m_container->getPlayParameters();
Chris@63 753 if (!params) return;
Chris@63 754
Chris@63 755 QString pluginId = params->getPlayPluginId();
Chris@63 756 QString configurationXml = params->getPlayPluginConfiguration();
Chris@377 757
Chris@377 758 PlayParameterRepository::EditCommand *command =
Chris@377 759 new PlayParameterRepository::EditCommand(params);
Chris@63 760
Chris@63 761 RealTimePluginFactory *factory =
Chris@63 762 RealTimePluginFactory::instanceFor(pluginId);
Chris@63 763 if (!factory) return;
Chris@63 764
Chris@63 765 RealTimePluginInstance *instance =
Chris@63 766 factory->instantiatePlugin(pluginId, 0, 0, 48000, 1024, 1);
Chris@63 767 if (!instance) return;
Chris@63 768
Chris@71 769 PluginXml(instance).setParametersFromXml(configurationXml);
Chris@63 770
Chris@163 771 PluginParameterDialog *dialog = new PluginParameterDialog(instance);
Chris@64 772 connect(dialog, SIGNAL(pluginConfigurationChanged(QString)),
Chris@64 773 this, SLOT(pluginConfigurationChanged(QString)));
Chris@64 774
Chris@63 775 if (dialog->exec() == QDialog::Accepted) {
Chris@377 776 QString newConfiguration = PluginXml(instance).toXmlString();
Chris@377 777 command->setPlayPluginConfiguration(newConfiguration);
Chris@377 778 CommandHistory::getInstance()->addCommand(command, true);
Chris@64 779 } else {
Chris@377 780 delete command;
Chris@64 781 // restore in case we mucked about with the configuration
Chris@64 782 // as a consequence of signals from the dialog
Chris@64 783 params->setPlayPluginConfiguration(configurationXml);
Chris@63 784 }
Chris@63 785
Chris@63 786 delete dialog;
Chris@63 787 delete instance;
Chris@63 788 }
Chris@63 789
Chris@64 790 void
Chris@64 791 PropertyBox::pluginConfigurationChanged(QString configurationXml)
Chris@64 792 {
Chris@64 793 PlayParameters *params = m_container->getPlayParameters();
Chris@64 794 if (!params) return;
Chris@64 795
Chris@64 796 params->setPlayPluginConfiguration(configurationXml);
Chris@64 797 }
Chris@185 798
Chris@185 799 void
Chris@185 800 PropertyBox::layerVisibilityChanged(bool visible)
Chris@185 801 {
Chris@185 802 if (m_showButton) m_showButton->setState(visible);
Chris@185 803 }
Chris@189 804
Chris@189 805 void
Chris@189 806 PropertyBox::mouseEnteredWidget()
Chris@189 807 {
Chris@218 808 updateContextHelp(sender());
Chris@218 809 }
Chris@218 810
Chris@218 811 void
Chris@218 812 PropertyBox::updateContextHelp(QObject *o)
Chris@218 813 {
Chris@218 814 QWidget *w = dynamic_cast<QWidget *>(o);
Chris@189 815 if (!w) return;
Chris@218 816
Chris@189 817 if (!m_container) return;
Chris@190 818 QString cname = m_container->getPropertyContainerName();
Chris@189 819 if (cname == "") return;
Chris@189 820
Chris@189 821 QString wname = w->objectName();
Chris@189 822
Chris@218 823 QString extraText;
Chris@218 824 AudioDial *dial = dynamic_cast<AudioDial *>(w);
Chris@218 825 if (dial) {
Chris@218 826 float mv = dial->mappedValue();
Chris@218 827 QString unit = "";
Chris@218 828 if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit();
Chris@218 829 if (unit != "") {
Chris@218 830 extraText = tr(" (current value: %1%2)").arg(mv).arg(unit);
Chris@218 831 } else {
Chris@218 832 extraText = tr(" (current value: %1)").arg(mv);
Chris@218 833 }
Chris@218 834 }
Chris@218 835
Chris@189 836 if (w == m_showButton) {
Chris@190 837 emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname));
Chris@189 838 } else if (w == m_playButton) {
Chris@190 839 emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname));
Chris@189 840 } else if (wname == "") {
Chris@189 841 return;
Chris@335 842 } else if (dynamic_cast<QAbstractButton *>(w)) {
Chris@190 843 emit contextHelpChanged(tr("Toggle %1 property of %2")
Chris@189 844 .arg(wname).arg(cname));
Chris@189 845 } else {
Chris@218 846 emit contextHelpChanged(tr("Adjust %1 property of %2%3")
Chris@218 847 .arg(wname).arg(cname).arg(extraText));
Chris@189 848 }
Chris@189 849 }
Chris@189 850
Chris@189 851 void
Chris@189 852 PropertyBox::mouseLeftWidget()
Chris@189 853 {
Chris@218 854 if (!(QApplication::mouseButtons() & Qt::LeftButton)) {
Chris@218 855 emit contextHelpChanged("");
Chris@218 856 }
Chris@189 857 }
Chris@189 858
Chris@64 859