File indexing completed on 2024-04-28 09:45:25

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