From a2b85eba83e9af615db30f90051d9cb76df7dfe9 Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sat, 24 Nov 2018 19:55:16 +0100 Subject: [PATCH 1/6] Added Catch2 tests, moved Age-class to own library --- CMakeLists.txt | 1 + conanfile.txt | 1 + source/{ => Age}/Age.cpp | 0 source/{ => Age}/Age.h | 0 source/Age/CMakeLists.txt | 23 +++++++++++++++++++++++ source/CMakeLists.txt | 3 ++- source/MetaData/CMakeLists.txt | 1 + source/MetaData/MetaDataModel.h | 2 +- source/ResultWidget/CMakeLists.txt | 1 + source/ResultWidget/PRMap.h | 2 +- source/ResultWidget/ResultModel.h | 2 +- test/Age.cpp | 17 +++++++++++++++++ test/CMakeLists.txt | 21 +++++++++++++++++++++ test/dummy.cpp | 7 +++++++ test/main.cpp | 2 ++ 15 files changed, 79 insertions(+), 4 deletions(-) rename source/{ => Age}/Age.cpp (100%) rename source/{ => Age}/Age.h (100%) create mode 100644 source/Age/CMakeLists.txt create mode 100644 test/Age.cpp create mode 100644 test/CMakeLists.txt create mode 100644 test/dummy.cpp create mode 100644 test/main.cpp 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 100% rename from source/Age.cpp rename to source/Age/Age.cpp 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..72bf70e 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -37,7 +37,6 @@ add_executable(${PROJECT_NAME} WIN32 LogoTest.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/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/test/Age.cpp b/test/Age.cpp new file mode 100644 index 0000000..46948b8 --- /dev/null +++ b/test/Age.cpp @@ -0,0 +1,17 @@ +#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)); +} + + 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 From 09f8fa4faf6b2b818ded3a8b9da3a7dccaee400e Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sat, 24 Nov 2018 20:08:01 +0100 Subject: [PATCH 2/6] Added some more tests --- test/Age.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/Age.cpp b/test/Age.cpp index 46948b8..34b3788 100644 --- a/test/Age.cpp +++ b/test/Age.cpp @@ -14,4 +14,16 @@ TEST_CASE("default initialization") REQUIRE(!(age < age2)); } +TEST_CASE("year/month initialization") +{ + for (unsigned int year = 0; year <= 100; ++year) + { + for (unsigned int month = 1; month <= 12; ++month) + { + Age age(year, month); + REQUIRE(age.years() == year); + REQUIRE(age.months() == month); + } + } +} From 220f92453d9d9cb959b6ec2c13fd340b3c74cb8b Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sun, 25 Nov 2018 14:30:45 +0100 Subject: [PATCH 3/6] Added more Age-class tests --- source/Age/Age.cpp | 10 +++++----- test/Age.cpp | 13 ++++++++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/source/Age/Age.cpp b/source/Age/Age.cpp index 81415e9..05613a4 100644 --- a/source/Age/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/test/Age.cpp b/test/Age.cpp index 34b3788..22b0fbb 100644 --- a/test/Age.cpp +++ b/test/Age.cpp @@ -18,7 +18,7 @@ TEST_CASE("year/month initialization") { for (unsigned int year = 0; year <= 100; ++year) { - for (unsigned int month = 1; month <= 12; ++month) + for (unsigned int month = 0; month < 12; ++month) { Age age(year, month); @@ -27,3 +27,14 @@ TEST_CASE("year/month initialization") } } } + +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); +} From 4fefdc65c5f7df1168c71255f3019aeebef1b7e2 Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sun, 2 Dec 2018 15:22:44 +0100 Subject: [PATCH 4/6] Open first command line argument as file --- source/LogoTest.cpp | 14 ++++++++-- source/mainwindow.cpp | 63 +++++++++++++++++++++++++++---------------- source/mainwindow.h | 13 ++++++--- 3 files changed, 61 insertions(+), 29 deletions(-) diff --git a/source/LogoTest.cpp b/source/LogoTest.cpp index 30539a1..1f15804 100644 --- a/source/LogoTest.cpp +++ b/source/LogoTest.cpp @@ -4,8 +4,18 @@ int main(int argc, char **argv) { QApplication app(argc, argv); - MainWindow mainWindow; - mainWindow.show(); + + 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/mainwindow.cpp b/source/mainwindow.cpp index 20d877a..cf307db 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,45 @@ 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); - newFile(); + connect(&m_dataModel, &DataModel::modelChanged, this, &MainWindow::dataModelChanged); } MainWindow::~MainWindow() @@ -42,21 +69,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 +84,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 +150,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 +161,7 @@ void MainWindow::print() const } QTextDocument printDoc; - printDoc.setHtml(QString::fromStdString(m_dataModel->toHtml())); + printDoc.setHtml(QString::fromStdString(m_dataModel.toHtml())); printDoc.print(&printer); } @@ -164,7 +181,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; diff --git a/source/mainwindow.h b/source/mainwindow.h index 78fa2bb..c2cf130 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,17 +19,19 @@ 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(); @@ -38,5 +42,6 @@ protected: void closeEvent(QCloseEvent *event) override; private: + void setupUi(); void saveFile(const QString &filename); }; From f38b9194fdf572cb9b290a87fcdbf64c47bc33b1 Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sat, 8 Dec 2018 16:39:33 +0100 Subject: [PATCH 5/6] Renamed LogoTest.cpp to ESGRAF48.cpp --- source/CMakeLists.txt | 2 +- source/{LogoTest.cpp => ESGRAF48.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename source/{LogoTest.cpp => ESGRAF48.cpp} (100%) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 72bf70e..0a0f40f 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -34,7 +34,7 @@ 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 ${LOGO_TEST_UI} diff --git a/source/LogoTest.cpp b/source/ESGRAF48.cpp similarity index 100% rename from source/LogoTest.cpp rename to source/ESGRAF48.cpp From bdf9706e58a82c301f0013567f6cee359169e492 Mon Sep 17 00:00:00 2001 From: Michael Mandl Date: Sun, 9 Dec 2018 11:11:55 +0100 Subject: [PATCH 6/6] Added pdf export --- source/mainwindow.cpp | 30 ++++++++++++++++++++++++++++++ source/mainwindow.h | 2 ++ source/mainwindow.ui | 9 +++++++++ 3 files changed, 41 insertions(+) diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index cf307db..e91549a 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -56,6 +56,7 @@ void MainWindow::setupUi() 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)); connect(&m_dataModel, &DataModel::modelChanged, this, &MainWindow::dataModelChanged); } @@ -172,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(); @@ -190,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 c2cf130..9675fb7 100644 --- a/source/mainwindow.h +++ b/source/mainwindow.h @@ -37,6 +37,7 @@ public slots: void closeFile(); void print() const; void dataModelChanged(); + void savePdf(); protected: void closeEvent(QCloseEvent *event) override; @@ -44,4 +45,5 @@ protected: 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 + +