File indexing completed on 2022-06-05 12:24:02

0001 /*
0002     SPDX-FileCopyrightText: 2001-2013 Evan Teran <evan.teran@gmail.com>
0003     SPDX-FileCopyrightText: 2006 Michel Marti <mma@objectxp.com>
0004     SPDX-FileCopyrightText: 1996-2000 Bernd Johannes Wuebben <wuebben@kde.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "kcalc.h"
0010 #include "kcalc_version.h"
0011 
0012 #include <clocale>
0013 
0014 #include <QActionGroup>
0015 #include <QApplication>
0016 #include <QButtonGroup>
0017 #include <QCommandLineParser>
0018 #include <QCursor>
0019 #include <QKeyEvent>
0020 #include <QMenuBar>
0021 #include <QShortcut>
0022 #include <QStyle>
0023 
0024 #include <KAboutData>
0025 #include <KAcceleratorManager>
0026 #include <KActionCollection>
0027 #include <KColorMimeData>
0028 #include <KConfigDialog>
0029 #include <KCrash>
0030 #include <KStandardAction>
0031 #include <KToggleAction>
0032 #include <KToolBar>
0033 #include <KXMLGUIFactory>
0034 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0035 #include <Kdelibs4ConfigMigrator>
0036 #endif
0037 
0038 #include "kcalc_bitset.h"
0039 #include "kcalc_const_menu.h"
0040 #include "kcalc_settings.h"
0041 #include "kcalc_statusbar.h"
0042 #include "kcalcdisplay.h"
0043 #include "kcalchistory.h"
0044 
0045 namespace
0046 {
0047 const int maxprecision = 1000;
0048 }
0049 
0050 //------------------------------------------------------------------------------
0051 // Name: KCalculator
0052 // Desc: constructor
0053 //------------------------------------------------------------------------------
0054 KCalculator::KCalculator(QWidget *parent)
0055     : KXmlGuiWindow(parent)
0056     , memory_num_(0.0)
0057     , core()
0058 {
0059     // central widget to contain all the elements
0060     auto const central = new QWidget(this);
0061     central->setLayoutDirection(Qt::LeftToRight);
0062     setCentralWidget(central);
0063     KAcceleratorManager::setNoAccel(central);
0064 
0065     // load science constants_ from xml-file
0066     KCalcConstMenu::init_consts();
0067 
0068     // setup interface (order is critical)
0069     setupUi(central);
0070     setupMainActions();
0071     setStatusBar(new KCalcStatusBar(this));
0072     createGUI();
0073     setupKeys();
0074 
0075     toolBar()->hide(); // hide by default
0076 
0077     // create button groups
0078     base_choose_group_ = new QButtonGroup(this);
0079     base_choose_group_->setExclusive(true);
0080     base_choose_group_->addButton(hexRadio, HexMode);
0081     base_choose_group_->addButton(decRadio, DecMode);
0082     base_choose_group_->addButton(octRadio, OctMode);
0083     base_choose_group_->addButton(binRadio, BinMode);
0084     connect(base_choose_group_, qOverload<QAbstractButton *>(&QButtonGroup::buttonClicked), this, &KCalculator::slotBaseSelected);
0085 
0086     base_conversion_labels_ = {binDisplay, hexDisplay, decDisplay, octDisplay};
0087 
0088     angle_choose_group_ = new QButtonGroup(this);
0089     angle_choose_group_->
0090     setExclusive(true);
0091     angle_choose_group_->addButton(degRadio, DegMode);
0092     angle_choose_group_->addButton(radRadio, RadMode);
0093     angle_choose_group_->addButton(gradRadio, GradMode);
0094     connect(angle_choose_group_, qOverload<QAbstractButton *>(&QButtonGroup::buttonClicked), this, &KCalculator::slotAngleSelected);
0095 
0096     // additional menu setup
0097     constants_menu_ = createConstantsMenu();
0098     menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_);
0099 
0100     // misc setup
0101     setColors();
0102     setBaseFont(KCalcSettings::buttonFont());
0103     setFonts();
0104 
0105     // Show the result in the app's caption in taskbar (wishlist - bug #52858)
0106     if (KCalcSettings::captionResult() == true) {
0107         connect(calc_display, &KCalcDisplay::changedText, this, &KCalculator::setWindowTitle);
0108     }
0109 
0110     calc_display->changeSettings();
0111     calc_history->changeSettings();
0112     update_history_window_ = true;
0113     setPrecision();
0114 
0115     updateGeometry();
0116 
0117     // Make window launch at its minimum size
0118     KCalculator::resize(0,0);
0119 
0120     updateDisplay(UPDATE_FROM_CORE);
0121     // clear history, otherwise we have a leading "0" in it
0122     calc_history->clearHistory();
0123 
0124     // misc settings
0125     KCalcSettings::EnumCalculatorMode::type calculatorMode = KCalcSettings::calculatorMode();
0126 
0127     switch (calculatorMode) {
0128     case KCalcSettings::EnumCalculatorMode::science:
0129         action_mode_science_->setChecked(true);
0130         break;
0131     case KCalcSettings::EnumCalculatorMode::statistics:
0132         action_mode_statistic_->setChecked(true);
0133         break;
0134     case KCalcSettings::EnumCalculatorMode::numeral:
0135         action_mode_numeral_->setChecked(true);
0136         break;
0137     case KCalcSettings::EnumCalculatorMode::simple:
0138     default:
0139         action_mode_simple_->setChecked(true);
0140     }
0141     is_still_in_launch_ = false;
0142 
0143     setAngle();
0144     setBase();
0145 
0146     calc_display->setFocus();
0147 }
0148 
0149 //------------------------------------------------------------------------------
0150 // Name: ~KCalculator
0151 // Desc: deconstructor
0152 //------------------------------------------------------------------------------
0153 KCalculator::~KCalculator()
0154 {
0155     KCalcSettings::self()->save();
0156 }
0157 
0158 //------------------------------------------------------------------------------
0159 // Name: setupMainActions
0160 // Desc: connects all of the basic actions
0161 //------------------------------------------------------------------------------
0162 void KCalculator::setupMainActions()
0163 {
0164     // file menu
0165     KStandardAction::quit(this, SLOT(close()), actionCollection());
0166 
0167     // edit menu
0168     KStandardAction::undo(calc_display, SLOT(slotHistoryBack()), actionCollection());
0169     KStandardAction::redo(calc_display, SLOT(slotHistoryForward()), actionCollection());
0170     KStandardAction::cut(calc_display, SLOT(slotCut()), actionCollection());
0171     KStandardAction::copy(calc_display, SLOT(slotCopy()), actionCollection());
0172     KStandardAction::paste(this, SLOT(slotPaste()), actionCollection());
0173 
0174     // mode menu
0175     auto modeGroup = new QActionGroup(this);
0176 
0177     action_mode_simple_ = actionCollection()->add<KToggleAction>(QStringLiteral("mode_simple"));
0178     action_mode_simple_->setActionGroup(modeGroup);
0179     action_mode_simple_->setText(i18n("Simple Mode"));
0180     connect(action_mode_simple_, &KToggleAction::toggled, this, &KCalculator::slotSetSimpleMode);
0181 
0182     action_mode_science_ = actionCollection()->add<KToggleAction>(QStringLiteral("mode_science"));
0183     action_mode_science_->setActionGroup(modeGroup);
0184     action_mode_science_->setText(i18n("Science Mode"));
0185     connect(action_mode_science_, &KToggleAction::toggled, this, &KCalculator::slotSetScienceMode);
0186 
0187     action_mode_statistic_ = actionCollection()->add<KToggleAction>(QStringLiteral("mode_statistics"));
0188     action_mode_statistic_->setActionGroup(modeGroup);
0189     action_mode_statistic_->setText(i18n("Statistic Mode"));
0190     connect(action_mode_statistic_, &KToggleAction::toggled, this, &KCalculator::slotSetStatisticMode);
0191 
0192     action_mode_numeral_ = actionCollection()->add<KToggleAction>(QStringLiteral("mode_numeral"));
0193     action_mode_numeral_->setActionGroup(modeGroup);
0194     action_mode_numeral_->setText(i18n("Numeral System Mode"));
0195     connect(action_mode_numeral_, &KToggleAction::toggled, this, &KCalculator::slotSetNumeralMode);
0196 
0197     // settings menu
0198     action_history_show_ = actionCollection()->add<KToggleAction>(QStringLiteral("show_history"));
0199     action_history_show_->setText(i18n("Show &History"));
0200     action_history_show_->setChecked(true);
0201     actionCollection()->setDefaultShortcut(action_history_show_, Qt::CTRL | Qt::Key_H);
0202     connect(action_history_show_, &KToggleAction::toggled, this, &KCalculator::slotHistoryshow);
0203 
0204     action_constants_show_ = actionCollection()->add<KToggleAction>(QStringLiteral("show_constants"));
0205     action_constants_show_->setText(i18n("Constants &Buttons"));
0206     action_constants_show_->setChecked(true);
0207     connect(action_constants_show_, &KToggleAction::toggled, this, &KCalculator::slotConstantsShow);
0208 
0209     action_bitset_show_ = actionCollection()->add<KToggleAction>(QStringLiteral("show_bitset"));
0210     action_bitset_show_->setText(i18n("Show B&it Edit"));
0211     action_bitset_show_->setChecked(true);
0212     connect(action_bitset_show_, &KToggleAction::toggled, this, &KCalculator::slotBitsetshow);
0213 
0214     KStandardAction::preferences(this, &KCalculator::showSettings, actionCollection());
0215 
0216     KStandardAction::keyBindings(guiFactory(), &KXMLGUIFactory::showConfigureShortcutsDialog, actionCollection());
0217 }
0218 
0219 //------------------------------------------------------------------------------
0220 // Name: createConstantsMenu
0221 // Desc: creates and returns a pointer to the constant menu
0222 //------------------------------------------------------------------------------
0223 KCalcConstMenu *KCalculator::createConstantsMenu()
0224 {
0225     auto const menu = new KCalcConstMenu(i18n("&Constants"), this);
0226     connect(menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotConstantToDisplay);
0227     return menu;
0228 }
0229 
0230 //------------------------------------------------------------------------------
0231 // Name: statusBar
0232 // Desc: returns a pointer to the status bar
0233 //------------------------------------------------------------------------------
0234 KCalcStatusBar *KCalculator::statusBar()
0235 {
0236     return static_cast<KCalcStatusBar *>(KXmlGuiWindow::statusBar());
0237 }
0238 
0239 //------------------------------------------------------------------------------
0240 // Name: setupNumberKeys
0241 // Desc: sets up number keys and related shortcuts
0242 //------------------------------------------------------------------------------
0243 void KCalculator::setupNumberKeys()
0244 {
0245     num_button_group_ = new QButtonGroup(this);
0246     connect(num_button_group_, qOverload<QAbstractButton *>(&QButtonGroup::buttonClicked), this, &KCalculator::slotNumberclicked);
0247 
0248     num_button_group_->addButton(pb0, 0);
0249     num_button_group_->addButton(pb1, 1);
0250     num_button_group_->addButton(pb2, 2);
0251     num_button_group_->addButton(pb3, 3);
0252     num_button_group_->addButton(pb4, 4);
0253     num_button_group_->addButton(pb5, 5);
0254     num_button_group_->addButton(pb6, 6);
0255     num_button_group_->addButton(pb7, 7);
0256     num_button_group_->addButton(pb8, 8);
0257     num_button_group_->addButton(pb9, 9);
0258     num_button_group_->addButton(pbA, 0xA);
0259     num_button_group_->addButton(pbB, 0xB);
0260     num_button_group_->addButton(pbC, 0xC);
0261     num_button_group_->addButton(pbD, 0xD);
0262     num_button_group_->addButton(pbE, 0xE);
0263     num_button_group_->addButton(pbF, 0xF);
0264     connect(this, &KCalculator::switchShowAccels, pb0, &KCalcButton::slotSetAccelDisplayMode);
0265     connect(this, &KCalculator::switchShowAccels, pb1, &KCalcButton::slotSetAccelDisplayMode);
0266     connect(this, &KCalculator::switchShowAccels, pb2, &KCalcButton::slotSetAccelDisplayMode);
0267     connect(this, &KCalculator::switchShowAccels, pb3, &KCalcButton::slotSetAccelDisplayMode);
0268     connect(this, &KCalculator::switchShowAccels, pb4, &KCalcButton::slotSetAccelDisplayMode);
0269     connect(this, &KCalculator::switchShowAccels, pb5, &KCalcButton::slotSetAccelDisplayMode);
0270     connect(this, &KCalculator::switchShowAccels, pb6, &KCalcButton::slotSetAccelDisplayMode);
0271     connect(this, &KCalculator::switchShowAccels, pb7, &KCalcButton::slotSetAccelDisplayMode);
0272     connect(this, &KCalculator::switchShowAccels, pb8, &KCalcButton::slotSetAccelDisplayMode);
0273     connect(this, &KCalculator::switchShowAccels, pb9, &KCalcButton::slotSetAccelDisplayMode);
0274     connect(this, &KCalculator::switchShowAccels, pbA, &KCalcButton::slotSetAccelDisplayMode);
0275     connect(this, &KCalculator::switchShowAccels, pbB, &KCalcButton::slotSetAccelDisplayMode);
0276     connect(this, &KCalculator::switchShowAccels, pbC, &KCalcButton::slotSetAccelDisplayMode);
0277     connect(this, &KCalculator::switchShowAccels, pbD, &KCalcButton::slotSetAccelDisplayMode);
0278     connect(this, &KCalculator::switchShowAccels, pbE, &KCalcButton::slotSetAccelDisplayMode);
0279     connect(this, &KCalculator::switchShowAccels, pbF, &KCalcButton::slotSetAccelDisplayMode);
0280 }
0281 
0282 //------------------------------------------------------------------------------
0283 // Name: setupRightKeypad
0284 // Desc: sets up right keypad keys and related shortcuts
0285 //------------------------------------------------------------------------------
0286 void KCalculator::setupRightKeypad()
0287 {
0288     connect(pbShift, &KCalcButton::toggled, this, &KCalculator::slotShifttoggled);
0289     connect(this, &KCalculator::switchShowAccels, pbShift, &KCalcButton::slotSetAccelDisplayMode);
0290 
0291     pbBackspace->setShortcut(QKeySequence(Qt::Key_Backspace));
0292     new QShortcut(Qt::Key_PageUp, pbBackspace, SLOT(animateClick()));
0293     connect(pbBackspace, &KCalcButton::clicked, this, &KCalculator::slotBackspaceclicked);
0294     connect(this, &KCalculator::switchShowAccels, pbBackspace, &KCalcButton::slotSetAccelDisplayMode);
0295 
0296     pbClear->setShortcut(QKeySequence(Qt::Key_Escape));
0297     new QShortcut(Qt::Key_PageUp, pbClear, SLOT(animateClick()));
0298     connect(pbClear, &KCalcButton::clicked, this, &KCalculator::slotClearclicked);
0299     connect(this, &KCalculator::switchShowAccels, pbClear, &KCalcButton::slotSetAccelDisplayMode);
0300 
0301     pbAllClear->setShortcut(QKeySequence(Qt::Key_Delete));
0302     new QShortcut(Qt::Key_PageDown, pbAllClear, SLOT(animateClick()));
0303     connect(pbAllClear, &KCalcButton::clicked, this, &KCalculator::slotAllClearclicked);
0304     connect(this, &KCalculator::switchShowAccels, pbAllClear, &KCalcButton::slotSetAccelDisplayMode);
0305     // also clear the content of the history when clicked
0306     connect(pbAllClear, &KCalcButton::clicked, calc_history, &KCalcHistory::clearHistory);
0307 
0308     pbParenOpen->setShortcut(QKeySequence(Qt::Key_ParenLeft));
0309     connect(pbParenOpen, &KCalcButton::clicked, this, &KCalculator::slotParenOpenclicked);
0310     connect(this, &KCalculator::switchShowAccels, pbParenOpen, &KCalcButton::slotSetAccelDisplayMode);
0311 
0312     pbParenClose->setShortcut(QKeySequence(Qt::Key_ParenRight));
0313     connect(pbParenClose, &KCalcButton::clicked, this, &KCalculator::slotParenCloseclicked);
0314     connect(this, &KCalculator::switchShowAccels, pbParenClose, &KCalcButton::slotSetAccelDisplayMode);
0315 
0316     pbMemRecall->setDisabled(true); // nothing in memory at start
0317     connect(pbMemRecall, &KCalcButton::clicked, this, &KCalculator::slotMemRecallclicked);
0318     connect(this, &KCalculator::switchShowAccels, pbMemRecall, &KCalcButton::slotSetAccelDisplayMode);
0319 
0320     connect(pbMemClear, &KCalcButton::clicked, this, &KCalculator::slotMemClearclicked);
0321     connect(this, &KCalculator::switchShowAccels, pbMemClear, &KCalcButton::slotSetAccelDisplayMode);
0322 
0323     pbMemPlusMinus->addMode(ModeNormal, i18nc("Add display to memory", "M+"), i18n("Add display to memory"));
0324     pbMemPlusMinus->addMode(ModeShift, i18nc("Subtract from memory", "M\xe2\x88\x92"), i18n("Subtract from memory"));
0325     connect(pbMemPlusMinus, &KCalcButton::clicked, this, &KCalculator::slotMemPlusMinusclicked);
0326     connect(this, &KCalculator::switchShowAccels, pbMemPlusMinus, &KCalcButton::slotSetAccelDisplayMode);
0327     connect(this, &KCalculator::switchMode, pbMemPlusMinus, &KCalcButton::slotSetMode);
0328 
0329     connect(pbMemStore, &KCalcButton::clicked, this, &KCalculator::slotMemStoreclicked);
0330     connect(this, &KCalculator::switchShowAccels, pbMemStore, &KCalcButton::slotSetAccelDisplayMode);
0331 
0332     pbPercent->setShortcut(QKeySequence(Qt::Key_Percent));
0333     connect(pbPercent, &KCalcButton::clicked, this, &KCalculator::slotPercentclicked);
0334     connect(this, &KCalculator::switchShowAccels, pbPercent, &KCalcButton::slotSetAccelDisplayMode);
0335 
0336     pbPlusMinus->setShortcut(QKeySequence(Qt::Key_Backslash));
0337     connect(pbPlusMinus, &KCalcButton::clicked, this, &KCalculator::slotPlusMinusclicked);
0338     connect(this, &KCalculator::switchShowAccels, pbPlusMinus, &KCalcButton::slotSetAccelDisplayMode);
0339 }
0340 
0341 //------------------------------------------------------------------------------
0342 // Name: setupNumericKeypad
0343 // Desc: sets up numeric keys and related shortcuts
0344 //------------------------------------------------------------------------------
0345 void KCalculator::setupNumericKeypad()
0346 {
0347     pbCube->addMode(ModeNormal, i18nc("Third power", "x<sup>3</sup>"), i18n("Third power"));
0348     pbCube->addMode(ModeShift, QStringLiteral("<sup>3</sup>&radic;x"), i18n("Cube root"));
0349     connect(pbCube, &KCalcButton::clicked, this, &KCalculator::slotCubeclicked);
0350     connect(this, &KCalculator::switchShowAccels, pbCube, &KCalcButton::slotSetAccelDisplayMode);
0351     connect(this, &KCalculator::switchMode, pbCube, &KCalcButton::slotSetMode);
0352 
0353     pbDivision->setShortcut(QKeySequence(Qt::Key_Slash));
0354     new QShortcut(Qt::Key_division, pbDivision, SLOT(animateClick()));
0355     connect(pbDivision, &KCalcButton::clicked, this, &KCalculator::slotDivisionclicked);
0356     connect(this, &KCalculator::switchShowAccels, pbDivision, &KCalcButton::slotSetAccelDisplayMode);
0357 
0358     pbMultiplication->setShortcut(QKeySequence(Qt::Key_Asterisk));
0359     new QShortcut(Qt::Key_X, pbMultiplication, SLOT(animateClick()));
0360     new QShortcut(Qt::Key_multiply, pbMultiplication, SLOT(animateClick()));
0361     connect(pbMultiplication, &KCalcButton::clicked, this, &KCalculator::slotMultiplicationclicked);
0362     connect(this, &KCalculator::switchShowAccels, pbMultiplication, &KCalcButton::slotSetAccelDisplayMode);
0363 
0364     pbMinus->setShortcut(QKeySequence(Qt::Key_Minus));
0365     connect(pbMinus, &KCalcButton::clicked, this, &KCalculator::slotMinusclicked);
0366     connect(this, &KCalculator::switchShowAccels, pbMinus, &KCalcButton::slotSetAccelDisplayMode);
0367 
0368     pbPlus->setShortcut(QKeySequence(Qt::Key_Plus));
0369     connect(pbPlus, &KCalcButton::clicked, this, &KCalculator::slotPlusclicked);
0370     connect(this, &KCalculator::switchShowAccels, pbPlus, &KCalcButton::slotSetAccelDisplayMode);
0371 
0372     // set decimal separator from locale
0373     pbPeriod->setText(QString(QLocale().decimalPoint()));
0374     pbPeriod->setShortcut(QString(QLocale().decimalPoint()));
0375 
0376     // add shortcut for the other decimal separator (point or comma)
0377     if (QLocale().decimalPoint() == QLatin1Char('.')) {
0378         new QShortcut(Qt::Key_Comma, pbPeriod, SLOT(animateClick()));
0379     } else if (QLocale().decimalPoint() == QLatin1Char(',')) {
0380         new QShortcut(Qt::Key_Period, pbPeriod, SLOT(animateClick()));
0381     }
0382 
0383     connect(pbPeriod, &KCalcButton::clicked, this, &KCalculator::slotPeriodclicked);
0384     connect(this, &KCalculator::switchShowAccels, pbPeriod, &KCalcButton::slotSetAccelDisplayMode);
0385 
0386     pbEqual->setShortcut(QKeySequence(Qt::Key_Enter));
0387     new QShortcut(Qt::Key_Equal, pbEqual, SLOT(animateClick()));
0388     new QShortcut(Qt::Key_Return, pbEqual, SLOT(animateClick()));
0389     connect(pbEqual, &KCalcButton::clicked, this, &KCalculator::slotEqualclicked);
0390     connect(this, &KCalculator::switchShowAccels, pbEqual, &KCalcButton::slotSetAccelDisplayMode);
0391 }
0392 
0393 //------------------------------------------------------------------------------
0394 // Name: setupLogicKeys
0395 // Desc: sets up logic keys and related shortcuts
0396 //------------------------------------------------------------------------------
0397 void KCalculator::setupLogicKeys()
0398 {
0399     logic_buttons_.append(pbAND);
0400     logic_buttons_.append(pbOR);
0401     logic_buttons_.append(pbXOR);
0402     logic_buttons_.append(pbLsh);
0403     logic_buttons_.append(pbRsh);
0404     logic_buttons_.append(pbCmp);
0405 
0406     pbAND->setShortcut(QKeySequence(Qt::Key_Ampersand));
0407     connect(this, &KCalculator::switchShowAccels, pbAND, &KCalcButton::slotSetAccelDisplayMode);
0408     connect(pbAND, &KCalcButton::clicked, this, &KCalculator::slotANDclicked);
0409 
0410     pbOR->setShortcut(QKeySequence(Qt::Key_Bar));
0411     connect(this, &KCalculator::switchShowAccels, pbOR, &KCalcButton::slotSetAccelDisplayMode);
0412     connect(pbOR, &KCalcButton::clicked, this, &KCalculator::slotORclicked);
0413 
0414     connect(this, &KCalculator::switchShowAccels, pbXOR, &KCalcButton::slotSetAccelDisplayMode);
0415     connect(pbXOR, &KCalcButton::clicked, this, &KCalculator::slotXORclicked);
0416 
0417     pbLsh->setShortcut(QKeySequence(Qt::Key_Less));
0418     connect(this, &KCalculator::switchShowAccels, pbLsh, &KCalcButton::slotSetAccelDisplayMode);
0419     connect(pbLsh, &KCalcButton::clicked, this, &KCalculator::slotLeftShiftclicked);
0420 
0421     pbRsh->setShortcut(QKeySequence(Qt::Key_Greater));
0422     connect(this, &KCalculator::switchShowAccels, pbRsh, &KCalcButton::slotSetAccelDisplayMode);
0423     connect(pbRsh, &KCalcButton::clicked, this, &KCalculator::slotRightShiftclicked);
0424 
0425     pbCmp->setShortcut(QKeySequence(Qt::Key_AsciiTilde));
0426     connect(this, &KCalculator::switchShowAccels, pbCmp, &KCalcButton::slotSetAccelDisplayMode);
0427     connect(pbCmp, &KCalcButton::clicked, this, &KCalculator::slotNegateclicked);
0428 }
0429 
0430 //------------------------------------------------------------------------------
0431 // Name: setupLogicKeys
0432 // Desc: sets up scientific keys and related shortcuts
0433 //------------------------------------------------------------------------------
0434 void KCalculator::setupScientificKeys()
0435 {
0436     scientific_buttons_.append(pbHyp);
0437     scientific_buttons_.append(pbSin);
0438     scientific_buttons_.append(pbCos);
0439     scientific_buttons_.append(pbTan);
0440     scientific_buttons_.append(pbLog);
0441     scientific_buttons_.append(pbLn);
0442 
0443     connect(this, &KCalculator::switchShowAccels, pbHyp, &KCalcButton::slotSetAccelDisplayMode);
0444     connect(pbHyp, &KCalcButton::toggled, this, &KCalculator::slotHyptoggled);
0445 
0446     pbSin->addMode(ModeNormal, i18nc("Sine", "sin"), i18n("Sine"));
0447     pbSin->addMode(ModeShift, i18nc("Arc sine", "asin"), i18n("Arc sine"));
0448     pbSin->addMode(ModeHyperbolic, i18nc("Hyperbolic sine", "sinh"), i18n("Hyperbolic sine"));
0449     pbSin->addMode(ButtonModeFlags(ModeShift | ModeHyperbolic), i18nc("Inverse hyperbolic sine", "asinh"), i18n("Inverse hyperbolic sine"));
0450     connect(this, &KCalculator::switchShowAccels, pbSin, &KCalcButton::slotSetAccelDisplayMode);
0451     connect(this, &KCalculator::switchMode, pbSin, &KCalcButton::slotSetMode);
0452     connect(pbSin, &KCalcButton::clicked, this, &KCalculator::slotSinclicked);
0453 
0454     pbCos->addMode(ModeNormal, i18nc("Cosine", "cos"), i18n("Cosine"));
0455     pbCos->addMode(ModeShift, i18nc("Arc cosine", "acos"), i18n("Arc cosine"));
0456     pbCos->addMode(ModeHyperbolic, i18nc("Hyperbolic cosine", "cosh"), i18n("Hyperbolic cosine"));
0457     pbCos->addMode(ButtonModeFlags(ModeShift | ModeHyperbolic), i18nc("Inverse hyperbolic cosine", "acosh"), i18n("Inverse hyperbolic cosine"));
0458     connect(this, &KCalculator::switchShowAccels, pbCos, &KCalcButton::slotSetAccelDisplayMode);
0459     connect(this, &KCalculator::switchMode, pbCos, &KCalcButton::slotSetMode);
0460     connect(pbCos, &KCalcButton::clicked, this, &KCalculator::slotCosclicked);
0461 
0462     pbTan->addMode(ModeNormal, i18nc("Tangent", "tan"), i18n("Tangent"));
0463     pbTan->addMode(ModeShift, i18nc("Arc tangent", "atan"), i18n("Arc tangent"));
0464     pbTan->addMode(ModeHyperbolic, i18nc("Hyperbolic tangent", "tanh"), i18n("Hyperbolic tangent"));
0465     pbTan->addMode(ButtonModeFlags(ModeShift | ModeHyperbolic), i18nc("Inverse hyperbolic tangent", "atanh"), i18n("Inverse hyperbolic tangent"));
0466     connect(this, &KCalculator::switchShowAccels, pbTan, &KCalcButton::slotSetAccelDisplayMode);
0467     connect(this, &KCalculator::switchMode, pbTan, &KCalcButton::slotSetMode);
0468     connect(pbTan, &KCalcButton::clicked, this, &KCalculator::slotTanclicked);
0469 
0470     pbLog->addMode(ModeNormal, i18nc("Logarithm to base 10", "log"), i18n("Logarithm to base 10"));
0471     pbLog->addMode(ModeShift, i18nc("10 to the power of x", "10<sup>x</sup>"), i18n("10 to the power of x"));
0472     connect(this, &KCalculator::switchShowAccels, pbLog, &KCalcButton::slotSetAccelDisplayMode);
0473     connect(this, &KCalculator::switchMode, pbLog, &KCalcButton::slotSetMode);
0474     connect(pbLog, &KCalcButton::clicked, this, &KCalculator::slotLogclicked);
0475     pbLn->addMode(ModeNormal, i18nc("Natural log", "ln"), i18n("Natural log"));
0476     pbLn->addMode(ModeShift, i18nc("Exponential function", "e<sup>x</sup>"), i18n("Exponential function"));
0477     connect(this, &KCalculator::switchShowAccels, pbLn, &KCalcButton::slotSetAccelDisplayMode);
0478     connect(this, &KCalculator::switchMode, pbLn, &KCalcButton::slotSetMode);
0479     connect(pbLn, &KCalcButton::clicked, this, &KCalculator::slotLnclicked);
0480 }
0481 
0482 //------------------------------------------------------------------------------
0483 // Name: setupStatisticKeys
0484 // Desc: sets up statistical keys and related shortcuts
0485 //------------------------------------------------------------------------------
0486 void KCalculator::setupStatisticKeys()
0487 {
0488     stat_buttons_.append(pbNData);
0489     stat_buttons_.append(pbMean);
0490     stat_buttons_.append(pbSd);
0491     stat_buttons_.append(pbMed);
0492     stat_buttons_.append(pbDat);
0493     stat_buttons_.append(pbCSt);
0494 
0495     pbNData->addMode(ModeNormal, i18nc("Number of data entered", "N"), i18n("Number of data entered"));
0496     pbNData->addMode(ModeShift, QString::fromUtf8("\xce\xa3") + QLatin1Char('x'), i18n("Sum of all data items"));
0497     connect(this, &KCalculator::switchShowAccels, pbNData, &KCalcButton::slotSetAccelDisplayMode);
0498     connect(this, &KCalculator::switchMode, pbNData, &KCalcButton::slotSetMode);
0499     connect(pbNData, &KCalcButton::clicked, this, &KCalculator::slotStatNumclicked);
0500 
0501     pbMean->addMode(ModeNormal, i18nc("Mean", "Mea"), i18n("Mean"));
0502     pbMean->addMode(ModeShift, QString::fromUtf8("\xce\xa3") + QLatin1String("x<sup>2</sup>"), i18n("Sum of all data items squared"));
0503     connect(this, &KCalculator::switchShowAccels, pbMean, &KCalcButton::slotSetAccelDisplayMode);
0504     connect(this, &KCalculator::switchMode, pbMean, &KCalcButton::slotSetMode);
0505     connect(pbMean, &KCalcButton::clicked, this, &KCalculator::slotStatMeanclicked);
0506 
0507     pbSd->addMode(ModeNormal, QString::fromUtf8("\xcf\x83") + QLatin1String("<sub>N</sub>"), i18n("Standard deviation"));
0508     pbSd->addMode(ModeShift, QString::fromUtf8("\xcf\x83") + QLatin1String("<sub>N-1</sub>"), i18n("Sample standard deviation"));
0509     connect(this, &KCalculator::switchShowAccels, pbSd, &KCalcButton::slotSetAccelDisplayMode);
0510     connect(this, &KCalculator::switchMode, pbSd, &KCalcButton::slotSetMode);
0511     connect(pbSd, &KCalcButton::clicked, this, &KCalculator::slotStatStdDevclicked);
0512 
0513     connect(this, &KCalculator::switchShowAccels, pbMed, &KCalcButton::slotSetAccelDisplayMode);
0514     connect(pbMed, &KCalcButton::clicked, this, &KCalculator::slotStatMedianclicked);
0515 
0516     pbDat->addMode(ModeNormal, i18nc("Enter data", "Dat"), i18n("Enter data"));
0517     pbDat->addMode(ModeShift, i18nc("Delete last data item", "CDat"), i18n("Delete last data item"));
0518     connect(this, &KCalculator::switchShowAccels, pbDat, &KCalcButton::slotSetAccelDisplayMode);
0519     connect(this, &KCalculator::switchMode, pbDat, &KCalcButton::slotSetMode);
0520     connect(pbDat, &KCalcButton::clicked, this, &KCalculator::slotStatDataInputclicked);
0521 
0522     connect(this, &KCalculator::switchShowAccels, pbCSt, &KCalcButton::slotSetAccelDisplayMode);
0523     connect(pbCSt, &KCalcButton::clicked, this, &KCalculator::slotStatClearDataclicked);
0524 }
0525 
0526 //------------------------------------------------------------------------------
0527 // Name: setupConstantsKeys
0528 // Desc: sets up constants keys and related shortcuts
0529 //------------------------------------------------------------------------------
0530 void KCalculator::setupConstantsKeys()
0531 {
0532     const_buttons_.append(pbC1);
0533     const_buttons_.append(pbC2);
0534     const_buttons_.append(pbC3);
0535     const_buttons_.append(pbC4);
0536     const_buttons_.append(pbC5);
0537     const_buttons_.append(pbC6);
0538 
0539     pbC1->setButtonNumber(0);
0540     connect(this, &KCalculator::switchShowAccels, pbC1, &KCalcConstButton::slotSetAccelDisplayMode);
0541     connect(this, &KCalculator::switchMode, pbC1, &KCalcConstButton::slotSetMode);
0542     connect(pbC1, &KCalcConstButton::constButtonClicked, this, &KCalculator::slotConstclicked);
0543 
0544     pbC2->setButtonNumber(1);
0545     connect(this, &KCalculator::switchShowAccels, pbC2, &KCalcConstButton::slotSetAccelDisplayMode);
0546     connect(this, &KCalculator::switchMode, pbC2, &KCalcConstButton::slotSetMode);
0547     connect(pbC2, &KCalcConstButton::constButtonClicked, this, &KCalculator::slotConstclicked);
0548 
0549     pbC3->setButtonNumber(2);
0550     connect(this, &KCalculator::switchShowAccels, pbC3, &KCalcConstButton::slotSetAccelDisplayMode);
0551     connect(this, &KCalculator::switchMode, pbC3, &KCalcConstButton::slotSetMode);
0552     connect(pbC3, &KCalcConstButton::constButtonClicked, this, &KCalculator::slotConstclicked);
0553 
0554     pbC4->setButtonNumber(3);
0555     connect(this, &KCalculator::switchShowAccels, pbC4, &KCalcConstButton::slotSetAccelDisplayMode);
0556     connect(this, &KCalculator::switchMode, pbC4, &KCalcConstButton::slotSetMode);
0557     connect(pbC4, &KCalcConstButton::constButtonClicked, this, &KCalculator::slotConstclicked);
0558 
0559     pbC5->setButtonNumber(4);
0560     connect(this, &KCalculator::switchShowAccels, pbC5, &KCalcConstButton::slotSetAccelDisplayMode);
0561     connect(this, &KCalculator::switchMode, pbC5, &KCalcConstButton::slotSetMode);
0562     connect(pbC5, &KCalcConstButton::constButtonClicked, this, &KCalculator::slotConstclicked);
0563 
0564     pbC6->setButtonNumber(5);
0565     connect(this, &KCalculator::switchShowAccels, pbC6, &KCalcConstButton::slotSetAccelDisplayMode);
0566     connect(this, &KCalculator::switchMode, pbC6, &KCalcConstButton::slotSetMode);
0567     connect(pbC6, &KCalcConstButton::constButtonClicked, this, &KCalculator::slotConstclicked);
0568 
0569     changeButtonNames();
0570 }
0571 
0572 //------------------------------------------------------------------------------
0573 // Name: setupMiscKeys
0574 // Desc: sets up misc keys and related shortcuts
0575 //------------------------------------------------------------------------------
0576 void KCalculator::setupMiscKeys()
0577 {
0578     pbMod->addMode(ModeNormal, i18nc("Modulo", "mod"), i18n("Modulo"));
0579     pbMod->addMode(ModeShift, i18nc("Integer division", "IntDiv"), i18n("Integer division"));
0580     connect(this, &KCalculator::switchMode, pbMod, &KCalcButton::slotSetMode);
0581     connect(this, &KCalculator::switchShowAccels, pbMod, &KCalcButton::slotSetAccelDisplayMode);
0582     pbMod->setShortcut(QKeySequence(Qt::Key_Colon));
0583     connect(pbMod, &KCalcButton::clicked, this, &KCalculator::slotModclicked);
0584 
0585     pbReci->addMode(ModeNormal, i18nc("Reciprocal", "1/x"), i18n("Reciprocal"));
0586     pbReci->addMode(ModeShift, i18nc("n Choose m", "nCm"), i18n("n Choose m"));
0587     connect(this, &KCalculator::switchMode, pbReci, &KCalcButton::slotSetMode);
0588     connect(this, &KCalculator::switchShowAccels, pbReci, &KCalcButton::slotSetAccelDisplayMode);
0589     connect(pbReci, &KCalcButton::clicked, this, &KCalculator::slotReciclicked);
0590 
0591     pbFactorial->addMode(ModeNormal, i18nc("Factorial", "x!"), i18n("Factorial"));
0592     pbFactorial->addMode(ModeShift, QStringLiteral("&#915;"), i18n("Gamma"));
0593     pbFactorial->setShortcut(QKeySequence(Qt::Key_Exclam));
0594     connect(this, &KCalculator::switchShowAccels, pbFactorial, &KCalcButton::slotSetAccelDisplayMode);
0595     connect(this, &KCalculator::switchMode, pbFactorial, &KCalcButton::slotSetMode);
0596     connect(pbFactorial, &KCalcButton::clicked, this, &KCalculator::slotFactorialclicked);
0597 
0598     pbSquare->addMode(ModeNormal, i18nc("Square", "x<sup>2</sup>"), i18n("Square"));
0599     pbSquare->addMode(ModeShift, QStringLiteral("&radic;x"), i18n("Square root"));
0600     pbSquare->setShortcut(QKeySequence(Qt::Key_BracketLeft));
0601     new QShortcut(Qt::Key_twosuperior, pbSquare, SLOT(animateClick()));
0602     connect(this, &KCalculator::switchShowAccels, pbSquare, &KCalcButton::slotSetAccelDisplayMode);
0603     connect(this, &KCalculator::switchMode, pbSquare, &KCalcButton::slotSetMode);
0604     connect(pbSquare, &KCalcButton::clicked, this, &KCalculator::slotSquareclicked);
0605 
0606     pbPower->addMode(ModeNormal, i18nc("x to the power of y", "x<sup>y</sup>"), i18n("x to the power of y"));
0607     pbPower->addMode(ModeShift, i18nc("x to the power of 1/y", "x<sup>1/y</sup>"), i18n("x to the power of 1/y"));
0608     connect(this, &KCalculator::switchShowAccels, pbPower, &KCalcButton::slotSetAccelDisplayMode);
0609     connect(this, &KCalculator::switchMode, pbPower, &KCalcButton::slotSetMode);
0610     pbPower->setShortcut(QKeySequence(Qt::Key_AsciiCircum));
0611     connect(pbPower, &KCalcButton::clicked, this, &KCalculator::slotPowerclicked);
0612 
0613     pbEE->addMode(ModeNormal,
0614                   QStringLiteral("x<small>"
0615                                  "\xb7"
0616                                  "10</small><sup>y</sup>"),
0617                   i18n("Exponent"));
0618     connect(this, &KCalculator::switchShowAccels, pbEE, &KCalcButton::slotSetAccelDisplayMode);
0619     connect(pbEE, &KCalcButton::clicked, this, &KCalculator::slotEEclicked);
0620 }
0621 
0622 //------------------------------------------------------------------------------
0623 // Name: createConstantsMenu
0624 // Desc: additional setup for button keys
0625 // NOTE: all alphanumeric shorts set in ui file
0626 //------------------------------------------------------------------------------
0627 void KCalculator::setupKeys()
0628 {
0629     setupNumberKeys();
0630     setupRightKeypad();
0631     setupNumericKeypad();
0632     setupLogicKeys();
0633     setupScientificKeys();
0634     setupStatisticKeys();
0635     setupConstantsKeys();
0636     setupMiscKeys();
0637 
0638     // other button lists
0639 
0640     function_button_list_.append(pbHyp);
0641     function_button_list_.append(pbShift);
0642     function_button_list_.append(pbEE);
0643     function_button_list_.append(pbSin);
0644     function_button_list_.append(pbPlusMinus);
0645     function_button_list_.append(pbCos);
0646     function_button_list_.append(pbReci);
0647     function_button_list_.append(pbTan);
0648     function_button_list_.append(pbFactorial);
0649     function_button_list_.append(pbLog);
0650     function_button_list_.append(pbSquare);
0651     function_button_list_.append(pbLn);
0652     function_button_list_.append(pbPower);
0653     function_button_list_.append(pbCube);
0654 
0655     mem_button_list_.append(pbMemRecall);
0656     mem_button_list_.append(pbMemPlusMinus);
0657     mem_button_list_.append(pbMemStore);
0658     mem_button_list_.append(pbMemClear);
0659     mem_button_list_.append(pbClear);
0660     mem_button_list_.append(pbAllClear);
0661     mem_button_list_.append(pbBackspace);
0662 
0663     operation_button_list_.append(pbMultiplication);
0664     operation_button_list_.append(pbParenOpen);
0665     operation_button_list_.append(pbParenClose);
0666     operation_button_list_.append(pbAND);
0667     operation_button_list_.append(pbDivision);
0668     operation_button_list_.append(pbOR);
0669     operation_button_list_.append(pbXOR);
0670     operation_button_list_.append(pbPlus);
0671     operation_button_list_.append(pbMinus);
0672     operation_button_list_.append(pbLsh);
0673     operation_button_list_.append(pbRsh);
0674     operation_button_list_.append(pbPeriod);
0675     operation_button_list_.append(pbEqual);
0676     operation_button_list_.append(pbPercent);
0677     operation_button_list_.append(pbCmp);
0678     operation_button_list_.append(pbMod);
0679 }
0680 
0681 //------------------------------------------------------------------------------
0682 // Name: updateGeometry
0683 // Desc: makes all the buttons have reasonable sizes
0684 //------------------------------------------------------------------------------
0685 void KCalculator::updateGeometry()
0686 {
0687     // Create font metrics using base font (at base size)
0688     const QFontMetrics fm(baseFont());
0689     
0690     // Calculate some useful values
0691     const QSize em = fm.size(0, QStringLiteral("M"));
0692     int margin = QApplication::style()->pixelMetric(QStyle::PM_ButtonMargin, nullptr, nullptr);
0693     margin = qMax(qMin(margin / 2, 3), 3);
0694 
0695     // left pad
0696     const auto leftPadList = leftPad->children();
0697     for (QObject *obj : leftPadList) {
0698         if (auto const button = qobject_cast<KCalcButton *>(obj)) {
0699             button->setMinimumWidth(em.width() * 4 + margin * 2);
0700             button->setMinimumHeight(em.height() * 1.25 + margin * 2);
0701             button->installEventFilter(this);
0702         }
0703     }
0704 
0705     // right pad
0706     const auto rightPadList = rightPad->children();
0707     for (QObject *obj : rightPadList) {
0708         if (auto const button = qobject_cast<KCalcButton *>(obj)) {
0709             button->setMinimumWidth(em.width() * 3 + margin * 2);
0710             button->setMinimumHeight(em.height() * 1.25 + margin * 2);
0711             button->installEventFilter(this);
0712         }
0713     }
0714 
0715     // numeric pad
0716     const auto numericPadList = numericPad->children();
0717     for (QObject *obj : numericPadList) {
0718         if (auto const button = qobject_cast<KCalcButton *>(obj)) {
0719             button->setMinimumWidth(em.width() * 3 + margin * 2);
0720             button->setMinimumHeight(em.height() * 1.25 + margin * 2);
0721             button->installEventFilter(this);
0722         }
0723     }
0724 }
0725 
0726 //------------------------------------------------------------------------------
0727 // Name: slotConstantToDisplay
0728 // Desc: inserts a constant
0729 //------------------------------------------------------------------------------
0730 void KCalculator::slotConstantToDisplay(const science_constant &const_chosen)
0731 {
0732     QString val = const_chosen.value;
0733     val.replace(QLatin1Char('.'), KNumber::decimalSeparator());
0734     calc_display->setAmount(KNumber(val));
0735     updateDisplay({});
0736     core.setOnlyUpdateOperation(false);
0737 }
0738 
0739 //------------------------------------------------------------------------------
0740 // Name: slotBaseSelected
0741 // Desc: changes the selected numeric base
0742 //------------------------------------------------------------------------------
0743 void KCalculator::slotBaseSelected(QAbstractButton *button)
0744 {
0745     if (button) {
0746         const int base = base_choose_group_->id(button);
0747         int current_base;
0748 
0749         // set display & statusbar (if item exist in statusbar)
0750         statusBar()->setBase(base);
0751         switch (base) {
0752         case BinMode:
0753             current_base = calc_display->setBase(NumBase(2));
0754             calc_display->setStatusText(BaseField, QStringLiteral("Bin"));
0755             break;
0756         case OctMode:
0757             current_base = calc_display->setBase(NumBase(8));
0758             calc_display->setStatusText(BaseField, QStringLiteral("Oct"));
0759             break;
0760         case DecMode:
0761             current_base = calc_display->setBase(NumBase(10));
0762             calc_display->setStatusText(BaseField, QStringLiteral("Dec"));
0763             break;
0764         case HexMode:
0765             current_base = calc_display->setBase(NumBase(16));
0766             calc_display->setStatusText(BaseField, QStringLiteral("Hex"));
0767             break;
0768         default:
0769             calc_display->setStatusText(BaseField, QStringLiteral("Error"));
0770             return;
0771         }
0772 
0773         // Enable the buttons available in this base
0774         for (int i = 0; i < current_base; ++i) {
0775             (num_button_group_->buttons().at(i))->setEnabled(true);
0776         }
0777 
0778         // Disable the buttons not available in this base
0779         for (int i = current_base; i < 16; ++i) {
0780             (num_button_group_->buttons().at(i))->setEnabled(false);
0781         }
0782 
0783         // Only enable the decimal point in decimal
0784         pbPeriod->setEnabled(current_base == NB_DECIMAL);
0785 
0786         // Only enable the x*10^y button in decimal
0787         pbEE->setEnabled(current_base == NB_DECIMAL);
0788 
0789         // Disable buttons that make only sense with floating point numbers
0790         if (current_base != NB_DECIMAL) {
0791             for (QAbstractButton *btn : std::as_const(scientific_buttons_)) {
0792                 btn->setEnabled(false);
0793             }
0794         } else {
0795             for (QAbstractButton *btn : std::as_const(scientific_buttons_)) {
0796                 btn->setEnabled(true);
0797             }
0798         }
0799 
0800         KCalcSettings::setBaseMode(base);
0801     }
0802 }
0803 
0804 //------------------------------------------------------------------------------
0805 // Name: keyPressEvent
0806 // Desc: handles keypress events
0807 //------------------------------------------------------------------------------
0808 void KCalculator::keyPressEvent(QKeyEvent *e)
0809 {
0810     // Fix for bug #314586
0811     // Basically, on some keyboards such as French, even though the decimal separator
0812     // is "," the numeric keypad has a "." key. So we fake it so people can more seamlessly
0813     // enter numbers using the keypad
0814     if (KNumber::decimalSeparator() != QLatin1String(".")) {
0815         if (e->key() == Qt::Key_Period && e->modifiers() & Qt::KeypadModifier) {
0816             pbPeriod->animateClick();
0817         }
0818     }
0819 
0820     if (((e->modifiers() & Qt::NoModifier) == 0) || (e->modifiers() & Qt::ShiftModifier)) {
0821         switch (e->key()) {
0822         case Qt::Key_Backspace:
0823             calc_display->deleteLastDigit();
0824             break;
0825         }
0826     }
0827 
0828     if (e->key() == Qt::Key_Control) {
0829         Q_EMIT switchShowAccels(true);
0830     }
0831 
0832     // Workaround for bug #283521
0833     // Unfortunately adding multiple shortcuts (A, Shift+A) to pushbuttons
0834     // does not work properly, so we handle the A-F keypresses with shift in Hex mode here
0835     if (hexRadio->isChecked() && e->modifiers() & Qt::ShiftModifier) {
0836         switch (e->key()) {
0837         case Qt::Key_A:
0838             pbA->animateClick();
0839             break;
0840         case Qt::Key_B:
0841             pbB->animateClick();
0842             break;
0843         case Qt::Key_C:
0844             pbC->animateClick();
0845             break;
0846         case Qt::Key_D:
0847             pbD->animateClick();
0848             break;
0849         case Qt::Key_E:
0850             pbE->animateClick();
0851             break;
0852         case Qt::Key_F:
0853             pbF->animateClick();
0854             break;
0855         default:
0856             break;
0857         }
0858     }
0859 }
0860 
0861 //------------------------------------------------------------------------------
0862 // Name: keyReleaseEvent
0863 // Desc: handles keyrelease events
0864 //------------------------------------------------------------------------------
0865 void KCalculator::keyReleaseEvent(QKeyEvent *e)
0866 {
0867     if (e->key() == Qt::Key_Control) {
0868         Q_EMIT switchShowAccels(false);
0869     }
0870 }
0871 
0872 //------------------------------------------------------------------------------
0873 // Name: slotAngleSelected
0874 // Desc: changes the selected angle system
0875 //------------------------------------------------------------------------------
0876 void KCalculator::slotAngleSelected(QAbstractButton *button)
0877 {
0878     if (button) {
0879         const int mode = angle_choose_group_->id(button);
0880         angle_mode_ = mode;
0881 
0882         statusBar()->setAngleMode(KCalcStatusBar::AngleMode(mode));
0883         switch (mode) {
0884         case DegMode:
0885             calc_display->setStatusText(AngleField, QStringLiteral("Deg"));
0886             break;
0887         case RadMode:
0888             calc_display->setStatusText(AngleField, QStringLiteral("Rad"));
0889             break;
0890         case GradMode:
0891             calc_display->setStatusText(AngleField, QStringLiteral("Gra"));
0892             break;
0893         default: // we shouldn't ever end up here
0894             angle_mode_ = RadMode;
0895         }
0896 
0897         KCalcSettings::setAngleMode(angle_mode_);
0898     }
0899 }
0900 
0901 //------------------------------------------------------------------------------
0902 // Name: slotEEclicked
0903 // Desc: starts the entering of numbers using scientific notation
0904 //------------------------------------------------------------------------------
0905 void KCalculator::slotEEclicked()
0906 {
0907     calc_display->newCharacter(QLatin1Char('e'));
0908 }
0909 
0910 //------------------------------------------------------------------------------
0911 // Name: slotShifttoggled
0912 // Desc: updates the shift state for alternate button functionality
0913 //------------------------------------------------------------------------------
0914 void KCalculator::slotShifttoggled(bool flag)
0915 {
0916     shift_mode_ = flag;
0917 
0918     Q_EMIT switchMode(ModeShift, flag);
0919 
0920     statusBar()->setShiftIndicator(shift_mode_);
0921     if (shift_mode_) {
0922         calc_display->setStatusText(ShiftField, i18n("Shift"));
0923     } else {
0924         calc_display->setStatusText(ShiftField, QString());
0925     }
0926 }
0927 
0928 //------------------------------------------------------------------------------
0929 // Name: slotHyptoggled
0930 // Desc: updates the Hyp state for alternate trig button functionality
0931 //------------------------------------------------------------------------------
0932 void KCalculator::slotHyptoggled(bool flag)
0933 {
0934     // toggle between hyperbolic and standard trig functions
0935     hyp_mode_ = flag;
0936 
0937     Q_EMIT switchMode(ModeHyperbolic, flag);
0938 }
0939 
0940 //------------------------------------------------------------------------------
0941 // Name: slotMemRecallclicked
0942 // Desc: recalls a value from memory
0943 //------------------------------------------------------------------------------
0944 void KCalculator::slotMemRecallclicked()
0945 {
0946     // temp. work-around
0947     calc_display->sendEvent(KCalcDisplay::EventReset);
0948 
0949     // temp. work-around
0950     calc_display->sendEvent(KCalcDisplay::EventReset);
0951 
0952     calc_history->addToHistory(QStringLiteral("MR"), false);
0953 
0954     calc_display->setAmount(memory_num_);
0955     updateDisplay({});
0956     core.setOnlyUpdateOperation(false);
0957     calc_history->addResultToHistory(memory_num_.toQString());
0958 }
0959 
0960 //------------------------------------------------------------------------------
0961 // Name: slotMemStoreclicked
0962 // Desc: stores a value into memory
0963 //------------------------------------------------------------------------------
0964 void KCalculator::slotMemStoreclicked()
0965 {
0966     calc_history->addToHistory(QStringLiteral("M"), false);
0967     update_history_window_ = false;
0968     EnterEqual(CalcEngine::REPEAT_PREVENT);
0969 
0970     memory_num_ = calc_display->getAmount();
0971     calc_display->setStatusText(MemField, QStringLiteral("M"));
0972     statusBar()->setMemoryIndicator(true);
0973     pbMemRecall->setEnabled(true);
0974 }
0975 
0976 //------------------------------------------------------------------------------
0977 // Name: slotNumberclicked
0978 // Desc: user has entered a digit
0979 //------------------------------------------------------------------------------
0980 void KCalculator::slotNumberclicked(QAbstractButton *button)
0981 {
0982     if (button) {
0983         const int number_clicked = num_button_group_->id(button);
0984         calc_display->enterDigit(number_clicked);
0985         core.setOnlyUpdateOperation(false);
0986     }
0987 }
0988 
0989 //------------------------------------------------------------------------------
0990 // Name: slotSinclicked
0991 // Desc: executes the sine function
0992 //------------------------------------------------------------------------------
0993 void KCalculator::slotSinclicked()
0994 {
0995     if (hyp_mode_) {
0996         // sinh or arsinh
0997         if (!shift_mode_) {
0998             calc_history->addFuncToHistory(QStringLiteral("sinh"));
0999             core.SinHyp(calc_display->getAmount());
1000         } else {
1001             calc_history->addFuncToHistory(QStringLiteral("arcsinh"));
1002             core.AreaSinHyp(calc_display->getAmount());
1003         }
1004     } else {
1005         // sine or arcsine
1006         if (!shift_mode_) {
1007             calc_history->addFuncToHistory(QStringLiteral("sin"));
1008             switch (angle_mode_) {
1009             case DegMode:
1010                 core.SinDeg(calc_display->getAmount());
1011                 break;
1012             case RadMode:
1013                 core.SinRad(calc_display->getAmount());
1014                 break;
1015             case GradMode:
1016                 core.SinGrad(calc_display->getAmount());
1017                 break;
1018             }
1019         } else {
1020             calc_history->addFuncToHistory(QStringLiteral("arcsin"));
1021             switch (angle_mode_) {
1022             case DegMode:
1023                 core.ArcSinDeg(calc_display->getAmount());
1024                 break;
1025             case RadMode:
1026                 core.ArcSinRad(calc_display->getAmount());
1027                 break;
1028             case GradMode:
1029                 core.ArcSinGrad(calc_display->getAmount());
1030                 break;
1031             }
1032         }
1033     }
1034 
1035     updateDisplay(UPDATE_FROM_CORE);
1036     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1037 }
1038 
1039 //------------------------------------------------------------------------------
1040 // Name: slotPlusMinusclicked
1041 // Desc: changes sign of number being displayed
1042 //------------------------------------------------------------------------------
1043 void KCalculator::slotPlusMinusclicked()
1044 {
1045     // display can only change sign, when in input mode, otherwise we
1046     // need the core to do this.
1047     if (!calc_display->sendEvent(KCalcDisplay::EventChangeSign)) {
1048         core.InvertSign(calc_display->getAmount());
1049         update_history_window_ = false;
1050         updateDisplay(UPDATE_FROM_CORE);
1051     }
1052 }
1053 
1054 //------------------------------------------------------------------------------
1055 // Name: slotMemPlusMinusclicked
1056 // Desc: handles arithmetic on values stored in memory
1057 //------------------------------------------------------------------------------
1058 void KCalculator::slotMemPlusMinusclicked()
1059 {
1060     bool tmp_shift_mode = shift_mode_; // store this, because next command deletes shift_mode_
1061     update_history_window_ = false;
1062     if (!tmp_shift_mode) {
1063         calc_history->addToHistory(QStringLiteral("M+"), false);
1064     } else {
1065         calc_history->addToHistory(QStringLiteral("M-"), false);
1066     }
1067 
1068     EnterEqual(); // finish calculation so far, to store result into MEM
1069 
1070     if (!tmp_shift_mode) {
1071         memory_num_ += calc_display->getAmount();
1072     } else {
1073         memory_num_ -= calc_display->getAmount();
1074     }
1075 
1076     pbShift->setChecked(false);
1077     statusBar()->setMemoryIndicator(true);
1078     calc_display->setStatusText(MemField, i18n("M"));
1079     pbMemRecall->setEnabled(true);
1080 }
1081 
1082 //------------------------------------------------------------------------------
1083 // Name: slotSinclicked
1084 // Desc: executes the cosine function
1085 //------------------------------------------------------------------------------
1086 void KCalculator::slotCosclicked()
1087 {
1088     if (hyp_mode_) {
1089         // cosh or arcosh
1090         if (!shift_mode_) {
1091             calc_history->addFuncToHistory(QStringLiteral("cosh"));
1092             core.CosHyp(calc_display->getAmount());
1093         } else {
1094             calc_history->addFuncToHistory(QStringLiteral("arcosh"));
1095             core.AreaCosHyp(calc_display->getAmount());
1096         }
1097     } else {
1098         // cosine or arccosine
1099         if (!shift_mode_) {
1100             calc_history->addFuncToHistory(QStringLiteral("cos"));
1101             switch (angle_mode_) {
1102             case DegMode:
1103                 core.CosDeg(calc_display->getAmount());
1104                 break;
1105             case RadMode:
1106                 core.CosRad(calc_display->getAmount());
1107                 break;
1108             case GradMode:
1109                 core.CosGrad(calc_display->getAmount());
1110                 break;
1111             }
1112         } else {
1113             calc_history->addFuncToHistory(QStringLiteral("arccos"));
1114             switch (angle_mode_) {
1115             case DegMode:
1116                 core.ArcCosDeg(calc_display->getAmount());
1117                 break;
1118             case RadMode:
1119                 core.ArcCosRad(calc_display->getAmount());
1120                 break;
1121             case GradMode:
1122                 core.ArcCosGrad(calc_display->getAmount());
1123                 break;
1124             }
1125         }
1126     }
1127 
1128     updateDisplay(UPDATE_FROM_CORE);
1129     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1130 }
1131 
1132 //------------------------------------------------------------------------------
1133 // Name: slotSinclicked
1134 // Desc: executes the reciprocal function
1135 //------------------------------------------------------------------------------
1136 void KCalculator::slotReciclicked()
1137 {
1138     if (shift_mode_) {
1139         calc_history->addFuncToHistory(QStringLiteral("nCm"));
1140         core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_BINOM);
1141     } else {
1142         calc_history->addFuncToHistory(QStringLiteral("1/"));
1143         core.Reciprocal(calc_display->getAmount());
1144         updateDisplay(UPDATE_FROM_CORE);
1145         calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1146         return;
1147     }
1148 
1149     // temp. work-around
1150     KNumber tmp_num = calc_display->getAmount();
1151     calc_display->sendEvent(KCalcDisplay::EventReset);
1152     calc_display->setAmount(tmp_num);
1153     updateDisplay({});
1154     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1155     if (shift_mode_) {
1156         updateHistoryWithFunction(CalcEngine::FUNC_BINOM);
1157     }
1158 }
1159 
1160 //------------------------------------------------------------------------------
1161 // Name: slotSinclicked
1162 // Desc: executes the tangent function
1163 //------------------------------------------------------------------------------
1164 void KCalculator::slotTanclicked()
1165 {
1166     if (hyp_mode_) {
1167         // tanh or artanh
1168         if (!shift_mode_) {
1169             calc_history->addFuncToHistory(QStringLiteral("tanh"));
1170             core.TangensHyp(calc_display->getAmount());
1171         } else {
1172             calc_history->addFuncToHistory(QStringLiteral("artanh"));
1173             core.AreaTangensHyp(calc_display->getAmount());
1174         }
1175     } else {
1176         // tan or arctan
1177         if (!shift_mode_) {
1178             calc_history->addFuncToHistory(QStringLiteral("tan"));
1179             switch (angle_mode_) {
1180             case DegMode:
1181                 core.TangensDeg(calc_display->getAmount());
1182                 break;
1183             case RadMode:
1184                 core.TangensRad(calc_display->getAmount());
1185                 break;
1186             case GradMode:
1187                 core.TangensGrad(calc_display->getAmount());
1188                 break;
1189             }
1190         } else {
1191             calc_history->addFuncToHistory(QStringLiteral("arctan"));
1192             switch (angle_mode_) {
1193             case DegMode:
1194                 core.ArcTangensDeg(calc_display->getAmount());
1195                 break;
1196             case RadMode:
1197                 core.ArcTangensRad(calc_display->getAmount());
1198                 break;
1199             case GradMode:
1200                 core.ArcTangensGrad(calc_display->getAmount());
1201                 break;
1202             }
1203         }
1204     }
1205 
1206     updateDisplay(UPDATE_FROM_CORE);
1207     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1208 }
1209 
1210 //------------------------------------------------------------------------------
1211 // Name: slotFactorialclicked
1212 // Desc: executes the factorial function
1213 //------------------------------------------------------------------------------
1214 void KCalculator::slotFactorialclicked()
1215 {
1216     bool gamma_ = false;
1217     // Set WaitCursor, as this operation may take looooong
1218     // time and UI frezes with large numbers. User needs some
1219     // visual feedback.
1220     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1221     if (!shift_mode_) {
1222         core.Factorial(calc_display->getAmount());
1223     } else {
1224         core.Gamma(calc_display->getAmount());
1225         gamma_ = true;
1226     }
1227     QApplication::restoreOverrideCursor();
1228     updateDisplay(UPDATE_FROM_CORE);
1229     if (gamma_) {
1230         calc_history->addFuncToHistory(QStringLiteral("&#915;"));
1231     } else {
1232         calc_history->addFuncToHistory(QStringLiteral("!"));
1233     }
1234     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1235 }
1236 
1237 //------------------------------------------------------------------------------
1238 // Name: slotLogclicked
1239 // Desc: executes the Log function
1240 //------------------------------------------------------------------------------
1241 void KCalculator::slotLogclicked()
1242 {
1243     if (!shift_mode_) {
1244         core.Log10(calc_display->getAmount());
1245         calc_history->addFuncToHistory(QStringLiteral("log"));
1246     } else {
1247         update_history_window_ = false;
1248         core.Exp10(calc_display->getAmount());
1249         calc_history->addFuncToHistory(QStringLiteral("10<sup>") + calc_display->getAmount().toQString(KCalcSettings::precision()) + QStringLiteral("</sup>"));
1250     }
1251 
1252     updateDisplay(UPDATE_FROM_CORE);
1253     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1254 }
1255 
1256 //------------------------------------------------------------------------------
1257 // Name: slotSquareclicked
1258 // Desc: executes the x^2 function
1259 //------------------------------------------------------------------------------
1260 void KCalculator::slotSquareclicked()
1261 {
1262     bool tmp_shift_mode = shift_mode_;
1263     if (!shift_mode_) {
1264         core.Square(calc_display->getAmount());
1265     } else {
1266         calc_history->addFuncToHistory(QStringLiteral("&radic;"));
1267         core.SquareRoot(calc_display->getAmount());
1268     }
1269 
1270     updateDisplay(UPDATE_FROM_CORE);
1271     if (!tmp_shift_mode) {
1272         calc_history->addFuncToHistory(QStringLiteral("<sup>2</sup>"));
1273     }
1274     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1275 }
1276 
1277 //------------------------------------------------------------------------------
1278 // Name: slotCubeclicked
1279 // Desc: executes the x^3 function
1280 //------------------------------------------------------------------------------
1281 void KCalculator::slotCubeclicked()
1282 {
1283     bool tmp_shift_mode = shift_mode_;
1284     if (!shift_mode_) {
1285         core.Cube(calc_display->getAmount());
1286     } else {
1287         calc_history->addFuncToHistory(QStringLiteral("<sup>3</sup>&radic;"));
1288         core.CubeRoot(calc_display->getAmount());
1289     }
1290 
1291     updateDisplay(UPDATE_FROM_CORE);
1292     if (!tmp_shift_mode) {
1293         calc_history->addFuncToHistory(QStringLiteral("<sup>3</sup>"));
1294     }
1295     calc_history->addResultToHistory(calc_display->formatDecimalNumber(calc_display->getAmount().toQString(KCalcSettings::precision())));
1296 }
1297 
1298 //------------------------------------------------------------------------------
1299 // Name: slotCubeclicked
1300 // Desc: executes the ln function
1301 //------------------------------------------------------------------------------
1302 void KCalculator::slotLnclicked()
1303 {
1304     if (!shift_mode_) {
1305         calc_history->addFuncToHistory(QStringLiteral("ln"));
1306         core.Ln(calc_display->getAmount());
1307     } else {
1308         calc_history->addFuncToHistory(QStringLiteral("e<sup>") + calc_display->getAmount().toQString(KCalcSettings::precision()) + QStringLiteral("</sup>"));
1309         core.Exp(calc_display->getAmount());
1310     }
1311 
1312     updateDisplay(UPDATE_FROM_CORE);
1313     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1314 }
1315 
1316 //------------------------------------------------------------------------------
1317 // Name: slotPowerclicked
1318 // Desc: executes the x^y function
1319 //------------------------------------------------------------------------------
1320 void KCalculator::slotPowerclicked()
1321 {
1322     if (shift_mode_) {
1323         calc_history->addToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()) + QStringLiteral("&nbsp;^ 1/"), false);
1324         core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_PWR_ROOT);
1325         pbShift->setChecked(false);
1326     } else {
1327         calc_history->addToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()), false);
1328         calc_history->addFuncToHistory(QStringLiteral("^"));
1329         core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_POWER);
1330     }
1331 
1332     // temp. work-around
1333     KNumber tmp_num = calc_display->getAmount();
1334     calc_display->sendEvent(KCalcDisplay::EventReset);
1335     calc_display->setAmount(tmp_num);
1336     updateDisplay({});
1337 }
1338 
1339 //------------------------------------------------------------------------------
1340 // Name: slotMemClearclicked
1341 // Desc: executes the MC function
1342 //------------------------------------------------------------------------------
1343 void KCalculator::slotMemClearclicked()
1344 {
1345     memory_num_ = KNumber::Zero;
1346     statusBar()->setMemoryIndicator(false);
1347     calc_display->setStatusText(MemField, QString());
1348     pbMemRecall->setDisabled(true);
1349     calc_history->addToHistory(QStringLiteral("M cleared"), true);
1350 }
1351 
1352 //------------------------------------------------------------------------------
1353 // Name: slotBackspaceclicked
1354 // Desc: removes the last input digit
1355 //------------------------------------------------------------------------------
1356 void KCalculator::slotBackspaceclicked()
1357 {
1358     calc_display->deleteLastDigit();
1359 }
1360 
1361 //------------------------------------------------------------------------------
1362 // Name: slotClearclicked
1363 // Desc: clears the display
1364 //------------------------------------------------------------------------------
1365 void KCalculator::slotClearclicked()
1366 {
1367     calc_display->sendEvent(KCalcDisplay::EventClear);
1368 }
1369 
1370 //------------------------------------------------------------------------------
1371 // Name: slotAllClearclicked
1372 // Desc: clears everything
1373 //------------------------------------------------------------------------------
1374 void KCalculator::slotAllClearclicked()
1375 {
1376     core.Reset();
1377     calc_display->sendEvent(KCalcDisplay::EventReset);
1378     updateDisplay(UPDATE_FROM_CORE);
1379 }
1380 
1381 //------------------------------------------------------------------------------
1382 // Name: slotParenOpenclicked
1383 // Desc: starts a sub-expression
1384 //------------------------------------------------------------------------------
1385 void KCalculator::slotParenOpenclicked()
1386 {
1387     core.ParenOpen(calc_display->getAmount());
1388     calc_history->addFuncToHistory(QStringLiteral("("));
1389 }
1390 
1391 //------------------------------------------------------------------------------
1392 // Name: slotParenCloseclicked
1393 // Desc: ends a sub-expression
1394 //------------------------------------------------------------------------------
1395 void KCalculator::slotParenCloseclicked()
1396 {
1397     core.ParenClose(calc_display->getAmount());
1398     updateDisplay(UPDATE_FROM_CORE);
1399     calc_history->addFuncToHistory(QStringLiteral(")"));
1400     update_history_window_ = false;
1401 }
1402 
1403 //------------------------------------------------------------------------------
1404 // Name: slotANDclicked
1405 // Desc: executes a bitwise AND
1406 //------------------------------------------------------------------------------
1407 void KCalculator::slotANDclicked()
1408 {
1409     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_AND);
1410     updateDisplay(UPDATE_FROM_CORE);
1411     updateHistoryWithFunction(CalcEngine::FUNC_AND);
1412 }
1413 
1414 //------------------------------------------------------------------------------
1415 // Name: slotMultiplicationclicked
1416 // Desc: executes multiplication
1417 //------------------------------------------------------------------------------
1418 void KCalculator::slotMultiplicationclicked()
1419 {
1420     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_MULTIPLY);
1421     updateDisplay(UPDATE_FROM_CORE);
1422     updateHistoryWithFunction(CalcEngine::FUNC_MULTIPLY);
1423 }
1424 
1425 //------------------------------------------------------------------------------
1426 // Name: slotDivisionclicked
1427 // Desc: executes division
1428 //------------------------------------------------------------------------------
1429 void KCalculator::slotDivisionclicked()
1430 {
1431     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_DIVIDE);
1432     updateDisplay(UPDATE_FROM_CORE);
1433     updateHistoryWithFunction(CalcEngine::FUNC_DIVIDE);
1434 }
1435 
1436 //------------------------------------------------------------------------------
1437 // Name: slotORclicked
1438 // Desc: executes a bitwise OR
1439 //------------------------------------------------------------------------------
1440 void KCalculator::slotORclicked()
1441 {
1442     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_OR);
1443     updateDisplay(UPDATE_FROM_CORE);
1444     updateHistoryWithFunction(CalcEngine::FUNC_OR);
1445 }
1446 
1447 //------------------------------------------------------------------------------
1448 // Name: slotXORclicked
1449 // Desc: executes a bitwise XOR
1450 //------------------------------------------------------------------------------
1451 void KCalculator::slotXORclicked()
1452 {
1453     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_XOR);
1454     updateDisplay(UPDATE_FROM_CORE);
1455     updateHistoryWithFunction(CalcEngine::FUNC_XOR);
1456 }
1457 
1458 //------------------------------------------------------------------------------
1459 // Name: slotPlusclicked
1460 // Desc: executes addition
1461 //------------------------------------------------------------------------------
1462 void KCalculator::slotPlusclicked()
1463 {
1464     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_ADD);
1465     updateDisplay(UPDATE_FROM_CORE);
1466     updateHistoryWithFunction(CalcEngine::FUNC_ADD);
1467 }
1468 
1469 //------------------------------------------------------------------------------
1470 // Name: slotPlusclicked
1471 // Desc: executes subtraction
1472 //------------------------------------------------------------------------------
1473 void KCalculator::slotMinusclicked()
1474 {
1475     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_SUBTRACT);
1476     updateDisplay(UPDATE_FROM_CORE);
1477     updateHistoryWithFunction(CalcEngine::FUNC_SUBTRACT);
1478 }
1479 
1480 //------------------------------------------------------------------------------
1481 // Name: slotLeftShiftclicked
1482 // Desc: executes a bitwise left shift
1483 //------------------------------------------------------------------------------
1484 void KCalculator::slotLeftShiftclicked()
1485 {
1486     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_LSH);
1487     updateDisplay(UPDATE_FROM_CORE);
1488     updateHistoryWithFunction(CalcEngine::FUNC_LSH);
1489 }
1490 
1491 //------------------------------------------------------------------------------
1492 // Name: slotLeftShiftclicked
1493 // Desc: executes a bitwise right shift
1494 //------------------------------------------------------------------------------
1495 void KCalculator::slotRightShiftclicked()
1496 {
1497     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_RSH);
1498     updateDisplay(UPDATE_FROM_CORE);
1499     updateHistoryWithFunction(CalcEngine::FUNC_RSH);
1500 }
1501 
1502 //------------------------------------------------------------------------------
1503 // Name: slotPeriodclicked
1504 // Desc: enters a decimal into the input stream
1505 //------------------------------------------------------------------------------
1506 void KCalculator::slotPeriodclicked()
1507 {
1508     // i know this isn't locale friendly, should be converted to appropriate
1509     // value at lower levels
1510     calc_display->newCharacter(QLocale().decimalPoint());
1511 }
1512 
1513 //------------------------------------------------------------------------------
1514 // Name: EnterEqual
1515 // Desc: calculates and displays the result of the pending operations
1516 //------------------------------------------------------------------------------
1517 void KCalculator::EnterEqual(CalcEngine::Repeat allow_repeat)
1518 {
1519     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_EQUAL, allow_repeat);
1520     updateDisplay(UPDATE_FROM_CORE | UPDATE_STORE_RESULT);
1521     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1522 }
1523 
1524 //------------------------------------------------------------------------------
1525 // Name: slotEqualclicked
1526 // Desc: calculates and displays the result of the pending operations
1527 //------------------------------------------------------------------------------
1528 void KCalculator::slotEqualclicked()
1529 {
1530     EnterEqual();
1531 }
1532 
1533 //------------------------------------------------------------------------------
1534 // Name: slotPercentclicked
1535 // Desc: calculates and displays the result of the pending operations as a percent
1536 //------------------------------------------------------------------------------
1537 void KCalculator::slotPercentclicked()
1538 {
1539     core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_PERCENT);
1540     updateDisplay(UPDATE_FROM_CORE);
1541     updateHistoryWithFunction(CalcEngine::FUNC_PERCENT);
1542     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1543 }
1544 
1545 //------------------------------------------------------------------------------
1546 // Name: slotNegateclicked
1547 // Desc: executes a bitwise 2's compliment
1548 // NOTE: implicitly converts the value to an unsigned quantity
1549 //------------------------------------------------------------------------------
1550 void KCalculator::slotNegateclicked()
1551 {
1552     calc_history->addFuncToHistory(QStringLiteral("~"));
1553     core.Complement(calc_display->getAmount());
1554     updateDisplay(UPDATE_FROM_CORE);
1555     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1556 }
1557 
1558 //------------------------------------------------------------------------------
1559 // Name: slotModclicked
1560 // Desc: executes modulous (remainder division)
1561 //------------------------------------------------------------------------------
1562 void KCalculator::slotModclicked()
1563 {
1564     if (shift_mode_) {
1565         core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_INTDIV);
1566     } else {
1567         core.enterOperation(calc_display->getAmount(), CalcEngine::FUNC_MOD);
1568     }
1569 
1570     updateDisplay(UPDATE_FROM_CORE);
1571 
1572     if (shift_mode_) {
1573         updateHistoryWithFunction(CalcEngine::FUNC_INTDIV);
1574     } else {
1575         updateHistoryWithFunction(CalcEngine::FUNC_MOD);
1576     }
1577 }
1578 
1579 //------------------------------------------------------------------------------
1580 // Name: slotStatNumclicked
1581 // Desc: executes Sum function
1582 //------------------------------------------------------------------------------
1583 void KCalculator::slotStatNumclicked()
1584 {
1585     update_history_window_ = false;
1586     if (!shift_mode_) {
1587         core.StatCount(KNumber::Zero);
1588         calc_history->addToHistory(i18n("Number of data entered"), false);
1589     } else {
1590         pbShift->setChecked(false);
1591         core.StatSum(KNumber::Zero);
1592         calc_history->addToHistory(QString::fromUtf8("\xce\xa3") + QLatin1Char('x'), false);
1593     }
1594 
1595     updateDisplay(UPDATE_FROM_CORE);
1596     core.setOnlyUpdateOperation(false);
1597     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1598 }
1599 
1600 //------------------------------------------------------------------------------
1601 // Name: slotStatMeanclicked
1602 // Desc: executes Mean function
1603 //------------------------------------------------------------------------------
1604 void KCalculator::slotStatMeanclicked()
1605 {
1606     update_history_window_ = false;
1607     if (!shift_mode_) {
1608         core.StatMean(KNumber::Zero);
1609         calc_history->addToHistory(i18n("Mean"), false);
1610     } else {
1611         pbShift->setChecked(false);
1612         core.StatSumSquares(KNumber::Zero);
1613         calc_history->addToHistory(QString::fromUtf8("\xce\xa3") + QStringLiteral("x<sup>2</sup>"), false);
1614     }
1615 
1616     updateDisplay(UPDATE_FROM_CORE);
1617     core.setOnlyUpdateOperation(false);
1618     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1619 }
1620 
1621 //------------------------------------------------------------------------------
1622 // Name: slotStatStdDevclicked
1623 // Desc: executes STD function
1624 //------------------------------------------------------------------------------
1625 void KCalculator::slotStatStdDevclicked()
1626 {
1627     update_history_window_ = false;
1628     if (shift_mode_) {
1629         // std (n-1)
1630         core.StatStdSample(KNumber::Zero);
1631         pbShift->setChecked(false);
1632         calc_history->addToHistory(QString::fromUtf8("\xcf\x83") + QStringLiteral("<sub>N-1</sub>"), false);
1633     } else {
1634         // std (n)
1635         core.StatStdDeviation(KNumber::Zero);
1636         calc_history->addToHistory(QString::fromUtf8("\xcf\x83") + QStringLiteral("N"), false);
1637     }
1638 
1639     updateDisplay(UPDATE_FROM_CORE);
1640     core.setOnlyUpdateOperation(false);
1641     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1642 }
1643 
1644 //------------------------------------------------------------------------------
1645 // Name: slotStatMedianclicked
1646 // Desc: executes Median function
1647 //------------------------------------------------------------------------------
1648 void KCalculator::slotStatMedianclicked()
1649 {
1650     update_history_window_ = false;
1651     if (!shift_mode_) {
1652         core.StatMedian(KNumber::Zero);
1653     } else {
1654         core.StatMedian(KNumber::Zero);
1655         pbShift->setChecked(false);
1656     }
1657 
1658     calc_history->addToHistory(i18n("Median"), false);
1659     // TODO: it seems two different modes should be implemented, but...?
1660     updateDisplay(UPDATE_FROM_CORE);
1661     core.setOnlyUpdateOperation(false);
1662     calc_history->addResultToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()));
1663 }
1664 
1665 //------------------------------------------------------------------------------
1666 // Name: slotStatDataInputclicked
1667 // Desc: enters a value for statistical functions
1668 //------------------------------------------------------------------------------
1669 void KCalculator::slotStatDataInputclicked()
1670 {
1671     update_history_window_ = false;
1672     if (!shift_mode_) {
1673         bool tmp_error;
1674         core.StatDataNew(calc_display->getAmount());
1675         calc_history->addToHistory(i18n("DAT [") + core.lastOutput(tmp_error).toQString() + i18n("] = ")
1676                                        + calc_display->getAmount().toQString(KCalcSettings::precision()),
1677                                    true);
1678     } else {
1679         pbShift->setChecked(false);
1680         core.StatDataDel(KNumber::Zero);
1681         statusBar()->showMessage(i18n("Last stat item erased"), 3000);
1682         calc_history->addToHistory(i18n("Last stat item erased"), true);
1683     }
1684 
1685     updateDisplay(UPDATE_FROM_CORE);
1686     core.setOnlyUpdateOperation(false);
1687 }
1688 
1689 //------------------------------------------------------------------------------
1690 // Name: slotStatClearDataclicked
1691 // Desc: clears memory for statical functions
1692 //------------------------------------------------------------------------------
1693 void KCalculator::slotStatClearDataclicked()
1694 {
1695     if (!shift_mode_) {
1696         core.StatClearAll(KNumber::Zero);
1697         statusBar()->showMessage(i18n("Stat mem cleared"), 3000);
1698         calc_history->addToHistory(i18n("Stat mem cleared"), true);
1699     } else {
1700         pbShift->setChecked(false);
1701         updateDisplay({});
1702     }
1703 }
1704 
1705 //------------------------------------------------------------------------------
1706 // Name: slotConstclicked
1707 // Desc: enters a constant
1708 //------------------------------------------------------------------------------
1709 void KCalculator::slotConstclicked(int button)
1710 {
1711     if (auto btn = qobject_cast<KCalcConstButton *>(const_buttons_[button])) {
1712         if (!shift_mode_) {
1713             // set the display to the configured value of constant button
1714             // internally, we deal with C locale style numbers, we need to convert
1715             QString val = btn->constant();
1716             val.replace(QLatin1Char('.'), KNumber::decimalSeparator());
1717             calc_display->setAmount(KNumber(val));
1718 
1719         } else {
1720             pbShift->setChecked(false);
1721 
1722             // internally, we deal with C locale style numbers, we need to convert
1723             QString val = calc_display->text();
1724             val.replace(KNumber::decimalSeparator(), QLatin1String("."));
1725             KCalcSettings::setValueConstant(button, val);
1726 
1727             // below set new tooltip
1728             btn->setLabelAndTooltip();
1729 
1730             // work around: after storing a number, pressing a digit should start
1731             // a new number
1732             calc_display->setAmount(calc_display->getAmount());
1733         }
1734 
1735         updateDisplay({});
1736         core.setOnlyUpdateOperation(false);
1737     }
1738 }
1739 
1740 //------------------------------------------------------------------------------
1741 // Name: showSettings
1742 // Desc: opens the shows the settings dialog
1743 //------------------------------------------------------------------------------
1744 void KCalculator::showSettings()
1745 {
1746     // Check if there is already a dialog and if so bring
1747     // it to the foreground.
1748     if (KConfigDialog::showDialog(QStringLiteral("settings"))) {
1749         return;
1750     }
1751 
1752     // Create a new dialog with the same name as the above checking code.
1753     auto const dialog = new KConfigDialog(this, QStringLiteral("settings"), KCalcSettings::self());
1754 
1755     // general settings
1756     auto const general = new General(nullptr);
1757     general->kcfg_Precision->setMaximum(maxprecision);
1758     dialog->addPage(general, i18n("General"), QStringLiteral("accessories-calculator"), i18n("General Settings"));
1759 
1760     // font settings
1761     auto const fonts = new Fonts(nullptr);
1762     dialog->addPage(fonts, i18n("Font"), QStringLiteral("preferences-desktop-font"), i18n("Select Display Font"));
1763 
1764     // color settings
1765     auto const color = new Colors(nullptr);
1766     dialog->addPage(color, i18n("Colors"), QStringLiteral("preferences-desktop-color"), i18n("Button & Display Colors"));
1767 
1768     // constant settings
1769     if (!constants_) {
1770         constants_ = new Constants(nullptr);
1771 
1772         KCalcConstMenu *tmp_menu;
1773         tmp_menu = new KCalcConstMenu(constants_);
1774         connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst0);
1775         constants_->pushButton0->setMenu(tmp_menu);
1776 
1777         tmp_menu = new KCalcConstMenu(constants_);
1778         connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst1);
1779         constants_->pushButton1->setMenu(tmp_menu);
1780 
1781         tmp_menu = new KCalcConstMenu(constants_);
1782         connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst2);
1783         constants_->pushButton2->setMenu(tmp_menu);
1784 
1785         tmp_menu = new KCalcConstMenu(constants_);
1786         connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst3);
1787         constants_->pushButton3->setMenu(tmp_menu);
1788 
1789         tmp_menu = new KCalcConstMenu(constants_);
1790         connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst4);
1791         constants_->pushButton4->setMenu(tmp_menu);
1792 
1793         tmp_menu = new KCalcConstMenu(constants_);
1794         connect(tmp_menu, &KCalcConstMenu::triggeredConstant, this, &KCalculator::slotChooseScientificConst5);
1795         constants_->pushButton5->setMenu(tmp_menu);
1796     }
1797 
1798     dialog->addPage(constants_, i18n("Constants"), QStringLiteral("preferences-kcalc-constants"), i18n("Define Constants"));
1799 
1800     // When the user clicks OK or Apply we want to update our settings.
1801     connect(dialog, &KConfigDialog::settingsChanged, this, &KCalculator::updateSettings);
1802 
1803     // Display the dialog.
1804     dialog->show();
1805 }
1806 
1807 // these 6 slots are just a quick hack, instead of setting the
1808 // TextEdit fields in the configuration dialog, we are setting the
1809 // Settingvalues themselves!!
1810 
1811 //------------------------------------------------------------------------------
1812 // Name: slotChooseScientificConst0
1813 // Desc: updates constants value
1814 //------------------------------------------------------------------------------
1815 void KCalculator::slotChooseScientificConst0(const science_constant &chosen_const)
1816 {
1817     constants_->kcfg_valueConstant0->setText(chosen_const.value);
1818     constants_->kcfg_nameConstant0->setText(chosen_const.label);
1819 }
1820 
1821 //------------------------------------------------------------------------------
1822 // Name: slotChooseScientificConst1
1823 // Desc: updates constants value
1824 //------------------------------------------------------------------------------
1825 void KCalculator::slotChooseScientificConst1(const science_constant &chosen_const)
1826 {
1827     constants_->kcfg_valueConstant1->setText(chosen_const.value);
1828     constants_->kcfg_nameConstant1->setText(chosen_const.label);
1829 }
1830 
1831 //------------------------------------------------------------------------------
1832 // Name: slotChooseScientificConst2
1833 // Desc: updates constants value
1834 //------------------------------------------------------------------------------
1835 void KCalculator::slotChooseScientificConst2(const science_constant &chosen_const)
1836 {
1837     constants_->kcfg_valueConstant2->setText(chosen_const.value);
1838     constants_->kcfg_nameConstant2->setText(chosen_const.label);
1839 }
1840 
1841 //------------------------------------------------------------------------------
1842 // Name: slotChooseScientificConst3
1843 // Desc: updates constants value
1844 //------------------------------------------------------------------------------
1845 void KCalculator::slotChooseScientificConst3(const science_constant &chosen_const)
1846 {
1847     constants_->kcfg_valueConstant3->setText(chosen_const.value);
1848     constants_->kcfg_nameConstant3->setText(chosen_const.label);
1849 }
1850 
1851 //------------------------------------------------------------------------------
1852 // Name: slotChooseScientificConst4
1853 // Desc: updates constants value
1854 //------------------------------------------------------------------------------
1855 void KCalculator::slotChooseScientificConst4(const science_constant &chosen_const)
1856 {
1857     constants_->kcfg_valueConstant4->setText(chosen_const.value);
1858     constants_->kcfg_nameConstant4->setText(chosen_const.label);
1859 }
1860 
1861 //------------------------------------------------------------------------------
1862 // Name: slotChooseScientificConst5
1863 // Desc: updates constants value
1864 //------------------------------------------------------------------------------
1865 void KCalculator::slotChooseScientificConst5(const science_constant &chosen_const)
1866 {
1867     constants_->kcfg_valueConstant5->setText(chosen_const.value);
1868     constants_->kcfg_nameConstant5->setText(chosen_const.label);
1869 }
1870 
1871 //------------------------------------------------------------------------------
1872 // Name: slotSetSimpleMode
1873 // Desc: sets the calculator to have a simple layout
1874 //------------------------------------------------------------------------------
1875 void KCalculator::slotSetSimpleMode()
1876 {
1877     bool wasMinimumSize = isMinimumSize();
1878 
1879     action_constants_show_->setChecked(false);
1880     action_constants_show_->setEnabled(false);
1881     action_bitset_show_->setEnabled(false);
1882     action_history_show_->setChecked(KCalcSettings::showHistory());
1883     showMemButtons(false);
1884     showScienceButtons(false);
1885     showStatButtons(false);
1886     showLogicButtons(false);
1887 
1888     // hide some individual buttons, which are not in one of the above groups
1889     pbShift->hide();
1890     pbMod->hide();
1891     pbReci->hide();
1892     pbFactorial->hide();
1893     pbSquare->hide();
1894     pbPower->hide();
1895     pbCube->hide();
1896     pbEE->hide();
1897 
1898     // delete the constant menu since it doesn't fit
1899     delete constants_menu_;
1900     constants_menu_ = nullptr;
1901 
1902     KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::simple);
1903     // must be done after setting the calculator mode because the
1904     // slotBitsetshow slot should save the state only in numeral mode
1905     action_bitset_show_->setChecked(false);
1906     
1907     // disable leftPad from affecting the layout
1908     setLeftPadLayoutActive(false);
1909 
1910     // update font size
1911     QApplication::processEvents();
1912     setFonts();
1913     updateGeometry();
1914 
1915     if (!is_still_in_launch_) {
1916         forceResizeEvent();
1917         QApplication::processEvents();
1918         if (wasMinimumSize) {
1919             resize(minimumSize());
1920         }
1921     }
1922 }
1923 
1924 //------------------------------------------------------------------------------
1925 // Name: slotSetScienceMode
1926 // Desc: sets the calculator to science mode
1927 //------------------------------------------------------------------------------
1928 void KCalculator::slotSetScienceMode()
1929 {
1930     bool wasMinimumSize = isMinimumSize();
1931 
1932     action_constants_show_->setEnabled(true);
1933     action_constants_show_->setChecked(KCalcSettings::showConstants());
1934     action_bitset_show_->setEnabled(false);
1935     action_history_show_->setChecked(KCalcSettings::showHistory());
1936 
1937     // show some individual buttons
1938     pbShift->show();
1939     pbMod->show();
1940     pbReci->show();
1941     pbFactorial->show();
1942     pbSquare->show();
1943     pbPower->show();
1944     pbCube->show();
1945     pbEE->show();
1946 
1947     // show or hide some groups of buttons
1948     showStatButtons(false);
1949     showLogicButtons(false);
1950     showMemButtons(true);
1951     showScienceButtons(true);
1952 
1953     if (!constants_menu_) {
1954         constants_menu_ = createConstantsMenu();
1955         menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_);
1956     }
1957 
1958     KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::science);
1959     // must be done after setting the calculator mode because the
1960     // slotBitsetshow slot should save the state only in numeral mode
1961     action_bitset_show_->setChecked(false);
1962     
1963     // enable leftPad to affect the layout
1964     setLeftPadLayoutActive(true);
1965 
1966     // update font size
1967     QApplication::processEvents();
1968     setFonts();
1969     updateGeometry();
1970 
1971     if (!is_still_in_launch_) {
1972         forceResizeEvent();
1973         QApplication::processEvents();
1974         if (wasMinimumSize) {
1975             resize(minimumSize());
1976         }
1977     }
1978 }
1979 
1980 //------------------------------------------------------------------------------
1981 // Name: slotSetStatisticMode
1982 // Desc: sets the calculator to stats mode
1983 //------------------------------------------------------------------------------
1984 void KCalculator::slotSetStatisticMode()
1985 {
1986     bool wasMinimumSize = isMinimumSize();
1987 
1988     action_constants_show_->setEnabled(true);
1989     action_constants_show_->setChecked(KCalcSettings::showConstants());
1990     action_bitset_show_->setEnabled(false);
1991     action_history_show_->setChecked(KCalcSettings::showHistory());
1992 
1993     // show some individual buttons
1994     pbShift->show();
1995     pbMod->show();
1996     pbReci->show();
1997     pbFactorial->show();
1998     pbSquare->show();
1999     pbPower->show();
2000     pbCube->show();
2001     pbEE->show();
2002 
2003     // show or hide some groups of buttons
2004     showLogicButtons(false);
2005     showMemButtons(true);
2006     showScienceButtons(true);
2007     showStatButtons(true);
2008 
2009     if (!constants_menu_) {
2010         constants_menu_ = createConstantsMenu();
2011         menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_);
2012     }
2013 
2014     KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::statistics);
2015     // must be done after setting the calculator mode because the
2016     // slotBitsetshow slot should save the state only in numeral mode
2017     action_bitset_show_->setChecked(false);
2018     
2019     // enable leftPad to affect the layout
2020     setLeftPadLayoutActive(true);
2021 
2022     // update font size
2023     QApplication::processEvents();
2024     setFonts();
2025     updateGeometry();
2026 
2027     if (!is_still_in_launch_) {
2028         forceResizeEvent();
2029         QApplication::processEvents();
2030         if (wasMinimumSize) {
2031             resize(minimumSize());
2032         }
2033     }
2034 }
2035 
2036 //------------------------------------------------------------------------------
2037 // Name: slotSetNumeralMode
2038 // Desc: sets the calculator to numerical ("programmers") mode
2039 //------------------------------------------------------------------------------
2040 void KCalculator::slotSetNumeralMode()
2041 {
2042     bool wasMinimumSize = isMinimumSize();
2043 
2044     action_constants_show_->setChecked(false);
2045     action_constants_show_->setEnabled(false);
2046     action_bitset_show_->setEnabled(true);
2047     action_bitset_show_->setChecked(KCalcSettings::showBitset());
2048     action_history_show_->setChecked(KCalcSettings::showHistory());
2049 
2050     // show some individual buttons
2051     pbShift->show();
2052     pbMod->show();
2053     pbReci->show();
2054     pbFactorial->show();
2055     pbSquare->show();
2056     pbPower->show();
2057     pbCube->show();
2058     pbEE->show();
2059 
2060     // show or hide some groups of buttons
2061     showScienceButtons(false);
2062     showStatButtons(false);
2063     showMemButtons(true);
2064     showLogicButtons(true);
2065 
2066     if (!constants_menu_) {
2067         constants_menu_ = createConstantsMenu();
2068         menuBar()->insertMenu((menuBar()->actions)()[2], constants_menu_);
2069     }
2070 
2071     KCalcSettings::setCalculatorMode(KCalcSettings::EnumCalculatorMode::numeral);
2072     
2073     // enable leftPad to affect the layout
2074     setLeftPadLayoutActive(true);
2075 
2076     // update font size
2077     QApplication::processEvents();
2078     setFonts();
2079     updateGeometry();
2080 
2081     if (!is_still_in_launch_) {
2082         forceResizeEvent();
2083         QApplication::processEvents();
2084         if (wasMinimumSize) {
2085             resize(minimumSize());
2086         }
2087     }
2088 }
2089 
2090 //------------------------------------------------------------------------------
2091 // Name: slotBaseModeAmountChanged
2092 // Desc: updates numerical base conversions
2093 //------------------------------------------------------------------------------
2094 void KCalculator::slotBaseModeAmountChanged(const KNumber &number)
2095 {
2096     quint64 n = number.toUint64();
2097 
2098     decDisplay->setText(QString::number(n, 10));
2099     binDisplay->setText(QString::number(n, 2));
2100     octDisplay->setText(QString::number(n, 8));
2101     hexDisplay->setText(QString::number(n, 16).toUpper());
2102 }
2103 
2104 //------------------------------------------------------------------------------
2105 // Name: showMemButtons
2106 // Desc: hides or shows the memory buttons
2107 //------------------------------------------------------------------------------
2108 void KCalculator::showMemButtons(bool toggled)
2109 {
2110     if (toggled) {
2111         for (QAbstractButton *btn : std::as_const(mem_button_list_)) {
2112             btn->show();
2113         }
2114     } else {
2115         for (QAbstractButton *btn : std::as_const(mem_button_list_)) {
2116             btn->hide();
2117         }
2118 
2119         // these are in the mem_button_list_ but should not be hidden
2120         pbClear->show();
2121         pbAllClear->show();
2122     }
2123 }
2124 
2125 //------------------------------------------------------------------------------
2126 // Name: showStatButtons
2127 // Desc: hides or shows the stat buttons
2128 //------------------------------------------------------------------------------
2129 void KCalculator::showStatButtons(bool toggled)
2130 {
2131     if (toggled) {
2132         for (QAbstractButton *btn : std::as_const(stat_buttons_)) {
2133             btn->show();
2134         }
2135     } else {
2136         for (QAbstractButton *btn : std::as_const(stat_buttons_)) {
2137             btn->hide();
2138         }
2139     }
2140 }
2141 
2142 //------------------------------------------------------------------------------
2143 // Name: showScienceButtons
2144 // Desc: hides or shows the science buttons
2145 //------------------------------------------------------------------------------
2146 void KCalculator::showScienceButtons(bool toggled)
2147 {
2148     if (toggled) {
2149         for (QAbstractButton *btn : std::as_const(scientific_buttons_)) {
2150             btn->show();
2151         }
2152         const auto buttons = angle_choose_group_->buttons();
2153         for (QAbstractButton *btn : buttons) {
2154             btn->show();
2155         }
2156 
2157         setAngle();
2158         statusBar()->setAngleModeIndicatorVisible(true);
2159     } else {
2160         for (QAbstractButton *btn : std::as_const(scientific_buttons_)) {
2161             btn->hide();
2162         }
2163 
2164         const auto buttons = angle_choose_group_->buttons();
2165         for (QAbstractButton *btn : buttons) {
2166             btn->hide();
2167         }
2168 
2169         statusBar()->setAngleModeIndicatorVisible(false);
2170         calc_display->setStatusText(AngleField, QString());
2171     }
2172 }
2173 
2174 //------------------------------------------------------------------------------
2175 // Name: showLogicButtons
2176 // Desc: hides or shows the logic buttons
2177 //------------------------------------------------------------------------------
2178 void KCalculator::showLogicButtons(bool toggled)
2179 {
2180     if (toggled) {
2181         mBitset->setEnabled(true);
2182         connect(mBitset, &KCalcBitset::valueChanged, this, &KCalculator::slotBitsetChanged);
2183         connect(calc_display, &KCalcDisplay::changedAmount, this, &KCalculator::slotUpdateBitset);
2184 
2185         for (QAbstractButton *btn : std::as_const(logic_buttons_)) {
2186             btn->show();
2187         }
2188 
2189         setBase();
2190         statusBar()->setBaseIndicatorVisible(true);
2191 
2192         const auto buttons = base_choose_group_->buttons();
2193         for (QAbstractButton *btn : buttons) {
2194             btn->show();
2195         }
2196 
2197         for (QLabel *lbl : base_conversion_labels_) {
2198             lbl->show();
2199         }
2200         connect(calc_display, &KCalcDisplay::changedAmount, this, &KCalculator::slotBaseModeAmountChanged);
2201 
2202         for (int i = 10; i < 16; ++i) {
2203             (num_button_group_->button(i))->show();
2204         }
2205     } else {
2206         mBitset->setEnabled(false);
2207         disconnect(mBitset, &KCalcBitset::valueChanged, this, &KCalculator::slotBitsetChanged);
2208         disconnect(calc_display, &KCalcDisplay::changedAmount, this, &KCalculator::slotUpdateBitset);
2209 
2210         for (QAbstractButton *btn : std::as_const(logic_buttons_)) {
2211             btn->hide();
2212         }
2213 
2214         // Hide Hex-Buttons, but first switch back to decimal
2215 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2216         decRadio->animateClick();
2217 #else
2218         decRadio->animateClick(0);
2219 #endif
2220 
2221         const auto buttons = base_choose_group_->buttons();
2222         for (QAbstractButton *btn : buttons) {
2223             btn->hide();
2224         }
2225 
2226         for (QLabel *lbl : base_conversion_labels_) {
2227             lbl->hide();
2228         }
2229         connect(calc_display, &KCalcDisplay::changedAmount, this, &KCalculator::slotBaseModeAmountChanged);
2230 
2231         statusBar()->setBaseIndicatorVisible(false);
2232         calc_display->setStatusText(BaseField, QString());
2233         for (int i = 10; i < 16; ++i) {
2234             (num_button_group_->button(i))->hide();
2235         }
2236     }
2237 }
2238 
2239 //------------------------------------------------------------------------------
2240 // Name: slotHistoryshow
2241 // Desc: hides or shows the history
2242 //------------------------------------------------------------------------------
2243 void KCalculator::slotHistoryshow(bool toggled) {
2244     bool wasMinimumSize = isMinimumSize();
2245 
2246     calc_history->setVisible(toggled);
2247     KCalcSettings::setShowHistory(toggled);
2248     updateGeometry();
2249 
2250     if (!is_still_in_launch_) {
2251         forceResizeEvent();
2252         QApplication::processEvents();
2253         if (wasMinimumSize) {
2254             resize(minimumSize());
2255         }
2256     }
2257 }
2258 
2259 //------------------------------------------------------------------------------
2260 // Name: slotConstantsShow
2261 // Desc: hides or shows the constants buttons
2262 //------------------------------------------------------------------------------
2263 void KCalculator::slotConstantsShow(bool toggled)
2264 {
2265     bool wasMinimumSize = isMinimumSize();
2266 
2267     if (toggled) {
2268         for (QAbstractButton *btn : std::as_const(const_buttons_)) {
2269             btn->show();
2270         }
2271     } else {
2272         for (QAbstractButton *btn : std::as_const(const_buttons_)) {
2273             btn->hide();
2274         }
2275     }
2276 
2277     KCalcSettings::setShowConstants(toggled);
2278     updateGeometry();
2279 
2280     if (!is_still_in_launch_) {
2281         forceResizeEvent();
2282         QApplication::processEvents();
2283         if (wasMinimumSize) {
2284             // In this specific case, we need to invalidate the layout before resize
2285             layout()->invalidate();
2286             QApplication::processEvents();
2287             resize(minimumSize());
2288         }
2289     }
2290 }
2291 
2292 //------------------------------------------------------------------------------
2293 // Name: slotBitsetshow
2294 // Desc: hides or shows the bitset buttons
2295 //------------------------------------------------------------------------------
2296 void KCalculator::slotBitsetshow(bool toggled)
2297 {
2298     bool wasMinimumSize = isMinimumSize();
2299 
2300     mBitset->setVisible(toggled);
2301     setBitsetLayoutActive(toggled);
2302     if (KCalcSettings::calculatorMode() == KCalcSettings::EnumCalculatorMode::numeral) {
2303         KCalcSettings::setShowBitset(toggled);
2304     }
2305     updateGeometry();
2306 
2307     if (!is_still_in_launch_) {
2308         forceResizeEvent();
2309         QApplication::processEvents();
2310         if (wasMinimumSize) {
2311             resize(minimumSize());
2312         }
2313     }
2314 }
2315 
2316 //------------------------------------------------------------------------------
2317 // Name: slotBitsetshow
2318 // Desc: This function is for setting the constant names configured in the
2319 //       kcalc settings menu. If the user doesn't enter a name for the
2320 //       constant C1 to C6 is used.
2321 //------------------------------------------------------------------------------
2322 void KCalculator::changeButtonNames()
2323 {
2324     for (QAbstractButton *btn : std::as_const(const_buttons_)) {
2325         if (auto const constbtn = qobject_cast<KCalcConstButton *>(btn)) {
2326             constbtn->setLabelAndTooltip();
2327         }
2328     }
2329 }
2330 
2331 //------------------------------------------------------------------------------
2332 // Name: slotBitsetChanged
2333 // Desc: updates the bitset display
2334 // NOTE: sets display to *unsigned* value
2335 //------------------------------------------------------------------------------
2336 void KCalculator::slotBitsetChanged(quint64 value)
2337 {
2338     calc_display->setAmount(KNumber(value));
2339     updateDisplay({});
2340     core.setOnlyUpdateOperation(false);
2341 }
2342 
2343 //------------------------------------------------------------------------------
2344 // Name: slotUpdateBitset
2345 // Desc: updates the bitset itself
2346 //------------------------------------------------------------------------------
2347 void KCalculator::slotUpdateBitset(const KNumber &nr)
2348 {
2349     mBitset->setValue(nr.toUint64());
2350 }
2351 
2352 //------------------------------------------------------------------------------
2353 // Name: updateSettings
2354 // Desc: updates the persistent settings
2355 //------------------------------------------------------------------------------
2356 void KCalculator::updateSettings()
2357 {
2358     changeButtonNames();
2359     setColors();
2360     setBaseFont(KCalcSettings::buttonFont());
2361     setFonts();
2362     setPrecision();
2363 
2364     // Show the result in the app's caption in taskbar (wishlist - bug #52858)
2365     disconnect(calc_display, SIGNAL(changedText(QString)), this, nullptr);
2366 
2367     if (KCalcSettings::captionResult()) {
2368         connect(calc_display, &KCalcDisplay::changedText, this, &KCalculator::setWindowTitle);
2369     } else {
2370         setCaption(QString());
2371     }
2372 
2373     calc_display->changeSettings();
2374     calc_history->changeSettings();
2375     updateGeometry();
2376 }
2377 
2378 //------------------------------------------------------------------------------
2379 // Name: updateDisplay
2380 // Desc: updates the display
2381 //------------------------------------------------------------------------------
2382 
2383 void KCalculator::updateDisplay(UpdateFlags flags)
2384 {
2385     if (flags & UPDATE_FROM_CORE) {
2386         if (update_history_window_) {
2387             calc_history->addToHistory(calc_display->getAmount().toQString(KCalcSettings::precision()), false);
2388         } else {
2389             update_history_window_ = true;
2390         }
2391         calc_display->updateFromCore(core, (flags & UPDATE_STORE_RESULT) != 0);
2392     } else {
2393         calc_display->update();
2394     }
2395 
2396     pbShift->setChecked(false);
2397 }
2398 
2399 //------------------------------------------------------------------------------
2400 // Name: updateHistoryWithFunction
2401 // Desc: updates the history with the last used function
2402 //------------------------------------------------------------------------------
2403 void KCalculator::updateHistoryWithFunction(CalcEngine::Operation func) {
2404     calc_history->addFuncToHistory(func);
2405 }
2406 
2407 //------------------------------------------------------------------------------
2408 // Name: setColors
2409 // Desc: set the various colours
2410 //------------------------------------------------------------------------------
2411 void KCalculator::setColors()
2412 {
2413     calc_display->changeSettings();
2414     calc_history->changeSettings();
2415 
2416     const QColor numFontColor(KCalcSettings::numberFontsColor());
2417     for (int i = 0; i < 10; ++i) {
2418         qobject_cast<KCalcButton *>((num_button_group_->button(i)))->setTextColor(numFontColor);
2419     }
2420 
2421     const QColor funcFontColor(KCalcSettings::functionFontsColor());
2422     for (QAbstractButton *btn : std::as_const(function_button_list_)) {
2423         qobject_cast<KCalcButton *>(btn)->setTextColor(funcFontColor);
2424     }
2425 
2426     const QColor statFontColor(KCalcSettings::statFontsColor());
2427     for (QAbstractButton *btn : std::as_const(stat_buttons_)) {
2428         qobject_cast<KCalcButton *>(btn)->setTextColor(statFontColor);
2429     }
2430 
2431     const QColor hexFontColor(KCalcSettings::hexFontsColor());
2432     for (int i = 10; i < 16; ++i) {
2433         qobject_cast<KCalcButton *>((num_button_group_->button(i)))->setTextColor(hexFontColor);
2434     }
2435 
2436     const QColor memFontColor(KCalcSettings::memoryFontsColor());
2437     for (QAbstractButton *btn : std::as_const(mem_button_list_)) {
2438         qobject_cast<KCalcButton *>(btn)->setTextColor(memFontColor);
2439     }
2440 
2441     const QColor opFontColor(KCalcSettings::operationFontsColor());
2442     for (QAbstractButton *btn : std::as_const(operation_button_list_)) {
2443         qobject_cast<KCalcButton *>(btn)->setTextColor(opFontColor);
2444     }
2445 
2446     const QColor coFontColor(KCalcSettings::constantsFontsColor());
2447     for (QAbstractButton *btn : std::as_const(const_buttons_)) {
2448         qobject_cast<KCalcButton *>(btn)->setTextColor(coFontColor);
2449     }
2450 
2451     KColorScheme schemeButtons(QPalette::Active, KColorScheme::Button);
2452     const QColor defaultColor = schemeButtons.background().color();
2453 
2454     // Do not apply style sheets when using default background colors, see bug #237513
2455     if (KCalcSettings::numberButtonsColor() == defaultColor && KCalcSettings::functionButtonsColor() == defaultColor
2456         && KCalcSettings::statButtonsColor() == defaultColor && KCalcSettings::hexButtonsColor() == defaultColor
2457         && KCalcSettings::memoryButtonsColor() == defaultColor && KCalcSettings::operationButtonsColor() == defaultColor
2458         && KCalcSettings::constantsButtonsColor() == defaultColor) {
2459         return;
2460     }
2461 
2462     const QString sheet = QStringLiteral("QPushButton { background-color: %1 }");
2463 
2464     const QColor numPal(KCalcSettings::numberButtonsColor());
2465     for (int i = 0; i < 10; ++i) {
2466         (num_button_group_->button(i))->setStyleSheet(sheet.arg(numPal.name()));
2467     }
2468 
2469     const QColor funcPal(KCalcSettings::functionButtonsColor());
2470     for (QAbstractButton *btn : std::as_const(function_button_list_)) {
2471         btn->setStyleSheet(sheet.arg(funcPal.name()));
2472     }
2473 
2474     const QColor statPal(KCalcSettings::statButtonsColor());
2475     for (QAbstractButton *btn : std::as_const(stat_buttons_)) {
2476         btn->setStyleSheet(sheet.arg(statPal.name()));
2477     }
2478 
2479     const QColor hexPal(KCalcSettings::hexButtonsColor());
2480     for (int i = 10; i < 16; ++i) {
2481         (num_button_group_->button(i))->setStyleSheet(sheet.arg(hexPal.name()));
2482     }
2483 
2484     const QColor memPal(KCalcSettings::memoryButtonsColor());
2485     for (QAbstractButton *btn : std::as_const(mem_button_list_)) {
2486         btn->setStyleSheet(sheet.arg(memPal.name()));
2487     }
2488 
2489     const QColor opPal(KCalcSettings::operationButtonsColor());
2490     for (QAbstractButton *btn : std::as_const(operation_button_list_)) {
2491         btn->setStyleSheet(sheet.arg(opPal.name()));
2492     }
2493 
2494     const QColor coPal(KCalcSettings::constantsButtonsColor());
2495     for (QAbstractButton *btn : std::as_const(const_buttons_)) {
2496         btn->setStyleSheet(sheet.arg(coPal.name()));
2497     }
2498 }
2499 
2500 //------------------------------------------------------------------------------
2501 // Name: setFonts
2502 // Desc: set the various fonts
2503 //------------------------------------------------------------------------------
2504 void KCalculator::setFonts()
2505 {
2506     // Get the font selected in the settings
2507     QFont buttonFont = baseFont();
2508 
2509     // Step 1: Gather the minimum button width and height of all buttons
2510 
2511     int minButtonWidth = INT_MAX;
2512     int minButtonHeight = INT_MAX;
2513 
2514     const auto leftPadLst = leftPad->children();
2515     for (QObject *obj : leftPadLst) {
2516         if (auto const button = qobject_cast<KCalcButton *>(obj)) {
2517             if (button->isVisible()) {
2518                 if (button->width() < minButtonWidth)
2519                     minButtonWidth = button->width();
2520                 if (button->height() < minButtonHeight)
2521                     minButtonHeight = button->height();
2522             }
2523         }
2524     }
2525 
2526     const auto numericPadLst = numericPad->children();
2527     for (QObject *obj : numericPadLst) {
2528         if (auto const button = qobject_cast<KCalcButton *>(obj)) {
2529             if (button->isVisible()) {
2530                 if (button->width() < minButtonWidth)
2531                     minButtonWidth = button->width();
2532                 if (button->height() < minButtonHeight)
2533                     minButtonHeight = button->height();
2534             }
2535         }
2536     }
2537 
2538     const auto rightPadLst = rightPad->children();
2539     for (QObject *obj : rightPadLst) {
2540         if (auto const button = qobject_cast<KCalcButton *>(obj)) {
2541             if (button->isVisible() && button != pbShift) {
2542                 if (button->width() < minButtonWidth)
2543                     minButtonWidth = button->width();
2544                 if (button->height() < minButtonHeight)
2545                     minButtonHeight = button->height();
2546             }
2547         }
2548     }
2549 
2550     // Step 2: If step 1 worked, calculate new font size
2551 
2552     if (!(minButtonWidth == INT_MAX || minButtonHeight == INT_MAX)) {
2553 
2554         // Calculate new font size. Use the font size from the settings as minimum font size.
2555         // Please note these constants are arbitrarily chosen for lack of a better solution.
2556         // If issues with scaling arise (due to abnormally wide/tall fonts), increase them to compensate.
2557         buttonFont.setPointSizeF(qMax(KCalcSettings::buttonFont().pointSizeF(), qMin(minButtonWidth / 4.8, minButtonHeight / 3.6)));
2558         
2559     }
2560 
2561     // Step 3: Apply the new font (and size) to all buttons.
2562 
2563     for (QObject *obj : leftPadLst) {
2564         if (auto const button = qobject_cast<KCalcButton *>(obj)) {
2565             button->setFont(buttonFont);
2566         }
2567     }
2568 
2569     for (QObject *obj : numericPadLst) {
2570         if (auto const button = qobject_cast<KCalcButton *>(obj)) {
2571             button->setFont(buttonFont);
2572         }
2573     }
2574 
2575     for (QObject *obj : rightPadLst) {
2576         if (auto const button = qobject_cast<KCalcButton *>(obj)) {
2577             button->setFont(buttonFont);
2578         }
2579     }
2580 }
2581 
2582 //------------------------------------------------------------------------------
2583 // Name: setBaseFont
2584 // Desc: set the base font
2585 //------------------------------------------------------------------------------
2586 void KCalculator::setBaseFont(const QFont &font)
2587 {
2588     // Overwrite current baseFont
2589     baseFont_ = font;
2590 }
2591 
2592 //------------------------------------------------------------------------------
2593 // Name: baseFont
2594 // Desc: get the base font
2595 //------------------------------------------------------------------------------
2596 const QFont& KCalculator::baseFont() const
2597 {
2598     return baseFont_;
2599 }
2600 
2601 //------------------------------------------------------------------------------
2602 // Name: isMinimumSize
2603 // Desc: Is KCalc currently at minimum size?
2604 //------------------------------------------------------------------------------
2605 bool KCalculator::isMinimumSize()
2606 {
2607     QSize contentSize = KCalculator::contentsRect().size();
2608     QMargins contentMargins = KCalculator::contentsMargins();
2609     QSize actualSize(contentSize.width() + contentMargins.left() + contentMargins.right(),
2610                      contentSize.height() + contentMargins.top() + contentMargins.bottom());
2611     QSize minSize = KCalculator::minimumSize();
2612     return actualSize == minSize;
2613 }
2614 
2615 //------------------------------------------------------------------------------
2616 // Name: forceResizeEvent
2617 // Desc: Force a resize event with no size changes
2618 //------------------------------------------------------------------------------
2619 void KCalculator::forceResizeEvent()
2620 {
2621     QApplication::postEvent(this, new QResizeEvent(size(), size()));
2622 }
2623 
2624 //------------------------------------------------------------------------------
2625 // Name: setLeftPadLayoutActive
2626 // Desc: Enable/disable whether leftPad affects the layout
2627 //------------------------------------------------------------------------------
2628 void KCalculator::setLeftPadLayoutActive(bool active)
2629 {
2630     QSizePolicy policy = leftPad->sizePolicy();
2631     policy.setHorizontalStretch((int)active); // 0 or 1
2632     leftPad->setSizePolicy(policy);
2633 }
2634 
2635 //------------------------------------------------------------------------------
2636 // Name: setBitsetLayoutActive
2637 // Desc: Enable/disable whether mBitset affects the layout
2638 //------------------------------------------------------------------------------
2639 void KCalculator::setBitsetLayoutActive(bool active)
2640 {
2641     firstVerticalLayout->setStretch(1, (int)active); // 0 or 1
2642 }
2643 
2644 //------------------------------------------------------------------------------
2645 // Name: event
2646 // Desc: catch application's palette and font change events
2647 //------------------------------------------------------------------------------
2648 bool KCalculator::event(QEvent *e)
2649 {
2650     switch (e->type()) {
2651     case QEvent::ApplicationFontChange:
2652         setBaseFont(KCalcSettings::buttonFont());
2653         setFonts();
2654         updateGeometry();
2655         break;
2656     case QEvent::ApplicationPaletteChange:
2657         setColors();
2658         break;
2659     default:
2660         break;
2661     }
2662     return KXmlGuiWindow::event(e);
2663 }
2664 
2665 //------------------------------------------------------------------------------
2666 // Name: setPrecision
2667 // Desc: set the precision of the display
2668 //------------------------------------------------------------------------------
2669 void KCalculator::setPrecision()
2670 {
2671     KNumber::setDefaultFloatPrecision(KCalcSettings::precision());
2672     updateDisplay({});
2673 }
2674 
2675 //------------------------------------------------------------------------------
2676 // Name: setAngle
2677 // Desc: sets the angle mode
2678 //------------------------------------------------------------------------------
2679 void KCalculator::setAngle()
2680 {
2681     if (QAbstractButton *const btn = angle_choose_group_->button(KCalcSettings::angleMode())) {
2682 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2683         btn->animateClick();
2684 #else
2685         btn->animateClick(0);
2686 #endif
2687     }
2688 }
2689 
2690 //------------------------------------------------------------------------------
2691 // Name: setBase
2692 // Desc: sets the numeric base
2693 //------------------------------------------------------------------------------
2694 void KCalculator::setBase()
2695 {
2696     if (QAbstractButton *const btn = base_choose_group_->button(KCalcSettings::baseMode())) {
2697 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2698         btn->animateClick();
2699 #else
2700         btn->animateClick(0);
2701 #endif
2702     }
2703 }
2704 
2705 //------------------------------------------------------------------------------
2706 // Name: eventFilter
2707 // Desc: general event filter used to track events like drag/drop
2708 //------------------------------------------------------------------------------
2709 bool KCalculator::eventFilter(QObject *o, QEvent *e)
2710 {
2711     switch (e->type()) {
2712     case QEvent::DragEnter: {
2713         auto const ev = reinterpret_cast<QDragEnterEvent *>(e);
2714         ev->setAccepted(KColorMimeData::canDecode(ev->mimeData()));
2715         return true;
2716     }
2717     case QEvent::DragLeave: {
2718         return true;
2719     }
2720     case QEvent::Drop: {
2721         auto const calcButton = qobject_cast<KCalcButton *>(o);
2722         if (!calcButton) {
2723             return false;
2724         }
2725 
2726         auto const ev = reinterpret_cast<QDropEvent *>(e);
2727         QColor c = KColorMimeData::fromMimeData(ev->mimeData());
2728 
2729         if (c.isValid()) {
2730             QString cn = c.name();
2731             QString sheet = QStringLiteral("background-color: %1");
2732 
2733             QList<QAbstractButton *> *list;
2734             const int num_but = num_button_group_->buttons().indexOf(calcButton);
2735             if (num_but != -1) {
2736                 // Was it hex-button or normal digit??
2737                 if (num_but < 10) {
2738                     for (int i = 0; i < 10; ++i) {
2739                         (num_button_group_->buttons().at(i))->setStyleSheet(sheet.arg(cn));
2740                     }
2741                 } else {
2742                     for (int i = 10; i < 16; ++i) {
2743                         (num_button_group_->buttons().at(i))->setStyleSheet(sheet.arg(cn));
2744                     }
2745                 }
2746                 return true;
2747             } else if (function_button_list_.contains(calcButton)) {
2748                 list = &function_button_list_;
2749             } else if (stat_button_list_.contains(calcButton)) {
2750                 list = &stat_button_list_;
2751             } else if (mem_button_list_.contains(calcButton)) {
2752                 list = &mem_button_list_;
2753             } else if (operation_button_list_.contains(calcButton)) {
2754                 list = &operation_button_list_;
2755             } else {
2756                 return false;
2757             }
2758 
2759             for (int i = 0; i < list->size(); ++i) {
2760                 list->at(i)->setStyleSheet(sheet.arg(cn));
2761             }
2762         }
2763         return true;
2764     }
2765     // FALL THROUGH
2766     default:
2767         return KXmlGuiWindow::eventFilter(o, e);
2768     }
2769 }
2770 
2771 //------------------------------------------------------------------------------
2772 // Name: slotPaste
2773 // Desc: paste a number from the clipboard
2774 //------------------------------------------------------------------------------
2775 void KCalculator::slotPaste()
2776 {
2777     calc_display->slotPaste();
2778     core.setOnlyUpdateOperation(false);
2779 }
2780 
2781 //------------------------------------------------------------------------------
2782 // Name: resizeEvent
2783 // Desc: resize window and make sure it's large enough for its content
2784 //------------------------------------------------------------------------------
2785 void KCalculator::resizeEvent(QResizeEvent* event)
2786 {
2787     // Call the overridden resize event
2788     KXmlGuiWindow::resizeEvent(event);
2789 
2790     updateGeometry();
2791 
2792     // If the content size is now larger than the window size, resize window to fit
2793     QSize actualSize = KCalculator::size();
2794     QSize minSize = KCalculator::minimumSize();
2795     if (actualSize.width() < minSize.width() || actualSize.height() < minSize.height()) {
2796         KCalculator::resize(minSize); // force window as small as possible for current layout
2797     }
2798 
2799     // Adjust button fonts
2800     setFonts();
2801 
2802     // Force mBitset to call its resizeEvent
2803     mBitset->resize(0, 0);
2804 }
2805 
2806 
2807 ////////////////////////////////////////////////////////////////
2808 // Include the meta-object code for classes in this file
2809 //
2810 
2811 //------------------------------------------------------------------------------
2812 // Name: main
2813 // Desc: entry point of the application
2814 //------------------------------------------------------------------------------
2815 int main(int argc, char *argv[])
2816 {
2817     QApplication app(argc, argv);
2818 
2819     KLocalizedString::setApplicationDomain("kcalc");
2820 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2821     /**
2822      * enable high dpi support
2823      */
2824     app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
2825     Kdelibs4ConfigMigrator migrate(QStringLiteral("kcalc"));
2826     migrate.setConfigFiles(QStringList() << QStringLiteral("kcalcrc"));
2827     migrate.setUiFiles(QStringList() << QStringLiteral("kcalcui.rc"));
2828     migrate.migrate();
2829 #endif
2830     KCrash::initialize();
2831     KAboutData aboutData(QStringLiteral("kcalc"),
2832                          i18n("KCalc"),
2833                          QStringLiteral(KCALC_VERSION_STRING),
2834                          i18n("KDE Calculator"),
2835                          KAboutLicense::GPL,
2836                          i18n("Copyright © 2008-2013, Evan Teran\n"
2837                               "Copyright © 2000-2008, The KDE Team\n"
2838                               "Copyright © 2003-2005, Klaus Niederkr"
2839                               "\xc3\xbc"
2840                               "ger\n"
2841                               "Copyright © 1996-2000, Bernd Johannes Wuebben"),
2842                          QString(),
2843                          QStringLiteral("https://apps.kde.org/kcalc/"));
2844 
2845     // Klaus Niederkrueger
2846     aboutData.addAuthor(i18n("Klaus Niederkr"
2847                              "\xc3\xbc"
2848                              "ger"),
2849                         QString(),
2850                         QStringLiteral("kniederk@math.uni-koeln.de"));
2851     aboutData.addAuthor(i18n("Bernd Johannes Wuebben"), QString(), QStringLiteral("wuebben@kde.org"));
2852     aboutData.addAuthor(i18n("Evan Teran"), i18n("Maintainer"), QStringLiteral("eteran@alum.rit.edu"));
2853     aboutData.addAuthor(i18n("Espen Sand"), QString(), QStringLiteral("espen@kde.org"));
2854     aboutData.addAuthor(i18n("Chris Howells"), QString(), QStringLiteral("howells@kde.org"));
2855     aboutData.addAuthor(i18n("Aaron J. Seigo"), QString(), QStringLiteral("aseigo@olympusproject.org"));
2856     aboutData.addAuthor(i18n("Charles Samuels"), QString(), QStringLiteral("charles@altair.dhs.org"));
2857     // Rene Merou
2858     aboutData.addAuthor(i18n("Ren"
2859                              "\xc3\xa9"
2860                              " M"
2861                              "\xc3\xa9"
2862                              "rou"),
2863                         QString(),
2864                         QStringLiteral("ochominutosdearco@yahoo.es"));
2865     aboutData.addAuthor(i18n("Michel Marti"), QString(), QStringLiteral("mma@objectxp.com"));
2866     aboutData.addAuthor(i18n("David Johnson"), QString(), QStringLiteral("david@usermode.org"));
2867     aboutData.addAuthor(i18n("Niklas Freund"), QString(), QStringLiteral("nalquas.dev@gmail.com"));
2868 
2869     KAboutData::setApplicationData(aboutData);
2870     app.setWindowIcon(QIcon::fromTheme(QStringLiteral("accessories-calculator"), app.windowIcon()));
2871 
2872     QCommandLineParser parser;
2873     aboutData.setupCommandLine(&parser);
2874     parser.process(app);
2875     aboutData.processCommandLine(&parser);
2876 
2877     // Force system locale to "C" internally. Fix for bug #159168, showing multiple commas
2878     // in floating point operations because of different thousands separator and comma separator.
2879     setlocale(LC_NUMERIC, "C");
2880 
2881     KNumber::setGroupSeparator(QLocale().groupSeparator());
2882     KNumber::setDecimalSeparator(QString(QLocale().decimalPoint()));
2883 
2884     auto calc = new KCalculator(nullptr);
2885 
2886     calc->show();
2887     return app.exec();
2888 }