diff --git a/bitbutton.h b/bitbutton.h index 594279f..1c6e216 100644 --- a/bitbutton.h +++ b/bitbutton.h @@ -1,42 +1,42 @@ /* Copyright (C) 2012 - 2013 Evan Teran evan.teran@gmail.com Copyright (C) 2006 Michel Marti mma@objectxp.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef BITBUTTON_H_20120104_ #define BITBUTTON_H_20120104_ #include class BitButton : public QAbstractButton { Q_OBJECT public: - explicit BitButton(QWidget *parent = 0); + explicit BitButton(QWidget *parent = nullptr); bool isOn() const; void setOn(bool value); protected: void paintEvent(QPaintEvent *event) override; private: bool on_; }; #endif diff --git a/kcalc.cpp b/kcalc.cpp index 368c421..0f11b5c 100644 --- a/kcalc.cpp +++ b/kcalc.cpp @@ -1,2335 +1,2335 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com Copyright (C) 2006 Michel Marti mma@objectxp.com Copyright (C) 1996 - 2000 Bernd Johannes Wuebben wuebben@kde.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "kcalc_version.h" #include "kcalc.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kcalc_bitset.h" #include "kcalc_const_menu.h" #include "kcalc_settings.h" #include "kcalc_statusbar.h" #include "kcalcdisplay.h" namespace { const char description[] = I18N_NOOP("KDE Calculator"); const int maxprecision = 1000; } //------------------------------------------------------------------------------ // Name: KCalculator // Desc: constructor //------------------------------------------------------------------------------ KCalculator::KCalculator(QWidget *parent) : KXmlGuiWindow(parent), shift_mode_(false), hyp_mode_(false), memory_num_(0.0), - constants_menu_(0), - constants_(0), + constants_menu_(nullptr), + constants_(nullptr), core() { // central widget to contain all the elements QWidget *const central = new QWidget(this); central->setLayoutDirection(Qt::LeftToRight); setCentralWidget(central); KAcceleratorManager::setNoAccel(central); // load science constants_ from xml-file KCalcConstMenu::init_consts(); // setup interface (order is critical) setupUi(central); setupMainActions(); setStatusBar(new KCalcStatusBar(this)); createGUI(); setupKeys(); toolBar()->hide(); // hide by default // create button groups base_choose_group_ = new QButtonGroup(this); base_choose_group_->setExclusive(true); base_choose_group_->addButton(hexRadio, HexMode); base_choose_group_->addButton(decRadio, DecMode); base_choose_group_->addButton(octRadio, OctMode); base_choose_group_->addButton(binRadio, BinMode); connect(base_choose_group_, static_cast(&QButtonGroup::buttonClicked), this, &KCalculator::slotBaseSelected); angle_choose_group_ = new QButtonGroup(this); angle_choose_group_->setExclusive(true); angle_choose_group_->addButton(degRadio, DegMode); angle_choose_group_->addButton(radRadio, RadMode); angle_choose_group_->addButton(gradRadio, GradMode); connect(angle_choose_group_, static_cast(&QButtonGroup::buttonClicked), this, &KCalculator::slotAngleSelected); // additional menu setup constants_menu_ = createConstantsMenu(); menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_); // misc setup setColors(); setFonts(); // Show the result in the app's caption in taskbar (wishlist - bug #52858) if (KCalcSettings::captionResult() == true) { connect(calc_display, &KCalcDisplay::changedText, this, &KCalculator::setWindowTitle); } calc_display->changeSettings(); setPrecision(); updateGeometry(); layout()->setSizeConstraint(QLayout::SetFixedSize); updateDisplay(UPDATE_FROM_CORE); // misc settings KCalcSettings::EnumCalculatorMode::type calculatorMode = KCalcSettings::calculatorMode(); switch (calculatorMode) { case KCalcSettings::EnumCalculatorMode::science: action_mode_science_->setChecked(true); break; case KCalcSettings::EnumCalculatorMode::statistics: action_mode_statistic_->setChecked(true); break; case KCalcSettings::EnumCalculatorMode::numeral: action_mode_numeral_->setChecked(true); break; case KCalcSettings::EnumCalculatorMode::simple: default: action_mode_simple_->setChecked(true); } setAngle(); setBase(); calc_display->setFocus(); } //------------------------------------------------------------------------------ // Name: ~KCalculator // Desc: deconstructor //------------------------------------------------------------------------------ KCalculator::~KCalculator() { KCalcSettings::self()->save(); } //------------------------------------------------------------------------------ // Name: setupMainActions // Desc: connects all of the basic actions //------------------------------------------------------------------------------ void KCalculator::setupMainActions() { // file menu KStandardAction::quit(this, SLOT(close()), actionCollection()); // edit menu KStandardAction::undo(calc_display, SLOT(slotHistoryBack()), actionCollection()); KStandardAction::redo(calc_display, SLOT(slotHistoryForward()), actionCollection()); KStandardAction::cut(calc_display, SLOT(slotCut()), actionCollection()); KStandardAction::copy(calc_display, SLOT(slotCopy()), actionCollection()); KStandardAction::paste(calc_display, SLOT(slotPaste()), actionCollection()); // mode menu QActionGroup *modeGroup = new QActionGroup(this); action_mode_simple_ = actionCollection()->add(QLatin1String("mode_simple")); action_mode_simple_->setActionGroup(modeGroup); action_mode_simple_->setText(i18n("Simple Mode")); connect(action_mode_simple_, &KToggleAction::toggled, this, &KCalculator::slotSetSimpleMode); action_mode_science_ = actionCollection()->add(QLatin1String("mode_science")); action_mode_science_->setActionGroup(modeGroup); action_mode_science_->setText(i18n("Science Mode")); connect(action_mode_science_, &KToggleAction::toggled, this, &KCalculator::slotSetScienceMode); action_mode_statistic_ = actionCollection()->add(QLatin1String("mode_statistics")); action_mode_statistic_->setActionGroup(modeGroup); action_mode_statistic_->setText(i18n("Statistic Mode")); connect(action_mode_statistic_, &KToggleAction::toggled, this, &KCalculator::slotSetStatisticMode); action_mode_numeral_ = actionCollection()->add(QLatin1String("mode_numeral")); action_mode_numeral_->setActionGroup(modeGroup); action_mode_numeral_->setText(i18n("Numeral System Mode")); connect(action_mode_numeral_, &KToggleAction::toggled, this, &KCalculator::slotSetNumeralMode); // settings menu action_constants_show_ = actionCollection()->add(QLatin1String("show_constants")); action_constants_show_->setText(i18n("Constants &Buttons")); action_constants_show_->setChecked(true); connect(action_constants_show_, &KToggleAction::toggled, this, &KCalculator::slotConstantsShow); action_bitset_show_ = actionCollection()->add(QLatin1String("show_bitset")); action_bitset_show_->setText(i18n("Show B&it Edit")); action_bitset_show_->setChecked(true); connect(action_bitset_show_, &KToggleAction::toggled, this, &KCalculator::slotBitsetshow); KStandardAction::preferences(this, SLOT(showSettings()), actionCollection()); KStandardAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), actionCollection()); } //------------------------------------------------------------------------------ // Name: createConstantsMenu // Desc: creates and returns a pointer to the constant menu //------------------------------------------------------------------------------ KCalcConstMenu *KCalculator::createConstantsMenu() { KCalcConstMenu *const menu = new KCalcConstMenu(i18n("&Constants"), this); connect(menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotConstantToDisplay); return menu; } //------------------------------------------------------------------------------ // Name: statusBar // Desc: returns a pointer to the status bar //------------------------------------------------------------------------------ KCalcStatusBar *KCalculator::statusBar() { return static_cast(KXmlGuiWindow::statusBar()); } //------------------------------------------------------------------------------ // Name: setupNumberKeys // Desc: sets up number keys and related shortcuts //------------------------------------------------------------------------------ void KCalculator::setupNumberKeys() { num_button_group_ = new QButtonGroup(this); connect(num_button_group_, static_cast(&QButtonGroup::buttonClicked), this, &KCalculator::slotNumberclicked); num_button_group_->addButton(pb0, 0); num_button_group_->addButton(pb1, 1); num_button_group_->addButton(pb2, 2); num_button_group_->addButton(pb3, 3); num_button_group_->addButton(pb4, 4); num_button_group_->addButton(pb5, 5); num_button_group_->addButton(pb6, 6); num_button_group_->addButton(pb7, 7); num_button_group_->addButton(pb8, 8); num_button_group_->addButton(pb9, 9); num_button_group_->addButton(pbA, 0xA); num_button_group_->addButton(pbB, 0xB); num_button_group_->addButton(pbC, 0xC); num_button_group_->addButton(pbD, 0xD); num_button_group_->addButton(pbE, 0xE); num_button_group_->addButton(pbF, 0xF); connect(this, &KCalculator::switchShowAccels, pb0, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pb1, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pb2, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pb3, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pb4, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pb5, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pb6, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pb7, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pb8, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pb9, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pbA, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pbB, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pbC, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pbD, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pbE, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchShowAccels, pbF, &KCalcButton::slotSetAccelDisplayMode); } //------------------------------------------------------------------------------ // Name: setupRightKeypad // Desc: sets up right keypad keys and related shortcuts //------------------------------------------------------------------------------ void KCalculator::setupRightKeypad() { connect(pbShift, &KCalcButton::toggled, this, &KCalculator::slotShifttoggled); connect(this, &KCalculator::switchShowAccels, pbShift, &KCalcButton::slotSetAccelDisplayMode); pbBackspace->setShortcut(QKeySequence(Qt::Key_Backspace)); new QShortcut(Qt::Key_PageUp, pbBackspace, SLOT(animateClick())); connect(pbBackspace, &KCalcButton::clicked, this, &KCalculator::slotBackspaceclicked); connect(this, &KCalculator::switchShowAccels, pbBackspace, &KCalcButton::slotSetAccelDisplayMode); pbClear->setShortcut(QKeySequence(Qt::Key_Escape)); new QShortcut(Qt::Key_PageUp, pbClear, SLOT(animateClick())); connect(pbClear, &KCalcButton::clicked, this, &KCalculator::slotClearclicked); connect(this, &KCalculator::switchShowAccels, pbClear, &KCalcButton::slotSetAccelDisplayMode); pbAllClear->setShortcut(QKeySequence(Qt::Key_Delete)); new QShortcut(Qt::Key_PageDown, pbAllClear, SLOT(animateClick())); connect(pbAllClear, &KCalcButton::clicked, this, &KCalculator::slotAllClearclicked); connect(this, &KCalculator::switchShowAccels, pbAllClear, &KCalcButton::slotSetAccelDisplayMode); pbParenOpen->setShortcut(QKeySequence(Qt::Key_ParenLeft)); connect(pbParenOpen, &KCalcButton::clicked, this, &KCalculator::slotParenOpenclicked); connect(this, &KCalculator::switchShowAccels, pbParenOpen, &KCalcButton::slotSetAccelDisplayMode); pbParenClose->setShortcut(QKeySequence(Qt::Key_ParenRight)); connect(pbParenClose, &KCalcButton::clicked, this, &KCalculator::slotParenCloseclicked); connect(this, &KCalculator::switchShowAccels, pbParenClose, &KCalcButton::slotSetAccelDisplayMode); pbMemRecall->setDisabled(true); // nothing in memory at start connect(pbMemRecall, &KCalcButton::clicked, this, &KCalculator::slotMemRecallclicked); connect(this, &KCalculator::switchShowAccels, pbMemRecall, &KCalcButton::slotSetAccelDisplayMode); connect(pbMemClear, &KCalcButton::clicked, this, &KCalculator::slotMemClearclicked); connect(this, &KCalculator::switchShowAccels, pbMemClear, &KCalcButton::slotSetAccelDisplayMode); pbMemPlusMinus->addMode(ModeNormal, i18nc("Add display to memory", "M+"), i18n("Add display to memory")); pbMemPlusMinus->addMode(ModeShift, i18nc("Subtract from memory", "M\xe2\x88\x92"), i18n("Subtract from memory")); connect(pbMemPlusMinus, &KCalcButton::clicked, this, &KCalculator::slotMemPlusMinusclicked); connect(this, &KCalculator::switchShowAccels, pbMemPlusMinus, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbMemPlusMinus, &KCalcButton::slotSetMode); connect(pbMemStore, &KCalcButton::clicked, this, &KCalculator::slotMemStoreclicked); connect(this, &KCalculator::switchShowAccels, pbMemStore, &KCalcButton::slotSetAccelDisplayMode); pbPercent->setShortcut(QKeySequence(Qt::Key_Percent)); connect(pbPercent, &KCalcButton::clicked, this, &KCalculator::slotPercentclicked); connect(this, &KCalculator::switchShowAccels, pbPercent, &KCalcButton::slotSetAccelDisplayMode); pbPlusMinus->setShortcut(QKeySequence(Qt::Key_Backslash)); connect(pbPlusMinus, &KCalcButton::clicked, this, &KCalculator::slotPlusMinusclicked); connect(this, &KCalculator::switchShowAccels, pbPlusMinus, &KCalcButton::slotSetAccelDisplayMode); } //------------------------------------------------------------------------------ // Name: setupNumericKeypad // Desc: sets up numeric keys and related shortcuts //------------------------------------------------------------------------------ void KCalculator::setupNumericKeypad() { pbCube->addMode(ModeNormal, i18nc("Third power", "x3"), i18n("Third power")); pbCube->addMode(ModeShift, QLatin1String("3√x"), i18n("Cube root")); connect(pbCube, &KCalcButton::clicked, this, &KCalculator::slotCubeclicked); connect(this, &KCalculator::switchShowAccels, pbCube, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbCube, &KCalcButton::slotSetMode); pbDivision->setShortcut(QKeySequence(Qt::Key_Slash)); new QShortcut(Qt::Key_division, pbDivision, SLOT(animateClick())); connect(pbDivision, &KCalcButton::clicked, this, &KCalculator::slotDivisionclicked); connect(this, &KCalculator::switchShowAccels, pbDivision, &KCalcButton::slotSetAccelDisplayMode); pbMultiplication->setShortcut(QKeySequence(Qt::Key_Asterisk)); new QShortcut(Qt::Key_X, pbMultiplication, SLOT(animateClick())); new QShortcut(Qt::Key_multiply, pbMultiplication, SLOT(animateClick())); connect(pbMultiplication, &KCalcButton::clicked, this, &KCalculator::slotMultiplicationclicked); connect(this, &KCalculator::switchShowAccels, pbMultiplication, &KCalcButton::slotSetAccelDisplayMode); pbMinus->setShortcut(QKeySequence(Qt::Key_Minus)); connect(pbMinus, &KCalcButton::clicked, this, &KCalculator::slotMinusclicked); connect(this, &KCalculator::switchShowAccels, pbMinus, &KCalcButton::slotSetAccelDisplayMode); pbPlus->setShortcut(QKeySequence(Qt::Key_Plus)); connect(pbPlus, &KCalcButton::clicked, this, &KCalculator::slotPlusclicked); connect(this, &KCalculator::switchShowAccels, pbPlus, &KCalcButton::slotSetAccelDisplayMode); // set decimal separator from locale pbPeriod->setText(QString(QLocale().decimalPoint())); pbPeriod->setShortcut(QString(QLocale().decimalPoint())); // add shortcut for the other decimal separator (point or comma) if (QLocale().decimalPoint() == QLatin1Char('.')) { new QShortcut(Qt::Key_Comma, pbPeriod, SLOT(animateClick())); } else if (QLocale().decimalPoint() == QLatin1Char(',')) { new QShortcut(Qt::Key_Period, pbPeriod, SLOT(animateClick())); } connect(pbPeriod, &KCalcButton::clicked, this, &KCalculator::slotPeriodclicked); connect(this, &KCalculator::switchShowAccels, pbPeriod, &KCalcButton::slotSetAccelDisplayMode); pbEqual->setShortcut(QKeySequence(Qt::Key_Enter)); new QShortcut(Qt::Key_Equal, pbEqual, SLOT(animateClick())); new QShortcut(Qt::Key_Return, pbEqual, SLOT(animateClick())); connect(pbEqual, &KCalcButton::clicked, this, &KCalculator::slotEqualclicked); connect(this, &KCalculator::switchShowAccels, pbEqual, &KCalcButton::slotSetAccelDisplayMode); } //------------------------------------------------------------------------------ // Name: setupLogicKeys // Desc: sets up logic keys and related shortcuts //------------------------------------------------------------------------------ void KCalculator::setupLogicKeys() { logic_buttons_.append(pbAND); logic_buttons_.append(pbOR); logic_buttons_.append(pbXOR); logic_buttons_.append(pbLsh); logic_buttons_.append(pbRsh); logic_buttons_.append(pbCmp); pbAND->setShortcut(QKeySequence(Qt::Key_Ampersand)); connect(this, &KCalculator::switchShowAccels, pbAND, &KCalcButton::slotSetAccelDisplayMode); connect(pbAND, &KCalcButton::clicked, this, &KCalculator::slotANDclicked); pbOR->setShortcut(QKeySequence(Qt::Key_Bar)); connect(this, &KCalculator::switchShowAccels, pbOR, &KCalcButton::slotSetAccelDisplayMode); connect(pbOR, &KCalcButton::clicked, this, &KCalculator::slotORclicked); connect(this, &KCalculator::switchShowAccels, pbXOR, &KCalcButton::slotSetAccelDisplayMode); connect(pbXOR, &KCalcButton::clicked, this, &KCalculator::slotXORclicked); pbLsh->setShortcut(QKeySequence(Qt::Key_Less)); connect(this, &KCalculator::switchShowAccels, pbLsh, &KCalcButton::slotSetAccelDisplayMode); connect(pbLsh, &KCalcButton::clicked, this, &KCalculator::slotLeftShiftclicked); pbRsh->setShortcut(QKeySequence(Qt::Key_Greater)); connect(this, &KCalculator::switchShowAccels, pbRsh, &KCalcButton::slotSetAccelDisplayMode); connect(pbRsh, &KCalcButton::clicked, this, &KCalculator::slotRightShiftclicked); pbCmp->setShortcut(QKeySequence(Qt::Key_AsciiTilde)); connect(this, &KCalculator::switchShowAccels, pbCmp, &KCalcButton::slotSetAccelDisplayMode); connect(pbCmp, &KCalcButton::clicked, this, &KCalculator::slotNegateclicked); } //------------------------------------------------------------------------------ // Name: setupLogicKeys // Desc: sets up scientific keys and related shortcuts //------------------------------------------------------------------------------ void KCalculator::setupScientificKeys() { scientific_buttons_.append(pbHyp); scientific_buttons_.append(pbSin); scientific_buttons_.append(pbCos); scientific_buttons_.append(pbTan); scientific_buttons_.append(pbLog); scientific_buttons_.append(pbLn); connect(this, &KCalculator::switchShowAccels, pbHyp, &KCalcButton::slotSetAccelDisplayMode); connect(pbHyp, &KCalcButton::toggled, this, &KCalculator::slotHyptoggled); pbSin->addMode(ModeNormal, i18nc("Sine", "Sin"), i18n("Sine")); pbSin->addMode(ModeShift, i18nc("Arc sine", "Asin"), i18n("Arc sine")); pbSin->addMode(ModeHyperbolic, i18nc("Hyperbolic sine", "Sinh"), i18n("Hyperbolic sine")); pbSin->addMode(ButtonModeFlags(ModeShift | ModeHyperbolic), i18nc("Inverse hyperbolic sine", "Asinh"), i18n("Inverse hyperbolic sine")); connect(this, &KCalculator::switchShowAccels, pbSin, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbSin, &KCalcButton::slotSetMode); connect(pbSin, &KCalcButton::clicked, this, &KCalculator::slotSinclicked); pbCos->addMode(ModeNormal, i18nc("Cosine", "Cos"), i18n("Cosine")); pbCos->addMode(ModeShift, i18nc("Arc cosine", "Acos"), i18n("Arc cosine")); pbCos->addMode(ModeHyperbolic, i18nc("Hyperbolic cosine", "Cosh"), i18n("Hyperbolic cosine")); pbCos->addMode(ButtonModeFlags(ModeShift | ModeHyperbolic), i18nc("Inverse hyperbolic cosine", "Acosh"), i18n("Inverse hyperbolic cosine")); connect(this, &KCalculator::switchShowAccels, pbCos, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbCos, &KCalcButton::slotSetMode); connect(pbCos, &KCalcButton::clicked, this, &KCalculator::slotCosclicked); pbTan->addMode(ModeNormal, i18nc("Tangent", "Tan"), i18n("Tangent")); pbTan->addMode(ModeShift, i18nc("Arc tangent", "Atan"), i18n("Arc tangent")); pbTan->addMode(ModeHyperbolic, i18nc("Hyperbolic tangent", "Tanh"), i18n("Hyperbolic tangent")); pbTan->addMode(ButtonModeFlags(ModeShift | ModeHyperbolic), i18nc("Inverse hyperbolic tangent", "Atanh"), i18n("Inverse hyperbolic tangent")); connect(this, &KCalculator::switchShowAccels, pbTan, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbTan, &KCalcButton::slotSetMode); connect(pbTan, &KCalcButton::clicked, this, &KCalculator::slotTanclicked); pbLog->addMode(ModeNormal, i18nc("Logarithm to base 10", "Log"), i18n("Logarithm to base 10")); pbLog->addMode(ModeShift, i18nc("10 to the power of x", "10x"), i18n("10 to the power of x")); connect(this, &KCalculator::switchShowAccels, pbLog, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbLog, &KCalcButton::slotSetMode); connect(pbLog, &KCalcButton::clicked, this, &KCalculator::slotLogclicked); pbLn->addMode(ModeNormal, i18nc("Natural log", "Ln"), i18n("Natural log")); pbLn->addMode(ModeShift, i18nc("Exponential function", "ex"), i18n("Exponential function")); connect(this, &KCalculator::switchShowAccels, pbLn, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbLn, &KCalcButton::slotSetMode); connect(pbLn, &KCalcButton::clicked, this, &KCalculator::slotLnclicked); } //------------------------------------------------------------------------------ // Name: setupStatisticKeys // Desc: sets up statistical keys and related shortcuts //------------------------------------------------------------------------------ void KCalculator::setupStatisticKeys() { stat_buttons_.append(pbNData); stat_buttons_.append(pbMean); stat_buttons_.append(pbSd); stat_buttons_.append(pbMed); stat_buttons_.append(pbDat); stat_buttons_.append(pbCSt); pbNData->addMode(ModeNormal, i18nc("Number of data entered", "N"), i18n("Number of data entered")); pbNData->addMode(ModeShift, QString::fromUtf8("\xce\xa3") + QLatin1Char('x'), i18n("Sum of all data items")); connect(this, &KCalculator::switchShowAccels, pbNData, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbNData, &KCalcButton::slotSetMode); connect(pbNData, &KCalcButton::clicked, this, &KCalculator::slotStatNumclicked); pbMean->addMode(ModeNormal, i18nc("Mean", "Mea"), i18n("Mean")); pbMean->addMode(ModeShift, QString::fromUtf8("\xce\xa3") + QLatin1String("x2"), i18n("Sum of all data items squared")); connect(this, &KCalculator::switchShowAccels, pbMean, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbMean, &KCalcButton::slotSetMode); connect(pbMean, &KCalcButton::clicked, this, &KCalculator::slotStatMeanclicked); pbSd->addMode(ModeNormal, QString::fromUtf8("\xcf\x83") + QLatin1String("N"), i18n("Standard deviation")); pbSd->addMode(ModeShift, QString::fromUtf8("\xcf\x83") + QLatin1String("N-1"), i18n("Sample standard deviation")); connect(this, &KCalculator::switchShowAccels, pbSd, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbSd, &KCalcButton::slotSetMode); connect(pbSd, &KCalcButton::clicked, this, &KCalculator::slotStatStdDevclicked); connect(this, &KCalculator::switchShowAccels, pbMed, &KCalcButton::slotSetAccelDisplayMode); connect(pbMed, &KCalcButton::clicked, this, &KCalculator::slotStatMedianclicked); pbDat->addMode(ModeNormal, i18nc("Enter data", "Dat"), i18n("Enter data")); pbDat->addMode(ModeShift, i18nc("Delete last data item", "CDat"), i18n("Delete last data item")); connect(this, &KCalculator::switchShowAccels, pbDat, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbDat, &KCalcButton::slotSetMode); connect(pbDat, &KCalcButton::clicked, this, &KCalculator::slotStatDataInputclicked); connect(this, &KCalculator::switchShowAccels, pbCSt, &KCalcButton::slotSetAccelDisplayMode); connect(pbCSt, &KCalcButton::clicked, this, &KCalculator::slotStatClearDataclicked); } //------------------------------------------------------------------------------ // Name: setupConstantsKeys // Desc: sets up constants keys and related shortcuts //------------------------------------------------------------------------------ void KCalculator::setupConstantsKeys() { const_buttons_.append(pbC1); const_buttons_.append(pbC2); const_buttons_.append(pbC3); const_buttons_.append(pbC4); const_buttons_.append(pbC5); const_buttons_.append(pbC6); pbC1->setButtonNumber(0); connect(this, &KCalculator::switchShowAccels, pbC1, &KCalcConstButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbC1, &KCalcConstButton::slotSetMode); connect(pbC1, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked); pbC2->setButtonNumber(1); connect(this, &KCalculator::switchShowAccels, pbC2, &KCalcConstButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbC2, &KCalcConstButton::slotSetMode); connect(pbC2, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked); pbC3->setButtonNumber(2); connect(this, &KCalculator::switchShowAccels, pbC3, &KCalcConstButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbC3, &KCalcConstButton::slotSetMode); connect(pbC3, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked); pbC4->setButtonNumber(3); connect(this, &KCalculator::switchShowAccels, pbC4, &KCalcConstButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbC4, &KCalcConstButton::slotSetMode); connect(pbC4, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked); pbC5->setButtonNumber(4); connect(this, &KCalculator::switchShowAccels, pbC5, &KCalcConstButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbC5, &KCalcConstButton::slotSetMode); connect(pbC5, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked); pbC6->setButtonNumber(5); connect(this, &KCalculator::switchShowAccels, pbC6, &KCalcConstButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbC6, &KCalcConstButton::slotSetMode); connect(pbC6, &KCalcConstButton::clicked, this, &KCalculator::slotConstclicked); changeButtonNames(); } //------------------------------------------------------------------------------ // Name: setupMiscKeys // Desc: sets up misc keys and related shortcuts //------------------------------------------------------------------------------ void KCalculator::setupMiscKeys() { pbMod->addMode(ModeNormal, i18nc("Modulo", "Mod"), i18n("Modulo")); pbMod->addMode(ModeShift, i18nc("Integer division", "IntDiv"), i18n("Integer division")); connect(this, &KCalculator::switchMode, pbMod, &KCalcButton::slotSetMode); connect(this, &KCalculator::switchShowAccels, pbMod, &KCalcButton::slotSetAccelDisplayMode); pbMod->setShortcut(QKeySequence(Qt::Key_Colon)); connect(pbMod, &KCalcButton::clicked, this, &KCalculator::slotModclicked); pbReci->addMode(ModeNormal, i18nc("Reciprocal", "1/x"), i18n("Reciprocal")); pbReci->addMode(ModeShift, i18nc("n Choose m", "nCm"), i18n("n Choose m")); connect(this, &KCalculator::switchMode, pbReci, &KCalcButton::slotSetMode); connect(this, &KCalculator::switchShowAccels, pbReci, &KCalcButton::slotSetAccelDisplayMode); connect(pbReci, &KCalcButton::clicked, this, &KCalculator::slotReciclicked); pbFactorial->addMode(ModeNormal, i18nc("Factorial", "x!"), i18n("Factorial")); pbFactorial->addMode(ModeShift, QLatin1String("Γ"), i18n("Gamma")); pbFactorial->setShortcut(QKeySequence(Qt::Key_Exclam)); connect(this, &KCalculator::switchShowAccels, pbFactorial, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbFactorial, &KCalcButton::slotSetMode); connect(pbFactorial, &KCalcButton::clicked, this, &KCalculator::slotFactorialclicked); pbSquare->addMode(ModeNormal, i18nc("Square", "x2"), i18n("Square")); pbSquare->addMode(ModeShift, QLatin1String("√x"), i18n("Square root")); pbSquare->setShortcut(QKeySequence(Qt::Key_BracketLeft)); new QShortcut(Qt::Key_twosuperior, pbSquare, SLOT(animateClick())); connect(this, &KCalculator::switchShowAccels, pbSquare, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbSquare, &KCalcButton::slotSetMode); connect(pbSquare, &KCalcButton::clicked, this, &KCalculator::slotSquareclicked); pbPower->addMode(ModeNormal, i18nc("x to the power of y", "xy"), i18n("x to the power of y")); pbPower->addMode(ModeShift, i18nc("x to the power of 1/y", "x1/y"), i18n("x to the power of 1/y")); connect(this, &KCalculator::switchShowAccels, pbPower, &KCalcButton::slotSetAccelDisplayMode); connect(this, &KCalculator::switchMode, pbPower, &KCalcButton::slotSetMode); pbPower->setShortcut(QKeySequence(Qt::Key_AsciiCircum)); connect(pbPower, &KCalcButton::clicked, this, &KCalculator::slotPowerclicked); pbEE->addMode(ModeNormal, QLatin1String("x" "\xb7" "10y"), i18n("Exponent")); connect(this, &KCalculator::switchShowAccels, pbEE, &KCalcButton::slotSetAccelDisplayMode); connect(pbEE, &KCalcButton::clicked, this, &KCalculator::slotEEclicked); } //------------------------------------------------------------------------------ // Name: createConstantsMenu // Desc: additional setup for button keys // NOTE: all alphanumeric shorts set in ui file //------------------------------------------------------------------------------ void KCalculator::setupKeys() { setupNumberKeys(); setupRightKeypad(); setupNumericKeypad(); setupLogicKeys(); setupScientificKeys(); setupStatisticKeys(); setupConstantsKeys(); setupMiscKeys(); // other button lists function_button_list_.append(pbHyp); function_button_list_.append(pbShift); function_button_list_.append(pbEE); function_button_list_.append(pbSin); function_button_list_.append(pbPlusMinus); function_button_list_.append(pbCos); function_button_list_.append(pbReci); function_button_list_.append(pbTan); function_button_list_.append(pbFactorial); function_button_list_.append(pbLog); function_button_list_.append(pbSquare); function_button_list_.append(pbLn); function_button_list_.append(pbPower); function_button_list_.append(pbCube); mem_button_list_.append(pbMemRecall); mem_button_list_.append(pbMemPlusMinus); mem_button_list_.append(pbMemStore); mem_button_list_.append(pbMemClear); mem_button_list_.append(pbClear); mem_button_list_.append(pbAllClear); operation_button_list_.append(pbMultiplication); operation_button_list_.append(pbParenOpen); operation_button_list_.append(pbParenClose); operation_button_list_.append(pbAND); operation_button_list_.append(pbDivision); operation_button_list_.append(pbOR); operation_button_list_.append(pbXOR); operation_button_list_.append(pbPlus); operation_button_list_.append(pbMinus); operation_button_list_.append(pbLsh); operation_button_list_.append(pbRsh); operation_button_list_.append(pbPeriod); operation_button_list_.append(pbEqual); operation_button_list_.append(pbPercent); operation_button_list_.append(pbCmp); operation_button_list_.append(pbMod); } //------------------------------------------------------------------------------ // Name: updateGeometry // Desc: makes all the buttons have reasonable sizes //------------------------------------------------------------------------------ void KCalculator::updateGeometry() { const QSize em = pbAND->fontMetrics().size(0, QLatin1String("M")); int margin = QApplication::style()->pixelMetric(QStyle::PM_ButtonMargin, 0, 0); margin = qMax(qMin(margin / 2, 3), 3); // left pad foreach(QObject *obj, leftPad->children()) { if (KCalcButton *const button = qobject_cast(obj)) { button->setFixedWidth(em.width() * 4 + margin * 2); button->installEventFilter(this); } } // right pad foreach(QObject *obj, rightPad->children()) { KCalcButton *const button = qobject_cast(obj); // let Shift expand freely if (button && button != pbShift) { button->setFixedWidth(em.width() * 3 + margin * 2); button->installEventFilter(this); } } // numeric pad foreach(QObject *obj, numericPad->children()) { if (KCalcButton *const button = qobject_cast(obj)) { // let pb0 expand freely if (button != pb0) { button->setFixedWidth(em.width() * 3 + margin * 2); } button->installEventFilter(this); } } } //------------------------------------------------------------------------------ // Name: slotConstantToDisplay // Desc: inserts a constant //------------------------------------------------------------------------------ void KCalculator::slotConstantToDisplay(const science_constant &const_chosen) { QString val = const_chosen.value; val.replace(QLatin1Char('.'), KNumber::decimalSeparator()); calc_display->setAmount(KNumber(val)); - updateDisplay(0); + updateDisplay({}); } //------------------------------------------------------------------------------ // Name: slotBaseSelected // Desc: changes the selected numeric base //------------------------------------------------------------------------------ void KCalculator::slotBaseSelected(int base) { int current_base; // set display & statusbar (if item exist in statusbar) statusBar()->setBase(base); switch (base) { case BinMode: current_base = calc_display->setBase(NumBase(2)); calc_display->setStatusText(BaseField, QLatin1String("Bin")); break; case OctMode: current_base = calc_display->setBase(NumBase(8)); calc_display->setStatusText(BaseField, QLatin1String("Oct")); break; case DecMode: current_base = calc_display->setBase(NumBase(10)); calc_display->setStatusText(BaseField, QLatin1String("Dec")); break; case HexMode: current_base = calc_display->setBase(NumBase(16)); calc_display->setStatusText(BaseField, QLatin1String("Hex")); break; default: calc_display->setStatusText(BaseField, QLatin1String("Error")); return; } // Enable the buttons available in this base for (int i = 0; i < current_base; ++i) { (num_button_group_->buttons()[i])->setEnabled(true); } // Disable the buttons not available in this base for (int i = current_base; i < 16; ++i) { (num_button_group_->buttons()[i])->setEnabled(false); } // Only enable the decimal point in decimal pbPeriod->setEnabled(current_base == NB_DECIMAL); // Only enable the x*10^y button in decimal pbEE->setEnabled(current_base == NB_DECIMAL); // Disable buttons that make only sense with floating point numbers if (current_base != NB_DECIMAL) { foreach(QAbstractButton *btn, scientific_buttons_) { btn->setEnabled(false); } } else { foreach(QAbstractButton *btn, scientific_buttons_) { btn->setEnabled(true); } } KCalcSettings::setBaseMode(base); } //------------------------------------------------------------------------------ // Name: keyPressEvent // Desc: handles keypress events //------------------------------------------------------------------------------ void KCalculator::keyPressEvent(QKeyEvent *e) { // Fix for bug #314586 // Basically, on some keyboards such as French, even though the decimal separator // is "," the numeric keypad has a "." key. So we fake it so people can more seemlessly // enter numbers using the keypad if(KNumber::decimalSeparator() != QLatin1String(".")) { if(e->key() == Qt::Key_Period && e->modifiers() & Qt::KeypadModifier) { pbPeriod->animateClick(); } } if (((e->modifiers() & Qt::NoModifier) == 0) || (e->modifiers() & Qt::ShiftModifier)) { switch (e->key()) { case Qt::Key_Backspace: calc_display->deleteLastDigit(); break; } } if (e->key() == Qt::Key_Control) { emit switchShowAccels(true); } } //------------------------------------------------------------------------------ // Name: keyReleaseEvent // Desc: handles keyrelease events //------------------------------------------------------------------------------ void KCalculator::keyReleaseEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Control) { emit switchShowAccels(false); } } //------------------------------------------------------------------------------ // Name: slotAngleSelected // Desc: changes the selected angle system //------------------------------------------------------------------------------ void KCalculator::slotAngleSelected(int mode) { angle_mode_ = mode; statusBar()->setAngleMode(KCalcStatusBar::AngleMode(mode)); switch (mode) { case DegMode: calc_display->setStatusText(AngleField, QLatin1String("Deg")); break; case RadMode: calc_display->setStatusText(AngleField, QLatin1String("Rad")); break; case GradMode: calc_display->setStatusText(AngleField, QLatin1String("Gra")); break; default: // we shouldn't ever end up here angle_mode_ = RadMode; } KCalcSettings::setAngleMode(angle_mode_); } //------------------------------------------------------------------------------ // Name: slotEEclicked // Desc: starts the entering of numers using scientific notation //------------------------------------------------------------------------------ void KCalculator::slotEEclicked() { calc_display->newCharacter(QLatin1Char('e')); } //------------------------------------------------------------------------------ // Name: slotShifttoggled // Desc: updates the shift state for alternate button functionality //------------------------------------------------------------------------------ void KCalculator::slotShifttoggled(bool flag) { shift_mode_ = flag; emit switchMode(ModeShift, flag); statusBar()->setShiftIndicator(shift_mode_); if (shift_mode_) { calc_display->setStatusText(ShiftField, i18n("Shift")); } else { calc_display->setStatusText(ShiftField, QString()); } } //------------------------------------------------------------------------------ // Name: slotHyptoggled // Desc: updates the Hyp state for alternate trig button functionality //------------------------------------------------------------------------------ void KCalculator::slotHyptoggled(bool flag) { // toggle between hyperbolic and standart trig functions hyp_mode_ = flag; emit switchMode(ModeHyperbolic, flag); } //------------------------------------------------------------------------------ // Name: slotMemRecallclicked // Desc: recalls a value from memory //------------------------------------------------------------------------------ void KCalculator::slotMemRecallclicked() { // temp. work-around calc_display->sendEvent(KCalcDisplay::EventReset); calc_display->setAmount(memory_num_); - updateDisplay(0); + updateDisplay({}); } //------------------------------------------------------------------------------ // Name: slotMemStoreclicked // Desc: stores a value into memory //------------------------------------------------------------------------------ void KCalculator::slotMemStoreclicked() { EnterEqual(); memory_num_ = calc_display->getAmount(); calc_display->setStatusText(MemField, QLatin1String("M")); statusBar()->setMemoryIndicator(true); pbMemRecall->setEnabled(true); } //------------------------------------------------------------------------------ // Name: slotNumberclicked // Desc: user has entered a digit //------------------------------------------------------------------------------ void KCalculator::slotNumberclicked(int number_clicked) { calc_display->enterDigit(number_clicked); core.setOnlyUpdateOperation(false); } //------------------------------------------------------------------------------ // Name: slotSinclicked // Desc: executes the sine function //------------------------------------------------------------------------------ void KCalculator::slotSinclicked() { if (hyp_mode_) { // sinh or arsinh if (!shift_mode_) { core.SinHyp(calc_display->getAmount()); } else { core.AreaSinHyp(calc_display->getAmount()); } } else { // sine or arcsine if (!shift_mode_) { switch (angle_mode_) { case DegMode: core.SinDeg(calc_display->getAmount()); break; case RadMode: core.SinRad(calc_display->getAmount()); break; case GradMode: core.SinGrad(calc_display->getAmount()); break; } } else { switch (angle_mode_) { case DegMode: core.ArcSinDeg(calc_display->getAmount()); break; case RadMode: core.ArcSinRad(calc_display->getAmount()); break; case GradMode: core.ArcSinGrad(calc_display->getAmount()); break; } } } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotPlusMinusclicked // Desc: changes sign of number being displayed //------------------------------------------------------------------------------ void KCalculator::slotPlusMinusclicked() { // display can only change sign, when in input mode, otherwise we // need the core to do this. if (!calc_display->sendEvent(KCalcDisplay::EventChangeSign)) { core.InvertSign(calc_display->getAmount()); updateDisplay(UPDATE_FROM_CORE); } } //------------------------------------------------------------------------------ // Name: slotMemPlusMinusclicked // Desc: handles arithmetic on values stored in memory //------------------------------------------------------------------------------ void KCalculator::slotMemPlusMinusclicked() { bool tmp_shift_mode = shift_mode_; // store this, because next command deletes shift_mode_ EnterEqual(); // finish calculation so far, to store result into MEM if (!tmp_shift_mode) { memory_num_ += calc_display->getAmount(); } else { memory_num_ -= calc_display->getAmount(); } pbShift->setChecked(false); statusBar()->setMemoryIndicator(true); calc_display->setStatusText(MemField, i18n("M")); pbMemRecall->setEnabled(true); } //------------------------------------------------------------------------------ // Name: slotSinclicked // Desc: executes the cosine function //------------------------------------------------------------------------------ void KCalculator::slotCosclicked() { if (hyp_mode_) { // cosh or arcosh if (!shift_mode_) { core.CosHyp(calc_display->getAmount()); } else { core.AreaCosHyp(calc_display->getAmount()); } } else { // cosine or arccosine if (!shift_mode_) { switch (angle_mode_) { case DegMode: core.CosDeg(calc_display->getAmount()); break; case RadMode: core.CosRad(calc_display->getAmount()); break; case GradMode: core.CosGrad(calc_display->getAmount()); break; } } else { switch (angle_mode_) { case DegMode: core.ArcCosDeg(calc_display->getAmount()); break; case RadMode: core.ArcCosRad(calc_display->getAmount()); break; case GradMode: core.ArcCosGrad(calc_display->getAmount()); break; } } } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotSinclicked // Desc: executes the recipricol function //------------------------------------------------------------------------------ void KCalculator::slotReciclicked() { if (shift_mode_) { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_BINOM); } else { core.Reciprocal(calc_display->getAmount()); updateDisplay(UPDATE_FROM_CORE); return; } // temp. work-around KNumber tmp_num = calc_display->getAmount(); calc_display->sendEvent(KCalcDisplay::EventReset); calc_display->setAmount(tmp_num); - updateDisplay(0); + updateDisplay({}); } //------------------------------------------------------------------------------ // Name: slotSinclicked // Desc: executes the tangent function //------------------------------------------------------------------------------ void KCalculator::slotTanclicked() { if (hyp_mode_) { // tanh or artanh if (!shift_mode_) { core.TangensHyp(calc_display->getAmount()); } else { core.AreaTangensHyp(calc_display->getAmount()); } } else { // tan or arctan if (!shift_mode_) { switch (angle_mode_) { case DegMode: core.TangensDeg(calc_display->getAmount()); break; case RadMode: core.TangensRad(calc_display->getAmount()); break; case GradMode: core.TangensGrad(calc_display->getAmount()); break; } } else { switch (angle_mode_) { case DegMode: core.ArcTangensDeg(calc_display->getAmount()); break; case RadMode: core.ArcTangensRad(calc_display->getAmount()); break; case GradMode: core.ArcTangensGrad(calc_display->getAmount()); break; } } } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotFactorialclicked // Desc: executes the factorial function //------------------------------------------------------------------------------ void KCalculator::slotFactorialclicked() { // Set WaitCursor, as this operation may take looooong // time and UI frezes with large numbers. User needs some // visual feedback. QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); if (!shift_mode_) { core.Factorial(calc_display->getAmount()); } else { core.Gamma(calc_display->getAmount()); } QApplication::restoreOverrideCursor(); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotLogclicked // Desc: executes the Log function //------------------------------------------------------------------------------ void KCalculator::slotLogclicked() { if (!shift_mode_) { core.Log10(calc_display->getAmount()); } else { core.Exp10(calc_display->getAmount()); } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotSquareclicked // Desc: executes the x^2 function //------------------------------------------------------------------------------ void KCalculator::slotSquareclicked() { if (!shift_mode_) { core.Square(calc_display->getAmount()); } else { core.SquareRoot(calc_display->getAmount()); } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotCubeclicked // Desc: executes the x^3 function //------------------------------------------------------------------------------ void KCalculator::slotCubeclicked() { if (!shift_mode_) { core.Cube(calc_display->getAmount()); } else { core.CubeRoot(calc_display->getAmount()); } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotCubeclicked // Desc: executes the ln function //------------------------------------------------------------------------------ void KCalculator::slotLnclicked() { if (!shift_mode_) { core.Ln(calc_display->getAmount()); } else { core.Exp(calc_display->getAmount()); } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotPowerclicked // Desc: executes the x^y function //------------------------------------------------------------------------------ void KCalculator::slotPowerclicked() { if (shift_mode_) { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_PWR_ROOT); pbShift->setChecked(false); } else { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_POWER); } // temp. work-around KNumber tmp_num = calc_display->getAmount(); calc_display->sendEvent(KCalcDisplay::EventReset); calc_display->setAmount(tmp_num); - updateDisplay(0); + updateDisplay({}); } //------------------------------------------------------------------------------ // Name: slotMemClearclicked // Desc: executes the MC function //------------------------------------------------------------------------------ void KCalculator::slotMemClearclicked() { memory_num_ = KNumber::Zero; statusBar()->setMemoryIndicator(false); calc_display->setStatusText(MemField, QString()); pbMemRecall->setDisabled(true); } //------------------------------------------------------------------------------ // Name: slotBackspaceclicked // Desc: removes the last input digit //------------------------------------------------------------------------------ void KCalculator::slotBackspaceclicked() { calc_display->deleteLastDigit(); } //------------------------------------------------------------------------------ // Name: slotClearclicked // Desc: clears the display //------------------------------------------------------------------------------ void KCalculator::slotClearclicked() { calc_display->sendEvent(KCalcDisplay::EventClear); } //------------------------------------------------------------------------------ // Name: slotAllClearclicked // Desc: clears everything //------------------------------------------------------------------------------ void KCalculator::slotAllClearclicked() { core.Reset(); calc_display->sendEvent(KCalcDisplay::EventReset); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotParenOpenclicked // Desc: starts a sub-expression //------------------------------------------------------------------------------ void KCalculator::slotParenOpenclicked() { core.ParenOpen(calc_display->getAmount()); } //------------------------------------------------------------------------------ // Name: slotParenCloseclicked // Desc: ends a sub-expression //------------------------------------------------------------------------------ void KCalculator::slotParenCloseclicked() { core.ParenClose(calc_display->getAmount()); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotANDclicked // Desc: executes a bitwise AND //------------------------------------------------------------------------------ void KCalculator::slotANDclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_AND); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotMultiplicationclicked // Desc: executes multiplication //------------------------------------------------------------------------------ void KCalculator::slotMultiplicationclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_MULTIPLY); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotDivisionclicked // Desc: executes division //------------------------------------------------------------------------------ void KCalculator::slotDivisionclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_DIVIDE); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotORclicked // Desc: executes a bitwise OR //------------------------------------------------------------------------------ void KCalculator::slotORclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_OR); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotXORclicked // Desc: executes a bitwise XOR //------------------------------------------------------------------------------ void KCalculator::slotXORclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_XOR); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotPlusclicked // Desc: executes addition //------------------------------------------------------------------------------ void KCalculator::slotPlusclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_ADD); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotPlusclicked // Desc: executes subtraction //------------------------------------------------------------------------------ void KCalculator::slotMinusclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_SUBTRACT); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotLeftShiftclicked // Desc: executes a bitwise left shift //------------------------------------------------------------------------------ void KCalculator::slotLeftShiftclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_LSH); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotLeftShiftclicked // Desc: executes a bitwise right shift //------------------------------------------------------------------------------ void KCalculator::slotRightShiftclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_RSH); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotPeriodclicked // Desc: enters a decimal into the input stream //------------------------------------------------------------------------------ void KCalculator::slotPeriodclicked() { // i know this isn't locale friendly, should be converted to appropriate // value at lower levels calc_display->newCharacter(QLocale().decimalPoint()); } //------------------------------------------------------------------------------ // Name: EnterEqual // Desc: calculates and displays the result of the pending operations //------------------------------------------------------------------------------ void KCalculator::EnterEqual() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_EQUAL); updateDisplay(UPDATE_FROM_CORE | UPDATE_STORE_RESULT); } //------------------------------------------------------------------------------ // Name: slotEqualclicked // Desc: calculates and displays the result of the pending operations //------------------------------------------------------------------------------ void KCalculator::slotEqualclicked() { EnterEqual(); } //------------------------------------------------------------------------------ // Name: slotPercentclicked // Desc: calculates and displays the result of the pending operations as a percent //------------------------------------------------------------------------------ void KCalculator::slotPercentclicked() { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_PERCENT); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotNegateclicked // Desc: executes a bitwise 2's compliment // NOTE: implicitly converts the value to an unsigned quantity //------------------------------------------------------------------------------ void KCalculator::slotNegateclicked() { core.Complement(calc_display->getAmount()); updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotModclicked // Desc: executes modulous (remainder division) //------------------------------------------------------------------------------ void KCalculator::slotModclicked(){ if (shift_mode_) { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_INTDIV); } else { core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_MOD); } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotStatNumclicked // Desc: executes Sum function //------------------------------------------------------------------------------ void KCalculator::slotStatNumclicked() { if (!shift_mode_) { core.StatCount(KNumber::Zero); } else { pbShift->setChecked(false); core.StatSum(KNumber::Zero); } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotStatMeanclicked // Desc: executes Mean function //------------------------------------------------------------------------------ void KCalculator::slotStatMeanclicked() { if (!shift_mode_) { core.StatMean(KNumber::Zero); } else { pbShift->setChecked(false); core.StatSumSquares(KNumber::Zero); } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotStatStdDevclicked // Desc: executes STD function //------------------------------------------------------------------------------ void KCalculator::slotStatStdDevclicked() { if (shift_mode_) { // std (n-1) core.StatStdDeviation(KNumber::Zero); pbShift->setChecked(false); } else { // std (n) core.StatStdSample(KNumber::Zero); } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotStatMedianclicked // Desc: executes Median function //------------------------------------------------------------------------------ void KCalculator::slotStatMedianclicked() { if (!shift_mode_) { // std (n-1) core.StatMedian(KNumber::Zero); } else { // std (n) core.StatMedian(KNumber::Zero); pbShift->setChecked(false); } // TODO: it seems two different modes should be implemented, but...? updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotStatDataInputclicked // Desc: enters a value for statistical functions //------------------------------------------------------------------------------ void KCalculator::slotStatDataInputclicked() { if (!shift_mode_) { core.StatDataNew(calc_display->getAmount()); } else { pbShift->setChecked(false); core.StatDataDel(KNumber::Zero); statusBar()->showMessage(i18n("Last stat item erased"), 3000); } updateDisplay(UPDATE_FROM_CORE); } //------------------------------------------------------------------------------ // Name: slotStatClearDataclicked // Desc: clears memory for statical functions //------------------------------------------------------------------------------ void KCalculator::slotStatClearDataclicked() { if (!shift_mode_) { core.StatClearAll(KNumber::Zero); statusBar()->showMessage(i18n("Stat mem cleared"), 3000); } else { pbShift->setChecked(false); - updateDisplay(0); + updateDisplay({}); } } //------------------------------------------------------------------------------ // Name: slotConstclicked // Desc: enters a constant //------------------------------------------------------------------------------ void KCalculator::slotConstclicked(int button) { if(KCalcConstButton *btn = qobject_cast(const_buttons_[button])) { if (!shift_mode_) { // set the display to the configured value of constant button // internally, we deal with C locale style numbers, we need to convert QString val = btn->constant(); val.replace(QLatin1Char('.'), KNumber::decimalSeparator()); calc_display->setAmount(KNumber(val)); } else { pbShift->setChecked(false); // internally, we deal with C locale style numbers, we need to convert QString val = calc_display->text(); val.replace(KNumber::decimalSeparator(), QLatin1String(".")); KCalcSettings::setValueConstant(button, val); // below set new tooltip btn->setLabelAndTooltip(); // work around: after storing a number, pressing a digit should start // a new number calc_display->setAmount(calc_display->getAmount()); } - updateDisplay(0); + updateDisplay({}); } } //------------------------------------------------------------------------------ // Name: showSettings // Desc: opens the shows the settings dialog //------------------------------------------------------------------------------ void KCalculator::showSettings() { // Check if there is already a dialog and if so bring // it to the foreground. if (KConfigDialog::showDialog(QLatin1String("settings"))) { return; } // Create a new dialog with the same name as the above checking code. KConfigDialog *const dialog = new KConfigDialog(this, QLatin1String("settings"), KCalcSettings::self()); // general settings - General *const general = new General(0); + General *const general = new General(nullptr); general->kcfg_Precision->setMaximum(maxprecision); dialog->addPage(general, i18n("General"), QLatin1String("accessories-calculator"), i18n("General Settings")); // font settings - Fonts *const fonts = new Fonts(0); + Fonts *const fonts = new Fonts(nullptr); dialog->addPage(fonts, i18n("Font"), QLatin1String("preferences-desktop-font"), i18n("Select Display Font")); // color settings - Colors *const color = new Colors(0); + Colors *const color = new Colors(nullptr); dialog->addPage(color, i18n("Colors"), QLatin1String("format-fill-color"), i18n("Button & Display Colors")); // constant settings if (!constants_) { - constants_ = new Constants(0); + constants_ = new Constants(nullptr); } KCalcConstMenu *tmp_menu; tmp_menu = new KCalcConstMenu(this); connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst0); constants_->pushButton0->setMenu(tmp_menu); tmp_menu = new KCalcConstMenu(this); connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst1); constants_->pushButton1->setMenu(tmp_menu); tmp_menu = new KCalcConstMenu(this); connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst2); constants_->pushButton2->setMenu(tmp_menu); tmp_menu = new KCalcConstMenu(this); connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst3); constants_->pushButton3->setMenu(tmp_menu); tmp_menu = new KCalcConstMenu(this); connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst4); constants_->pushButton4->setMenu(tmp_menu); tmp_menu = new KCalcConstMenu(this); connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst5); constants_->pushButton5->setMenu(tmp_menu); dialog->addPage(constants_, i18n("Constants"), QLatin1String("preferences-kcalc-constants"), i18n("Define Constants")); // When the user clicks OK or Apply we want to update our settings. connect(dialog, &KConfigDialog::settingsChanged, this, &KCalculator::updateSettings); // Display the dialog. dialog->show(); } // these 6 slots are just a quick hack, instead of setting the // TextEdit fields in the configuration dialog, we are setting the // Settingvalues themselves!! //------------------------------------------------------------------------------ // Name: slotChooseScientificConst0 // Desc: updates constants value //------------------------------------------------------------------------------ void KCalculator::slotChooseScientificConst0(const science_constant &chosen_const) { constants_->kcfg_valueConstant0->setText(chosen_const.value); constants_->kcfg_nameConstant0->setText(chosen_const.label); } //------------------------------------------------------------------------------ // Name: slotChooseScientificConst1 // Desc: updates constants value //------------------------------------------------------------------------------ void KCalculator::slotChooseScientificConst1(const science_constant &chosen_const) { constants_->kcfg_valueConstant1->setText(chosen_const.value); constants_->kcfg_nameConstant1->setText(chosen_const.label); } //------------------------------------------------------------------------------ // Name: slotChooseScientificConst2 // Desc: updates constants value //------------------------------------------------------------------------------ void KCalculator::slotChooseScientificConst2(const science_constant &chosen_const) { constants_->kcfg_valueConstant2->setText(chosen_const.value); constants_->kcfg_nameConstant2->setText(chosen_const.label); } //------------------------------------------------------------------------------ // Name: slotChooseScientificConst3 // Desc: updates constants value //------------------------------------------------------------------------------ void KCalculator::slotChooseScientificConst3(const science_constant &chosen_const) { constants_->kcfg_valueConstant3->setText(chosen_const.value); constants_->kcfg_nameConstant3->setText(chosen_const.label); } //------------------------------------------------------------------------------ // Name: slotChooseScientificConst4 // Desc: updates constants value //------------------------------------------------------------------------------ void KCalculator::slotChooseScientificConst4(const science_constant &chosen_const) { constants_->kcfg_valueConstant4->setText(chosen_const.value); constants_->kcfg_nameConstant4->setText(chosen_const.label); } //------------------------------------------------------------------------------ // Name: slotChooseScientificConst5 // Desc: updates constants value //------------------------------------------------------------------------------ void KCalculator::slotChooseScientificConst5(const science_constant &chosen_const) { constants_->kcfg_valueConstant5->setText(chosen_const.value); constants_->kcfg_nameConstant5->setText(chosen_const.label); } //------------------------------------------------------------------------------ // Name: slotSetSimpleMode // Desc: sets the calculator to have a simple layout //------------------------------------------------------------------------------ void KCalculator::slotSetSimpleMode() { action_constants_show_->setChecked(false); action_constants_show_->setEnabled(false); action_bitset_show_->setEnabled(false); showMemButtons(false); showScienceButtons(false); showStatButtons(false); showLogicButtons(false); // hide some individual buttons, which are not in one of the above groups pbShift->hide(); pbMod->hide(); pbReci->hide(); pbFactorial->hide(); pbSquare->hide(); pbPower->hide(); pbCube->hide(); pbBackspace->hide(); pbEE->hide(); // delete the constant menu since it doesn't fit delete constants_menu_; - constants_menu_ = 0; + constants_menu_ = nullptr; KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::simple); // must be done after setting the calculator mode because the // slotBitsetshow slot should save the state only in numeral mode action_bitset_show_->setChecked(false); } //------------------------------------------------------------------------------ // Name: slotSetScienceMode // Desc: sets the calculator to science mode //------------------------------------------------------------------------------ void KCalculator::slotSetScienceMode() { action_constants_show_->setEnabled(true); action_constants_show_->setChecked(KCalcSettings::showConstants()); action_bitset_show_->setEnabled(false); // show some individual buttons pbShift->show(); pbMod->show(); pbReci->show(); pbFactorial->show(); pbSquare->show(); pbPower->show(); pbCube->show(); pbBackspace->show(); pbEE->show(); // show or hide some groups of buttons showMemButtons(true); showScienceButtons(true); showStatButtons(false); showLogicButtons(false); if(!constants_menu_) { constants_menu_ = createConstantsMenu(); menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_); } KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::science); // must be done after setting the calculator mode because the // slotBitsetshow slot should save the state only in numeral mode action_bitset_show_->setChecked(false); } //------------------------------------------------------------------------------ // Name: slotSetStatisticMode // Desc: sets the calculator to stats mode //------------------------------------------------------------------------------ void KCalculator::slotSetStatisticMode() { action_constants_show_->setEnabled(true); action_constants_show_->setChecked(KCalcSettings::showConstants()); action_bitset_show_->setEnabled(false); // show some individual buttons pbShift->show(); pbMod->show(); pbReci->show(); pbFactorial->show(); pbSquare->show(); pbPower->show(); pbCube->show(); pbBackspace->show(); pbEE->show(); // show or hide some groups of buttons showMemButtons(true); showScienceButtons(true); showStatButtons(true); showLogicButtons(false); if(!constants_menu_) { constants_menu_ = createConstantsMenu(); menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_); } KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::statistics); // must be done after setting the calculator mode because the // slotBitsetshow slot should save the state only in numeral mode action_bitset_show_->setChecked(false); } //------------------------------------------------------------------------------ // Name: slotSetNumeralMode // Desc: sets the calculator to numerical ("programmers") mode //------------------------------------------------------------------------------ void KCalculator::slotSetNumeralMode() { action_constants_show_->setChecked(false); action_constants_show_->setEnabled(false); action_bitset_show_->setEnabled(true); action_bitset_show_->setChecked(KCalcSettings::showBitset()); // show some individual buttons pbShift->show(); pbMod->show(); pbReci->show(); pbFactorial->show(); pbSquare->show(); pbPower->show(); pbCube->show(); pbBackspace->show(); pbEE->show(); // show or hide some groups of buttons showMemButtons(true); showScienceButtons(false); showStatButtons(false); showLogicButtons(true); if(!constants_menu_) { constants_menu_ = createConstantsMenu(); menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_); } KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::numeral); } //------------------------------------------------------------------------------ // Name: showMemButtons // Desc: hides or shows the memory buttons //------------------------------------------------------------------------------ void KCalculator::showMemButtons(bool toggled) { if (toggled) { foreach(QAbstractButton *btn, mem_button_list_) { btn->show(); } } else { foreach(QAbstractButton *btn, mem_button_list_) { btn->hide(); } // these are in the mem_button_list_ but should not be hidden pbClear->show(); pbAllClear->show(); } } //------------------------------------------------------------------------------ // Name: showStatButtons // Desc: hides or shows the stat buttons //------------------------------------------------------------------------------ void KCalculator::showStatButtons(bool toggled) { if (toggled) { foreach(QAbstractButton *btn, stat_buttons_) { btn->show(); } } else { foreach(QAbstractButton *btn, stat_buttons_) { btn->hide(); } } } //------------------------------------------------------------------------------ // Name: showScienceButtons // Desc: hides or shows the science buttons //------------------------------------------------------------------------------ void KCalculator::showScienceButtons(bool toggled) { if (toggled) { foreach(QAbstractButton* btn, scientific_buttons_) { btn->show(); } foreach(QAbstractButton* btn, angle_choose_group_->buttons()) { btn->show(); } setAngle(); statusBar()->setAngleModeIndicatorVisible(true); } else { foreach(QAbstractButton* btn, scientific_buttons_) { btn->hide(); } foreach(QAbstractButton* btn, angle_choose_group_->buttons()) { btn->hide(); } statusBar()->setAngleModeIndicatorVisible(false); calc_display->setStatusText(AngleField, QString()); } } //------------------------------------------------------------------------------ // Name: showLogicButtons // Desc: hides or shows the logic buttons //------------------------------------------------------------------------------ void KCalculator::showLogicButtons(bool toggled) { if (toggled) { mBitset->setEnabled(true); connect(mBitset, &KCalcBitset::valueChanged, this, &KCalculator::slotBitsetChanged); connect(calc_display, &KCalcDisplay::changedAmount, this, &KCalculator::slotUpdateBitset); foreach(QAbstractButton* btn, logic_buttons_) { btn->show(); } setBase(); statusBar()->setBaseIndicatorVisible(true); foreach(QAbstractButton *btn, base_choose_group_->buttons()) { btn->show(); } for (int i = 10; i < 16; ++i) { (num_button_group_->button(i))->show(); } } else { mBitset->setEnabled(false); disconnect(mBitset, &KCalcBitset::valueChanged, this, &KCalculator::slotBitsetChanged); disconnect(calc_display, &KCalcDisplay::changedAmount, this, &KCalculator::slotUpdateBitset); foreach(QAbstractButton* btn, logic_buttons_) { btn->hide(); } // Hide Hex-Buttons, but first switch back to decimal decRadio->animateClick(0); foreach(QAbstractButton *btn, base_choose_group_->buttons()) { btn->hide(); } statusBar()->setBaseIndicatorVisible(false); calc_display->setStatusText(BaseField, QString()); for (int i = 10; i < 16; ++i) { (num_button_group_->button(i))->hide(); } } } //------------------------------------------------------------------------------ // Name: slotConstantsShow // Desc: hides or shows the constants buttons //------------------------------------------------------------------------------ void KCalculator::slotConstantsShow(bool toggled) { if (toggled) { foreach(QAbstractButton *btn, const_buttons_) { btn->show(); } } else { foreach(QAbstractButton *btn, const_buttons_) { btn->hide(); } } KCalcSettings::setShowConstants(toggled); } //------------------------------------------------------------------------------ // Name: slotBitsetshow // Desc: hides or shows the bitset buttons //------------------------------------------------------------------------------ void KCalculator::slotBitsetshow(bool toggled) { mBitset->setVisible(toggled); if (KCalcSettings::calculatorMode() == KCalcSettings::EnumCalculatorMode::numeral) { KCalcSettings::setShowBitset(toggled); } } //------------------------------------------------------------------------------ // Name: slotBitsetshow // Desc: This function is for setting the constant names configured in the // kcalc settings menu. If the user doesn't enter a name for the // constant C1 to C6 is used. //------------------------------------------------------------------------------ void KCalculator::changeButtonNames() { foreach(QAbstractButton *btn, const_buttons_) { if (KCalcConstButton *const constbtn = qobject_cast(btn)) { constbtn->setLabelAndTooltip(); } } } //------------------------------------------------------------------------------ // Name: slotBitsetChanged // Desc: updates the bitset display // NOTE: sets display to *unsigned* value //------------------------------------------------------------------------------ void KCalculator::slotBitsetChanged(quint64 value) { calc_display->setAmount(KNumber(value)); - updateDisplay(0); + updateDisplay({}); } //------------------------------------------------------------------------------ // Name: slotUpdateBitset // Desc: updates the bitset itself //------------------------------------------------------------------------------ void KCalculator::slotUpdateBitset(const KNumber &nr) { mBitset->setValue(nr.toUint64()); } //------------------------------------------------------------------------------ // Name: updateSettings // Desc: updates the persistent settings //------------------------------------------------------------------------------ void KCalculator::updateSettings() { changeButtonNames(); setColors(); setFonts(); setPrecision(); // Show the result in the app's caption in taskbar (wishlist - bug #52858) - disconnect(calc_display, SIGNAL(changedText(QString)), this, 0); + disconnect(calc_display, SIGNAL(changedText(QString)), this, nullptr); if (KCalcSettings::captionResult()) { connect(calc_display, &KCalcDisplay::changedText, this, &KCalculator::setWindowTitle); } else { setCaption(QString()); } calc_display->changeSettings(); updateGeometry(); } //------------------------------------------------------------------------------ // Name: updateDisplay // Desc: updates the display //------------------------------------------------------------------------------ void KCalculator::updateDisplay(UpdateFlags flags) { if(flags & UPDATE_FROM_CORE) { calc_display->updateFromCore(core, (flags & UPDATE_STORE_RESULT) != 0); core.setOnlyUpdateOperation(true); } else { calc_display->update(); } pbShift->setChecked(false); } //------------------------------------------------------------------------------ // Name: setColors // Desc: set the various colours //------------------------------------------------------------------------------ void KCalculator::setColors() { calc_display->changeSettings(); KColorScheme schemeButtons(QPalette::Active, KColorScheme::Button); const QColor defaultColor = schemeButtons.background().color(); if (KCalcSettings::numberButtonsColor() == defaultColor && KCalcSettings::functionButtonsColor() == defaultColor && KCalcSettings::statButtonsColor() == defaultColor && KCalcSettings::hexButtonsColor() == defaultColor && KCalcSettings::memoryButtonsColor() == defaultColor && KCalcSettings::operationButtonsColor() == defaultColor) { return; } const QString sheet = QLatin1String("QPushButton { background-color: %1 }"); const QColor numPal(KCalcSettings::numberButtonsColor()); for (int i = 0; i < 10; ++i) { (num_button_group_->button(i))->setStyleSheet(sheet.arg(numPal.name())); } const QColor funcPal(KCalcSettings::functionButtonsColor()); foreach(QAbstractButton *btn, function_button_list_) { btn->setStyleSheet(sheet.arg(funcPal.name())); } const QColor statPal(KCalcSettings::statButtonsColor()); foreach(QAbstractButton *btn, stat_buttons_) { btn->setStyleSheet(sheet.arg(statPal.name())); } const QColor hexPal(KCalcSettings::hexButtonsColor()); for (int i = 10; i < 16; ++i) { (num_button_group_->button(i))->setStyleSheet(sheet.arg(hexPal.name())); } const QColor memPal(KCalcSettings::memoryButtonsColor()); foreach(QAbstractButton *btn, mem_button_list_) { btn->setStyleSheet(sheet.arg(memPal.name())); } const QColor opPal(KCalcSettings::operationButtonsColor()); foreach(QAbstractButton *btn, operation_button_list_) { btn->setStyleSheet(sheet.arg(opPal.name())); } } //------------------------------------------------------------------------------ // Name: setFonts // Desc: set the various fonts //------------------------------------------------------------------------------ void KCalculator::setFonts() { foreach(QObject *obj, leftPad->children()) { if (KCalcButton *const button = qobject_cast(obj)) { button->setFont(KCalcSettings::buttonFont()); } } foreach(QObject *obj, numericPad->children()) { if (KCalcButton *const button = qobject_cast(obj)) { button->setFont(KCalcSettings::buttonFont()); } } foreach(QObject *obj, rightPad->children()) { if (KCalcButton *const button = qobject_cast(obj)) { button->setFont(KCalcSettings::buttonFont()); } } updateGeometry(); } //------------------------------------------------------------------------------ // Name: event // Desc: catch application's palette and font change events //------------------------------------------------------------------------------ bool KCalculator::event(QEvent *e) { switch (e->type()) { case QEvent::ApplicationFontChange: setFonts(); break; case QEvent::ApplicationPaletteChange: setColors(); break; default: break; } return KXmlGuiWindow::event(e); } //------------------------------------------------------------------------------ // Name: setPrecision // Desc: set the precision of the display //------------------------------------------------------------------------------ void KCalculator::setPrecision() { KNumber::setDefaultFloatPrecision(KCalcSettings::precision()); - updateDisplay(0); + updateDisplay({}); } //------------------------------------------------------------------------------ // Name: setAngle // Desc: sets the angle mode //------------------------------------------------------------------------------ void KCalculator::setAngle() { if (QAbstractButton *const btn = angle_choose_group_->button(KCalcSettings::angleMode())) { btn->animateClick(0); } } //------------------------------------------------------------------------------ // Name: setBase // Desc: sets the numeric base //------------------------------------------------------------------------------ void KCalculator::setBase() { if (QAbstractButton *const btn = base_choose_group_->button(KCalcSettings::baseMode())) { btn->animateClick(0); } } //------------------------------------------------------------------------------ // Name: eventFilter // Desc: general event filter used to track events like drag/drop //------------------------------------------------------------------------------ bool KCalculator::eventFilter(QObject *o, QEvent *e) { switch (e->type()) { case QEvent::DragEnter: { QDragEnterEvent *const ev = reinterpret_cast(e); ev->setAccepted(KColorMimeData::canDecode(ev->mimeData())); return true; } case QEvent::DragLeave: { return true; } case QEvent::Drop: { KCalcButton *const calcButton = qobject_cast(o); if (!calcButton) { return false; } QDropEvent *const ev = reinterpret_cast(e); QColor c = KColorMimeData::fromMimeData(ev->mimeData()); if (c.isValid()) { QString cn = c.name(); QString sheet = QLatin1String("background-color: %1"); QList *list; const int num_but = num_button_group_->buttons().indexOf(calcButton); if (num_but != -1) { // Was it hex-button or normal digit?? if (num_but < 10) { for (int i = 0; i < 10; ++i) { (num_button_group_->buttons()[i])->setStyleSheet(sheet.arg(cn)); } } else { for (int i = 10; i < 16; ++i) { (num_button_group_->buttons()[i])->setStyleSheet(sheet.arg(cn)); } } return true; } else if (function_button_list_.contains(calcButton)) { list = &function_button_list_; } else if (stat_button_list_.contains(calcButton)) { list = &stat_button_list_; } else if (mem_button_list_.contains(calcButton)) { list = &mem_button_list_; } else if (operation_button_list_.contains(calcButton)) { list = &operation_button_list_; } else { return false; } for (int i = 0; i < list->size(); ++i) { list->at(i)->setStyleSheet(sheet.arg(cn)); } } return true; } // FALL THROUGH default: return KXmlGuiWindow::eventFilter(o, e); } } //////////////////////////////////////////////////////////////// // Include the meta-object code for classes in this file // //------------------------------------------------------------------------------ // Name: kdemain // Desc: entry point of the application //------------------------------------------------------------------------------ extern "C" Q_DECL_EXPORT int kdemain(int argc, char *argv[]) { QApplication app(argc, argv); KLocalizedString::setApplicationDomain("kcalc"); /** * enable high dpi support */ app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); Kdelibs4ConfigMigrator migrate(QLatin1String("kcalc")); migrate.setConfigFiles(QStringList() << QLatin1String("kcalcrc")); migrate.setUiFiles(QStringList() << QLatin1String("kcalcui.rc")); migrate.migrate(); KAboutData aboutData(QStringLiteral("kcalc"), i18n("KCalc"), QStringLiteral(KCALC_VERSION_STRING), i18n(description), KAboutLicense::GPL, i18n("Copyright © 2008-2013, Evan Teran\n" "Copyright © 2000-2008, The KDE Team\n" "Copyright © 2003-2005, Klaus Niederkr" "\xc3\xbc" "ger\n" "Copyright © 1996-2000, Bernd Johannes Wuebben"), QStringLiteral(), QStringLiteral("http://utils.kde.org/projects/kcalc")); // Klaus Niederkrueger aboutData.addAuthor(i18n("Klaus Niederkr" "\xc3\xbc" "ger"), QString(), QStringLiteral("kniederk@math.uni-koeln.de")); aboutData.addAuthor(i18n("Bernd Johannes Wuebben"), QString(), QStringLiteral("wuebben@kde.org")); aboutData.addAuthor(i18n("Evan Teran"), i18n("Maintainer"), QStringLiteral("eteran@alum.rit.edu")); aboutData.addAuthor(i18n("Espen Sand"), QString(), QStringLiteral("espen@kde.org")); aboutData.addAuthor(i18n("Chris Howells"), QString(), QStringLiteral("howells@kde.org")); aboutData.addAuthor(i18n("Aaron J. Seigo"), QString(), QStringLiteral("aseigo@olympusproject.org")); aboutData.addAuthor(i18n("Charles Samuels"), QString(), QStringLiteral("charles@altair.dhs.org")); // Rene Merou aboutData.addAuthor(i18n("Ren" "\xc3\xa9" " M" "\xc3\xa9" "rou"), QString(), QStringLiteral("ochominutosdearco@yahoo.es")); aboutData.addAuthor(i18n("Michel Marti"), QString(), QStringLiteral("mma@objectxp.com")); aboutData.addAuthor(i18n("David Johnson"), QString(), QStringLiteral("david@usermode.org")); KAboutData::setApplicationData(aboutData); app.setWindowIcon(QIcon::fromTheme(QLatin1String("accessories-calculator"), app.windowIcon())); QCommandLineParser parser; parser.addHelpOption(); parser.addVersionOption(); aboutData.setupCommandLine(&parser); parser.process(app); aboutData.processCommandLine(&parser); // force system locale to "C" internally [bug 159168] setlocale(LC_NUMERIC, "C"); KNumber::setGroupSeparator(QLocale().groupSeparator()); KNumber::setDecimalSeparator(QString(QLocale().decimalPoint())); KCalculator *calc = new KCalculator(nullptr); calc->show(); return app.exec(); } diff --git a/kcalc.h b/kcalc.h index 3668436..842da44 100644 --- a/kcalc.h +++ b/kcalc.h @@ -1,283 +1,287 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com Copyright (C) 1996 - 2000 Bernd Johannes Wuebben wuebben@kde.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KCALC_H_ #define KCALC_H_ class Constants; class QButtonGroup; class KToggleAction; class KCalcConstMenu; class KCalcStatusBar; /* Kcalc basically consist of a class for the GUI (here), a class for the display (dlabel.h), and one for the mathematics core (kcalc_core.h). When for example '+' is pressed, one sends the contents of the Display and the '+' to the core via "core.Plus(DISPLAY_AMOUNT)". This only updates the core. To bring the changes to the display, use afterwards "UpdateDisplay(true)". "UpdateDisplay(true)" means that the amount to be displayed should be taken from the core (get the result of some operation that was performed), "UpdateDisplay(false)" has already the information, what to be display (e.g. user is typing in a number). Note that in the last case the core does not know the number typed in until some operation button is pressed, e.g. "core.Plus(display_number)". */ #include "kcalc_core.h" #include "kcalc_button.h" #include "kcalc_const_button.h" #include "ui_kcalc.h" #include "ui_general.h" #include "ui_fonts.h" #include "ui_constants.h" #include "ui_colors.h" #include #include class General: public QWidget, public Ui::General { + Q_OBJECT public: explicit General(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class Fonts: public QWidget, public Ui::Fonts { + Q_OBJECT public: explicit Fonts(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class Constants : public QWidget, public Ui::Constants { + Q_OBJECT public: explicit Constants(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class Colors : public QWidget, public Ui::Colors { + Q_OBJECT public: explicit Colors(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class KCalculator : public KXmlGuiWindow, private Ui::KCalculator { Q_OBJECT public: - explicit KCalculator(QWidget *parent = 0); + explicit KCalculator(QWidget *parent = nullptr); ~KCalculator(); Q_SIGNALS: void switchShift(bool); void switchMode(ButtonModeFlags, bool); void switchShowAccels(bool); public: enum UpdateFlag { UPDATE_FROM_CORE = 1, UPDATE_STORE_RESULT = 2 }; Q_DECLARE_FLAGS(UpdateFlags, UpdateFlag) private: bool eventFilter(QObject *o, QEvent *e) override; bool event(QEvent *e) override; void updateGeometry(); void setupMainActions(); void setupKeys(); void setupNumberKeys(); void setupRightKeypad(); void setupNumericKeypad(); void setupLogicKeys(); void setupScientificKeys(); void setupStatisticKeys(); void setupConstantsKeys(); void setupMiscKeys(); void keyPressEvent(QKeyEvent *e) override; void keyReleaseEvent(QKeyEvent *e) override; void setPrecision(); void setAngle(); void setBase(); void updateDisplay(UpdateFlags flags); KCalcStatusBar *statusBar(); // button sets void showMemButtons(bool toggled); void showStatButtons(bool toggled); void showScienceButtons(bool toggled); void showLogicButtons(bool toggled); KCalcConstMenu *createConstantsMenu(); protected Q_SLOTS: void changeButtonNames(); void updateSettings(); void setColors(); void setFonts(); void EnterEqual(); void showSettings(); // Mode void slotSetSimpleMode(); void slotSetScienceMode(); void slotSetStatisticMode(); void slotSetNumeralMode(); void slotConstantsShow(bool toggled); void slotBitsetshow(bool toggled); void slotAngleSelected(int mode); void slotBaseSelected(int base); void slotNumberclicked(int number_clicked); void slotEEclicked(); void slotShifttoggled(bool myboolean); void slotMemRecallclicked(); void slotMemStoreclicked(); void slotSinclicked(); void slotPlusMinusclicked(); void slotMemPlusMinusclicked(); void slotCosclicked(); void slotReciclicked(); void slotTanclicked(); void slotFactorialclicked(); void slotLogclicked(); void slotSquareclicked(); void slotCubeclicked(); void slotLnclicked(); void slotPowerclicked(); void slotMemClearclicked(); void slotClearclicked(); void slotAllClearclicked(); void slotParenOpenclicked(); void slotParenCloseclicked(); void slotANDclicked(); void slotMultiplicationclicked(); void slotDivisionclicked(); void slotORclicked(); void slotXORclicked(); void slotPlusclicked(); void slotMinusclicked(); void slotLeftShiftclicked(); void slotRightShiftclicked(); void slotPeriodclicked(); void slotEqualclicked(); void slotPercentclicked(); void slotNegateclicked(); void slotModclicked(); void slotStatNumclicked(); void slotStatMeanclicked(); void slotStatStdDevclicked(); void slotStatMedianclicked(); void slotStatDataInputclicked(); void slotStatClearDataclicked(); void slotHyptoggled(bool flag); void slotConstclicked(int); void slotBackspaceclicked(); void slotConstantToDisplay(const science_constant &const_chosen); void slotChooseScientificConst0(const science_constant &); void slotChooseScientificConst1(const science_constant &); void slotChooseScientificConst2(const science_constant &); void slotChooseScientificConst3(const science_constant &); void slotChooseScientificConst4(const science_constant &); void slotChooseScientificConst5(const science_constant &); void slotBitsetChanged(quint64); void slotUpdateBitset(const KNumber &); private: enum StatusField { ShiftField = 0, BaseField, AngleField, MemField }; enum AngleMode { DegMode = 0, RadMode, GradMode }; enum BaseMode { BinMode = 2, OctMode = 8, DecMode = 10, HexMode = 16 }; private: bool shift_mode_; bool hyp_mode_; KNumber memory_num_; int angle_mode_; // angle modes for trigonometric values KCalcConstMenu* constants_menu_; Constants* constants_; // this is the dialog for configuring const buttons QButtonGroup* angle_choose_group_; QButtonGroup* base_choose_group_; // num_button_group_: 0-9 = digits, 0xA-0xF = hex-keys QButtonGroup* num_button_group_; QList logic_buttons_; QList scientific_buttons_; QList stat_buttons_; QList const_buttons_; KToggleAction *action_bitset_show_; KToggleAction *action_constants_show_; KToggleAction *action_mode_simple_; KToggleAction *action_mode_science_; KToggleAction *action_mode_statistic_; KToggleAction *action_mode_numeral_; QList function_button_list_; QList stat_button_list_; QList mem_button_list_; QList operation_button_list_; CalcEngine core; }; Q_DECLARE_OPERATORS_FOR_FLAGS(KCalculator::UpdateFlags) #endif diff --git a/kcalc_bitset.h b/kcalc_bitset.h index 2d19311..0e67dd5 100644 --- a/kcalc_bitset.h +++ b/kcalc_bitset.h @@ -1,48 +1,48 @@ /* Copyright (C) 2012 - 2013 Evan Teran evan.teran@gmail.com Copyright (C) 2006 Michel Marti mma@objectxp.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KCALC_BITSET_H_ #define KCALC_BITSET_H_ #include class QButtonGroup; class KCalcBitset : public QFrame { Q_OBJECT public: - explicit KCalcBitset(QWidget *parent = 0); + explicit KCalcBitset(QWidget *parent = nullptr); quint64 getValue() const; public Q_SLOTS: void setValue(quint64 value); void slotToggleBit(int bit); Q_SIGNALS: void valueChanged(quint64 value); private: QButtonGroup *bit_button_group_; quint64 value_; }; #endif diff --git a/kcalc_button.cpp b/kcalc_button.cpp index 4620936..4c62d46 100644 --- a/kcalc_button.cpp +++ b/kcalc_button.cpp @@ -1,251 +1,251 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com Copyright (C) 1996 - 2000 Bernd Johannes Wuebben wuebben@kde.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "kcalc_button.h" #include #include #include #include #include //------------------------------------------------------------------------------ // Name: KCalcButton // Desc: constructor //------------------------------------------------------------------------------ KCalcButton::KCalcButton(QWidget *parent) : QPushButton(parent), show_shortcut_mode_(false), mode_flags_(ModeNormal), size_() { setAcceptDrops(true); // allow color drops setFocusPolicy(Qt::TabFocus); setAutoDefault(false); // use preferred size policy for vertical setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); setAttribute(Qt::WA_LayoutUsesWidgetRect); } //------------------------------------------------------------------------------ // Name: KCalcButton // Desc: constructor //------------------------------------------------------------------------------ KCalcButton::KCalcButton(const QString &label, QWidget *parent, const QString &tooltip) : QPushButton(label, parent), show_shortcut_mode_(false), mode_flags_(ModeNormal), size_() { setAutoDefault(false); addMode(ModeNormal, label, tooltip); // use preferred size policy for vertical setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); setAttribute(Qt::WA_LayoutUsesWidgetRect); } //------------------------------------------------------------------------------ // Name: addMode // Desc: //------------------------------------------------------------------------------ void KCalcButton::addMode(ButtonModeFlags mode, const QString &label, const QString &tooltip) { if (mode_.contains(mode)) { mode_.remove(mode); } mode_[mode] = ButtonMode(label, tooltip); calcSizeHint(); // Need to put each button into default mode first if (mode == ModeNormal) { slotSetMode(ModeNormal, true); } } //------------------------------------------------------------------------------ // Name: slotSetMode // Desc: //------------------------------------------------------------------------------ void KCalcButton::slotSetMode(ButtonModeFlags mode, bool flag) { ButtonModeFlags new_mode; if (flag) { // if the specified mode is to be set (i.e. flag = true) new_mode = ButtonModeFlags(mode_flags_ | mode); } else if (mode_flags_ && mode) { // if the specified mode is to be cleared (i.e. flag = false) new_mode = ButtonModeFlags(mode_flags_ - mode); } else { return; // nothing to do } if (mode_.contains(new_mode)) { // save shortcut, because setting label erases it QKeySequence current_shortcut = shortcut(); setText(mode_[new_mode].label); this->setToolTip(mode_[new_mode].tooltip); mode_flags_ = new_mode; // restore shortcut setShortcut(current_shortcut); } // this is necessary for people pressing CTRL and changing mode at // the same time... if (show_shortcut_mode_) { slotSetAccelDisplayMode(true); } update(); } //------------------------------------------------------------------------------ // Name: slotSetAccelDisplayMode // Desc: //------------------------------------------------------------------------------ void KCalcButton::slotSetAccelDisplayMode(bool flag) { show_shortcut_mode_ = flag; // save shortcut, because setting label erases it QKeySequence current_shortcut = shortcut(); if (flag) { setText(shortcut().toString(QKeySequence::NativeText)); } else { setText(mode_[mode_flags_].label); } // restore shortcut setShortcut(current_shortcut); update(); } //------------------------------------------------------------------------------ // Name: paintEvent // Desc: draws the button //------------------------------------------------------------------------------ void KCalcButton::paintEvent(QPaintEvent *) { QPainter p(this); QStyleOptionButton option; initStyleOption(&option); const bool is_down = isDown() || isChecked(); const int x_offset = is_down ? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &option, this) : 0; const int y_offset = is_down ? style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &option, this) : 0; // draw bevel style()->drawControl(QStyle::CE_PushButtonBevel, &option, &p, this); // draw label... p.save(); // rant: Qt4 needs QSimpleRichText, dammit! QTextDocument doc; QAbstractTextDocumentLayout::PaintContext context; doc.setHtml(QLatin1String("
") + text() + QLatin1String("
")); doc.setDefaultFont(font()); context.palette = palette(); context.palette.setColor(QPalette::Text, context.palette.buttonText().color()); p.translate((width() / 2 - doc.size().width() / 2) + x_offset, (height() / 2 - doc.size().height() / 2) + y_offset); doc.documentLayout()->draw(&p, context); p.restore(); // draw focus if (hasFocus()) { QStyleOptionFocusRect fropt; fropt.QStyleOption::operator=(option); fropt.rect = style()->subElementRect(QStyle::SE_PushButtonFocusRect, &option, this); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, &p, this); } } //------------------------------------------------------------------------------ // Name: sizeHint // Desc: //------------------------------------------------------------------------------ QSize KCalcButton::sizeHint() const { // reimplemented to provide a smaller button return size_; } //------------------------------------------------------------------------------ // Name: calcSizeHint // Desc: //------------------------------------------------------------------------------ void KCalcButton::calcSizeHint() { - int margin = style()->pixelMetric(QStyle::PM_ButtonMargin, 0, this); + int margin = style()->pixelMetric(QStyle::PM_ButtonMargin, nullptr, this); // want narrow margin than normal margin = qMax(margin / 2, 3); // approximation because metrics doesn't account for richtext size_ = fontMetrics().size(0, mode_[ModeNormal].label); if (mode_.contains(ModeShift)) { size_ = size_.expandedTo(fontMetrics().size(0, mode_[ModeShift].label)); } if (mode_.contains(ModeHyperbolic)) { size_ = size_.expandedTo(fontMetrics().size(0, mode_[ModeHyperbolic].label)); } size_ += QSize(margin * 2, margin * 2); size_ = size_.expandedTo(QApplication::globalStrut()); } //------------------------------------------------------------------------------ // Name: setFont // Desc: //------------------------------------------------------------------------------ void KCalcButton::setFont(const QFont &fnt) { QPushButton::setFont(fnt); calcSizeHint(); } //------------------------------------------------------------------------------ // Name: setText // Desc: //------------------------------------------------------------------------------ void KCalcButton::setText(const QString &text) { QPushButton::setText(text); // normal mode may not have been explicitly set if (mode_[ModeNormal].label.isEmpty()) { mode_[ModeNormal].label = text; } calcSizeHint(); } //------------------------------------------------------------------------------ // Name: setToolTip // Desc: //------------------------------------------------------------------------------ void KCalcButton::setToolTip(const QString &tip) { QPushButton::setToolTip(tip); // normal mode may not have been explicitly set if (mode_[ModeNormal].tooltip.isEmpty()) { mode_[ModeNormal].tooltip = tip; } } diff --git a/kcalc_const_menu.h b/kcalc_const_menu.h index 3768daa..397de36 100644 --- a/kcalc_const_menu.h +++ b/kcalc_const_menu.h @@ -1,65 +1,65 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com Copyright (C) 2003 - 2005 Klaus Niederkrueger kniederk@math.uni-koeln.de This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KCALC_CONST_MENU_H_ #define KCALC_CONST_MENU_H_ #include #include enum ConstantCategory { Mathematics = 1, Electromagnetic = 2, Nuclear = 4, Thermodynamics = 8, Gravitation = 16 }; struct science_constant { QString label; QString name; QString whatsthis; QString value; ConstantCategory category; }; class KCalcConstMenu : public QMenu { Q_OBJECT public: - explicit KCalcConstMenu(QWidget * parent = 0); - explicit KCalcConstMenu(const QString &title, QWidget * parent = 0); + explicit KCalcConstMenu(QWidget * parent = nullptr); + explicit KCalcConstMenu(const QString &title, QWidget * parent = nullptr); public: static void init_consts(); Q_SIGNALS: void triggeredConstant(const science_constant &); private: void init_all(); public Q_SLOTS: void slotPassSignalThrough(QAction *chosen_const); }; #endif diff --git a/kcalc_statusbar.h b/kcalc_statusbar.h index 63c3425..9111f05 100644 --- a/kcalc_statusbar.h +++ b/kcalc_statusbar.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2014 Christoph Feck * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KCALC_STATUSBAR_H_ #define KCALC_STATUSBAR_H_ #include class QLabel; class KCalcStatusBar : public QStatusBar { Q_OBJECT public: - KCalcStatusBar(QWidget *parent = 0); + explicit KCalcStatusBar(QWidget *parent = nullptr); ~KCalcStatusBar(); public: enum AngleMode { DegMode, RadMode, GradMode }; public: void setBaseIndicatorVisible(bool visible); void setAngleModeIndicatorVisible(bool visible); void setShiftIndicator(bool shift); void setBase(int base); void setAngleMode(AngleMode mode); void setMemoryIndicator(bool memory); private: QLabel *addIndicator(QList indicatorTexts); private: QLabel *shift_indicator_; QLabel *base_indicator_; QLabel *angle_mode_indicator_; QLabel *memory_indicator_; }; #endif diff --git a/kcalcdisplay.h b/kcalcdisplay.h index b6ac035..144ab24 100644 --- a/kcalcdisplay.h +++ b/kcalcdisplay.h @@ -1,156 +1,156 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com Copyright (C) 1996 - 2000 Bernd Johannes Wuebben wuebben@kde.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KCALCDISPLAY_H_ #define KCALCDISPLAY_H_ #include #include #include "knumber.h" class CalcEngine; class QTimer; class QStyleOptionFrame; #define NUM_STATUS_TEXT 4 /* This class provides a pocket calculator display. The display has implicitely two major modes: One is for editing and one is purely for displaying. When one uses "setAmount", the given amount is displayed, and the amount which was possibly typed in before is lost. At the same time this new value can not be modified. On the other hand, "addNewChar" adds a new digit to the amount that is being typed in. If "setAmount" was used before, the display is cleared and a new input starts. TODO: Check overflows, number of digits and such... */ enum NumBase { NB_BINARY = 2, NB_OCTAL = 8, NB_DECIMAL = 10, NB_HEX = 16 }; class KCalcDisplay : public QFrame { Q_OBJECT public: - explicit KCalcDisplay(QWidget *parent = 0); - ~KCalcDisplay(); + explicit KCalcDisplay(QWidget *parent = nullptr); + ~KCalcDisplay() override; enum Event { EventReset, // resets display EventClear, // if no error reset display EventError, EventChangeSign }; bool sendEvent(Event event); void deleteLastDigit(); const KNumber &getAmount() const; void newCharacter(const QChar new_char); bool setAmount(const KNumber &new_amount); int setBase(NumBase new_base); void setBeep(bool flag); void setGroupDigits(bool flag); void setTwosComplement(bool flag); void setBinaryGrouping(int digits); void setOctalGrouping(int digits); void setHexadecimalGrouping(int digits); void setFixedPrecision(int precision); void setPrecision(int precision); void setText(const QString &string); QString formatDecimalNumber(QString string); QString groupDigits(const QString &displayString, int numDigits); QString text() const; void updateDisplay(); void setStatusText(int i, const QString &text); QSize sizeHint() const override; void changeSettings(); void enterDigit(int data); void updateFromCore(const CalcEngine &core, bool store_result_in_history = false); public Q_SLOTS: void slotCut(); void slotCopy(); void slotPaste(bool bClipboard = true); Q_SIGNALS: void clicked(); void changedText(const QString &); void changedAmount(const KNumber &); protected: void mousePressEvent(QMouseEvent *) override; void paintEvent(QPaintEvent *p) override; private: bool changeSign(); void invertColors(); void initStyleOption(QStyleOptionFrame *option) const; private Q_SLOTS: void slotSelectionTimedOut(); void slotDisplaySelected(); void slotHistoryBack(); void slotHistoryForward(); private: QString text_; bool beep_; bool groupdigits_; bool twoscomplement_; int binaryGrouping_; int octalGrouping_; int hexadecimalGrouping_; int button_; bool lit_; NumBase num_base_; int precision_; int fixed_precision_; // "-1" = no fixed_precision KNumber display_amount_; QVector history_list_; int history_index_; // only used for input of new numbers bool eestate_; bool period_; bool neg_sign_; QString str_int_; QString str_int_exp_; QString str_status_[NUM_STATUS_TEXT]; QTimer* selection_timer_; }; #endif diff --git a/knumber/knumber.cpp b/knumber/knumber.cpp index aaa4be8..872e5db 100644 --- a/knumber/knumber.cpp +++ b/knumber/knumber.cpp @@ -1,946 +1,946 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "knumber.h" #include "knumber_base.h" #include "knumber_error.h" #include "knumber_float.h" #include "knumber_fraction.h" #include "knumber_integer.h" #include #include #include #include QString KNumber::GroupSeparator = QLatin1String(","); QString KNumber::DecimalSeparator = QLatin1String("."); const KNumber KNumber::Zero(QLatin1String("0")); const KNumber KNumber::One(QLatin1String("1")); const KNumber KNumber::NegOne(QLatin1String("-1")); const KNumber KNumber::PosInfinity(QLatin1String("inf")); const KNumber KNumber::NegInfinity(QLatin1String("-inf")); const KNumber KNumber::NaN(QLatin1String("nan")); namespace { namespace impl { //------------------------------------------------------------------------------ // Name: increment //------------------------------------------------------------------------------ void increment(QString &str, int position) { for (int i = position; i >= 0; i--) { const char last_char = str[i].toLatin1(); switch (last_char) { case '0': str[i] = QLatin1Char('1'); break; case '1': str[i] = QLatin1Char('2'); break; case '2': str[i] = QLatin1Char('3'); break; case '3': str[i] = QLatin1Char('4'); break; case '4': str[i] = QLatin1Char('5'); break; case '5': str[i] = QLatin1Char('6'); break; case '6': str[i] = QLatin1Char('7'); break; case '7': str[i] = QLatin1Char('8'); break; case '8': str[i] = QLatin1Char('9'); break; case '9': str[i] = QLatin1Char('0'); if (i == 0) { str.prepend(QLatin1Char('1')); } continue; case '.': continue; } break; } } //------------------------------------------------------------------------------ // Name: round //------------------------------------------------------------------------------ void round(QString &str, int precision) { // Cut off if more digits in fractional part than 'precision' int decimalSymbolPos = str.indexOf(QLatin1Char('.')); if (decimalSymbolPos == -1) { if (precision == 0) { return; } else if (precision > 0) { // add dot if missing (and needed) str.append(QLatin1Char('.')); decimalSymbolPos = str.length() - 1; } } // fill up with more than enough zeroes (in case fractional part too short) str.append(QString().fill(QLatin1Char('0'), precision)); // Now decide whether to round up or down const char last_char = str[decimalSymbolPos + precision + 1].toLatin1(); switch (last_char) { case '0': case '1': case '2': case '3': case '4': // nothing to do, rounding down break; case '5': case '6': case '7': case '8': case '9': // rounding up increment(str, decimalSymbolPos + precision); break; default: break; } decimalSymbolPos = str.indexOf(QLatin1Char('.')); str.truncate(decimalSymbolPos + precision + 1); // if precision == 0 delete also '.' if (precision == 0) { str = str.section(QLatin1Char('.'), 0, 0); } } } //------------------------------------------------------------------------------ // Name: round //------------------------------------------------------------------------------ QString round(const QString &s, int precision) { QString tmp = s; if (precision < 0 || !QRegExp(QLatin1String("^[+-]?\\d+(\\.\\d+)*(e[+-]?\\d+)?$")).exactMatch(tmp)) { return s; } // Skip the sign (for now) const bool neg = (tmp[0] == QLatin1Char('-')); if (neg || tmp[0] == QLatin1Char('+')) { tmp.remove(0, 1); } // Split off exponential part (including 'e'-symbol) QString mantString = tmp.section(QLatin1Char('e'), 0, 0, QString::SectionCaseInsensitiveSeps); QString expString = tmp.section(QLatin1Char('e'), 1, 1, QString::SectionCaseInsensitiveSeps | QString::SectionIncludeLeadingSep); if (expString.length() == 1) { expString.clear(); } impl::round(mantString, precision); if (neg) { mantString.prepend(QLatin1Char('-')); } return mantString + expString; } } //------------------------------------------------------------------------------ // Name: setGroupSeparator //------------------------------------------------------------------------------ void KNumber::setGroupSeparator(const QString &ch) { GroupSeparator = ch; } //------------------------------------------------------------------------------ // Name: setDecimalSeparator //------------------------------------------------------------------------------ void KNumber::setDecimalSeparator(const QString &ch) { DecimalSeparator = ch; } //------------------------------------------------------------------------------ // Name: groupSeparator //------------------------------------------------------------------------------ QString KNumber::groupSeparator() { return GroupSeparator; } //------------------------------------------------------------------------------ // Name: decimalSeparator //------------------------------------------------------------------------------ QString KNumber::decimalSeparator() { return DecimalSeparator; } //------------------------------------------------------------------------------ // Name: setDefaultFloatPrecision //------------------------------------------------------------------------------ void KNumber::setDefaultFloatPrecision(int precision) { // Need to transform decimal digits into binary digits const unsigned long int bin_prec = static_cast(double(precision) * M_LN10 / M_LN2 + 1); mpf_set_default_prec(bin_prec); } //------------------------------------------------------------------------------ // Name: setSplitoffIntegerForFractionOutput //------------------------------------------------------------------------------ void KNumber::setSplitoffIntegerForFractionOutput(bool x) { detail::knumber_fraction::set_split_off_integer_for_fraction_output(x); } //------------------------------------------------------------------------------ // Name: setDefaultFractionalInput //------------------------------------------------------------------------------ void KNumber::setDefaultFractionalInput(bool x) { detail::knumber_fraction::set_default_fractional_input(x); } //------------------------------------------------------------------------------ // Name: setDefaultFloatOutput //------------------------------------------------------------------------------ void KNumber::setDefaultFloatOutput(bool x) { detail::knumber_fraction::set_default_fractional_output(!x); } //------------------------------------------------------------------------------ // Name: Pi //------------------------------------------------------------------------------ KNumber KNumber::Pi() { // TODO: after 4.10 release: // create a new constructor which works just like the normal QString // accepting constructor, but allows us to specify separator // characters, this will allow things to be done slightly more // efficiently QString s(QLatin1String("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068")); s.replace(QLatin1Char('.'), DecimalSeparator); return KNumber(s); } //------------------------------------------------------------------------------ // Name: Euler //------------------------------------------------------------------------------ KNumber KNumber::Euler() { // TODO: after 4.10 release: // create a new constructor which works just like the normal QString // accepting constructor, but allows us to specify separator // characters, this will allow things to be done slightly more // efficiently QString s(QLatin1String("2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274")); s.replace(QLatin1Char('.'), DecimalSeparator); return KNumber(s); } //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ KNumber::KNumber() : value_(new detail::knumber_integer(0)) { } //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ -KNumber::KNumber(const QString &s) : value_(0) { +KNumber::KNumber(const QString &s) : value_(nullptr) { const QRegExp special_regex(QLatin1String("^(inf|-inf|nan)$")); const QRegExp integer_regex(QLatin1String("^[+-]?\\d+$")); const QRegExp fraction_regex(QLatin1String("^[+-]?\\d+/\\d+$")); const QRegExp float_regex(QString(QLatin1String("^([+-]?\\d*)(%1\\d*)?(e([+-]?\\d+))?$")).arg(QRegExp::escape(DecimalSeparator))); if (special_regex.exactMatch(s)) { value_ = new detail::knumber_error(s); } else if (integer_regex.exactMatch(s)) { value_ = new detail::knumber_integer(s); } else if (fraction_regex.exactMatch(s)) { value_ = new detail::knumber_fraction(s); simplify(); } else if (float_regex.exactMatch(s)) { if(detail::knumber_fraction::default_fractional_input) { const QStringList list = float_regex.capturedTexts(); if(list.size() == 5) { const QString ipart = list[1]; const QString fpart = list[2]; const QString epart = list[3]; const int e_val = list[4].toInt(); QString num = ipart + fpart.mid(1); QString den = QLatin1String("1") + QString(fpart.size() - 1, QLatin1Char('0')); if(e_val < 0) { den = den + QString(::abs(e_val), QLatin1Char('0')); } else if(e_val > 0) { num = num + QString(::abs(e_val), QLatin1Char('0')); } value_ = new detail::knumber_fraction(QString(QLatin1String("%1/%2")).arg(num, den)); simplify(); return; } } // we need to normalize the decimal searator to US style because that's // the only type that the GMP function accept QString new_s = s; new_s.replace(DecimalSeparator, QLatin1String(".")); value_ = new detail::knumber_float(new_s); simplify(); } else { value_ = new detail::knumber_error(detail::knumber_error::ERROR_UNDEFINED); } } //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ KNumber::KNumber(qint32 value) : value_(new detail::knumber_integer(value)) { } //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ KNumber::KNumber(qint64 value) : value_(new detail::knumber_integer(value)) { } //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ KNumber::KNumber(quint32 value) : value_(new detail::knumber_integer(value)) { } //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ KNumber::KNumber(quint64 value) : value_(new detail::knumber_integer(value)) { } //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ KNumber::KNumber(qint64 num, quint64 den) : value_(new detail::knumber_fraction(num, den)) { } //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ KNumber::KNumber(quint64 num, quint64 den) : value_(new detail::knumber_fraction(num, den)) { } #ifdef HAVE_LONG_DOUBLE //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ KNumber::KNumber(long double value) : value_(new detail::knumber_float(value)) { simplify(); } #endif //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ KNumber::KNumber(double value) : value_(new detail::knumber_float(value)) { simplify(); } //------------------------------------------------------------------------------ // Name: KNumber //------------------------------------------------------------------------------ -KNumber::KNumber(const KNumber &other) : value_(0) { +KNumber::KNumber(const KNumber &other) : value_(nullptr) { if(&other != this) { value_ = other.value_->clone(); } } //------------------------------------------------------------------------------ // Name: ~KNumber //------------------------------------------------------------------------------ KNumber::~KNumber() { delete value_; } //------------------------------------------------------------------------------ // Name: type //------------------------------------------------------------------------------ KNumber::Type KNumber::type() const { if(dynamic_cast(value_)) { return TYPE_INTEGER; } else if(dynamic_cast(value_)) { return TYPE_FLOAT; } else if(dynamic_cast(value_)) { return TYPE_FRACTION; } else if(dynamic_cast(value_)) { return TYPE_ERROR; } else { Q_ASSERT(0); return TYPE_ERROR; } } //------------------------------------------------------------------------------ // Name: operator= //------------------------------------------------------------------------------ KNumber &KNumber::operator=(const KNumber &rhs) { KNumber(rhs).swap(*this); return *this; } //------------------------------------------------------------------------------ // Name: swap //------------------------------------------------------------------------------ void KNumber::swap(KNumber &other) { qSwap(value_, other.value_); } //------------------------------------------------------------------------------ // Name: integerPart //------------------------------------------------------------------------------ KNumber KNumber::integerPart() const { KNumber x(*this); if(detail::knumber_integer *const p = dynamic_cast(value_)) { // NO-OP Q_UNUSED(p); } else if(detail::knumber_float *const p = dynamic_cast(value_)) { detail::knumber_base *v = new detail::knumber_integer(p); qSwap(v, x.value_); delete v; } else if(detail::knumber_fraction *const p = dynamic_cast(value_)) { detail::knumber_base *v = new detail::knumber_integer(p); qSwap(v, x.value_); delete v; } else if(detail::knumber_error *const p = dynamic_cast(value_)) { // NO-OP Q_UNUSED(p); } else { Q_ASSERT(0); } return x; } //------------------------------------------------------------------------------ // Name: simplify //------------------------------------------------------------------------------ void KNumber::simplify() { if(value_->is_integer()) { if(detail::knumber_integer *const p = dynamic_cast(value_)) { // NO-OP Q_UNUSED(p); } else if(detail::knumber_float *const p = dynamic_cast(value_)) { detail::knumber_base *v = new detail::knumber_integer(p); qSwap(v, value_); delete v; } else if(detail::knumber_fraction *const p = dynamic_cast(value_)) { detail::knumber_base *v = new detail::knumber_integer(p); qSwap(v, value_); delete v; } else if(detail::knumber_error *const p = dynamic_cast(value_)) { // NO-OP Q_UNUSED(p); } else { Q_ASSERT(0); } } } //------------------------------------------------------------------------------ // Name: operator+= //------------------------------------------------------------------------------ KNumber &KNumber::operator+=(const KNumber &rhs) { value_ = value_->add(rhs.value_); simplify(); return *this; } //------------------------------------------------------------------------------ // Name: operator-= //------------------------------------------------------------------------------ KNumber &KNumber::operator-=(const KNumber &rhs) { value_ = value_->sub(rhs.value_); simplify(); return *this; } //------------------------------------------------------------------------------ // Name: operator*= //------------------------------------------------------------------------------ KNumber &KNumber::operator*=(const KNumber &rhs) { value_ = value_->mul(rhs.value_); simplify(); return *this; } //------------------------------------------------------------------------------ // Name: operator/= //------------------------------------------------------------------------------ KNumber &KNumber::operator/=(const KNumber &rhs) { // Fix for bug #330577, x /0 is undefined, not infinity // Also indirectly fixes bug #329897, tan(90) is undefined, not infinity if(rhs == Zero) { *this = NaN; return *this; } value_ = value_->div(rhs.value_); simplify(); return *this; } //------------------------------------------------------------------------------ // Name: operator%= //------------------------------------------------------------------------------ KNumber &KNumber::operator%=(const KNumber &rhs) { value_ = value_->mod(rhs.value_); simplify(); return *this; } //------------------------------------------------------------------------------ // Name: operator&= //------------------------------------------------------------------------------ KNumber &KNumber::operator&=(const KNumber &rhs) { value_ = value_->bitwise_and(rhs.value_); return *this; } //------------------------------------------------------------------------------ // Name: operator|= //------------------------------------------------------------------------------ KNumber &KNumber::operator|=(const KNumber &rhs) { value_ = value_->bitwise_or(rhs.value_); return *this; } //------------------------------------------------------------------------------ // Name: operator^= //------------------------------------------------------------------------------ KNumber &KNumber::operator^=(const KNumber &rhs) { value_ = value_->bitwise_xor(rhs.value_); return *this; } //------------------------------------------------------------------------------ // Name: operator<< //------------------------------------------------------------------------------ KNumber &KNumber::operator<<=(const KNumber &rhs) { value_ = value_->bitwise_shift(rhs.value_); return *this; } //------------------------------------------------------------------------------ // Name: operator>>= //------------------------------------------------------------------------------ KNumber &KNumber::operator>>=(const KNumber &rhs) { const KNumber rhs_neg(-rhs); value_ = value_->bitwise_shift(rhs_neg.value_); return *this; } //------------------------------------------------------------------------------ // Name: operator- //------------------------------------------------------------------------------ KNumber KNumber::operator-() const { KNumber x(*this); x.value_ = x.value_->neg(); return x; } //------------------------------------------------------------------------------ // Name: operator~ //------------------------------------------------------------------------------ KNumber KNumber::operator~() const { KNumber x(*this); x.value_ = x.value_->cmp(); return x; } //------------------------------------------------------------------------------ // Name: toQString //------------------------------------------------------------------------------ QString KNumber::toQString(int width, int precision) const { if(value_->is_zero()) { return QLatin1String("0"); } QString s; if(detail::knumber_integer *const p = dynamic_cast(value_)) { if(width > 0) { s = detail::knumber_float(p).toString(width); } else { s = value_->toString(width); } } else if(detail::knumber_float *const p = dynamic_cast(value_)) { if(width > 0) { s = value_->toString(width); } else { s = value_->toString(3 * mpf_get_default_prec() / 10); } } else if(detail::knumber_fraction *const p = dynamic_cast(value_)) { s = value_->toString(width); } else { return value_->toString(width); } // now do some rounding to make sure things are displayed reasonably if (precision >= 0) { return round(s, precision); } else { return s; } } //------------------------------------------------------------------------------ // Name: toUint64 //------------------------------------------------------------------------------ quint64 KNumber::toUint64() const { return value_->toUint64(); } //------------------------------------------------------------------------------ // Name: toInt64 //------------------------------------------------------------------------------ qint64 KNumber::toInt64() const { return value_->toInt64(); } //------------------------------------------------------------------------------ // Name: abs //------------------------------------------------------------------------------ KNumber KNumber::abs() const { KNumber z(*this); z.value_ = z.value_->abs(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: cbrt //------------------------------------------------------------------------------ KNumber KNumber::cbrt() const { KNumber z(*this); z.value_ = z.value_->cbrt(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: sqrt //------------------------------------------------------------------------------ KNumber KNumber::sqrt() const { KNumber z(*this); z.value_ = z.value_->sqrt(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: pow //------------------------------------------------------------------------------ KNumber KNumber::pow(const KNumber &x) const { // Fix for bug #330711 (pow(0, -x) was causing crashes // Fix for bug #330597 (pow(0,0) was 1 now it is NaN // Thanks to Raushan Kumar for identifying the issue and submitting // patches if(*this == Zero && x <= Zero) { return NaN; } // if the LHS is a special then we can use this function // no matter what, cause the result is a special too if(!dynamic_cast(value_)) { // number much bigger than this tend to crash GMP with // an abort if(x > KNumber(QLatin1String("1000000000"))) { return PosInfinity; } } KNumber z(*this); z.value_ = z.value_->pow(x.value_); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: sin //------------------------------------------------------------------------------ KNumber KNumber::sin() const { KNumber z(*this); z.value_ = z.value_->sin(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: cos //------------------------------------------------------------------------------ KNumber KNumber::cos() const { KNumber z(*this); z.value_ = z.value_->cos(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: tan //------------------------------------------------------------------------------ KNumber KNumber::tan() const { KNumber z(*this); z.value_ = z.value_->tan(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: tgamma //------------------------------------------------------------------------------ KNumber KNumber::tgamma() const { KNumber z(*this); if(z > KNumber(QLatin1String("10000000000"))) { return PosInfinity; } z.value_ = z.value_->tgamma(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: asin //------------------------------------------------------------------------------ KNumber KNumber::asin() const { KNumber z(*this); z.value_ = z.value_->asin(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: acos //------------------------------------------------------------------------------ KNumber KNumber::acos() const { KNumber z(*this); z.value_ = z.value_->acos(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: atan //------------------------------------------------------------------------------ KNumber KNumber::atan() const { KNumber z(*this); z.value_ = z.value_->atan(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: sinh //------------------------------------------------------------------------------ KNumber KNumber::sinh() const { KNumber z(*this); z.value_ = z.value_->sinh(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: cosh //------------------------------------------------------------------------------ KNumber KNumber::cosh() const { KNumber z(*this); z.value_ = z.value_->cosh(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: tanh //------------------------------------------------------------------------------ KNumber KNumber::tanh() const { KNumber z(*this); z.value_ = z.value_->tanh(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: asinh //------------------------------------------------------------------------------ KNumber KNumber::asinh() const { KNumber z(*this); z.value_ = z.value_->asinh(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: acosh //------------------------------------------------------------------------------ KNumber KNumber::acosh() const { KNumber z(*this); z.value_ = z.value_->acosh(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: atanh //------------------------------------------------------------------------------ KNumber KNumber::atanh() const { KNumber z(*this); z.value_ = z.value_->atanh(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: factorial //------------------------------------------------------------------------------ KNumber KNumber::factorial() const { KNumber z(*this); // number much bigger than this tend to crash GMP with // an abort if(z > KNumber(QLatin1String("10000000000"))) { return PosInfinity; } z.value_ = z.value_->factorial(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: log2 //------------------------------------------------------------------------------ KNumber KNumber::log2() const { KNumber z(*this); z.value_ = z.value_->log2(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: log10 //------------------------------------------------------------------------------ KNumber KNumber::log10() const { KNumber z(*this); z.value_ = z.value_->log10(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: ln //------------------------------------------------------------------------------ KNumber KNumber::ln() const { KNumber z(*this); z.value_ = z.value_->ln(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: floor //------------------------------------------------------------------------------ KNumber KNumber::floor() const { KNumber z(*this); z.value_ = z.value_->floor(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: ceil //------------------------------------------------------------------------------ KNumber KNumber::ceil() const { KNumber z(*this); z.value_ = z.value_->ceil(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: exp2 //------------------------------------------------------------------------------ KNumber KNumber::exp2() const { KNumber z(*this); z.value_ = z.value_->exp2(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: exp10 //------------------------------------------------------------------------------ KNumber KNumber::exp10() const { KNumber z(*this); z.value_ = z.value_->exp10(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: exp //------------------------------------------------------------------------------ KNumber KNumber::exp() const { KNumber z(*this); z.value_ = z.value_->exp(); z.simplify(); return z; } //------------------------------------------------------------------------------ // Name: bin //------------------------------------------------------------------------------ KNumber KNumber::bin(const KNumber &x) const { KNumber z(*this); z.value_ = z.value_->bin(x.value_); z.simplify(); return z; } diff --git a/knumber/knumber_base.h b/knumber/knumber_base.h index fc888da..150d86f 100644 --- a/knumber/knumber_base.h +++ b/knumber/knumber_base.h @@ -1,118 +1,118 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KNUMBER_BASE_H_ #define KNUMBER_BASE_H_ // Workaround: include before gmp.h to fix build with gcc-4.9 #include #include #ifdef KNUMBER_USE_MPFR #include #endif #include #include namespace detail { class knumber_error; class knumber_integer; class knumber_fraction; class knumber_float; class knumber_base { public: - virtual ~knumber_base() { } + virtual ~knumber_base() = default; public: virtual knumber_base *clone() = 0; public: virtual QString toString(int precision) const = 0; virtual quint64 toUint64() const = 0; virtual qint64 toInt64() const = 0; public: virtual bool is_integer() const = 0; virtual bool is_zero() const = 0; virtual int sign() const = 0; public: // basic math virtual knumber_base *add(knumber_base *rhs) = 0; virtual knumber_base *sub(knumber_base *rhs) = 0; virtual knumber_base *mul(knumber_base *rhs) = 0; virtual knumber_base *div(knumber_base *rhs) = 0; virtual knumber_base *mod(knumber_base *rhs) = 0; public: // logical operators virtual knumber_base *bitwise_and(knumber_base *rhs) = 0; virtual knumber_base *bitwise_xor(knumber_base *rhs) = 0; virtual knumber_base *bitwise_or(knumber_base *rhs) = 0; virtual knumber_base *bitwise_shift(knumber_base *rhs) = 0; public: // algebraic functions virtual knumber_base *pow(knumber_base *rhs) = 0; virtual knumber_base *neg() = 0; virtual knumber_base *cmp() = 0; virtual knumber_base *abs() = 0; virtual knumber_base *sqrt() = 0; virtual knumber_base *cbrt() = 0; virtual knumber_base *factorial() = 0; virtual knumber_base *reciprocal() = 0; public: // special functions virtual knumber_base *log2() = 0; virtual knumber_base *log10() = 0; virtual knumber_base *ln() = 0; virtual knumber_base *exp2() = 0; virtual knumber_base *exp10() = 0; virtual knumber_base *floor() = 0; virtual knumber_base *ceil() = 0; virtual knumber_base *exp() = 0; virtual knumber_base *bin(knumber_base *rhs) = 0; public: // trig functions virtual knumber_base *sin() = 0; virtual knumber_base *cos() = 0; virtual knumber_base *tan() = 0; virtual knumber_base *asin() = 0; virtual knumber_base *acos() = 0; virtual knumber_base *atan() = 0; virtual knumber_base *sinh() = 0; virtual knumber_base *cosh() = 0; virtual knumber_base *tanh() = 0; virtual knumber_base *asinh() = 0; virtual knumber_base *acosh() = 0; virtual knumber_base *atanh() = 0; virtual knumber_base *tgamma() = 0; public: // comparison virtual int compare(knumber_base *rhs) = 0; }; } #endif diff --git a/knumber/knumber_error.h b/knumber/knumber_error.h index 23178c3..65da7a6 100644 --- a/knumber/knumber_error.h +++ b/knumber/knumber_error.h @@ -1,125 +1,125 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KNUMBER_ERROR_H_ #define KNUMBER_ERROR_H_ #include "knumber_base.h" class KNumber; namespace detail { class knumber_error : public knumber_base { friend class ::KNumber; friend class knumber_integer; friend class knumber_fraction; friend class knumber_float; public: enum Error { ERROR_UNDEFINED, ERROR_POS_INFINITY, ERROR_NEG_INFINITY }; public: explicit knumber_error(const QString &s); explicit knumber_error(Error e); knumber_error(); - virtual ~knumber_error(); + ~knumber_error() override; public: QString toString(int precision) const override; quint64 toUint64() const override; qint64 toInt64() const override; public: bool is_integer() const override; bool is_zero() const override; int sign() const override; public: knumber_base *add(knumber_base *rhs) override; knumber_base *sub(knumber_base *rhs) override; knumber_base *mul(knumber_base *rhs) override; knumber_base *div(knumber_base *rhs) override; knumber_base *mod(knumber_base *rhs) override; public: knumber_base *bitwise_and(knumber_base *rhs) override; knumber_base *bitwise_xor(knumber_base *rhs) override; knumber_base *bitwise_or(knumber_base *rhs) override; knumber_base *bitwise_shift(knumber_base *rhs) override; public: knumber_base *pow(knumber_base *rhs) override; knumber_base *neg() override; knumber_base *cmp() override; knumber_base *abs() override; knumber_base *sqrt() override; knumber_base *cbrt() override; knumber_base *factorial() override; knumber_base *reciprocal() override; knumber_base *tgamma() override; public: knumber_base *log2() override; knumber_base *log10() override; knumber_base *ln() override; knumber_base *exp2() override; knumber_base *exp10() override; knumber_base *floor() override; knumber_base *ceil() override; knumber_base *exp() override; knumber_base *bin(knumber_base *rhs) override; public: knumber_base *sin() override; knumber_base *cos() override; knumber_base *tan() override; knumber_base *asin() override; knumber_base *acos() override; knumber_base *atan() override; knumber_base *sinh() override; knumber_base *cosh() override; knumber_base *tanh() override; knumber_base *asinh() override; knumber_base *acosh() override; knumber_base *atanh() override; public: int compare(knumber_base *rhs) override; private: // conversion constructors explicit knumber_error(const knumber_integer *value); explicit knumber_error(const knumber_fraction *value); explicit knumber_error(const knumber_float *value); explicit knumber_error(const knumber_error *value); public: knumber_base *clone() override; private: Error error_; }; } #endif diff --git a/knumber/knumber_float.h b/knumber/knumber_float.h index 1b512c6..f9ed9fc 100644 --- a/knumber/knumber_float.h +++ b/knumber/knumber_float.h @@ -1,135 +1,135 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KNUMBER_FLOAT_H_ #define KNUMBER_FLOAT_H_ #include "knumber_base.h" class KNumber; namespace detail { class knumber_float : public knumber_base { friend class ::KNumber; friend class knumber_error; friend class knumber_integer; friend class knumber_fraction; private: #ifdef KNUMBER_USE_MPFR static const mpfr_rnd_t rounding_mode; static const mpfr_prec_t precision; #endif public: explicit knumber_float(const QString &s); explicit knumber_float(double value); #ifdef HAVE_LONG_DOUBLE explicit knumber_float(long double value); #endif explicit knumber_float(mpf_t mpf); - virtual ~knumber_float(); + ~knumber_float() override; private: // conversion constructors explicit knumber_float(const knumber_integer *value); explicit knumber_float(const knumber_fraction *value); explicit knumber_float(const knumber_float *value); explicit knumber_float(const knumber_error *value); public: QString toString(int precision) const override; quint64 toUint64() const override; qint64 toInt64() const override; public: bool is_integer() const override; bool is_zero() const override; int sign() const override; public: knumber_base *add(knumber_base *rhs) override; knumber_base *sub(knumber_base *rhs) override; knumber_base *mul(knumber_base *rhs) override; knumber_base *div(knumber_base *rhs) override; knumber_base *mod(knumber_base *rhs) override; public: knumber_base *pow(knumber_base *rhs) override; knumber_base *neg() override; knumber_base *cmp() override; knumber_base *abs() override; knumber_base *sqrt() override; knumber_base *cbrt() override; knumber_base *factorial() override; knumber_base *reciprocal() override; knumber_base *tgamma() override; public: knumber_base *log2() override; knumber_base *log10() override; knumber_base *ln() override; knumber_base *floor() override; knumber_base *ceil() override; knumber_base *exp2() override; knumber_base *exp10() override; knumber_base *exp() override; knumber_base *bin(knumber_base *rhs) override; public: knumber_base *sin() override; knumber_base *cos() override; knumber_base *tan() override; knumber_base *asin() override; knumber_base *acos() override; knumber_base *atan() override; knumber_base *sinh() override; knumber_base *cosh() override; knumber_base *tanh() override; knumber_base *asinh() override; knumber_base *acosh() override; knumber_base *atanh() override; public: int compare(knumber_base *rhs) override; public: knumber_base *bitwise_and(knumber_base *rhs) override; knumber_base *bitwise_xor(knumber_base *rhs) override; knumber_base *bitwise_or(knumber_base *rhs) override; knumber_base *bitwise_shift(knumber_base *rhs) override; public: knumber_base *clone() override; private: template knumber_base *execute_libc_func(double x); template knumber_base *execute_libc_func(double x, double y); private: mpf_t mpf_; }; } #endif diff --git a/knumber/knumber_fraction.cpp b/knumber/knumber_fraction.cpp index af2a20c..289cc59 100644 --- a/knumber/knumber_fraction.cpp +++ b/knumber/knumber_fraction.cpp @@ -1,909 +1,909 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "knumber_integer.h" #include "knumber_float.h" #include "knumber_fraction.h" #include "knumber_error.h" #include #include namespace detail { bool knumber_fraction::default_fractional_input = false; bool knumber_fraction::default_fractional_output = true; bool knumber_fraction::split_off_integer_for_fraction_output = false; //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ void knumber_fraction::set_default_fractional_input(bool value) { default_fractional_input = value; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ void knumber_fraction::set_default_fractional_output(bool value) { default_fractional_output = value; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ void knumber_fraction::set_split_off_integer_for_fraction_output(bool value) { split_off_integer_for_fraction_output = value; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_fraction::knumber_fraction(const QString &s) { mpq_init(mpq_); mpq_set_str(mpq_, s.toLatin1().constData(), 10); mpq_canonicalize(mpq_); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_fraction::knumber_fraction(qint64 num, quint64 den) { mpq_init(mpq_); mpq_set_si(mpq_, num, den); mpq_canonicalize(mpq_); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_fraction::knumber_fraction(quint64 num, quint64 den) { mpq_init(mpq_); mpq_set_ui(mpq_, num, den); mpq_canonicalize(mpq_); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_fraction::knumber_fraction(mpq_t mpq) { mpq_init(mpq_); mpq_set(mpq_, mpq); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_fraction::knumber_fraction(const knumber_fraction *value) { mpq_init(mpq_); mpq_set(mpq_, value->mpq_); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_fraction::knumber_fraction(const knumber_integer *value) { mpq_init(mpq_); mpq_set_z(mpq_, value->mpz_); } #if 0 //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_fraction::knumber_fraction(const knumber_float *value) { mpq_init(mpq_); mpq_set_f(mpq_, value->mpf_); } #endif //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::clone() { return new knumber_fraction(this); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_fraction::~knumber_fraction() { mpq_clear(mpq_); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ bool knumber_fraction::is_integer() const { return (mpz_cmp_ui(mpq_denref(mpq_), 1) == 0); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::add(knumber_base *rhs) { if(knumber_integer *const p = dynamic_cast(rhs)) { knumber_fraction q(p); mpq_add(mpq_, mpq_, q.mpq_); return this; } else if(knumber_float *const p = dynamic_cast(rhs)) { knumber_float *f = new knumber_float(this); delete this; return f->add(p); } else if(knumber_fraction *const p = dynamic_cast(rhs)) { mpq_add(mpq_, mpq_, p->mpq_); return this; } else if(knumber_error *const p = dynamic_cast(rhs)) { knumber_error *e = new knumber_error(p); delete this; return e; } Q_ASSERT(0); - return 0; + return nullptr; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::sub(knumber_base *rhs) { if(knumber_integer *const p = dynamic_cast(rhs)) { knumber_fraction q(p); mpq_sub(mpq_, mpq_, q.mpq_); return this; } else if(knumber_float *const p = dynamic_cast(rhs)) { knumber_float *f = new knumber_float(this); delete this; return f->sub(p); } else if(knumber_fraction *const p = dynamic_cast(rhs)) { mpq_sub(mpq_, mpq_, p->mpq_); return this; } else if(knumber_error *const p = dynamic_cast(rhs)) { knumber_error *e = new knumber_error(p); delete this; return e->neg(); } Q_ASSERT(0); - return 0; + return nullptr; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::mul(knumber_base *rhs) { if(knumber_integer *const p = dynamic_cast(rhs)) { knumber_fraction q(p); mpq_mul(mpq_, mpq_, q.mpq_); return this; } else if(knumber_float *const p = dynamic_cast(rhs)) { knumber_float *q = new knumber_float(this); delete this; return q->mul(p); } else if(knumber_fraction *const p = dynamic_cast(rhs)) { mpq_mul(mpq_, mpq_, p->mpq_); return this; } else if(knumber_error *const p = dynamic_cast(rhs)) { if(is_zero()) { delete this; knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED); return e; } if(sign() < 0) { delete this; knumber_error *e = new knumber_error(p); return e->neg(); } else { delete this; knumber_error *e = new knumber_error(p); return e; } } Q_ASSERT(0); - return 0; + return nullptr; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::div(knumber_base *rhs) { if(rhs->is_zero()) { if(sign() < 0) { delete this; return new knumber_error(knumber_error::ERROR_NEG_INFINITY); } else { delete this; return new knumber_error(knumber_error::ERROR_POS_INFINITY); } } if(knumber_integer *const p = dynamic_cast(rhs)) { knumber_fraction f(p); return div(&f); } else if(knumber_float *const p = dynamic_cast(rhs)) { knumber_float *f = new knumber_float(this); delete this; return f->div(p); } else if(knumber_fraction *const p = dynamic_cast(rhs)) { mpq_div(mpq_, mpq_, p->mpq_); return this; } else if(knumber_error *const p = dynamic_cast(rhs)) { if(p->sign() > 0) { delete this; return new knumber_integer(0); } else if(p->sign() < 0) { delete this; return new knumber_integer(0); } knumber_error *e = new knumber_error(p); delete this; return e; } Q_ASSERT(0); - return 0; + return nullptr; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::mod(knumber_base *rhs) { if(rhs->is_zero()) { delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } // NOTE: we don't support modulus operations with non-integer operands mpq_set_d(mpq_, 0); return this; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::bitwise_and(knumber_base *rhs) { Q_UNUSED(rhs); delete this; // NOTE: we don't support bitwise operations with non-integer operands return new knumber_integer(0); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::bitwise_xor(knumber_base *rhs) { Q_UNUSED(rhs); delete this; // NOTE: we don't support bitwise operations with non-integer operands return new knumber_integer(0); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::bitwise_or(knumber_base *rhs) { Q_UNUSED(rhs); delete this; // NOTE: we don't support bitwise operations with non-integer operands return new knumber_integer(0); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::bitwise_shift(knumber_base *rhs) { Q_UNUSED(rhs); delete this; // NOTE: we don't support bitwise operations with non-integer operands return new knumber_error(knumber_error::ERROR_UNDEFINED); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::neg() { mpq_neg(mpq_, mpq_); return this; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::abs() { mpq_abs(mpq_, mpq_); return this; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::cmp() { delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::sqrt() { if(sign() < 0) { delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } if(mpz_perfect_square_p(mpq_numref(mpq_)) && mpz_perfect_square_p(mpq_denref(mpq_))) { mpz_t num; mpz_t den; mpz_init(num); mpz_init(den); mpq_get_num(num, mpq_); mpq_get_den(den, mpq_); mpz_sqrt(num, num); mpz_sqrt(den, den); mpq_set_num(mpq_, num); mpq_set_den(mpq_, den); mpq_canonicalize(mpq_); mpz_clear(num); mpz_clear(den); return this; } else { knumber_float *f = new knumber_float(this); delete this; return f->sqrt(); } } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::cbrt() { // TODO: figure out how to properly use mpq_numref/mpq_denref here mpz_t num; mpz_t den; mpz_init(num); mpz_init(den); mpq_get_num(num, mpq_); mpq_get_den(den, mpq_); if(mpz_root(num, num, 3) && mpz_root(den, den, 3)) { mpq_set_num(mpq_, num); mpq_set_den(mpq_, den); mpq_canonicalize(mpq_); mpz_clear(num); mpz_clear(den); return this; } else { mpz_clear(num); mpz_clear(den); knumber_float *f = new knumber_float(this); delete this; return f->cbrt(); } } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::factorial() { if(sign() < 0) { delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } knumber_integer *i = new knumber_integer(this); delete this; return i->factorial(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::pow(knumber_base *rhs) { // TODO: figure out how to properly use mpq_numref/mpq_denref here if(knumber_integer *const p = dynamic_cast(rhs)) { mpz_t num; mpz_t den; mpz_init(num); mpz_init(den); mpq_get_num(num, mpq_); mpq_get_den(den, mpq_); mpz_pow_ui(num, num, mpz_get_ui(p->mpz_)); mpz_pow_ui(den, den, mpz_get_ui(p->mpz_)); mpq_set_num(mpq_, num); mpq_set_den(mpq_, den); mpq_canonicalize(mpq_); mpz_clear(num); mpz_clear(den); if(p->sign() < 0) { return reciprocal(); } else { return this; } } else if(knumber_float *const p = dynamic_cast(rhs)) { Q_UNUSED(p); knumber_float *f = new knumber_float(this); delete this; return f->pow(rhs); } else if(knumber_fraction *const p = dynamic_cast(rhs)) { // ok, so if any part of the number is > 1,000,000, then we risk // the pow function overflowing... so we'll just convert to float to be safe // TODO: at some point, we should figure out exactly what the threashold is // and if there is a better way to determine if the pow function will // overflow. if(mpz_cmpabs_ui(mpq_numref(mpq_), 1000000) > 0 || mpz_cmpabs_ui(mpq_denref(mpq_), 1000000) > 0 || mpz_cmpabs_ui(mpq_numref(p->mpq_), 1000000) > 0 || mpz_cmpabs_ui(mpq_denref(p->mpq_), 1000000) > 0) { knumber_float *f = new knumber_float(this); delete this; return f->pow(rhs); } mpz_t lhs_num; mpz_t lhs_den; mpz_t rhs_num; mpz_t rhs_den; mpz_init(lhs_num); mpz_init(lhs_den); mpz_init(rhs_num); mpz_init(rhs_den); mpq_get_num(lhs_num, mpq_); mpq_get_den(lhs_den, mpq_); mpq_get_num(rhs_num, p->mpq_); mpq_get_den(rhs_den, p->mpq_); mpz_pow_ui(lhs_num, lhs_num, mpz_get_ui(rhs_num)); mpz_pow_ui(lhs_den, lhs_den, mpz_get_ui(rhs_num)); if(mpz_sgn(lhs_num) < 0 && mpz_even_p(rhs_den)) { mpz_clear(lhs_num); mpz_clear(lhs_den); mpz_clear(rhs_num); mpz_clear(rhs_den); delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } if(mpz_sgn(lhs_den) < 0 && mpz_even_p(rhs_den)) { mpz_clear(lhs_num); mpz_clear(lhs_den); mpz_clear(rhs_num); mpz_clear(rhs_den); delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } const int n1 = mpz_root(lhs_num, lhs_num, mpz_get_ui(rhs_den)); const int n2 = mpz_root(lhs_den, lhs_den, mpz_get_ui(rhs_den)); if(n1 && n2) { mpq_set_num(mpq_, lhs_num); mpq_set_den(mpq_, lhs_den); mpq_canonicalize(mpq_); mpz_clear(lhs_num); mpz_clear(lhs_den); mpz_clear(rhs_num); mpz_clear(rhs_den); if(p->sign() < 0) { return reciprocal(); } else { return this; } } else { mpz_clear(lhs_num); mpz_clear(lhs_den); mpz_clear(rhs_num); mpz_clear(rhs_den); knumber_float *f = new knumber_float(this); delete this; return f->pow(rhs); } } else if(knumber_error *const p = dynamic_cast(rhs)) { if(p->sign() > 0) { knumber_error *e = new knumber_error(knumber_error::ERROR_POS_INFINITY); delete this; return e; } else if(p->sign() < 0) { knumber_integer *n = new knumber_integer(0); delete this; return n; } else { knumber_error *e = new knumber_error(knumber_error::ERROR_UNDEFINED); delete this; return e; } } Q_ASSERT(0); - return 0; + return nullptr; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::sin() { knumber_float *f = new knumber_float(this); delete this; return f->sin(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::floor() { knumber_float *f = new knumber_float(this); delete this; return f->floor(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::ceil() { knumber_float *f = new knumber_float(this); delete this; return f->ceil(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::cos() { knumber_float *f = new knumber_float(this); delete this; return f->cos(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::tgamma() { knumber_float *f = new knumber_float(this); delete this; return f->tgamma(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::tan() { knumber_float *f = new knumber_float(this); delete this; return f->tan(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::asin() { knumber_float *f = new knumber_float(this); delete this; return f->asin(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::acos() { knumber_float *f = new knumber_float(this); delete this; return f->acos(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::atan() { knumber_float *f = new knumber_float(this); delete this; return f->atan(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::sinh() { knumber_float *f = new knumber_float(this); delete this; return f->sinh(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::cosh() { knumber_float *f = new knumber_float(this); delete this; return f->cosh(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::tanh() { knumber_float *f = new knumber_float(this); delete this; return f->tanh(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::asinh() { knumber_float *f = new knumber_float(this); delete this; return f->asinh(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::acosh() { knumber_float *f = new knumber_float(this); delete this; return f->acosh(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::atanh() { knumber_float *f = new knumber_float(this); delete this; return f->atanh(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ int knumber_fraction::compare(knumber_base *rhs) { if(knumber_integer *const p = dynamic_cast(rhs)) { knumber_fraction f(p); return mpq_cmp(mpq_, f.mpq_); } else if(knumber_float *const p = dynamic_cast(rhs)) { knumber_float f(this); return f.compare(p); } else if(knumber_fraction *const p = dynamic_cast(rhs)) { return mpq_cmp(mpq_, p->mpq_); } else if(knumber_error *const p = dynamic_cast(rhs)) { // NOTE: any number compared to NaN/Inf/-Inf always compares less // at the moment return -1; } Q_ASSERT(0); return 0; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ QString knumber_fraction::toString(int precision) const { if(knumber_fraction::default_fractional_output) { // TODO: figure out how to properly use mpq_numref/mpq_denref here knumber_integer integer_part(this); if(split_off_integer_for_fraction_output && !integer_part.is_zero()) { mpz_t num; mpz_init(num); mpq_get_num(num, mpq_); knumber_integer integer_part_1(this); mpz_mul(integer_part.mpz_, integer_part.mpz_, mpq_denref(mpq_)); mpz_sub(num, num, integer_part.mpz_); if(mpz_sgn(num) < 0) { mpz_neg(num, num); } - const size_t size = gmp_snprintf(NULL, 0, "%Zd %Zd/%Zd", integer_part_1.mpz_, num, mpq_denref(mpq_)) + 1; + const size_t size = gmp_snprintf(nullptr, 0, "%Zd %Zd/%Zd", integer_part_1.mpz_, num, mpq_denref(mpq_)) + 1; QScopedArrayPointer buf(new char[size]); gmp_snprintf(&buf[0], size, "%Zd %Zd/%Zd", integer_part_1.mpz_, num, mpq_denref(mpq_)); mpz_clear(num); return QLatin1String(&buf[0]); } else { mpz_t num; mpz_init(num); mpq_get_num(num, mpq_); - const size_t size = gmp_snprintf(NULL, 0, "%Zd/%Zd", num, mpq_denref(mpq_)) + 1; + const size_t size = gmp_snprintf(nullptr, 0, "%Zd/%Zd", num, mpq_denref(mpq_)) + 1; QScopedArrayPointer buf(new char[size]); gmp_snprintf(&buf[0], size, "%Zd/%Zd", num, mpq_denref(mpq_)); mpz_clear(num); return QLatin1String(&buf[0]); } } else { return knumber_float(this).toString(precision); } } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ bool knumber_fraction::is_zero() const { return mpq_sgn(mpq_) == 0; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ int knumber_fraction::sign() const { return mpq_sgn(mpq_); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::reciprocal() { mpq_inv(mpq_, mpq_); return this; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_integer *knumber_fraction::numerator() const { mpz_t num; mpz_init(num); mpq_get_num(num, mpq_); knumber_integer *n = new knumber_integer(num); mpz_clear(num); return n; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_integer *knumber_fraction::denominator() const { mpz_t den; mpz_init(den); mpq_get_den(den, mpq_); knumber_integer *n = new knumber_integer(den); mpz_clear(den); return n; } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::log2() { knumber_float *f = new knumber_float(this); delete this; return f->log2(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::log10() { knumber_float *f = new knumber_float(this); delete this; return f->log10(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::ln() { knumber_float *f = new knumber_float(this); delete this; return f->ln(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::exp2() { knumber_float *f = new knumber_float(this); delete this; return f->exp2(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::exp10() { knumber_float *f = new knumber_float(this); delete this; return f->exp10(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::exp() { knumber_float *f = new knumber_float(this); delete this; return f->exp(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ quint64 knumber_fraction::toUint64() const { return knumber_integer(this).toUint64(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ qint64 knumber_fraction::toInt64() const { return knumber_integer(this).toInt64(); } //------------------------------------------------------------------------------ // Name: //------------------------------------------------------------------------------ knumber_base *knumber_fraction::bin(knumber_base *rhs) { Q_UNUSED(rhs); delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } } diff --git a/knumber/knumber_fraction.h b/knumber/knumber_fraction.h index 4bcf719..490251f 100644 --- a/knumber/knumber_fraction.h +++ b/knumber/knumber_fraction.h @@ -1,137 +1,137 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KNUMBER_FRACTION_H_ #define KNUMBER_FRACTION_H_ #include "knumber_base.h" class KNumber; namespace detail { class knumber_fraction : public knumber_base { friend class ::KNumber; friend class knumber_error; friend class knumber_integer; friend class knumber_float; public: static bool default_fractional_input; static bool default_fractional_output; static bool split_off_integer_for_fraction_output; public: static void set_default_fractional_input(bool value); static void set_default_fractional_output(bool value); static void set_split_off_integer_for_fraction_output(bool value); public: explicit knumber_fraction(const QString &s); knumber_fraction(qint64 num, quint64 den); knumber_fraction(quint64 num, quint64 den); explicit knumber_fraction(mpq_t mpq); - virtual ~knumber_fraction(); + ~knumber_fraction() override; public: knumber_base *clone() override; public: QString toString(int precision) const override; quint64 toUint64() const override; qint64 toInt64() const override; public: bool is_integer() const override; bool is_zero() const override; int sign() const override; public: knumber_base *add(knumber_base *rhs) override; knumber_base *sub(knumber_base *rhs) override; knumber_base *mul(knumber_base *rhs) override; knumber_base *div(knumber_base *rhs) override; knumber_base *mod(knumber_base *rhs) override; public: knumber_base *bitwise_and(knumber_base *rhs) override; knumber_base *bitwise_xor(knumber_base *rhs) override; knumber_base *bitwise_or(knumber_base *rhs) override; knumber_base *bitwise_shift(knumber_base *rhs) override; public: knumber_base *pow(knumber_base *rhs) override; knumber_base *neg() override; knumber_base *cmp() override; knumber_base *abs() override; knumber_base *sqrt() override; knumber_base *cbrt() override; knumber_base *factorial() override; knumber_base *reciprocal() override; knumber_base *tgamma() override; public: knumber_base *log2() override; knumber_base *log10() override; knumber_base *ln() override; knumber_base *exp2() override; knumber_base *floor() override; knumber_base *ceil() override; knumber_base *exp10() override; knumber_base *exp() override; knumber_base *bin(knumber_base *rhs) override; public: knumber_base *sin() override; knumber_base *cos() override; knumber_base *tan() override; knumber_base *asin() override; knumber_base *acos() override; knumber_base *atan() override; knumber_base *sinh() override; knumber_base *cosh() override; knumber_base *tanh() override; knumber_base *asinh() override; knumber_base *acosh() override; knumber_base *atanh() override; public: int compare(knumber_base *rhs) override; private: knumber_integer *numerator() const; knumber_integer *denominator() const; private: // conversion constructors explicit knumber_fraction(const knumber_integer *value); explicit knumber_fraction(const knumber_fraction *value); #if 0 // TODO: this is omitted because there is no good way to // implement it knumber_fraction(const knumber_float *value); #endif explicit knumber_fraction(const knumber_error *value); private: mpq_t mpq_; }; } #endif diff --git a/knumber/knumber_integer.h b/knumber/knumber_integer.h index b9fe52d..f1c9eaf 100644 --- a/knumber/knumber_integer.h +++ b/knumber/knumber_integer.h @@ -1,123 +1,123 @@ /* Copyright (C) 2001 - 2013 Evan Teran evan.teran@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KNUMBER_INTEGER_H_ #define KNUMBER_INTEGER_H_ #include "knumber_base.h" class KNumber; namespace detail { class knumber_integer : public knumber_base { friend class ::KNumber; friend class knumber_error; friend class knumber_fraction; friend class knumber_float; public: explicit knumber_integer(const QString &s); explicit knumber_integer(qint32 value); explicit knumber_integer(qint64 value); explicit knumber_integer(quint32 value); explicit knumber_integer(quint64 value); explicit knumber_integer(mpz_t mpz); - virtual ~knumber_integer(); + ~knumber_integer() override; public: knumber_base *clone() override; public: QString toString(int precision) const override; quint64 toUint64() const override; qint64 toInt64() const override; public: virtual bool is_even() const; virtual bool is_odd() const; bool is_integer() const override; bool is_zero() const override; int sign() const override; public: knumber_base *add(knumber_base *rhs) override; knumber_base *sub(knumber_base *rhs) override; knumber_base *mul(knumber_base *rhs) override; knumber_base *div(knumber_base *rhs) override; knumber_base *mod(knumber_base *rhs) override; public: knumber_base *bitwise_and(knumber_base *rhs) override; knumber_base *bitwise_xor(knumber_base *rhs) override; knumber_base *bitwise_or(knumber_base *rhs) override; knumber_base *bitwise_shift(knumber_base *rhs) override; public: knumber_base *pow(knumber_base *rhs) override; knumber_base *neg() override; knumber_base *cmp() override; knumber_base *abs() override; knumber_base *sqrt() override; knumber_base *cbrt() override; knumber_base *factorial() override; knumber_base *reciprocal() override; public: knumber_base *log2() override; knumber_base *log10() override; knumber_base *ln() override; knumber_base *exp2() override; knumber_base *floor() override; knumber_base *ceil() override; knumber_base *exp10() override; knumber_base *exp() override; knumber_base *bin(knumber_base *rhs) override; public: knumber_base *sin() override; knumber_base *cos() override; knumber_base *tan() override; knumber_base *asin() override; knumber_base *acos() override; knumber_base *atan() override; knumber_base *sinh() override; knumber_base *cosh() override; knumber_base *tanh() override; knumber_base *asinh() override; knumber_base *acosh() override; knumber_base *atanh() override; knumber_base *tgamma() override; public: int compare(knumber_base *rhs) override; private: // conversion constructors explicit knumber_integer(const knumber_integer *value); explicit knumber_integer(const knumber_fraction *value); explicit knumber_integer(const knumber_float *value); explicit knumber_integer(const knumber_error *value); private: mpz_t mpz_; }; } #endif