File indexing completed on 2024-12-22 04:18:19
0001 /*************************************************************************** 0002 * * 0003 * copyright : (C) 2007 The University of Toronto * 0004 * netterfield@astro.utoronto.ca * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify * 0007 * it under the terms of the GNU General Public License as published by * 0008 * the Free Software Foundation; either version 2 of the License, or * 0009 * (at your option) any later version. * 0010 * * 0011 ***************************************************************************/ 0012 0013 #include "scalarselector.h" 0014 0015 #include "dialoglauncher.h" 0016 #include "datacollection.h" 0017 #include "objectstore.h" 0018 #include "updateserver.h" 0019 0020 #include "enodes.h" 0021 #include "geticon.h" 0022 0023 namespace Kst { 0024 0025 ScalarSelector::ScalarSelector(QWidget *parent, ObjectStore *store) 0026 : QWidget(parent), _store(store) { 0027 0028 _defaultsSet = false; 0029 setupUi(this); 0030 if (property("isFOverSR").toBool()) { 0031 _cutoffLabel->show(); 0032 _cutoff->show(); 0033 _SRLabel->show(); 0034 _SR->show(); 0035 0036 } else { 0037 _cutoffLabel->hide(); 0038 _cutoff->hide(); 0039 _SRLabel->hide(); 0040 _SR->hide(); 0041 } 0042 0043 _newScalar->setIcon(KstGetIcon("kst_scalarnew")); 0044 _editScalar->setIcon(KstGetIcon("kst_scalaredit")); 0045 0046 _newScalar->setFixedSize(iconWidth(), iconWidth()); 0047 _editScalar->setFixedSize(iconWidth(), iconWidth()); 0048 _selectScalar->setFixedSize(iconWidth(), iconWidth()); 0049 0050 _scalarListSelector = new ScalarListSelector(this); 0051 0052 0053 //_scalar->resize(10,5); 0054 connect(_newScalar, SIGNAL(pressed()), this, SLOT(newScalar())); 0055 connect(_editScalar, SIGNAL(pressed()), this, SLOT(editScalar())); 0056 connect(_selectScalar, SIGNAL(pressed()), this, SLOT(selectScalar())); 0057 connect(_scalar, SIGNAL(editTextChanged(QString)), this, SLOT(emitSelectionChanged())); 0058 connect(_scalar, SIGNAL(editTextChanged(QString)), this, SLOT(updateDescriptionTip())); 0059 connect(_scalar, SIGNAL(editTextChanged(QString)), this, SLOT(ratioChanged())); 0060 connect(_cutoff, SIGNAL(textEdited(QString)), this, SLOT(cutoffChanged())); 0061 connect(_SR, SIGNAL(textChanged(QString)), this, SLOT(srChanged())); 0062 connect(_SR, SIGNAL(textChanged(QString)), this, SIGNAL(SRChanged(QString))); 0063 0064 connect(UpdateServer::self(), SIGNAL(objectListsChanged()), this, SLOT(updateScalarList())); 0065 0066 } 0067 0068 0069 ScalarSelector::~ScalarSelector() { 0070 } 0071 0072 int ScalarSelector::iconWidth() const { 0073 return fontMetrics().lineSpacing()*4/3; 0074 } 0075 0076 void ScalarSelector::setIsFOverSR(bool is_f_over_sr) 0077 { 0078 setProperty("isFOVerSR", is_f_over_sr); 0079 0080 if (is_f_over_sr) { 0081 _cutoffLabel->show(); 0082 _cutoff->show(); 0083 _SRLabel->show(); 0084 _SR->show(); 0085 0086 QSize size = _scalar->size(); 0087 size.setWidth(fontMetrics().width("000000000")); 0088 _SR->setMinimumSize(size); 0089 _cutoff->setMinimumSize(size); 0090 0091 size.setWidth(fontMetrics().width("0000000000000")); 0092 _scalar->setMinimumSize(size); 0093 0094 //setMinimumWidth(3*min_width + _cutoffLabel->width() + _SRLabel->width()+3*_newScalar->width()); 0095 0096 } else { 0097 _cutoffLabel->hide(); 0098 _cutoff->hide(); 0099 _SRLabel->hide(); 0100 _SR->hide(); 0101 } 0102 0103 } 0104 0105 QSize ScalarSelector::minimumSizeHint() const { 0106 return QSize(15*fontMetrics().width("m")+ 3 * iconWidth(), iconWidth()); 0107 } 0108 0109 0110 void ScalarSelector::setObjectStore(ObjectStore *store) { 0111 _store = store; 0112 fillScalars(); 0113 } 0114 0115 0116 void ScalarSelector::updateDescriptionTip() { 0117 bool editable; 0118 setToolTip(selectedScalarString(&editable)); 0119 _editScalar->setEnabled(editable); 0120 } 0121 0122 0123 void ScalarSelector::emitSelectionChanged() { 0124 emit selectionChanged(_scalar->currentText()); 0125 } 0126 0127 0128 void ScalarSelector::setDefaultValue(double value) { 0129 QString string = QString::number(value); 0130 int index = _scalar->findText(string); 0131 if (index<0) { 0132 _scalar->addItem(string, qVariantFromValue(0)); 0133 _scalar->setCurrentIndex(_scalar->findText(string)); 0134 } else { 0135 _scalar->setCurrentIndex(index); 0136 } 0137 _defaultsSet = true; 0138 } 0139 0140 0141 ScalarPtr ScalarSelector::selectedScalar() { 0142 bool existingScalar; 0143 if (_scalar->findText(_scalar->currentText(), Qt::MatchExactly) == -1) { 0144 // Value typed in. 0145 existingScalar = false; 0146 } else { 0147 if (_scalar->itemData(_scalar->findText(_scalar->currentText())).value<Scalar*>()) { 0148 existingScalar = true; 0149 } else { 0150 // Default Value. Doesn't exist as scalar yet. 0151 existingScalar = false; 0152 } 0153 } 0154 0155 if (!existingScalar) { 0156 // Create the Scalar. 0157 bool ok = false; 0158 double value = _scalar->currentText().toDouble(&ok); 0159 if (!ok) { 0160 value = Equations::interpret(_store, _scalar->currentText().toLatin1(), &ok); 0161 } 0162 0163 if (!ok) { 0164 return 0; 0165 } 0166 0167 // Check if a scalar with this value exist & is hidden. 0168 foreach(Scalar* scalar, _store->getObjects<Scalar>()) { 0169 if (scalar->hidden()) { 0170 if (scalar->value() == value) { 0171 return scalar; 0172 } 0173 } 0174 } 0175 0176 ScalarPtr scalar = _store->createObject<Scalar>(); 0177 scalar->setValue(value); 0178 scalar->setEditable(false); 0179 scalar->setDescriptiveName(QString()); 0180 scalar->setOrphan(true); 0181 scalar->setHidden(true); 0182 0183 _scalar->clearEditText(); 0184 fillScalars(); 0185 0186 scalar->writeLock(); 0187 scalar->registerChange(); 0188 scalar->unlock(); 0189 0190 setSelectedScalar(scalar); 0191 0192 return scalar; 0193 } 0194 return _scalar->itemData(_scalar->currentIndex()).value<Scalar*>();; 0195 } 0196 0197 0198 QString ScalarSelector::selectedScalarString(bool *editable) { 0199 if (_scalar->findText(_scalar->currentText(),Qt::MatchExactly) == -1) { 0200 if (editable) { 0201 *editable = false; 0202 } 0203 return _scalar->currentText(); 0204 } 0205 0206 Scalar* scalar = _scalar->itemData(_scalar->currentIndex()).value<Scalar*>();; 0207 if (scalar) { 0208 if (editable) { 0209 *editable = scalar->editable(); 0210 } 0211 return scalar->descriptionTip(); 0212 } else { 0213 if (editable) { 0214 *editable = false; 0215 } 0216 return QString(); 0217 } 0218 } 0219 0220 0221 void ScalarSelector::setSelectedScalar(QString Name) { 0222 bool ok; 0223 QString trimmed_name = Name.split('(').at(0).trimmed(); 0224 double value = trimmed_name.toDouble(&ok); 0225 0226 if (ok) { 0227 setDefaultValue(value); 0228 } else { 0229 Kst::Object* object = _store->retrieveObject(trimmed_name); 0230 Kst::Scalar* scalar = static_cast<Kst::Scalar*>(object); 0231 if (scalar) { 0232 setSelectedScalar(scalar); 0233 } 0234 } 0235 } 0236 0237 void ScalarSelector::setSR(const QString &SR) { 0238 _SR->setText(SR); 0239 } 0240 0241 QString ScalarSelector::SR() { 0242 return _SR->text(); 0243 } 0244 0245 0246 void ScalarSelector::setSelectedScalar(ScalarPtr selectedScalar) { 0247 int i=-1; 0248 for (int j=0; j<_scalar->count() ; ++j) { 0249 if (selectedScalar.data() == _scalar->itemData(j).value<Scalar*>()) { 0250 i=j; 0251 break; 0252 } 0253 } 0254 0255 if (i==-1) { 0256 setDefaultValue(selectedScalar->value()); 0257 } else { 0258 _scalar->setCurrentIndex(i); 0259 _defaultsSet = false; 0260 } 0261 } 0262 0263 void ScalarSelector::newScalar() { 0264 QString scalarName; 0265 DialogLauncher::self()->showScalarDialog(scalarName, 0, true); 0266 fillScalars(); 0267 ScalarPtr scalar = kst_cast<Scalar>(_store->retrieveObject(scalarName)); 0268 0269 if (scalar) { 0270 setSelectedScalar(scalar); 0271 emitSelectionChanged(); 0272 } 0273 } 0274 0275 0276 void ScalarSelector::editScalar() { 0277 if (selectedScalar()->provider()) { 0278 DialogLauncher::self()->showObjectDialog(selectedScalar()->provider()); 0279 } else { 0280 QString scalarName; 0281 DialogLauncher::self()->showScalarDialog(scalarName, ObjectPtr(selectedScalar()), true); 0282 } 0283 fillScalars(); 0284 } 0285 0286 void ScalarSelector::selectScalar() { 0287 if (_scalarListSelector->exec() == QDialog::Accepted) { 0288 _scalar->setCurrentIndex(_scalar->findText(_scalarListSelector->selectedScalar())); 0289 } 0290 } 0291 0292 0293 void ScalarSelector::fillScalars() { 0294 if (!_store) { 0295 return; 0296 } 0297 0298 QHash<QString, ScalarPtr> scalars; 0299 0300 ScalarList scalarList = _store->getObjects<Scalar>(); 0301 0302 ScalarList::ConstIterator it = scalarList.constBegin(); 0303 for (; it != scalarList.constEnd(); ++it) { 0304 ScalarPtr scalar = (*it); 0305 0306 scalar->readLock(); 0307 if (!scalar->hidden()) { 0308 scalars.insert(scalar->CleanedName(), scalar); 0309 } 0310 scalar->unlock(); 0311 } 0312 0313 QStringList list = scalars.keys(); 0314 0315 qSort(list); 0316 0317 QString current_text = _scalar->currentText(); 0318 ScalarPtr current = _scalar->itemData(_scalar->currentIndex()).value<Scalar*>(); 0319 0320 _scalar->clear(); 0321 foreach (const QString &string, list) { 0322 ScalarPtr v = scalars.value(string); 0323 _scalar->addItem(string, qVariantFromValue(v.data())); 0324 } 0325 0326 _scalarListSelector->clear(); 0327 _scalarListSelector->fillScalars(list); 0328 0329 if (current) { 0330 setSelectedScalar(current); 0331 } else { 0332 _scalar->addItem(current_text, qVariantFromValue(0)); 0333 _scalar->setCurrentIndex(_scalar->findText(current_text)); 0334 _defaultsSet = true; 0335 } 0336 0337 _editScalar->setEnabled(_scalar->count() > 0); 0338 _selectScalar->setEnabled(_scalar->count() > 0); 0339 updateDescriptionTip(); 0340 } 0341 0342 void ScalarSelector::updateScalarList() { 0343 if (_defaultsSet) { 0344 QString defaultText = _scalar->currentText(); 0345 fillScalars(); 0346 setDefaultValue(defaultText.toDouble()); 0347 } else { 0348 fillScalars(); 0349 } 0350 } 0351 0352 void ScalarSelector::ratioChanged() { 0353 updateFields(Ratio); 0354 } 0355 0356 void ScalarSelector::cutoffChanged() { 0357 updateFields(Cutoff); 0358 } 0359 0360 void ScalarSelector::srChanged() { 0361 updateFields(SampleRate); 0362 } 0363 0364 void ScalarSelector::updateFields(ControlField control_field) { 0365 0366 0367 // Start Ratio 0368 // Last Cutoff 0369 // Range SR 0370 0371 double ratio; 0372 double cutoff; 0373 double frequency; 0374 bool ok = false; 0375 0376 // set ratio: the value of the selected scalar, or evaluate as equation, or convert to double. 0377 if (_scalar->itemData(_scalar->findText(_scalar->currentText())).value<Scalar*>()) { 0378 ratio = ScalarPtr(_scalar->itemData(_scalar->findText(_scalar->currentText())).value<Scalar*>())->value(); 0379 } else { 0380 ok = false; 0381 ratio = _scalar->currentText().toDouble(&ok); 0382 if (!ok) { 0383 ratio = Equations::interpret(_store, _scalar->currentText().toLatin1(), &ok); 0384 } 0385 0386 if (!ok) { 0387 ratio = 0; 0388 } 0389 } 0390 0391 // set cutoff: either evaluate as equation, or convert to double. 0392 ok = false; 0393 cutoff = _cutoff->text().toDouble(&ok); 0394 if (!ok) { 0395 cutoff = Equations::interpret(_store, _cutoff->text().toLatin1(), &ok); 0396 } 0397 0398 if (!ok) { 0399 cutoff = 0.0; 0400 } 0401 0402 // set frequency: either evaluate as equation, or convert to double. 0403 ok = false; 0404 frequency = _SR->text().toDouble(&ok); 0405 if (!ok) { 0406 frequency = Equations::interpret(_store, _SR->text().toLatin1(), &ok); 0407 } 0408 0409 if (!ok) { 0410 frequency = 0.0; 0411 } 0412 0413 // keep physical 0414 if (cutoff <=0.0) { 0415 cutoff = 1.0; 0416 } 0417 0418 if (frequency <= 0) { 0419 frequency = 1.0; 0420 } 0421 0422 if (ratio <= 0) { 0423 ratio = 1.0; 0424 } 0425 0426 if (control_field == Ratio) { // Frequency follows ratio: Keep SR fixed 0427 cutoff = ratio * frequency; 0428 _cutoff->setText(QString::number(cutoff, 'g', 12)); 0429 } else if (control_field == Cutoff) { // Ratio follows frequency: Keep SR fixed 0430 ratio = cutoff/frequency; 0431 setDefaultValue(ratio); 0432 //QString string = QString::number(ratio, 'g', 12); 0433 //_scalar->addItem(string, qVariantFromValue(0)); 0434 //_scalar->setCurrentIndex(_scalar->findText(string)); 0435 //_scalar->setCurrentText(QString::number(ratio, 'g', 12)); 0436 } else if (control_field == SampleRate) { // Cutoff follows SR. Keep ratio fixed 0437 cutoff = ratio * frequency; 0438 _cutoff->setText(QString::number(cutoff, 'g', 12)); 0439 //ratio = cutoff/frequency; 0440 //_scalar->setCurrentText(QString::number(ratio, 'g', 12)); 0441 } 0442 0443 } 0444 0445 } 0446 0447 // vim: ts=2 sw=2 et