QString UnitSystem::displayAmount( double amount, Unit* units, int precision, Unit::unitScale scale ) { // If the precision is not specified, we take the default one if( precision < 0) { precision = this->precision; } // Special cases. Make sure the unit isn't null and that we're // dealing with volume. if( units == 0 || units->getUnitType() != _type) return QString("%L1").arg(amount, fieldWidth, format, precision); // We really shouldn't ever reference something that could be null until // after we have verified it isn't. double SIAmount = units->toSI( amount ); double absSIAmount = qAbs(SIAmount); Unit* last = 0; // Don't loop if the 'without' key is defined if ( scaleToUnit().contains(Unit::scaleWithout) ) scale = Unit::scaleWithout; // If a specific scale is provided, just use that and don't loop. if ( scaleToUnit().contains(scale) ) { Unit* bob = scaleToUnit().value(scale); return QString("%L1 %2").arg(bob->fromSI(SIAmount), fieldWidth, format, precision).arg(bob->getUnitName()); } // scaleToUnit() is a QMap which means we loop in the order in which the // items were inserted. Order counts, and this map has to be // created from smallest to largest scale (e.g., mg, g, kg). QMap<Unit::unitScale, Unit*>::const_iterator it; for( it = scaleToUnit().begin(); it != scaleToUnit().end(); ++it) { Unit* bob = it.value(); double boundary = bob->boundary(); // This is a nice bit of work, if I may say so myself. If we've been // through the loop at least once already, and the boundary condition is // met, use the Unit* from the last loop. if ( last && absSIAmount < bob->toSI(boundary) ) return QString("%L1 %2").arg(last->fromSI(SIAmount), fieldWidth, format, precision).arg(last->getUnitName()); // If we get all the way through the map, this will be the largest unit // available last = bob; } // If we get here, use the largest unit available if( last ) return QString("%L1 %2").arg(last->fromSI(SIAmount), fieldWidth, format, precision).arg(last->getUnitName()); else return QString("nounit"); // Should never happen, so be obvious if it does }
void EquipmentEditor::save() { if( obsEquip == 0 ) { setVisible(false); return; } Unit* weightUnit = 0; Unit* volumeUnit = 0; Brewtarget::getThicknessUnits( &volumeUnit, &weightUnit ); bool ok = false; double grainAbs = Brewtarget::toDouble( lineEdit_grainAbsorption->text(), &ok ); if ( ! ok ) Brewtarget::logW( QString("EquipmentEditor::save() could not convert %1 to double").arg(lineEdit_grainAbsorption->text())); double ga_LKg = grainAbs * volumeUnit->toSI(1.0) * weightUnit->fromSI(1.0); // Do some prewarning things. I would prefer to do this only on change, but // we need to be worried about new equipment too. if ( lineEdit_tunVolume->toSI() <= 0.001 ) QMessageBox::warning(this, tr("Tun Volume Warning"), tr("The tun volume you entered is 0. This may cause problems")); if ( lineEdit_batchSize->toSI() <= 0.001 ) QMessageBox::warning(this, tr("Batch Size Warning"), tr("The batch size you entered is 0. This may cause problems")); if ( lineEdit_hopUtilization->toSI() < 0.001 ) QMessageBox::warning(this, tr("Hop Utilization Warning"), tr("The hop utilization percentage you entered is 0. This may cause problems")); obsEquip->setName( lineEdit_name->text() ); obsEquip->setBoilSize_l( lineEdit_boilSize->toSI() ); obsEquip->setBatchSize_l( lineEdit_batchSize->toSI() ); obsEquip->setTunVolume_l( lineEdit_tunVolume->toSI() ); obsEquip->setTunWeight_kg( lineEdit_tunWeight->toSI() ); obsEquip->setTunSpecificHeat_calGC( lineEdit_tunSpecificHeat->toSI() ); obsEquip->setBoilTime_min( lineEdit_boilTime->toSI()); obsEquip->setEvapRate_lHr( lineEdit_evaporationRate->toSI() ); obsEquip->setTopUpKettle_l( lineEdit_topUpKettle->toSI() ); obsEquip->setTopUpWater_l( lineEdit_topUpWater->toSI() ); obsEquip->setTrubChillerLoss_l( lineEdit_trubChillerLoss->toSI() ); obsEquip->setLauterDeadspace_l( lineEdit_lauterDeadspace->toSI() ); obsEquip->setGrainAbsorption_LKg( ga_LKg ); obsEquip->setBoilingPoint_c( lineEdit_boilingPoint->toSI() ); obsEquip->setHopUtilization_pct( lineEdit_hopUtilization->toSI() ); obsEquip->setNotes(textEdit_notes->toPlainText()); obsEquip->setCalcBoilVolume(checkBox_calcBoilVolume->checkState() == Qt::Checked); setVisible(false); return; }
void EquipmentEditor::showChanges() { Equipment *e = obsEquip; if( e == 0 ) { clear(); return; } // Get weight and volume units for grain absorption. Unit* weightUnit = 0; Unit* volumeUnit = 0; Brewtarget::getThicknessUnits( &volumeUnit, &weightUnit ); label_absorption->setText(tr("Grain absorption (%1/%2)").arg(volumeUnit->getUnitName()).arg(weightUnit->getUnitName())); //equipmentComboBox->setIndexByEquipment(e); lineEdit_name->setText(e->name()); lineEdit_name->setCursorPosition(0); lineEdit_boilSize->setText(e); checkBox_calcBoilVolume->blockSignals(true); // Keep next line from emitting a signal and changing e. checkBox_calcBoilVolume->setCheckState( (e->calcBoilVolume())? Qt::Checked : Qt::Unchecked ); checkBox_calcBoilVolume->blockSignals(false); lineEdit_batchSize->setText(e); lineEdit_tunVolume->setText(e); lineEdit_tunWeight->setText(e); lineEdit_tunSpecificHeat->setText(e); lineEdit_boilTime->setText(e); lineEdit_evaporationRate->setText(e); lineEdit_topUpKettle->setText(e); lineEdit_topUpWater->setText(e); lineEdit_trubChillerLoss->setText(e); lineEdit_lauterDeadspace->setText(e); textEdit_notes->setText( e->notes() ); double gaCustomUnits = e->grainAbsorption_LKg() * volumeUnit->fromSI(1.0) * weightUnit->toSI(1.0); lineEdit_grainAbsorption->setText(gaCustomUnits); lineEdit_boilingPoint->setText(e); lineEdit_hopUtilization->setText(e); checkBox_defaultEquipment->blockSignals(true); if ( Brewtarget::option("defaultEquipmentKey",-1) == e->key() ) checkBox_defaultEquipment->setCheckState(Qt::Checked); else checkBox_defaultEquipment->setCheckState(Qt::Unchecked); checkBox_defaultEquipment->blockSignals(false); }
double UnitSystem::qstringToSI(QString qstr, Unit* defUnit, bool force, Unit::unitScale scale) { double amt = 0.0; Unit* u = defUnit; Unit* found = 0; // make sure we can parse the string if (amtUnit.indexIn(qstr) == -1) { return 0.0; } amt = Brewtarget::toDouble( amtUnit.cap(1), "UnitSystem::qstringToSI()"); QString unit = amtUnit.cap(2); // Look first in this unit system. If you can't find it here, find it // globally. I *think* this finally has all the weird magic right. If the // field is marked as "Imperial" and you enter "3 qt" you get 3 imperial // qts, 3.6 US qts, 3.41L. If you enter 3L, you get 2.64 imperial qts, // 3.17 US qt. If you mean 3 US qt, you are SOL unless you mark the field // as US Customary. if ( ! unit.isEmpty() ) { found = qstringToUnit().value(unit); } else if ( scale != Unit::noScale ) { found = scaleToUnit().value(scale); } if ( ! found ) found = Unit::getUnit(unit,false); // If the calling method isn't overriding the search and we actually found // something, use it if ( ! force && found ) { u = found; } // It is possible for u to be NULL at this point, so make sure we handle // that case if ( u == 0 ) { return -1.0; } return u->toSI(amt); }
double UnitSystem::amountDisplay( double amount, Unit* units, Unit::unitScale scale ) { // Special cases. Make sure the unit isn't null and that we're // dealing with volume. if( units == 0 || units->getUnitType() != _type) return amount; double SIAmount = units->toSI( amount ); double absSIAmount = qAbs(SIAmount); Unit* last = 0; // Short circuit if the 'without' key is defined if ( scaleToUnit().contains(Unit::scaleWithout) ) scale = Unit::scaleWithout; if ( scaleToUnit().contains(scale) ) { Unit* bob = scaleToUnit().value(scale); return bob->fromSI(SIAmount); } QMap<Unit::unitScale, Unit*>::const_iterator it; for( it = scaleToUnit().begin(); it != scaleToUnit().end(); ++it) { Unit* bob = it.value(); double boundary = bob->boundary(); if ( last && absSIAmount < bob->toSI(boundary) ) return last->fromSI(SIAmount); last = bob; } // If we get here, use the largest unit available if( last ) return last->fromSI(SIAmount); else return -42.42; // Should never happen, so be obvious if it does }
void EquipmentEditor::resetAbsorption() { if( obsEquip == 0 ) return; // Get weight and volume units for grain absorption. Unit* weightUnit = 0; Unit* volumeUnit = 0; Brewtarget::getThicknessUnits( &volumeUnit, &weightUnit ); double gaCustomUnits = PhysicalConstants::grainAbsorption_Lkg * volumeUnit->fromSI(1.0) * weightUnit->toSI(1.0); lineEdit_grainAbsorption->displayAmount(gaCustomUnits); }