annotate widgets/PropertyBox.cpp @ 1386:fc3d89f88690 spectrogramparam

Use log-frequency rather than log-bin for calculating x coord in spectrum. This has the advantage that frequency positions don't move when we change the window size or oversampling ratio, but it does give us an unhelpfully large amount of space for very low frequencies - to be considered
author Chris Cannam
date Mon, 12 Nov 2018 11:34:34 +0000
parents 78eecb19e688
children c8a6fd3f9dff
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@100 23 #include "base/UnitDatabase.h"
Chris@167 24 #include "base/RangeMapper.h"
Chris@0 25
Chris@0 26 #include "AudioDial.h"
Chris@33 27 #include "LEDButton.h"
Chris@335 28 #include "IconLoader.h"
Chris@1178 29 #include "LevelPanWidget.h"
Chris@1179 30 #include "LevelPanToolButton.h"
Chris@1174 31 #include "WidgetScale.h"
Chris@0 32
Chris@189 33 #include "NotifyingCheckBox.h"
Chris@189 34 #include "NotifyingComboBox.h"
Chris@335 35 #include "NotifyingPushButton.h"
Chris@1189 36 #include "NotifyingToolButton.h"
Chris@1196 37 #include "ColourComboBox.h"
Chris@1198 38 #include "ColourMapComboBox.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@1189 44 #include <QToolButton>
Chris@0 45 #include <QLabel>
Chris@33 46 #include <QFrame>
Chris@218 47 #include <QApplication>
Chris@285 48 #include <QColorDialog>
Chris@285 49 #include <QInputDialog>
Chris@769 50 #include <QDir>
Chris@0 51
Chris@0 52 #include <cassert>
Chris@0 53 #include <iostream>
Martin@46 54 #include <cmath>
Chris@0 55
Chris@456 56 //#define DEBUG_PROPERTY_BOX 1
Chris@0 57
Chris@0 58 PropertyBox::PropertyBox(PropertyContainer *container) :
Chris@185 59 m_container(container),
Chris@189 60 m_showButton(0),
Chris@189 61 m_playButton(0)
Chris@0 62 {
Chris@0 63 #ifdef DEBUG_PROPERTY_BOX
Chris@682 64 cerr << "PropertyBox[" << this << "(\"" <<
Chris@1266 65 container->getPropertyContainerName() << "\" at " << container << ")]::PropertyBox" << endl;
Chris@0 66 #endif
Chris@0 67
Chris@34 68 m_mainBox = new QVBoxLayout;
Chris@34 69 setLayout(m_mainBox);
Chris@33 70
Chris@980 71 #ifdef Q_OS_MAC
Chris@980 72 QMargins mm = m_mainBox->contentsMargins();
Chris@980 73 QMargins mmhalf(mm.left()/2, mm.top()/3, mm.right()/2, mm.bottom()/3);
Chris@980 74 m_mainBox->setContentsMargins(mmhalf);
Chris@980 75 #endif
Chris@980 76
Chris@107 77 // m_nameWidget = new QLabel;
Chris@107 78 // m_mainBox->addWidget(m_nameWidget);
Chris@107 79 // m_nameWidget->setText(container->objectName());
Chris@107 80
Chris@34 81 m_mainWidget = new QWidget;
Chris@34 82 m_mainBox->addWidget(m_mainWidget);
Chris@107 83 m_mainBox->insertStretch(2, 10);
Chris@33 84
Chris@34 85 m_viewPlayFrame = 0;
Chris@34 86 populateViewPlayFrame();
Chris@33 87
Chris@0 88 m_layout = new QGridLayout;
Chris@34 89 m_layout->setMargin(0);
Chris@833 90 m_layout->setHorizontalSpacing(2);
Chris@833 91 m_layout->setVerticalSpacing(1);
Chris@33 92 m_mainWidget->setLayout(m_layout);
Chris@0 93
Chris@34 94 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@0 95
Chris@0 96 blockSignals(true);
Chris@0 97
Chris@0 98 size_t i;
Chris@0 99
Chris@0 100 for (i = 0; i < properties.size(); ++i) {
Chris@1266 101 updatePropertyEditor(properties[i]);
Chris@0 102 }
Chris@0 103
Chris@0 104 blockSignals(false);
Chris@0 105
Chris@0 106 m_layout->setRowStretch(m_layout->rowCount(), 10);
Chris@0 107
Chris@100 108 connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()),
Chris@100 109 this, SLOT(unitDatabaseChanged()));
Chris@100 110
Chris@0 111 #ifdef DEBUG_PROPERTY_BOX
Chris@682 112 cerr << "PropertyBox[" << this << "]::PropertyBox returning" << endl;
Chris@0 113 #endif
Chris@0 114 }
Chris@0 115
Chris@0 116 PropertyBox::~PropertyBox()
Chris@0 117 {
Chris@0 118 #ifdef DEBUG_PROPERTY_BOX
Chris@682 119 cerr << "PropertyBox[" << this << "]::~PropertyBox" << endl;
Chris@0 120 #endif
Chris@0 121 }
Chris@0 122
Chris@0 123 void
Chris@34 124 PropertyBox::populateViewPlayFrame()
Chris@33 125 {
Chris@36 126 #ifdef DEBUG_PROPERTY_BOX
Chris@729 127 cerr << "PropertyBox[" << this << ":" << m_container << "]::populateViewPlayFrame" << endl;
Chris@36 128 #endif
Chris@34 129
Chris@34 130 if (m_viewPlayFrame) {
Chris@1266 131 delete m_viewPlayFrame;
Chris@1266 132 m_viewPlayFrame = 0;
Chris@34 133 }
Chris@34 134
Chris@34 135 if (!m_container) return;
Chris@34 136
Chris@34 137 Layer *layer = dynamic_cast<Layer *>(m_container);
Chris@34 138 if (layer) {
Chris@1266 139 disconnect(layer, SIGNAL(modelReplaced()),
Chris@193 140 this, SLOT(populateViewPlayFrame()));
Chris@1266 141 connect(layer, SIGNAL(modelReplaced()),
Chris@1266 142 this, SLOT(populateViewPlayFrame()));
Chris@34 143 }
Chris@34 144
Chris@34 145 PlayParameters *params = m_container->getPlayParameters();
Chris@33 146 if (!params && !layer) return;
Chris@33 147
Chris@34 148 m_viewPlayFrame = new QFrame;
Chris@34 149 m_viewPlayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
Chris@34 150 m_mainBox->addWidget(m_viewPlayFrame);
Chris@34 151
Chris@1189 152 QGridLayout *layout = new QGridLayout;
Chris@34 153 m_viewPlayFrame->setLayout(layout);
Chris@34 154
Chris@34 155 layout->setMargin(layout->margin() / 2);
Chris@34 156
Chris@36 157 #ifdef DEBUG_PROPERTY_BOX
Chris@587 158 SVDEBUG << "PropertyBox::populateViewPlayFrame: container " << m_container << " (name " << m_container->getPropertyContainerName() << ") params " << params << endl;
Chris@36 159 #endif
Chris@1189 160
Chris@1189 161 QSize buttonSize = WidgetScale::scaleQSize(QSize(26, 26));
Chris@1189 162 int col = 0;
Chris@1189 163
Chris@33 164 if (params) {
Chris@1189 165
Chris@1189 166 m_playButton = new NotifyingToolButton;
Chris@1187 167 m_playButton->setCheckable(true);
Chris@1187 168 m_playButton->setIcon(IconLoader().load("speaker"));
Chris@1190 169 m_playButton->setToolTip(tr("Click to toggle playback"));
Chris@1187 170 m_playButton->setChecked(!params->isPlayMuted());
Chris@1189 171 m_playButton->setFixedSize(buttonSize);
Chris@1266 172 connect(m_playButton, SIGNAL(toggled(bool)),
Chris@1266 173 this, SLOT(playAudibleButtonChanged(bool)));
Chris@1187 174 connect(m_playButton, SIGNAL(mouseEntered()),
Chris@1187 175 this, SLOT(mouseEnteredWidget()));
Chris@1187 176 connect(m_playButton, SIGNAL(mouseLeft()),
Chris@1187 177 this, SLOT(mouseLeftWidget()));
Chris@1266 178 connect(params, SIGNAL(playAudibleChanged(bool)),
Chris@1266 179 this, SLOT(playAudibleChanged(bool)));
Chris@63 180
Chris@1179 181 LevelPanToolButton *levelPan = new LevelPanToolButton;
Chris@1189 182 levelPan->setFixedSize(buttonSize);
Chris@1189 183 levelPan->setImageSize((buttonSize.height() * 3) / 4);
Chris@1189 184 layout->addWidget(levelPan, 0, col++, Qt::AlignCenter);
Chris@1178 185 connect(levelPan, SIGNAL(levelChanged(float)),
Chris@1178 186 this, SLOT(playGainControlChanged(float)));
Chris@1178 187 connect(levelPan, SIGNAL(panChanged(float)),
Chris@1178 188 this, SLOT(playPanControlChanged(float)));
Chris@1178 189 connect(params, SIGNAL(playGainChanged(float)),
Chris@1178 190 levelPan, SLOT(setLevel(float)));
Chris@1178 191 connect(params, SIGNAL(playPanChanged(float)),
Chris@1178 192 levelPan, SLOT(setPan(float)));
Chris@1180 193 connect(levelPan, SIGNAL(mouseEntered()),
Chris@1180 194 this, SLOT(mouseEnteredWidget()));
Chris@1180 195 connect(levelPan, SIGNAL(mouseLeft()),
Chris@1180 196 this, SLOT(mouseLeftWidget()));
Chris@1180 197
Chris@1266 198 layout->addWidget(m_playButton, 0, col++, Qt::AlignCenter);
Chris@1189 199
Chris@1187 200 if (params->getPlayClipId() != "") {
Chris@1223 201 NotifyingToolButton *playParamButton = new NotifyingToolButton;
Chris@1187 202 playParamButton->setObjectName("playParamButton");
Chris@1187 203 playParamButton->setIcon(IconLoader().load("faders"));
Chris@1189 204 playParamButton->setFixedSize(buttonSize);
Chris@1189 205 layout->addWidget(playParamButton, 0, col++, Qt::AlignCenter);
Chris@1187 206 connect(playParamButton, SIGNAL(clicked()),
Chris@1187 207 this, SLOT(editPlayParameters()));
Chris@1187 208 connect(playParamButton, SIGNAL(mouseEntered()),
Chris@1187 209 this, SLOT(mouseEnteredWidget()));
Chris@1187 210 connect(playParamButton, SIGNAL(mouseLeft()),
Chris@1187 211 this, SLOT(mouseLeftWidget()));
Chris@1187 212 }
Chris@1187 213 }
Chris@1187 214
Chris@1189 215 layout->setColumnStretch(col++, 10);
Chris@1187 216
Chris@1187 217 if (layer) {
Chris@1187 218
Chris@1266 219 QLabel *showLabel = new QLabel(tr("Show"));
Chris@1266 220 layout->addWidget(showLabel, 0, col++, Qt::AlignVCenter | Qt::AlignRight);
Chris@1187 221
Chris@1266 222 m_showButton = new LEDButton(palette().highlight().color());
Chris@1266 223 layout->addWidget(m_showButton, 0, col++, Qt::AlignVCenter | Qt::AlignLeft);
Chris@1266 224 connect(m_showButton, SIGNAL(stateChanged(bool)),
Chris@1266 225 this, SIGNAL(showLayer(bool)));
Chris@1187 226 connect(m_showButton, SIGNAL(mouseEntered()),
Chris@1180 227 this, SLOT(mouseEnteredWidget()));
Chris@1187 228 connect(m_showButton, SIGNAL(mouseLeft()),
Chris@1180 229 this, SLOT(mouseLeftWidget()));
Chris@33 230 }
Chris@33 231 }
Chris@33 232
Chris@33 233 void
Chris@197 234 PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name,
Chris@197 235 bool rangeChanged)
Chris@0 236 {
Chris@0 237 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@0 238 int row = m_layout->rowCount();
Chris@0 239
Chris@216 240 int min = 0, max = 0, value = 0, deflt = 0;
Chris@216 241 value = m_container->getPropertyRangeAndValue(name, &min, &max, &deflt);
Chris@0 242
Chris@0 243 bool have = (m_propertyControllers.find(name) !=
Chris@1266 244 m_propertyControllers.end());
Chris@0 245
Chris@0 246 QString groupName = m_container->getPropertyGroupName(name);
Chris@87 247 QString propertyLabel = m_container->getPropertyLabel(name);
Chris@335 248 QString iconName = m_container->getPropertyIconName(name);
Chris@0 249
Chris@0 250 #ifdef DEBUG_PROPERTY_BOX
Chris@682 251 cerr << "PropertyBox[" << this
Chris@1266 252 << "(\"" << m_container->getPropertyContainerName()
Chris@1266 253 << "\")]";
Chris@1281 254 cerr << "::updatePropertyEditor(\"" << name << "\", "
Chris@1281 255 << rangeChanged << "):";
Chris@1281 256 cerr << " type " << type << ", value " << value
Chris@1281 257 << ", have " << have << ", group \"" << groupName << "\"" << endl;
Chris@0 258 #endif
Chris@0 259
Chris@1204 260 QString groupLabel = groupName;
Chris@1204 261 if (groupName == QString()) {
Chris@1204 262 groupName = "ungrouped: " + name; // not tr(), this is internal id
Chris@1204 263 groupLabel = propertyLabel;
Chris@1204 264 }
Chris@1204 265
Chris@0 266 if (!have) {
Chris@1204 267 if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) {
Chris@1204 268 QWidget *labelWidget = new QLabel(groupLabel, m_mainWidget);
Chris@1190 269 m_layout->addWidget(labelWidget, row, 0);
Chris@1190 270 QWidget *frame = new QWidget(m_mainWidget);
Chris@1190 271 frame->setMinimumSize(WidgetScale::scaleQSize(QSize(1, 24)));
Chris@1190 272 m_groupLayouts[groupName] = new QGridLayout;
Chris@1195 273 #ifdef Q_OS_MAC
Chris@1195 274 // Seems to be plenty of whitespace already
Chris@1195 275 m_groupLayouts[groupName]->setContentsMargins(0, 0, 0, 0);
Chris@1195 276 #else
Chris@1195 277 // Need a bit of padding on the left
Chris@1195 278 m_groupLayouts[groupName]->setContentsMargins
Chris@1195 279 (WidgetScale::scalePixelSize(10), 0, 0, 0);
Chris@1195 280 #endif
Chris@1190 281 frame->setLayout(m_groupLayouts[groupName]);
Chris@1190 282 m_layout->addWidget(frame, row, 1, 1, 2);
Chris@1190 283 m_layout->setColumnStretch(1, 10);
Chris@1190 284 }
Chris@0 285 }
Chris@0 286
Chris@1204 287 QGridLayout *groupLayout = m_groupLayouts[groupName];
Chris@1204 288
Chris@1204 289 #ifdef DEBUG_PROPERTY_BOX
Chris@1204 290 cerr << "groupName becomes \"" << groupName << "\", groupLabel = \""
Chris@1204 291 << groupLabel << "\", groupLayout = " << groupLayout << endl;
Chris@1204 292 #endif
Chris@1204 293
Chris@1204 294 assert(groupLayout);
Chris@1204 295
Chris@1204 296 QWidget *existing = m_propertyControllers[name];
Chris@1204 297
Chris@0 298 switch (type) {
Chris@0 299
Chris@0 300 case PropertyContainer::ToggleProperty:
Chris@0 301 {
Chris@1204 302 QAbstractButton *button;
Chris@0 303
Chris@1266 304 if (!(button = qobject_cast<QAbstractButton *>(existing))) {
Chris@0 305 #ifdef DEBUG_PROPERTY_BOX
Chris@1266 306 cerr << "PropertyBox: creating new checkbox" << endl;
Chris@0 307 #endif
Chris@335 308 if (iconName != "") {
cannam@1309 309 #ifdef Q_OS_MAC
cannam@1309 310 button = new NotifyingToolButton();
cannam@1309 311 #else
Chris@335 312 button = new NotifyingPushButton();
cannam@1309 313 #endif
Chris@335 314 button->setCheckable(true);
Chris@335 315 QIcon icon(IconLoader().load(iconName));
Chris@335 316 button->setIcon(icon);
Chris@335 317 button->setObjectName(name);
Chris@1174 318 button->setFixedSize(WidgetScale::scaleQSize(QSize(18, 18)));
Chris@335 319 } else {
Chris@335 320 button = new NotifyingCheckBox();
Chris@335 321 button->setObjectName(name);
Chris@335 322 }
Chris@1266 323 connect(button, SIGNAL(toggled(bool)),
Chris@1266 324 this, SLOT(propertyControllerChanged(bool)));
Chris@335 325 connect(button, SIGNAL(mouseEntered()),
Chris@189 326 this, SLOT(mouseEnteredWidget()));
Chris@335 327 connect(button, SIGNAL(mouseLeft()),
Chris@189 328 this, SLOT(mouseLeftWidget()));
Chris@1197 329 button->setToolTip(propertyLabel);
Chris@1204 330
Chris@1204 331 if (existing) {
Chris@1204 332 groupLayout->replaceWidget(existing, button);
Chris@1204 333 delete existing;
Chris@1204 334 } else {
Chris@1204 335 groupLayout->addWidget(button, 0, groupLayout->columnCount());
Chris@1204 336 }
Chris@1204 337
Chris@1266 338 m_propertyControllers[name] = button;
Chris@1266 339 }
Chris@0 340
Chris@335 341 if (button->isChecked() != (value > 0)) {
Chris@1266 342 button->blockSignals(true);
Chris@1266 343 button->setChecked(value > 0);
Chris@1266 344 button->blockSignals(false);
Chris@1266 345 }
Chris@1266 346 break;
Chris@0 347 }
Chris@0 348
Chris@0 349 case PropertyContainer::RangeProperty:
Chris@0 350 {
Chris@1266 351 AudioDial *dial;
Chris@0 352
Chris@1266 353 if ((dial = qobject_cast<AudioDial *>(existing))) {
Chris@197 354 if (rangeChanged) {
Chris@197 355 dial->blockSignals(true);
Chris@197 356 dial->setMinimum(min);
Chris@197 357 dial->setMaximum(max);
Chris@197 358 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
Chris@197 359 dial->blockSignals(false);
Chris@197 360 }
Chris@1204 361 } else {
Chris@0 362 #ifdef DEBUG_PROPERTY_BOX
Chris@1266 363 cerr << "PropertyBox: creating new dial" << endl;
Chris@0 364 #endif
Chris@1266 365 dial = new AudioDial();
Chris@1266 366 dial->setObjectName(name);
Chris@1266 367 dial->setMinimum(min);
Chris@1266 368 dial->setMaximum(max);
Chris@1266 369 dial->setPageStep(1);
Chris@1266 370 dial->setNotchesVisible((max - min) <= 12);
Chris@1126 371 // important to set the range mapper before the default,
Chris@1126 372 // because the range mapper is used to map the default
Chris@1126 373 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
Chris@1266 374 dial->setDefaultValue(deflt);
Chris@168 375 dial->setShowToolTip(true);
Chris@1266 376 connect(dial, SIGNAL(valueChanged(int)),
Chris@1266 377 this, SLOT(propertyControllerChanged(int)));
Chris@189 378 connect(dial, SIGNAL(mouseEntered()),
Chris@189 379 this, SLOT(mouseEnteredWidget()));
Chris@189 380 connect(dial, SIGNAL(mouseLeft()),
Chris@189 381 this, SLOT(mouseLeftWidget()));
Chris@0 382
Chris@1197 383 dial->setFixedWidth(WidgetScale::scalePixelSize(24));
Chris@1197 384 dial->setFixedHeight(WidgetScale::scalePixelSize(24));
Chris@1204 385
Chris@1204 386 if (existing) {
Chris@1204 387 groupLayout->replaceWidget(existing, dial);
Chris@1204 388 delete existing;
Chris@1204 389 } else {
Chris@1204 390 groupLayout->addWidget(dial, 0, groupLayout->columnCount());
Chris@1204 391 }
Chris@0 392
Chris@1266 393 m_propertyControllers[name] = dial;
Chris@1266 394 }
Chris@0 395
Chris@1266 396 if (dial->value() != value) {
Chris@1266 397 dial->blockSignals(true);
Chris@1266 398 dial->setValue(value);
Chris@1266 399 dial->blockSignals(false);
Chris@1266 400 }
Chris@1266 401 break;
Chris@0 402 }
Chris@0 403
Chris@1196 404 case PropertyContainer::ColourProperty:
Chris@1196 405 {
Chris@1196 406 ColourComboBox *cb;
Chris@1196 407
Chris@1266 408 if (!(cb = qobject_cast<ColourComboBox *>(existing))) {
Chris@1204 409
Chris@1196 410 #ifdef DEBUG_PROPERTY_BOX
Chris@1266 411 cerr << "PropertyBox: creating new colour combobox" << endl;
Chris@1196 412 #endif
Chris@1196 413 cb = new ColourComboBox(true);
Chris@1196 414 cb->setObjectName(name);
Chris@1196 415
Chris@1266 416 connect(cb, SIGNAL(colourChanged(int)),
Chris@1266 417 this, SLOT(propertyControllerChanged(int)));
Chris@1196 418 connect(cb, SIGNAL(mouseEntered()),
Chris@1196 419 this, SLOT(mouseEnteredWidget()));
Chris@1196 420 connect(cb, SIGNAL(mouseLeft()),
Chris@1196 421 this, SLOT(mouseLeftWidget()));
Chris@1196 422
Chris@1197 423 cb->setToolTip(propertyLabel);
Chris@1204 424
Chris@1204 425 if (existing) {
Chris@1204 426 groupLayout->replaceWidget(existing, cb);
Chris@1204 427 delete existing;
Chris@1204 428 } else {
Chris@1204 429 groupLayout->addWidget(cb, 0, groupLayout->columnCount());
Chris@1204 430 }
Chris@1204 431
Chris@1266 432 m_propertyControllers[name] = cb;
Chris@1266 433 }
Chris@1196 434
Chris@1196 435 if (cb->currentIndex() != value) {
Chris@1196 436 cb->blockSignals(true);
Chris@1196 437 cb->setCurrentIndex(value);
Chris@1196 438 cb->blockSignals(false);
Chris@1196 439 }
Chris@1196 440
Chris@1198 441 break;
Chris@1198 442 }
Chris@1198 443
Chris@1198 444 case PropertyContainer::ColourMapProperty:
Chris@1198 445 {
Chris@1198 446 ColourMapComboBox *cb;
Chris@1204 447
Chris@1204 448 if (!(cb = qobject_cast<ColourMapComboBox *>(existing))) {
Chris@1198 449 #ifdef DEBUG_PROPERTY_BOX
Chris@1266 450 cerr << "PropertyBox: creating new colourmap combobox" << endl;
Chris@1196 451 #endif
Chris@1199 452 cb = new ColourMapComboBox(false);
Chris@1198 453 cb->setObjectName(name);
Chris@1196 454
Chris@1266 455 connect(cb, SIGNAL(colourMapChanged(int)),
Chris@1266 456 this, SLOT(propertyControllerChanged(int)));
Chris@1198 457 connect(cb, SIGNAL(mouseEntered()),
Chris@1198 458 this, SLOT(mouseEnteredWidget()));
Chris@1198 459 connect(cb, SIGNAL(mouseLeft()),
Chris@1198 460 this, SLOT(mouseLeftWidget()));
Chris@1204 461
Chris@1204 462 cb->setToolTip(propertyLabel);
Chris@1198 463
Chris@1204 464 if (existing) {
Chris@1204 465 groupLayout->replaceWidget(existing, cb);
Chris@1204 466 delete existing;
Chris@1204 467 } else {
Chris@1204 468 groupLayout->addWidget(cb, 0, groupLayout->columnCount());
Chris@1204 469 }
Chris@1204 470
Chris@1266 471 m_propertyControllers[name] = cb;
Chris@1266 472 }
Chris@1198 473
Chris@1198 474 if (cb->currentIndex() != value) {
Chris@1198 475 cb->blockSignals(true);
Chris@1198 476 cb->setCurrentIndex(value);
Chris@1198 477 cb->blockSignals(false);
Chris@1198 478 }
Chris@1198 479
Chris@1196 480 break;
Chris@1196 481 }
Chris@1196 482
Chris@0 483 case PropertyContainer::ValueProperty:
Chris@100 484 case PropertyContainer::UnitsProperty:
Chris@0 485 {
Chris@1266 486 NotifyingComboBox *cb;
Chris@0 487
Chris@1266 488 if (!(cb = qobject_cast<NotifyingComboBox *>(existing))) {
Chris@0 489 #ifdef DEBUG_PROPERTY_BOX
Chris@1266 490 cerr << "PropertyBox: creating new combobox" << endl;
Chris@0 491 #endif
Chris@1266 492 cb = new NotifyingComboBox();
Chris@1266 493 cb->setObjectName(name);
Chris@100 494 cb->setDuplicatesEnabled(false);
Chris@197 495 }
Chris@100 496
Chris@197 497 if (!have || rangeChanged) {
Chris@285 498
Chris@197 499 cb->blockSignals(true);
Chris@197 500 cb->clear();
Chris@285 501 cb->setEditable(false);
Chris@285 502
Chris@100 503 if (type == PropertyContainer::ValueProperty) {
Chris@285 504
Chris@100 505 for (int i = min; i <= max; ++i) {
Chris@862 506
Chris@862 507 QString label = m_container->getPropertyValueLabel(name, i);
Chris@862 508 QString iname = m_container->getPropertyValueIconName(name, i);
Chris@862 509
Chris@862 510 if (iname != "") {
Chris@862 511 QIcon icon(IconLoader().load(iname));
Chris@862 512 cb->addItem(icon, label);
Chris@862 513 } else {
Chris@862 514 cb->addItem(label);
Chris@862 515 }
Chris@100 516 }
Chris@285 517
Chris@1196 518 } else { // PropertyContainer::UnitsProperty
Chris@285 519
Chris@100 520 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
Chris@100 521 for (int i = 0; i < units.size(); ++i) {
Chris@100 522 cb->addItem(units[i]);
Chris@100 523 }
Chris@285 524
Chris@100 525 cb->setEditable(true);
Chris@280 526 }
Chris@197 527 }
Chris@100 528
Chris@197 529 if (!have) {
Chris@1266 530 connect(cb, SIGNAL(activated(int)),
Chris@1266 531 this, SLOT(propertyControllerChanged(int)));
Chris@189 532 connect(cb, SIGNAL(mouseEntered()),
Chris@189 533 this, SLOT(mouseEnteredWidget()));
Chris@189 534 connect(cb, SIGNAL(mouseLeft()),
Chris@189 535 this, SLOT(mouseLeftWidget()));
Chris@100 536
Chris@1197 537 cb->setToolTip(propertyLabel);
Chris@1204 538 groupLayout->addWidget(cb, 0, groupLayout->columnCount());
Chris@1266 539 m_propertyControllers[name] = cb;
Chris@1266 540 } else if (existing != cb) {
Chris@1204 541 groupLayout->replaceWidget(existing, cb);
Chris@1204 542 delete existing;
Chris@1204 543 }
Chris@0 544
Chris@100 545 cb->blockSignals(true);
Chris@1196 546 if (type == PropertyContainer::ValueProperty) {
Chris@100 547 if (cb->currentIndex() != value) {
Chris@100 548 cb->setCurrentIndex(value);
Chris@100 549 }
Chris@100 550 } else {
Chris@100 551 QString unit = UnitDatabase::getInstance()->getUnitById(value);
Chris@100 552 if (cb->currentText() != unit) {
Chris@100 553 for (int i = 0; i < cb->count(); ++i) {
Chris@100 554 if (cb->itemText(i) == unit) {
Chris@100 555 cb->setCurrentIndex(i);
Chris@100 556 break;
Chris@100 557 }
Chris@100 558 }
Chris@100 559 }
Chris@100 560 }
Chris@100 561 cb->blockSignals(false);
Chris@0 562
Chris@1266 563 break;
Chris@0 564 }
Chris@0 565
Chris@807 566 case PropertyContainer::InvalidProperty:
Chris@0 567 default:
Chris@1266 568 break;
Chris@0 569 }
Chris@0 570 }
Chris@0 571
Chris@0 572 void
Chris@0 573 PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@0 574 {
Chris@0 575 if (pc != m_container) return;
Chris@0 576
Chris@55 577 #ifdef DEBUG_PROPERTY_BOX
Chris@587 578 SVDEBUG << "PropertyBox::propertyContainerPropertyChanged" << endl;
Chris@55 579 #endif
Chris@55 580
Chris@0 581 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@0 582 size_t i;
Chris@0 583
Chris@0 584 blockSignals(true);
Chris@0 585
Chris@0 586 for (i = 0; i < properties.size(); ++i) {
Chris@1266 587 updatePropertyEditor(properties[i]);
Chris@0 588 }
Chris@0 589
Chris@0 590 blockSignals(false);
Chris@0 591 }
Chris@0 592
Chris@0 593 void
Chris@249 594 PropertyBox::propertyContainerPropertyRangeChanged(PropertyContainer *)
Chris@197 595 {
Chris@197 596 blockSignals(true);
Chris@197 597
Chris@197 598 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@197 599 for (size_t i = 0; i < properties.size(); ++i) {
Chris@1266 600 updatePropertyEditor(properties[i], true);
Chris@197 601 }
Chris@197 602
Chris@197 603 blockSignals(false);
Chris@197 604 }
Chris@197 605
Chris@197 606 void
Chris@100 607 PropertyBox::unitDatabaseChanged()
Chris@100 608 {
Chris@729 609 #ifdef DEBUG_PROPERTY_BOX
Chris@682 610 cerr << "PropertyBox[" << this << "]: unitDatabaseChanged" << endl;
Chris@729 611 #endif
Chris@100 612 blockSignals(true);
Chris@100 613
Chris@682 614 // cerr << "my container is " << m_container << endl;
Chris@682 615 // cerr << "my container's name is... " << endl;
Chris@682 616 // cerr << m_container->objectName() << endl;
Chris@456 617
Chris@100 618 PropertyContainer::PropertyList properties = m_container->getProperties();
Chris@100 619 for (size_t i = 0; i < properties.size(); ++i) {
Chris@285 620 if (m_container->getPropertyType(properties[i]) ==
Chris@285 621 PropertyContainer::UnitsProperty) {
Chris@285 622 updatePropertyEditor(properties[i]);
Chris@285 623 }
Chris@285 624 }
Chris@285 625
Chris@285 626 blockSignals(false);
Chris@285 627 }
Chris@285 628
Chris@285 629 void
Chris@335 630 PropertyBox::propertyControllerChanged(bool on)
Chris@335 631 {
Chris@335 632 propertyControllerChanged(on ? 1 : 0);
Chris@335 633 }
Chris@335 634
Chris@335 635 void
Chris@0 636 PropertyBox::propertyControllerChanged(int value)
Chris@0 637 {
Chris@0 638 QObject *obj = sender();
Chris@0 639 QString name = obj->objectName();
Chris@0 640
Chris@34 641 #ifdef DEBUG_PROPERTY_BOX
Chris@1266 642 SVDEBUG << "PropertyBox::propertyControllerChanged(" << name << ", " << value << ")" << endl;
Chris@34 643 #endif
Chris@0 644
Chris@0 645 PropertyContainer::PropertyType type = m_container->getPropertyType(name);
Chris@100 646
Chris@376 647 Command *c = 0;
Chris@376 648
Chris@100 649 if (type == PropertyContainer::UnitsProperty) {
Chris@285 650
Chris@1196 651 NotifyingComboBox *cb = qobject_cast<NotifyingComboBox *>(obj);
Chris@100 652 if (cb) {
Chris@100 653 QString unit = cb->currentText();
Chris@376 654 c = m_container->getSetPropertyCommand
Chris@100 655 (name, UnitDatabase::getInstance()->getUnitId(unit));
Chris@100 656 }
Chris@285 657
Chris@100 658 } else if (type != PropertyContainer::InvalidProperty) {
Chris@285 659
Chris@1266 660 c = m_container->getSetPropertyCommand(name, value);
Chris@0 661 }
Chris@376 662
Chris@376 663 if (c) CommandHistory::getInstance()->addCommand(c, true, true);
Chris@218 664
Chris@218 665 updateContextHelp(obj);
Chris@0 666 }
Chris@285 667
Chris@285 668 void
Chris@377 669 PropertyBox::playAudibleChanged(bool audible)
Chris@377 670 {
Chris@1180 671 m_playButton->setChecked(audible);
Chris@377 672 }
Chris@377 673
Chris@377 674 void
Chris@377 675 PropertyBox::playAudibleButtonChanged(bool audible)
Chris@377 676 {
Chris@377 677 PlayParameters *params = m_container->getPlayParameters();
Chris@377 678 if (!params) return;
Chris@377 679
Chris@377 680 if (params->isPlayAudible() != audible) {
Chris@377 681 PlayParameterRepository::EditCommand *command =
Chris@377 682 new PlayParameterRepository::EditCommand(params);
Chris@377 683 command->setPlayAudible(audible);
Chris@377 684 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 685 }
Chris@377 686 }
Chris@34 687
Chris@34 688 void
Chris@1178 689 PropertyBox::playGainControlChanged(float gain)
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@377 696 if (params->getPlayGain() != gain) {
Chris@377 697 PlayParameterRepository::EditCommand *command =
Chris@377 698 new PlayParameterRepository::EditCommand(params);
Chris@377 699 command->setPlayGain(gain);
Chris@377 700 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 701 }
Chris@377 702
Chris@218 703 updateContextHelp(obj);
Chris@34 704 }
Chris@34 705
Chris@34 706 void
Chris@1178 707 PropertyBox::playPanControlChanged(float pan)
Chris@34 708 {
Chris@218 709 QObject *obj = sender();
Chris@377 710
Chris@377 711 PlayParameters *params = m_container->getPlayParameters();
Chris@377 712 if (!params) return;
Chris@377 713
Chris@377 714 if (params->getPlayPan() != pan) {
Chris@377 715 PlayParameterRepository::EditCommand *command =
Chris@377 716 new PlayParameterRepository::EditCommand(params);
Chris@377 717 command->setPlayPan(pan);
Chris@377 718 CommandHistory::getInstance()->addCommand(command, true, true);
Chris@377 719 }
Chris@377 720
Chris@218 721 updateContextHelp(obj);
Chris@34 722 }
Chris@769 723
Chris@63 724 void
Chris@769 725 PropertyBox::editPlayParameters()
Chris@63 726 {
Chris@63 727 PlayParameters *params = m_container->getPlayParameters();
Chris@63 728 if (!params) return;
Chris@63 729
Chris@769 730 QString clip = params->getPlayClipId();
Chris@377 731
Chris@377 732 PlayParameterRepository::EditCommand *command =
Chris@377 733 new PlayParameterRepository::EditCommand(params);
Chris@63 734
Chris@769 735 QInputDialog *dialog = new QInputDialog(this);
Chris@63 736
Chris@769 737 QDir dir(":/samples");
Chris@769 738 QStringList clipFiles = dir.entryList(QStringList() << "*.wav", QDir::Files);
Chris@63 739
Chris@769 740 QStringList clips;
Chris@769 741 foreach (QString str, clipFiles) {
Chris@769 742 clips.push_back(str.replace(".wav", ""));
Chris@769 743 }
Chris@769 744 dialog->setComboBoxItems(clips);
Chris@63 745
Chris@769 746 dialog->setLabelText(tr("Set playback clip:"));
Chris@769 747
Chris@769 748 QComboBox *cb = dialog->findChild<QComboBox *>();
Chris@779 749 if (cb) {
Chris@779 750 for (int i = 0; i < cb->count(); ++i) {
Chris@779 751 if (cb->itemText(i) == clip) {
Chris@779 752 cb->setCurrentIndex(i);
Chris@779 753 }
Chris@779 754 }
Chris@779 755 }
Chris@769 756
Chris@769 757 connect(dialog, SIGNAL(textValueChanged(QString)),
Chris@769 758 this, SLOT(playClipChanged(QString)));
Chris@64 759
Chris@63 760 if (dialog->exec() == QDialog::Accepted) {
Chris@769 761 QString newClip = dialog->textValue();
Chris@769 762 command->setPlayClipId(newClip);
Chris@377 763 CommandHistory::getInstance()->addCommand(command, true);
Chris@64 764 } else {
Chris@377 765 delete command;
Chris@64 766 // restore in case we mucked about with the configuration
Chris@64 767 // as a consequence of signals from the dialog
Chris@769 768 params->setPlayClipId(clip);
Chris@63 769 }
Chris@63 770
Chris@63 771 delete dialog;
Chris@63 772 }
Chris@63 773
Chris@64 774 void
Chris@769 775 PropertyBox::playClipChanged(QString id)
Chris@64 776 {
Chris@64 777 PlayParameters *params = m_container->getPlayParameters();
Chris@64 778 if (!params) return;
Chris@64 779
Chris@769 780 params->setPlayClipId(id);
Chris@64 781 }
Chris@769 782
Chris@185 783 void
Chris@185 784 PropertyBox::layerVisibilityChanged(bool visible)
Chris@185 785 {
Chris@185 786 if (m_showButton) m_showButton->setState(visible);
Chris@185 787 }
Chris@189 788
Chris@189 789 void
Chris@189 790 PropertyBox::mouseEnteredWidget()
Chris@189 791 {
Chris@218 792 updateContextHelp(sender());
Chris@218 793 }
Chris@218 794
Chris@218 795 void
Chris@218 796 PropertyBox::updateContextHelp(QObject *o)
Chris@218 797 {
Chris@1196 798 QWidget *w = qobject_cast<QWidget *>(o);
Chris@189 799 if (!w) return;
Chris@218 800
Chris@189 801 if (!m_container) return;
Chris@190 802 QString cname = m_container->getPropertyContainerName();
Chris@189 803 if (cname == "") return;
Chris@189 804
Chris@1380 805 QString help;
Chris@1380 806 QString mainText;
Chris@1380 807 QString extraText;
Chris@1380 808 QString editText;
Chris@1380 809
Chris@1380 810 QString wname = w->objectName();
Chris@1380 811 QString propertyLabel;
Chris@1380 812 if (wname != "") {
Chris@1380 813 propertyLabel = m_container->getPropertyLabel(wname);
Chris@1180 814 }
Chris@1180 815
Chris@1380 816 LevelPanToolButton *lp = qobject_cast<LevelPanToolButton *>(w);
Chris@1380 817 AudioDial *dial = qobject_cast<AudioDial *>(w);
Chris@189 818
Chris@1380 819 if (lp) {
Chris@1380 820
Chris@1380 821 mainText = tr("Adjust playback level and pan of %1").arg(cname);
Chris@1380 822 editText = tr("click then drag to adjust, ctrl+click to reset");
Chris@1380 823
Chris@1380 824 } else if (wname == "playParamButton") {
Chris@1380 825
Chris@1180 826 PlayParameters *params = m_container->getPlayParameters();
Chris@1180 827 if (params) {
Chris@1380 828 help = tr("Change sound used for playback (currently \"%1\")")
Chris@1380 829 .arg(params->getPlayClipId());
Chris@1180 830 }
Chris@1380 831
Chris@1380 832 } else if (dial) {
Chris@1380 833
Chris@908 834 double mv = dial->mappedValue();
Chris@218 835 QString unit = "";
Chris@218 836 if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit();
Chris@218 837 if (unit != "") {
Chris@218 838 extraText = tr(" (current value: %1%2)").arg(mv).arg(unit);
Chris@218 839 } else {
Chris@218 840 extraText = tr(" (current value: %1)").arg(mv);
Chris@218 841 }
Chris@1380 842 editText = tr("drag up/down to adjust, ctrl+click to reset");
Chris@1380 843
Chris@1380 844 } else if (w == m_showButton) {
Chris@1380 845 help = tr("Toggle Visibility of %1").arg(cname);
Chris@1380 846
Chris@1380 847 } else if (w == m_playButton) {
Chris@1380 848 help = tr("Toggle Playback of %1").arg(cname);
Chris@1380 849
Chris@218 850 }
Chris@218 851
Chris@1380 852 if (help == "" && wname != "") {
Chris@1380 853
Chris@1380 854 if (qobject_cast<QAbstractButton *>(w)) {
Chris@1380 855 mainText = tr("Toggle %1 property of %2")
Chris@1380 856 .arg(propertyLabel).arg(cname);
Chris@1380 857
Chris@1380 858 } else {
Chris@1380 859
Chris@1380 860 // Last param empty for historical reasons, to avoid
Chris@1380 861 // changing tr() string
Chris@1380 862 mainText = tr("Adjust %1 property of %2%3")
Chris@1380 863 .arg(propertyLabel).arg(cname).arg("");
Chris@1380 864 }
Chris@1377 865 }
Chris@1380 866
Chris@1380 867 if (help == "") {
Chris@1380 868 if (mainText != "") {
Chris@1380 869 if (editText != "") {
Chris@1380 870 help = tr("%1%2: %3")
Chris@1380 871 .arg(mainText).arg(extraText).arg(editText);
Chris@1380 872 } else {
Chris@1380 873 help = tr("%1%2")
Chris@1380 874 .arg(mainText).arg(extraText);
Chris@1380 875 }
Chris@1380 876 }
Chris@1380 877 }
Chris@1380 878
Chris@1380 879 if (help != "") {
Chris@1380 880 emit contextHelpChanged(help);
Chris@189 881 }
Chris@189 882 }
Chris@189 883
Chris@189 884 void
Chris@189 885 PropertyBox::mouseLeftWidget()
Chris@189 886 {
Chris@218 887 if (!(QApplication::mouseButtons() & Qt::LeftButton)) {
Chris@218 888 emit contextHelpChanged("");
Chris@218 889 }
Chris@189 890 }
Chris@189 891
Chris@64 892