svgui  1.9
PropertyBox.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "PropertyBox.h"
00017 #include "PluginParameterDialog.h"
00018 
00019 #include "base/PropertyContainer.h"
00020 #include "base/PlayParameters.h"
00021 #include "base/PlayParameterRepository.h"
00022 #include "layer/Layer.h"
00023 #include "layer/ColourDatabase.h"
00024 #include "base/UnitDatabase.h"
00025 #include "base/RangeMapper.h"
00026 
00027 #include "AudioDial.h"
00028 #include "LEDButton.h"
00029 #include "IconLoader.h"
00030 
00031 #include "NotifyingCheckBox.h"
00032 #include "NotifyingComboBox.h"
00033 #include "NotifyingPushButton.h"
00034 #include "ColourNameDialog.h"
00035 
00036 #include <QGridLayout>
00037 #include <QHBoxLayout>
00038 #include <QVBoxLayout>
00039 #include <QPushButton>
00040 #include <QLabel>
00041 #include <QFrame>
00042 #include <QApplication>
00043 #include <QColorDialog>
00044 #include <QInputDialog>
00045 #include <QDir>
00046 
00047 #include <cassert>
00048 #include <iostream>
00049 #include <cmath>
00050 
00051 //#define DEBUG_PROPERTY_BOX 1
00052 
00053 PropertyBox::PropertyBox(PropertyContainer *container) :
00054     m_container(container),
00055     m_showButton(0),
00056     m_playButton(0)
00057 {
00058 #ifdef DEBUG_PROPERTY_BOX
00059     cerr << "PropertyBox[" << this << "(\"" <<
00060         container->getPropertyContainerName() << "\" at " << container << ")]::PropertyBox" << endl;
00061 #endif
00062 
00063     m_mainBox = new QVBoxLayout;
00064     setLayout(m_mainBox);
00065 
00066 //    m_nameWidget = new QLabel;
00067 //    m_mainBox->addWidget(m_nameWidget);
00068 //    m_nameWidget->setText(container->objectName());
00069 
00070     m_mainWidget = new QWidget;
00071     m_mainBox->addWidget(m_mainWidget);
00072     m_mainBox->insertStretch(2, 10);
00073 
00074     m_viewPlayFrame = 0;
00075     populateViewPlayFrame();
00076 
00077     m_layout = new QGridLayout;
00078     m_layout->setMargin(0);
00079     m_layout->setHorizontalSpacing(2);
00080     m_layout->setVerticalSpacing(1);
00081     m_mainWidget->setLayout(m_layout);
00082 
00083     PropertyContainer::PropertyList properties = m_container->getProperties();
00084 
00085     blockSignals(true);
00086 
00087     size_t i;
00088 
00089     for (i = 0; i < properties.size(); ++i) {
00090         updatePropertyEditor(properties[i]);
00091     }
00092 
00093     blockSignals(false);
00094 
00095     m_layout->setRowStretch(m_layout->rowCount(), 10);
00096 
00097     connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()),
00098             this, SLOT(unitDatabaseChanged()));
00099 
00100     connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()),
00101             this, SLOT(colourDatabaseChanged()));
00102 
00103 #ifdef DEBUG_PROPERTY_BOX
00104     cerr << "PropertyBox[" << this << "]::PropertyBox returning" << endl;
00105 #endif
00106 }
00107 
00108 PropertyBox::~PropertyBox()
00109 {
00110 #ifdef DEBUG_PROPERTY_BOX
00111     cerr << "PropertyBox[" << this << "]::~PropertyBox" << endl;
00112 #endif
00113 }
00114 
00115 void
00116 PropertyBox::populateViewPlayFrame()
00117 {
00118 #ifdef DEBUG_PROPERTY_BOX
00119     cerr << "PropertyBox[" << this << ":" << m_container << "]::populateViewPlayFrame" << endl;
00120 #endif
00121 
00122     if (m_viewPlayFrame) {
00123         delete m_viewPlayFrame;
00124         m_viewPlayFrame = 0;
00125     }
00126 
00127     if (!m_container) return;
00128 
00129     Layer *layer = dynamic_cast<Layer *>(m_container);
00130     if (layer) {
00131         disconnect(layer, SIGNAL(modelReplaced()),
00132                    this, SLOT(populateViewPlayFrame()));
00133         connect(layer, SIGNAL(modelReplaced()),
00134                 this, SLOT(populateViewPlayFrame()));
00135     }
00136 
00137     PlayParameters *params = m_container->getPlayParameters();
00138     if (!params && !layer) return;
00139 
00140     m_viewPlayFrame = new QFrame;
00141     m_viewPlayFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
00142     m_mainBox->addWidget(m_viewPlayFrame);
00143 
00144     QHBoxLayout *layout = new QHBoxLayout;
00145     m_viewPlayFrame->setLayout(layout);
00146 
00147     layout->setMargin(layout->margin() / 2);
00148 
00149 #ifdef DEBUG_PROPERTY_BOX
00150     SVDEBUG << "PropertyBox::populateViewPlayFrame: container " << m_container << " (name " << m_container->getPropertyContainerName() << ") params " << params << endl;
00151 #endif
00152 
00153     if (layer) {
00154         QLabel *showLabel = new QLabel(tr("Show"));
00155         layout->addWidget(showLabel);
00156         layout->setAlignment(showLabel, Qt::AlignVCenter);
00157 
00158         m_showButton = new LEDButton(Qt::blue);
00159         layout->addWidget(m_showButton);
00160         connect(m_showButton, SIGNAL(stateChanged(bool)),
00161                 this, SIGNAL(showLayer(bool)));
00162         connect(m_showButton, SIGNAL(mouseEntered()),
00163                 this, SLOT(mouseEnteredWidget()));
00164         connect(m_showButton, SIGNAL(mouseLeft()),
00165                 this, SLOT(mouseLeftWidget()));
00166         layout->setAlignment(m_showButton, Qt::AlignVCenter);
00167     }
00168     
00169     if (params) {
00170 
00171         QLabel *playLabel = new QLabel(tr("Play"));
00172         layout->addWidget(playLabel);
00173         layout->setAlignment(playLabel, Qt::AlignVCenter);
00174 
00175         m_playButton = new LEDButton(Qt::darkGreen);
00176         m_playButton->setState(!params->isPlayMuted());
00177         layout->addWidget(m_playButton);
00178         connect(m_playButton, SIGNAL(stateChanged(bool)),
00179                 this, SLOT(playAudibleButtonChanged(bool)));
00180         connect(m_playButton, SIGNAL(mouseEntered()),
00181                 this, SLOT(mouseEnteredWidget()));
00182         connect(m_playButton, SIGNAL(mouseLeft()),
00183                 this, SLOT(mouseLeftWidget()));
00184         connect(params, SIGNAL(playAudibleChanged(bool)),
00185                 this, SLOT(playAudibleChanged(bool)));
00186         layout->setAlignment(m_playButton, Qt::AlignVCenter);
00187 
00188         layout->insertStretch(-1, 10);
00189 
00190         if (params->getPlayClipId() != "") {
00191             QPushButton *playParamButton =
00192                 new QPushButton(QIcon(":icons/faders.png"), "");
00193             playParamButton->setFixedWidth(24);
00194             playParamButton->setFixedHeight(24);
00195             layout->addWidget(playParamButton);
00196             connect(playParamButton, SIGNAL(clicked()),
00197                     this, SLOT(editPlayParameters()));
00198         }
00199 
00200         AudioDial *gainDial = new AudioDial;
00201         layout->addWidget(gainDial);
00202         gainDial->setMeterColor(Qt::darkRed);
00203         gainDial->setMinimum(-50);
00204         gainDial->setMaximum(50);
00205         gainDial->setPageStep(1);
00206         gainDial->setFixedWidth(24);
00207         gainDial->setFixedHeight(24);
00208         gainDial->setNotchesVisible(false);
00209         gainDial->setDefaultValue(0);
00210         gainDial->setObjectName(tr("Playback Gain"));
00211         gainDial->setRangeMapper(new LinearRangeMapper
00212                                  (-50, 50, -25, 25, tr("dB")));
00213         gainDial->setShowToolTip(true);
00214         connect(gainDial, SIGNAL(valueChanged(int)),
00215                 this, SLOT(playGainDialChanged(int)));
00216         connect(params, SIGNAL(playGainChanged(float)),
00217                 this, SLOT(playGainChanged(float)));
00218         connect(this, SIGNAL(changePlayGainDial(int)),
00219                 gainDial, SLOT(setValue(int)));
00220         connect(gainDial, SIGNAL(mouseEntered()),
00221                 this, SLOT(mouseEnteredWidget()));
00222         connect(gainDial, SIGNAL(mouseLeft()),
00223                 this, SLOT(mouseLeftWidget()));
00224         playGainChanged(params->getPlayGain());
00225         layout->setAlignment(gainDial, Qt::AlignVCenter);
00226 
00227         AudioDial *panDial = new AudioDial;
00228         layout->addWidget(panDial);
00229         panDial->setMeterColor(Qt::darkGreen);
00230         panDial->setMinimum(-50);
00231         panDial->setMaximum(50);
00232         panDial->setPageStep(1);
00233         panDial->setFixedWidth(24);
00234         panDial->setFixedHeight(24);
00235         panDial->setNotchesVisible(false);
00236         panDial->setToolTip(tr("Playback Pan / Balance"));
00237         panDial->setDefaultValue(0);
00238         panDial->setObjectName(tr("Playback Pan / Balance"));
00239         panDial->setShowToolTip(true);
00240         connect(panDial, SIGNAL(valueChanged(int)),
00241                 this, SLOT(playPanDialChanged(int)));
00242         connect(params, SIGNAL(playPanChanged(float)),
00243                 this, SLOT(playPanChanged(float)));
00244         connect(this, SIGNAL(changePlayPanDial(int)),
00245                 panDial, SLOT(setValue(int)));
00246         connect(panDial, SIGNAL(mouseEntered()),
00247                 this, SLOT(mouseEnteredWidget()));
00248         connect(panDial, SIGNAL(mouseLeft()),
00249                 this, SLOT(mouseLeftWidget()));
00250         playPanChanged(params->getPlayPan());
00251         layout->setAlignment(panDial, Qt::AlignVCenter);
00252 
00253     } else {
00254 
00255         layout->insertStretch(-1, 10);
00256     }
00257 }
00258 
00259 void
00260 PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name,
00261                                   bool rangeChanged)
00262 {
00263     PropertyContainer::PropertyType type = m_container->getPropertyType(name);
00264     int row = m_layout->rowCount();
00265 
00266     int min = 0, max = 0, value = 0, deflt = 0;
00267     value = m_container->getPropertyRangeAndValue(name, &min, &max, &deflt);
00268 
00269     bool have = (m_propertyControllers.find(name) !=
00270                  m_propertyControllers.end());
00271 
00272     QString groupName = m_container->getPropertyGroupName(name);
00273     QString propertyLabel = m_container->getPropertyLabel(name);
00274     QString iconName = m_container->getPropertyIconName(name);
00275 
00276 #ifdef DEBUG_PROPERTY_BOX
00277     cerr << "PropertyBox[" << this
00278               << "(\"" << m_container->getPropertyContainerName()
00279               << "\")]";
00280     cerr << "::updatePropertyEditor(\"" << name << "\"):";
00281     cerr << " value " << value << ", have " << have << ", group \""
00282               << groupName << "\"" << endl;
00283 #endif
00284 
00285     bool inGroup = (groupName != QString());
00286 
00287     if (!have) {
00288         if (inGroup) {
00289             if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) {
00290 #ifdef DEBUG_PROPERTY_BOX
00291                 cerr << "PropertyBox: adding label \"" << groupName << "\" and frame for group for \"" << name << "\"" << endl;
00292 #endif
00293                 m_layout->addWidget(new QLabel(groupName, m_mainWidget), row, 0);
00294                 QFrame *frame = new QFrame(m_mainWidget);
00295                 m_layout->addWidget(frame, row, 1, 1, 2);
00296                 m_groupLayouts[groupName] = new QGridLayout;
00297                 m_groupLayouts[groupName]->setMargin(0);
00298                 frame->setLayout(m_groupLayouts[groupName]);
00299             }
00300         } else {
00301 #ifdef DEBUG_PROPERTY_BOX 
00302             cerr << "PropertyBox: adding label \"" << propertyLabel << "\"" << endl;
00303 #endif
00304             m_layout->addWidget(new QLabel(propertyLabel, m_mainWidget), row, 0);
00305         }
00306     }
00307 
00308     switch (type) {
00309 
00310     case PropertyContainer::ToggleProperty:
00311     {
00312         QAbstractButton *button = 0;
00313 
00314         if (have) {
00315             button = dynamic_cast<QAbstractButton *>(m_propertyControllers[name]);
00316             assert(button);
00317         } else {
00318 #ifdef DEBUG_PROPERTY_BOX 
00319             cerr << "PropertyBox: creating new checkbox" << endl;
00320 #endif
00321             if (iconName != "") {
00322                 button = new NotifyingPushButton();
00323                 button->setCheckable(true);
00324                 QIcon icon(IconLoader().load(iconName));
00325                 button->setIcon(icon);
00326                 button->setObjectName(name);
00327                 button->setFixedSize(QSize(18, 18));
00328             } else {
00329                 button = new NotifyingCheckBox();
00330                 button->setObjectName(name);
00331             }
00332             connect(button, SIGNAL(toggled(bool)),
00333                     this, SLOT(propertyControllerChanged(bool)));
00334             connect(button, SIGNAL(mouseEntered()),
00335                     this, SLOT(mouseEnteredWidget()));
00336             connect(button, SIGNAL(mouseLeft()),
00337                     this, SLOT(mouseLeftWidget()));
00338             if (inGroup) {
00339                 button->setToolTip(propertyLabel);
00340                 m_groupLayouts[groupName]->addWidget
00341                     (button, 0, m_groupLayouts[groupName]->columnCount());
00342             } else {
00343                 m_layout->addWidget(button, row, 1, 1, 2);
00344             }
00345             m_propertyControllers[name] = button;
00346         }
00347 
00348         if (button->isChecked() != (value > 0)) {
00349             button->blockSignals(true);
00350             button->setChecked(value > 0);
00351             button->blockSignals(false);
00352         }
00353         break;
00354     }
00355 
00356     case PropertyContainer::RangeProperty:
00357     {
00358         AudioDial *dial;
00359 
00360         if (have) {
00361             dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]);
00362             assert(dial);
00363             if (rangeChanged) {
00364                 dial->blockSignals(true);
00365                 dial->setMinimum(min);
00366                 dial->setMaximum(max);
00367                 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
00368                 dial->blockSignals(false);
00369             }
00370                 
00371         } else {
00372 #ifdef DEBUG_PROPERTY_BOX 
00373             cerr << "PropertyBox: creating new dial" << endl;
00374 #endif
00375             dial = new AudioDial();
00376             dial->setObjectName(name);
00377             dial->setMinimum(min);
00378             dial->setMaximum(max);
00379             dial->setPageStep(1);
00380             dial->setNotchesVisible((max - min) <= 12);
00381             dial->setDefaultValue(deflt);
00382             dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name));
00383             dial->setShowToolTip(true);
00384             connect(dial, SIGNAL(valueChanged(int)),
00385                     this, SLOT(propertyControllerChanged(int)));
00386             connect(dial, SIGNAL(mouseEntered()),
00387                     this, SLOT(mouseEnteredWidget()));
00388             connect(dial, SIGNAL(mouseLeft()),
00389                     this, SLOT(mouseLeftWidget()));
00390 
00391             if (inGroup) {
00392                 dial->setFixedWidth(24);
00393                 dial->setFixedHeight(24);
00394                 m_groupLayouts[groupName]->addWidget
00395                     (dial, 0, m_groupLayouts[groupName]->columnCount());
00396             } else {
00397                 dial->setFixedWidth(32);
00398                 dial->setFixedHeight(32);
00399                 m_layout->addWidget(dial, row, 1);
00400                 QLabel *label = new QLabel(m_mainWidget);
00401                 connect(dial, SIGNAL(valueChanged(int)),
00402                         label, SLOT(setNum(int)));
00403                 label->setNum(value);
00404                 m_layout->addWidget(label, row, 2);
00405             }
00406 
00407             m_propertyControllers[name] = dial;
00408         }
00409 
00410         if (dial->value() != value) {
00411             dial->blockSignals(true);
00412             dial->setValue(value);
00413             dial->blockSignals(false);
00414         }
00415         break;
00416     }
00417 
00418     case PropertyContainer::ValueProperty:
00419     case PropertyContainer::UnitsProperty:
00420     case PropertyContainer::ColourProperty:
00421     {
00422         NotifyingComboBox *cb;
00423 
00424         if (have) {
00425             cb = dynamic_cast<NotifyingComboBox *>(m_propertyControllers[name]);
00426             assert(cb);
00427         } else {
00428 #ifdef DEBUG_PROPERTY_BOX 
00429             cerr << "PropertyBox: creating new combobox" << endl;
00430 #endif
00431 
00432             cb = new NotifyingComboBox();
00433             cb->setObjectName(name);
00434             cb->setDuplicatesEnabled(false);
00435         }
00436 
00437         if (!have || rangeChanged) {
00438 
00439             cb->blockSignals(true);
00440             cb->clear();
00441             cb->setEditable(false);
00442 
00443             if (type == PropertyContainer::ValueProperty) {
00444 
00445                 for (int i = min; i <= max; ++i) {
00446                     cb->addItem(m_container->getPropertyValueLabel(name, i));
00447                 }
00448 
00449             } else if (type == PropertyContainer::UnitsProperty) {
00450 
00451                 QStringList units = UnitDatabase::getInstance()->getKnownUnits();
00452                 for (int i = 0; i < units.size(); ++i) {
00453                     cb->addItem(units[i]);
00454                 }
00455 
00456                 cb->setEditable(true);
00457 
00458             } else { // ColourProperty
00459 
00461                 // manages its own Add New Colour entry...
00462                 
00463                 ColourDatabase *db = ColourDatabase::getInstance();
00464                 for (int i = 0; i < db->getColourCount(); ++i) {
00465                     QString name = db->getColourName(i);
00466                     cb->addItem(db->getExamplePixmap(i, QSize(12, 12)), name);
00467                 }
00468                 cb->addItem(tr("Add New Colour..."));
00469             }                
00470                 
00471             cb->blockSignals(false);
00472             if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) {
00473                 cb->setMaxVisibleItems(cb->count());
00474             }
00475         }
00476 
00477         if (!have) {
00478             connect(cb, SIGNAL(activated(int)),
00479                     this, SLOT(propertyControllerChanged(int)));
00480             connect(cb, SIGNAL(mouseEntered()),
00481                     this, SLOT(mouseEnteredWidget()));
00482             connect(cb, SIGNAL(mouseLeft()),
00483                     this, SLOT(mouseLeftWidget()));
00484 
00485             if (inGroup) {
00486                 cb->setToolTip(propertyLabel);
00487                 m_groupLayouts[groupName]->addWidget
00488                     (cb, 0, m_groupLayouts[groupName]->columnCount());
00489             } else {
00490                 m_layout->addWidget(cb, row, 1, 1, 2);
00491             }
00492             m_propertyControllers[name] = cb;
00493         }
00494 
00495         cb->blockSignals(true);
00496         if (type == PropertyContainer::ValueProperty ||
00497             type == PropertyContainer::ColourProperty) {
00498             if (cb->currentIndex() != value) {
00499                 cb->setCurrentIndex(value);
00500             }
00501         } else {
00502             QString unit = UnitDatabase::getInstance()->getUnitById(value);
00503             if (cb->currentText() != unit) {
00504                 for (int i = 0; i < cb->count(); ++i) {
00505                     if (cb->itemText(i) == unit) {
00506                         cb->setCurrentIndex(i);
00507                         break;
00508                     }
00509                 }
00510             }
00511         }
00512         cb->blockSignals(false);
00513 
00514 #ifdef Q_OS_MAC
00515         // Crashes on startup without this, for some reason
00516         cb->setMinimumSize(QSize(10, 10));
00517 #endif
00518 
00519         break;
00520     }
00521 
00522     case PropertyContainer::InvalidProperty:
00523     default:
00524         break;
00525     }
00526 }
00527 
00528 void
00529 PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc)
00530 {
00531     if (pc != m_container) return;
00532     
00533 #ifdef DEBUG_PROPERTY_BOX
00534     SVDEBUG << "PropertyBox::propertyContainerPropertyChanged" << endl;
00535 #endif
00536 
00537     PropertyContainer::PropertyList properties = m_container->getProperties();
00538     size_t i;
00539 
00540     blockSignals(true);
00541 
00542     for (i = 0; i < properties.size(); ++i) {
00543         updatePropertyEditor(properties[i]);
00544     }
00545 
00546     blockSignals(false);
00547 }
00548 
00549 void
00550 PropertyBox::propertyContainerPropertyRangeChanged(PropertyContainer *)
00551 {
00552     blockSignals(true);
00553 
00554     PropertyContainer::PropertyList properties = m_container->getProperties();
00555     for (size_t i = 0; i < properties.size(); ++i) {
00556         updatePropertyEditor(properties[i], true);
00557     }
00558 
00559     blockSignals(false);
00560 }    
00561 
00562 void
00563 PropertyBox::unitDatabaseChanged()
00564 {
00565 #ifdef DEBUG_PROPERTY_BOX
00566     cerr << "PropertyBox[" << this << "]: unitDatabaseChanged" << endl;
00567 #endif
00568     blockSignals(true);
00569 
00570 //    cerr << "my container is " << m_container << endl;
00571 //    cerr << "my container's name is... " << endl;
00572 //    cerr << m_container->objectName() << endl;
00573 
00574     PropertyContainer::PropertyList properties = m_container->getProperties();
00575     for (size_t i = 0; i < properties.size(); ++i) {
00576         if (m_container->getPropertyType(properties[i]) ==
00577             PropertyContainer::UnitsProperty) {
00578             updatePropertyEditor(properties[i]);
00579         }
00580     }
00581 
00582     blockSignals(false);
00583 }    
00584 
00585 void
00586 PropertyBox::colourDatabaseChanged()
00587 {
00588     blockSignals(true);
00589 
00590     PropertyContainer::PropertyList properties = m_container->getProperties();
00591     for (size_t i = 0; i < properties.size(); ++i) {
00592         if (m_container->getPropertyType(properties[i]) ==
00593             PropertyContainer::ColourProperty) {
00594             updatePropertyEditor(properties[i], true);
00595         }
00596     }
00597 
00598     blockSignals(false);
00599 }    
00600 
00601 void
00602 PropertyBox::propertyControllerChanged(bool on)
00603 {
00604     propertyControllerChanged(on ? 1 : 0);
00605 }
00606 
00607 void
00608 PropertyBox::propertyControllerChanged(int value)
00609 {
00610     QObject *obj = sender();
00611     QString name = obj->objectName();
00612 
00613 #ifdef DEBUG_PROPERTY_BOX
00614     SVDEBUG << "PropertyBox::propertyControllerChanged(" << name              << ", " << value << ")" << endl;
00615 #endif
00616     
00617     PropertyContainer::PropertyType type = m_container->getPropertyType(name);
00618 
00619     Command *c = 0;
00620 
00621     if (type == PropertyContainer::UnitsProperty) {
00622 
00623         NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj);
00624         if (cb) {
00625             QString unit = cb->currentText();
00626             c = m_container->getSetPropertyCommand
00627                 (name, UnitDatabase::getInstance()->getUnitId(unit));
00628         }
00629 
00630     } else if (type == PropertyContainer::ColourProperty) {
00631 
00632         if (value == int(ColourDatabase::getInstance()->getColourCount())) {
00633             addNewColour();
00634             if (value == int(ColourDatabase::getInstance()->getColourCount())) {
00635                 propertyContainerPropertyChanged(m_container);
00636                 return;
00637             }
00638         }
00639         c = m_container->getSetPropertyCommand(name, value);
00640 
00641     } else if (type != PropertyContainer::InvalidProperty) {
00642 
00643         c = m_container->getSetPropertyCommand(name, value);
00644     }
00645 
00646     if (c) CommandHistory::getInstance()->addCommand(c, true, true);
00647     
00648     updateContextHelp(obj);
00649 }
00650 
00651 void
00652 PropertyBox::addNewColour()
00653 {
00654     QColor newColour = QColorDialog::getColor();
00655     if (!newColour.isValid()) return;
00656 
00657     ColourNameDialog dialog(tr("Name New Colour"),
00658                             tr("Enter a name for the new colour:"),
00659                             newColour, newColour.name(), this);
00660     dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour"));
00661     if (dialog.exec() == QDialog::Accepted) {
00663         ColourDatabase *db = ColourDatabase::getInstance();
00664         int index = db->addColour(newColour, dialog.getColourName());
00665         db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked());
00666     }
00667 }
00668 
00669 void
00670 PropertyBox::playAudibleChanged(bool audible)
00671 {
00672     m_playButton->setState(audible);
00673 }
00674 
00675 void
00676 PropertyBox::playAudibleButtonChanged(bool audible)
00677 {
00678     PlayParameters *params = m_container->getPlayParameters();
00679     if (!params) return;
00680 
00681     if (params->isPlayAudible() != audible) {
00682         PlayParameterRepository::EditCommand *command =
00683             new PlayParameterRepository::EditCommand(params);
00684         command->setPlayAudible(audible);
00685         CommandHistory::getInstance()->addCommand(command, true, true);
00686     }
00687 }
00688     
00689 void
00690 PropertyBox::playGainChanged(float gain)
00691 {
00692     int dialValue = lrint(log10(gain) * 20.0);
00693     if (dialValue < -50) dialValue = -50;
00694     if (dialValue >  50) dialValue =  50;
00695     emit changePlayGainDial(dialValue);
00696 }
00697 
00698 void
00699 PropertyBox::playGainDialChanged(int dialValue)
00700 {
00701     QObject *obj = sender();
00702 
00703     PlayParameters *params = m_container->getPlayParameters();
00704     if (!params) return;
00705 
00706     float gain = pow(10, float(dialValue) / 20.0);
00707 
00708     if (params->getPlayGain() != gain) {
00709         PlayParameterRepository::EditCommand *command =
00710             new PlayParameterRepository::EditCommand(params);
00711         command->setPlayGain(gain);
00712         CommandHistory::getInstance()->addCommand(command, true, true);
00713     }
00714 
00715     updateContextHelp(obj);
00716 }
00717     
00718 void
00719 PropertyBox::playPanChanged(float pan)
00720 {
00721     int dialValue = lrint(pan * 50.0);
00722     if (dialValue < -50) dialValue = -50;
00723     if (dialValue >  50) dialValue =  50;
00724     emit changePlayPanDial(dialValue);
00725 }
00726 
00727 void
00728 PropertyBox::playPanDialChanged(int dialValue)
00729 {
00730     QObject *obj = sender();
00731 
00732     PlayParameters *params = m_container->getPlayParameters();
00733     if (!params) return;
00734 
00735     float pan = float(dialValue) / 50.0;
00736     if (pan < -1.0) pan = -1.0;
00737     if (pan >  1.0) pan =  1.0;
00738 
00739     if (params->getPlayPan() != pan) {
00740         PlayParameterRepository::EditCommand *command =
00741             new PlayParameterRepository::EditCommand(params);
00742         command->setPlayPan(pan);
00743         CommandHistory::getInstance()->addCommand(command, true, true);
00744     }
00745 
00746     updateContextHelp(obj);
00747 }
00748 
00749 void
00750 PropertyBox::editPlayParameters()
00751 {
00752     PlayParameters *params = m_container->getPlayParameters();
00753     if (!params) return;
00754 
00755     QString clip = params->getPlayClipId();
00756 
00757     PlayParameterRepository::EditCommand *command = 
00758         new PlayParameterRepository::EditCommand(params);
00759     
00760     QInputDialog *dialog = new QInputDialog(this);
00761 
00762     QDir dir(":/samples");
00763     QStringList clipFiles = dir.entryList(QStringList() << "*.wav", QDir::Files);
00764 
00765     QStringList clips;
00766     foreach (QString str, clipFiles) {
00767         clips.push_back(str.replace(".wav", ""));
00768     }
00769     dialog->setComboBoxItems(clips);
00770 
00771     dialog->setLabelText(tr("Set playback clip:"));
00772 
00773     QComboBox *cb = dialog->findChild<QComboBox *>();
00774     if (cb) {
00775         for (int i = 0; i < cb->count(); ++i) {
00776             if (cb->itemText(i) == clip) {
00777                 cb->setCurrentIndex(i);
00778             }
00779         }
00780     }
00781 
00782     connect(dialog, SIGNAL(textValueChanged(QString)), 
00783             this, SLOT(playClipChanged(QString)));
00784 
00785     if (dialog->exec() == QDialog::Accepted) {
00786         QString newClip = dialog->textValue();
00787         command->setPlayClipId(newClip);
00788         CommandHistory::getInstance()->addCommand(command, true);
00789     } else {
00790         delete command;
00791         // restore in case we mucked about with the configuration
00792         // as a consequence of signals from the dialog
00793         params->setPlayClipId(clip);
00794     }
00795 
00796     delete dialog;
00797 }
00798 
00799 void
00800 PropertyBox::playClipChanged(QString id)
00801 {
00802     PlayParameters *params = m_container->getPlayParameters();
00803     if (!params) return;
00804 
00805     params->setPlayClipId(id);
00806 }    
00807 
00808 void
00809 PropertyBox::layerVisibilityChanged(bool visible)
00810 {
00811     if (m_showButton) m_showButton->setState(visible);
00812 }
00813 
00814 void
00815 PropertyBox::mouseEnteredWidget()
00816 {
00817     updateContextHelp(sender());
00818 }
00819 
00820 void
00821 PropertyBox::updateContextHelp(QObject *o)
00822 {
00823     QWidget *w = dynamic_cast<QWidget *>(o);
00824     if (!w) return;
00825 
00826     if (!m_container) return;
00827     QString cname = m_container->getPropertyContainerName();
00828     if (cname == "") return;
00829 
00830     QString wname = w->objectName();
00831 
00832     QString extraText;
00833     AudioDial *dial = dynamic_cast<AudioDial *>(w);
00834     if (dial) {
00835         float mv = dial->mappedValue();
00836         QString unit = "";
00837         if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit();
00838         if (unit != "") {
00839             extraText = tr(" (current value: %1%2)").arg(mv).arg(unit);
00840         } else {
00841             extraText = tr(" (current value: %1)").arg(mv);
00842         }
00843     }
00844 
00845     if (w == m_showButton) {
00846         emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname));
00847     } else if (w == m_playButton) {
00848         emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname));
00849     } else if (wname == "") {
00850         return;
00851     } else if (dynamic_cast<QAbstractButton *>(w)) {
00852         emit contextHelpChanged(tr("Toggle %1 property of %2")
00853                                 .arg(wname).arg(cname));
00854     } else {
00855         emit contextHelpChanged(tr("Adjust %1 property of %2%3")
00856                                 .arg(wname).arg(cname).arg(extraText));
00857     }
00858 }
00859 
00860 void
00861 PropertyBox::mouseLeftWidget()
00862 {
00863     if (!(QApplication::mouseButtons() & Qt::LeftButton)) {
00864         emit contextHelpChanged("");
00865     }
00866 }
00867 
00868