Initial commit: Qt Colculator with C++20

This commit is contained in:
Sigismund Dijkstra 2025-07-12 19:11:31 -05:00
commit 0196d4ab36
6 changed files with 277 additions and 0 deletions

27
.gitignore vendored Normal file
View File

@ -0,0 +1,27 @@
# Build directories
build/
cmake-build-*/
# Qt MOC files
moc_*.cpp
moc_*.h
*.moc
# IDE files
.idea/
.vscode/
*.user
*.pro.user*
# Executables
Calculator
*.exe
# CMake
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
Makefile
# Debug files
*.dSYM/

19
CMakeLists.txt Normal file
View File

@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.16)
project(Calculator)
set(CMAKE_CXX_STANDARD 20)
# Добавить флаги для отладки
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")
endif()
find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
set(CMAKE_AUTOMOC ON)
add_executable(Calculator main.cpp
Calculator.cpp
Calculator.h)
target_link_libraries(Calculator Qt5::Core Qt5::Widgets)

154
Calculator.cpp Normal file
View File

@ -0,0 +1,154 @@
#include "Calculator.h"
#include <QVBoxLayout>
#include <QGridLayout>
#include <QString>
#include <QApplication>
Calculator::Calculator(QWidget *parent) : QWidget(parent)
{
setupUI(); // Set up the user interface
connectSignals(); // Connect signals and slots
setWindowTitle("Calculator"); // Set the window title
resize(300, 400); // Resize the window to a reasonable size
}
void Calculator::setupUI()
{
auto *mainLayout = new QVBoxLayout(this);
//Display setup
display = new QLineEdit("0");
display -> setReadOnly(true);
display -> setAlignment(Qt::AlignRight);
display -> setStyleSheet("font-size: 18px; padding: 10px;");
mainLayout -> addWidget(display);
// Button grid
auto *gridLayout = new QGridLayout();
// Clear button
clearBtn = new QPushButton("C");
gridLayout -> addWidget(clearBtn, 0, 0, 1, 4);
// Number buttons
for (int i = 1; i <= 9; ++i)
{
auto *btn = new QPushButton(QString::number(i));
int row = 3- (i - 1) / 3;
int col = (i - 1) % 3;
gridLayout -> addWidget(btn, row, col);
connect(btn, &QPushButton::clicked, this, &Calculator::digitClicked);
}
//Zero button
auto *zeroBtn = new QPushButton("0");
gridLayout -> addWidget(zeroBtn, 4, 0, 1, 2);
connect(zeroBtn, &QPushButton::clicked, this, &Calculator::digitClicked);
// Decimal point button
auto *dotBtn = new QPushButton(".");
gridLayout -> addWidget(dotBtn, 4, 2);
connect(dotBtn, &QPushButton::clicked, this, &Calculator::digitClicked);
// Operator buttons
auto *addBtn = new QPushButton("+");
auto *subBtn = new QPushButton("-");
auto *mulBtn = new QPushButton("*");
auto *divBtn = new QPushButton("/");
equalBtn = new QPushButton("=");
gridLayout -> addWidget(divBtn, 1, 3);
gridLayout -> addWidget(mulBtn, 2, 3);
gridLayout -> addWidget(subBtn, 3, 3);
gridLayout -> addWidget(addBtn, 4, 3);
gridLayout -> addWidget(equalBtn, 5, 0, 1, 4);
mainLayout -> addLayout(gridLayout);
// Store buttons for connections
operatorButtons = {addBtn, subBtn, mulBtn, divBtn};
}
void Calculator::connectSignals()
{
for (auto *btn : operatorButtons)
{
connect(btn, &QPushButton::clicked, this, &Calculator::operatorClicked);
}
connect(clearBtn, &QPushButton::clicked, this, &Calculator::clearDisplay);
connect(equalBtn, &QPushButton::clicked, this, &Calculator::calculateResult);
}
void Calculator::digitClicked()
{
const auto *button = qobject_cast<QPushButton *>(sender()); // const auto*
const QString digit = button -> text(); // const
if (waitingForOperand) {
display -> clear();
waitingForOperand = false;
}
if (display -> text() == "0" && digit != ".") {
display -> clear();
}
display -> setText(display -> text() + digit);
}
void Calculator::operatorClicked()
{
auto *button = qobject_cast<QPushButton *>(sender());
const QString op = button -> text();
if (!waitingForOperand && !operation.isEmpty()) {
calculateResult();
}
firstNumber = display -> text().toDouble();
operation = op;
waitingForOperand = true;
}
void Calculator::calculateResult()
{
if (waitingForOperand || operation.isEmpty()) {
return; // No operation to perform
}
double secondNumber = display -> text().toDouble();
double result = 0.0;
if (operation == "+")
result = firstNumber + secondNumber;
else if (operation == "-")
result = firstNumber - secondNumber;
else if (operation == "*")
result = firstNumber * secondNumber;
else if (operation == "/")
{
if (secondNumber != 0)
result = firstNumber / secondNumber;
else
{
display -> setText("Error");
clearDisplay();
return;
}
}
display -> setText(QString::number(result));
operation.clear();
waitingForOperand = true;
}
void Calculator::clearDisplay()
{
display -> setText("0");
firstNumber = 0.0;
operation.clear();
waitingForOperand = true;
}

44
Calculator.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef CALCULATOR_H
#define CALCULATOR_H
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QList>
class Calculator final : public QWidget{
Q_OBJECT
public:
explicit Calculator(QWidget *parent = nullptr);
~Calculator() override = default;
Calculator(const Calculator &) = delete;
Calculator &operator=(const Calculator &) = delete;
Calculator(Calculator &&) = delete;
Calculator &operator=(Calculator &&) = delete;
private slots:
void digitClicked();
void operatorClicked();
void calculateResult();
void clearDisplay();
private:
void setupUI();
void connectSignals();
QLineEdit *display;
QPushButton *clearBtn;
QPushButton *equalBtn;
QList<QPushButton *> operatorButtons;
double firstNumber = 0.0;
QString operation;
bool waitingForOperand = true;
};
#endif //CALCULATOR_H

20
README.md Normal file
View File

@ -0,0 +1,20 @@
# Qt Calculator
A simple calculator application built with Qt5 and C++20.
## Features
- Basic arithmetic operations (+, -, *, /)
- Clear functionality
- Error handling for division by zero
- Modern C++ practices (Rule of Five)
## Build Requirements
- Qt5 (Core, Widgets)
- CMake 3.16+
- C++20 compatible compiler
## Building
```bash
mkdir build && cd build
cmake ..
make

13
main.cpp Normal file
View File

@ -0,0 +1,13 @@
#include <QApplication>
#include "Calculator.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
Calculator calculator;
calculator.show();
return app.exec();
}