File indexing completed on 2024-03-24 05:53:15
0001 /*************************************************************************** 0002 keurocalc.cpp - main widget 0003 ------------------- 0004 begin : sam déc 1 23:40:19 CET 2001 0005 copyright : (C) 2001-2022 by Éric Bischoff 0006 email : bischoff@kde.org 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 ***************************************************************************/ 0017 0018 #include <stdlib.h> 0019 #include <math.h> 0020 #include <locale.h> 0021 0022 #include <QDBusConnection> 0023 #include <QPushButton> 0024 #include <QKeyEvent> 0025 0026 #include <KLocalizedString> 0027 #include <KConfigGroup> 0028 #include <KSharedConfig> 0029 #include <KAboutData> 0030 #include <KAboutApplicationDialog> 0031 #include <KMessageBox> 0032 #include <KHelpClient> 0033 0034 #include "keurocalc.h" 0035 #include "preferences.h" 0036 0037 #include <config-keurocalc.h> 0038 0039 #if HAVE_XLOCALE_H 0040 #include <xlocale.h> 0041 #endif 0042 0043 static const char 0044 *euroSymbol = " €"; 0045 // *dollarSymbol = " $"; 0046 0047 // Constructor 0048 KEuroCalc::KEuroCalc(QWidget *parent) 0049 : QDialog(parent), Ui::Calculator(), 0050 currencies() 0051 { 0052 int position; 0053 QPalette palette; 0054 0055 setupUi(this); 0056 QDBusConnection::sessionBus().registerObject 0057 ("/KEuroCalc", this, QDBusConnection::ExportScriptableSlots); 0058 connect( ¤cies, SIGNAL(endDownload(int,QString)), 0059 this, SLOT(endDownload(int,QString)) 0060 ); 0061 0062 c_locale = newlocale(LC_NUMERIC_MASK, "C", NULL); 0063 isSimpleValue = false; 0064 simpleValue = 0.0; 0065 referenceValue = 0.0; 0066 currencyValue = 0.0; 0067 0068 memorySet = false; 0069 isSimpleMemory = false; 0070 simpleMemory = 0.0; 0071 referenceMemory = 0.0; 0072 0073 if ( !currencies.readCurrencies( "currencies.xml" ) ) 0074 { 0075 KMessageBox::error( 0, i18n( "Cannot load currencies.xml" ) ); 0076 exit(1); 0077 } 0078 readOptions( reference, currencyNum, rounding, displayColor, splashScreen ); 0079 0080 displayNewCurrency(); 0081 displayNewResult(); 0082 resetInput(); 0083 initButtons(); 0084 startDownload(); 0085 0086 position = currencies.position(currencyNum); 0087 if (position < 0) position = 0; 0088 CurrencyList->setCurrentIndex( position ); 0089 0090 palette.setColor( backgroundRole(), displayColor ); 0091 ResultDisplay->setPalette( palette ); 0092 InputDisplay->setPalette( palette ); 0093 OperatorDisplay->setPalette( palette ); 0094 0095 setFocusPolicy( Qt::StrongFocus ); 0096 connect(ZeroButton, &QAbstractButton::pressed, this, &KEuroCalc::InputZero); 0097 connect(FiveButton, &QAbstractButton::pressed, this, &KEuroCalc::InputFive); 0098 connect(FourButton, &QAbstractButton::pressed, this, &KEuroCalc::InputFour); 0099 connect(SevenButton, &QAbstractButton::pressed, this, &KEuroCalc::InputSeven); 0100 connect(SixButton, &QAbstractButton::pressed, this, &KEuroCalc::InputSix); 0101 connect(ThreeButton, &QAbstractButton::pressed, this, &KEuroCalc::InputThree); 0102 connect(TwoButton, &QAbstractButton::pressed, this, &KEuroCalc::InputTwo); 0103 connect(EightButton, &QAbstractButton::pressed, this, &KEuroCalc::InputEight); 0104 connect(NineButton, &QAbstractButton::pressed, this, &KEuroCalc::InputNine); 0105 connect(HelpButton, &QAbstractButton::pressed, this, &KEuroCalc::DisplayHelp); 0106 connect(DotButton, &QAbstractButton::pressed, this, &KEuroCalc::InputDot); 0107 connect(OneButton, &QAbstractButton::pressed, this, &KEuroCalc::InputOne); 0108 connect(BackspaceButton, &QAbstractButton::pressed, this, &KEuroCalc::InputBackspace); 0109 connect(ResetButton, &QAbstractButton::pressed, this, &KEuroCalc::Reset); 0110 connect(ReferenceButton, &QAbstractButton::pressed, this, &KEuroCalc::ValidateReference); 0111 connect(SlashButton, &QAbstractButton::pressed, this, &KEuroCalc::InputSlash); 0112 connect(AsteriskButton, &QAbstractButton::pressed, this, &KEuroCalc::InputAsterisk); 0113 connect(MinusButton, &QAbstractButton::pressed, this, &KEuroCalc::InputMinus); 0114 connect(PlusButton, &QAbstractButton::pressed, this, &KEuroCalc::InputPlus); 0115 connect(CurrencyButton, &QAbstractButton::pressed, this, &KEuroCalc::ValidateCurrency); 0116 connect(PercentButton, &QAbstractButton::pressed, this, &KEuroCalc::ValidatePercent); 0117 connect(PlusMinusButton, &QAbstractButton::pressed, this, &KEuroCalc::ChangeSign); 0118 connect(SimpleValueButton, &QAbstractButton::pressed, this, &KEuroCalc::ValidateSimpleValue); 0119 connect(AboutButton, &QAbstractButton::pressed, this, &KEuroCalc::DisplayAbout); 0120 connect(MInputButton, &QAbstractButton::pressed, this, &KEuroCalc::MemoryInput); 0121 connect(MRecallButton, &QAbstractButton::pressed, this, &KEuroCalc::MemoryRecall); 0122 connect(MMinusButton, &QAbstractButton::pressed, this, &KEuroCalc::MemoryMinus); 0123 connect(MPlusButton, &QAbstractButton::pressed, this, &KEuroCalc::MemoryPlus); 0124 connect(CurrencyList, &QComboBox::activated, this, &KEuroCalc::SelectCurrency); 0125 connect(SettingsButton, &QAbstractButton::pressed, this, &KEuroCalc::DisplaySettings); 0126 } 0127 0128 // Destructor 0129 KEuroCalc::~KEuroCalc() 0130 { 0131 freelocale(c_locale); 0132 } 0133 0134 // Is splash screen to be displayed ? 0135 bool KEuroCalc::readSplashScreen() const 0136 { 0137 KConfigGroup config(KSharedConfig::openConfig(), "General"); 0138 QString option; 0139 0140 option = config.readEntry("SplashScreen", "yes"); 0141 0142 return option == "yes"; 0143 } 0144 0145 // Read options from preferences file 0146 void KEuroCalc::readOptions(int &oldReference, int &oldCurrency, int &oldRounding, QColor &oldDisplayColor, bool &oldSplashScreen) const 0147 { 0148 KConfigGroup config(KSharedConfig::openConfig(), "General"); 0149 QString option; 0150 0151 option = config.readEntry("Reference", "EURO_ECB"); 0152 if (option == "EURO_FIXED") 0153 oldReference = EURO_FIXED; 0154 else if (option == "EURO_ECB") 0155 oldReference = EURO_ECB; 0156 // else if (option == "DOLLAR_NY_FRB") 0157 // oldReference = DOLLAR_NY_FRB; 0158 else if (option == "EURO_TG") 0159 oldReference = EURO_TG; 0160 else oldReference = EURO_ECB; 0161 0162 option = config.readEntry("Currency", "USD"); 0163 for (oldCurrency = 0; oldCurrency < currencies.number(); ++oldCurrency) 0164 if ( option == currencies.code(oldCurrency) ) 0165 break; 0166 if ( oldCurrency == currencies.number() ) 0167 oldCurrency = currencies.dollar(); 0168 0169 option = config.readEntry("Rounding", "OFFICIAL_RULES"); 0170 if (option == "OFFICIAL_RULES") 0171 oldRounding = OFFICIAL_RULES; 0172 else if (option == "SMALLEST_COIN") 0173 oldRounding = SMALLEST_COIN; 0174 else if (option == "NO_ROUNDING") 0175 oldRounding = NO_ROUNDING; 0176 else oldRounding = OFFICIAL_RULES; 0177 0178 option = config.readEntry("DiplayColor", "#C0FFFF"); 0179 oldDisplayColor.setNamedColor(option); 0180 0181 option = config.readEntry("SplashScreen", "yes"); 0182 oldSplashScreen = option == "yes"; 0183 } 0184 0185 // Write options to preferences file 0186 void KEuroCalc::writeOptions(int newReference, int newCurrency, int newRounding, const QColor &newDisplayColor, bool newSplashScreen) 0187 { 0188 KConfigGroup config(KSharedConfig::openConfig(), "General"); 0189 0190 switch (newReference) 0191 { case EURO_FIXED: 0192 config.writeEntry("Reference", "EURO_FIXED"); 0193 break; 0194 case EURO_ECB: 0195 config.writeEntry("Reference", "EURO_ECB"); 0196 break; 0197 // case DOLLAR_NY_FRB: 0198 // config.writeEntry("Reference", "DOLLAR_NY_FRB"); 0199 // break; 0200 case EURO_TG: 0201 config.writeEntry("Reference", "EURO_TG"); 0202 } 0203 0204 config.writeEntry("Currency", currencies.code(newCurrency) ); 0205 0206 switch (newRounding) 0207 { case OFFICIAL_RULES: 0208 config.writeEntry("Rounding", "OFFICIAL_RULES"); 0209 break; 0210 case SMALLEST_COIN: 0211 config.writeEntry("Rounding", "SMALLEST_COIN"); 0212 break; 0213 case NO_ROUNDING: 0214 config.writeEntry("Rounding", "NO_ROUNDING"); 0215 } 0216 0217 config.writeEntry("DiplayColor", newDisplayColor.name()); 0218 0219 config.writeEntry("SplashScreen", newSplashScreen? "yes": "no"); 0220 0221 config.sync(); 0222 } 0223 0224 // Set new preferences dialog 0225 void KEuroCalc::setPreferences(int newReference, int newCurrency, int newRounding, const QColor &newDisplayColor, bool newSplashScreen) 0226 { 0227 reference = newReference; 0228 currencyNum = newCurrency; 0229 rounding = newRounding; 0230 displayColor = newDisplayColor; 0231 splashScreen = newSplashScreen; 0232 0233 CurrencyList->clear(); 0234 initButtons(); 0235 startDownload(); 0236 Reset(); 0237 } 0238 0239 // Handle key press events 0240 void KEuroCalc::keyPressEvent(QKeyEvent *e) 0241 { 0242 switch (e->key()) 0243 { 0244 case Qt::Key_Period: 0245 case Qt::Key_Comma: 0246 inputDigit('.'); 0247 break; 0248 case Qt::Key_0: 0249 ZeroButton->animateClick(); 0250 break; 0251 case Qt::Key_1: 0252 OneButton->animateClick(); 0253 break; 0254 case Qt::Key_2: 0255 TwoButton->animateClick(); 0256 break; 0257 case Qt::Key_3: 0258 ThreeButton->animateClick(); 0259 break; 0260 case Qt::Key_4: 0261 FourButton->animateClick(); 0262 break; 0263 case Qt::Key_5: 0264 FiveButton->animateClick(); 0265 break; 0266 case Qt::Key_6: 0267 SixButton->animateClick(); 0268 break; 0269 case Qt::Key_7: 0270 SevenButton->animateClick(); 0271 break; 0272 case Qt::Key_8: 0273 EightButton->animateClick(); 0274 break; 0275 case Qt::Key_9: 0276 NineButton->animateClick(); 0277 break; 0278 case Qt::Key_Plus: 0279 PlusButton->animateClick(); 0280 break; 0281 case Qt::Key_Minus: 0282 MinusButton->animateClick(); 0283 break; 0284 case Qt::Key_Asterisk: 0285 AsteriskButton->animateClick(); 0286 break; 0287 case Qt::Key_Slash: 0288 SlashButton->animateClick(); 0289 break; 0290 case Qt::Key_Backspace: 0291 BackspaceButton->animateClick(); 0292 break; 0293 case Qt::Key_E: 0294 case Qt::Key_Dollar: 0295 ReferenceButton->animateClick(); 0296 break; 0297 case Qt::Key_Percent: 0298 PercentButton->animateClick(); 0299 break; 0300 case Qt::Key_Enter: 0301 case Qt::Key_Return: 0302 SimpleValueButton->animateClick(); 0303 break; 0304 case Qt::Key_S: 0305 PlusMinusButton->animateClick(); 0306 break; 0307 case Qt::Key_Shift: 0308 case Qt::Key_Control: 0309 case Qt::Key_Meta: 0310 case Qt::Key_Alt: 0311 case Qt::Key_CapsLock: 0312 case Qt::Key_NumLock: 0313 case Qt::Key_ScrollLock: 0314 break; 0315 default: 0316 CurrencyButton->animateClick(); 0317 break; 0318 } 0319 } 0320 0321 // Dot button or key pressed 0322 void KEuroCalc::InputDot() 0323 { 0324 inputDigit('.'); 0325 } 0326 0327 // Zero button or key pressed 0328 void KEuroCalc::InputZero() 0329 { 0330 inputDigit('0'); 0331 } 0332 0333 // One button or key pressed 0334 void KEuroCalc::InputOne() 0335 { 0336 inputDigit('1'); 0337 } 0338 0339 // Two button or key pressed 0340 void KEuroCalc::InputTwo() 0341 { 0342 inputDigit('2'); 0343 } 0344 0345 // Three button or key pressed 0346 void KEuroCalc::InputThree() 0347 { 0348 inputDigit('3'); 0349 } 0350 0351 // Four button or key pressed 0352 void KEuroCalc::InputFour() 0353 { 0354 inputDigit('4'); 0355 } 0356 0357 // Five button or key pressed 0358 void KEuroCalc::InputFive() 0359 { 0360 inputDigit('5'); 0361 } 0362 0363 // Six button or key pressed 0364 void KEuroCalc::InputSix() 0365 { 0366 inputDigit('6'); 0367 } 0368 0369 // Seven button or key pressed 0370 void KEuroCalc::InputSeven() 0371 { 0372 inputDigit('7'); 0373 } 0374 0375 // Eight button or key pressed 0376 void KEuroCalc::InputEight() 0377 { 0378 inputDigit('8'); 0379 } 0380 0381 // Nine button or key pressed 0382 void KEuroCalc::InputNine() 0383 { 0384 inputDigit('9'); 0385 } 0386 0387 // Plus button or key pressed 0388 void KEuroCalc::InputPlus() 0389 { 0390 inputOperator('+'); 0391 } 0392 0393 // Minus button or key pressed 0394 void KEuroCalc::InputMinus() 0395 { 0396 inputOperator('-'); 0397 } 0398 0399 // Multiply button or key pressed 0400 void KEuroCalc::InputAsterisk() 0401 { 0402 inputOperator('x'); 0403 } 0404 0405 // Divide button or key pressed 0406 void KEuroCalc::InputSlash() 0407 { 0408 inputOperator('/'); 0409 } 0410 0411 // Correct last entered digit 0412 void KEuroCalc::InputBackspace() 0413 { 0414 inputCorrect(); 0415 } 0416 0417 // Convert to currency, and add or subtract too if needed 0418 void KEuroCalc::ValidateReference() 0419 { 0420 double inputValue, currencyRate, currencyPrecision; 0421 0422 inputValue = strtod_l( inputDisplay, NULL, c_locale ); 0423 currencyRate = currencies.rate(currencyNum); 0424 switch (rounding) 0425 { 0426 case OFFICIAL_RULES: 0427 currencyPrecision = currencies.officialRulesPrecision(currencyNum); 0428 break; 0429 case SMALLEST_COIN: 0430 currencyPrecision = currencies.smallestCoinPrecision(currencyNum); 0431 break; 0432 default: 0433 currencyPrecision = 1.0; 0434 } 0435 if ( inputDisplay[10] == ' ' ) 0436 { 0437 if ( isSimpleValue && *operatorDisplay == ' ' ) 0438 { 0439 isSimpleValue = false; 0440 referenceValue = simpleValue; 0441 currencyValue = referenceValue * currencyRate * currencyPrecision; 0442 displayNewResult(); 0443 } 0444 else QApplication::beep(); 0445 return; 0446 } 0447 0448 switch ( *operatorDisplay ) 0449 { 0450 case ' ': 0451 isSimpleValue = false; 0452 referenceValue = inputValue; 0453 currencyValue = referenceValue * currencyRate * currencyPrecision; 0454 break; 0455 case '+': 0456 if ( isSimpleValue ) 0457 { 0458 QApplication::beep(); 0459 return; 0460 } 0461 referenceValue += inputValue; 0462 currencyValue = referenceValue * currencyRate * currencyPrecision; 0463 break; 0464 case '-': 0465 if ( isSimpleValue ) 0466 { 0467 QApplication::beep(); 0468 return; 0469 } 0470 referenceValue -= inputValue; 0471 currencyValue = referenceValue * currencyRate * currencyPrecision; 0472 break; 0473 case 'x': 0474 if ( isSimpleValue ) 0475 { 0476 isSimpleValue = false; 0477 referenceValue = simpleValue * inputValue; 0478 currencyValue = referenceValue * currencyRate * currencyPrecision; 0479 } 0480 else 0481 { 0482 QApplication::beep(); 0483 return; 0484 } 0485 break; 0486 case '/': 0487 if ( !isSimpleValue && inputValue != 0.0 ) 0488 { 0489 isSimpleValue = true; 0490 simpleValue = referenceValue / inputValue; 0491 } 0492 else 0493 { 0494 QApplication::beep(); 0495 return; 0496 } 0497 } 0498 resetInput(); 0499 displayNewResult(); 0500 displayMemoryButtons(); 0501 } 0502 0503 // Convert to reference, and add or subtract too if needed 0504 void KEuroCalc::ValidateCurrency() 0505 { 0506 double inputValue, currencyRate, currencyPrecision; 0507 0508 inputValue = strtod_l( inputDisplay, NULL, c_locale ); 0509 currencyRate = currencies.rate(currencyNum); 0510 switch (rounding) 0511 { 0512 case OFFICIAL_RULES: 0513 currencyPrecision = currencies.officialRulesPrecision(currencyNum); 0514 break; 0515 case SMALLEST_COIN: 0516 currencyPrecision = currencies.smallestCoinPrecision(currencyNum); 0517 break; 0518 default: 0519 currencyPrecision = 1.0; 0520 } 0521 0522 if ( inputDisplay[10] == ' ' ) 0523 { 0524 if ( isSimpleValue && *operatorDisplay == ' ' ) 0525 { 0526 isSimpleValue = false; 0527 currencyValue = simpleValue; 0528 referenceValue = currencyValue / currencyRate / currencyPrecision; 0529 displayNewResult(); 0530 } 0531 else QApplication::beep(); 0532 return; 0533 } 0534 0535 switch ( *operatorDisplay ) 0536 { 0537 case ' ': 0538 isSimpleValue = false; 0539 currencyValue = inputValue; 0540 referenceValue = currencyValue / currencyRate / currencyPrecision; 0541 break; 0542 case '+': 0543 if ( isSimpleValue ) 0544 { 0545 QApplication::beep(); 0546 return; 0547 } 0548 currencyValue += inputValue; 0549 referenceValue = currencyValue / currencyRate / currencyPrecision; 0550 break; 0551 case '-': 0552 if ( isSimpleValue ) 0553 { 0554 QApplication::beep(); 0555 return; 0556 } 0557 currencyValue -= inputValue; 0558 referenceValue = currencyValue / currencyRate / currencyPrecision; 0559 break; 0560 case 'x': 0561 if ( isSimpleValue ) 0562 { 0563 isSimpleValue = false; 0564 currencyValue = simpleValue * inputValue; 0565 referenceValue = currencyValue / currencyRate / currencyPrecision; 0566 } 0567 else 0568 { 0569 QApplication::beep(); 0570 return; 0571 } 0572 break; 0573 case '/': 0574 if ( !isSimpleValue && inputValue != 0.0 ) 0575 { 0576 isSimpleValue = true; 0577 simpleValue = currencyValue / inputValue; 0578 } 0579 else 0580 { 0581 QApplication::beep(); 0582 return; 0583 } 0584 } 0585 resetInput(); 0586 displayNewResult(); 0587 displayMemoryButtons(); 0588 } 0589 0590 // Apply percentage, and add or subtract too if needed 0591 void KEuroCalc::ValidatePercent() 0592 { 0593 double inputValue, currencyRate, currencyPrecision; 0594 0595 inputValue = strtod_l( inputDisplay, NULL, c_locale ); 0596 currencyRate = currencies.rate(currencyNum); 0597 switch (rounding) 0598 { 0599 case OFFICIAL_RULES: 0600 currencyPrecision = currencies.officialRulesPrecision(currencyNum); 0601 break; 0602 case SMALLEST_COIN: 0603 currencyPrecision = currencies.smallestCoinPrecision(currencyNum); 0604 break; 0605 default: 0606 currencyPrecision = 1.0; 0607 } 0608 0609 if ( inputDisplay[10] == ' ' ) 0610 { 0611 QApplication::beep(); 0612 return; 0613 } 0614 0615 switch ( *operatorDisplay ) 0616 { 0617 case ' ': 0618 if ( isSimpleValue ) 0619 simpleValue = (inputValue * simpleValue) / 100.0; 0620 else 0621 { 0622 referenceValue = (inputValue * referenceValue) / 100.0; 0623 currencyValue = referenceValue * currencyRate * currencyPrecision; 0624 } 0625 break; 0626 case '+': 0627 if ( isSimpleValue ) 0628 simpleValue = ((100.0 + inputValue) * simpleValue) / 100.0; 0629 else 0630 { 0631 referenceValue = ((100.0 + inputValue) * referenceValue) / 100.0; 0632 currencyValue = referenceValue * currencyRate * currencyPrecision; 0633 } 0634 break; 0635 case '-': 0636 if ( isSimpleValue ) 0637 simpleValue = ((100.0 - inputValue) * simpleValue) / 100.0; 0638 else 0639 { 0640 referenceValue = ((100.0 - inputValue) * referenceValue) / 100.0; 0641 currencyValue = referenceValue * currencyRate * currencyPrecision; 0642 } 0643 break; 0644 case 'x': 0645 case '/': 0646 QApplication::beep(); 0647 return; 0648 } 0649 resetInput(); 0650 displayNewResult(); 0651 } 0652 0653 // Enter a simple value, and multiply or divide too if needed. 0654 void KEuroCalc::ValidateSimpleValue() 0655 { 0656 double inputValue, currencyRate, currencyPrecision; 0657 0658 inputValue = strtod_l( inputDisplay, NULL, c_locale ); 0659 currencyRate = currencies.rate(currencyNum); 0660 switch (rounding) 0661 { 0662 case OFFICIAL_RULES: 0663 currencyPrecision = currencies.officialRulesPrecision(currencyNum); 0664 break; 0665 case SMALLEST_COIN: 0666 currencyPrecision = currencies.smallestCoinPrecision(currencyNum); 0667 break; 0668 default: 0669 currencyPrecision = 1.0; 0670 } 0671 0672 if ( inputDisplay[10] == ' ' ) 0673 { 0674 QApplication::beep(); 0675 return; 0676 } 0677 0678 switch ( *operatorDisplay ) 0679 { 0680 case ' ': 0681 isSimpleValue = true; 0682 simpleValue = inputValue; 0683 break; 0684 case '+': 0685 if ( isSimpleValue ) 0686 simpleValue += inputValue; 0687 else 0688 { 0689 QApplication::beep(); 0690 return; 0691 } 0692 break; 0693 case '-': 0694 if ( isSimpleValue ) 0695 simpleValue -= inputValue; 0696 else 0697 { 0698 QApplication::beep(); 0699 return; 0700 } 0701 break; 0702 case 'x': 0703 if ( isSimpleValue ) 0704 simpleValue *= inputValue; 0705 else 0706 { 0707 referenceValue *= inputValue; 0708 currencyValue = referenceValue * currencyRate * currencyPrecision; 0709 } 0710 break; 0711 case '/': 0712 if ( inputValue == 0.0 ) 0713 { 0714 QApplication::beep(); 0715 return; 0716 } 0717 if ( isSimpleValue ) 0718 simpleValue /= inputValue; 0719 else 0720 { 0721 referenceValue /= inputValue; 0722 currencyValue = referenceValue * currencyRate * currencyPrecision; 0723 } 0724 break; 0725 default: 0726 QApplication::beep(); 0727 return; 0728 } 0729 resetInput(); 0730 displayNewResult(); 0731 displayMemoryButtons(); 0732 } 0733 0734 // Change the sign of the result 0735 void KEuroCalc::ChangeSign() 0736 { 0737 double currencyRate, currencyPrecision; 0738 0739 currencyRate = currencies.rate(currencyNum); 0740 switch (rounding) 0741 { 0742 case OFFICIAL_RULES: 0743 currencyPrecision = currencies.officialRulesPrecision(currencyNum); 0744 break; 0745 case SMALLEST_COIN: 0746 currencyPrecision = currencies.smallestCoinPrecision(currencyNum); 0747 break; 0748 default: 0749 currencyPrecision = 1.0; 0750 } 0751 0752 if ( isSimpleValue ) 0753 simpleValue = -simpleValue; 0754 else 0755 { 0756 referenceValue = -referenceValue; 0757 currencyValue = referenceValue * currencyRate * currencyPrecision; 0758 } 0759 displayNewResult(); 0760 } 0761 0762 // Transfer from display to memory 0763 void KEuroCalc::MemoryInput() 0764 { 0765 memorySet = true; 0766 isSimpleMemory = isSimpleValue; 0767 simpleMemory = simpleValue; 0768 referenceMemory = referenceValue; 0769 0770 displayMemoryButtons(); 0771 } 0772 0773 // Transfer from memory to display 0774 void KEuroCalc::MemoryRecall() 0775 { 0776 double currencyRate, currencyPrecision; 0777 0778 currencyRate = currencies.rate(currencyNum); 0779 switch (rounding) 0780 { 0781 case OFFICIAL_RULES: 0782 currencyPrecision = currencies.officialRulesPrecision(currencyNum); 0783 break; 0784 case SMALLEST_COIN: 0785 currencyPrecision = currencies.smallestCoinPrecision(currencyNum); 0786 break; 0787 default: 0788 currencyPrecision = 1.0; 0789 } 0790 0791 if ( !memorySet ) 0792 { 0793 QApplication::beep(); 0794 return; 0795 } 0796 0797 switch ( *operatorDisplay ) 0798 { 0799 case ' ': 0800 isSimpleValue = isSimpleMemory; 0801 if ( isSimpleMemory ) 0802 simpleValue = simpleMemory; 0803 else 0804 { 0805 referenceValue = referenceMemory; 0806 currencyValue = referenceValue * currencyRate * currencyPrecision; 0807 } 0808 break; 0809 case '+': 0810 if ( isSimpleValue != isSimpleMemory ) 0811 { 0812 QApplication::beep(); 0813 return; 0814 } 0815 if ( isSimpleMemory ) 0816 simpleValue += simpleMemory; 0817 else 0818 { 0819 referenceValue += referenceMemory; 0820 currencyValue = referenceValue * currencyRate * currencyPrecision; 0821 } 0822 break; 0823 case '-': 0824 if ( isSimpleValue != isSimpleMemory ) 0825 { 0826 QApplication::beep(); 0827 return; 0828 } 0829 if ( isSimpleMemory ) 0830 simpleValue -= simpleMemory; 0831 else 0832 { 0833 referenceValue -= referenceMemory; 0834 currencyValue = referenceValue * currencyRate * currencyPrecision; 0835 } 0836 break; 0837 case 'x': 0838 if ( isSimpleMemory ) 0839 { 0840 if ( isSimpleValue ) 0841 simpleValue *= simpleMemory; 0842 else 0843 { 0844 referenceValue *= simpleMemory; 0845 currencyValue = referenceValue * currencyRate * currencyPrecision; 0846 } 0847 } 0848 else 0849 { 0850 if ( isSimpleValue ) 0851 { 0852 isSimpleValue = false; 0853 referenceValue = simpleValue * referenceMemory; 0854 currencyValue = referenceValue * currencyRate * currencyPrecision; 0855 } 0856 else 0857 { 0858 QApplication::beep(); 0859 return; 0860 } 0861 } 0862 break; 0863 case '/': 0864 if ( isSimpleMemory ) 0865 { 0866 if ( simpleMemory == 0.0 ) 0867 { 0868 QApplication::beep(); 0869 return; 0870 } 0871 if ( isSimpleValue ) 0872 simpleValue /= simpleMemory; 0873 else 0874 { 0875 referenceValue /= simpleMemory; 0876 currencyValue = referenceValue * currencyRate * currencyPrecision; 0877 } 0878 } 0879 else 0880 { 0881 if ( !isSimpleValue && referenceMemory != 0.0 ) 0882 { 0883 isSimpleValue = true; 0884 simpleValue = referenceValue / referenceMemory; 0885 } 0886 else 0887 { 0888 QApplication::beep(); 0889 return; 0890 } 0891 } 0892 } 0893 resetInput(); 0894 displayNewResult(); 0895 displayMemoryButtons(); 0896 } 0897 0898 // Add memory to display 0899 void KEuroCalc::MemoryPlus() 0900 { 0901 if ( !memorySet || (isSimpleValue != isSimpleMemory) ) 0902 { 0903 QApplication::beep(); 0904 return; 0905 } 0906 if ( isSimpleMemory ) 0907 simpleMemory += simpleValue; 0908 else 0909 referenceMemory += referenceValue; 0910 } 0911 0912 // Subtract memory from display 0913 void KEuroCalc::MemoryMinus() 0914 { 0915 if ( !memorySet || (isSimpleValue != isSimpleMemory) ) 0916 { 0917 QApplication::beep(); 0918 return; 0919 } 0920 if ( isSimpleMemory ) 0921 simpleMemory -= simpleValue; 0922 else 0923 referenceMemory -= referenceValue; 0924 } 0925 0926 // Reset both input, result and memory 0927 void KEuroCalc::Reset() 0928 { 0929 resetInput(); 0930 0931 isSimpleValue = false; 0932 simpleValue = 0.0; 0933 referenceValue = 0.0; 0934 currencyValue = 0.0; 0935 0936 displayNewResult(); 0937 0938 memorySet = false; 0939 isSimpleMemory = false; 0940 simpleMemory = 0.0; 0941 referenceMemory = 0.0; 0942 0943 displayMemoryButtons(); 0944 } 0945 0946 // Display "about" page 0947 void KEuroCalc::DisplayAbout() 0948 { 0949 KAboutApplicationDialog *d = new KAboutApplicationDialog(KAboutData::applicationData(), this); 0950 d->exec(); 0951 delete d; 0952 AboutButton->setDown( false ); 0953 } 0954 0955 // Display help pages 0956 void KEuroCalc::DisplayHelp() 0957 { 0958 KHelpClient::invokeHelp(); 0959 } 0960 0961 // Display settings pages 0962 void KEuroCalc::DisplaySettings() 0963 { 0964 Preferences *d = new Preferences(this, ¤cies); 0965 d->exec(); 0966 delete d; 0967 SettingsButton->setDown( false ); 0968 } 0969 0970 // Select currency accordingly to drop down list position 0971 void KEuroCalc::SelectCurrency(int position) 0972 { 0973 int num; 0974 double currencyRate, currencyPrecision; 0975 0976 for (num = 0; num < currencies.number(); num++) 0977 if (currencies.position(num) == position) 0978 break; 0979 if ( num == currencies.number() ) return; 0980 currencyNum = num; 0981 0982 displayNewCurrency(); 0983 0984 currencyRate = currencies.rate(currencyNum); 0985 switch (rounding) 0986 { 0987 case OFFICIAL_RULES: 0988 currencyPrecision = currencies.officialRulesPrecision(currencyNum); 0989 break; 0990 case SMALLEST_COIN: 0991 currencyPrecision = currencies.smallestCoinPrecision(currencyNum); 0992 break; 0993 default: 0994 currencyPrecision = 1.0; 0995 } 0996 currencyValue = referenceValue * currencyRate * currencyPrecision; 0997 displayNewResult(); 0998 setFocus(); 0999 } 1000 1001 // Initialize the buttons without translation and the buttons with UTF-8 1002 // text not correctly handled by uic 1003 void KEuroCalc::initButtons() 1004 { 1005 switch ( reference ) 1006 { 1007 case EURO_FIXED: 1008 SourceLabel->setText( i18n( "Fixed" ) ); 1009 DateLabel->setText( "" ); 1010 break; 1011 case EURO_ECB: 1012 SourceLabel->setText( i18n( "ECB" ) ); 1013 DateLabel->setText( i18n( "Loading..." ) ); 1014 break; 1015 // case DOLLAR_NY_FRB: 1016 // SourceLabel->setText( i18n( "NY FRB" ) ); 1017 // DateLabel->setText( i18n( "Loading..." ) ); 1018 // break; 1019 case EURO_TG: 1020 SourceLabel->setText( i18n( "TG" ) ); 1021 DateLabel->setText( i18n( "Loading..." ) ); 1022 } 1023 switch ( rounding ) 1024 { 1025 case OFFICIAL_RULES: 1026 RoundingLabel->setText( i18n( "Official rules" ) ); 1027 break; 1028 case SMALLEST_COIN: 1029 RoundingLabel->setText( i18n( "Smallest coin" ) ); 1030 break; 1031 case NO_ROUNDING: 1032 RoundingLabel->setText( i18n( "No rounding" ) ); 1033 } 1034 DotButton->setText( QLocale().decimalPoint() ); 1035 ZeroButton->setText( QString::fromUtf8( "0" ) ); 1036 OneButton->setText( QString::fromUtf8( "1" ) ); 1037 TwoButton->setText( QString::fromUtf8( "2" ) ); 1038 ThreeButton->setText( QString::fromUtf8( "3" ) ); 1039 FourButton->setText( QString::fromUtf8( "4" ) ); 1040 FiveButton->setText( QString::fromUtf8( "5" ) ); 1041 SixButton->setText( QString::fromUtf8( "6" ) ); 1042 SevenButton->setText( QString::fromUtf8( "7" ) ); 1043 EightButton->setText( QString::fromUtf8( "8" ) ); 1044 NineButton->setText( QString::fromUtf8( "9" ) ); 1045 BackspaceButton->setText( QString::fromUtf8( "<-" ) ); 1046 1047 MInputButton->setText( QString::fromUtf8( "Min" ) ); 1048 MRecallButton->setText( QString::fromUtf8( "MR" ) ); 1049 MMinusButton->setText( QString::fromUtf8( "M-" ) ); 1050 MPlusButton->setText( QString::fromUtf8( "M+" ) ); 1051 SlashButton->setText( QString::fromUtf8( "/" ) ); 1052 AsteriskButton->setText( QString::fromUtf8( "X" ) ); 1053 MinusButton->setText( QString::fromUtf8( "-" ) ); 1054 PlusButton->setText( QString::fromUtf8( "+" ) ); 1055 // ReferenceButton->setText( QString::fromUtf8( reference == DOLLAR_NY_FRB? dollarSymbol: euroSymbol ) ); 1056 ReferenceButton->setText( QString::fromUtf8( euroSymbol ) ); 1057 PercentButton->setText( QString::fromUtf8( "%" ) ); 1058 PlusMinusButton->setText( QString::fromUtf8( "+/-" ) ); 1059 } 1060 1061 // Start downloading rates 1062 void KEuroCalc::startDownload() 1063 { 1064 currencies.clearRates(); 1065 switch (reference) 1066 { 1067 case EURO_FIXED: 1068 currencies.addFixedRates( rounding ); 1069 // endDownload is called here 1070 break; 1071 case EURO_ECB: 1072 currencies.addFixedRates( rounding, true ); 1073 // endDownload is called here for the first time 1074 CurrencyList->addItem( "--------------------------------------------" ); 1075 currencies.addECBRates( rounding ); 1076 // endDowload is called again when completed 1077 break; 1078 // case DOLLAR_NY_FRB: 1079 // currencies.addNY_FRBRates( rounding ); 1080 // // endDowload is called when completed 1081 // break; 1082 case EURO_TG: 1083 currencies.addFixedRates( rounding, true ); 1084 // endDownload is called here for the first time 1085 CurrencyList->addItem( "--------------------------------------------" ); 1086 currencies.addTGRates( rounding ); 1087 // endDowload is called again when completed 1088 break; 1089 } 1090 } 1091 1092 // Download has ended 1093 void KEuroCalc::endDownload(int defaultCurrency, const QString &date) 1094 { 1095 int position, num; 1096 1097 position = CurrencyList->count(); 1098 for (num = 0; num < currencies.number(); ++num) 1099 if (currencies.position(num) == -2) 1100 { 1101 currencies.setPosition(num, position); 1102 CurrencyList->addItem 1103 ( currencies.code(num) + " - " + currencies.name(num) ); 1104 position++; 1105 } 1106 DateLabel->setText( date.isNull()? i18n( "Not loaded" ): date ); 1107 if ( defaultCurrency ) 1108 newRatesList( defaultCurrency ); 1109 } 1110 1111 // The rates list has changed, refresh the display 1112 void KEuroCalc::newRatesList(int defaultCurrency) 1113 { 1114 int position; 1115 1116 position = currencies.position(currencyNum); 1117 if (position < 0) // If current currency does not exist in new rates list, change current currency 1118 { 1119 for (currencyNum = 0; currencyNum < currencies.number(); ++currencyNum) 1120 { 1121 position = currencies.position(currencyNum); 1122 if (position == 0) break; 1123 } 1124 if ( currencyNum == currencies.number() ) // Handle case of empty list (no currencies at all) 1125 { 1126 currencyNum = defaultCurrency; 1127 currencies.setRate(currencyNum, 1.0); 1128 position = 0; 1129 currencies.setPosition(currencyNum, 0); 1130 CurrencyList->addItem 1131 ( currencies.code(currencyNum) + " - " + currencies.name(currencyNum) ); 1132 } 1133 } 1134 CurrencyList->setCurrentIndex( position ); 1135 displayNewCurrency(); 1136 displayNewResult(); 1137 } 1138 1139 // Input a digit ('0' to '9' or '.') 1140 void KEuroCalc::inputDigit(char c) 1141 { 1142 const char *s; 1143 char *d; 1144 switch ( inputPos ) 1145 { 1146 case atUnits: 1147 inputDisplay[10] = c; 1148 switch ( c ) 1149 { 1150 case '.': 1151 inputDisplay[9] = '0'; 1152 inputPos = afterUnits; 1153 break; 1154 case '0': 1155 break; 1156 default: 1157 inputPos = beforeUnits; 1158 } 1159 break; 1160 case beforeUnits: 1161 if ( inputDisplay[0] != ' ' ) 1162 { 1163 QApplication::beep(); 1164 return; 1165 } 1166 s = inputDisplay + 1; 1167 d = inputDisplay; 1168 while ( d < inputDisplay + 10 ) *d++ = *s++; 1169 *d = c; 1170 if ( c == '.' ) inputPos = afterUnits; 1171 break; 1172 case afterUnits: 1173 if ( inputDisplay[0] != ' ' ) 1174 { 1175 QApplication::beep(); 1176 return; 1177 } 1178 if ( c == '.' ) 1179 { 1180 QApplication::beep(); 1181 return; 1182 } 1183 s = inputDisplay + 1; 1184 d = inputDisplay; 1185 while ( d < inputDisplay + 10 ) *d++ = *s++; 1186 *d = c; 1187 break; 1188 } 1189 displayNewInput(); 1190 } 1191 1192 // Remove last entered digit 1193 void KEuroCalc::inputCorrect() 1194 { 1195 const char *s; 1196 char *d; 1197 1198 switch ( inputPos ) 1199 { 1200 case atUnits: 1201 if ( inputDisplay[10] == ' ' ) 1202 *operatorDisplay = ' '; 1203 break; 1204 case beforeUnits: 1205 case afterUnits: 1206 s = inputDisplay + 9; 1207 d = inputDisplay + 10; 1208 while ( d > inputDisplay) *d-- = *s--; 1209 *d = ' '; 1210 break; 1211 } 1212 inputPos = 1213 inputDisplay[10] == ' '? 1214 atUnits: 1215 (QString(inputDisplay).indexOf('.') == -1? beforeUnits: afterUnits); 1216 1217 displayNewInput(); 1218 } 1219 1220 // Input an operator ('+', '-', 'x' or '/') 1221 void KEuroCalc::inputOperator(char c) 1222 { 1223 if ( inputDisplay[10] != ' ' ) 1224 ValidateSimpleValue(); 1225 1226 *operatorDisplay = c; 1227 1228 displayNewInput(); 1229 } 1230 1231 // Reset input area 1232 void KEuroCalc::resetInput() 1233 { 1234 strcpy(operatorDisplay, " "); 1235 strcpy( inputDisplay, " " ); 1236 inputPos = atUnits; 1237 OperatorDisplay->setText( operatorDisplay ); 1238 InputDisplay->setText( inputDisplay ); 1239 } 1240 1241 // Display current input in input area 1242 void KEuroCalc::displayNewInput() 1243 { 1244 QString display(inputDisplay); 1245 normalize( display ); 1246 1247 OperatorDisplay->setText( operatorDisplay ); 1248 InputDisplay->setText( display ); 1249 } 1250 1251 // Display latest computed value in results area 1252 void KEuroCalc::displayNewResult() 1253 { 1254 if ( isSimpleValue ) 1255 { 1256 QString simpleDisplay; 1257 1258 simpleDisplay.setNum( simpleValue ); 1259 normalize( simpleDisplay ); 1260 ResultDisplay->setText( simpleDisplay ); 1261 } 1262 else 1263 { 1264 double currencyPrecision; 1265 float roundedReferenceValue, roundedCurrencyValue; 1266 QString referenceDisplay, currencyDisplay; 1267 QString referenceSymbol, currencySymbol; 1268 1269 if (rounding != NO_ROUNDING) 1270 { 1271 roundedReferenceValue = floor(referenceValue * 100.0 + 0.5) / 100.0; 1272 referenceDisplay.setNum( roundedReferenceValue, 'f', 2 ); 1273 } 1274 else referenceDisplay.setNum( referenceValue ); 1275 normalize( referenceDisplay ); 1276 // referenceSymbol = QString::fromUtf8( reference == DOLLAR_NY_FRB ? dollarSymbol: euroSymbol ); 1277 referenceSymbol = QString::fromUtf8( euroSymbol ); 1278 1279 switch (rounding) 1280 { 1281 case OFFICIAL_RULES: 1282 currencyPrecision = currencies.officialRulesPrecision(currencyNum); 1283 roundedCurrencyValue = floor(currencyValue * 100.0 / currencyPrecision + 0.5) 1284 / 100.0 * currencyPrecision; 1285 currencyDisplay.setNum( roundedCurrencyValue, 'f', currencyPrecision < 100.0? 2: 0 ); 1286 break; 1287 case SMALLEST_COIN: 1288 currencyPrecision = currencies.smallestCoinPrecision(currencyNum); 1289 roundedCurrencyValue = floor(currencyValue * 100.0 / currencyPrecision + 0.5) 1290 / 100.0 * currencyPrecision; 1291 currencyDisplay.setNum( roundedCurrencyValue, 'f', currencyPrecision < 100.0? 2: 0 ); 1292 break; 1293 default: 1294 currencyDisplay.setNum( currencyValue ); 1295 } 1296 normalize( currencyDisplay ); 1297 currencySymbol = currencies.symbol(currencyNum); 1298 1299 ResultDisplay->setText( referenceDisplay + referenceSymbol + '\n' + 1300 currencyDisplay + ' ' + currencySymbol ); 1301 } 1302 } 1303 1304 // Update the currency button accordingly to new currency 1305 void KEuroCalc::displayNewCurrency() 1306 { 1307 QString referenceSymbol, currencySymbol; 1308 1309 currencySymbol = currencies.symbol(currencyNum); 1310 CurrencyButton->setText( currencySymbol ); 1311 if ( currencies.position(currencyNum) >= 0 ) 1312 { 1313 double currencyRate, currencyPrecision; 1314 QString rate; 1315 1316 currencyRate = currencies.rate(currencyNum); 1317 switch (rounding) 1318 { 1319 case OFFICIAL_RULES: 1320 currencyPrecision = currencies.officialRulesPrecision(currencyNum); 1321 break; 1322 case SMALLEST_COIN: 1323 currencyPrecision = currencies.smallestCoinPrecision(currencyNum); 1324 break; 1325 default: 1326 currencyPrecision = 1.0; 1327 } 1328 rate.setNum( currencyRate * currencyPrecision ); 1329 // referenceSymbol = QString::fromUtf8( reference == DOLLAR_NY_FRB ? dollarSymbol: euroSymbol ); 1330 referenceSymbol = QString::fromUtf8( euroSymbol ); 1331 RateLabel->setText 1332 ( '1' + referenceSymbol + " = " + rate + ' ' + currencySymbol ); 1333 } 1334 else RateLabel->setText( "" ); 1335 } 1336 1337 // Display the memory Plus and Minus buttons 1338 void KEuroCalc::displayMemoryButtons() 1339 { 1340 bool recallEnabled = memorySet, 1341 sumsEnabled = memorySet && (isSimpleValue == isSimpleMemory); 1342 1343 MRecallButton->setEnabled( recallEnabled ); 1344 MMinusButton->setEnabled( sumsEnabled ); 1345 MPlusButton->setEnabled( sumsEnabled ); 1346 } 1347 1348 // Normalize the display of a number 1349 void KEuroCalc::normalize( QString &numberDisplay ) 1350 { 1351 int dotPos = numberDisplay.indexOf('.'), 1352 unitPos = (dotPos == -1? numberDisplay.length(): dotPos) - 3; 1353 1354 if ( dotPos != -1 ) 1355 numberDisplay.replace( dotPos, 1356 1, 1357 QLocale().decimalPoint() ); 1358 1359 while (unitPos > 0) 1360 { 1361 numberDisplay.insert( unitPos, 1362 " "); 1363 unitPos -= 3; 1364 } 1365 } 1366 1367 #include "moc_keurocalc.cpp"