IVS-calculator
Loading...
Searching...
No Matches
gui.cpp
Go to the documentation of this file.
1
6#include "gui.h"
7#include "ui_gui.h"
8
9#include <QMessageBox>
10#include <QKeyEvent>
11#include <QString>
12#include <cmath>
13
18Gui::Gui(QWidget *parent)
19 : QMainWindow(parent),
20 ui(new Ui::Gui),
21 justEvaluated(false)
22{
23 ui->setupUi(this);
24 currentExpression.clear();
25}
26
31{
32 delete ui;
33}
34
40{
41 switch (err) {
43 QMessageBox::warning(this, "Error", "Division by zero!");
44 break;
46 QMessageBox::warning(this, "Error", "Factorial of negative number!");
47 break;
49 QMessageBox::warning(this, "Error", "Invalid root operation!");
50 break;
52 QMessageBox::warning(this, "Error", "Invalid argument!");
53 break;
54 default:
55 break;
56 }
57}
58
65{
66 ui->display->setText(currentExpression.isEmpty() ? "0" : currentExpression);
67}
68
74{
75 if (currentExpression.isEmpty()) return false;
76 QChar last = currentExpression.back();
77 return last == '+' || last == '-' || last == '*' ||
78 last == '/' || last == '%' || last == '^';
79}
80
88bool Gui::hasOperator() const
89{
90 // Start scanning from index 1 to allow a leading negative sign
91 for (int i = 1; i < currentExpression.size(); ++i) {
92 QChar c = currentExpression[i];
93 if (c == '+' || c == '*' || c == '/' || c == '%' || c == '^')
94 return true;
95 // A '-' that isn't at position 0 counts as an operator
96 if (c == '-')
97 return true;
98 }
99 return false;
100}
101
108void Gui::appendDigit(const QString &digit)
109{
110 if (justEvaluated) {
111 currentExpression.clear();
112 justEvaluated = false;
113 }
114 currentExpression += digit;
116}
117
125void Gui::appendOperator(const QString &op)
126{
127 // After evaluation, chain onto the result
128 if (justEvaluated) {
129 justEvaluated = false;
130 }
131
132 // Don't allow an operator on an empty expression
133 // (except minus, which creates a negative number)
134 if (currentExpression.isEmpty()) {
135 if (op == "-") {
136 currentExpression += op;
138 }
139 return;
140 }
141
142 // If expression already ends with an operator, replace it
143 if (endsWithOperator()) {
144 currentExpression.chop(1);
145 currentExpression += op;
147 return;
148 }
149
150 // Only allow one binary operator per expression
151 if (hasOperator()) {
152 return;
153 }
154
155 currentExpression += op;
157}
158
159// ---- Digit button handlers ----
160
171
172// ---- Operator button handlers ----
173
180
188{
189 if (justEvaluated) {
190 currentExpression.clear();
191 justEvaluated = false;
192 }
193
194 // Find the current number segment (after the last operator)
195 int lastOp = -1;
196 for (int i = currentExpression.size() - 1; i >= 0; --i) {
197 QChar c = currentExpression[i];
198 if (c == '+' || c == '-' || c == '*' ||
199 c == '/' || c == '%' || c == '^') {
200 lastOp = i;
201 break;
202 }
203 }
204 QString segment = currentExpression.mid(lastOp + 1);
205
206 // Only add a dot if this number segment doesn't already have one
207 if (!segment.contains('.')) {
208 currentExpression += ".";
210 }
211}
212
219{
220 if (justEvaluated) {
221 currentExpression.clear();
222 justEvaluated = false;
223 }
224
225 // √ is a prefix unary op — only valid at the beginning
226 if (currentExpression.isEmpty()) {
227 currentExpression = "√";
229 }
230}
231
239{
240 if (justEvaluated) {
241 justEvaluated = false;
242 }
243
244 if (currentExpression.isEmpty() || endsWithOperator())
245 return;
246
247 // Don't allow factorial if there's already an operator (keeps single-op rule)
248 // but do allow it as the sole operation on a plain number
249 if (hasOperator())
250 return;
251
252 // Don't allow double factorial
253 if (currentExpression.endsWith("!"))
254 return;
255
256 currentExpression += "!";
258}
259
264{
265 currentExpression.clear();
266 justEvaluated = false;
268}
269
278int Gui::findOperatorPos(QChar op) const
279{
280 // Start at 1 to skip a possible leading negative sign
281 for (int i = 1; i < currentExpression.size(); ++i) {
282 if (currentExpression[i] == op)
283 return i;
284 }
285 return -1;
286}
287
295{
296 if (currentExpression.isEmpty())
297 return;
298
299
300 if (justEvaluated)
301 return;
302
303
304 if (endsWithOperator())
305 return;
306
308 double result = 0.0;
309 bool evaluated = false;
310
311
312
313
314 if (currentExpression.endsWith("!")) {
315 int val = currentExpression.chopped(1).toInt();
316 result = mathlib::factorial(val, err);
317 evaluated = true;
318 }
319
320 else if (currentExpression.startsWith("√")) {
321 double val = currentExpression.mid(1).toDouble();
322 result = mathlib::root(val, 2, err);
323 evaluated = true;
324 }
325
326
327
328 if (!evaluated) {
329 int pos = -1;
330 QChar op = '\0';
331
332
333 const QString ops = "+*/%^";
334 for (QChar c : ops) {
335 pos = findOperatorPos(c);
336 if (pos != -1) { op = c; break; }
337 }
338
339 if (pos == -1) {
340 pos = findOperatorPos('-');
341 if (pos != -1) op = '-';
342 }
343
344 if (pos != -1) {
345 double left = currentExpression.left(pos).toDouble();
346 double right = currentExpression.mid(pos + 1).toDouble();
347
348 if (op == '+') result = mathlib::add(left, right);
349 else if (op == '-') result = mathlib::subtract(left, right);
350 else if (op == '*') result = mathlib::multiply(left, right);
351 else if (op == '/') result = mathlib::divide(left, right, err);
352 else if (op == '%') result = mathlib::modulo(left, right, err);
353 else if (op == '^') result = mathlib::power(left, static_cast<int>(right));
354
355 evaluated = true;
356 }
357 }
358
359 // Plain number — just keep it
360 if (!evaluated) {
361 result = currentExpression.toDouble();
362 }
363
364 if (err != mathlib::OK) {
365 showError(err);
366 currentExpression.clear();
367 justEvaluated = false;
369 return;
370 }
371
372 currentExpression = QString::number(result);
373 justEvaluated = true;
375}
376
384void Gui::keyPressEvent(QKeyEvent *event)
385{
386 int key = event->key();
387
388 // Digit keys 0-9
389 if (key >= Qt::Key_0 && key <= Qt::Key_9) {
390 appendDigit(QString::number(key - Qt::Key_0));
391 return;
392 }
393
394 switch (key) {
395 // Basic operators
396 case Qt::Key_Plus:
397 appendOperator("+");
398 break;
399 case Qt::Key_Minus:
400 appendOperator("-");
401 break;
402 case Qt::Key_Asterisk:
403 appendOperator("*");
404 break;
405 case Qt::Key_Slash:
406 appendOperator("/");
407 break;
408 case Qt::Key_Percent:
409 appendOperator("%");
410 break;
411 case Qt::Key_AsciiCircum:
412 appendOperator("^");
413 break;
414 case Qt::Key_Exclam:
416 break;
417
418 // Decimal point
419 case Qt::Key_Period:
420 case Qt::Key_Comma:
422 break;
423
424 // Evaluate
425 case Qt::Key_Return:
426 case Qt::Key_Enter:
427 case Qt::Key_Equal:
429 break;
430
431 // Backspace — delete last character
432 case Qt::Key_Backspace:
433 if (justEvaluated) {
434 currentExpression.clear();
435 justEvaluated = false;
436 } else if (!currentExpression.isEmpty()) {
437 currentExpression.chop(1);
438 }
440 break;
441
442 // Clear
443 case Qt::Key_Escape:
444 case Qt::Key_Delete:
445 case Qt::Key_C:
447 break;
448
449 default:
450 QMainWindow::keyPressEvent(event);
451 break;
452 }
453}
Main window class for the calculator GUI.
Definition gui.h:26
Ui::Gui * ui
Definition gui.h:62
void on_btn_plus_clicked()
Operation button handlers.
Definition gui.cpp:174
bool hasOperator() const
Checks if the expression already contains a binary operator.
Definition gui.cpp:88
void on_btn_clear_clicked()
Control buttons.
Definition gui.cpp:263
void updateDisplay()
Updates the calculator display.
Definition gui.cpp:64
QString currentExpression
Definition gui.h:63
void on_btn_3_clicked()
Definition gui.cpp:164
int findOperatorPos(QChar op) const
Finds the position of the binary operator in the expression.
Definition gui.cpp:278
~Gui()
Destructor. Frees allocated resources.
Definition gui.cpp:30
bool endsWithOperator() const
Helpers for input validation.
Definition gui.cpp:73
void on_btn_div_clicked()
Definition gui.cpp:177
void appendOperator(const QString &op)
Appends a binary operator to the expression.
Definition gui.cpp:125
void on_btn_mul_clicked()
Definition gui.cpp:176
void on_btn_mod_clicked()
Definition gui.cpp:178
void on_btn_5_clicked()
Definition gui.cpp:166
Gui(QWidget *parent=nullptr)
Constructs the GUI and initializes components.
Definition gui.cpp:18
void on_btn_root_clicked()
Appends square root operator.
Definition gui.cpp:218
void on_btn_2_clicked()
Definition gui.cpp:163
void appendDigit(const QString &digit)
Appends a digit to the expression.
Definition gui.cpp:108
void on_btn_1_clicked()
Definition gui.cpp:162
void on_btn_minus_clicked()
Definition gui.cpp:175
void on_btn_pow_clicked()
Definition gui.cpp:179
void on_btn_0_clicked()
Digit button handlers.
Definition gui.cpp:161
void on_btn_7_clicked()
Definition gui.cpp:168
void on_btn_dot_clicked()
Appends a decimal point to the current expression.
Definition gui.cpp:187
void on_btn_4_clicked()
Definition gui.cpp:165
void keyPressEvent(QKeyEvent *event) override
Keyboard input handler.
Definition gui.cpp:384
void showError(mathlib::MathError err)
Displays an error message based on mathlib error code.
Definition gui.cpp:39
void on_btn_8_clicked()
Definition gui.cpp:169
void on_btn_equal_clicked()
Evaluates the current expression.
Definition gui.cpp:294
bool justEvaluated
Definition gui.h:64
void on_btn_6_clicked()
Definition gui.cpp:167
void on_btn_9_clicked()
Definition gui.cpp:170
void on_btn_fac_clicked()
Appends factorial operator.
Definition gui.cpp:238
Library for the calculator GUI.
Definition gui.h:15
double root(double base, int n, MathError &err)
Implementation of function root.
Definition mathlib.cpp:85
double add(double a, double b)
Implementation of function add.
Definition mathlib.cpp:9
double multiply(double a, double b)
Implementation of function multiply.
Definition mathlib.cpp:25
double modulo(double a, double b, MathError &err)
Implementation of function modulo.
Definition mathlib.cpp:111
MathError
Definition mathlib.h:11
@ INVALID_ROOT
Definition mathlib.h:15
@ NEGATIVE_FACTORIAL
Definition mathlib.h:14
@ DIVISION_BY_ZERO
Definition mathlib.h:13
@ INVALID_ARGUMENT
Definition mathlib.h:16
double divide(double a, double b, MathError &err)
Implementation of function divide.
Definition mathlib.cpp:33
double subtract(double a, double b)
Implementation of function subtract.
Definition mathlib.cpp:17
double factorial(int a, MathError &err)
Implementation of function factorial.
Definition mathlib.cpp:47
double power(double base, int exp)
Implementation of function power.
Definition mathlib.cpp:67