| 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@0 | 27 #include "AudioDial.h" | 
| Chris@33 | 28 #include "LEDButton.h" | 
| Chris@335 | 29 #include "IconLoader.h" | 
| Chris@1178 | 30 #include "LevelPanWidget.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@285 | 36 #include "ColourNameDialog.h" | 
| Chris@189 | 37 | 
| Chris@0 | 38 #include <QGridLayout> | 
| Chris@0 | 39 #include <QHBoxLayout> | 
| Chris@33 | 40 #include <QVBoxLayout> | 
| Chris@63 | 41 #include <QPushButton> | 
| Chris@0 | 42 #include <QLabel> | 
| Chris@33 | 43 #include <QFrame> | 
| Chris@218 | 44 #include <QApplication> | 
| Chris@285 | 45 #include <QColorDialog> | 
| Chris@285 | 46 #include <QInputDialog> | 
| Chris@769 | 47 #include <QDir> | 
| Chris@0 | 48 | 
| Chris@0 | 49 #include <cassert> | 
| Chris@0 | 50 #include <iostream> | 
| Martin@46 | 51 #include <cmath> | 
| Chris@0 | 52 | 
| Chris@456 | 53 //#define DEBUG_PROPERTY_BOX 1 | 
| Chris@0 | 54 | 
| Chris@0 | 55 PropertyBox::PropertyBox(PropertyContainer *container) : | 
| Chris@185 | 56     m_container(container), | 
| Chris@189 | 57     m_showButton(0), | 
| Chris@189 | 58     m_playButton(0) | 
| Chris@0 | 59 { | 
| Chris@0 | 60 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@682 | 61     cerr << "PropertyBox[" << this << "(\"" << | 
| Chris@682 | 62 	container->getPropertyContainerName() << "\" at " << container << ")]::PropertyBox" << endl; | 
| Chris@0 | 63 #endif | 
| Chris@0 | 64 | 
| Chris@34 | 65     m_mainBox = new QVBoxLayout; | 
| Chris@34 | 66     setLayout(m_mainBox); | 
| Chris@33 | 67 | 
| Chris@980 | 68 #ifdef Q_OS_MAC | 
| Chris@980 | 69     QMargins mm = m_mainBox->contentsMargins(); | 
| Chris@980 | 70     QMargins mmhalf(mm.left()/2, mm.top()/3, mm.right()/2, mm.bottom()/3); | 
| Chris@980 | 71     m_mainBox->setContentsMargins(mmhalf); | 
| Chris@980 | 72 #endif | 
| Chris@980 | 73 | 
| Chris@107 | 74 //    m_nameWidget = new QLabel; | 
| Chris@107 | 75 //    m_mainBox->addWidget(m_nameWidget); | 
| Chris@107 | 76 //    m_nameWidget->setText(container->objectName()); | 
| Chris@107 | 77 | 
| Chris@34 | 78     m_mainWidget = new QWidget; | 
| Chris@34 | 79     m_mainBox->addWidget(m_mainWidget); | 
| Chris@107 | 80     m_mainBox->insertStretch(2, 10); | 
| Chris@33 | 81 | 
| Chris@34 | 82     m_viewPlayFrame = 0; | 
| Chris@34 | 83     populateViewPlayFrame(); | 
| Chris@33 | 84 | 
| Chris@0 | 85     m_layout = new QGridLayout; | 
| Chris@34 | 86     m_layout->setMargin(0); | 
| Chris@833 | 87     m_layout->setHorizontalSpacing(2); | 
| Chris@833 | 88     m_layout->setVerticalSpacing(1); | 
| Chris@33 | 89     m_mainWidget->setLayout(m_layout); | 
| Chris@0 | 90 | 
| Chris@34 | 91     PropertyContainer::PropertyList properties = m_container->getProperties(); | 
| Chris@0 | 92 | 
| Chris@0 | 93     blockSignals(true); | 
| Chris@0 | 94 | 
| Chris@0 | 95     size_t i; | 
| Chris@0 | 96 | 
| Chris@0 | 97     for (i = 0; i < properties.size(); ++i) { | 
| Chris@0 | 98 	updatePropertyEditor(properties[i]); | 
| Chris@0 | 99     } | 
| Chris@0 | 100 | 
| Chris@0 | 101     blockSignals(false); | 
| Chris@0 | 102 | 
| Chris@0 | 103     m_layout->setRowStretch(m_layout->rowCount(), 10); | 
| Chris@0 | 104 | 
| Chris@100 | 105     connect(UnitDatabase::getInstance(), SIGNAL(unitDatabaseChanged()), | 
| Chris@100 | 106             this, SLOT(unitDatabaseChanged())); | 
| Chris@100 | 107 | 
| Chris@285 | 108     connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()), | 
| Chris@285 | 109             this, SLOT(colourDatabaseChanged())); | 
| Chris@285 | 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@34 | 131 	delete m_viewPlayFrame; | 
| Chris@34 | 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@193 | 139 	disconnect(layer, SIGNAL(modelReplaced()), | 
| Chris@193 | 140                    this, SLOT(populateViewPlayFrame())); | 
| Chris@34 | 141 	connect(layer, SIGNAL(modelReplaced()), | 
| Chris@34 | 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@34 | 152     QHBoxLayout *layout = new QHBoxLayout; | 
| 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@36 | 160 | 
| Chris@33 | 161     if (layer) { | 
| Chris@34 | 162 	QLabel *showLabel = new QLabel(tr("Show")); | 
| Chris@34 | 163 	layout->addWidget(showLabel); | 
| Chris@34 | 164 	layout->setAlignment(showLabel, Qt::AlignVCenter); | 
| Chris@34 | 165 | 
| Chris@185 | 166 	m_showButton = new LEDButton(Qt::blue); | 
| Chris@185 | 167 	layout->addWidget(m_showButton); | 
| Chris@185 | 168 	connect(m_showButton, SIGNAL(stateChanged(bool)), | 
| Chris@47 | 169 		this, SIGNAL(showLayer(bool))); | 
| Chris@189 | 170         connect(m_showButton, SIGNAL(mouseEntered()), | 
| Chris@189 | 171                 this, SLOT(mouseEnteredWidget())); | 
| Chris@189 | 172         connect(m_showButton, SIGNAL(mouseLeft()), | 
| Chris@189 | 173                 this, SLOT(mouseLeftWidget())); | 
| Chris@185 | 174 	layout->setAlignment(m_showButton, Qt::AlignVCenter); | 
| Chris@33 | 175     } | 
| Chris@33 | 176 | 
| Chris@33 | 177     if (params) { | 
| Chris@34 | 178 | 
| Chris@34 | 179 	QLabel *playLabel = new QLabel(tr("Play")); | 
| Chris@34 | 180 	layout->addWidget(playLabel); | 
| Chris@34 | 181 	layout->setAlignment(playLabel, Qt::AlignVCenter); | 
| Chris@34 | 182 | 
| Chris@189 | 183 	m_playButton = new LEDButton(Qt::darkGreen); | 
| Chris@189 | 184         m_playButton->setState(!params->isPlayMuted()); | 
| Chris@189 | 185 	layout->addWidget(m_playButton); | 
| Chris@189 | 186 	connect(m_playButton, SIGNAL(stateChanged(bool)), | 
| Chris@377 | 187 		this, SLOT(playAudibleButtonChanged(bool))); | 
| Chris@189 | 188         connect(m_playButton, SIGNAL(mouseEntered()), | 
| Chris@189 | 189                 this, SLOT(mouseEnteredWidget())); | 
| Chris@189 | 190         connect(m_playButton, SIGNAL(mouseLeft()), | 
| Chris@189 | 191                 this, SLOT(mouseLeftWidget())); | 
| Chris@34 | 192 	connect(params, SIGNAL(playAudibleChanged(bool)), | 
| Chris@377 | 193 		this, SLOT(playAudibleChanged(bool))); | 
| Chris@189 | 194 	layout->setAlignment(m_playButton, Qt::AlignVCenter); | 
| Chris@34 | 195 | 
| Chris@34 | 196 	layout->insertStretch(-1, 10); | 
| Chris@34 | 197 | 
| Chris@769 | 198         if (params->getPlayClipId() != "") { | 
| Chris@769 | 199             QPushButton *playParamButton = | 
| Chris@769 | 200                 new QPushButton(QIcon(":icons/faders.png"), ""); | 
| Chris@1174 | 201             playParamButton->setFixedWidth(WidgetScale::scalePixelSize(24)); | 
| Chris@1174 | 202             playParamButton->setFixedHeight(WidgetScale::scalePixelSize(24)); | 
| Chris@769 | 203             layout->addWidget(playParamButton); | 
| Chris@769 | 204             connect(playParamButton, SIGNAL(clicked()), | 
| Chris@769 | 205                     this, SLOT(editPlayParameters())); | 
| Chris@63 | 206         } | 
| Chris@63 | 207 | 
| Chris@1178 | 208         LevelPanWidget *levelPan = new LevelPanWidget; | 
| Chris@1178 | 209         layout->addWidget(levelPan); | 
| Chris@1178 | 210         connect(levelPan, SIGNAL(levelChanged(float)), | 
| Chris@1178 | 211                 this, SLOT(playGainControlChanged(float))); | 
| Chris@1178 | 212         connect(levelPan, SIGNAL(panChanged(float)), | 
| Chris@1178 | 213                 this, SLOT(playPanControlChanged(float))); | 
| Chris@1178 | 214         connect(params, SIGNAL(playGainChanged(float)), | 
| Chris@1178 | 215                 levelPan, SLOT(setLevel(float))); | 
| Chris@1178 | 216         connect(params, SIGNAL(playPanChanged(float)), | 
| Chris@1178 | 217                 levelPan, SLOT(setPan(float))); | 
| Chris@34 | 218 | 
| Chris@34 | 219     } else { | 
| Chris@34 | 220 | 
| Chris@34 | 221 	layout->insertStretch(-1, 10); | 
| Chris@33 | 222     } | 
| Chris@33 | 223 } | 
| Chris@33 | 224 | 
| Chris@33 | 225 void | 
| Chris@197 | 226 PropertyBox::updatePropertyEditor(PropertyContainer::PropertyName name, | 
| Chris@197 | 227                                   bool rangeChanged) | 
| Chris@0 | 228 { | 
| Chris@0 | 229     PropertyContainer::PropertyType type = m_container->getPropertyType(name); | 
| Chris@0 | 230     int row = m_layout->rowCount(); | 
| Chris@0 | 231 | 
| Chris@216 | 232     int min = 0, max = 0, value = 0, deflt = 0; | 
| Chris@216 | 233     value = m_container->getPropertyRangeAndValue(name, &min, &max, &deflt); | 
| Chris@0 | 234 | 
| Chris@0 | 235     bool have = (m_propertyControllers.find(name) != | 
| Chris@0 | 236 		 m_propertyControllers.end()); | 
| Chris@0 | 237 | 
| Chris@0 | 238     QString groupName = m_container->getPropertyGroupName(name); | 
| Chris@87 | 239     QString propertyLabel = m_container->getPropertyLabel(name); | 
| Chris@335 | 240     QString iconName = m_container->getPropertyIconName(name); | 
| Chris@0 | 241 | 
| Chris@0 | 242 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@682 | 243     cerr << "PropertyBox[" << this | 
| Chris@683 | 244 	      << "(\"" << m_container->getPropertyContainerName() | 
| Chris@0 | 245 	      << "\")]"; | 
| Chris@682 | 246     cerr << "::updatePropertyEditor(\"" << name << "\"):"; | 
| Chris@682 | 247     cerr << " value " << value << ", have " << have << ", group \"" | 
| Chris@682 | 248 	      << groupName << "\"" << endl; | 
| Chris@0 | 249 #endif | 
| Chris@0 | 250 | 
| Chris@0 | 251     bool inGroup = (groupName != QString()); | 
| Chris@0 | 252 | 
| Chris@0 | 253     if (!have) { | 
| Chris@0 | 254 	if (inGroup) { | 
| Chris@0 | 255 	    if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) { | 
| Chris@0 | 256 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@682 | 257 		cerr << "PropertyBox: adding label \"" << groupName << "\" and frame for group for \"" << name << "\"" << endl; | 
| Chris@0 | 258 #endif | 
| Chris@33 | 259 		m_layout->addWidget(new QLabel(groupName, m_mainWidget), row, 0); | 
| Chris@33 | 260 		QFrame *frame = new QFrame(m_mainWidget); | 
| Chris@0 | 261 		m_layout->addWidget(frame, row, 1, 1, 2); | 
| Chris@493 | 262 		m_groupLayouts[groupName] = new QGridLayout; | 
| Chris@0 | 263 		m_groupLayouts[groupName]->setMargin(0); | 
| Chris@0 | 264 		frame->setLayout(m_groupLayouts[groupName]); | 
| Chris@0 | 265 	    } | 
| Chris@0 | 266 	} else { | 
| Chris@0 | 267 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@682 | 268 	    cerr << "PropertyBox: adding label \"" << propertyLabel << "\"" << endl; | 
| Chris@0 | 269 #endif | 
| Chris@87 | 270 	    m_layout->addWidget(new QLabel(propertyLabel, m_mainWidget), row, 0); | 
| Chris@0 | 271 	} | 
| Chris@0 | 272     } | 
| Chris@0 | 273 | 
| Chris@0 | 274     switch (type) { | 
| Chris@0 | 275 | 
| Chris@0 | 276     case PropertyContainer::ToggleProperty: | 
| Chris@0 | 277     { | 
| Chris@335 | 278         QAbstractButton *button = 0; | 
| Chris@0 | 279 | 
| Chris@0 | 280 	if (have) { | 
| Chris@335 | 281             button = dynamic_cast<QAbstractButton *>(m_propertyControllers[name]); | 
| Chris@335 | 282             assert(button); | 
| Chris@0 | 283 	} else { | 
| Chris@0 | 284 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@682 | 285 	    cerr << "PropertyBox: creating new checkbox" << endl; | 
| Chris@0 | 286 #endif | 
| Chris@335 | 287             if (iconName != "") { | 
| Chris@335 | 288                 button = new NotifyingPushButton(); | 
| Chris@335 | 289                 button->setCheckable(true); | 
| Chris@335 | 290                 QIcon icon(IconLoader().load(iconName)); | 
| Chris@335 | 291                 button->setIcon(icon); | 
| Chris@335 | 292                 button->setObjectName(name); | 
| Chris@1174 | 293                 button->setFixedSize(WidgetScale::scaleQSize(QSize(18, 18))); | 
| Chris@335 | 294             } else { | 
| Chris@335 | 295                 button = new NotifyingCheckBox(); | 
| Chris@335 | 296                 button->setObjectName(name); | 
| Chris@335 | 297             } | 
| Chris@335 | 298 	    connect(button, SIGNAL(toggled(bool)), | 
| Chris@335 | 299 		    this, SLOT(propertyControllerChanged(bool))); | 
| Chris@335 | 300             connect(button, SIGNAL(mouseEntered()), | 
| Chris@189 | 301                     this, SLOT(mouseEnteredWidget())); | 
| Chris@335 | 302             connect(button, SIGNAL(mouseLeft()), | 
| Chris@189 | 303                     this, SLOT(mouseLeftWidget())); | 
| Chris@0 | 304 	    if (inGroup) { | 
| Chris@335 | 305 		button->setToolTip(propertyLabel); | 
| Chris@493 | 306 		m_groupLayouts[groupName]->addWidget | 
| Chris@493 | 307                     (button, 0, m_groupLayouts[groupName]->columnCount()); | 
| Chris@0 | 308 	    } else { | 
| Chris@335 | 309 		m_layout->addWidget(button, row, 1, 1, 2); | 
| Chris@0 | 310 	    } | 
| Chris@335 | 311 	    m_propertyControllers[name] = button; | 
| Chris@0 | 312 	} | 
| Chris@0 | 313 | 
| Chris@335 | 314         if (button->isChecked() != (value > 0)) { | 
| Chris@335 | 315 	    button->blockSignals(true); | 
| Chris@335 | 316 	    button->setChecked(value > 0); | 
| Chris@335 | 317 	    button->blockSignals(false); | 
| Chris@55 | 318 	} | 
| Chris@0 | 319 	break; | 
| Chris@0 | 320     } | 
| Chris@0 | 321 | 
| Chris@0 | 322     case PropertyContainer::RangeProperty: | 
| Chris@0 | 323     { | 
| Chris@0 | 324 	AudioDial *dial; | 
| Chris@0 | 325 | 
| Chris@0 | 326 	if (have) { | 
| Chris@0 | 327 	    dial = dynamic_cast<AudioDial *>(m_propertyControllers[name]); | 
| Chris@0 | 328 	    assert(dial); | 
| Chris@197 | 329             if (rangeChanged) { | 
| Chris@197 | 330                 dial->blockSignals(true); | 
| Chris@197 | 331                 dial->setMinimum(min); | 
| Chris@197 | 332                 dial->setMaximum(max); | 
| Chris@197 | 333                 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name)); | 
| Chris@197 | 334                 dial->blockSignals(false); | 
| Chris@197 | 335             } | 
| Chris@197 | 336 | 
| Chris@0 | 337 	} else { | 
| Chris@0 | 338 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@682 | 339 	    cerr << "PropertyBox: creating new dial" << endl; | 
| Chris@0 | 340 #endif | 
| Chris@0 | 341 	    dial = new AudioDial(); | 
| Chris@0 | 342 	    dial->setObjectName(name); | 
| Chris@0 | 343 	    dial->setMinimum(min); | 
| Chris@0 | 344 	    dial->setMaximum(max); | 
| Chris@0 | 345 	    dial->setPageStep(1); | 
| Chris@34 | 346 	    dial->setNotchesVisible((max - min) <= 12); | 
| Chris@1126 | 347             // important to set the range mapper before the default, | 
| Chris@1126 | 348             // because the range mapper is used to map the default | 
| Chris@1126 | 349             dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name)); | 
| Chris@216 | 350 	    dial->setDefaultValue(deflt); | 
| Chris@168 | 351             dial->setShowToolTip(true); | 
| Chris@0 | 352 	    connect(dial, SIGNAL(valueChanged(int)), | 
| Chris@0 | 353 		    this, SLOT(propertyControllerChanged(int))); | 
| Chris@189 | 354             connect(dial, SIGNAL(mouseEntered()), | 
| Chris@189 | 355                     this, SLOT(mouseEnteredWidget())); | 
| Chris@189 | 356             connect(dial, SIGNAL(mouseLeft()), | 
| Chris@189 | 357                     this, SLOT(mouseLeftWidget())); | 
| Chris@0 | 358 | 
| Chris@0 | 359 	    if (inGroup) { | 
| Chris@1174 | 360 		dial->setFixedWidth(WidgetScale::scalePixelSize(24)); | 
| Chris@1174 | 361 		dial->setFixedHeight(WidgetScale::scalePixelSize(24)); | 
| Chris@493 | 362 		m_groupLayouts[groupName]->addWidget | 
| Chris@493 | 363                     (dial, 0, m_groupLayouts[groupName]->columnCount()); | 
| Chris@0 | 364 	    } else { | 
| Chris@1174 | 365 		dial->setFixedWidth(WidgetScale::scalePixelSize(32)); | 
| Chris@1174 | 366 		dial->setFixedHeight(WidgetScale::scalePixelSize(32)); | 
| Chris@0 | 367 		m_layout->addWidget(dial, row, 1); | 
| Chris@33 | 368 		QLabel *label = new QLabel(m_mainWidget); | 
| Chris@0 | 369 		connect(dial, SIGNAL(valueChanged(int)), | 
| Chris@0 | 370 			label, SLOT(setNum(int))); | 
| Chris@0 | 371 		label->setNum(value); | 
| Chris@0 | 372 		m_layout->addWidget(label, row, 2); | 
| Chris@0 | 373 	    } | 
| Chris@0 | 374 | 
| Chris@0 | 375 	    m_propertyControllers[name] = dial; | 
| Chris@0 | 376 	} | 
| Chris@0 | 377 | 
| Chris@55 | 378 	if (dial->value() != value) { | 
| Chris@55 | 379 	    dial->blockSignals(true); | 
| Chris@55 | 380 	    dial->setValue(value); | 
| Chris@55 | 381 	    dial->blockSignals(false); | 
| Chris@55 | 382 	} | 
| Chris@0 | 383 	break; | 
| Chris@0 | 384     } | 
| Chris@0 | 385 | 
| Chris@0 | 386     case PropertyContainer::ValueProperty: | 
| Chris@100 | 387     case PropertyContainer::UnitsProperty: | 
| Chris@285 | 388     case PropertyContainer::ColourProperty: | 
| Chris@0 | 389     { | 
| Chris@189 | 390 	NotifyingComboBox *cb; | 
| Chris@0 | 391 | 
| Chris@0 | 392 	if (have) { | 
| Chris@189 | 393 	    cb = dynamic_cast<NotifyingComboBox *>(m_propertyControllers[name]); | 
| Chris@0 | 394 	    assert(cb); | 
| Chris@0 | 395 	} else { | 
| Chris@0 | 396 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@682 | 397 	    cerr << "PropertyBox: creating new combobox" << endl; | 
| Chris@0 | 398 #endif | 
| Chris@0 | 399 | 
| Chris@189 | 400 	    cb = new NotifyingComboBox(); | 
| Chris@0 | 401 	    cb->setObjectName(name); | 
| Chris@100 | 402             cb->setDuplicatesEnabled(false); | 
| Chris@197 | 403         } | 
| Chris@100 | 404 | 
| Chris@197 | 405         if (!have || rangeChanged) { | 
| Chris@285 | 406 | 
| Chris@197 | 407             cb->blockSignals(true); | 
| Chris@197 | 408             cb->clear(); | 
| Chris@285 | 409             cb->setEditable(false); | 
| Chris@285 | 410 | 
| Chris@100 | 411             if (type == PropertyContainer::ValueProperty) { | 
| Chris@285 | 412 | 
| Chris@100 | 413                 for (int i = min; i <= max; ++i) { | 
| Chris@862 | 414 | 
| Chris@862 | 415                     QString label = m_container->getPropertyValueLabel(name, i); | 
| Chris@862 | 416                     QString iname = m_container->getPropertyValueIconName(name, i); | 
| Chris@862 | 417 | 
| Chris@862 | 418                     if (iname != "") { | 
| Chris@862 | 419                         QIcon icon(IconLoader().load(iname)); | 
| Chris@862 | 420                         cb->addItem(icon, label); | 
| Chris@862 | 421                     } else { | 
| Chris@862 | 422                         cb->addItem(label); | 
| Chris@862 | 423                     } | 
| Chris@100 | 424                 } | 
| Chris@285 | 425 | 
| Chris@285 | 426             } else if (type == PropertyContainer::UnitsProperty) { | 
| Chris@285 | 427 | 
| Chris@100 | 428                 QStringList units = UnitDatabase::getInstance()->getKnownUnits(); | 
| Chris@100 | 429                 for (int i = 0; i < units.size(); ++i) { | 
| Chris@100 | 430                     cb->addItem(units[i]); | 
| Chris@100 | 431                 } | 
| Chris@285 | 432 | 
| Chris@100 | 433                 cb->setEditable(true); | 
| Chris@285 | 434 | 
| Chris@285 | 435             } else { // ColourProperty | 
| Chris@290 | 436 | 
| Chris@290 | 437                 //!!! should be a proper colour combobox class that | 
| Chris@290 | 438                 // manages its own Add New Colour entry... | 
| Chris@1173 | 439 | 
| Chris@1173 | 440                 int size = (QFontMetrics(QFont()).height() * 2) / 3; | 
| Chris@1173 | 441                 if (size < 12) size = 12; | 
| Chris@285 | 442 | 
| Chris@285 | 443                 ColourDatabase *db = ColourDatabase::getInstance(); | 
| Chris@769 | 444                 for (int i = 0; i < db->getColourCount(); ++i) { | 
| Chris@285 | 445                     QString name = db->getColourName(i); | 
| Chris@1173 | 446                     cb->addItem(db->getExamplePixmap(i, QSize(size, size)), name); | 
| Chris@285 | 447                 } | 
| Chris@285 | 448                 cb->addItem(tr("Add New Colour...")); | 
| Chris@285 | 449             } | 
| Chris@285 | 450 | 
| Chris@197 | 451             cb->blockSignals(false); | 
| Chris@280 | 452             if (cb->count() < 20 && cb->count() > cb->maxVisibleItems()) { | 
| Chris@280 | 453                 cb->setMaxVisibleItems(cb->count()); | 
| Chris@280 | 454             } | 
| Chris@197 | 455         } | 
| Chris@100 | 456 | 
| Chris@197 | 457         if (!have) { | 
| Chris@0 | 458 	    connect(cb, SIGNAL(activated(int)), | 
| Chris@0 | 459 		    this, SLOT(propertyControllerChanged(int))); | 
| Chris@189 | 460             connect(cb, SIGNAL(mouseEntered()), | 
| Chris@189 | 461                     this, SLOT(mouseEnteredWidget())); | 
| Chris@189 | 462             connect(cb, SIGNAL(mouseLeft()), | 
| Chris@189 | 463                     this, SLOT(mouseLeftWidget())); | 
| Chris@100 | 464 | 
| Chris@0 | 465 	    if (inGroup) { | 
| Chris@108 | 466 		cb->setToolTip(propertyLabel); | 
| Chris@493 | 467 		m_groupLayouts[groupName]->addWidget | 
| Chris@493 | 468                     (cb, 0, m_groupLayouts[groupName]->columnCount()); | 
| Chris@0 | 469 	    } else { | 
| Chris@0 | 470 		m_layout->addWidget(cb, row, 1, 1, 2); | 
| Chris@0 | 471 	    } | 
| Chris@0 | 472 	    m_propertyControllers[name] = cb; | 
| Chris@0 | 473 	} | 
| Chris@0 | 474 | 
| Chris@100 | 475         cb->blockSignals(true); | 
| Chris@285 | 476         if (type == PropertyContainer::ValueProperty || | 
| Chris@285 | 477             type == PropertyContainer::ColourProperty) { | 
| Chris@100 | 478             if (cb->currentIndex() != value) { | 
| Chris@100 | 479                 cb->setCurrentIndex(value); | 
| Chris@100 | 480             } | 
| Chris@100 | 481         } else { | 
| Chris@100 | 482             QString unit = UnitDatabase::getInstance()->getUnitById(value); | 
| Chris@100 | 483             if (cb->currentText() != unit) { | 
| Chris@100 | 484                 for (int i = 0; i < cb->count(); ++i) { | 
| Chris@100 | 485                     if (cb->itemText(i) == unit) { | 
| Chris@100 | 486                         cb->setCurrentIndex(i); | 
| Chris@100 | 487                         break; | 
| Chris@100 | 488                     } | 
| Chris@100 | 489                 } | 
| Chris@100 | 490             } | 
| Chris@100 | 491         } | 
| Chris@100 | 492         cb->blockSignals(false); | 
| Chris@0 | 493 | 
| Chris@681 | 494 #ifdef Q_OS_MAC | 
| Chris@982 | 495 	// Crashes on startup without this, for some reason; also | 
| Chris@982 | 496 	// prevents combo boxes from getting weirdly squished | 
| Chris@982 | 497 	// vertically | 
| Chris@982 | 498 	cb->setMinimumSize(QSize(10, cb->font().pixelSize() * 2)); | 
| Chris@0 | 499 #endif | 
| Chris@0 | 500 | 
| Chris@0 | 501 	break; | 
| Chris@0 | 502     } | 
| Chris@0 | 503 | 
| Chris@807 | 504     case PropertyContainer::InvalidProperty: | 
| Chris@0 | 505     default: | 
| Chris@0 | 506 	break; | 
| Chris@0 | 507     } | 
| Chris@0 | 508 } | 
| Chris@0 | 509 | 
| Chris@0 | 510 void | 
| Chris@0 | 511 PropertyBox::propertyContainerPropertyChanged(PropertyContainer *pc) | 
| Chris@0 | 512 { | 
| Chris@0 | 513     if (pc != m_container) return; | 
| Chris@0 | 514 | 
| Chris@55 | 515 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@587 | 516     SVDEBUG << "PropertyBox::propertyContainerPropertyChanged" << endl; | 
| Chris@55 | 517 #endif | 
| Chris@55 | 518 | 
| Chris@0 | 519     PropertyContainer::PropertyList properties = m_container->getProperties(); | 
| Chris@0 | 520     size_t i; | 
| Chris@0 | 521 | 
| Chris@0 | 522     blockSignals(true); | 
| Chris@0 | 523 | 
| Chris@0 | 524     for (i = 0; i < properties.size(); ++i) { | 
| Chris@0 | 525 	updatePropertyEditor(properties[i]); | 
| Chris@0 | 526     } | 
| Chris@0 | 527 | 
| Chris@0 | 528     blockSignals(false); | 
| Chris@0 | 529 } | 
| Chris@0 | 530 | 
| Chris@0 | 531 void | 
| Chris@249 | 532 PropertyBox::propertyContainerPropertyRangeChanged(PropertyContainer *) | 
| Chris@197 | 533 { | 
| Chris@197 | 534     blockSignals(true); | 
| Chris@197 | 535 | 
| Chris@197 | 536     PropertyContainer::PropertyList properties = m_container->getProperties(); | 
| Chris@197 | 537     for (size_t i = 0; i < properties.size(); ++i) { | 
| Chris@197 | 538 	updatePropertyEditor(properties[i], true); | 
| Chris@197 | 539     } | 
| Chris@197 | 540 | 
| Chris@197 | 541     blockSignals(false); | 
| Chris@197 | 542 } | 
| Chris@197 | 543 | 
| Chris@197 | 544 void | 
| Chris@100 | 545 PropertyBox::unitDatabaseChanged() | 
| Chris@100 | 546 { | 
| Chris@729 | 547 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@682 | 548     cerr << "PropertyBox[" << this << "]: unitDatabaseChanged" << endl; | 
| Chris@729 | 549 #endif | 
| Chris@100 | 550     blockSignals(true); | 
| Chris@100 | 551 | 
| Chris@682 | 552 //    cerr << "my container is " << m_container << endl; | 
| Chris@682 | 553 //    cerr << "my container's name is... " << endl; | 
| Chris@682 | 554 //    cerr << m_container->objectName() << endl; | 
| Chris@456 | 555 | 
| Chris@100 | 556     PropertyContainer::PropertyList properties = m_container->getProperties(); | 
| Chris@100 | 557     for (size_t i = 0; i < properties.size(); ++i) { | 
| Chris@285 | 558         if (m_container->getPropertyType(properties[i]) == | 
| Chris@285 | 559             PropertyContainer::UnitsProperty) { | 
| Chris@285 | 560             updatePropertyEditor(properties[i]); | 
| Chris@285 | 561         } | 
| Chris@285 | 562     } | 
| Chris@285 | 563 | 
| Chris@285 | 564     blockSignals(false); | 
| Chris@285 | 565 } | 
| Chris@285 | 566 | 
| Chris@285 | 567 void | 
| Chris@285 | 568 PropertyBox::colourDatabaseChanged() | 
| Chris@285 | 569 { | 
| Chris@285 | 570     blockSignals(true); | 
| Chris@285 | 571 | 
| Chris@285 | 572     PropertyContainer::PropertyList properties = m_container->getProperties(); | 
| Chris@285 | 573     for (size_t i = 0; i < properties.size(); ++i) { | 
| Chris@285 | 574         if (m_container->getPropertyType(properties[i]) == | 
| Chris@285 | 575             PropertyContainer::ColourProperty) { | 
| Chris@285 | 576             updatePropertyEditor(properties[i], true); | 
| Chris@285 | 577         } | 
| Chris@100 | 578     } | 
| Chris@100 | 579 | 
| Chris@100 | 580     blockSignals(false); | 
| Chris@100 | 581 } | 
| Chris@100 | 582 | 
| Chris@100 | 583 void | 
| Chris@335 | 584 PropertyBox::propertyControllerChanged(bool on) | 
| Chris@335 | 585 { | 
| Chris@335 | 586     propertyControllerChanged(on ? 1 : 0); | 
| Chris@335 | 587 } | 
| Chris@335 | 588 | 
| Chris@335 | 589 void | 
| Chris@0 | 590 PropertyBox::propertyControllerChanged(int value) | 
| Chris@0 | 591 { | 
| Chris@0 | 592     QObject *obj = sender(); | 
| Chris@0 | 593     QString name = obj->objectName(); | 
| Chris@0 | 594 | 
| Chris@34 | 595 #ifdef DEBUG_PROPERTY_BOX | 
| Chris@587 | 596     SVDEBUG << "PropertyBox::propertyControllerChanged(" << name	      << ", " << value << ")" << endl; | 
| Chris@34 | 597 #endif | 
| Chris@0 | 598 | 
| Chris@0 | 599     PropertyContainer::PropertyType type = m_container->getPropertyType(name); | 
| Chris@100 | 600 | 
| Chris@376 | 601     Command *c = 0; | 
| Chris@376 | 602 | 
| Chris@100 | 603     if (type == PropertyContainer::UnitsProperty) { | 
| Chris@285 | 604 | 
| Chris@189 | 605         NotifyingComboBox *cb = dynamic_cast<NotifyingComboBox *>(obj); | 
| Chris@100 | 606         if (cb) { | 
| Chris@100 | 607             QString unit = cb->currentText(); | 
| Chris@376 | 608             c = m_container->getSetPropertyCommand | 
| Chris@100 | 609                 (name, UnitDatabase::getInstance()->getUnitId(unit)); | 
| Chris@100 | 610         } | 
| Chris@285 | 611 | 
| Chris@285 | 612     } else if (type == PropertyContainer::ColourProperty) { | 
| Chris@285 | 613 | 
| Chris@285 | 614         if (value == int(ColourDatabase::getInstance()->getColourCount())) { | 
| Chris@285 | 615             addNewColour(); | 
| Chris@285 | 616             if (value == int(ColourDatabase::getInstance()->getColourCount())) { | 
| Chris@285 | 617                 propertyContainerPropertyChanged(m_container); | 
| Chris@285 | 618                 return; | 
| Chris@285 | 619             } | 
| Chris@285 | 620         } | 
| Chris@376 | 621         c = m_container->getSetPropertyCommand(name, value); | 
| Chris@285 | 622 | 
| Chris@100 | 623     } else if (type != PropertyContainer::InvalidProperty) { | 
| Chris@285 | 624 | 
| Chris@376 | 625 	c = m_container->getSetPropertyCommand(name, value); | 
| Chris@0 | 626     } | 
| Chris@376 | 627 | 
| Chris@376 | 628     if (c) CommandHistory::getInstance()->addCommand(c, true, true); | 
| Chris@218 | 629 | 
| Chris@218 | 630     updateContextHelp(obj); | 
| Chris@0 | 631 } | 
| Chris@285 | 632 | 
| Chris@285 | 633 void | 
| Chris@285 | 634 PropertyBox::addNewColour() | 
| Chris@285 | 635 { | 
| Chris@285 | 636     QColor newColour = QColorDialog::getColor(); | 
| Chris@285 | 637     if (!newColour.isValid()) return; | 
| Chris@285 | 638 | 
| Chris@285 | 639     ColourNameDialog dialog(tr("Name New Colour"), | 
| Chris@361 | 640                             tr("Enter a name for the new colour:"), | 
| Chris@361 | 641                             newColour, newColour.name(), this); | 
| Chris@285 | 642     dialog.showDarkBackgroundCheckbox(tr("Prefer black background for this colour")); | 
| Chris@285 | 643     if (dialog.exec() == QDialog::Accepted) { | 
| Chris@285 | 644         //!!! command | 
| Chris@285 | 645         ColourDatabase *db = ColourDatabase::getInstance(); | 
| Chris@285 | 646         int index = db->addColour(newColour, dialog.getColourName()); | 
| Chris@285 | 647         db->setUseDarkBackground(index, dialog.isDarkBackgroundChecked()); | 
| Chris@285 | 648     } | 
| Chris@285 | 649 } | 
| Chris@377 | 650 | 
| Chris@377 | 651 void | 
| Chris@377 | 652 PropertyBox::playAudibleChanged(bool audible) | 
| Chris@377 | 653 { | 
| Chris@377 | 654     m_playButton->setState(audible); | 
| Chris@377 | 655 } | 
| Chris@377 | 656 | 
| Chris@377 | 657 void | 
| Chris@377 | 658 PropertyBox::playAudibleButtonChanged(bool audible) | 
| Chris@377 | 659 { | 
| Chris@377 | 660     PlayParameters *params = m_container->getPlayParameters(); | 
| Chris@377 | 661     if (!params) return; | 
| Chris@377 | 662 | 
| Chris@377 | 663     if (params->isPlayAudible() != audible) { | 
| Chris@377 | 664         PlayParameterRepository::EditCommand *command = | 
| Chris@377 | 665             new PlayParameterRepository::EditCommand(params); | 
| Chris@377 | 666         command->setPlayAudible(audible); | 
| Chris@377 | 667         CommandHistory::getInstance()->addCommand(command, true, true); | 
| Chris@377 | 668     } | 
| Chris@377 | 669 } | 
| Chris@34 | 670 | 
| Chris@34 | 671 void | 
| Chris@1178 | 672 PropertyBox::playGainControlChanged(float gain) | 
| Chris@34 | 673 { | 
| Chris@218 | 674     QObject *obj = sender(); | 
| 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->getPlayGain() != gain) { | 
| Chris@377 | 680         PlayParameterRepository::EditCommand *command = | 
| Chris@377 | 681             new PlayParameterRepository::EditCommand(params); | 
| Chris@377 | 682         command->setPlayGain(gain); | 
| Chris@377 | 683         CommandHistory::getInstance()->addCommand(command, true, true); | 
| Chris@377 | 684     } | 
| Chris@377 | 685 | 
| Chris@218 | 686     updateContextHelp(obj); | 
| Chris@34 | 687 } | 
| Chris@34 | 688 | 
| Chris@34 | 689 void | 
| Chris@1178 | 690 PropertyBox::playPanControlChanged(float pan) | 
| Chris@34 | 691 { | 
| Chris@218 | 692     QObject *obj = sender(); | 
| Chris@377 | 693 | 
| Chris@377 | 694     PlayParameters *params = m_container->getPlayParameters(); | 
| Chris@377 | 695     if (!params) return; | 
| Chris@377 | 696 | 
| Chris@377 | 697     if (params->getPlayPan() != pan) { | 
| Chris@377 | 698         PlayParameterRepository::EditCommand *command = | 
| Chris@377 | 699             new PlayParameterRepository::EditCommand(params); | 
| Chris@377 | 700         command->setPlayPan(pan); | 
| Chris@377 | 701         CommandHistory::getInstance()->addCommand(command, true, true); | 
| Chris@377 | 702     } | 
| Chris@377 | 703 | 
| Chris@218 | 704     updateContextHelp(obj); | 
| Chris@34 | 705 } | 
| Chris@769 | 706 | 
| Chris@63 | 707 void | 
| Chris@769 | 708 PropertyBox::editPlayParameters() | 
| Chris@63 | 709 { | 
| Chris@63 | 710     PlayParameters *params = m_container->getPlayParameters(); | 
| Chris@63 | 711     if (!params) return; | 
| Chris@63 | 712 | 
| Chris@769 | 713     QString clip = params->getPlayClipId(); | 
| Chris@377 | 714 | 
| Chris@377 | 715     PlayParameterRepository::EditCommand *command = | 
| Chris@377 | 716         new PlayParameterRepository::EditCommand(params); | 
| Chris@63 | 717 | 
| Chris@769 | 718     QInputDialog *dialog = new QInputDialog(this); | 
| Chris@63 | 719 | 
| Chris@769 | 720     QDir dir(":/samples"); | 
| Chris@769 | 721     QStringList clipFiles = dir.entryList(QStringList() << "*.wav", QDir::Files); | 
| Chris@63 | 722 | 
| Chris@769 | 723     QStringList clips; | 
| Chris@769 | 724     foreach (QString str, clipFiles) { | 
| Chris@769 | 725         clips.push_back(str.replace(".wav", "")); | 
| Chris@769 | 726     } | 
| Chris@769 | 727     dialog->setComboBoxItems(clips); | 
| Chris@63 | 728 | 
| Chris@769 | 729     dialog->setLabelText(tr("Set playback clip:")); | 
| Chris@769 | 730 | 
| Chris@769 | 731     QComboBox *cb = dialog->findChild<QComboBox *>(); | 
| Chris@779 | 732     if (cb) { | 
| Chris@779 | 733         for (int i = 0; i < cb->count(); ++i) { | 
| Chris@779 | 734             if (cb->itemText(i) == clip) { | 
| Chris@779 | 735                 cb->setCurrentIndex(i); | 
| Chris@779 | 736             } | 
| Chris@779 | 737         } | 
| Chris@779 | 738     } | 
| Chris@769 | 739 | 
| Chris@769 | 740     connect(dialog, SIGNAL(textValueChanged(QString)), | 
| Chris@769 | 741             this, SLOT(playClipChanged(QString))); | 
| Chris@64 | 742 | 
| Chris@63 | 743     if (dialog->exec() == QDialog::Accepted) { | 
| Chris@769 | 744         QString newClip = dialog->textValue(); | 
| Chris@769 | 745         command->setPlayClipId(newClip); | 
| Chris@377 | 746         CommandHistory::getInstance()->addCommand(command, true); | 
| Chris@64 | 747     } else { | 
| Chris@377 | 748         delete command; | 
| Chris@64 | 749         // restore in case we mucked about with the configuration | 
| Chris@64 | 750         // as a consequence of signals from the dialog | 
| Chris@769 | 751         params->setPlayClipId(clip); | 
| Chris@63 | 752     } | 
| Chris@63 | 753 | 
| Chris@63 | 754     delete dialog; | 
| Chris@63 | 755 } | 
| Chris@63 | 756 | 
| Chris@64 | 757 void | 
| Chris@769 | 758 PropertyBox::playClipChanged(QString id) | 
| Chris@64 | 759 { | 
| Chris@64 | 760     PlayParameters *params = m_container->getPlayParameters(); | 
| Chris@64 | 761     if (!params) return; | 
| Chris@64 | 762 | 
| Chris@769 | 763     params->setPlayClipId(id); | 
| Chris@64 | 764 } | 
| Chris@769 | 765 | 
| Chris@185 | 766 void | 
| Chris@185 | 767 PropertyBox::layerVisibilityChanged(bool visible) | 
| Chris@185 | 768 { | 
| Chris@185 | 769     if (m_showButton) m_showButton->setState(visible); | 
| Chris@185 | 770 } | 
| Chris@189 | 771 | 
| Chris@189 | 772 void | 
| Chris@189 | 773 PropertyBox::mouseEnteredWidget() | 
| Chris@189 | 774 { | 
| Chris@218 | 775     updateContextHelp(sender()); | 
| Chris@218 | 776 } | 
| Chris@218 | 777 | 
| Chris@218 | 778 void | 
| Chris@218 | 779 PropertyBox::updateContextHelp(QObject *o) | 
| Chris@218 | 780 { | 
| Chris@218 | 781     QWidget *w = dynamic_cast<QWidget *>(o); | 
| Chris@189 | 782     if (!w) return; | 
| Chris@218 | 783 | 
| Chris@189 | 784     if (!m_container) return; | 
| Chris@190 | 785     QString cname = m_container->getPropertyContainerName(); | 
| Chris@189 | 786     if (cname == "") return; | 
| Chris@189 | 787 | 
| Chris@189 | 788     QString wname = w->objectName(); | 
| Chris@189 | 789 | 
| Chris@218 | 790     QString extraText; | 
| Chris@218 | 791     AudioDial *dial = dynamic_cast<AudioDial *>(w); | 
| Chris@218 | 792     if (dial) { | 
| Chris@908 | 793         double mv = dial->mappedValue(); | 
| Chris@218 | 794         QString unit = ""; | 
| Chris@218 | 795         if (dial->rangeMapper()) unit = dial->rangeMapper()->getUnit(); | 
| Chris@218 | 796         if (unit != "") { | 
| Chris@218 | 797             extraText = tr(" (current value: %1%2)").arg(mv).arg(unit); | 
| Chris@218 | 798         } else { | 
| Chris@218 | 799             extraText = tr(" (current value: %1)").arg(mv); | 
| Chris@218 | 800         } | 
| Chris@218 | 801     } | 
| Chris@218 | 802 | 
| Chris@189 | 803     if (w == m_showButton) { | 
| Chris@190 | 804         emit contextHelpChanged(tr("Toggle Visibility of %1").arg(cname)); | 
| Chris@189 | 805     } else if (w == m_playButton) { | 
| Chris@190 | 806         emit contextHelpChanged(tr("Toggle Playback of %1").arg(cname)); | 
| Chris@189 | 807     } else if (wname == "") { | 
| Chris@189 | 808         return; | 
| Chris@335 | 809     } else if (dynamic_cast<QAbstractButton *>(w)) { | 
| Chris@190 | 810         emit contextHelpChanged(tr("Toggle %1 property of %2") | 
| Chris@189 | 811                                 .arg(wname).arg(cname)); | 
| Chris@189 | 812     } else { | 
| Chris@218 | 813         emit contextHelpChanged(tr("Adjust %1 property of %2%3") | 
| Chris@218 | 814                                 .arg(wname).arg(cname).arg(extraText)); | 
| Chris@189 | 815     } | 
| Chris@189 | 816 } | 
| Chris@189 | 817 | 
| Chris@189 | 818 void | 
| Chris@189 | 819 PropertyBox::mouseLeftWidget() | 
| Chris@189 | 820 { | 
| Chris@218 | 821     if (!(QApplication::mouseButtons() & Qt::LeftButton)) { | 
| Chris@218 | 822         emit contextHelpChanged(""); | 
| Chris@218 | 823     } | 
| Chris@189 | 824 } | 
| Chris@189 | 825 | 
| Chris@64 | 826 |