Compare commits

..

18 Commits

Author SHA1 Message Date
e64ef375fb Increased print resolution to get thinner table borders 2018-12-15 17:10:21 +01:00
c8bd1bbdb8 Paint empty result cells gray 2018-12-15 16:31:51 +01:00
6eb585b08c Use central table format for printing 2018-12-15 16:12:20 +01:00
a718113747 Print subtest 1 2018-12-13 20:46:38 +01:00
be3a3f453d WIP V2/Svk printing 2018-12-12 22:19:42 +01:00
cc20d46a76 Print causal sentence points 2018-12-12 21:40:26 +01:00
8ef56f1855 Display causal sentence point count below subtest 2 2018-12-12 21:33:44 +01:00
98196e05d6 Implemented printing for late skills tests 2018-12-10 22:29:49 +01:00
f6c2da5edc Implemented plural-test printing 2018-12-10 21:11:46 +01:00
2570d5d5b5 Print results 2018-12-09 12:49:12 +01:00
c065b04cbe Use std::accumulate instead of manually adding 2018-12-09 11:27:13 +01:00
e89f157bac Merge branch 'develop' into feature/print-as-qtextdocument 2018-12-09 11:14:41 +01:00
49b52f1dbc Print subtests 2, 3 and 4 2018-12-08 21:02:35 +01:00
e2237110cf Merge branch 'develop' into feature/print-as-qtextdocument 2018-12-08 17:02:46 +01:00
b06e717575 Very basic subtest 2 print output 2018-12-02 22:57:56 +01:00
bcd0b17caa Removed html output 2018-11-28 22:43:32 +01:00
bf08d0c5e4 Print formatting 2018-11-28 22:39:51 +01:00
bf963adeb5 Print metadata and v2svk header 2018-11-26 21:47:42 +01:00
70 changed files with 1066 additions and 2124 deletions

4
.gitignore vendored
View File

@ -1,9 +1,5 @@
compile_commands.json compile_commands.json
_*/ _*/
build/
build-* build-*
*.user *.user
tags tags
*.esgraf48
*.swp
*.pdf

View File

@ -2,14 +2,8 @@ cmake_minimum_required(VERSION 3.5)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(cmake/conan.cmake)
conan_cmake_run(CONANFILE conanfile.txt
BASIC_SETUP
BUILD missing
)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup() conan_basic_setup()
add_subdirectory(source) add_subdirectory(source)
#add_subdirectory(test) add_subdirectory(test)

View File

@ -1,516 +0,0 @@
# The MIT License (MIT)
# Copyright (c) 2018 JFrog
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# This file comes from: https://github.com/conan-io/cmake-conan. Please refer
# to this repository for issues and documentation.
# Its purpose is to wrap and launch Conan C/C++ Package Manager when cmake is called.
# It will take CMake current settings (os, compiler, compiler version, architecture)
# and translate them to conan settings for installing and retrieving dependencies.
# It is intended to facilitate developers building projects that have conan dependencies,
# but it is only necessary on the end-user side. It is not necessary to create conan
# packages, in fact it shouldn't be use for that. Check the project documentation.
include(CMakeParseArguments)
function(_get_msvc_ide_version result)
set(${result} "" PARENT_SCOPE)
if(NOT MSVC_VERSION VERSION_LESS 1400 AND MSVC_VERSION VERSION_LESS 1500)
set(${result} 8 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1500 AND MSVC_VERSION VERSION_LESS 1600)
set(${result} 9 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1600 AND MSVC_VERSION VERSION_LESS 1700)
set(${result} 10 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1700 AND MSVC_VERSION VERSION_LESS 1800)
set(${result} 11 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1800 AND MSVC_VERSION VERSION_LESS 1900)
set(${result} 12 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1900 AND MSVC_VERSION VERSION_LESS 1910)
set(${result} 14 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1910 AND MSVC_VERSION VERSION_LESS 1920)
set(${result} 15 PARENT_SCOPE)
else()
message(FATAL_ERROR "Conan: Unknown MSVC compiler version [${MSVC_VERSION}]")
endif()
endfunction()
function(conan_cmake_settings result)
#message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER})
#message(STATUS "COMPILER " ${CMAKE_CXX_COMPILER_ID})
#message(STATUS "VERSION " ${CMAKE_CXX_COMPILER_VERSION})
#message(STATUS "FLAGS " ${CMAKE_LANG_FLAGS})
#message(STATUS "LIB ARCH " ${CMAKE_CXX_LIBRARY_ARCHITECTURE})
#message(STATUS "BUILD TYPE " ${CMAKE_BUILD_TYPE})
#message(STATUS "GENERATOR " ${CMAKE_GENERATOR})
#message(STATUS "GENERATOR WIN64 " ${CMAKE_CL_64})
message(STATUS "Conan: Automatic detection of conan settings from cmake")
parse_arguments(${ARGV})
if(ARGUMENTS_BUILD_TYPE)
set(_CONAN_SETTING_BUILD_TYPE ${ARGUMENTS_BUILD_TYPE})
elseif(CMAKE_BUILD_TYPE)
set(_CONAN_SETTING_BUILD_TYPE ${CMAKE_BUILD_TYPE})
else()
message(FATAL_ERROR "Please specify in command line CMAKE_BUILD_TYPE (-DCMAKE_BUILD_TYPE=Release)")
endif()
if(ARGUMENTS_ARCH)
set(_CONAN_SETTING_ARCH ${ARGUMENTS_ARCH})
endif()
#handle -s os setting
if(CMAKE_SYSTEM_NAME)
#use default conan os setting if CMAKE_SYSTEM_NAME is not defined
set(CONAN_SYSTEM_NAME ${CMAKE_SYSTEM_NAME})
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
set(CONAN_SYSTEM_NAME Macos)
endif()
set(CONAN_SUPPORTED_PLATFORMS Windows Linux Macos Android iOS FreeBSD WindowsStore)
list (FIND CONAN_SUPPORTED_PLATFORMS "${CONAN_SYSTEM_NAME}" _index)
if (${_index} GREATER -1)
#check if the cmake system is a conan supported one
set(_CONAN_SETTING_OS ${CONAN_SYSTEM_NAME})
else()
message(FATAL_ERROR "cmake system ${CONAN_SYSTEM_NAME} is not supported by conan. Use one of ${CONAN_SUPPORTED_PLATFORMS}")
endif()
endif()
get_property(_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
if (";${_languages};" MATCHES ";CXX;")
set(LANGUAGE CXX)
set(USING_CXX 1)
elseif (";${_languages};" MATCHES ";C;")
set(LANGUAGE C)
set(USING_CXX 0)
else ()
message(FATAL_ERROR "Conan: Neither C or C++ was detected as a language for the project. Unabled to detect compiler version.")
endif()
if (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL GNU)
# using GCC
# TODO: Handle other params
string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION})
list(GET VERSION_LIST 0 MAJOR)
list(GET VERSION_LIST 1 MINOR)
set(COMPILER_VERSION ${MAJOR}.${MINOR})
if(${MAJOR} GREATER 4)
set(COMPILER_VERSION ${MAJOR})
endif()
set(_CONAN_SETTING_COMPILER gcc)
set(_CONAN_SETTING_COMPILER_VERSION ${COMPILER_VERSION})
if (USING_CXX)
conan_cmake_detect_gnu_libcxx(_LIBCXX)
set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
endif ()
elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL AppleClang)
# using AppleClang
string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION})
list(GET VERSION_LIST 0 MAJOR)
list(GET VERSION_LIST 1 MINOR)
set(_CONAN_SETTING_COMPILER apple-clang)
set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR}.${MINOR})
if (USING_CXX)
set(_CONAN_SETTING_COMPILER_LIBCXX libc++)
endif ()
elseif (${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL Clang)
string(REPLACE "." ";" VERSION_LIST ${CMAKE_${LANGUAGE}_COMPILER_VERSION})
list(GET VERSION_LIST 0 MAJOR)
list(GET VERSION_LIST 1 MINOR)
if(APPLE)
cmake_policy(GET CMP0025 APPLE_CLANG_POLICY_ENABLED)
if(NOT APPLE_CLANG_POLICY_ENABLED)
message(STATUS "Conan: APPLE and Clang detected. Assuming apple-clang compiler. Set CMP0025 to avoid it")
set(_CONAN_SETTING_COMPILER apple-clang)
set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR}.${MINOR})
else()
set(_CONAN_SETTING_COMPILER clang)
set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR}.${MINOR})
endif()
if (USING_CXX)
set(_CONAN_SETTING_COMPILER_LIBCXX libc++)
endif ()
else()
set(_CONAN_SETTING_COMPILER clang)
if(${MAJOR} GREATER 7)
set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR})
else()
set(_CONAN_SETTING_COMPILER_VERSION ${MAJOR}.${MINOR})
endif()
if (USING_CXX)
conan_cmake_detect_gnu_libcxx(_LIBCXX)
set(_CONAN_SETTING_COMPILER_LIBCXX ${_LIBCXX})
endif ()
endif()
elseif(${CMAKE_${LANGUAGE}_COMPILER_ID} STREQUAL MSVC)
set(_VISUAL "Visual Studio")
_get_msvc_ide_version(_VISUAL_VERSION)
if("${_VISUAL_VERSION}" STREQUAL "")
message(FATAL_ERROR "Conan: Visual Studio not recognized")
else()
set(_CONAN_SETTING_COMPILER ${_VISUAL})
set(_CONAN_SETTING_COMPILER_VERSION ${_VISUAL_VERSION})
endif()
if(NOT _CONAN_SETTING_ARCH)
if (MSVC_${LANGUAGE}_ARCHITECTURE_ID MATCHES "64")
set(_CONAN_SETTING_ARCH x86_64)
elseif (MSVC_${LANGUAGE}_ARCHITECTURE_ID MATCHES "^ARM")
message(STATUS "Conan: Using default ARM architecture from MSVC")
set(_CONAN_SETTING_ARCH armv6)
elseif (MSVC_${LANGUAGE}_ARCHITECTURE_ID MATCHES "86")
set(_CONAN_SETTING_ARCH x86)
else ()
message(FATAL_ERROR "Conan: Unknown MSVC architecture [${MSVC_${LANGUAGE}_ARCHITECTURE_ID}]")
endif()
endif()
conan_cmake_detect_vs_runtime(_vs_runtime)
message(STATUS "Conan: Detected VS runtime: ${_vs_runtime}")
set(_CONAN_SETTING_COMPILER_RUNTIME ${_vs_runtime})
if (CMAKE_GENERATOR_TOOLSET)
set(_CONAN_SETTING_COMPILER_TOOLSET ${CMAKE_VS_PLATFORM_TOOLSET})
elseif(CMAKE_VS_PLATFORM_TOOLSET AND (CMAKE_GENERATOR STREQUAL "Ninja"))
set(_CONAN_SETTING_COMPILER_TOOLSET ${CMAKE_VS_PLATFORM_TOOLSET})
endif()
else()
message(FATAL_ERROR "Conan: compiler setup not recognized")
endif()
# If profile is defined it is used
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND ARGUMENTS_DEBUG_PROFILE)
set(_SETTINGS -pr ${ARGUMENTS_DEBUG_PROFILE})
elseif(CMAKE_BUILD_TYPE STREQUAL "Release" AND ARGUMENTS_RELEASE_PROFILE)
set(_SETTINGS -pr ${ARGUMENTS_RELEASE_PROFILE})
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" AND ARGUMENTS_RELWITHDEBINFO_PROFILE)
set(_SETTINGS -pr ${ARGUMENTS_RELWITHDEBINFO_PROFILE})
elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel" AND ARGUMENTS_MINSIZEREL_PROFILE)
set(_SETTINGS -pr ${ARGUMENTS_MINSIZEREL_PROFILE})
elseif(ARGUMENTS_PROFILE)
set(_SETTINGS -pr ${ARGUMENTS_PROFILE})
endif()
if(NOT _SETTINGS OR ARGUMENTS_PROFILE_AUTO STREQUAL "ALL")
set(ARGUMENTS_PROFILE_AUTO arch build_type compiler compiler.version
compiler.runtime compiler.libcxx compiler.toolset)
endif()
# Automatic from CMake
foreach(ARG ${ARGUMENTS_PROFILE_AUTO})
string(TOUPPER ${ARG} _arg_name)
string(REPLACE "." "_" _arg_name ${_arg_name})
if(_CONAN_SETTING_${_arg_name})
set(_SETTINGS ${_SETTINGS} -s ${ARG}=${_CONAN_SETTING_${_arg_name}})
endif()
endforeach()
foreach(ARG ${ARGUMENTS_SETTINGS})
set(_SETTINGS ${_SETTINGS} -s ${ARG})
endforeach()
message(STATUS "Conan: Settings= ${_SETTINGS}")
set(${result} ${_SETTINGS} PARENT_SCOPE)
endfunction()
function(conan_cmake_detect_gnu_libcxx result)
# Allow -D_GLIBCXX_USE_CXX11_ABI=ON/OFF as argument to cmake
if(DEFINED _GLIBCXX_USE_CXX11_ABI)
if(_GLIBCXX_USE_CXX11_ABI)
set(${result} libstdc++11 PARENT_SCOPE)
return()
else()
set(${result} libstdc++ PARENT_SCOPE)
return()
endif()
endif()
# Check if there's any add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
get_directory_property(defines DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS)
foreach(define ${defines})
if(define STREQUAL "_GLIBCXX_USE_CXX11_ABI=0")
set(${result} libstdc++ PARENT_SCOPE)
return()
endif()
endforeach()
# Use C++11 stdlib as default if gcc is 5.1+
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.1")
set(${result} libstdc++ PARENT_SCOPE)
else()
set(${result} libstdc++11 PARENT_SCOPE)
endif()
endfunction()
function(conan_cmake_detect_vs_runtime result)
string(TOUPPER ${CMAKE_BUILD_TYPE} build_type)
set(variables CMAKE_CXX_FLAGS_${build_type} CMAKE_C_FLAGS_${build_type} CMAKE_CXX_FLAGS CMAKE_C_FLAGS)
foreach(variable ${variables})
string(REPLACE " " ";" flags ${${variable}})
foreach (flag ${flags})
if(${flag} STREQUAL "/MD" OR ${flag} STREQUAL "/MDd" OR ${flag} STREQUAL "/MT" OR ${flag} STREQUAL "/MTd")
string(SUBSTRING ${flag} 1 -1 runtime)
set(${result} ${runtime} PARENT_SCOPE)
return()
endif()
endforeach()
endforeach()
if(${build_type} STREQUAL "DEBUG")
set(${result} "MDd" PARENT_SCOPE)
else()
set(${result} "MD" PARENT_SCOPE)
endif()
endfunction()
macro(parse_arguments)
set(options BASIC_SETUP CMAKE_TARGETS UPDATE KEEP_RPATHS NO_OUTPUT_DIRS OUTPUT_QUIET)
set(oneValueArgs CONANFILE DEBUG_PROFILE RELEASE_PROFILE RELWITHDEBINFO_PROFILE MINSIZEREL_PROFILE
PROFILE ARCH BUILD_TYPE INSTALL_FOLDER CONAN_COMMAND)
set(multiValueArgs REQUIRES OPTIONS IMPORTS SETTINGS BUILD ENV GENERATORS PROFILE_AUTO)
cmake_parse_arguments(ARGUMENTS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
endmacro()
function(conan_cmake_install)
# Calls "conan install"
# Argument BUILD is equivalant to --build={missing, PkgName,...} or
# --build when argument is 'BUILD all' (which builds all packages from source)
# Argument CONAN_COMMAND, to specify the conan path, e.g. in case of running from source
# cmake does not identify conan as command, even if it is +x and it is in the path
parse_arguments(${ARGV})
if(CONAN_CMAKE_MULTI)
set(ARGUMENTS_GENERATORS ${ARGUMENTS_GENERATORS} cmake_multi)
else()
set(ARGUMENTS_GENERATORS ${ARGUMENTS_GENERATORS} cmake)
endif()
set(CONAN_BUILD_POLICY "")
foreach(ARG ${ARGUMENTS_BUILD})
if(${ARG} STREQUAL "all")
set(CONAN_BUILD_POLICY ${CONAN_BUILD_POLICY} --build)
break()
else()
set(CONAN_BUILD_POLICY ${CONAN_BUILD_POLICY} --build=${ARG})
endif()
endforeach()
if(ARGUMENTS_CONAN_COMMAND)
set(conan_command ${ARGUMENTS_CONAN_COMMAND})
else()
set(conan_command conan)
endif()
set(CONAN_OPTIONS "")
if(ARGUMENTS_CONANFILE)
set(CONANFILE ${CMAKE_CURRENT_SOURCE_DIR}/${ARGUMENTS_CONANFILE})
# A conan file has been specified - apply specified options as well if provided
foreach(ARG ${ARGUMENTS_OPTIONS})
set(CONAN_OPTIONS ${CONAN_OPTIONS} -o=${ARG})
endforeach()
else()
set(CONANFILE ".")
endif()
if(ARGUMENTS_UPDATE)
set(CONAN_INSTALL_UPDATE --update)
endif()
set(CONAN_INSTALL_FOLDER "")
if(ARGUMENTS_INSTALL_FOLDER)
set(CONAN_INSTALL_FOLDER -if=${ARGUMENTS_INSTALL_FOLDER})
endif()
foreach(ARG ${ARGUMENTS_GENERATORS})
set(CONAN_GENERATORS ${CONAN_GENERATORS} -g=${ARG})
endforeach()
foreach(ARG ${ARGUMENTS_ENV})
set(CONAN_ENV_VARS ${CONAN_ENV_VARS} -e=${ARG})
endforeach()
set(conan_args install ${CONANFILE} ${settings} ${CONAN_ENV_VARS} ${CONAN_GENERATORS} ${CONAN_BUILD_POLICY} ${CONAN_INSTALL_UPDATE} ${CONAN_OPTIONS} ${CONAN_INSTALL_FOLDER})
string (REPLACE ";" " " _conan_args "${conan_args}")
message(STATUS "Conan executing: ${conan_command} ${_conan_args}")
if(ARGUMENTS_OUTPUT_QUIET)
set(OUTPUT_CONTROL OUTPUT_QUIET)
endif()
execute_process(COMMAND ${conan_command} ${conan_args}
RESULT_VARIABLE return_code
OUTPUT_VARIABLE conan_output
ERROR_VARIABLE conan_output
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
message(STATUS "${conan_output}")
if(NOT "${return_code}" STREQUAL "0")
message(FATAL_ERROR "Conan install failed='${return_code}'")
endif()
endfunction()
function(conan_cmake_setup_conanfile)
parse_arguments(${ARGV})
if(ARGUMENTS_CONANFILE)
# configure_file will make sure cmake re-runs when conanfile is updated
configure_file(${ARGUMENTS_CONANFILE} ${ARGUMENTS_CONANFILE}.junk)
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${ARGUMENTS_CONANFILE}.junk)
else()
conan_cmake_generate_conanfile(${ARGV})
endif()
endfunction()
function(conan_cmake_generate_conanfile)
# Generate, writing in disk a conanfile.txt with the requires, options, and imports
# specified as arguments
# This will be considered as temporary file, generated in CMAKE_CURRENT_BINARY_DIR)
parse_arguments(${ARGV})
set(_FN "${CMAKE_CURRENT_BINARY_DIR}/conanfile.txt")
file(WRITE ${_FN} "[generators]\ncmake\n\n[requires]\n")
foreach(ARG ${ARGUMENTS_REQUIRES})
file(APPEND ${_FN} ${ARG} "\n")
endforeach()
file(APPEND ${_FN} ${ARG} "\n[options]\n")
foreach(ARG ${ARGUMENTS_OPTIONS})
file(APPEND ${_FN} ${ARG} "\n")
endforeach()
file(APPEND ${_FN} ${ARG} "\n[imports]\n")
foreach(ARG ${ARGUMENTS_IMPORTS})
file(APPEND ${_FN} ${ARG} "\n")
endforeach()
endfunction()
macro(conan_load_buildinfo)
if(CONAN_CMAKE_MULTI)
set(_CONANBUILDINFO conanbuildinfo_multi.cmake)
else()
set(_CONANBUILDINFO conanbuildinfo.cmake)
endif()
# Checks for the existence of conanbuildinfo.cmake, and loads it
# important that it is macro, so variables defined at parent scope
if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${_CONANBUILDINFO}")
message(STATUS "Conan: Loading ${_CONANBUILDINFO}")
include(${CMAKE_CURRENT_BINARY_DIR}/${_CONANBUILDINFO})
else()
message(FATAL_ERROR "${_CONANBUILDINFO} doesn't exist in ${CMAKE_CURRENT_BINARY_DIR}")
endif()
endmacro()
macro(conan_cmake_run)
parse_arguments(${ARGV})
if(CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE AND NOT CONAN_EXPORTED
AND NOT ARGUMENTS_BUILD_TYPE)
set(CONAN_CMAKE_MULTI ON)
message(STATUS "Conan: Using cmake-multi generator")
else()
set(CONAN_CMAKE_MULTI OFF)
endif()
if(NOT CONAN_EXPORTED)
conan_cmake_setup_conanfile(${ARGV})
if(CONAN_CMAKE_MULTI)
foreach(CMAKE_BUILD_TYPE "Release" "Debug")
set(ENV{CONAN_IMPORT_PATH} ${CMAKE_BUILD_TYPE})
conan_cmake_settings(settings ${ARGV})
conan_cmake_install(SETTINGS ${settings} ${ARGV})
endforeach()
set(CMAKE_BUILD_TYPE)
else()
conan_cmake_settings(settings ${ARGV})
conan_cmake_install(SETTINGS ${settings} ${ARGV})
endif()
endif()
conan_load_buildinfo()
if(ARGUMENTS_BASIC_SETUP)
foreach(_option CMAKE_TARGETS KEEP_RPATHS NO_OUTPUT_DIRS)
if(ARGUMENTS_${_option})
if(${_option} STREQUAL "CMAKE_TARGETS")
list(APPEND _setup_options "TARGETS")
else()
list(APPEND _setup_options ${_option})
endif()
endif()
endforeach()
conan_basic_setup(${_setup_options})
endif()
endmacro()
macro(conan_check)
# Checks conan availability in PATH
# Arguments REQUIRED and VERSION are optional
# Example usage:
# conan_check(VERSION 1.0.0 REQUIRED)
message(STATUS "Conan: checking conan executable in path")
set(options REQUIRED)
set(oneValueArgs VERSION)
cmake_parse_arguments(CONAN "${options}" "${oneValueArgs}" "" ${ARGN})
find_program(CONAN_CMD conan)
if(NOT CONAN_CMD AND CONAN_REQUIRED)
message(FATAL_ERROR "Conan executable not found!")
endif()
message(STATUS "Conan: Found program ${CONAN_CMD}")
execute_process(COMMAND ${CONAN_CMD} --version
OUTPUT_VARIABLE CONAN_VERSION_OUTPUT
ERROR_VARIABLE CONAN_VERSION_OUTPUT)
message(STATUS "Conan: Version found ${CONAN_VERSION_OUTPUT}")
if(DEFINED CONAN_VERSION)
string(REGEX MATCH ".*Conan version ([0-9]+\.[0-9]+\.[0-9]+)" FOO
"${CONAN_VERSION_OUTPUT}")
if(${CMAKE_MATCH_1} VERSION_LESS ${CONAN_VERSION})
message(FATAL_ERROR "Conan outdated. Installed: ${CONAN_VERSION}, \
required: ${CONAN_VERSION_REQUIRED}. Consider updating via 'pip \
install conan --upgrade'.")
endif()
endif()
endmacro()
macro(conan_add_remote)
# Adds a remote
# Arguments URL and NAME are required, INDEX is optional
# Example usage:
# conan_add_remote(NAME bincrafters INDEX 1
# URL https://api.bintray.com/conan/bincrafters/public-conan)
set(oneValueArgs URL NAME INDEX)
cmake_parse_arguments(CONAN "" "${oneValueArgs}" "" ${ARGN})
if(DEFINED CONAN_INDEX)
set(CONAN_INDEX_ARG "-i ${CONAN_INDEX}")
endif()
message(STATUS "Conan: Adding ${CONAN_NAME} remote repositoy (${CONAN_URL})")
execute_process(COMMAND ${CONAN_CMD} remote add ${CONAN_NAME} ${CONAN_URL}
${CONAN_INDEX_ARG} -f)
endmacro()

View File

@ -1,7 +1,5 @@
[requires] [requires]
qt/5.12.0@bincrafters/stable
protobuf/3.6.1@bincrafters/stable protobuf/3.6.1@bincrafters/stable
protoc_installer/3.6.1@bincrafters/stable
catch2/2.4.2@bincrafters/stable catch2/2.4.2@bincrafters/stable
[generators] [generators]
@ -9,5 +7,3 @@ cmake
[options] [options]
protobuf:shared=False protobuf:shared=False
qt:qttools=True
qt:qttranslations=True

View File

@ -6,14 +6,14 @@ message DativModel
{ {
message TiereModel message TiereModel
{ {
bool Affe = 1; bool Tiger = 1;
bool Gans = 2; bool Katze = 2;
bool Tiger = 3; bool Affe = 3;
bool Hund = 4; bool Gans = 4;
bool Elefant = 5; bool Baer = 5;
bool Pferd = 6; bool Pferd = 6;
bool Baer = 7; bool Hund = 7;
bool Katze = 8; bool Elefant = 8;
} }
message VersteckeModel message VersteckeModel
@ -28,19 +28,19 @@ message DativModel
bool Baum2 = 8; bool Baum2 = 8;
} }
message NomTiereModel message FutterModel
{ {
bool Gans = 1; bool Salat = 1;
bool Tiger = 2; bool Fleisch = 2;
bool Hund = 3; bool Knochen = 3;
bool Affe = 4; bool Banane = 4;
bool Elefant = 5; bool Apfel = 5;
bool Pferd = 6; bool Karotte = 6;
bool Baer = 7; bool Honig = 7;
bool Katze = 8; bool Zucker = 8;
} }
TiereModel Tiere = 1; TiereModel Tiere = 1;
VersteckeModel Verstecke = 2; VersteckeModel Verstecke = 2;
NomTiereModel NomTiere = 3; FutterModel Futter = 3;
} }

View File

@ -1,24 +1,6 @@
cmake_minimum_required(VERSION 3.6) cmake_minimum_required(VERSION 3.6)
set(BUILD_VERSION_MAJOR_MINOR 0.6) project(ESGRAF48 LANGUAGES CXX)
if ($ENV{BUILD_NUMBER})
set(BUILD_VERSION_PATCH $ENV{BUILD_NUMBER})
else()
set(BUILD_VERSION_PATCH 0)
endif()
project(ESGRAF48
VERSION ${BUILD_VERSION_MAJOR_MINOR}.${BUILD_VERSION_PATCH}
DESCRIPTION "ESGRAF 4-8"
LANGUAGES CXX
)
configure_file(
version.h.in
version.h
)
find_package(Qt5Widgets REQUIRED) find_package(Qt5Widgets REQUIRED)
find_package(Qt5PrintSupport REQUIRED) find_package(Qt5PrintSupport REQUIRED)
@ -54,6 +36,7 @@ protobuf_generate_cpp(DataModel_PROTO_SRCS DataModel_PROTO_HDRS
add_executable(${PROJECT_NAME} WIN32 add_executable(${PROJECT_NAME} WIN32
ESGRAF48.cpp ESGRAF48.cpp
DataModel.cpp DataModel.cpp
PrintableModel.cpp
mainwindow.cpp mainwindow.cpp
${LOGO_TEST_UI} ${LOGO_TEST_UI}
${LOGO_TEST_QRC} ${LOGO_TEST_QRC}
@ -78,7 +61,6 @@ target_link_libraries(${PROJECT_NAME}
CheckableItem CheckableItem
CheckableTest CheckableTest
CheckableTestModel CheckableTestModel
PrintableModel
MetaData MetaData
VerbEnd VerbEnd
Plural Plural
@ -92,30 +74,10 @@ target_link_libraries(${PROJECT_NAME}
${Protobuf_LIBRARIES} ${Protobuf_LIBRARIES}
) )
if (WIN32)
get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION)
message(STATUS "_qmake_executable: ${_qmake_executable}")
get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY)
message(STATUS "_qt_bin_dir: ${_qt_bin_dir}")
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}")
if (WINDEPLOYQT_EXECUTABLE)
message(STATUS "Found ${WINDEPLOYQT_EXECUTABLE}")
else()
message(FATAL_ERROR "Unable to find windeployqt")
endif()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${WINDEPLOYQT_EXECUTABLE} $<TARGET_FILE:${PROJECT_NAME}>)
endif()
add_subdirectory(Age) add_subdirectory(Age)
add_subdirectory(CheckableItem) add_subdirectory(CheckableItem)
add_subdirectory(CheckableTest) add_subdirectory(CheckableTest)
add_subdirectory(CheckableTestModel) add_subdirectory(CheckableTestModel)
add_subdirectory(PrintableModel)
add_subdirectory(MetaData) add_subdirectory(MetaData)
add_subdirectory(SubTests) add_subdirectory(SubTests)

View File

@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.6)
project(CheckableTestModel LANGUAGES CXX) project(CheckableTestModel LANGUAGES CXX)
find_package(Qt5Core REQUIRED) find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
add_library(${PROJECT_NAME} add_library(${PROJECT_NAME}
CheckableTestModel.cpp CheckableTestModel.cpp
@ -18,9 +19,9 @@ target_include_directories(${PROJECT_NAME}
) )
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PUBLIC PRIVATE
CheckableItem CheckableItem
CheckableTest CheckableTest
PRIVATE
Qt5::Core Qt5::Core
Qt5::Gui
) )

View File

@ -2,6 +2,7 @@
#include <QJsonArray> #include <QJsonArray>
#include <QSize> #include <QSize>
#include <QTextTable>
#include <QDebug> #include <QDebug>
CheckableTestModel::CheckableTestModel(QObject *parent) CheckableTestModel::CheckableTestModel(QObject *parent)
@ -94,29 +95,13 @@ bool CheckableTestModel::setData(const QModelIndex &index, const QVariant &value
QVariant CheckableTestModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant CheckableTestModel::headerData(int section, Qt::Orientation orientation, int role) const
{ {
switch (orientation) if (role == Qt::DisplayRole && orientation == Qt::Vertical)
{
case Qt::Vertical:
{
switch (role)
{
case Qt::DisplayRole:
{ {
if (section < m_tests.size()) if (section < m_tests.size())
{ {
return m_tests.at(section).name(); return m_tests.at(section).name();
} }
} }
case Qt::SizeHintRole:
{
return QSize(200, 0);
}
}
break;
}
default:
break;
}
return QAbstractTableModel::headerData(section, orientation, role); return QAbstractTableModel::headerData(section, orientation, role);
} }
@ -131,6 +116,81 @@ bool CheckableTestModel::isValidIndex(const QModelIndex &index) const
return false; return false;
} }
void CheckableTestModel::printTo(QTextCursor &cursor) const
{
QTextCharFormat headerFormat;
headerFormat.setFontPointSize(10);
cursor.insertBlock();
cursor.insertText("\n");
cursor.insertText(getName().c_str(), headerFormat);
printTableTo(cursor);
cursor.movePosition(QTextCursor::End);
cursor.insertBlock();
cursor.insertText("\n");
printSummaryTo(cursor);
cursor.movePosition(QTextCursor::End);
}
void CheckableTestModel::printTableTo(QTextCursor &cursor) const
{
QTextTableFormat tableFormat = defaultTableFormat();
tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 20),
QTextLength(QTextLength::PercentageLength, 9),
QTextLength(QTextLength::PercentageLength, 9),
QTextLength(QTextLength::PercentageLength, 9),
QTextLength(QTextLength::PercentageLength, 9),
QTextLength(QTextLength::PercentageLength, 9),
QTextLength(QTextLength::PercentageLength, 9),
QTextLength(QTextLength::PercentageLength, 9),
QTextLength(QTextLength::PercentageLength, 9),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3)});
QTextTable *table = cursor.insertTable(m_tests.size() * 2, 13, tableFormat);
int currentRow = 0;
for (const auto &test : m_tests)
{
table->mergeCells(currentRow, 0, 2, 1);
int currentColumn = 0;
setCellText(*table, currentRow, currentColumn, test.name());
currentColumn++;
for (const auto &item : test.items())
{
setCellText(*table, currentRow, currentColumn, item.getText().c_str());
setCellChecked(*table, currentRow + 1, currentColumn, item.isChecked());
currentColumn++;
}
setCellNumber(*table, currentRow + 1, 12, test.getPoints());
currentRow += 2;
}
}
void CheckableTestModel::printSummaryTo(QTextCursor &cursor) const
{
QTextTableFormat tableFormat = defaultTableFormat();
tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 76),
QTextLength(QTextLength::PercentageLength, 20),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3)});
QTextTable *table = cursor.insertTable(1, 4, tableFormat);
setCellText(*table, 0, 1, "Rohwertpunkte Total:");
setCellNumber(*table, 0, 3, getPoints());
}
CheckableItems &CheckableTestModel::getItems(const QModelIndex &index) CheckableItems &CheckableTestModel::getItems(const QModelIndex &index)
{ {
if (index.row() < m_tests.size()) if (index.row() < m_tests.size())
@ -175,20 +235,7 @@ const CheckableItem &CheckableTestModel::getItem(const QModelIndex &index) const
unsigned int CheckableTestModel::getPoints() const unsigned int CheckableTestModel::getPoints() const
{ {
unsigned int points = 0; return std::accumulate(
std::begin(m_tests), std::end(m_tests), 0,
for (const auto &test : m_tests) [](int base, const CheckableTest &test) { return base + test.getPoints(); });
{
for (const auto &item : test.items())
{
points += item.points();
}
}
return points;
}
QString CheckableTestModel::getTitle() const
{
return m_title;
} }

View File

@ -1,14 +1,16 @@
#pragma once #pragma once
#include "../PrintableModel.h"
#include "CheckableTest.h" #include "CheckableTest.h"
#include <QAbstractTableModel>
class CheckableTestModel : public QAbstractTableModel #include <QAbstractTableModel>
#include <QTextCursor>
class CheckableTestModel : public QAbstractTableModel, protected PrintableModel
{ {
Q_OBJECT Q_OBJECT
protected: protected:
QString m_title;
CheckableTests m_tests; CheckableTests m_tests;
public: public:
@ -17,20 +19,27 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(
const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
QVariant headerData(int section, Qt::Orientation orientation, QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override; int role = Qt::DisplayRole) const override;
unsigned int getPoints() const; unsigned int getPoints() const;
QString getTitle() const; void printTo(QTextCursor &cursor) const override;
protected: protected:
virtual bool isValidIndex(const QModelIndex &index) const; virtual bool isValidIndex(const QModelIndex &index) const;
virtual std::string getName() const = 0;
virtual void printTableTo(QTextCursor &cursor) const;
virtual void printSummaryTo(QTextCursor &cursor) const;
private: private:
CheckableItems &getItems(const QModelIndex &index); CheckableItems &getItems(const QModelIndex &index);
const CheckableItems &getItems(const QModelIndex &index) const; const CheckableItems &getItems(const QModelIndex &index) const;

View File

@ -1,8 +1,6 @@
#include "DataModel.h" #include "DataModel.h"
#include "DataModel.pb.h" #include "DataModel.pb.h"
#include <QFile>
#include <sstream> #include <sstream>
DataModel::DataModel(QObject *parent) DataModel::DataModel(QObject *parent)
@ -14,10 +12,7 @@ DataModel::DataModel(QObject *parent)
, m_results(this) , m_results(this)
, m_akkusativ(this) , m_akkusativ(this)
, m_dativ(this) , m_dativ(this)
, m_wfModel(this) , m_v2Svk(this)
, m_otModel(this)
, m_tPrModel(this)
, m_tPeModel(this)
, m_passiv(this) , m_passiv(this)
, m_genitiv(this) , m_genitiv(this)
{ {
@ -27,27 +22,17 @@ DataModel::DataModel(QObject *parent)
connect(&m_verbEnd, &VerbEndModel::dataChanged, this, &DataModel::verbEndModelChanged); connect(&m_verbEnd, &VerbEndModel::dataChanged, this, &DataModel::verbEndModelChanged);
connect(&m_akkusativ, &AkkusativModel::dataChanged, this, &DataModel::akkusativModelChanged); connect(&m_akkusativ, &AkkusativModel::dataChanged, this, &DataModel::akkusativModelChanged);
connect(&m_dativ, &DativModel::dataChanged, this, &DataModel::dativModelChanged); connect(&m_dativ, &DativModel::dataChanged, this, &DataModel::dativModelChanged);
connect(&m_v2Svk, &V2SvkModel::dataChanged, this, &DataModel::v2SvkModelChanged);
connect(&m_wfModel, &WFModel::dataChanged, this, &DataModel::v2SvkModelChanged);
connect(&m_otModel, &OTModel::dataChanged, this, &DataModel::v2SvkModelChanged);
connect(&m_tPrModel, &TPrModel::dataChanged, this, &DataModel::v2SvkModelChanged);
connect(&m_tPeModel, &TPeModel::dataChanged, this, &DataModel::v2SvkModelChanged);
connect(&m_passiv, &PassivModel::dataChanged, this, &DataModel::passivModelChanged); connect(&m_passiv, &PassivModel::dataChanged, this, &DataModel::passivModelChanged);
connect(&m_genitiv, &GenitivModel::dataChanged, this, &DataModel::genitivModelChanged); connect(&m_genitiv, &GenitivModel::dataChanged, this, &DataModel::genitivModelChanged);
} }
void DataModel::write(const QString &filename) const void DataModel::write(std::ostream &outStream) const
{ {
ESGRAF48::DataModel dataModel; ESGRAF48::DataModel dataModel;
m_metaData.write(*dataModel.mutable_metadata()); m_metaData.write(*dataModel.mutable_metadata());
m_v2Svk.write(*dataModel.mutable_v2svk());
m_wfModel.write(*dataModel.mutable_v2svk());
m_otModel.write(*dataModel.mutable_v2svk());
m_tPrModel.write(*dataModel.mutable_v2svk());
m_tPeModel.write(*dataModel.mutable_v2svk());
m_verbEnd.write(*dataModel.mutable_verbend()); m_verbEnd.write(*dataModel.mutable_verbend());
m_genus.write(*dataModel.mutable_genus()); m_genus.write(*dataModel.mutable_genus());
m_akkusativ.write(*dataModel.mutable_akkusativ()); m_akkusativ.write(*dataModel.mutable_akkusativ());
@ -56,41 +41,16 @@ void DataModel::write(const QString &filename) const
m_genitiv.write(*dataModel.mutable_lateskillsgenitiv()); m_genitiv.write(*dataModel.mutable_lateskillsgenitiv());
m_passiv.write(*dataModel.mutable_lateskillspassiv()); m_passiv.write(*dataModel.mutable_lateskillspassiv());
QFile outFile(filename); dataModel.SerializeToOstream(&outStream);
if (!outFile.open(QIODevice::WriteOnly))
{
throw std::runtime_error("failed to open file");
} }
bool success = dataModel.SerializeToFileDescriptor(outFile.handle()); void DataModel::read(std::istream &inStream)
if (success == false)
{ {
throw std::runtime_error("filed to write file");
}
}
void DataModel::read(const QString &filename)
{
QFile inFile(filename);
if (!inFile.open(QIODevice::ReadOnly))
{
throw std::runtime_error("failed to read file");
}
ESGRAF48::DataModel dataModel; ESGRAF48::DataModel dataModel;
bool success = dataModel.ParseFromFileDescriptor(inFile.handle()); dataModel.ParseFromIstream(&inStream);
if (success == false)
{
throw std::runtime_error("invalid file format");
}
m_metaData.read(dataModel.metadata()); m_metaData.read(dataModel.metadata());
m_v2Svk.read(dataModel.v2svk());
m_wfModel.read(dataModel.v2svk());
m_otModel.read(dataModel.v2svk());
m_tPrModel.read(dataModel.v2svk());
m_tPeModel.read(dataModel.v2svk());
m_verbEnd.read(dataModel.verbend()); m_verbEnd.read(dataModel.verbend());
m_genus.read(dataModel.genus()); m_genus.read(dataModel.genus());
m_akkusativ.read(dataModel.akkusativ()); m_akkusativ.read(dataModel.akkusativ());
@ -100,43 +60,27 @@ void DataModel::read(const QString &filename)
m_passiv.read(dataModel.lateskillspassiv()); m_passiv.read(dataModel.lateskillspassiv());
} }
void DataModel::printTo(QPrinter &printer) const void DataModel::printTo(QTextCursor &cursor) const
{ {
QPainter painter; QTextCharFormat titleFormat;
painter.begin(&printer); titleFormat.setFontPointSize(14);
painter.setFont(PrintableModel::h1Font()); cursor.insertText("ESGRAF 4-8 Auswertungsbogen", titleFormat);
painter.drawText(0, painter.fontMetrics().lineSpacing(), "ESGRAF 4-8 Auswertungsbogen"); cursor.insertText("\n", titleFormat);
painter.translate(0, 3 * painter.fontMetrics().lineSpacing());
m_metaData.printTo(painter); m_metaData.printTo(cursor);
m_wfModel.printTo(painter); m_v2Svk.printTo(cursor);
m_otModel.printTo(painter); m_verbEnd.printTo(cursor);
m_tPrModel.printTo(painter); m_genus.printTo(cursor);
m_tPeModel.printTo(painter); m_akkusativ.printTo(cursor);
V2SvkModel::printSummary(painter, m_dativ.printTo(cursor);
m_wfModel.getV2Points() + m_otModel.getV2Points()
+ m_tPrModel.getV2Points() + m_tPeModel.getV2Points(),
m_wfModel.getSvkPoints() + m_otModel.getSvkPoints()
+ m_tPrModel.getSvkPoints() + m_tPeModel.getSvkPoints());
m_verbEnd.printTo(painter); m_plural.printTo(cursor);
m_genus.printTo(painter); m_passiv.printTo(cursor);
m_genitiv.printTo(cursor);
printer.newPage(); m_results.printTo(cursor);
painter.resetTransform();
m_akkusativ.printTo(painter);
m_dativ.printTo(painter);
m_plural.printTo(painter);
m_passiv.printTo(painter);
m_genitiv.printTo(painter);
m_results.printTo(painter);
painter.end();
} }
void DataModel::pluralModelChanged() void DataModel::pluralModelChanged()
@ -183,10 +127,8 @@ void DataModel::dativModelChanged()
void DataModel::v2SvkModelChanged() void DataModel::v2SvkModelChanged()
{ {
m_results.setV2Result(m_wfModel.getV2Points() + m_otModel.getV2Points() m_results.setV2Result(m_v2Svk.getV2Points());
+ m_tPrModel.getV2Points() + m_tPeModel.getV2Points()); m_results.setSvkResult(m_v2Svk.getSvkPoints());
m_results.setSvkResult(m_wfModel.getSvkPoints() + m_otModel.getSvkPoints()
+ m_tPrModel.getSvkPoints() + m_tPeModel.getSvkPoints());
emit modelChanged(); emit modelChanged();
} }

View File

@ -1,25 +1,19 @@
#pragma once #pragma once
#include "PrintableModel.h"
#include "MetaData/MetaDataModel.h" #include "MetaData/MetaDataModel.h"
#include "GenusModel.h" #include "GenusModel.h"
#include "VerbEndModel.h" #include "VerbEndModel.h"
#include "PluralModel.h" #include "PluralModel.h"
#include "AkkusativModel.h" #include "AkkusativModel.h"
#include "DativModel.h" #include "DativModel.h"
#include "V2SvkModel.h"
#include "WFModel.h"
#include "OTModel.h"
#include "TPrModel.h"
#include "TPeModel.h"
#include "PassivModel.h" #include "PassivModel.h"
#include "GenitivModel.h" #include "GenitivModel.h"
#include "ResultModel.h" #include "ResultModel.h"
#include <QPrinter> #include <QJsonObject>
#include <QTextCursor>
class DataModel : public QObject class DataModel : public QObject
{ {
@ -32,12 +26,7 @@ public:
PluralModel m_plural; PluralModel m_plural;
AkkusativModel m_akkusativ; AkkusativModel m_akkusativ;
DativModel m_dativ; DativModel m_dativ;
V2SvkModel m_v2Svk;
WFModel m_wfModel;
OTModel m_otModel;
TPrModel m_tPrModel;
TPeModel m_tPeModel;
PassivModel m_passiv; PassivModel m_passiv;
GenitivModel m_genitiv; GenitivModel m_genitiv;
@ -46,10 +35,9 @@ public:
public: public:
DataModel(QObject *parent); DataModel(QObject *parent);
void write(const QString &filename) const; void printTo(QTextCursor &cursor) const;
void read(const QString &filename); void write(std::ostream &outStream) const;
void read(std::istream &inStream);
void printTo(QPrinter &printer) const;
signals: signals:
void modelChanged(); void modelChanged();

View File

@ -1,34 +1,18 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "version.h"
#include <QApplication> #include <QApplication>
#include <QCommandLineParser>
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
QCoreApplication::setApplicationName(ESGRAF48_DESCRIPTION);
QCoreApplication::setApplicationVersion(ESGRAF48_VERSION);
QCommandLineParser cmdParser;
cmdParser.setApplicationDescription(ESGRAF48_DESCRIPTION);
cmdParser.addHelpOption();
cmdParser.addVersionOption();
cmdParser.addPositionalArgument("filename", "file to open");
cmdParser.process(app);
const QStringList args = cmdParser.positionalArguments();
std::unique_ptr<MainWindow> mainWindow; std::unique_ptr<MainWindow> mainWindow;
if (args.empty()) if (argc < 2)
{ {
mainWindow = std::make_unique<MainWindow>(nullptr); mainWindow = std::make_unique<MainWindow>(nullptr);
} }
else else
{ {
mainWindow = std::make_unique<MainWindow>(nullptr, args.at(0)); mainWindow = std::make_unique<MainWindow>(nullptr, argv[1]);
} }
mainWindow->show(); mainWindow->show();

View File

@ -42,7 +42,6 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
Age Age
PrintableModel
Qt5::Widgets Qt5::Widgets
${Protobuf_LIBRARIES} ${Protobuf_LIBRARIES}
) )

View File

@ -1,11 +1,12 @@
#include "MetaDataModel.h" #include "MetaDataModel.h"
#include <QTextTable>
#include <QDebug> #include <QDebug>
#include <sstream> #include <sstream>
MetaDataModel::MetaDataModel(QObject *parent) MetaDataModel::MetaDataModel(QObject *parent)
: PrintableModel(parent) : QAbstractTableModel(parent)
{ {
m_dateOfBirth = QDate::currentDate().addYears(-9); m_dateOfBirth = QDate::currentDate().addYears(-9);
m_dateOfTest = QDate::currentDate(); m_dateOfTest = QDate::currentDate();
@ -130,44 +131,52 @@ void MetaDataModel::write(ESGRAF48::MetaDataModel &model) const
model.set_remarks(m_remarks.toStdString()); model.set_remarks(m_remarks.toStdString());
} }
void MetaDataModel::printTo(QPainter &painter) const void MetaDataModel::printTo(QTextCursor &cursor) const
{ {
painter.setFont(tableFont()); cursor.insertBlock();
auto width = painter.device()->width(); QTextTableFormat tableFormat = defaultTableFormat();
auto height = 1.5 * painter.fontMetrics().lineSpacing(); tableFormat.setBorderStyle(QTextTableFormat::BorderStyle_None);
auto hasRemarks = !m_remarks.trimmed().isEmpty(); tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 25),
QTextLength(QTextLength::PercentageLength, 25),
QTextLength(QTextLength::PercentageLength, 25),
QTextLength(QTextLength::PercentageLength, 25)});
painter.drawText(0, 0, "Name, Vorname"); QTextTable *table = cursor.insertTable(4, 4, tableFormat);
painter.drawText(0.25 * width, 0, m_participant); table->mergeCells(1, 2, 1, 2);
painter.drawText(0.5 * width, 0, "Untersucher(in)"); table->mergeCells(2, 2, 2, 2);
painter.drawText(0.75 * width, 0, m_instructor);
painter.translate(0, height); cursor.insertText("Name, Vorname");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(m_participant);
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText("Untersucher(in)");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(m_instructor);
cursor.movePosition(QTextCursor::NextRow);
painter.drawText(0, 0, "Geburtsdatum"); cursor.insertText("Geburtsdatum");
painter.drawText(0.25 * width, 0, m_dateOfBirth.toString("dd.MM.yyyy")); cursor.movePosition(QTextCursor::NextCell);
if (hasRemarks) cursor.insertText(m_dateOfBirth.toString("dd.MM.yyyy"));
cursor.movePosition(QTextCursor::NextCell);
if (!m_remarks.trimmed().isEmpty())
{ {
painter.drawText(0.5 * width, 0, "Bemerkungen:"); cursor.insertText("Bemerkungen:");
painter.drawText(QRect(0.5 * width, 0.5 * height, width, 2 * height), m_remarks); }
cursor.movePosition(QTextCursor::NextRow);
cursor.insertText("Untersuchungsdatum");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(m_dateOfTest.toString("dd.MM.yyyy"));
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(m_remarks.trimmed());
cursor.movePosition(QTextCursor::NextRow);
cursor.insertText("Alter am Testtag");
cursor.movePosition(QTextCursor::NextCell);
cursor.insertText(getAge().toString().c_str());
cursor.movePosition(QTextCursor::End);
} }
painter.translate(0, height);
painter.drawText(0, 0, "Untersuchungsdatum");
painter.drawText(0.25 * width, 0, m_dateOfTest.toString("dd.MM.yyyy"));
painter.translate(0, height);
painter.drawText(0, 0, "Alter am Testtag");
painter.drawText(0.25 * width, 0, getAge().toString().c_str());
painter.translate(0, 2 * height);
}
Age MetaDataModel::getAge() const
{
return {m_dateOfBirth, m_dateOfTest};
}

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "PrintableModel.h" #include "../PrintableModel.h"
#include "Age.h" #include "Age.h"
#include "MetaDataModel.pb.h" #include "MetaDataModel.pb.h"
@ -9,8 +8,10 @@
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QString> #include <QString>
#include <QDate> #include <QDate>
#include <QJsonObject>
#include <QTextCursor>
class MetaDataModel : public PrintableModel class MetaDataModel : public QAbstractTableModel, protected PrintableModel
{ {
Q_OBJECT Q_OBJECT
@ -32,7 +33,10 @@ public:
void read(const ESGRAF48::MetaDataModel &model); void read(const ESGRAF48::MetaDataModel &model);
void write(ESGRAF48::MetaDataModel &model) const; void write(ESGRAF48::MetaDataModel &model) const;
void printTo(QPainter &painter) const override; void printTo(QTextCursor &cursor) const override;
Age getAge() const; Age getAge() const
{
return {m_dateOfBirth, m_dateOfTest};
}
}; };

46
source/PrintableModel.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "PrintableModel.h"
QTextTableFormat PrintableModel::defaultTableFormat()
{
QTextTableFormat tableFormat;
tableFormat.setCellPadding(2);
tableFormat.setCellSpacing(0);
return tableFormat;
}
void PrintableModel::setCellText(QTextTable &table, int row, int column, const QString &text)
{
auto cell = table.cellAt(row, column);
auto textCursor = cell.firstCursorPosition();
auto blockFormat = textCursor.blockFormat();
blockFormat.setAlignment(Qt::AlignCenter);
textCursor.setBlockFormat(blockFormat);
auto cellFormat = cell.format();
cellFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
cell.setFormat(cellFormat);
auto charFormat = textCursor.charFormat();
charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
charFormat.setFontPointSize(8);
textCursor.setCharFormat(charFormat);
textCursor.insertText(text);
}
void PrintableModel::setCellChecked(QTextTable &table, int row, int column, bool check)
{
setCellText(table, row, column, check ? "x" : "\u2610");
}
void PrintableModel::setCellBackground(QTextTable &table, int row, int column, const QColor &color)
{
auto cell = table.cellAt(row, column);
auto cellFormat = cell.format();
cellFormat.setBackground(QBrush(color));
cell.setFormat(cellFormat);
}

23
source/PrintableModel.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <QTextTableFormat>
#include <QTextTable>
class PrintableModel
{
public:
virtual void printTo(QTextCursor &cursor) const = 0;
protected:
static QTextTableFormat defaultTableFormat();
static void setCellText(QTextTable &table, int row, int column, const QString &text);
static void setCellChecked(QTextTable &table, int row, int column, bool check);
static void setCellBackground(QTextTable &table, int row, int column, const QColor &color);
template<typename NumberType>
static void setCellNumber(QTextTable &table, int row, int column, const NumberType &number)
{
setCellText(table, row, column, QString::number(number));
}
};

View File

@ -1,27 +0,0 @@
cmake_minimum_required(VERSION 3.6)
project(PrintableModel LANGUAGES CXX)
find_package(Qt5Core REQUIRED)
find_package(Qt5Widgets REQUIRED)
add_library(${PROJECT_NAME}
PrintableModel.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
CheckableTestModel
PRIVATE
Qt5::Core
Qt5::Widgets
)

View File

@ -1,184 +0,0 @@
#include "PrintableModel.h"
#include <regex>
PrintableModel::PrintableModel(QObject *parent)
: CheckableTestModel(parent)
{
}
void PrintableModel::printTo(QPainter &painter) const
{
printHeader(painter);
printTests(painter);
printSummary(painter);
}
QFont PrintableModel::h1Font()
{
return QFont("Helvetica", 16);
}
QFont PrintableModel::h2Font()
{
return QFont("Helvetica", 10);
}
QFont PrintableModel::tableFont()
{
return QFont("Helvetica", 8);
}
QPen PrintableModel::tablePen()
{
return QPen(Qt::black, 1, Qt::SolidLine);
}
QPen PrintableModel::resultPen()
{
return QPen(Qt::black, 2, Qt::SolidLine);
}
double PrintableModel::headerWidthFactor()
{
return 0.17;
}
double PrintableModel::cellWidthFactor()
{
return headerWidthFactor() / 2;
}
void PrintableModel::drawTextSquare(QPainter &painter, const QRectF &cell, const QString &text)
{
auto prevPen = painter.pen();
painter.setPen(tablePen());
painter.drawText(cell, Qt::AlignCenter, text);
painter.drawLine(cell.topLeft(), cell.topRight());
painter.drawLine(cell.topRight(), cell.bottomRight());
painter.drawLine(cell.bottomRight(), cell.bottomLeft());
painter.drawLine(cell.bottomLeft(), cell.topLeft());
painter.setPen(prevPen);
}
void PrintableModel::drawNumberSquare(QPainter &painter, double x, double y, int number)
{
QRectF cell = {x, y, 0.03 * painter.device()->width(),
1.5 * painter.fontMetrics().lineSpacing()};
painter.drawText(cell, Qt::AlignCenter, QString::number(number));
painter.drawLine(cell.topLeft(), cell.topRight());
painter.drawLine(cell.topRight(), cell.bottomRight());
painter.drawLine(cell.bottomRight(), cell.bottomLeft());
painter.drawLine(cell.bottomLeft(), cell.topLeft());
}
void PrintableModel::PrintableModel::drawCheckSquare(QPainter &painter, const QRectF &cell,
bool checked)
{
drawTextSquare(painter, cell, checked ? u8"\u2612" : u8"\u2610");
}
void PrintableModel::drawResultSquare(QPainter &painter, double y, bool rightCell,
unsigned int value)
{
double pageWidth = painter.device()->width();
double cellWidth = 0.03 * pageWidth;
double cellHeight = 1.5 * painter.fontMetrics().lineSpacing();
double x = pageWidth - cellWidth - (rightCell ? 0 : 0.04 * pageWidth);
drawTextSquare(painter, {x, y, cellWidth, cellHeight}, QString::number(value));
}
void PrintableModel::drawGreySquare(QPainter &painter, const QRectF &cell)
{
auto prevBrush = painter.brush();
auto prevPen = painter.pen();
painter.setBrush(QBrush(QColor(224, 224, 224)));
painter.setPen(QPen(Qt::NoPen));
QPointF points[4] = {cell.topLeft(), cell.topRight(), cell.bottomRight(), cell.bottomLeft()};
painter.drawPolygon(points, 4);
painter.setPen(tablePen());
painter.drawLine(cell.topLeft(), cell.topRight());
painter.drawLine(cell.topRight(), cell.bottomRight());
painter.drawLine(cell.bottomRight(), cell.bottomLeft());
painter.drawLine(cell.bottomLeft(), cell.topLeft());
painter.setBrush(prevBrush);
painter.setPen(prevPen);
}
void PrintableModel::drawHeader2(QPainter &painter, const QString &text)
{
painter.setFont(h2Font());
painter.drawText(0, 0, text);
painter.translate(0, 0.5 * painter.fontMetrics().lineSpacing());
}
void PrintableModel::printHeader(QPainter &painter) const
{
auto title = getTitle();
if (!title.isEmpty())
{
drawHeader2(painter, getTitle());
}
}
void PrintableModel::printTests(QPainter &painter) const
{
painter.setFont(tableFont());
painter.setPen(tablePen());
auto width = painter.device()->width();
auto height = 1.5 * painter.fontMetrics().lineSpacing();
double headerWidth = headerWidthFactor() * width;
double cellWidth = cellWidthFactor() * width;
double rowHeight = height;
double x = 0;
double y = 0;
for (const auto &test : m_tests)
{
QString testName = QString::fromStdString(
std::regex_replace(test.name().toStdString(), std::regex("\\s"), "\n"));
drawTextSquare(painter, {0, y, headerWidth, 2 * rowHeight}, testName);
x = headerWidth;
for (const auto &item : test.items())
{
drawTextSquare(painter, {x, y, cellWidth, rowHeight}, item.getText().c_str());
drawCheckSquare(painter, {x, y + rowHeight, cellWidth, rowHeight}, item.isChecked());
x += cellWidth;
}
y += rowHeight;
drawResultSquare(painter, y, true, test.getPoints());
y += rowHeight;
}
painter.translate(0, y + rowHeight);
}
void PrintableModel::printSummary(QPainter &painter) const
{
painter.setFont(tableFont());
auto width = painter.device()->width();
auto height = 1.5 * painter.fontMetrics().lineSpacing();
painter.drawText(0, 0, 0.95 * width, height, Qt::AlignRight | Qt::AlignVCenter,
"Rohwertpunkte Total:");
painter.setPen(resultPen());
drawNumberSquare(painter, 0.97 * width, 0, getPoints());
painter.translate(0, 3 * height);
}

View File

@ -1,42 +0,0 @@
#pragma once
#include "CheckableTestModel.h"
#include <QPainter>
#include <QFont>
#include <QPen>
#include <QRect>
#include <QString>
class PrintableModel : public CheckableTestModel
{
Q_OBJECT
public:
PrintableModel(QObject *parent);
virtual void printTo(QPainter &painter) const;
static QFont h1Font();
static QFont h2Font();
static QFont tableFont();
static QPen tablePen();
static QPen resultPen();
static double headerWidthFactor();
static double cellWidthFactor();
static void drawTextSquare(QPainter &painter, const QRectF &cell, const QString &text);
static void drawNumberSquare(QPainter &painter, double x, double y, int number);
static void drawCheckSquare(QPainter &painter, const QRectF &cell, bool checked);
static void drawResultSquare(QPainter &painter, double y, bool rightCell, unsigned int value);
static void drawGreySquare(QPainter &painter, const QRectF &cell);
static void drawHeader2(QPainter &painter, const QString &text);
protected:
virtual void printHeader(QPainter &painter) const;
virtual void printTests(QPainter &painter) const;
virtual void printSummary(QPainter &painter) const;
};

View File

@ -12,6 +12,7 @@ qt5_wrap_ui(GENUS_UI
add_library(${PROJECT_NAME} add_library(${PROJECT_NAME}
ResultWidget.cpp ResultWidget.cpp
TestResult.cpp
ResultModel.cpp ResultModel.cpp
PRMap.cpp PRMap.cpp
${GENUS_UI} ${GENUS_UI}
@ -30,7 +31,6 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
PrintableModel
Age Age
Qt5::Widgets Qt5::Widgets
) )

View File

@ -20,7 +20,7 @@ unsigned int PRMap::lookup(const Age &age, const unsigned int &points)
if (m_ages.back() < age) if (m_ages.back() < age)
{ {
return m_ages.size() - 2; return m_ages.size() - 1;
} }
for (size_t index = 1; index < m_ages.size(); ++index) for (size_t index = 1; index < m_ages.size(); ++index)

View File

@ -10,15 +10,13 @@
#include "PassivPR.h" #include "PassivPR.h"
#include "GenitivPR.h" #include "GenitivPR.h"
#include "PrintableModel.h" #include <QTextTable>
#include <QDebug> #include <QDebug>
ResultModel::ResultModel(QObject *parent) ResultModel::ResultModel(QObject *parent)
: QAbstractTableModel(parent) : QAbstractTableModel(parent)
{ {
m_results = {{"V2", "SVK", "VE", "Passiv", "Genus", "Akkusativ", "Dativ", "Genitiv", "Plural"}}; m_results = {"V2", "SVK", "VE", "Passiv", "Genus", "Akkusativ", "Dativ", "Genitiv", "Plural"};
m_results = {{"V2", "SVK", "VE", "Genus", "Akkusativ", "Dativ", "Plural", "Passiv", "Genitiv"}};
} }
int ResultModel::rowCount(const QModelIndex &parent) const int ResultModel::rowCount(const QModelIndex &parent) const
@ -103,11 +101,11 @@ QVariant ResultModel::headerData(int section, Qt::Orientation orientation, int r
case 0: case 0:
return "RP"; return "RP";
case 1: case 1:
return ">= PR 84"; return "\u2265 PR 84";
case 2: case 2:
return "< PR 84"; return "< PR 84";
case 3: case 3:
return "<= PR 16"; return "\u2264 PR 16";
default: default:
return {}; return {};
} }
@ -124,21 +122,21 @@ void ResultModel::setAge(const Age &age)
void ResultModel::setPluralResult(unsigned int points) void ResultModel::setPluralResult(unsigned int points)
{ {
if (m_results[6].points() != points) if (m_results[8].points() != points)
{ {
m_results[6].setPoints(points); m_results[8].setPoints(points);
m_results[6].setPR(PluralPR().lookup(m_age, points)); m_results[8].setPR(PluralPR().lookup(m_age, points));
emit dataChanged(index(0, 6), index(4, 6)); emit dataChanged(index(0, 8), index(4, 8));
} }
} }
void ResultModel::setGenusResult(unsigned int points) void ResultModel::setGenusResult(unsigned int points)
{ {
if (m_results[3].points() != points) if (m_results[4].points() != points)
{ {
m_results[3].setPoints(points); m_results[4].setPoints(points);
m_results[3].setPR(GenusPR().lookup(m_age, points)); m_results[4].setPR(GenusPR().lookup(m_age, points));
emit dataChanged(index(0, 3), index(4, 3)); emit dataChanged(index(0, 4), index(4, 4));
} }
} }
@ -154,21 +152,21 @@ void ResultModel::setVerbEndResult(unsigned int points)
void ResultModel::setAkkusativResult(unsigned int points) void ResultModel::setAkkusativResult(unsigned int points)
{ {
if (m_results[4].points() != points) if (m_results[5].points() != points)
{ {
m_results[4].setPoints(points); m_results[5].setPoints(points);
m_results[4].setPR(AkkusativPR().lookup(m_age, points)); m_results[5].setPR(AkkusativPR().lookup(m_age, points));
emit dataChanged(index(0, 4), index(4, 4)); emit dataChanged(index(0, 5), index(4, 5));
} }
} }
void ResultModel::setDativResult(unsigned int points) void ResultModel::setDativResult(unsigned int points)
{ {
if (m_results[5].points() != points) if (m_results[6].points() != points)
{ {
m_results[5].setPoints(points); m_results[6].setPoints(points);
m_results[5].setPR(DativPR().lookup(m_age, points)); m_results[6].setPR(DativPR().lookup(m_age, points));
emit dataChanged(index(0, 5), index(4, 5)); emit dataChanged(index(0, 6), index(4, 6));
} }
} }
@ -194,66 +192,92 @@ void ResultModel::setSvkResult(unsigned int points)
void ResultModel::setPassivResult(unsigned int points) void ResultModel::setPassivResult(unsigned int points)
{ {
if (m_results[7].points() != points) if (m_results[3].points() != points)
{ {
m_results[7].setPoints(points); m_results[3].setPoints(points);
m_results[7].setPR(PassivPR().lookup(m_age, points)); m_results[3].setPR(PassivPR().lookup(m_age, points));
emit dataChanged(index(0, 7), index(4, 7)); emit dataChanged(index(0, 3), index(4, 3));
} }
} }
void ResultModel::setGenitivResult(unsigned int points) void ResultModel::setGenitivResult(unsigned int points)
{ {
if (m_results[8].points() != points) if (m_results[7].points() != points)
{ {
m_results[8].setPoints(points); m_results[7].setPoints(points);
m_results[8].setPR(GenitivPR().lookup(m_age, points)); m_results[7].setPR(GenitivPR().lookup(m_age, points));
emit dataChanged(index(0, 8), index(4, 8)); emit dataChanged(index(0, 7), index(4, 7));
} }
} }
void ResultModel::printTo(QPainter &painter) const void ResultModel::printTo(QTextCursor &cursor) const
{ {
PrintableModel::drawHeader2(painter, "Prozentränge (PR)"); QTextCharFormat headerFormat;
headerFormat.setFontPointSize(10);
cursor.insertBlock();
cursor.insertText("\nProzentränge (PR)");
painter.setFont(PrintableModel::tableFont()); QTextTableFormat tableFormat = defaultTableFormat();
painter.setPen(PrintableModel::tablePen());
auto width = painter.device()->width(); const unsigned int columnCount = 10;
auto height = 1.5 * painter.fontMetrics().lineSpacing();
double cellWidth = width / (m_results.size() + 1); tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 10),
double rowHeight = 2 * height; QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10)});
double x = 0; QTextTable *table = cursor.insertTable(4, columnCount, tableFormat);
double y = 0;
PrintableModel::drawTextSquare(painter, {x, y + 0 * rowHeight, cellWidth, rowHeight}, ""); auto insertText = [&table](int row, int column, const QString &text) {
PrintableModel::drawTextSquare(painter, {x, y + 1 * rowHeight, cellWidth, rowHeight}, auto cell = table->cellAt(row, column);
u8"\u2265 PR 84"); auto textCursor = cell.firstCursorPosition();
PrintableModel::drawTextSquare(painter, {x, y + 2 * rowHeight, cellWidth, rowHeight},
"< PR 84");
PrintableModel::drawGreySquare(painter, {x, y + 3 * rowHeight, cellWidth, rowHeight}); auto blockFormat = textCursor.blockFormat();
PrintableModel::drawTextSquare(painter, {x, y + 3 * rowHeight, cellWidth, rowHeight}, blockFormat.setAlignment(Qt::AlignCenter);
u8"\u2264 PR 16"); textCursor.setBlockFormat(blockFormat);
x += cellWidth; auto cellFormat = cell.format();
for (const auto &result : m_results) cellFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
if (row == 3)
{ {
PrintableModel::drawTextSquare(painter, {x, y + 0 * rowHeight, cellWidth, rowHeight}, QBrush backgroundBrush(QColor(192, 192, 192));
result.name()); cellFormat.setBackground(backgroundBrush);
const auto pr = result.pr(); }
PrintableModel::drawTextSquare(painter, {x, y + 1 * rowHeight, cellWidth, rowHeight}, cell.setFormat(cellFormat);
pr >= 84 ? QString::number(pr) : "-");
PrintableModel::drawTextSquare(painter, {x, y + 2 * rowHeight, cellWidth, rowHeight},
pr < 84 && pr > 16 ? QString::number(pr) : "-");
PrintableModel::drawGreySquare(painter, {x, y + 3 * rowHeight, cellWidth, rowHeight}); auto charFormat = textCursor.charFormat();
PrintableModel::drawTextSquare(painter, {x, y + 3 * rowHeight, cellWidth, rowHeight}, charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
pr <= 16 ? QString::number(pr) : "-"); charFormat.setFontPointSize(8);
x += cellWidth; if (row == 0 || column == 0)
{
charFormat.setFontWeight(QFont::Bold);
}
textCursor.setCharFormat(charFormat);
textCursor.insertText(text);
};
insertText(1, 0, "\u2265 PR 84");
insertText(2, 0, "< PR 84");
insertText(3, 0, "\u2264 PR 16");
for (size_t index = 0; index < m_results.size(); ++index)
{
insertText(0, index + 1, m_results[index].name());
int pr = m_results[index].pr();
insertText(1, index + 1, pr >= 84 ? QString::number(pr) : "-");
insertText(2, index + 1, pr < 84 && pr > 16 ? QString::number(pr) : "-");
insertText(3, index + 1, pr <= 16 ? QString::number(pr) : "-");
} }
} }

View File

@ -1,50 +1,13 @@
#pragma once #pragma once
#include "../PrintableModel.h"
#include "Age.h" #include "Age.h"
#include "TestResult.h"
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QPainter> #include <QTextCursor>
class TestResult class ResultModel : public QAbstractTableModel, protected PrintableModel
{
private:
QString m_name;
size_t m_points = 0;
size_t m_pr = 0;
public:
TestResult(const char *name)
: m_name(name)
{
}
void setPoints(const size_t &points)
{
m_points = points;
}
void setPR(const unsigned int &pr)
{
m_pr = pr;
}
const QString &name() const
{
return m_name;
}
const size_t points() const
{
return m_points;
}
const size_t pr() const
{
return m_pr;
}
};
class ResultModel : public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
@ -58,8 +21,7 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data( QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override; int role = Qt::DisplayRole) const override;
@ -75,5 +37,5 @@ public:
void setPassivResult(unsigned int points); void setPassivResult(unsigned int points);
void setGenitivResult(unsigned int points); void setGenitivResult(unsigned int points);
void printTo(QPainter &painter) const; void printTo(QTextCursor &cursor) const override;
}; };

View File

@ -0,0 +1,31 @@
#include "TestResult.h"
TestResult::TestResult(const char *name)
: m_name(name)
{
}
void TestResult::setPoints(const size_t &points)
{
m_points = points;
}
void TestResult::setPR(const unsigned int &pr)
{
m_pr = pr;
}
QString TestResult::name() const
{
return m_name;
}
size_t TestResult::points() const
{
return m_points;
}
size_t TestResult::pr() const
{
return m_pr;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <QString>
class TestResult
{
private:
QString m_name;
size_t m_points = 0;
size_t m_pr = 0;
public:
TestResult(const char *name);
void setPoints(const size_t &points);
void setPR(const unsigned int &pr);
QString name() const;
size_t points() const;
size_t pr() const;
};

View File

@ -1,7 +1,7 @@
#include "AkkusativModel.h" #include "AkkusativModel.h"
AkkusativModel::AkkusativModel(QObject *parent) AkkusativModel::AkkusativModel(QObject *parent)
: PrintableModel(parent) : CheckableTestModel(parent)
{ {
m_tests = {{"Akkusativ Nominalphrase", m_tests = {{"Akkusativ Nominalphrase",
{"Tiger", "Katze", "Affe", "Gans", "Bär", "Pferd", "Hund", "Elefant"}}, {"Tiger", "Katze", "Affe", "Gans", "Bär", "Pferd", "Hund", "Elefant"}},
@ -106,7 +106,7 @@ void AkkusativModel::write(ESGRAF48::AkkusativModel &model) const
} }
} }
void AkkusativModel::printHeader(QPainter &painter) const std::string AkkusativModel::getName() const
{ {
drawHeader2(painter, "Subtest 4: Akkusativ und Dativ"); return "Subtest 4: Akkusativ und Dativ";
} }

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include "PrintableModel.h" #include "CheckableTestModel.h"
#include "AkkusativModel.pb.h" #include "AkkusativModel.pb.h"
class AkkusativModel : public PrintableModel class AkkusativModel : public CheckableTestModel
{ {
Q_OBJECT Q_OBJECT
@ -14,5 +14,5 @@ public:
void write(ESGRAF48::AkkusativModel &model) const; void write(ESGRAF48::AkkusativModel &model) const;
protected: protected:
void printHeader(QPainter &painter) const override; std::string getName() const override;
}; };

View File

@ -43,7 +43,9 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
PrintableModel CheckableItem
CheckableTest
CheckableTestModel
Qt5::Widgets Qt5::Widgets
${Protobuf_LIBRARIES} ${Protobuf_LIBRARIES}
) )

View File

@ -1,14 +1,14 @@
#include "DativModel.h" #include "DativModel.h"
DativModel::DativModel(QObject *parent) DativModel::DativModel(QObject *parent)
: PrintableModel(parent) : CheckableTestModel(parent)
{ {
m_tests = {{"Dativ Nominalphrase", m_tests = {{"Dativ Nominalphrase",
{"Affe", "Gans", "Tiger", "Hund", "Elefant", "Pferd", "Bär", "Katze"}}, {"Tiger", "Katze", "Affe", "Gans", "Bär", "Pferd", "Hund", "Elefant"}},
{"Präpositionalphrase (Verstecke)", {"Präpositionalphrase (Verstecke)",
{"Vorhang", "Kiste", "Holz", "Kiste", "Baum", "Vorhang", "Holz", "Baum"}}, {"Vorhang", "Kiste", "Holz", "Kiste", "Baum", "Vorhang", "Holz", "Baum"}},
{"Nominalphrase (Tiere)", {"Nominalphrase (Tiere)",
{"Gans", "Tiger", "Hund", "Affe", "Elefant", "Pferd", "Bär", "Katze"}}}; {"Salat", "Fleisch", "Knochen", "Banane", "Apfel", "Karotte", "Honig", "Zucker"}}};
} }
void DativModel::read(const ESGRAF48::DativModel &model) void DativModel::read(const ESGRAF48::DativModel &model)
@ -17,14 +17,14 @@ void DativModel::read(const ESGRAF48::DativModel &model)
{ {
auto &testItems = m_tests.at(0).items(); auto &testItems = m_tests.at(0).items();
testItems[0].setState(tiereModel.affe()); testItems[0].setState(tiereModel.tiger());
testItems[1].setState(tiereModel.gans()); testItems[1].setState(tiereModel.katze());
testItems[2].setState(tiereModel.tiger()); testItems[2].setState(tiereModel.affe());
testItems[3].setState(tiereModel.hund()); testItems[3].setState(tiereModel.gans());
testItems[4].setState(tiereModel.elefant()); testItems[4].setState(tiereModel.baer());
testItems[5].setState(tiereModel.pferd()); testItems[5].setState(tiereModel.pferd());
testItems[6].setState(tiereModel.baer()); testItems[6].setState(tiereModel.hund());
testItems[7].setState(tiereModel.katze()); testItems[7].setState(tiereModel.elefant());
} }
const auto &versteckeModel = model.verstecke(); const auto &versteckeModel = model.verstecke();
@ -41,18 +41,18 @@ void DativModel::read(const ESGRAF48::DativModel &model)
testItems[7].setState(versteckeModel.baum2()); testItems[7].setState(versteckeModel.baum2());
} }
const auto &nomTiereModel = model.nomtiere(); const auto &futterModel = model.futter();
{ {
auto &testItems = m_tests.at(2).items(); auto &testItems = m_tests.at(2).items();
testItems[0].setState(nomTiereModel.gans()); testItems[0].setState(futterModel.salat());
testItems[1].setState(nomTiereModel.tiger()); testItems[1].setState(futterModel.fleisch());
testItems[2].setState(nomTiereModel.hund()); testItems[2].setState(futterModel.knochen());
testItems[3].setState(nomTiereModel.affe()); testItems[3].setState(futterModel.banane());
testItems[4].setState(nomTiereModel.elefant()); testItems[4].setState(futterModel.apfel());
testItems[5].setState(nomTiereModel.pferd()); testItems[5].setState(futterModel.karotte());
testItems[6].setState(nomTiereModel.baer()); testItems[6].setState(futterModel.honig());
testItems[7].setState(nomTiereModel.katze()); testItems[7].setState(futterModel.zucker());
} }
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
@ -65,14 +65,14 @@ void DativModel::write(ESGRAF48::DativModel &model) const
{ {
const auto &testItems = m_tests.at(0).items(); const auto &testItems = m_tests.at(0).items();
tiereModel->set_affe(testItems[0].isChecked()); tiereModel->set_tiger(testItems[0].isChecked());
tiereModel->set_gans(testItems[1].isChecked()); tiereModel->set_katze(testItems[1].isChecked());
tiereModel->set_tiger(testItems[2].isChecked()); tiereModel->set_affe(testItems[2].isChecked());
tiereModel->set_hund(testItems[3].isChecked()); tiereModel->set_gans(testItems[3].isChecked());
tiereModel->set_elefant(testItems[4].isChecked()); tiereModel->set_baer(testItems[4].isChecked());
tiereModel->set_pferd(testItems[5].isChecked()); tiereModel->set_pferd(testItems[5].isChecked());
tiereModel->set_baer(testItems[6].isChecked()); tiereModel->set_hund(testItems[6].isChecked());
tiereModel->set_katze(testItems[7].isChecked()); tiereModel->set_elefant(testItems[7].isChecked());
} }
auto *versteckeModel = model.mutable_verstecke(); auto *versteckeModel = model.mutable_verstecke();
@ -90,23 +90,23 @@ void DativModel::write(ESGRAF48::DativModel &model) const
versteckeModel->set_baum2(testItems[7].isChecked()); versteckeModel->set_baum2(testItems[7].isChecked());
} }
auto *nomTiereModel = model.mutable_nomtiere(); auto *futterModel = model.mutable_futter();
if (nomTiereModel != nullptr) if (futterModel != nullptr)
{ {
const auto &testItems = m_tests.at(2).items(); const auto &testItems = m_tests.at(2).items();
nomTiereModel->set_gans(testItems[0].isChecked()); futterModel->set_salat(testItems[0].isChecked());
nomTiereModel->set_tiger(testItems[1].isChecked()); futterModel->set_fleisch(testItems[1].isChecked());
nomTiereModel->set_hund(testItems[2].isChecked()); futterModel->set_knochen(testItems[2].isChecked());
nomTiereModel->set_affe(testItems[3].isChecked()); futterModel->set_banane(testItems[3].isChecked());
nomTiereModel->set_elefant(testItems[4].isChecked()); futterModel->set_apfel(testItems[4].isChecked());
nomTiereModel->set_pferd(testItems[5].isChecked()); futterModel->set_karotte(testItems[5].isChecked());
nomTiereModel->set_baer(testItems[6].isChecked()); futterModel->set_honig(testItems[6].isChecked());
nomTiereModel->set_katze(testItems[7].isChecked()); futterModel->set_zucker(testItems[7].isChecked());
} }
} }
void DativModel::printHeader(QPainter &painter) const std::string DativModel::getName() const
{ {
painter.translate(0, -1.5 * painter.fontMetrics().lineSpacing()); return "";
} }

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include "PrintableModel.h" #include "CheckableTestModel.h"
#include "DativModel.pb.h" #include "DativModel.pb.h"
class DativModel : public PrintableModel class DativModel : public CheckableTestModel
{ {
Q_OBJECT Q_OBJECT
@ -14,5 +14,5 @@ public:
void write(ESGRAF48::DativModel &model) const; void write(ESGRAF48::DativModel &model) const;
protected: protected:
void printHeader(QPainter &painter) const override; std::string getName() const override;
}; };

View File

@ -39,7 +39,9 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
PrintableModel CheckableItem
CheckableTest
CheckableTestModel
Qt5::Widgets Qt5::Widgets
${Protobuf_LIBRARIES} ${Protobuf_LIBRARIES}
) )

View File

@ -1,10 +1,8 @@
#include "GenusModel.h" #include "GenusModel.h"
GenusModel::GenusModel(QObject *parent) GenusModel::GenusModel(QObject *parent)
: PrintableModel(parent) : CheckableTestModel(parent)
{ {
m_title = "Subtest 3: Genus";
m_tests = {{"Tiere", {"Tiger", "Bär", "Katze", "Pferd", "Gans", "Elefant", "Affe", "Hund"}}, m_tests = {{"Tiere", {"Tiger", "Bär", "Katze", "Pferd", "Gans", "Elefant", "Affe", "Hund"}},
{"Futter", {"Futter",
{"Salat", "Fleisch", "Knochen", "Banane", "Apfel", "Karotte", "Honig", "Zucker"}}, {"Salat", "Fleisch", "Knochen", "Banane", "Apfel", "Karotte", "Honig", "Zucker"}},
@ -97,3 +95,8 @@ void GenusModel::write(ESGRAF48::GenusModel &model) const
zirkusModel->set_baum(testItems[3].isChecked()); zirkusModel->set_baum(testItems[3].isChecked());
} }
} }
std::string GenusModel::getName() const
{
return "Subtest 3: Genus";
}

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include "PrintableModel.h" #include "CheckableTestModel.h"
#include "GenusModel.pb.h" #include "GenusModel.pb.h"
class GenusModel : public PrintableModel class GenusModel : public CheckableTestModel
{ {
Q_OBJECT Q_OBJECT
@ -12,4 +12,7 @@ public:
void read(const ESGRAF48::GenusModel &model); void read(const ESGRAF48::GenusModel &model);
void write(ESGRAF48::GenusModel &model) const; void write(ESGRAF48::GenusModel &model) const;
protected:
std::string getName() const override;
}; };

View File

@ -44,7 +44,9 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
PrintableModel CheckableItem
CheckableTest
CheckableTestModel
Qt5::Widgets Qt5::Widgets
${Protobuf_LIBRARIES} ${Protobuf_LIBRARIES}
) )

View File

@ -108,7 +108,7 @@ void GenitivModel::write(ESGRAF48::LateSkillsGenitivModel &model) const
} }
} }
void GenitivModel::printHeader(QPainter &painter) const std::string GenitivModel::getName() const
{ {
painter.translate(0, -1.5 * painter.fontMetrics().lineSpacing()); return "";
} }

View File

@ -16,5 +16,5 @@ public:
void write(ESGRAF48::LateSkillsGenitivModel &model) const; void write(ESGRAF48::LateSkillsGenitivModel &model) const;
protected: protected:
void printHeader(QPainter &painter) const override; std::string getName() const override;
}; };

View File

@ -1,64 +1,65 @@
#include "LateSkillsModel.h" #include "LateSkillsModel.h"
#include <QTextTable>
#include <regex> #include <regex>
LateSkillsModel::LateSkillsModel(QObject *parent) LateSkillsModel::LateSkillsModel(QObject *parent)
: PrintableModel(parent) : CheckableTestModel(parent)
{ {
} }
void LateSkillsModel::printTests(QPainter &painter) const void LateSkillsModel::printTableTo(QTextCursor &cursor) const
{ {
painter.setFont(tableFont()); QTextTableFormat tableFormat = defaultTableFormat();
painter.setPen(tablePen());
auto width = painter.device()->width(); tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 20),
auto height = 1.5 * painter.fontMetrics().lineSpacing(); QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 26),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3)});
double headerWidth = headerWidthFactor() * width; QTextTable *table = cursor.insertTable(m_tests.size() * 3, 14, tableFormat);
double cellHeaderWidth = cellWidthFactor() * width;
double cellWidth = 0.5 * cellHeaderWidth;
double rowHeight = height;
double x = 0; int currentRow = 0;
double y = 0;
for (const auto &test : m_tests) for (const auto &test : m_tests)
{ {
QString testName = QString::fromStdString( table->mergeCells(currentRow, 0, 3, 1);
std::regex_replace(test.name().toStdString(), std::regex("\\s"), "\n"));
drawTextSquare(painter, {0, y, headerWidth, 3 * rowHeight}, testName); int currentColumn = 0;
const auto &items = test.items(); setCellText(*table, currentRow, currentColumn, test.name());
currentColumn++;
x = headerWidth; for (auto it = std::begin(test.items()); it != std::end(test.items()); std::advance(it, 2))
for (unsigned int i = 0; i < items.size(); i += 2)
{ {
const auto &item = test.items().at(i); const auto &item = *it;
QString itemText = QString::fromStdString(item.getText()).split(" ").at(0); const auto &nextItem = *std::next(it);
drawTextSquare(painter, {x, y, cellHeaderWidth, rowHeight}, itemText); table->mergeCells(currentRow, currentColumn, 1, 2);
x += cellHeaderWidth; auto itemName = std::regex_replace(item.getText(), std::regex(R"((\S+).*)"), "$1");
}
y += rowHeight;
x = headerWidth; setCellText(*table, currentRow, currentColumn, itemName.c_str());
for (const auto &item : items) setCellText(*table, currentRow + 1, currentColumn, "1");
{ setCellText(*table, currentRow + 1, currentColumn + 1, "2");
drawTextSquare(painter, {x, y, cellWidth, rowHeight}, QString::number(item.value())); setCellChecked(*table, currentRow + 2, currentColumn, item.isChecked());
drawCheckSquare(painter, {x, y + rowHeight, cellWidth, rowHeight}, item.isChecked()); setCellChecked(*table, currentRow + 2, currentColumn + 1, nextItem.isChecked());
x += cellWidth; currentColumn += 2;
} }
if (m_tests.size() > 1) setCellNumber(*table, currentRow + 2, 13, test.getPoints());
{
drawResultSquare(painter, y + rowHeight, true, test.getPoints());
}
y += 2 * rowHeight; currentRow += 3;
} }
painter.translate(0, y + rowHeight);
} }

View File

@ -1,9 +1,8 @@
#pragma once #pragma once
#include "PrintableModel.h" #include "CheckableTestModel.h"
#include "LateSkillsPassivModel.pb.h"
class LateSkillsModel : public PrintableModel class LateSkillsModel : public CheckableTestModel
{ {
Q_OBJECT Q_OBJECT
@ -11,5 +10,5 @@ public:
LateSkillsModel(QObject *parent); LateSkillsModel(QObject *parent);
protected: protected:
void printTests(QPainter &painter) const override; void printTableTo(QTextCursor &cursor) const override;
}; };

View File

@ -66,7 +66,7 @@ void PassivModel::write(ESGRAF48::LateSkillsPassivModel &model) const
model.set_fleisch2(testItems[9].isChecked()); model.set_fleisch2(testItems[9].isChecked());
} }
void PassivModel::printHeader(QPainter &painter) const std::string PassivModel::getName() const
{ {
drawHeader2(painter, "Subtest 6: Späte Fähigkeiten (7;0-8;11)"); return "Subtest 6: Späte Fähigkeiten (7;0 - 8;11)";
} }

View File

@ -9,11 +9,12 @@ class PassivModel : public LateSkillsModel
public: public:
PassivModel(QObject *parent); PassivModel(QObject *parent);
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
void read(const ESGRAF48::LateSkillsPassivModel &model); void read(const ESGRAF48::LateSkillsPassivModel &model);
void write(ESGRAF48::LateSkillsPassivModel &model) const; void write(ESGRAF48::LateSkillsPassivModel &model) const;
protected: protected:
void printHeader(QPainter &painter) const override; std::string getName() const override;
}; };

View File

@ -39,7 +39,9 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
PrintableModel CheckableItem
CheckableTest
CheckableTestModel
Qt5::Widgets Qt5::Widgets
${Protobuf_LIBRARIES} ${Protobuf_LIBRARIES}
) )

View File

@ -1,19 +1,29 @@
#include "PluralModel.h" #include "PluralModel.h"
#include <QSize> #include <QSize>
#include <QTextTable>
#include <QDebug>
#include <regex> #include <regex>
PluralModel::PluralModel(QObject *parent) PluralModel::PluralModel(QObject *parent)
: PrintableModel(parent) : CheckableTestModel(parent)
{ {
m_title = "Subtest 5: Plural"; m_tests = {{"",
m_tests = {{"Plural",
{"Fisch /-e/", "Banane /-n/", "Bonbon /-s/", "Ei /-er/", "Eimer /-ø/", {"Fisch /-e/", "Banane /-n/", "Bonbon /-s/", "Ei /-er/", "Eimer /-ø/",
"Korn UML+/-er/", "Nuss UML+/-e/", "Bär /-en/", "Apfel UML"}}}; "Korn UML+/-er/", "Nuss UML+/-e/", "Bär /-en/", "Apfel UML"}}};
} }
QVariant PluralModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::SizeHintRole)
{
return QSize(180, 0);
}
return CheckableTestModel::data(index, role);
}
void PluralModel::read(const ESGRAF48::PluralModel &model) void PluralModel::read(const ESGRAF48::PluralModel &model)
{ {
auto &testItems = m_tests.at(0).items(); auto &testItems = m_tests.at(0).items();
@ -46,38 +56,40 @@ void PluralModel::write(ESGRAF48::PluralModel &model) const
model.set_apfel(testItems[8].isChecked()); model.set_apfel(testItems[8].isChecked());
} }
void PluralModel::printTests(QPainter &painter) const std::string PluralModel::getName() const
{ {
painter.setFont(tableFont()); return "Subtest 5: Plural";
painter.setPen(tablePen()); }
auto width = painter.device()->width(); void PluralModel::printTableTo(QTextCursor &cursor) const
auto height = 1.5 * painter.fontMetrics().lineSpacing();
double headerWidth = headerWidthFactor() * width;
double cellWidth = cellWidthFactor() * width;
double rowHeight = height;
double x = 0;
double y = 0;
for (const auto &test : m_tests)
{ {
drawTextSquare(painter, {0, y, headerWidth, 3 * rowHeight}, test.name()); QTextTableFormat tableFormat = defaultTableFormat();
x = headerWidth;
tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10)});
QTextTable *table = cursor.insertTable(2, 10, tableFormat);
const auto &test = m_tests.front();
int currentColumn = 0;
for (const auto &item : test.items()) for (const auto &item : test.items())
{ {
QString itemText = std::string itemName = std::regex_replace(item.getText(), std::regex("\\s"), "\n",
QString::fromStdString(std::regex_replace(item.getText(), std::regex("\\s"), "\n")); std::regex_constants::format_first_only);
drawTextSquare(painter, {x, y, cellWidth, 2 * rowHeight}, itemText); setCellText(*table, 0, currentColumn, itemName.c_str());
drawCheckSquare(painter, {x, y + 2 * rowHeight, cellWidth, rowHeight}, setCellChecked(*table, 1, currentColumn, item.isChecked());
item.isChecked());
x += cellWidth; currentColumn++;
} }
y += 2 * rowHeight;
} }
painter.translate(0, y + 2 * rowHeight);
}

View File

@ -1,18 +1,23 @@
#pragma once #pragma once
#include "PrintableModel.h" #include "CheckableTestModel.h"
#include "PluralModel.pb.h" #include "PluralModel.pb.h"
class PluralModel : public PrintableModel class PluralModel : public CheckableTestModel
{ {
Q_OBJECT Q_OBJECT
public: public:
PluralModel(QObject *parent); PluralModel(QObject *parent);
QVariant data(
const QModelIndex &index, int role = Qt::DisplayRole) const override;
void read(const ESGRAF48::PluralModel &model); void read(const ESGRAF48::PluralModel &model);
void write(ESGRAF48::PluralModel &model) const; void write(ESGRAF48::PluralModel &model) const;
protected: protected:
virtual void printTests(QPainter &painter) const; std::string getName() const override;
void printTableTo(QTextCursor &cursor) const override;
}; };

View File

@ -8,8 +8,6 @@ PluralWidget::PluralWidget(QWidget *parent)
, ui(new Ui::PluralWidget) , ui(new Ui::PluralWidget)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->pluralTableView->horizontalHeader()->hide();
} }
PluralWidget::~PluralWidget() PluralWidget::~PluralWidget()
@ -20,4 +18,5 @@ PluralWidget::~PluralWidget()
void PluralWidget::setModel(PluralModel *model) void PluralWidget::setModel(PluralModel *model)
{ {
ui->pluralTableView->setModel(model); ui->pluralTableView->setModel(model);
ui->pluralTableView->resizeColumnsToContents();
} }

View File

@ -15,7 +15,17 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QTableView" name="pluralTableView"/> <widget class="QTableView" name="pluralTableView">
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>120</number>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@ -20,10 +20,6 @@ protobuf_generate_cpp(V2Svk_PROTO_SRCS V2Svk_PROTO_HDRS ${V2Svk_PROTO_FILES})
add_library(${PROJECT_NAME} add_library(${PROJECT_NAME}
V2SvkWidget.cpp V2SvkWidget.cpp
V2SvkModel.cpp V2SvkModel.cpp
WFModel.cpp
OTModel.cpp
TPrModel.cpp
TPeModel.cpp
${UI_HEADERS} ${UI_HEADERS}
${V2Svk_PROTO_SRCS} ${V2Svk_PROTO_SRCS}
${V2Svk_PROTO_HDRS} ${V2Svk_PROTO_HDRS}
@ -43,7 +39,9 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE PRIVATE
PrintableModel CheckableItem
CheckableTest
CheckableTestModel
Qt5::Widgets Qt5::Widgets
${Protobuf_LIBRARIES} ${Protobuf_LIBRARIES}
) )

View File

@ -1,115 +0,0 @@
#include "OTModel.h"
OTModel::OTModel(QObject *parent)
: V2SvkModel(parent)
{
m_tests = {
{"Objekt-Topikalisierung",
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
"Gans", "Gans", "Gans"}},
{"SVK: Stamm",
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
"Gans", "Gans", "Gans"}},
};
}
unsigned int OTModel::getV2Points() const
{
unsigned int points = 0;
for (auto testIndex : {0})
{
const auto &test = m_tests.at(testIndex);
for (const auto &item : test.items())
{
if (item.isChecked())
{
points++;
}
}
}
return points;
}
unsigned int OTModel::getSvkPoints() const
{
unsigned int points = 0;
for (auto testIndex : {1})
{
const auto &test = m_tests.at(testIndex);
for (const auto &item : test.items())
{
if (item.isChecked())
{
points++;
}
}
}
return points;
}
void OTModel::write(ESGRAF48::V2SvkModel &model) const
{
auto writeFourVals = [&](ESGRAF48::V2SvkModel::FourEach *modelData, int testIndex) {
if (modelData != nullptr)
{
const auto &testItems = m_tests.at(testIndex).items();
modelData->set_affe1(testItems[0].isChecked());
modelData->set_affe2(testItems[1].isChecked());
modelData->set_affe3(testItems[2].isChecked());
modelData->set_affe4(testItems[3].isChecked());
modelData->set_schwein1(testItems[4].isChecked());
modelData->set_schwein2(testItems[5].isChecked());
modelData->set_schwein3(testItems[6].isChecked());
modelData->set_schwein4(testItems[7].isChecked());
modelData->set_gans1(testItems[8].isChecked());
modelData->set_gans2(testItems[9].isChecked());
modelData->set_gans3(testItems[10].isChecked());
modelData->set_gans4(testItems[11].isChecked());
}
};
writeFourVals(model.mutable_objtop(), 0);
writeFourVals(model.mutable_svkstamm(), 1);
}
void OTModel::read(const ESGRAF48::V2SvkModel &model)
{
auto readFourVals = [&](const ESGRAF48::V2SvkModel::FourEach &modelData, int testIndex) {
auto &testItems = m_tests.at(testIndex).items();
testItems[0].setState(modelData.affe1());
testItems[1].setState(modelData.affe2());
testItems[2].setState(modelData.affe3());
testItems[3].setState(modelData.affe4());
testItems[4].setState(modelData.schwein1());
testItems[5].setState(modelData.schwein2());
testItems[6].setState(modelData.schwein3());
testItems[7].setState(modelData.schwein4());
testItems[8].setState(modelData.gans1());
testItems[9].setState(modelData.gans2());
testItems[10].setState(modelData.gans3());
testItems[11].setState(modelData.gans4());
};
readFourVals(model.objtop(), 0);
readFourVals(model.svkstamm(), 1);
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
}
std::set<int> OTModel::v2Tests() const
{
return {0};
};
std::set<int> OTModel::svkTests() const
{
return {1};
};

View File

@ -1,24 +0,0 @@
#pragma once
#include "V2SvkModel.h"
#include "V2SvkModel.pb.h"
class OTModel : public V2SvkModel
{
Q_OBJECT
public:
OTModel(QObject *parent);
unsigned int getV2Points() const override;
unsigned int getSvkPoints() const override;
void write(ESGRAF48::V2SvkModel &model) const override;
void read(const ESGRAF48::V2SvkModel &model) override;
protected:
void printHeader(QPainter &) const override {};
std::set<int> v2Tests() const override;
std::set<int> svkTests() const override;
};

View File

@ -1,105 +0,0 @@
#include "TPeModel.h"
TPeModel::TPeModel(QObject *parent)
: V2SvkModel(parent)
{
m_tests = {
{"Temporaladverb Perfekt", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
{"Verbtrennung", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
{"SVK: /-e/ o. Stamm", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
{"Partizip", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
};
}
unsigned int TPeModel::getV2Points() const
{
unsigned int points = 0;
for (auto testIndex : {0, 1})
{
const auto &test = m_tests.at(testIndex);
for (const auto &item : test.items())
{
if (item.isChecked())
{
points++;
}
}
}
return points;
}
unsigned int TPeModel::getSvkPoints() const
{
unsigned int points = 0;
for (auto testIndex : {2, 3})
{
const auto &test = m_tests.at(testIndex);
for (const auto &item : test.items())
{
if (item.isChecked())
{
points++;
}
}
}
return points;
}
void TPeModel::write(ESGRAF48::V2SvkModel &model) const
{
auto writeTwoVals = [&](ESGRAF48::V2SvkModel::TwoEach *modelData, int testIndex) {
if (modelData != nullptr)
{
const auto &testItems = m_tests.at(testIndex).items();
modelData->set_affe1(testItems[0].isChecked());
modelData->set_affe2(testItems[1].isChecked());
modelData->set_schwein1(testItems[2].isChecked());
modelData->set_schwein2(testItems[3].isChecked());
modelData->set_gans1(testItems[4].isChecked());
modelData->set_gans2(testItems[5].isChecked());
}
};
writeTwoVals(model.mutable_tempperf(), 0);
writeTwoVals(model.mutable_verbtrennung2(), 1);
writeTwoVals(model.mutable_svke2(), 2);
writeTwoVals(model.mutable_partizip(), 3);
}
void TPeModel::read(const ESGRAF48::V2SvkModel &model)
{
auto readTwoVals = [&](const ESGRAF48::V2SvkModel::TwoEach &modelData, int testIndex) {
auto &testItems = m_tests.at(testIndex).items();
testItems[0].setState(modelData.affe1());
testItems[1].setState(modelData.affe2());
testItems[2].setState(modelData.schwein1());
testItems[3].setState(modelData.schwein2());
testItems[4].setState(modelData.gans1());
testItems[5].setState(modelData.gans2());
};
readTwoVals(model.tempperf(), 0);
readTwoVals(model.verbtrennung2(), 1);
readTwoVals(model.svke2(), 2);
readTwoVals(model.partizip(), 3);
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
}
std::set<int> TPeModel::v2Tests() const
{
return {0, 1};
};
std::set<int> TPeModel::svkTests() const
{
return {2, 3};
};

View File

@ -1,24 +0,0 @@
#pragma once
#include "V2SvkModel.h"
#include "V2SvkModel.pb.h"
class TPeModel : public V2SvkModel
{
Q_OBJECT
public:
TPeModel(QObject *parent);
unsigned int getV2Points() const override;
unsigned int getSvkPoints() const override;
void write(ESGRAF48::V2SvkModel &model) const override;
void read(const ESGRAF48::V2SvkModel &model) override;
protected:
void printHeader(QPainter &) const override {};
std::set<int> v2Tests() const override;
std::set<int> svkTests() const override;
};

View File

@ -1,99 +0,0 @@
#include "TPrModel.h"
TPrModel::TPrModel(QObject *parent)
: V2SvkModel(parent)
{
m_tests = {
{"Temporaladverb Präsens", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
{"SKV: /-e/ o. Stamm", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
};
}
unsigned int TPrModel::getV2Points() const
{
unsigned int points = 0;
for (auto testIndex : {0})
{
const auto &test = m_tests.at(testIndex);
for (const auto &item : test.items())
{
if (item.isChecked())
{
points++;
}
}
}
return points;
}
unsigned int TPrModel::getSvkPoints() const
{
unsigned int points = 0;
for (auto testIndex : {1})
{
const auto &test = m_tests.at(testIndex);
for (const auto &item : test.items())
{
if (item.isChecked())
{
points++;
}
}
}
return points;
}
void TPrModel::write(ESGRAF48::V2SvkModel &model) const
{
auto writeTwoVals = [&](ESGRAF48::V2SvkModel::TwoEach *modelData, int testIndex) {
if (modelData != nullptr)
{
const auto &testItems = m_tests.at(testIndex).items();
modelData->set_affe1(testItems[0].isChecked());
modelData->set_affe2(testItems[1].isChecked());
modelData->set_schwein1(testItems[2].isChecked());
modelData->set_schwein2(testItems[3].isChecked());
modelData->set_gans1(testItems[4].isChecked());
modelData->set_gans2(testItems[5].isChecked());
}
};
writeTwoVals(model.mutable_temppraes(), 0);
writeTwoVals(model.mutable_svke1(), 1);
}
void TPrModel::read(const ESGRAF48::V2SvkModel &model)
{
auto readTwoVals = [&](const ESGRAF48::V2SvkModel::TwoEach &modelData, int testIndex) {
auto &testItems = m_tests.at(testIndex).items();
testItems[0].setState(modelData.affe1());
testItems[1].setState(modelData.affe2());
testItems[2].setState(modelData.schwein1());
testItems[3].setState(modelData.schwein2());
testItems[4].setState(modelData.gans1());
testItems[5].setState(modelData.gans2());
};
readTwoVals(model.temppraes(), 0);
readTwoVals(model.svke1(), 1);
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
}
std::set<int> TPrModel::v2Tests() const
{
return {0};
};
std::set<int> TPrModel::svkTests() const
{
return {1};
};

View File

@ -1,24 +0,0 @@
#pragma once
#include "V2SvkModel.h"
#include "V2SvkModel.pb.h"
class TPrModel : public V2SvkModel
{
Q_OBJECT
public:
TPrModel(QObject *parent);
unsigned int getV2Points() const override;
unsigned int getSvkPoints() const override;
void write(ESGRAF48::V2SvkModel &model) const override;
void read(const ESGRAF48::V2SvkModel &model) override;
protected:
void printHeader(QPainter &) const override{};
std::set<int> v2Tests() const override;
std::set<int> svkTests() const override;
};

View File

@ -1,137 +1,347 @@
#include "V2SvkModel.h" #include "V2SvkModel.h"
#include <regex> #include <QTextTable>
V2SvkModel::V2SvkModel(QObject *parent) V2SvkModel::V2SvkModel(QObject *parent)
: PrintableModel(parent) : CheckableTestModel(parent)
{ {
m_tests = {
{"W-Fragen",
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
"Gans", "Gans", "Gans"}},
{"Verbtrennung", {"", "Affe", "", "", "", "", "", "Schwein", "", "", "Gans", ""}},
{"SVK: /-st/",
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
"Gans", "Gans", "Gans"}},
{"Objekt-Topikalisierung",
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
"Gans", "Gans", "Gans"}},
{"SVK: Stamm",
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
"Gans", "Gans", "Gans"}},
{"Temporaladverb Präsens", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
{"SKV: /-e/ o. Stamm", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
{"Temporaladverb Perfekt", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
{"Verbtrennung", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
{"SVK: /-e/ o. Stamm", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
{"Partizip", {"Affe", "Affe", "Schwein", "Schwein", "Gans", "Gans"}},
};
} }
void V2SvkModel::printTests(QPainter &painter) const unsigned int V2SvkModel::getV2Points() const
{ {
painter.setFont(tableFont()); unsigned int points = 0;
painter.setPen(tablePen());
auto width = painter.device()->width(); for (auto testIndex : {0, 1, 3, 5, 7, 8})
auto height = 1.5 * painter.fontMetrics().lineSpacing();
auto v2TestIndices = v2Tests();
auto svkTestIndices = svkTests();
double x = 0;
double y = 0;
auto testIndex = 0;
for (const auto &test : m_tests)
{ {
double rowHeaderWidth = headerWidthFactor() * width; const auto &test = m_tests.at(testIndex);
double resultCellWidth = (test.size() > 8 ? 0.5 : 1) * cellWidthFactor() * width;
double rowHeight = height;
QString testName = test.name();
if (testName.length() > 20)
{
testName = QString::fromStdString(
std::regex_replace(testName.toStdString(), std::regex("[\\s-]"), "\n"));
}
if (testIndex == 0)
{
drawTextSquare(painter, {x, y, rowHeaderWidth, 2 * rowHeight}, testName);
x += rowHeaderWidth;
std::vector<std::pair<std::string, unsigned int>> columnHeaders;
for (const auto &item : test.items()) for (const auto &item : test.items())
{ {
const auto &itemText = item.getText(); if (item.isChecked())
if (!columnHeaders.empty() && columnHeaders.back().first == itemText)
{ {
columnHeaders.back().second++; points++;
} }
else
{
columnHeaders.emplace_back(itemText, 1);
} }
} }
for (const auto &columnHeader : columnHeaders) return points;
{
double cellWidth = columnHeader.second * resultCellWidth;
drawTextSquare(painter, {x, y, cellWidth, rowHeight}, columnHeader.first.c_str());
x += cellWidth;
}
x = rowHeaderWidth;
y += rowHeight;
}
else
{
drawTextSquare(painter, {x, y, rowHeaderWidth, rowHeight}, testName);
x += rowHeaderWidth;
} }
unsigned int emptyItemsStack = 0; unsigned int V2SvkModel::getSvkPoints() const
{
unsigned int points = 0;
for (auto testIndex : {2, 4, 6, 9, 10})
{
const auto &test = m_tests.at(testIndex);
for (const auto &item : test.items()) for (const auto &item : test.items())
{ {
if (item.isChecked())
{
points++;
}
}
}
return points;
}
bool V2SvkModel::isValidIndex(const QModelIndex &index) const
{
switch (index.row())
{
case 1:
return index.column() == 1 || index.column() == 7 || index.column() == 10;
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
return index.column() < 6;
default:
return CheckableTestModel::isValidIndex(index);
}
}
void V2SvkModel::write(ESGRAF48::V2SvkModel &model) const
{
auto writeOneVal = [&](ESGRAF48::V2SvkModel::OneEach *modelData, int testIndex) {
if (modelData != nullptr)
{
const auto &testItems = m_tests.at(testIndex).items();
modelData->set_affe(testItems[1].isChecked());
modelData->set_schwein(testItems[7].isChecked());
modelData->set_gans(testItems[10].isChecked());
}
};
auto writeTwoVals = [&](ESGRAF48::V2SvkModel::TwoEach *modelData, int testIndex) {
if (modelData != nullptr)
{
const auto &testItems = m_tests.at(testIndex).items();
modelData->set_affe1(testItems[0].isChecked());
modelData->set_affe2(testItems[1].isChecked());
modelData->set_schwein1(testItems[2].isChecked());
modelData->set_schwein2(testItems[3].isChecked());
modelData->set_gans1(testItems[4].isChecked());
modelData->set_gans2(testItems[5].isChecked());
}
};
auto writeFourVals = [&](ESGRAF48::V2SvkModel::FourEach *modelData, int testIndex) {
if (modelData != nullptr)
{
const auto &testItems = m_tests.at(testIndex).items();
modelData->set_affe1(testItems[0].isChecked());
modelData->set_affe2(testItems[1].isChecked());
modelData->set_affe3(testItems[2].isChecked());
modelData->set_affe4(testItems[3].isChecked());
modelData->set_schwein1(testItems[4].isChecked());
modelData->set_schwein2(testItems[5].isChecked());
modelData->set_schwein3(testItems[6].isChecked());
modelData->set_schwein4(testItems[7].isChecked());
modelData->set_gans1(testItems[8].isChecked());
modelData->set_gans2(testItems[9].isChecked());
modelData->set_gans3(testItems[10].isChecked());
modelData->set_gans4(testItems[11].isChecked());
}
};
writeFourVals(model.mutable_wfrage(), 0);
writeOneVal(model.mutable_verbtrennung1(), 1);
writeFourVals(model.mutable_svkst(), 2);
writeFourVals(model.mutable_objtop(), 3);
writeFourVals(model.mutable_svkstamm(), 4);
writeTwoVals(model.mutable_temppraes(), 5);
writeTwoVals(model.mutable_svke1(), 6);
writeTwoVals(model.mutable_tempperf(), 7);
writeTwoVals(model.mutable_verbtrennung2(), 8);
writeTwoVals(model.mutable_svke2(), 9);
writeTwoVals(model.mutable_partizip(), 10);
}
void V2SvkModel::read(const ESGRAF48::V2SvkModel &model)
{
auto readOneVal = [&](const ESGRAF48::V2SvkModel::OneEach &modelData, int testIndex) {
auto &testItems = m_tests.at(testIndex).items();
testItems[1].setState(modelData.affe());
testItems[7].setState(modelData.schwein());
testItems[10].setState(modelData.gans());
};
auto readTwoVals = [&](const ESGRAF48::V2SvkModel::TwoEach &modelData, int testIndex) {
auto &testItems = m_tests.at(testIndex).items();
testItems[0].setState(modelData.affe1());
testItems[1].setState(modelData.affe2());
testItems[2].setState(modelData.schwein1());
testItems[3].setState(modelData.schwein2());
testItems[4].setState(modelData.gans1());
testItems[5].setState(modelData.gans2());
};
auto readFourVals = [&](const ESGRAF48::V2SvkModel::FourEach &modelData, int testIndex) {
auto &testItems = m_tests.at(testIndex).items();
testItems[0].setState(modelData.affe1());
testItems[1].setState(modelData.affe2());
testItems[2].setState(modelData.affe3());
testItems[3].setState(modelData.affe4());
testItems[4].setState(modelData.schwein1());
testItems[5].setState(modelData.schwein2());
testItems[6].setState(modelData.schwein3());
testItems[7].setState(modelData.schwein4());
testItems[8].setState(modelData.gans1());
testItems[9].setState(modelData.gans2());
testItems[10].setState(modelData.gans3());
testItems[11].setState(modelData.gans4());
};
readFourVals(model.wfrage(), 0);
readOneVal(model.verbtrennung1(), 1);
readFourVals(model.svkst(), 2);
readFourVals(model.objtop(), 3);
readFourVals(model.svkstamm(), 4);
readTwoVals(model.temppraes(), 5);
readTwoVals(model.svke1(), 6);
readTwoVals(model.tempperf(), 7);
readTwoVals(model.verbtrennung2(), 8);
readTwoVals(model.svke2(), 9);
readTwoVals(model.partizip(), 10);
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
}
std::string V2SvkModel::getName() const
{
return "Subtest 1: Verbzweitstellungsregel (V2) und Subjekt-Verb-Kontrollregel (SVK)";
}
void V2SvkModel::printTableTo(QTextCursor &cursor) const
{
QTextTableFormat tableFormat12 = defaultTableFormat();
tableFormat12.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 20),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 5),
QTextLength(QTextLength::PercentageLength, 13),
QTextLength(QTextLength::PercentageLength, 3),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3)});
QTextTableFormat tableFormat6 = defaultTableFormat();
tableFormat6.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 20),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 10),
QTextLength(QTextLength::PercentageLength, 13),
QTextLength(QTextLength::PercentageLength, 3),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3)});
auto writeHeader = [](QTextTable *table, const CheckableTest &test, int colSpan) {
table->mergeCells(0, 0, 2, 1);
int column = 1;
for (auto it = std::begin(test.items()); it != std::end(test.items());
std::advance(it, colSpan))
{
table->mergeCells(0, column, 1, colSpan);
setCellText(*table, 0, column, it->getText().c_str());
column += colSpan;
}
};
auto writeLine = [](QTextTable *table, const CheckableTest &test, int row, int resultColumn) {
int column = 0;
setCellText(*table, row, column, test.name());
for (const auto item : test.items())
{
column++;
if (item.getText().empty()) if (item.getText().empty())
{ {
emptyItemsStack++; setCellBackground(*table, row, column, QColor(92, 92, 92));
} }
else else
{ {
if (emptyItemsStack > 0) setCellChecked(*table, row, column, item.isChecked());
}
}
setCellNumber(*table, row, resultColumn, test.getPoints());
};
{ {
drawGreySquare(painter, {x - emptyItemsStack * resultCellWidth, y, QTextTable *table = cursor.insertTable(4, 17, tableFormat12);
emptyItemsStack * resultCellWidth, rowHeight});
emptyItemsStack = 0; writeHeader(table, m_tests[0], 4);
writeLine(table, m_tests[0], 1, 14);
writeLine(table, m_tests[1], 2, 14);
writeLine(table, m_tests[2], 3, 16);
} }
drawCheckSquare(painter, {x, y, resultCellWidth, rowHeight}, item.isChecked()); cursor.movePosition(QTextCursor::End);
} cursor.insertBlock();
x += resultCellWidth; cursor.insertText("\n");
}
if (emptyItemsStack > 0)
{ {
drawGreySquare(painter, {x - emptyItemsStack * resultCellWidth, y, QTextTable *table = cursor.insertTable(3, 17, tableFormat12);
emptyItemsStack * resultCellWidth, rowHeight});
emptyItemsStack = 0; writeHeader(table, m_tests[3], 4);
writeLine(table, m_tests[3], 1, 14);
writeLine(table, m_tests[4], 2, 16);
} }
if (v2TestIndices.find(testIndex) != v2TestIndices.end()) cursor.movePosition(QTextCursor::End);
cursor.insertBlock();
cursor.insertText("\n");
{ {
drawResultSquare(painter, y, false, test.getPoints()); QTextTable *table = cursor.insertTable(3, 11, tableFormat6);
writeHeader(table, m_tests[5], 2);
writeLine(table, m_tests[5], 1, 8);
writeLine(table, m_tests[6], 2, 10);
} }
if (svkTestIndices.find(testIndex) != svkTestIndices.end()) cursor.movePosition(QTextCursor::End);
cursor.insertBlock();
cursor.insertText("\n");
{ {
drawResultSquare(painter, y, true, test.getPoints()); QTextTable *table = cursor.insertTable(5, 11, tableFormat6);
writeHeader(table, m_tests[7], 2);
writeLine(table, m_tests[7], 1, 8);
writeLine(table, m_tests[8], 2, 8);
writeLine(table, m_tests[9], 3, 10);
writeLine(table, m_tests[10], 4, 10);
}
} }
x = 0; void V2SvkModel::printSummaryTo(QTextCursor &cursor) const
y += rowHeight;
testIndex++;
}
x = 0;
y += height;
painter.translate(0, y);
}
void V2SvkModel::printSummary(QPainter &painter, unsigned int v2Points, unsigned int svkPoints)
{ {
painter.setFont(PrintableModel::tableFont()); QTextTableFormat tableFormat = defaultTableFormat();
painter.setPen(PrintableModel::tablePen());
auto width = painter.device()->width(); tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 72),
auto height = 1.5 * painter.fontMetrics().lineSpacing(); QTextLength(QTextLength::PercentageLength, 20),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3)});
painter.drawText(0, 0, 0.91 * width, height, Qt::AlignRight | Qt::AlignVCenter, QTextTable *table = cursor.insertTable(1, 6, tableFormat);
"Rohwertpunkte Total:");
painter.setPen(resultPen()); setCellText(*table, 0, 1, "Rohwertpunkte Total:");
drawNumberSquare(painter, 0.93 * width, 0, v2Points); setCellNumber(*table, 0, 3, getV2Points());
drawNumberSquare(painter, 0.97 * width, 0, svkPoints); setCellNumber(*table, 0, 5, getSvkPoints());
painter.translate(0, 3 * height);
} }

View File

@ -1,27 +1,27 @@
#pragma once #pragma once
#include "PrintableModel.h" #include "CheckableTestModel.h"
#include "V2SvkModel.pb.h" #include "V2SvkModel.pb.h"
class V2SvkModel : public PrintableModel #include <QTextCursor>
class V2SvkModel : public CheckableTestModel
{ {
Q_OBJECT Q_OBJECT
public: public:
V2SvkModel(QObject *parent); V2SvkModel(QObject *parent);
virtual unsigned int getV2Points() const = 0; unsigned int getV2Points() const;
virtual unsigned int getSvkPoints() const = 0; unsigned int getSvkPoints() const;
virtual void write(ESGRAF48::V2SvkModel &model) const = 0; void write(ESGRAF48::V2SvkModel &model) const;
virtual void read(const ESGRAF48::V2SvkModel &model) = 0; void read(const ESGRAF48::V2SvkModel &model);
static void printSummary(QPainter &painter, unsigned int v2Points, unsigned int svkPoints);
protected: protected:
void printTests(QPainter &painter) const override; bool isValidIndex(const QModelIndex &index) const override;
void printSummary(QPainter &painter) const override {};
virtual std::set<int> v2Tests() const = 0; std::string getName() const override;
virtual std::set<int> svkTests() const = 0; void printTableTo(QTextCursor &cursor) const override;
void printSummaryTo(QTextCursor &cursor) const override;
}; };

View File

@ -1,20 +1,14 @@
#include "V2SvkWidget.h" #include "V2SvkWidget.h"
#include "ui_V2SvkWidget.h" #include "ui_V2SvkWidget.h"
#include "WFModel.h" #include "V2SvkModel.h"
#include "OTModel.h"
#include "TPrModel.h"
#include "TPeModel.h"
V2SvkWidget::V2SvkWidget(QWidget *parent) V2SvkWidget::V2SvkWidget(QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::V2SvkWidget) , ui(new Ui::V2SvkWidget)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->wfTableView->horizontalHeader()->hide(); ui->v2SvkTableView->horizontalHeader()->hide();
ui->otTableView->horizontalHeader()->hide();
ui->tprTableView->horizontalHeader()->hide();
ui->tpeTableView->horizontalHeader()->hide();
} }
V2SvkWidget::~V2SvkWidget() V2SvkWidget::~V2SvkWidget()
@ -22,22 +16,7 @@ V2SvkWidget::~V2SvkWidget()
delete ui; delete ui;
} }
void V2SvkWidget::setWFModel(WFModel *model) void V2SvkWidget::setV2SvkModel(V2SvkModel *model)
{ {
ui->wfTableView->setModel(model); ui->v2SvkTableView->setModel(model);
}
void V2SvkWidget::setOTModel(OTModel *model)
{
ui->otTableView->setModel(model);
}
void V2SvkWidget::setTPrModel(TPrModel *model)
{
ui->tprTableView->setModel(model);
}
void V2SvkWidget::setTPeModel(TPeModel *model)
{
ui->tpeTableView->setModel(model);
} }

View File

@ -2,10 +2,7 @@
#include <QWidget> #include <QWidget>
class WFModel; class V2SvkModel;
class OTModel;
class TPrModel;
class TPeModel;
namespace Ui { namespace Ui {
class V2SvkWidget; class V2SvkWidget;
@ -22,8 +19,5 @@ public:
V2SvkWidget(QWidget *parent = nullptr); V2SvkWidget(QWidget *parent = nullptr);
~V2SvkWidget(); ~V2SvkWidget();
void setWFModel(WFModel *model); void setV2SvkModel(V2SvkModel *model);
void setOTModel(OTModel *model);
void setTPrModel(TPrModel *model);
void setTPeModel(TPeModel *model);
}; };

View File

@ -15,16 +15,7 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QTableView" name="wfTableView"/> <widget class="QTableView" name="v2SvkTableView"/>
</item>
<item>
<widget class="QTableView" name="otTableView"/>
</item>
<item>
<widget class="QTableView" name="tprTableView"/>
</item>
<item>
<widget class="QTableView" name="tpeTableView"/>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@ -1,147 +0,0 @@
#include "WFModel.h"
WFModel::WFModel(QObject *parent)
: V2SvkModel(parent)
{
m_title = "Subtest 1: Verbzweitstellungsregel (V2) und Subjekt-Verb-Kontrollregel (SVK)";
m_tests = {
{"W-Frage",
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
"Gans", "Gans", "Gans"}},
{"Verbtrennung", {"", "Affe", "", "", "", "", "", "Schwein", "", "", "Gans", ""}},
{"SVK: /-st/",
{"Affe", "Affe", "Affe", "Affe", "Schwein", "Schwein", "Schwein", "Schwein", "Gans",
"Gans", "Gans", "Gans"}},
};
}
unsigned int WFModel::getV2Points() const
{
unsigned int points = 0;
for (auto testIndex : {0, 1})
{
const auto &test = m_tests.at(testIndex);
for (const auto &item : test.items())
{
if (item.isChecked())
{
points++;
}
}
}
return points;
}
unsigned int WFModel::getSvkPoints() const
{
unsigned int points = 0;
for (auto testIndex : {2})
{
const auto &test = m_tests.at(testIndex);
for (const auto &item : test.items())
{
if (item.isChecked())
{
points++;
}
}
}
return points;
}
bool WFModel::isValidIndex(const QModelIndex &index) const
{
if (index.row() == 1)
{
return index.column() == 1 || index.column() == 7 || index.column() == 10;
}
return CheckableTestModel::isValidIndex(index);
}
void WFModel::write(ESGRAF48::V2SvkModel &model) const
{
auto writeOneVal = [&](ESGRAF48::V2SvkModel::OneEach *modelData, int testIndex) {
if (modelData != nullptr)
{
const auto &testItems = m_tests.at(testIndex).items();
modelData->set_affe(testItems[1].isChecked());
modelData->set_schwein(testItems[7].isChecked());
modelData->set_gans(testItems[10].isChecked());
}
};
auto writeFourVals = [&](ESGRAF48::V2SvkModel::FourEach *modelData, int testIndex) {
if (modelData != nullptr)
{
const auto &testItems = m_tests.at(testIndex).items();
modelData->set_affe1(testItems[0].isChecked());
modelData->set_affe2(testItems[1].isChecked());
modelData->set_affe3(testItems[2].isChecked());
modelData->set_affe4(testItems[3].isChecked());
modelData->set_schwein1(testItems[4].isChecked());
modelData->set_schwein2(testItems[5].isChecked());
modelData->set_schwein3(testItems[6].isChecked());
modelData->set_schwein4(testItems[7].isChecked());
modelData->set_gans1(testItems[8].isChecked());
modelData->set_gans2(testItems[9].isChecked());
modelData->set_gans3(testItems[10].isChecked());
modelData->set_gans4(testItems[11].isChecked());
}
};
writeFourVals(model.mutable_wfrage(), 0);
writeOneVal(model.mutable_verbtrennung1(), 1);
}
void WFModel::read(const ESGRAF48::V2SvkModel &model)
{
auto readOneVal = [&](const ESGRAF48::V2SvkModel::OneEach &modelData, int testIndex) {
auto &testItems = m_tests.at(testIndex).items();
testItems[1].setState(modelData.affe());
testItems[7].setState(modelData.schwein());
testItems[10].setState(modelData.gans());
};
auto readFourVals = [&](const ESGRAF48::V2SvkModel::FourEach &modelData, int testIndex) {
auto &testItems = m_tests.at(testIndex).items();
testItems[0].setState(modelData.affe1());
testItems[1].setState(modelData.affe2());
testItems[2].setState(modelData.affe3());
testItems[3].setState(modelData.affe4());
testItems[4].setState(modelData.schwein1());
testItems[5].setState(modelData.schwein2());
testItems[6].setState(modelData.schwein3());
testItems[7].setState(modelData.schwein4());
testItems[8].setState(modelData.gans1());
testItems[9].setState(modelData.gans2());
testItems[10].setState(modelData.gans3());
testItems[11].setState(modelData.gans4());
};
readFourVals(model.wfrage(), 0);
readOneVal(model.verbtrennung1(), 1);
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
}
std::set<int> WFModel::v2Tests() const
{
return {0, 1};
};
std::set<int> WFModel::svkTests() const
{
return {2};
};

View File

@ -1,24 +0,0 @@
#pragma once
#include "V2SvkModel.h"
#include "V2SvkModel.pb.h"
class WFModel : public V2SvkModel
{
Q_OBJECT
public:
WFModel(QObject *parent);
unsigned int getV2Points() const override;
unsigned int getSvkPoints() const override;
void write(ESGRAF48::V2SvkModel &model) const override;
void read(const ESGRAF48::V2SvkModel &model) override;
protected:
std::set<int> v2Tests() const override;
std::set<int> svkTests() const override;
bool isValidIndex(const QModelIndex &index) const override;
};

View File

@ -42,7 +42,6 @@ target_link_libraries(${PROJECT_NAME}
CheckableItem CheckableItem
CheckableTest CheckableTest
CheckableTestModel CheckableTestModel
PrintableModel
Qt5::Widgets Qt5::Widgets
${Protobuf_LIBRARIES} ${Protobuf_LIBRARIES}
) )

View File

@ -1,14 +1,17 @@
#include "VerbEndModel.h" #include "VerbEndModel.h"
VerbEndModel::VerbEndModel(QObject *parent) #include <QTextTable>
: PrintableModel(parent) #include <QDebug>
{
m_title = "Subtest 2: Verbendstellungsregel (VE)";
VerbEndModel::VerbEndModel(QObject *parent)
: CheckableTestModel(parent)
{
m_tests = { m_tests = {
{"Telefonat", {"Kausal", "Kausal", "Relativ", "Kausal", "Final", "Temporal", "Temporal"}}, {"Telefonat", {"Kausal", "Kausal", "Relativ", "Kausal", "Final", "Temporal", "Temporal"}},
{"Zaubertrick", {"Relativ", "Final", "Kausal", "Final", "Temporal", "Kausal", "Temporal"}}, {"Zaubertrick", {"Relativ", "Final", "Kausal", "Final", "Temporal", "Kausal", "Temporal"}},
{"Zauberregel", {"Temporal", "Kausal", "Final", "Relativ", "Temporal", "Relativ"}}}; {"Zauberregel", {"Temporal", "Kausal", "Final", "Relativ", "Temporal", "Relativ"}}};
connect(this, &VerbEndModel::dataChanged, this, &VerbEndModel::modelChanged);
} }
void VerbEndModel::write(ESGRAF48::VerbEndModel &model) const void VerbEndModel::write(ESGRAF48::VerbEndModel &model) const
@ -98,31 +101,51 @@ void VerbEndModel::read(const ESGRAF48::VerbEndModel &model)
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
} }
unsigned int VerbEndModel::getKausalPoints() const unsigned int VerbEndModel::getCausalPoints() const
{ {
auto points = [&](unsigned int testId, unsigned int itemId) { unsigned int points = 0;
return m_tests.at(testId).items().at(itemId).points();
for (const auto &test : m_tests)
{
for (const auto &item : test.items())
{
if (item.getText() == "Kausal")
{
points += item.points();
}
}
}
return points;
}
void VerbEndModel::modelChanged()
{
emit causalPointsChanged(getCausalPoints());
}
std::string VerbEndModel::getName() const
{
return "Subtest 2: Verbendstellungsregel (VE)";
}; };
return points(0, 0) + points(0, 1) + points(0, 3) + points(1, 2) + points(1, 5) + points(2, 1); void VerbEndModel::printSummaryTo(QTextCursor &cursor) const
}
void VerbEndModel::printSummary(QPainter &painter) const
{ {
painter.setFont(tableFont()); QTextTableFormat tableFormat = defaultTableFormat();
auto width = painter.device()->width(); tableFormat.setColumnWidthConstraints({QTextLength(QTextLength::PercentageLength, 46),
auto height = 1.5 * painter.fontMetrics().lineSpacing(); QTextLength(QTextLength::PercentageLength, 25),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 20),
QTextLength(QTextLength::PercentageLength, 1),
QTextLength(QTextLength::PercentageLength, 3)});
painter.drawText(0, 0, 0.71 * width, height, Qt::AlignRight | Qt::AlignVCenter, QTextTable *table = cursor.insertTable(1, 8, tableFormat);
"Rohwertpunkte Kausalsätze:");
painter.drawText(0, 0, 0.95 * width, height, Qt::AlignRight | Qt::AlignVCenter,
"Rohwertpunkte Total:");
drawNumberSquare(painter, 0.73 * width, 0, getKausalPoints()); setCellText(*table, 0, 1, "Rohwertpunkte Kausalsätze:");
setCellNumber(*table, 0, 3, getCausalPoints());
painter.setPen(resultPen()); setCellText(*table, 0, 5, "Rohwertpunkte Total:");
drawNumberSquare(painter, 0.97 * width, 0, getKausalPoints()); setCellNumber(*table, 0, 7, getPoints());
painter.translate(0, 3 * height);
} }

View File

@ -1,9 +1,11 @@
#pragma once #pragma once
#include "PrintableModel.h" #include "CheckableTestModel.h"
#include "VerbEndModel.pb.h" #include "VerbEndModel.pb.h"
class VerbEndModel : public PrintableModel #include <QTextCursor>
class VerbEndModel : public CheckableTestModel
{ {
Q_OBJECT Q_OBJECT
@ -13,8 +15,15 @@ public:
void write(ESGRAF48::VerbEndModel &model) const; void write(ESGRAF48::VerbEndModel &model) const;
void read(const ESGRAF48::VerbEndModel &model); void read(const ESGRAF48::VerbEndModel &model);
unsigned int getKausalPoints() const; unsigned int getCausalPoints() const;
protected: protected:
void printSummary(QPainter &painter) const override; std::string getName() const override;
void printSummaryTo(QTextCursor &cursor) const override;
private slots:
void modelChanged();
signals:
void causalPointsChanged(unsigned int points);
}; };

View File

@ -20,4 +20,11 @@ VerbEndWidget::~VerbEndWidget()
void VerbEndWidget::setModel(VerbEndModel *model) void VerbEndWidget::setModel(VerbEndModel *model)
{ {
ui->verbEndTableView->setModel(model); ui->verbEndTableView->setModel(model);
connect(model, &VerbEndModel::causalPointsChanged, this, &VerbEndWidget::causalPointsChanged);
}
void VerbEndWidget::causalPointsChanged(unsigned int points)
{
ui->causalPointsLabel->setText(QString::number(points));
} }

View File

@ -20,4 +20,7 @@ public:
~VerbEndWidget(); ~VerbEndWidget();
void setModel(VerbEndModel *model); void setModel(VerbEndModel *model);
public slots:
void causalPointsChanged(unsigned int points);
}; };

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>556</width> <width>732</width>
<height>210</height> <height>381</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -17,6 +17,30 @@
<item> <item>
<widget class="QTableView" name="verbEndTableView"/> <widget class="QTableView" name="verbEndTableView"/>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Kausalsätze: </string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="causalPointsLabel">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@ -1,8 +1,6 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "version.h"
#include <QJsonObject> #include <QJsonObject>
#include <QJsonDocument> #include <QJsonDocument>
#include <QFile> #include <QFile>
@ -13,7 +11,6 @@
#include <QtPrintSupport/QPrinter> #include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QPrintDialog> #include <QtPrintSupport/QPrintDialog>
#include <QTextDocument> #include <QTextDocument>
#include <QPainter>
#include <QDebug> #include <QDebug>
@ -49,12 +46,7 @@ void MainWindow::setupUi()
ui->pluralWidget->setModel(&m_dataModel.m_plural); ui->pluralWidget->setModel(&m_dataModel.m_plural);
ui->akkusativDativWidget->setAkkusativModel(&m_dataModel.m_akkusativ); ui->akkusativDativWidget->setAkkusativModel(&m_dataModel.m_akkusativ);
ui->akkusativDativWidget->setDativModel(&m_dataModel.m_dativ); ui->akkusativDativWidget->setDativModel(&m_dataModel.m_dativ);
ui->v2SvkWidget->setV2SvkModel(&m_dataModel.m_v2Svk);
ui->v2SvkWidget->setWFModel(&m_dataModel.m_wfModel);
ui->v2SvkWidget->setOTModel(&m_dataModel.m_otModel);
ui->v2SvkWidget->setTPrModel(&m_dataModel.m_tPrModel);
ui->v2SvkWidget->setTPeModel(&m_dataModel.m_tPeModel);
ui->lateSkillsWidget->setPassivModel(&m_dataModel.m_passiv); ui->lateSkillsWidget->setPassivModel(&m_dataModel.m_passiv);
ui->lateSkillsWidget->setGenitivModel(&m_dataModel.m_genitiv); ui->lateSkillsWidget->setGenitivModel(&m_dataModel.m_genitiv);
ui->resultWidget->setModel(&m_dataModel.m_results); ui->resultWidget->setModel(&m_dataModel.m_results);
@ -66,8 +58,6 @@ void MainWindow::setupUi()
connect(ui->actionPrint, &QAction::triggered, this, &MainWindow::print); connect(ui->actionPrint, &QAction::triggered, this, &MainWindow::print);
connect(ui->actionExport_PDF, &QAction::triggered, this, qOverload<>(&MainWindow::savePdf)); connect(ui->actionExport_PDF, &QAction::triggered, this, qOverload<>(&MainWindow::savePdf));
connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::aboutDialog);
connect(&m_dataModel, &DataModel::modelChanged, this, &MainWindow::dataModelChanged); connect(&m_dataModel, &DataModel::modelChanged, this, &MainWindow::dataModelChanged);
} }
@ -95,22 +85,15 @@ void MainWindow::openFile()
return; return;
} }
try
{
openFile(filename); openFile(filename);
} }
catch (std::exception &e)
{
QString errorMessage = QString("Error loading \"") + filename + "\": " + e.what();
QMessageBox::critical(this, "Error", errorMessage);
}
}
void MainWindow::openFile(const QString &filename) void MainWindow::openFile(const QString &filename)
{ {
closeFile(); closeFile();
m_dataModel.read(filename); std::fstream protoInFile(filename.toStdString(), std::ios::in | std::ios::binary);
m_dataModel.read(protoInFile);
setWindowModified(false); setWindowModified(false);
setWindowTitle(filename + "[*]"); setWindowTitle(filename + "[*]");
@ -135,7 +118,6 @@ void MainWindow::saveFile()
void MainWindow::saveFileAs() void MainWindow::saveFileAs()
{ {
QFileDialog saveFilenameDialog(this); QFileDialog saveFilenameDialog(this);
saveFilenameDialog.setAcceptMode(QFileDialog::AcceptSave);
saveFilenameDialog.setDefaultSuffix("esgraf48"); saveFilenameDialog.setDefaultSuffix("esgraf48");
saveFilenameDialog.setFileMode(QFileDialog::AnyFile); saveFilenameDialog.setFileMode(QFileDialog::AnyFile);
saveFilenameDialog.setNameFilter("ESGRAF 4-8 (*.esgraf48)"); saveFilenameDialog.setNameFilter("ESGRAF 4-8 (*.esgraf48)");
@ -169,8 +151,7 @@ void MainWindow::closeFile()
void MainWindow::print() const void MainWindow::print() const
{ {
QPrinter printer; QPrinter printer;
printer.setPaperSize(QPrinter::A4); printer.setResolution(1200);
printer.setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);
QPrintDialog dialog(&printer); QPrintDialog dialog(&printer);
if (dialog.exec() != QDialog::Accepted) if (dialog.exec() != QDialog::Accepted)
@ -178,7 +159,11 @@ void MainWindow::print() const
return; return;
} }
m_dataModel.printTo(printer); QTextDocument printDoc;
QTextCursor printCursor(&printDoc);
m_dataModel.printTo(printCursor);
printDoc.print(&printer);
} }
void MainWindow::dataModelChanged() void MainWindow::dataModelChanged()
@ -210,16 +195,9 @@ void MainWindow::closeEvent(QCloseEvent *event)
void MainWindow::saveFile(const QString &filename) void MainWindow::saveFile(const QString &filename)
{ {
try std::fstream protoOutFile(filename.toStdString(),
{ std::ios::out | std::ios::trunc | std::ios::binary);
m_dataModel.write(filename); m_dataModel.write(protoOutFile);
}
catch (std::exception &e)
{
QString errorMessage = QString("Error saving \"") + filename + "\": " + e.what();
QMessageBox::critical(this, "Error", errorMessage);
return;
}
qDebug() << "Wrote" << filename; qDebug() << "Wrote" << filename;
@ -232,17 +210,14 @@ void MainWindow::saveFile(const QString &filename)
void MainWindow::savePdf(const QString &filename) void MainWindow::savePdf(const QString &filename)
{ {
QPrinter printer; QPrinter printer;
printer.setResolution(1200);
printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFormat(QPrinter::PdfFormat);
printer.setPaperSize(QPrinter::A4); printer.setPaperSize(QPrinter::A4);
printer.setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);
printer.setOutputFileName(filename); printer.setOutputFileName(filename);
m_dataModel.printTo(printer); QTextDocument printDoc;
} QTextCursor printCursor(&printDoc);
m_dataModel.printTo(printCursor);
void MainWindow::aboutDialog() printDoc.print(&printer);
{
QString infoString =
QString::fromUtf8(ESGRAF48_DESCRIPTION) + " Version " + QString::fromUtf8(ESGRAF48_VERSION);
QMessageBox::information(this, ESGRAF48_DESCRIPTION, infoString);
} }

View File

@ -4,8 +4,6 @@
#include <QMainWindow> #include <QMainWindow>
#include <QString> #include <QString>
#include <QFont>
class DataModel; class DataModel;
class QDataWidgetMapper; class QDataWidgetMapper;
@ -39,7 +37,6 @@ public slots:
void print() const; void print() const;
void dataModelChanged(); void dataModelChanged();
void savePdf(); void savePdf();
void aboutDialog();
protected: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;

View File

@ -137,14 +137,7 @@
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionQuit"/> <addaction name="actionQuit"/>
</widget> </widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionAbout"/>
</widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menuHelp"/>
</widget> </widget>
<widget class="QToolBar" name="toolBar"> <widget class="QToolBar" name="toolBar">
<property name="windowTitle"> <property name="windowTitle">
@ -244,11 +237,6 @@
<string>Export as PDF file</string> <string>Export as PDF file</string>
</property> </property>
</action> </action>
<action name="actionAbout">
<property name="text">
<string>About</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -1,4 +0,0 @@
#pragma once
#define ESGRAF48_VERSION "@PROJECT_VERSION@"
#define ESGRAF48_DESCRIPTION "@PROJECT_DESCRIPTION@"