diff --git a/CMakeLists.txt b/CMakeLists.txt index d819e35..4603e7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,3 +6,4 @@ include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() add_subdirectory(source) +add_subdirectory(test) diff --git a/conanfile.txt b/conanfile.txt index dd246ef..7591bc8 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -1,5 +1,6 @@ [requires] protobuf/3.6.1@bincrafters/stable +catch2/2.4.2@bincrafters/stable [generators] cmake diff --git a/source/Age.cpp b/source/Age/Age.cpp similarity index 95% rename from source/Age.cpp rename to source/Age/Age.cpp index 81415e9..05613a4 100644 --- a/source/Age.cpp +++ b/source/Age/Age.cpp @@ -4,8 +4,8 @@ #include Age::Age(unsigned int years, unsigned int months) - : m_years(years) - , m_months(months) + : m_years(years) + , m_months(months) { } @@ -37,7 +37,7 @@ Age::Age(const QDate &birth, const QDate &reference) m_years = years; m_months = months; } - + bool Age::operator<(const Age &cmp) const { if (m_years == cmp.m_years) @@ -47,7 +47,7 @@ bool Age::operator<(const Age &cmp) const return m_years < cmp.m_years; } - + unsigned int Age::years() const { return m_years; @@ -57,7 +57,7 @@ unsigned int Age::months() const { return m_months; } - + std::string Age::toString() const { std::ostringstream result; diff --git a/source/Age.h b/source/Age/Age.h similarity index 100% rename from source/Age.h rename to source/Age/Age.h diff --git a/source/Age/CMakeLists.txt b/source/Age/CMakeLists.txt new file mode 100644 index 0000000..820be2c --- /dev/null +++ b/source/Age/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.6) + +project(Age LANGUAGES CXX) + +find_package(Qt5Core REQUIRED) + +add_library(${PROJECT_NAME} + Age.cpp +) + +set_target_properties(${PROJECT_NAME} + PROPERTIES CXX_STANDARD 14 +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(${PROJECT_NAME} + PUBLIC + Qt5::Core +) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index ab95560..0a0f40f 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -34,10 +34,9 @@ protobuf_generate_cpp(DataModel_PROTO_SRCS DataModel_PROTO_HDRS ${DataModel_PROTO_FILES}) add_executable(${PROJECT_NAME} WIN32 - LogoTest.cpp + ESGRAF48.cpp DataModel.cpp mainwindow.cpp - Age.cpp ${LOGO_TEST_UI} ${LOGO_TEST_QRC} ${DataModel_PROTO_SRCS} @@ -57,6 +56,7 @@ target_include_directories(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} PRIVATE + Age CheckableItem CheckableTest CheckableTestModel @@ -73,6 +73,7 @@ target_link_libraries(${PROJECT_NAME} ${Protobuf_LIBRARIES} ) +add_subdirectory(Age) add_subdirectory(CheckableItem) add_subdirectory(CheckableTest) add_subdirectory(CheckableTestModel) diff --git a/source/ESGRAF48.cpp b/source/ESGRAF48.cpp new file mode 100644 index 0000000..1f15804 --- /dev/null +++ b/source/ESGRAF48.cpp @@ -0,0 +1,21 @@ +#include "mainwindow.h" +#include + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + std::unique_ptr mainWindow; + if (argc < 2) + { + mainWindow = std::make_unique(nullptr); + } + else + { + mainWindow = std::make_unique(nullptr, argv[1]); + } + + mainWindow->show(); + + return app.exec(); +} diff --git a/source/LogoTest.cpp b/source/LogoTest.cpp deleted file mode 100644 index 30539a1..0000000 --- a/source/LogoTest.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "mainwindow.h" -#include - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - MainWindow mainWindow; - mainWindow.show(); - - return app.exec(); -} diff --git a/source/MetaData/CMakeLists.txt b/source/MetaData/CMakeLists.txt index b61703a..e00d8de 100644 --- a/source/MetaData/CMakeLists.txt +++ b/source/MetaData/CMakeLists.txt @@ -41,6 +41,7 @@ target_include_directories(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} PRIVATE + Age Qt5::Widgets ${Protobuf_LIBRARIES} ) diff --git a/source/MetaData/MetaDataModel.h b/source/MetaData/MetaDataModel.h index d2ebaa7..0c8bbeb 100644 --- a/source/MetaData/MetaDataModel.h +++ b/source/MetaData/MetaDataModel.h @@ -1,6 +1,6 @@ #pragma once -#include "../Age.h" +#include "Age.h" #include "MetaDataModel.pb.h" diff --git a/source/ResultWidget/CMakeLists.txt b/source/ResultWidget/CMakeLists.txt index b85d0c1..bfdd22c 100644 --- a/source/ResultWidget/CMakeLists.txt +++ b/source/ResultWidget/CMakeLists.txt @@ -30,5 +30,6 @@ target_include_directories(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} PRIVATE + Age Qt5::Widgets ) diff --git a/source/ResultWidget/PRMap.h b/source/ResultWidget/PRMap.h index 5ad5bcf..6d9104c 100644 --- a/source/ResultWidget/PRMap.h +++ b/source/ResultWidget/PRMap.h @@ -1,6 +1,6 @@ #pragma once -#include "../Age.h" +#include "Age.h" #include class PRMap diff --git a/source/ResultWidget/ResultModel.h b/source/ResultWidget/ResultModel.h index 1c290f4..ae6dd78 100644 --- a/source/ResultWidget/ResultModel.h +++ b/source/ResultWidget/ResultModel.h @@ -1,6 +1,6 @@ #pragma once -#include "../Age.h" +#include "Age.h" #include class TestResult diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index 20d877a..e91549a 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -1,8 +1,6 @@ #include "mainwindow.h" #include "ui_mainwindow.h" -#include "DataModel.h" - #include #include #include @@ -21,16 +19,46 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) + , m_dataModel(this) { ui->setupUi(this); + setupUi(); + + newFile(); +} + +MainWindow::MainWindow(QWidget *parent, const QString &filename) + : QMainWindow(parent) + , ui(new Ui::MainWindow) + , m_dataModel(this) +{ + ui->setupUi(this); + setupUi(); + + openFile(filename); +} + +void MainWindow::setupUi() +{ + ui->metaDataWidget->setModel(&m_dataModel.m_metaData); + ui->verbEndWidget->setModel(&m_dataModel.m_verbEnd); + ui->genusWidget->setModel(&m_dataModel.m_genus); + ui->pluralWidget->setModel(&m_dataModel.m_plural); + ui->akkusativDativWidget->setAkkusativModel(&m_dataModel.m_akkusativ); + ui->akkusativDativWidget->setDativModel(&m_dataModel.m_dativ); + ui->v2SvkWidget->setV2SvkModel(&m_dataModel.m_v2Svk); + ui->lateSkillsWidget->setPassivModel(&m_dataModel.m_passiv); + ui->lateSkillsWidget->setGenitivModel(&m_dataModel.m_genitiv); + ui->resultWidget->setModel(&m_dataModel.m_results); connect(ui->actionNew, &QAction::triggered, this, &MainWindow::newFile); - connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::openFile); + connect(ui->actionOpen, &QAction::triggered, this, qOverload<>(&MainWindow::openFile)); connect(ui->actionSave, &QAction::triggered, this, qOverload<>(&MainWindow::saveFile)); connect(ui->actionSave_as, &QAction::triggered, this, &MainWindow::saveFileAs); connect(ui->actionPrint, &QAction::triggered, this, &MainWindow::print); + connect(ui->actionExport_PDF, &QAction::triggered, this, qOverload<>(&MainWindow::savePdf)); - newFile(); + connect(&m_dataModel, &DataModel::modelChanged, this, &MainWindow::dataModelChanged); } MainWindow::~MainWindow() @@ -42,21 +70,6 @@ void MainWindow::newFile() { closeFile(); - m_dataModel = std::make_unique(this); - ui->metaDataWidget->setModel(&m_dataModel->m_metaData); - ui->verbEndWidget->setModel(&m_dataModel->m_verbEnd); - ui->genusWidget->setModel(&m_dataModel->m_genus); - ui->pluralWidget->setModel(&m_dataModel->m_plural); - ui->akkusativDativWidget->setAkkusativModel(&m_dataModel->m_akkusativ); - ui->akkusativDativWidget->setDativModel(&m_dataModel->m_dativ); - ui->v2SvkWidget->setV2SvkModel(&m_dataModel->m_v2Svk); - ui->lateSkillsWidget->setPassivModel(&m_dataModel->m_passiv); - ui->lateSkillsWidget->setGenitivModel(&m_dataModel->m_genitiv); - - ui->resultWidget->setModel(&m_dataModel->m_results); - - connect(&*m_dataModel, &DataModel::modelChanged, this, &MainWindow::dataModelChanged); - setWindowModified(false); setWindowTitle("untitled[*]"); m_filename = ""; @@ -72,10 +85,15 @@ void MainWindow::openFile() return; } + openFile(filename); +} + +void MainWindow::openFile(const QString &filename) +{ closeFile(); std::fstream protoInFile(filename.toStdString(), std::ios::in | std::ios::binary); - m_dataModel->read(protoInFile); + m_dataModel.read(protoInFile); setWindowModified(false); setWindowTitle(filename + "[*]"); @@ -133,7 +151,7 @@ void MainWindow::closeFile() void MainWindow::print() const { //std::ofstream htmlfile("print.html"); - //htmlfile << m_dataModel->toHtml(); + //htmlfile << m_dataModel.toHtml(); QPrinter printer; @@ -144,7 +162,7 @@ void MainWindow::print() const } QTextDocument printDoc; - printDoc.setHtml(QString::fromStdString(m_dataModel->toHtml())); + printDoc.setHtml(QString::fromStdString(m_dataModel.toHtml())); printDoc.print(&printer); } @@ -155,6 +173,22 @@ void MainWindow::dataModelChanged() setWindowModified(true); } +void MainWindow::savePdf() +{ + QFileDialog saveFilenameDialog(this); + saveFilenameDialog.setDefaultSuffix("pdf"); + saveFilenameDialog.setFileMode(QFileDialog::AnyFile); + saveFilenameDialog.setNameFilter("PDF File (*.pdf)"); + saveFilenameDialog.setWindowTitle("Save file"); + + if (!saveFilenameDialog.exec()) + { + return; + } + + savePdf(saveFilenameDialog.selectedFiles().first()); +} + void MainWindow::closeEvent(QCloseEvent *event) { closeFile(); @@ -164,7 +198,7 @@ void MainWindow::saveFile(const QString &filename) { std::fstream protoOutFile(filename.toStdString(), std::ios::out | std::ios::trunc | std::ios::binary); - m_dataModel->write(protoOutFile); + m_dataModel.write(protoOutFile); qDebug() << "Wrote" << filename; @@ -173,3 +207,16 @@ void MainWindow::saveFile(const QString &filename) m_filename = filename; m_saveOnClose = false; } + +void MainWindow::savePdf(const QString &filename) +{ + QPrinter printer; + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setPaperSize(QPrinter::A4); + printer.setOutputFileName(filename); + + QTextDocument printDoc; + printDoc.setHtml(QString::fromStdString(m_dataModel.toHtml())); + + printDoc.print(&printer); +} diff --git a/source/mainwindow.h b/source/mainwindow.h index 78fa2bb..9675fb7 100644 --- a/source/mainwindow.h +++ b/source/mainwindow.h @@ -1,8 +1,10 @@ #pragma once -#include +#include "DataModel.h" + +#include +#include -#include class DataModel; class QDataWidgetMapper; @@ -17,26 +19,31 @@ class MainWindow : public QMainWindow private: Ui::MainWindow *ui; - std::unique_ptr m_dataModel; + DataModel m_dataModel; QString m_filename; bool m_saveOnClose = false; public: - MainWindow(QWidget *parent = nullptr); + MainWindow(QWidget *parent); + MainWindow(QWidget *parent, const QString &filename); ~MainWindow(); public slots: void newFile(); void openFile(); + void openFile(const QString &filename); void saveFile(); void saveFileAs(); void closeFile(); void print() const; void dataModelChanged(); + void savePdf(); protected: void closeEvent(QCloseEvent *event) override; private: + void setupUi(); void saveFile(const QString &filename); + void savePdf(const QString &filename); }; diff --git a/source/mainwindow.ui b/source/mainwindow.ui index 86d0199..9622ce3 100644 --- a/source/mainwindow.ui +++ b/source/mainwindow.ui @@ -133,6 +133,7 @@ + @@ -228,6 +229,14 @@ Ctrl+P + + + Export PDF + + + Export as PDF file + + diff --git a/test/Age.cpp b/test/Age.cpp new file mode 100644 index 0000000..22b0fbb --- /dev/null +++ b/test/Age.cpp @@ -0,0 +1,40 @@ +#include + +#include "Age.h" + +TEST_CASE("default initialization") +{ + Age age; + REQUIRE(age.years() == 0); + REQUIRE(age.months() == 0); + REQUIRE(age.toString() == "0;0"); + + Age age2; + REQUIRE(!(age < age)); + REQUIRE(!(age < age2)); +} + +TEST_CASE("year/month initialization") +{ + for (unsigned int year = 0; year <= 100; ++year) + { + for (unsigned int month = 0; month < 12; ++month) + { + Age age(year, month); + + REQUIRE(age.years() == year); + REQUIRE(age.months() == month); + } + } +} + +TEST_CASE("age by reference") +{ + QDate birth(1970, 1, 1); + QDate reference(1980, 1, 1); + + Age age(birth, reference); + + REQUIRE(age.years() == 10); + REQUIRE(age.months() == 0); +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..5984746 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.5) +project(run-tests) + +find_package(Catch2 REQUIRED) + +add_executable(${PROJECT_NAME} + main.cpp + dummy.cpp + Age.cpp +) + +target_link_libraries(${PROJECT_NAME} + PRIVATE + Catch2::Catch2 + Age +) + +include(CTest) +include(Catch) +catch_discover_tests(${PROJECT_NAME}) + diff --git a/test/dummy.cpp b/test/dummy.cpp new file mode 100644 index 0000000..0eb8941 --- /dev/null +++ b/test/dummy.cpp @@ -0,0 +1,7 @@ +#include + +TEST_CASE("Dummy") +{ + REQUIRE(true == true); +} + diff --git a/test/main.cpp b/test/main.cpp new file mode 100644 index 0000000..4ed06df --- /dev/null +++ b/test/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include