Small fixes

This commit is contained in:
Sigismund Dijkstra 2025-07-21 00:20:08 -05:00
parent 0196d4ab36
commit ec4da11bb8
7 changed files with 291 additions and 113 deletions

24
.gitattributes vendored Normal file
View File

@ -0,0 +1,24 @@
# Set default behavior to automatically normalize line endings
* text=auto
# C++ source files
*.cpp text diff=cpp
*.h text diff=cpp
# CMake files
CMakeLists.txt text
*.cmake text
# QMake files
*.pro text
# Bash scripts
*.sh text eol=lf
# Documentation
*.md text diff=markdown
# Binary files
*.png binary
*.jpg binary
*.ico binary

31
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Build Qt Calculator
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Qt
run: |
sudo apt-get update
sudo apt-get install -y qtbase5-dev qt5-qmake cmake
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build
- name: Build
run: cmake --build ${{github.workspace}}/build
- name: Test
working-directory: ${{github.workspace}}/build
run: |
echo "Running built application to verify it works"
# Add tests if you implement them later

View File

@ -8,9 +8,26 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")
endif()
find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
# Установить пути поиска для Qt5
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/lib/qt5" "/usr/lib/x86_64-linux-gnu/qt5" "/usr/lib/cmake/Qt5")
# Альтернативный способ поиска Qt5
if(NOT Qt5_DIR)
set(Qt5_DIR "/usr/lib/cmake/Qt5")
endif()
# Настройка Qt5 и пути модулей
find_package(Qt5 COMPONENTS Core Widgets QUIET)
# Проверка наличия Qt5
if(NOT Qt5_FOUND)
message(FATAL_ERROR "Qt5 не найден. Установите пакеты Qt5: sudo apt install qtbase5-dev qt5-qmake")
endif()
# Включение автоматической генерации MOC-файлов для Qt
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
add_executable(Calculator main.cpp
Calculator.cpp

View File

@ -5,150 +5,150 @@
#include <QApplication>
Calculator::Calculator(QWidget *parent) : QWidget(parent)
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)
{
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
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);
}
void Calculator::setupUI()
{
auto *mainLayout = new QVBoxLayout(this);
// Zero button
auto *zeroBtn = new QPushButton("0");
gridLayout->addWidget(zeroBtn, 4, 0, 1, 2);
connect(zeroBtn, &QPushButton::clicked, this, &Calculator::digitClicked);
//Display setup
display = new QLineEdit("0");
display -> setReadOnly(true);
display -> setAlignment(Qt::AlignRight);
display -> setStyleSheet("font-size: 18px; padding: 10px;");
mainLayout -> addWidget(display);
// Decimal point button
auto *dotBtn = new QPushButton(".");
gridLayout->addWidget(dotBtn, 4, 2);
connect(dotBtn, &QPushButton::clicked, this, &Calculator::digitClicked);
// Button grid
auto *gridLayout = new QGridLayout();
// Operator buttons
auto *addBtn = new QPushButton("+");
auto *subBtn = new QPushButton("-");
auto *mulBtn = new QPushButton("*");
auto *divBtn = new QPushButton("/");
equalBtn = new QPushButton("=");
// Clear button
clearBtn = new QPushButton("C");
gridLayout -> addWidget(clearBtn, 0, 0, 1, 4);
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);
// 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);
}
mainLayout->addLayout(gridLayout);
//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};
// Store buttons for connections
operatorButtons = {addBtn, subBtn, mulBtn, divBtn};
}
void Calculator::connectSignals()
{
for (auto *btn : operatorButtons)
{
connect(btn, &QPushButton::clicked, this, &Calculator::operatorClicked);
}
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);
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
const auto *button = qobject_cast<QPushButton *>(sender());
const QString digit = button->text();
if (waitingForOperand) {
display -> clear();
waitingForOperand = false;
}
if (waitingForOperand) {
display->clear();
waitingForOperand = false;
}
if (display -> text() == "0" && digit != ".") {
display -> clear();
}
if (display->text() == "0" && digit != ".") {
display->clear();
}
display -> setText(display -> text() + digit);
display->setText(display->text() + digit);
}
void Calculator::operatorClicked()
{
auto *button = qobject_cast<QPushButton *>(sender());
const QString op = button -> text();
auto *button = qobject_cast<QPushButton *>(sender());
const QString op = button->text();
if (!waitingForOperand && !operation.isEmpty()) {
calculateResult();
}
if (!waitingForOperand && !operation.isEmpty()) {
calculateResult();
}
firstNumber = display -> text().toDouble();
operation = op;
waitingForOperand = true;
firstNumber = display->text().toDouble();
operation = op;
waitingForOperand = true;
}
void Calculator::calculateResult()
{
if (waitingForOperand || operation.isEmpty()) {
return; // No operation to perform
}
if (waitingForOperand || operation.isEmpty()) {
return; // No operation to perform
}
double secondNumber = display -> text().toDouble();
double result = 0.0;
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 (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
{
if (secondNumber != 0)
result = firstNumber / secondNumber;
else
{
display -> setText("Error");
clearDisplay();
return;
}
display->setText("Error");
clearDisplay();
return;
}
}
display -> setText(QString::number(result));
operation.clear();
waitingForOperand = true;
display->setText(QString::number(result));
operation.clear();
waitingForOperand = true;
}
void Calculator::clearDisplay()
{
display -> setText("0");
firstNumber = 0.0;
operation.clear();
waitingForOperand = true;
display->setText("0");
firstNumber = 0.0;
operation.clear();
waitingForOperand = true;
}

View File

@ -3,18 +3,86 @@ # 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)
- Modern C++ practices (Rule of Five implementation)
## Build Requirements
- Qt5 (Core, Widgets)
- CMake 3.16+
## Requirements
To compile and run this project, you need:
- CMake 3.16 or higher
- Qt5 (Core and Widgets)
- C++20 compatible compiler
## Building
## Installing Dependencies
### Ubuntu/Debian:
```bash
# Full development environment
sudo apt install qtcreator qtbase5-dev qt5-qmake qtbase5-dev-tools cmake
# Minimal required packages
sudo apt install qtbase5-dev qt5-qmake cmake
```
### Verifying Qt5 Installation
Check if Qt5 packages are installed and locate them:
```bash
dpkg -l | grep qt5
find /usr -name "Qt5Config.cmake"
```
If Qt5Config.cmake is not found, install the necessary packages:
```bash
sudo apt install qtbase5-dev
```
### Fedora:
```bash
sudo dnf install qt5-qtbase-devel qt5-qttools-devel qt-creator cmake
```
### Arch Linux:
```bash
sudo pacman -S qt5-base qt5-tools qtcreator cmake
```
## Building the Project
### Using CMake (recommended)
```bash
mkdir build && cd build
cmake ..
make
make
```
### Using QMake (alternative)
```bash
qmake qt-project.pro
make
```
## Running the Application
```bash
./Calculator
```
## Troubleshooting Qt5 Find Issues
If CMake cannot find Qt5, you can specify the Qt5 path manually:
```bash
cmake -DQt5_DIR=/path/to/qt5/lib/cmake/Qt5 ..
```

21
build.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/bash
# Check for Qt5 installation
if ! dpkg -l | grep -q qtbase5-dev; then
echo "Qt5 is not installed. Installing required packages..."
sudo apt install -y qtbase5-dev qt5-qmake cmake
fi
# Create build directory
mkdir -p build
cd build
# Configure CMake with Qt5 paths
cmake .. \
-DQt5_DIR=/usr/lib/cmake/Qt5 \
-DCMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake
# Build the project
make
echo "Build completed. Run the calculator with: ./build/Calculator"

17
qt-project.pro Normal file
View File

@ -0,0 +1,17 @@
# Alternative project file for Qt Creator and qmake
QT += core widgets
CONFIG += c++20
TARGET = Calculator
TEMPLATE = app
SOURCES += main.cpp \
Calculator.cpp
HEADERS += Calculator.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target