diff --git a/calculator.cpp b/calculator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..24eebe31f3576c5446d3932f11675349d2b26774 --- /dev/null +++ b/calculator.cpp @@ -0,0 +1,684 @@ +#include "calculator.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +Calculator::Calculator(QWidget *parent) + : QWidget(parent), + f_lcdNum(0), + f_currentNum(""), + f_if_currNumChangable(true) +{ + setMinimumSize(600, 500); + this->setWindowTitle("Calculator (standard mode)"); + MainLayout = new QGridLayout(this); + f_BtnLayoutCasual = new QGridLayout(this); + f_BtnLayoutSciExtr = new QGridLayout(this); + f_BtnLayoutSciExtrWidget = new QWidget(this); + f_BtnLayoutCasualExtrWidget = new QWidget(this); + f_HBoxBtnLayout = new QHBoxLayout(this); + + f_lcdNum = new QLCDNumber(12, this); + f_lcdNum->setSegmentStyle(QLCDNumber::Flat); + f_lcdNum->setMinimumSize(400,60); + f_lcdNum->setDigitCount(20); + + + + f_radioBtnCasual = new QRadioButton("Casual", this); + f_radioBtnCasual->toggle(); + f_radioBtnSci = new QRadioButton("Science", this); + + connect(f_radioBtnCasual, SIGNAL(toggled(bool)), this, SLOT(slotHideSci(bool))); + connect(f_radioBtnSci, SIGNAL(toggled(bool)), this, SLOT(slotShowSci(bool))); + QString ButtonsTxtCasual[4][5] = { + {"7","8","9","/","sqrt"}, + {"4","5","6","*","rev"}, + {"1","2","3","-","sqr"}, + {".","0","=","+","-x"} + }; + + QString ButtonsTxtSciExtr[4][4] = { + {"sinh", "sin", "exp", "ln"}, + {"cosh", "cos", "n!", "log"}, + {"tanh", "tan", "cubic sqr", "ysqr"}, + {"pi", "e", "cubic root", "ysqrt"} + }; + + + + for (int row = 0; row < 4; row++) + { + for (int col = 0; col < 5; col++) + { + f_BtnLayoutCasual->addWidget(createButton(ButtonsTxtCasual[row][col], 30, 40), row+2, col); + } + } + + for (int row = 0; row < 4; row++) + { + for (int col = 0; col < 4; col++) + { + f_BtnLayoutSciExtr->addWidget(createButton(ButtonsTxtSciExtr[row][col], 30, 40), row+2, col); + } + } + + f_BtnLayoutSciExtrWidget->setLayout(f_BtnLayoutSciExtr); + f_BtnLayoutCasualExtrWidget->setLayout(f_BtnLayoutCasual); + f_HBoxBtnLayout->addWidget(f_BtnLayoutSciExtrWidget); + f_HBoxBtnLayout->addWidget(f_BtnLayoutCasualExtrWidget); + MainLayout->addWidget(f_lcdNum, 0, 0, 1, 7, Qt::AlignmentFlag::AlignHCenter); + MainLayout->addWidget(createButton("CE", 40, 35), 0, 8, Qt::AlignmentFlag::AlignCenter); + + MainLayout->addWidget(f_radioBtnCasual, 1, 0, 1, 2, Qt::AlignmentFlag::AlignCenter); + MainLayout->addWidget(f_radioBtnSci, 1, 2, 1, 2, Qt::AlignmentFlag::AlignCenter); + + MainLayout->addLayout(f_HBoxBtnLayout, 2, 0, 4, 9, Qt::AlignmentFlag::AlignCenter); + + f_BtnLayoutSciExtrWidget->hide(); + this->setLayout(MainLayout); + resize (500, 400); +} + +QPushButton* Calculator::createButton(const QString &p_str, size_t p_horz, size_t p_vert) +{ + QPushButton* new_PBtn = new QPushButton(p_str); + new_PBtn->setMinimumSize(p_horz, p_vert); + connect(new_PBtn, SIGNAL(clicked()), this, SLOT(slotButtonClicked())); + return new_PBtn; +} + +Calculator::~Calculator() +{} + +void Calculator::calc() +{ + if (f_operStack.size() < 2) + return; + + if (f_operStack.size() == 2) + { + QString operation = f_operStack.pop(); + double operand = f_operStack.pop().toDouble(); + qDebug() << operand << operation << " 0 if binary"; + + if (operation == "rev") + { + if (operand == 0) + { + f_lcdNum->display("ERR"); + qDebug() << "ERR"; + } + else + f_lcdNum->display(1 / operand); + qDebug() << 1/operand; + } + + if (operation == "sqr") + {f_lcdNum->display(operand * operand); + qDebug() << operand * operand;} + + if (operation == "sqrt") + {f_lcdNum->display(sqrt(operand)); + qDebug() << sqrt(operand);} + + if(operation == "-x") + {f_lcdNum->display(-operand); + qDebug() << -operand;} + + if(operation == "cubic root") + { double tt = 1/3.0; + f_lcdNum->display(qPow(operand, tt)); + qDebug() << qPow(operand, tt);} + + if(operation == "cubic sqr") + {f_lcdNum->display(operand * operand * operand); + qDebug() << operand * operand * operand;} + + if(operation == "n!") + { + int res = 1; + int oper = static_cast(operand); + if (oper < 1) + { + f_lcdNum->display("Err"); + return; + } + else + { + while (oper > 1) + { + res *= oper; + oper--; + } + } + f_lcdNum->display(res); + qDebug() << res;} + + if (operation == "+" || operation == "-") + {f_lcdNum->display(operand); + qDebug() << operand;} + + if (operation == "*") + {f_lcdNum->display(0); + qDebug() << 0;} + + if (operation == "/") + {f_lcdNum->display("Err"); + qDebug() << "Err";} + + if (operation == "log") + {f_lcdNum->display("Err"); + qDebug() << "Err";} + + if(operation == "sin") + {f_lcdNum->display(qSin(operand)); + qDebug() << qSin(operand);} + + if(operation == "sinh") + {f_lcdNum->display(qAsin(operand)); + qDebug() << qAsin(operand);} + + if(operation == "cos") + {f_lcdNum->display(qCos(operand)); + qDebug() << qCos(operand);} + + if(operation == "cosh") + {f_lcdNum->display(qAcos(operand)); + qDebug() << qAcos(operand);} + + if(operation == "tan") + {f_lcdNum->display(qTan(operand)); + qDebug() << qTan(operand);} + + if(operation == "tanh") + {f_lcdNum->display(qAtan(operand)); + qDebug() << qAtan(operand);} + + if(operation == "ln") + {f_lcdNum->display(qLn(operand)); + qDebug() << qLn(operand);} + + if(operation == "exp") + {f_lcdNum->display(qExp(operand)); + qDebug() << qExp(operand);} + if (operation == "ysqr") + {f_lcdNum->display(1); + qDebug() << 1;} + + if (operation == "ysqrt") + {f_lcdNum->display("Err"); + qDebug() << "Err";} + + + } + else if(f_operStack.size() == 3) + { + + double operand2 = f_operStack.pop().toDouble(); + QString operation = f_operStack.pop(); + double operand1 = f_operStack.pop().toDouble(); + + qDebug() << operand1 << operation << operand2 << ":"; + + if (operation == "+") + {f_lcdNum->display(operand1 + operand2); + qDebug() << operand1 + operand2;} + + if (operation == "-") + {f_lcdNum->display(operand1 - operand2); + qDebug() << operand1 - operand2;} + + if (operation == "*") + {f_lcdNum->display(operand1 * operand2); + qDebug() << operand1 * operand2;} + + if (operation == "/") + {f_lcdNum->display(operand1 / operand2); + qDebug() << operand1 / operand2;} + + if (operation == "log") + {f_lcdNum->display(qLn(operand1) / qLn(operand2)); + qDebug() << qLn(operand1) / qLn(operand2);} + + if (operation == "ysqr") + {f_lcdNum->display(qPow(operand1, operand2)); + qDebug() << qPow(operand1, operand2);} + + if (operation == "ysqrt") + {f_lcdNum->display(qPow(operand1, 1.0 / operand2)); + qDebug() << qPow(operand1, 1.0 / operand2);} + } + else if (f_operStack.size() == 5) + { double operand3 = f_operStack.pop().toDouble(); + QString operation2 = f_operStack.pop(); + double operand2 = f_operStack.pop().toDouble(); + QString operation1 = f_operStack.pop(); + double operand1 = f_operStack.pop().toDouble(); + double mid_res; + + qDebug() << operand1 << operation1 << operand2 << operation2 << operand3 << ":"; + if (operation2 == "*") + {mid_res = operand2 * operand3; + qDebug() << "mid_res = " << operand2 * operand3;} + + if (operation1 == "+") + {f_lcdNum->display(operand1 + mid_res); + qDebug() << operand1 + mid_res;} + + if (operation1 == "-") + {f_lcdNum->display(operand1 - mid_res); + qDebug() << operand1 - mid_res;} + + if (operation1 == "*") + {f_lcdNum->display(operand1 * mid_res); + qDebug() << operand1 * mid_res;} + + if (operation1 == "/") + {f_lcdNum->display(operand1 / mid_res); + qDebug() << operand1 / mid_res;} + + if (operation1 == "log") + {f_lcdNum->display(qLn(operand1) / qLn(mid_res)); + qDebug() << qLn(operand1) / qLn(mid_res);} + + if (operation1 == "ysqr") + {f_lcdNum->display(qPow(operand1, mid_res)); + qDebug() << qPow(operand1, mid_res);} + + if (operation1 == "ysqrt") + {f_lcdNum->display(qPow(operand1, 1.0 / mid_res)); + qDebug() << qPow(operand1, 1.0 / mid_res);} + + if (operation2 == "/") + {mid_res = operand2 / operand3; + qDebug() << "mid_res = " << operand2 / operand3;} + + if (operation2 == "log") + {mid_res = qLn(operand2) / qLn(operand3); + qDebug() << "mid_res = " << qLn(operand2) / qLn(operand3);} + + if (operation2 == "ysqr") + {mid_res = qPow(operand2, operand3); + qDebug() << "mid_res = " << qPow(operand2, operand3);} + + if (operation2 == "ysqrt") + {mid_res = qPow(operand2, 1.0 / operand3); + qDebug() << "mid_res = " << qPow(operand2, 1.0 / operand3);} + } +} + +void Calculator::slotHideSci(bool p_is) +{ + if (p_is) + { + this->setWindowTitle("Casual (standard mode)"); + f_BtnLayoutSciExtrWidget->hide(); + + setMinimumSize(600, 500); + resize(600,500); + qDebug() << "Resize (600, 500)"; + f_lcdNum->setMinimumSize(400,60); + f_lcdNum->setDigitCount(20); + } +} + +void Calculator::slotShowSci(bool p_is) +{ + if (p_is) + { + this->setWindowTitle("Upgrade Calculator (scientific mode)"); + f_BtnLayoutSciExtrWidget->show(); + + setMinimumSize(900, 500); + resize(900, 500); + + qDebug() << "Resize (900, 500)"; + f_lcdNum->setMinimumSize(650,60); + f_lcdNum->setDigitCount(35); + } +} + + +void Calculator::slotButtonClicked() +{ + QPushButton* s = dynamic_cast(sender()); + QString input; + if(s) + input = s->text(); + else + return; + + qDebug() << "Just pressed: " << input; + + if (input == "CE") + { + f_operStack.clear(); + f_currentNum = ""; + f_lcdNum->display(0); + return; + } + + if (input == "C") + { + if (f_currentNum != "") + { + f_currentNum = ""; + f_lcdNum->display(0); + return; + } + else //if not, clear stack + { + f_operStack.clear(); + f_lcdNum->display(0); + return; + } + } + + if (input.contains(QRegExp("[0-9]"))) + { + if (f_if_currNumChangable) + { + if (input == "0" && f_currentNum == "") + { + f_lcdNum->display(0); + return; + } + f_currentNum += input; + f_lcdNum->display(f_currentNum); + return; + } + else + { + f_if_currNumChangable = true; + if (input == "0") + { + f_currentNum = ""; + f_lcdNum->display(0); + return; + } + f_currentNum = input; + f_lcdNum->display(f_currentNum); + return; + } + } + else if (input == ".") + { + if (f_currentNum == "") + { + f_currentNum += "0."; + f_lcdNum->display(f_currentNum); + return; + } + else + { + if (f_if_currNumChangable) + { + if (f_currentNum.contains('.')) + { + /*f_currentNum = "0."; + f_lcdNum->display(f_currentNum); + return;*/ + return; + } + f_currentNum += input; + f_lcdNum->display(f_currentNum); + return; + } + else //if not changable + { + f_if_currNumChangable = true; + f_currentNum = "0."; + f_lcdNum->display(f_currentNum); + return; + } + } + } + else if (NumND.contains(input)) + { + if (input == "e") + { + f_currentNum = QString::number(qExp(1)); + f_if_currNumChangable = false; + f_lcdNum->display(f_currentNum); + return; + } + else + { + f_currentNum = QString::number(PI); + f_if_currNumChangable = false; + f_lcdNum->display(f_currentNum); + return; + } + } + else //if input is an operation + { + if (input == "=") //if = + { + if (f_operStack.size() == 0) + { + return; + } + else if (f_operStack.size() == 2) + { + if (f_currentNum == "") + { + calc(); + return; + } + else + { + f_operStack.push_back(f_currentNum); + calc(); + f_operStack.clear(); + f_currentNum = ""; + return; + } + } + else + { + if (f_currentNum == "") + { + f_operStack.pop_back(); + calc(); + f_operStack.clear(); + return; + } + else + { + f_operStack.push_back(f_currentNum); + f_currentNum = ""; + calc(); + f_operStack.clear(); + return; + } + } + } + else + { + if (f_operStack.size() == 0) + { + if (f_currentNum == "") + { + f_operStack.push_back(QString::number(f_lcdNum->value())); + f_operStack.push_back(input); + if (UnOp.contains(input)) + { + calc(); + f_operStack.clear(); + return; + } + return; + } + else + { + f_operStack.push_back(f_currentNum); + f_currentNum = ""; + f_operStack.push_back(input); + if (UnOp.contains(input)) + { + calc(); + f_operStack.clear(); + return; + } + return; + } + } + else if (f_operStack.size() == 2) + { + if (f_currentNum == "") + { + f_operStack.pop_back(); + f_operStack.push_back(input); + if (UnOp.contains(input)) + { + calc(); + f_operStack.clear(); + return; + } + return; + } + else + { + + QString tech_oper; + tech_oper = f_operStack.pop(); + + if (OpToCountimmediately.contains(tech_oper) || SumOp.contains(input)) + { + f_operStack.push_back(tech_oper); + f_operStack.push_back(f_currentNum); + f_currentNum = ""; + calc(); + f_operStack.clear(); + f_operStack.push_back(QString::number(f_lcdNum->value())); + f_operStack.push_back(input); + return; + } + else + { + if (UnOp.contains(input)) + { + QString tech_f_operand; + tech_f_operand = f_operStack.pop(); + + f_operStack.push_back(f_currentNum); + f_operStack.push_back(input); + calc(); + f_operStack.clear(); + f_operStack.push_back(tech_f_operand); + f_operStack.push_back(tech_oper); + f_currentNum = QString::number(f_lcdNum->value()); + f_if_currNumChangable = false; + return; + } + else //else add second number and second operation to stack + { + f_operStack.push_back(f_currentNum); + f_currentNum = ""; + f_operStack.push_back(input); + return; + } + } + } + } + else + { + if (f_currentNum == "") + { + f_operStack.pop_back(); //drop operation 2 + if (UnOp.contains(input)) + { + QString tech_f_operand; + QString tech_s_operand; + QString tech_oper; + tech_s_operand = f_operStack.pop(); + tech_oper = f_operStack.pop(); + tech_f_operand = f_operStack.pop(); + f_operStack.push_back(tech_s_operand); + f_operStack.push_back(input); + calc(); + f_operStack.clear(); + f_operStack.push_back(tech_f_operand); + f_operStack.push_back(tech_oper); + f_currentNum = QString::number(f_lcdNum->value()); + return; + } + else + { + f_operStack.push_back(input); + return; + } + } + else + { + if (UnOp.contains(input)) + { + QString tech_f_operand; + QString tech_s_operand; + QString tech_oper1; + QString tech_oper2; + + tech_oper2 = f_operStack.pop(); + tech_s_operand = f_operStack.pop(); + tech_oper1 = f_operStack.pop(); + tech_f_operand = f_operStack.pop(); + + f_operStack.push_back(f_currentNum); + f_operStack.push_back(input); + calc(); + f_operStack.clear(); + f_currentNum = QString::number(f_lcdNum->value()); + f_if_currNumChangable = false; + + f_operStack.push_back(tech_f_operand); + f_operStack.push_back(tech_oper1); + f_operStack.push_back(tech_s_operand); + f_operStack.push_back(tech_oper2); + return; + } + else //if inputed operation 3 is binary + { + if (SumOp.contains(input)) + { + f_operStack.push_back(f_currentNum); + f_currentNum = ""; + calc(); + f_operStack.clear(); + f_operStack.push_back(QString::number(f_lcdNum->value())); + f_operStack.push_back(input); + return; + } + QString tech_f_operand; + QString tech_s_operand; + QString tech_oper1; + QString tech_oper2; + + tech_oper2 = f_operStack.pop(); + tech_s_operand = f_operStack.pop(); + tech_oper1 = f_operStack.pop(); + tech_f_operand = f_operStack.pop(); + + f_operStack.push_back(tech_s_operand); + f_operStack.push_back(tech_oper2); + f_operStack.push_back(f_currentNum); + calc(); + f_operStack.clear(); + f_operStack.push_back(tech_f_operand); + f_operStack.push_back(tech_oper1); + f_operStack.push_back(QString::number(f_lcdNum->value())); + f_operStack.push_back(input); + f_currentNum = ""; + return; + } + } + } + } + } +}