From ec4da11bb89121d90cedeaea3f5ba8c013cf3f5f Mon Sep 17 00:00:00 2001 From: Darkheim Date: Mon, 21 Jul 2025 00:20:08 -0500 Subject: [PATCH] Small fixes --- .gitattributes | 24 ++++ .github/workflows/build.yml | 31 ++++++ CMakeLists.txt | 19 +++- Calculator.cpp | 212 ++++++++++++++++++------------------ README.md | 80 +++++++++++++- build.sh | 21 ++++ qt-project.pro | 17 +++ 7 files changed, 291 insertions(+), 113 deletions(-) create mode 100644 .gitattributes create mode 100644 .github/workflows/build.yml create mode 100644 build.sh create mode 100644 qt-project.pro diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..2e80584 --- /dev/null +++ b/.gitattributes @@ -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 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..c1efa96 --- /dev/null +++ b/.github/workflows/build.yml @@ -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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 8700200..7e3ee76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/Calculator.cpp b/Calculator.cpp index 63d231c..20c44bf 100644 --- a/Calculator.cpp +++ b/Calculator.cpp @@ -5,150 +5,150 @@ #include - 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(sender()); // const auto* - const QString digit = button -> text(); // const + const auto *button = qobject_cast(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(sender()); - const QString op = button -> text(); + auto *button = qobject_cast(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; } diff --git a/README.md b/README.md index 3d3e787..e05f340 100644 --- a/README.md +++ b/README.md @@ -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 \ No newline at end of file +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 .. +``` \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..fc347f0 --- /dev/null +++ b/build.sh @@ -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" diff --git a/qt-project.pro b/qt-project.pro new file mode 100644 index 0000000..e7f1f5e --- /dev/null +++ b/qt-project.pro @@ -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