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