Compare commits

...

41 Commits
main ... devel

Author SHA1 Message Date
Valentino Orlandi e7ada82d28
Fixed CTest directives
Fixed LogDocTester return value
2024-04-28 20:23:04 +02:00
Valentino Orlandi 5df9f2731a
Updated build scripts
Changed cmake build target from 'all' to 'LogDoctor'
2024-04-28 19:50:22 +02:00
Valentino Orlandi 4db09dcfc4
Updated CMake directives
Added targets to update and release translations
2024-04-28 19:37:28 +02:00
Valentino Orlandi cbf76a26a5
CMake improvements
Modernized cmake project structure
2024-04-28 16:09:40 +02:00
Valentino Orlandi 0789e7f4b5
Code improvements
Improved Fetcher.
Introduced namespace: QueryFactory.
2024-04-27 21:44:14 +02:00
Valentino Orlandi b6bac6d39a
Updated doc comments 2024-04-27 20:21:40 +02:00
Valentino Orlandi d319a25c2e
Fixed some compiler warnings 2024-04-27 20:05:13 +02:00
Valentino Orlandi d83bb2af85
CMake improvements
Splitted project sources into separate cmake files
2024-04-27 19:36:16 +02:00
Valentino Orlandi eba625e5b3
Structure improvements
Renamed HashOps to Hasher.
Improved Craplog files tree structure.
2024-04-27 18:04:01 +02:00
Valentino Orlandi 88e080fb4d
Code improvements
Improved Crapview and Fetcher
2024-04-27 17:15:56 +02:00
Valentino Orlandi d999d8501f
Structure improvements
Renamed DbQuery to Fetcher.
Changed crapview-related files tree structure.
2024-04-27 12:35:51 +02:00
Valentino Orlandi 1ea1b0d979
Code improvements
Improved Crapview and DbQuery
2024-04-27 11:28:05 +02:00
Valentino Orlandi 01ee5a81e5
Updated translation resources 2024-04-22 20:04:04 +02:00
Valentino Orlandi 1cb69b0a31
Updated translation files 2024-04-22 20:03:58 +02:00
Valentino Orlandi 9abeab6257
Updated default conf file 2024-04-22 20:02:31 +02:00
Valentino Orlandi bd8f40802a
Updated Crapview
Added new methods and data members
2024-04-22 20:02:14 +02:00
Valentino Orlandi 601862c2a0
Updated MainWindow
Added slots for the new configs
2024-04-22 20:01:11 +02:00
Valentino Orlandi 2da551b4c0
Updated ConfigsPage enum 2024-04-22 20:00:17 +02:00
Valentino Orlandi 997d1c8eb3
Updated resources
Added icons for the new configs page
2024-04-22 19:59:46 +02:00
Valentino Orlandi 225110473a
Updated UI
Added page in the Configs to tweak the Relational stats chart
2024-04-22 19:58:45 +02:00
Valentino Orlandi 4339d0366e
Updated MainWindow
Updated readConfigs and writeConfigs methods
2024-04-22 00:25:12 +02:00
Valentino Orlandi d2115ce3e0
Updated default conf file 2024-04-22 00:22:21 +02:00
Valentino Orlandi 4dbfc272be
Improved and updated Crapview
Improved and updated DbQuery.
Added new methods and data members.
2024-04-21 23:37:33 +02:00
Valentino Orlandi e59d5fcf27
Updated MainWindow
Added slots for the new configs
2024-04-21 23:33:51 +02:00
Valentino Orlandi 88f4c899b1
Updated ConfigsPage enum with new values 2024-04-21 23:31:55 +02:00
Valentino Orlandi be433248ef
Updated main stylesheet 2024-04-21 23:31:05 +02:00
Valentino Orlandi 969666f4b2
Updated resources
Added icons for the new configs pages
2024-04-21 23:30:24 +02:00
Valentino Orlandi ae6867d84b
Updated UI
Added pages to the Configs section for tweaking the stats charts
2024-04-21 23:27:09 +02:00
Valentino Orlandi fcfc52f1ba
Improvements and updates
Using ConfigsPage enum instead of plain int
2024-04-21 11:34:43 +02:00
Valentino Orlandi 0fc4281066
Added Crapconf lib 2024-04-21 11:33:16 +02:00
Valentino Orlandi b418eca43a
Code improvements 2024-04-20 23:54:44 +02:00
Valentino Orlandi abb2662b98
Fixed compiler warning
Fixed possibly uninitialized values warning
2024-04-20 20:35:59 +02:00
Valentino Orlandi 56c2ced6e5
Improved tests suite
Added tests for ArrayOps
2024-04-20 20:32:33 +02:00
Valentino Orlandi c2b0e89bd6
Added IsStdArray concept to ArrayOps 2024-04-20 20:28:39 +02:00
Valentino Orlandi 8b656049ce
Fixed typo in ArrayOps 2024-04-20 18:42:39 +02:00
Valentino Orlandi 969a5f58d0
Code improvements 2024-04-16 20:05:36 +02:00
Valentino Orlandi fa0ea678d1
Updated CMakeLists.txt
Improved Release build with IPO
2024-04-16 20:04:25 +02:00
Valentino Orlandi cc0dcadc75
Updated HOW_TO_COMPILE 2024-03-01 23:25:53 +01:00
Valentino Orlandi 5d2b4aa24e
Updated build scripts
Changed build type from MinSizeRel to Release
2024-03-01 23:24:36 +01:00
Valentino Orlandi 71ab2b999c
Fix
Fixed error message of unexistent directory when the logs path is empty
2024-03-01 21:37:41 +01:00
Valentino Orlandi f31abb364b
Improved tests suite
Enhanced tests printed output.
Created own assertions so that tests can be also executed when compiling
in release mode.
2024-02-18 15:39:50 +01:00
149 changed files with 7530 additions and 3931 deletions

View File

@ -5,7 +5,7 @@
### Requirements / Dependencies
- C++ 20
- Qt6 *(Framework 6.2+, Linguist, Widgets, Charts, Sql, Network)*
- Qt6 *(Framework 6.6+, Linguist, Widgets, Charts, Sql, Network)*
- CMake
- gcc / clang / msvc<br/><br/>
@ -16,7 +16,7 @@
- Prepare a build folder:
<br/>`mkdir build && cd build`<br/><br/>
- Prepare **CMake**'s build files:
<br/>`cmake ../logdoctor -DCMAKE_BUILD_TYPE=MinSizeRel`<br/><br/>
<br/>`cmake ../logdoctor -DCMAKE_BUILD_TYPE=Release`<br/><br/>
- Use **CMake** to compile the entire project:
<br/>`cmake --build ./ --target all`<br/><br/>

View File

@ -67,3 +67,8 @@ IisBlacklistClientUsed=true
[Crapview]
CrapviewDialogsLevel=1
CrapviewSpeedTimeInterval=1
CrapviewSpeedTimeFormat=hh:mm
CrapviewCountPieSize=0.6
CrapviewCountMaxSlices=15
CrapviewRelationalTimeFormat=hh:mm

View File

@ -2,334 +2,34 @@ cmake_minimum_required(VERSION 3.5)
project(LogDoctor VERSION 4.00 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include(cmake/project.cmake)
logdoc_set_cmake_options()
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
include(cmake/dependencies.cmake)
logdoc_find_required_packages()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
qt_add_executable(LogDoctor MANUAL_FINALIZATION)
if(MSVC)
add_compile_options(/W2)
set(CMAKE_CXX_FLAGS_MINSIZEREL "/Os")
set(CMAKE_CXX_FLAGS_RELEASE "/O2")
else()
add_compile_options(-Wall -Wextra -Wpedantic)
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
endif()
include(cmake/sources.cmake)
logdoc_add_target_sources()
find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core Widgets Charts LinguistTools Sql Network)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets Charts LinguistTools Sql Network)
include(cmake/build.cmake)
logdoc_set_compiler_options()
logdoc_set_linker_options()
logdoc_set_target_properties()
if(${QT_VERSION_MAJOR} LESS 6)
message("Error: Qt6 or greater required")
return()
endif()
set(TS_FILES
translations/LogDoctor_en_GB.ts
translations/LogDoctor_es_ES.ts
translations/LogDoctor_fr_FR.ts
translations/LogDoctor_it_IT.ts
translations/LogDoctor_ja_JP.ts
translations/LogDoctor_pt_BR.ts
)
set(PROJECT_SOURCES
main.cpp
mainwindow.ui
mainwindow.h
mainwindow.cpp
main_lib.h
globals/db_names.h
globals/db_names.cpp
globals/global_configs.h
globals/global_configs.cpp
customs/logfile_treewidgetitem.h
customs/models/logfields_listmodel.h
customs/models/logfields_listmodel.cpp
utilities/arrays.h
utilities/bwlists.h
utilities/bwutils.cpp
utilities/chars.h
utilities/checks.h
utilities/checks.cpp
utilities/colors.h
utilities/colors.cpp
utilities/gzip.h
utilities/gzip.cpp
utilities/io.h
utilities/io.cpp
utilities/memory.h
utilities/memory.cpp
utilities/printables.h
utilities/printables.cpp
utilities/rtf.h
utilities/rtf.cpp
utilities/strings.h
utilities/strings.cpp
utilities/stylesheets.h
utilities/stylesheets.cpp
utilities/vectors.h
modules/shared.h
modules/exceptions.h
modules/exceptions.cpp
modules/tb.h
modules/tb.cpp
modules/database/database.h
modules/database/database.cpp
modules/dialogs.h
modules/dialogs.cpp
modules/dialogs/message_dialog.ui
modules/dialogs/message_dialog.h
modules/dialogs/message_dialog.cpp
modules/dialogs/boolean_dialog.ui
modules/dialogs/boolean_dialog.h
modules/dialogs/boolean_dialog.cpp
modules/dialogs/ida_dialog.ui
modules/dialogs/ida_dialog.h
modules/dialogs/ida_dialog.cpp
modules/blacklists/blacklists.h
modules/blacklists/blacklists.cpp
modules/blacklists/modules/lib.h
modules/blacklists/modules/blacklist.h
modules/blacklists/modules/blacklist.cpp
modules/blacklists/modules/blacklist_item.h
modules/blacklists/modules/blacklist_item.cpp
modules/warnlists/warnlists.h
modules/warnlists/warnlists.cpp
modules/warnlists/modules/lib.h
modules/warnlists/modules/warnlist.h
modules/warnlists/modules/warnlist.cpp
modules/warnlists/modules/warnlist_item.h
modules/warnlists/modules/warnlist_item.cpp
modules/craplog/lib.h
modules/craplog/craplog.h
modules/craplog/craplog.cpp
modules/craplog/modules/lib.h
modules/craplog/modules/datetime.h
modules/craplog/modules/datetime.cpp
modules/craplog/modules/donuts.h
modules/craplog/modules/donuts.cpp
modules/craplog/modules/formats.h
modules/craplog/modules/formats.cpp
modules/craplog/modules/hash.h
modules/craplog/modules/hash.cpp
modules/craplog/modules/logs.h
modules/craplog/modules/logs.cpp
modules/craplog/modules/sha256.h
modules/craplog/modules/sha256.cpp
modules/craplog/modules/workers/lib.h
modules/craplog/modules/workers/lister.h
modules/craplog/modules/workers/lister.cpp
modules/craplog/modules/workers/parser.h
modules/craplog/modules/workers/parser.cpp
modules/craplog/modules/workers/impl/loglinedata.cpp
modules/crapview/lib.h
modules/crapview/crapview.h
modules/crapview/crapview.cpp
modules/crapview/modules/lib.h
modules/crapview/modules/filters.h
modules/crapview/modules/filters.cpp
modules/crapview/modules/query.h
modules/crapview/modules/query.cpp
modules/craphelp/craphelp.ui
modules/craphelp/craphelp.h
modules/craphelp/craphelp.cpp
modules/crapup/crapup.ui
modules/crapup/crapup.h
modules/crapup/crapup.cpp
modules/crapup/modules/stylesheets.h
modules/crapup/modules/stylesheets.cpp
modules/crapinfo/crapinfo.ui
modules/crapinfo/crapinfo.h
modules/crapinfo/crapinfo.cpp
modules/crapinfo/modules/stylesheets.h
modules/crapinfo/modules/stylesheets.cpp
modules/changelog/changelog.ui
modules/changelog/changelog.h
modules/changelog/changelog.cpp
modules/changelog/modules/stylesheets.h
modules/changelog/modules/stylesheets.cpp
tools/crappath/crappath.h
tools/crappath/crappath.cpp
tools/crapnote/crapnote.ui
tools/crapnote/crapnote.h
tools/crapnote/crapnote.cpp
tools/crapnote/modules/stylesheets.h
tools/crapnote/modules/stylesheets.cpp
games/game_dialog.ui
games/game_dialog.h
games/game_dialog.cpp
games/crisscross/crisscross.ui
games/crisscross/game.h
games/crisscross/game.cpp
games/crisscross/modules/stylesheets.h
games/crisscross/modules/stylesheets.cpp
games/snake/snake.ui
games/snake/game.h
games/snake/game.cpp
games/snake/snake.h
games/snake/snake.cpp
games/snake/food.h
games/snake/food.cpp
games/snake/modules/stylesheets.h
games/snake/modules/stylesheets.cpp
resources/resources.qrc
${TS_FILES}
)
qt_add_executable(LogDoctor
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Bstatic -lstdc++ -lwinpthread")
target_link_libraries(LogDoctor PRIVATE
-static Qt${QT_VERSION_MAJOR}::Core
-static Qt${QT_VERSION_MAJOR}::Widgets
-static Qt${QT_VERSION_MAJOR}::Charts
-static Qt${QT_VERSION_MAJOR}::Sql
-static Qt${QT_VERSION_MAJOR}::Network
)
else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
target_link_libraries(LogDoctor PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Charts
Qt${QT_VERSION_MAJOR}::Sql
Qt${QT_VERSION_MAJOR}::Network
)
# Include zlib
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries(LogDoctor PRIVATE ${ZLIB_LIBRARIES})
endif()
if(WIN32)
set_target_properties(LogDoctor PROPERTIES
WIN32_EXECUTABLE TRUE
)
elseif(APPLE)
set_target_properties(LogDoctor PROPERTIES
MACOSX_BUNDLE TRUE
#MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}
MACOSX_BUNDLE_ICON_FILE ${PROJECT_NAME}
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
)
endif()
include(cmake/translations.cmake)
logdoc_add_lupdate_target()
#logdoc_add_lrelease_target()
qt_finalize_executable(LogDoctor)
# CTest
include(CTest)
enable_testing()
add_executable(LogDocTester
tests/main.cpp
tests/white_box.h
tests/white_box.cpp
# 2 test
modules/exceptions.h
modules/exceptions.cpp
modules/craplog/modules/lib.h
modules/craplog/modules/workers/lib.h
modules/craplog/modules/workers/impl/loglinedata.cpp
utilities/gzip.h
utilities/gzip.cpp
utilities/io.h
utilities/io.cpp
utilities/strings.h
utilities/strings.cpp
utilities/vectors.h
modules/craplog/modules/datetime.h
modules/craplog/modules/datetime.cpp
modules/craplog/modules/formats.h
modules/craplog/modules/formats.cpp
modules/craplog/modules/logs.h
modules/craplog/modules/logs.cpp
modules/crapview/modules/filters.h
modules/crapview/modules/filters.cpp
)
if(WIN32)
target_link_libraries(LogDocTester PRIVATE
-static Qt${QT_VERSION_MAJOR}::Widgets
#-static Qt${QT_VERSION_MAJOR}::Sql
)
else()
target_link_libraries(LogDocTester PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
#Qt${QT_VERSION_MAJOR}::Sql
${ZLIB_LIBRARIES}
)
endif()
add_test(
NAME LogDocTester
COMMAND $<TARGET_FILE:LogDocTester>
)
# Test
include(cmake/tests.cmake)
logdoc_add_tests()
# Deb/Flatpak
if(UNIX AND NOT APPLE)
install(TARGETS
LogDoctor
RUNTIME DESTINATION /usr/bin
CONFIGURATIONS Release
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ
RENAME logdoctor
)
install(FILES
${CMAKE_SOURCE_DIR}/installation_stuff/LogDoctor.desktop
DESTINATION /usr/share/applications
)
install(DIRECTORY
DESTINATION /usr/share/LogDoctor
)
install(FILES
${CMAKE_SOURCE_DIR}/installation_stuff/LogDoctor.svg
DESTINATION /usr/share/LogDoctor
)
install(DIRECTORY
${CMAKE_SOURCE_DIR}/installation_stuff/logdocdata/help
DESTINATION /usr/share/LogDoctor
)
install(DIRECTORY
${CMAKE_SOURCE_DIR}/installation_stuff/logdocdata/licenses
DESTINATION /usr/share/LogDoctor
)
endif()
# Install
include(cmake/install.cmake)
logdoc_add_install_directives()

View File

@ -0,0 +1,68 @@
macro(logdoc_set_compiler_options)
if(MSVC)
add_compile_options(/W2)
set(CMAKE_CXX_FLAGS_MINSIZEREL "/Os")
set(CMAKE_CXX_FLAGS_RELEASE "/O2")
else()
add_compile_options(-Wall -Wextra -Wpedantic)
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
endif()
if(CMAKE_BUILD_TYPE EQUAL "RELEASE")
include(CheckIPOSupported)
check_ipo_supported(RESULT supported)
if(supported)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
endif()
endmacro()
macro(logdoc_set_linker_options)
if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Bstatic -lstdc++ -lwinpthread")
target_link_libraries(LogDoctor PRIVATE
-static Qt${QT_VERSION_MAJOR}::Core
-static Qt${QT_VERSION_MAJOR}::Widgets
-static Qt${QT_VERSION_MAJOR}::Charts
-static Qt${QT_VERSION_MAJOR}::Sql
-static Qt${QT_VERSION_MAJOR}::Network
)
else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
target_link_libraries(LogDoctor PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Charts
Qt${QT_VERSION_MAJOR}::Sql
Qt${QT_VERSION_MAJOR}::Network
${ZLIB_LIBRARIES}
)
endif()
endmacro()
macro(logdoc_set_target_properties)
if(WIN32)
set_target_properties(LogDoctor PROPERTIES
WIN32_EXECUTABLE TRUE
)
elseif(APPLE)
set_target_properties(LogDoctor PROPERTIES
MACOSX_BUNDLE TRUE
#MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}
MACOSX_BUNDLE_ICON_FILE ${PROJECT_NAME}
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
)
endif()
endmacro()

View File

@ -0,0 +1,13 @@
macro(logdoc_find_required_packages)
find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core Widgets Charts LinguistTools Sql Network)
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Charts LinguistTools Sql Network)
# zlib
if(NOT WIN32)
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIRS})
endif()
endmacro()

View File

@ -0,0 +1,45 @@
function(logdoc_add_install_directives)
set(INSTALLATION_STUFF_DIR ${CMAKE_SOURCE_DIR}/../installation_stuff)
# Linux/Flatpak
if(UNIX AND NOT APPLE)
install(TARGETS
LogDoctor
RUNTIME DESTINATION /usr/bin
CONFIGURATIONS Release
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ
RENAME logdoctor
)
if(BSD)
install(FILES
${INSTALLATION_STUFF_DIR}/LogDoctor.desktop
DESTINATION /usr/local/share/applications
)
else()
install(FILES
${INSTALLATION_STUFF_DIR}/LogDoctor.desktop
DESTINATION /usr/share/applications
)
endif()
install(DIRECTORY
DESTINATION /usr/share/LogDoctor
)
install(FILES
${INSTALLATION_STUFF_DIR}/LogDoctor.svg
DESTINATION /usr/share/LogDoctor
)
install(DIRECTORY
${INSTALLATION_STUFF_DIR}/logdocdata/help
DESTINATION /usr/share/LogDoctor
)
install(DIRECTORY
${INSTALLATION_STUFF_DIR}/logdocdata/licenses
DESTINATION /usr/share/LogDoctor
)
endif()
endfunction()

View File

@ -0,0 +1,13 @@
macro(logdoc_set_cmake_options)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endmacro()

View File

@ -0,0 +1,21 @@
function(logdoc_add_target_sources)
target_sources(LogDoctor PRIVATE
main.cpp
mainwindow.ui
mainwindow.h
mainwindow.cpp
main_lib.h
)
add_subdirectory(customs)
add_subdirectory(games)
add_subdirectory(globals)
add_subdirectory(modules)
add_subdirectory(tools)
add_subdirectory(utilities)
add_subdirectory(resources)
endfunction()

View File

@ -0,0 +1,58 @@
macro(logdoc_add_tests)
include(CTest)
enable_testing()
add_executable(LogDocTester
tests/main.cpp
# suites
tests/lib.h
tests/white_box.h
tests/white_box.cpp
# to test
modules/exceptions.h
modules/exceptions.cpp
modules/craplog/modules/lib.h
modules/craplog/modules/formats.h
modules/craplog/modules/formats.cpp
modules/craplog/utilities/datetime.h
modules/craplog/utilities/datetime.cpp
modules/craplog/utilities/logs.h
modules/craplog/utilities/logs.cpp
modules/crapview/utilities/filters.h
modules/crapview/utilities/filters.cpp
modules/craplog/workers/lib.h
modules/craplog/workers/parser/logs_data.h
modules/craplog/workers/parser/logs_data.cpp
utilities/gzip.h
utilities/gzip.cpp
utilities/io.h
utilities/io.cpp
utilities/strings.h
utilities/strings.cpp
utilities/vectors.h
)
if(WIN32)
target_link_libraries(LogDocTester PRIVATE
-static Qt${QT_VERSION_MAJOR}::Widgets
#-static Qt${QT_VERSION_MAJOR}::Sql
)
else()
target_link_libraries(LogDocTester PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
#Qt${QT_VERSION_MAJOR}::Sql
${ZLIB_LIBRARIES}
)
endif()
add_test(
NAME LogDocTester
COMMAND $<TARGET_FILE:LogDocTester>
)
endmacro()

View File

@ -0,0 +1,47 @@
set(TS_FILES
translations/LogDoctor_en_GB.ts
translations/LogDoctor_es_ES.ts
translations/LogDoctor_fr_FR.ts
translations/LogDoctor_it_IT.ts
translations/LogDoctor_ja_JP.ts
translations/LogDoctor_pt_BR.ts
)
macro(logdoc_add_lupdate_target)
if(${QT_VERSION_MINOR} LESS 7)
qt_add_lupdate(LogDoctor
TS_FILES ${TS_FILES}
INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}
OPTIONS "-no-obsolete"
)
else()
qt_add_lupdate(
SOURCE_TARGETS LogDoctor
TS_FILES ${TS_FILES}
INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}
OPTIONS "-no-obsolete"
)
endif()
endmacro()
macro(logdoc_add_lrelease_target)
if(${QT_VERSION_MINOR} LESS 7)
qt_add_lrelease(LogDoctor
TS_FILES ${TS_FILES}
QM_FILES_OUTPUT_VARIABLE QM_FILES
)
else()
qt_add_lrelease(
TS_FILES ${TS_FILES}
QM_FILES_OUTPUT_VARIABLE QM_FILES
)
endif()
#install(FILES ${QM_FILES} DESTINATION resources/translations)
endmacro()

View File

@ -0,0 +1,6 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/logfile_treewidgetitem.h
)
add_subdirectory(models)

View File

@ -0,0 +1,5 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/logfields_listmodel.h
${CMAKE_CURRENT_SOURCE_DIR}/logfields_listmodel.cpp
)

View File

@ -0,0 +1,9 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/game_dialog.ui
${CMAKE_CURRENT_SOURCE_DIR}/game_dialog.h
${CMAKE_CURRENT_SOURCE_DIR}/game_dialog.cpp
)
add_subdirectory(crisscross)
add_subdirectory(snake)

View File

@ -0,0 +1,8 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/crisscross.ui
${CMAKE_CURRENT_SOURCE_DIR}/game.h
${CMAKE_CURRENT_SOURCE_DIR}/game.cpp
)
add_subdirectory(modules)

View File

@ -0,0 +1,5 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.h
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.cpp
)

View File

@ -0,0 +1,12 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/snake.ui
${CMAKE_CURRENT_SOURCE_DIR}/game.h
${CMAKE_CURRENT_SOURCE_DIR}/game.cpp
${CMAKE_CURRENT_SOURCE_DIR}/snake.h
${CMAKE_CURRENT_SOURCE_DIR}/snake.cpp
${CMAKE_CURRENT_SOURCE_DIR}/food.h
${CMAKE_CURRENT_SOURCE_DIR}/food.cpp
)
add_subdirectory(modules)

View File

@ -0,0 +1,5 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.h
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.cpp
)

View File

@ -0,0 +1,7 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/db_names.h
${CMAKE_CURRENT_SOURCE_DIR}/db_names.cpp
${CMAKE_CURRENT_SOURCE_DIR}/global_configs.h
${CMAKE_CURRENT_SOURCE_DIR}/global_configs.cpp
)

View File

@ -31,7 +31,9 @@
#include "modules/craplog/lib.h"
#include "modules/crapview/lib.h"
#include "modules/crapview/modules/filters.h"
#include "modules/crapview/utilities/filters.h"
#include "modules/crapconf/lib.h"
#include "tools/crappath/crappath.h"
#include "tools/crapnote/crapnote.h"
@ -221,6 +223,11 @@ MainWindow::MainWindow(QWidget *parent)
// charts
this->ui->box_ConfCharts_Theme->setCurrentIndex( static_cast<int>(GlobalConfigs::charts_theme) );
this->refreshChartsPreview();
this->ui->box_ConfCharts_Speed_TimeInterval->setCurrentText( QString::number(this->crapview.getSpeedTimeInterval()) );
this->ui->box_ConfCharts_Speed_TimeFormat->setCurrentText( this->crapview.getSpeedTimeFormat() );
this->ui->doubleSpinBox_ConfCharts_Count_PieSize->setValue( this->crapview.getCountPieSize() );
this->ui->spinBox_ConfCharts_Count_MaxSlices->setValue( this->crapview.getCountMaxSlices() );
this->ui->box_ConfCharts_Relat_TimeFormat->setCurrentText( this->crapview.getRelatTimeFormat() );
// databases
this->ui->inLine_ConfDatabases_Data_Path->setText( QString::fromStdString( this->db_data_path ) );
this->ui->button_ConfDatabases_Data_Save->setEnabled( false );
@ -847,6 +854,56 @@ void MainWindow::readConfigs()
invalid_lines.append( QString::fromStdString( line ) );
}
} else if ( var == "CrapviewSpeedTimeInterval" ) {
try {
const qint64 value{ std::stoll( val ) };
if ( const int index{this->ui->box_ConfCharts_Speed_TimeInterval->findText( QString::fromStdString( val ) )}; index >= 0 ) {
this->crapview.setSpeedTimeInterval( value );
} else {
invalid_lines.append( QString::fromStdString( line ) );
}
} catch ( ... ) { // std::exception
invalid_lines.append( QString::fromStdString( line ) );
}
} else if ( var == "CrapviewSpeedTimeFormat" ) {
if ( val == "hh:mm" || val == "hh" ) {
this->crapview.setSpeedTimeFormat( QString::fromStdString( val ) );
} else {
invalid_lines.append( QString::fromStdString( line ) );
}
} else if ( var == "CrapviewCountPieSize" ) {
try {
const qreal value{ std::stod( val ) };
if ( value >= 0.6 && value <= 0.8 ) {
this->crapview.setCountPieSize( value );
} else {
invalid_lines.append( QString::fromStdString( line ) );
}
} catch ( ... ) { // std::exception
invalid_lines.append( QString::fromStdString( line ) );
}
} else if ( var == "CrapviewCountMaxSlices" ) {
try {
const int value{ std::stoi( val ) };
if ( value >= 1 && value <= 31 ) {
this->crapview.setCountMaxSlices( value );
} else {
invalid_lines.append( QString::fromStdString( line ) );
}
} catch ( ... ) { // std::exception
invalid_lines.append( QString::fromStdString( line ) );
}
} else if ( var == "CrapviewRelationalTimeFormat" ) {
if ( val == "hh:mm" || val == "hh" ) {
this->crapview.setRelatTimeFormat( QString::fromStdString( val ) );
} else {
invalid_lines.append( QString::fromStdString( line ) );
}
}/* else {
// not valid
}*/
@ -1063,6 +1120,11 @@ void MainWindow::writeConfigs()
//// CRAPVIEW ////
configs += "\n\n[Crapview]";
configs += "\nCrapviewDialogsLevel=" + toString( this->crapview.getDialogsLevel() );
configs += "\nCrapviewSpeedTimeInterval=" + std::to_string( this->crapview.getSpeedTimeInterval() );
configs += "\nCrapviewSpeedTimeFormat=" + this->crapview.getSpeedTimeFormat().toStdString();
configs += "\nCrapviewCountPieSize=" + std::to_string( this->crapview.getCountPieSize() );
configs += "\nCrapviewCountMaxSlices=" + std::to_string( this->crapview.getCountMaxSlices() );
configs += "\nCrapviewRelationalTimeFormat=" + this->crapview.getRelatTimeFormat().toStdString();
// write on file
try {
@ -1439,6 +1501,14 @@ void MainWindow::updateUiIcons()
icon_name += "conf_dialogs";
} else if ( text == tr("Charts") ) {
icon_name += "conf_charts";
} else if ( text == tr("Appearance") ) {
icon_name += "conf_charts_style";
} else if ( text == tr("Speed") ) {
icon_name += "conf_speed";
} else if ( text == tr("Count") ) {
icon_name += "conf_count";
} else if ( text == tr("Relational") ) {
icon_name += "conf_relational";
} else if ( text == tr("TextBrowser") ) {
icon_name += "conf_textbrowser";
} else if ( text == tr("Databases") ) {
@ -1559,9 +1629,10 @@ void MainWindow::updateUiFonts()
const QFont& small_font{ this->fonts.at( "main_small" ) };
const QFont& font{ this->fonts.at( "main" ) };
const QFont& big_font{ this->fonts.at( "main_big" ) };
QFont menu_font{ this->fonts.at( "main_small" ) };
const QFont& tb_font{ this->TB.getFont() };
QFont menu_font{ small_font };
menu_font.setPointSizeF( this->font_size_small+1.5 );
QFont header_font{ this->fonts.at( "main_small" ) };
QFont header_font{ small_font };
header_font.setPointSizeF( this->font_size_small+2 );
// menu
this->ui->menuLanguage->setFont( menu_font );
@ -1588,7 +1659,7 @@ void MainWindow::updateUiFonts()
this->ui->listLogFiles->setFont( font );
this->ui->listLogFiles->headerItem()->setFont( 0, header_font );
this->ui->listLogFiles->headerItem()->setFont( 1, header_font );
this->ui->textLogFiles->setFont( this->TB.getFont() );
this->ui->textLogFiles->setFont( tb_font );
// log files parse
this->ui->label_MakeStats_Size->setFont( font );
this->ui->label_MakeStats_Lines->setFont( font );
@ -1750,11 +1821,21 @@ void MainWindow::updateUiFonts()
this->ui->label_ConfTextBrowser_ColorScheme->setFont( big_font );
this->ui->box_ConfTextBrowser_ColorScheme->setFont( font );
this->ui->label_ConfTextBrowser_Preview->setFont( big_font );
this->ui->textBrowser_ConfTextBrowser_Preview->setFont( this->TB.getFont() );
this->ui->textBrowser_ConfTextBrowser_Preview->setFont( tb_font );
// conf charts
this->ui->label_ConfCharts_Theme->setFont( big_font );
this->ui->box_ConfCharts_Theme->setFont( font );
this->ui->label_ConfCharts_Preview->setFont( big_font );
this->ui->label_ConfCharts_Speed_TimeInterval->setFont( big_font );
this->ui->box_ConfCharts_Speed_TimeInterval->setFont( font );
this->ui->label_ConfCharts_Speed_TimeFormat->setFont( big_font );
this->ui->box_ConfCharts_Speed_TimeFormat->setFont( font );
this->ui->label_ConfCharts_Count_PieSize->setFont( big_font );
this->ui->doubleSpinBox_ConfCharts_Count_PieSize->setFont( font );
this->ui->label_ConfCharts_Count_MaxSlices->setFont( big_font );
this->ui->spinBox_ConfCharts_Count_MaxSlices->setFont( font );
this->ui->label_ConfCharts_Relat_TimeFormat->setFont( big_font );
this->ui->box_ConfCharts_Relat_TimeFormat->setFont( font );
// conf databases
this->ui->label_ConfDatabases_Paths->setFont( big_font );
this->ui->label_ConfDatabases_Data->setFont( font );
@ -1781,7 +1862,7 @@ void MainWindow::updateUiFonts()
this->ui->label_ConfApache_Format_String->setFont( font );
this->ui->inLine_ConfApache_Format_String->setFont( font );
this->ui->button_ConfApache_Format_Sample->setFont( font );
this->ui->preview_ConfApache_Format_Sample->setFont( this->TB.getFont() );
this->ui->preview_ConfApache_Format_Sample->setFont( tb_font );
this->ui->box_ConfApache_Warnlist_Field->setFont( font );
this->ui->checkBox_ConfApache_Warnlist_Used->setFont( font );
this->ui->inLine_ConfApache_Warnlist_String->setFont( font );
@ -1796,7 +1877,7 @@ void MainWindow::updateUiFonts()
this->ui->label_ConfNginx_Format_String->setFont( font );
this->ui->inLine_ConfNginx_Format_String->setFont( font );
this->ui->button_ConfNginx_Format_Sample->setFont( font );
this->ui->preview_ConfNginx_Format_Sample->setFont( this->TB.getFont() );
this->ui->preview_ConfNginx_Format_Sample->setFont( tb_font );
this->ui->box_ConfNginx_Warnlist_Field->setFont( font );
this->ui->checkBox_ConfNginx_Warnlist_Used->setFont( font );
this->ui->inLine_ConfNginx_Warnlist_String->setFont( font );
@ -1811,7 +1892,7 @@ void MainWindow::updateUiFonts()
this->ui->label_ConfIis_Format_String->setFont( font );
this->ui->inLine_ConfIis_Format_String->setFont( font );
this->ui->button_ConfIis_Format_Sample->setFont( font );
this->ui->preview_ConfIis_Format_Sample->setFont( this->TB.getFont() );
this->ui->preview_ConfIis_Format_Sample->setFont( tb_font );
this->ui->box_ConfIis_Warnlist_Field->setFont( font );
this->ui->checkBox_ConfIis_Warnlist_Used->setFont( font );
this->ui->inLine_ConfIis_Warnlist_String->setFont( font );
@ -2024,7 +2105,7 @@ void MainWindow::makeInitialChecks()
ok &= false;
} else {
this->craplog.setHashesDatabasePath( this->db_hashes_path );
this->craplog.hashOps.loadUsedHashesLists( this->db_hashes_path + "/" + DatabasesNames::hashes );
this->craplog.hasher.loadUsedHashesLists( this->db_hashes_path + "/" + DatabasesNames::hashes );
}
}
}
@ -2788,10 +2869,10 @@ void MainWindow::refreshFinished()
// refresh finished, back to normal state
if ( this->craplog.getLogsListSize() > 0ul ) {
this->ui->checkBox_LogFiles_CheckAll->setEnabled( true );
this->ui->button_LogFiles_RefreshList->setEnabled( true );
this->ui->button_LogFiles_ViewFile->setEnabled( true );
this->ui->listLogFiles->setEnabled( true );
}
this->ui->button_LogFiles_RefreshList->setEnabled( true );
this->ui->button_LogFiles_ViewFile->setEnabled( true );
this->ui->button_LogFiles_Apache->setEnabled( true );
this->ui->button_LogFiles_Nginx->setEnabled( true );
this->ui->button_LogFiles_Iis->setEnabled( true );
@ -3241,7 +3322,8 @@ void MainWindow::drawStatsWarn()
{
const int wsIndex{ this->ui->box_StatsWarn_WebServer->currentIndex() };
this->ui->table_StatsWarn->horizontalHeader()->setSortIndicator( -1, Qt::SortOrder::AscendingOrder );
this->ui->table_StatsWarn->setRowCount(0);
this->ui->table_StatsWarn->setRowCount( 0 );
this->ui->chart_StatsWarn->setChart( new QChart() );
this->crapview.drawWarn(
this->ui->table_StatsWarn, this->ui->chart_StatsWarn,
this->CHARTS_THEMES.at( static_cast<size_t>(GlobalConfigs::charts_theme) ),
@ -3425,7 +3507,8 @@ void MainWindow::on_button_StatsSpeed_Draw_clicked()
void MainWindow::drawStatsSpeed()
{
this->ui->table_StatsSpeed->horizontalHeader()->setSortIndicator( -1, Qt::SortOrder::AscendingOrder );
this->ui->table_StatsSpeed->setRowCount(0);
this->ui->table_StatsSpeed->setRowCount( 0 );
this->ui->chart_StatsSpeed->setChart( new QChart() );
this->crapview.drawSpeed(
this->ui->table_StatsSpeed,
this->ui->chart_StatsSpeed,
@ -3669,7 +3752,8 @@ void MainWindow::on_button_StatsCount_Client_clicked()
void MainWindow::drawStatsCount()
{
this->ui->table_StatsCount->horizontalHeader()->setSortIndicator( -1, Qt::SortOrder::AscendingOrder );
this->ui->table_StatsCount->setRowCount(0);
this->ui->table_StatsCount->setRowCount( 0 );
this->ui->chart_StatsCount->setChart( new QChart() );
this->crapview.drawCount(
this->ui->table_StatsCount, this->ui->chart_StatsCount,
this->CHARTS_THEMES.at( static_cast<size_t>(GlobalConfigs::charts_theme) ),
@ -3955,6 +4039,7 @@ void MainWindow::on_button_StatsDay_Draw_clicked()
void MainWindow::drawStatsDay()
{
const bool period{ this->ui->checkBox_StatsDay_Period->isChecked() };
this->ui->chart_StatsDay->setChart( new QChart() );
this->crapview.drawDay(
this->ui->chart_StatsDay,
this->CHARTS_THEMES.at( static_cast<size_t>(GlobalConfigs::charts_theme) ),
@ -4248,6 +4333,7 @@ void MainWindow::on_button_StatsRelat_Draw_clicked()
}
void MainWindow::drawStatsRelat()
{
this->ui->chart_StatsRelat->setChart( new QChart() );
this->crapview.drawRelat(
this->ui->chart_StatsRelat,
this->CHARTS_THEMES.at( static_cast<size_t>(GlobalConfigs::charts_theme) ),
@ -4429,58 +4515,66 @@ void MainWindow::on_tree_ConfSections_itemClicked(QTreeWidgetItem *item, int col
if ( section == tr("General") ) {
return;
} else if ( section == tr("Window") ) {
this->ui->stackedPages_Conf->setCurrentIndex(0);
this->setConfigsPage( General_Window );
} else if ( section == tr("Dialogs") ) {
this->ui->stackedPages_Conf->setCurrentIndex(1);
this->setConfigsPage( General_Dialogs );
} else if ( section == tr("Charts") ) {
this->ui->stackedPages_Conf->setCurrentIndex(2);
return;
} else if ( section == tr("Appearance") ) {
this->setConfigsPage( General_Charts_Appearance );
} else if ( section == tr("Speed") ) {
this->setConfigsPage( General_Charts_Speed );
} else if ( section == tr("Count") ) {
this->setConfigsPage( General_Charts_Count );
} else if ( section == tr("Relational") ) {
this->setConfigsPage( General_Charts_Relational );
} else if ( section == tr("TextBrowser") ) {
this->ui->stackedPages_Conf->setCurrentIndex(3);
this->setConfigsPage( General_TextBrowser );
} else if ( section == tr("Databases") ) {
this->ui->stackedPages_Conf->setCurrentIndex(4);
this->setConfigsPage( General_Databases );
} else if ( section == tr("Logs") ) {
return;
} else if ( section == tr("Defaults") ) {
this->ui->stackedPages_Conf->setCurrentIndex(5);
this->setConfigsPage( Logs_Defaults );
} else if ( section == tr("Control") ) {
this->ui->stackedPages_Conf->setCurrentIndex(6);
this->setConfigsPage( Logs_Control );
} else if ( section == tr("Apache2") || section == tr("Nginx") || section == tr("IIS") ) {
return;
} else if ( section == tr("Path") ) {
const QString parent{ item->parent()->text(0) };
if ( parent == tr("Apache2") ) {
this->ui->stackedPages_Conf->setCurrentIndex(7);
this->setConfigsPage( Logs_Apache2_Path );
} else if ( parent == tr("Nginx") ) {
this->ui->stackedPages_Conf->setCurrentIndex(11);
this->setConfigsPage( Logs_Nginx_Path );
} else if ( parent == tr("IIS") ) {
this->ui->stackedPages_Conf->setCurrentIndex(15);
this->setConfigsPage( Logs_IIS_Path );
}
} else if ( section == tr("Format") ) {
const QString parent{ item->parent()->text(0) };
if ( parent == tr("Apache2") ) {
this->ui->stackedPages_Conf->setCurrentIndex(8);
this->setConfigsPage( Logs_Apache2_Format );
} else if ( parent == tr("Nginx") ) {
this->ui->stackedPages_Conf->setCurrentIndex(12);
this->setConfigsPage( Logs_Nginx_Format );
} else if ( parent == tr("IIS") ) {
this->ui->stackedPages_Conf->setCurrentIndex(16);
this->setConfigsPage( Logs_IIS_Format );
}
} else if ( section == tr("Warnlists") ) {
const QString parent{ item->parent()->text(0) };
if ( parent == tr("Apache2") ) {
this->ui->stackedPages_Conf->setCurrentIndex(9);
this->setConfigsPage( Logs_Apache2_Warnlists );
} else if ( parent == tr("Nginx") ) {
this->ui->stackedPages_Conf->setCurrentIndex(13);
this->setConfigsPage( Logs_Nginx_Warnlists );
} else if ( parent == tr("IIS") ) {
this->ui->stackedPages_Conf->setCurrentIndex(17);
this->setConfigsPage( Logs_IIS_Warnlists );
}
} else if ( section == tr("Blacklists") ) {
const QString parent{ item->parent()->text(0) };
if ( parent == tr("Apache2") ) {
this->ui->stackedPages_Conf->setCurrentIndex(10);
this->setConfigsPage( Logs_Apache2_Blacklists );
} else if ( parent == tr("Nginx") ) {
this->ui->stackedPages_Conf->setCurrentIndex(14);
this->setConfigsPage( Logs_Nginx_Blacklists );
} else if ( parent == tr("IIS") ) {
this->ui->stackedPages_Conf->setCurrentIndex(18);
this->setConfigsPage( Logs_IIS_Blacklists );
}
} else {
throw("Unexpected Conf section: "+section.toStdString());
@ -4492,6 +4586,11 @@ void MainWindow::on_tree_ConfSections_itemDoubleClicked(QTreeWidgetItem *item, i
this->on_tree_ConfSections_itemClicked( item, column );
}
void MainWindow::setConfigsPage( const ConfigsPage page )
{
this->ui->stackedPages_Conf->setCurrentIndex( page );
}
/////////////////
//// GENERAL ////
/////////////////
@ -4711,6 +4810,31 @@ void MainWindow::refreshChartsPreview()
this->ui->chart_ConfCharts_Preview );
}
void MainWindow::on_box_ConfCharts_Speed_TimeInterval_currentTextChanged(const QString& arg1)
{
this->crapview.setSpeedTimeInterval( arg1.toLong() );
}
void MainWindow::on_box_ConfCharts_Speed_TimeFormat_currentTextChanged(const QString& arg1)
{
this->crapview.setSpeedTimeFormat( arg1 );
}
void MainWindow::on_doubleSpinBox_ConfCharts_Count_PieSize_valueChanged(double arg1)
{
this->crapview.setCountPieSize( arg1 );
}
void MainWindow::on_spinBox_ConfCharts_Count_MaxSlices_valueChanged(int arg1)
{
this->crapview.setCountMaxSlices( arg1 );
}
void MainWindow::on_box_ConfCharts_Relat_TimeFormat_currentTextChanged(const QString& arg1)
{
this->crapview.setRelatTimeFormat( arg1 );
}
///////////////////
//// DATABASES ////

View File

@ -35,6 +35,8 @@ class QTreeWidgetItem;
enum class LogField;
enum class ColorsScheme : unsigned char;
enum ConfigsPage : unsigned char;
namespace Ui {
class MainWindow;
@ -65,6 +67,7 @@ private slots:
///////////////////
//// OVERRIDES ////
void closeEvent( QCloseEvent* event ) override;
@ -274,8 +277,8 @@ private slots:
void on_button_StatsGlob_Iis_clicked();
/////////////////
//// CRAPSET ////
//////////////////
//// CRAPCONF ////
void on_tree_ConfSections_itemClicked(QTreeWidgetItem *item, int column);
@ -309,6 +312,16 @@ private slots:
void on_box_ConfCharts_Theme_currentIndexChanged(int index);
void on_box_ConfCharts_Speed_TimeInterval_currentTextChanged(const QString& arg1);
void on_box_ConfCharts_Speed_TimeFormat_currentTextChanged(const QString& arg1);
void on_doubleSpinBox_ConfCharts_Count_PieSize_valueChanged(double arg1);
void on_spinBox_ConfCharts_Count_MaxSlices_valueChanged(int arg1);
void on_box_ConfCharts_Relat_TimeFormat_currentTextChanged(const QString& arg1);
//// DATABASES ////
void on_tool_ConfDatabases_Data_Dialog_clicked();
@ -896,9 +909,11 @@ private:
void resetStatsGlob();
/////////////////
//// CRAPSET ////
/////////////////
//////////////////
//// CRAPCONF ////
//////////////////
void setConfigsPage( const ConfigsPage page );
void refreshTextBrowserPreview();

View File

@ -2727,7 +2727,7 @@ Use '!', '=','&lt;' or '&gt;' to declare what to use</string>
<widget class="QWidget" name="scrollAreaContent_StatsCount">
<property name="geometry">
<rect>
<x>0</x>
<x>14</x>
<y>0</y>
<width>263</width>
<height>402</height>
@ -6008,6 +6008,26 @@ With numbers, use '!', '=','&lt;' or '&gt;' to declare what to use</string>
<property name="text">
<string>Charts</string>
</property>
<item>
<property name="text">
<string>Appearance</string>
</property>
</item>
<item>
<property name="text">
<string>Speed</string>
</property>
</item>
<item>
<property name="text">
<string>Count</string>
</property>
</item>
<item>
<property name="text">
<string>Relational</string>
</property>
</item>
</item>
<item>
<property name="text">
@ -6826,7 +6846,7 @@ With numbers, use '!', '=','&lt;' or '&gt;' to declare what to use</string>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_Conf_General_Charts">
<widget class="QWidget" name="page_Conf_General_Charts_Theme">
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QFrame" name="frame_ConfCharts_Theme">
@ -6947,7 +6967,7 @@ With numbers, use '!', '=','&lt;' or '&gt;' to declare what to use</string>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_ConfCharts_Preview">
<widget class="QFrame" name="frame_ConfCharts_Theme_Preview">
<layout class="QGridLayout" name="gridLayout_83">
<item row="0" column="0">
<widget class="QLabel" name="label_ConfCharts_Preview">
@ -6981,6 +7001,9 @@ With numbers, use '!', '=','&lt;' or '&gt;' to declare what to use</string>
<height>256</height>
</size>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
@ -6988,6 +7011,597 @@ With numbers, use '!', '=','&lt;' or '&gt;' to declare what to use</string>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_Conf_General_Charts_Speed">
<layout class="QVBoxLayout" name="verticalLayout_31">
<item>
<widget class="QFrame" name="frame_ConfCharts_Speed_TimeInterval">
<layout class="QGridLayout" name="gridLayout_89">
<item row="1" column="0">
<spacer name="spacer_ConfCharts_Speed_1">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<spacer name="spacer_ConfCharts_Speed_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>569</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="label_ConfCharts_Speed_TimeInterval">
<property name="minimumSize">
<size>
<width>128</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="toolTip">
<string>Represents a step in the time axis, in seconds.
All the values falling inside the same interval will be merged and the mean value will be used.</string>
</property>
<property name="text">
<string>Time interval</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="box_ConfCharts_Speed_TimeInterval">
<property name="minimumSize">
<size>
<width>72</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>10</string>
</property>
</item>
<item>
<property name="text">
<string>15</string>
</property>
</item>
<item>
<property name="text">
<string>20</string>
</property>
</item>
<item>
<property name="text">
<string>30</string>
</property>
</item>
<item>
<property name="text">
<string>60</string>
</property>
</item>
<item>
<property name="text">
<string>120</string>
</property>
</item>
<item>
<property name="text">
<string>180</string>
</property>
</item>
<item>
<property name="text">
<string>240</string>
</property>
</item>
<item>
<property name="text">
<string>300</string>
</property>
</item>
<item>
<property name="text">
<string>600</string>
</property>
</item>
<item>
<property name="text">
<string>900</string>
</property>
</item>
<item>
<property name="text">
<string>1200</string>
</property>
</item>
<item>
<property name="text">
<string>1800</string>
</property>
</item>
<item>
<property name="text">
<string>3600</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_ConfCharts_Speed_TimeFormat">
<layout class="QGridLayout" name="gridLayout_90">
<item row="1" column="2">
<spacer name="spacer_ConfCharts_Speed_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>569</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="label_ConfCharts_Speed_TimeFormat">
<property name="minimumSize">
<size>
<width>128</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="toolTip">
<string>The format to use for the labels of the time axis.</string>
</property>
<property name="text">
<string>Time format</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="spacer_ConfCharts_Speed_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="box_ConfCharts_Speed_TimeFormat">
<property name="minimumSize">
<size>
<width>96</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<item>
<property name="text">
<string>hh:mm</string>
</property>
</item>
<item>
<property name="text">
<string>hh</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="spacer_ConfCharts_Speed">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>608</width>
<height>333</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_Conf_General_Charts_Count">
<layout class="QVBoxLayout" name="verticalLayout_30">
<item>
<widget class="QFrame" name="frame_ConfCharts_Count_PieSize">
<layout class="QGridLayout" name="gridLayout_86">
<item row="1" column="0">
<spacer name="spacer_ConfCharts_Count_1">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<spacer name="spacer_ConfCharts_Count_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>569</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="label_ConfCharts_Count_PieSize">
<property name="minimumSize">
<size>
<width>128</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="toolTip">
<string>The size of the pie</string>
</property>
<property name="text">
<string>Pie size</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_ConfCharts_Count_PieSize">
<property name="minimumSize">
<size>
<width>64</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::PlusMinus</enum>
</property>
<property name="correctionMode">
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
</property>
<property name="minimum">
<double>0.400000000000000</double>
</property>
<property name="maximum">
<double>0.800000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.600000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_ConfCharts_Count_MaxSlices">
<layout class="QGridLayout" name="gridLayout_87">
<item row="1" column="0">
<spacer name="spacer_ConfCharts_Count_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<spacer name="spacer_ConfCharts_Count_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>569</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="label_ConfCharts_Count_MaxSlices">
<property name="minimumSize">
<size>
<width>128</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="toolTip">
<string>The maximum number of slices that the pie will be composed of.
Exceeding slices will be grouped into one comprehensive slice.</string>
</property>
<property name="text">
<string>Maximum slices</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_ConfCharts_Count_MaxSlices">
<property name="minimumSize">
<size>
<width>56</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::PlusMinus</enum>
</property>
<property name="correctionMode">
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>31</number>
</property>
<property name="value">
<number>15</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="spacer_ConfCharts_Count">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_Conf_General_Charts_Relat">
<layout class="QVBoxLayout" name="verticalLayout_32">
<item>
<widget class="QFrame" name="frame_ConfCharts_Relat_TimeFormat">
<layout class="QGridLayout" name="gridLayout_91">
<item row="1" column="2">
<spacer name="spacer_ConfCharts_Relat_1">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>569</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="label_ConfCharts_Relat_TimeFormat">
<property name="minimumSize">
<size>
<width>128</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="toolTip">
<string>The format to use for the labels of the time axis.</string>
</property>
<property name="text">
<string>Time format</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="box_ConfCharts_Relat_TimeFormat">
<property name="minimumSize">
<size>
<width>96</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>32</height>
</size>
</property>
<item>
<property name="text">
<string>hh:mm</string>
</property>
</item>
<item>
<property name="text">
<string>hh</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<spacer name="spacer_ConfCharts_Relat_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="spacer_ConfCharts_Relat">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>608</width>
<height>427</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_Conf_General_TextBrowser">
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
@ -8582,7 +9196,7 @@ Any field not considered by LogDoctor will appear as 'DISCARDED'</string>
<rect>
<x>0</x>
<y>0</y>
<width>98</width>
<width>62</width>
<height>54</height>
</rect>
</property>
@ -9456,7 +10070,7 @@ Fields marked as 'DISCARDED' got parsed correctly, but are not considered by Log
<rect>
<x>0</x>
<y>0</y>
<width>98</width>
<width>62</width>
<height>54</height>
</rect>
</property>
@ -10654,7 +11268,7 @@ Any field not considered by LogDoctor will appear as 'DISCARDED'</string>
<rect>
<x>0</x>
<y>0</y>
<width>98</width>
<width>62</width>
<height>54</height>
</rect>
</property>

View File

@ -0,0 +1,22 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/shared.h
${CMAKE_CURRENT_SOURCE_DIR}/dialogs.h
${CMAKE_CURRENT_SOURCE_DIR}/dialogs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/exceptions.h
${CMAKE_CURRENT_SOURCE_DIR}/exceptions.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tb.h
${CMAKE_CURRENT_SOURCE_DIR}/tb.cpp
)
add_subdirectory(blacklists)
add_subdirectory(changelog)
add_subdirectory(crapconf)
add_subdirectory(craphelp)
add_subdirectory(crapinfo)
add_subdirectory(craplog)
add_subdirectory(crapup)
add_subdirectory(crapview)
add_subdirectory(database)
add_subdirectory(dialogs)
add_subdirectory(warnlists)

View File

@ -0,0 +1,7 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/blacklists.h
${CMAKE_CURRENT_SOURCE_DIR}/blacklists.cpp
)
add_subdirectory(modules)

View File

@ -0,0 +1,8 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib.h
${CMAKE_CURRENT_SOURCE_DIR}/blacklist.h
${CMAKE_CURRENT_SOURCE_DIR}/blacklist.cpp
${CMAKE_CURRENT_SOURCE_DIR}/blacklist_item.h
${CMAKE_CURRENT_SOURCE_DIR}/blacklist_item.cpp
)

View File

@ -0,0 +1,8 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/changelog.ui
${CMAKE_CURRENT_SOURCE_DIR}/changelog.h
${CMAKE_CURRENT_SOURCE_DIR}/changelog.cpp
)
add_subdirectory(modules)

View File

@ -0,0 +1,5 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.h
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.cpp
)

View File

@ -0,0 +1,4 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib.h
)

View File

@ -0,0 +1,31 @@
#ifndef LOGDOCTOR__CRAPCONF__LIB_H
#define LOGDOCTOR__CRAPCONF__LIB_H
enum ConfigsPage : unsigned char {
General_Window = 0,
General_Dialogs = 1,
General_Charts_Appearance = 2,
General_Charts_Speed = 3,
General_Charts_Count = 4,
General_Charts_Relational = 5,
General_TextBrowser = 6,
General_Databases = 7,
Logs_Defaults = 8,
Logs_Control = 9,
Logs_Apache2_Path = 10,
Logs_Apache2_Format = 11,
Logs_Apache2_Warnlists = 12,
Logs_Apache2_Blacklists = 13,
Logs_Nginx_Path = 14,
Logs_Nginx_Format = 15,
Logs_Nginx_Warnlists = 16,
Logs_Nginx_Blacklists = 17,
Logs_IIS_Path = 18,
Logs_IIS_Format = 19,
Logs_IIS_Warnlists = 20,
Logs_IIS_Blacklists = 21,
};
#endif // LOGDOCTOR__CRAPCONF__LIB_H

View File

@ -0,0 +1,6 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/craphelp.ui
${CMAKE_CURRENT_SOURCE_DIR}/craphelp.h
${CMAKE_CURRENT_SOURCE_DIR}/craphelp.cpp
)

View File

@ -0,0 +1,8 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/crapinfo.ui
${CMAKE_CURRENT_SOURCE_DIR}/crapinfo.h
${CMAKE_CURRENT_SOURCE_DIR}/crapinfo.cpp
)
add_subdirectory(modules)

View File

@ -0,0 +1,5 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.h
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.cpp
)

View File

@ -0,0 +1,10 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib.h
${CMAKE_CURRENT_SOURCE_DIR}/craplog.h
${CMAKE_CURRENT_SOURCE_DIR}/craplog.cpp
)
add_subdirectory(modules)
add_subdirectory(utilities)
add_subdirectory(workers)

View File

@ -19,9 +19,9 @@
#include "modules/craplog/modules/lib.h"
#include "modules/craplog/modules/donuts.h"
#include "modules/craplog/modules/logs.h"
#include "modules/craplog/modules/workers/lister.h"
#include "modules/craplog/modules/workers/parser.h"
#include "modules/craplog/workers/lister.h"
#include "modules/craplog/workers/parser.h"
#include "modules/craplog/utilities/logs.h"
#include <QPainter>
#include <QWaitCondition>
@ -87,7 +87,7 @@ DialogsLevel Craplog::getDialogsLevel() const noexcept
void Craplog::setDialogsLevel( const DialogsLevel new_level ) noexcept
{
this->dialogs_level = new_level;
this->hashOps.setDialogLevel( new_level );
this->hasher.setDialogLevel( new_level );
}
const std::string& Craplog::getStatsDatabasePath() const noexcept
@ -198,17 +198,17 @@ QString Craplog::getLogsFormatSample( const WebServer& web_server ) const
bool Craplog::checkCurrentLogsFormat() const noexcept
{
if ( this->current_log_format.string.empty() ) {
// format string not set
DialogSec::errLogFormatNotSet( nullptr );
return false;
// format string not set
DialogSec::errLogFormatNotSet( nullptr );
return false;
} else if ( this->current_log_format.fields.empty() ) {
// no field, useless to parse
DialogSec::errLogFormatNoFields( nullptr );
return false;
// no field, useless to parse
DialogSec::errLogFormatNoFields( nullptr );
return false;
} else if ( this->current_log_format.separators.size() < this->current_log_format.fields.size()-1 ) {
// at least one separator is missing between two (or more) fields
DialogSec::errLogFormatNoSeparators( nullptr );
return false;
// at least one separator is missing between two (or more) fields
DialogSec::errLogFormatNoSeparators( nullptr );
return false;
}
return true;
}
@ -270,7 +270,7 @@ const std::vector<LogFile>& Craplog::getLogsList() const noexcept
const LogFile& Craplog::getLogFileItem( const QString& file_name ) const
{
const auto item{ std::find_if( this->logs_list.begin(), this->logs_list.end(),
[&file_name](const LogFile& file){ return file.name()==file_name; } ) };
[&file_name](const LogFile& file){ return file.name()==file_name; } ) };
if ( item != this->logs_list.end() ) return *item;
// should be unreachable
throw GenericException("File item not found");
@ -281,7 +281,7 @@ const LogFile& Craplog::getLogFileItem( const QString& file_name ) const
bool Craplog::setLogFileSelected( const QString& file_name ) noexcept
{
const auto item{ std::find_if( this->logs_list.begin(), this->logs_list.end(),
[&file_name](const LogFile& file){ return file.name() == file_name; } ) };
[&file_name](const LogFile& file){ return file.name() == file_name; } ) };
if ( item != this->logs_list.end() ) {
item->setSelected();
return true;
@ -293,8 +293,7 @@ void Craplog::clearLogFilesSelection() noexcept
{
std::ignore = std::for_each(
this->logs_list.begin(), this->logs_list.end(),
[]( LogFile& it )
{ if (it.isSelected()) it.setUnselected(); } );
[](LogFile& it){ if (it.isSelected()) it.setUnselected(); } );
}
@ -308,8 +307,8 @@ void Craplog::scanLogsDir()
this->dialogs_level,
this->logs_paths.at( this->current_web_server ),
this->logs_formats.at( this->current_web_server ),
this->hashOps,
[this]( const std::string& file_name)
this->hasher,
[this]( const std::string& file_name )
{ return this->isFileNameValid( file_name ); }
) };
QThread* worker_thread{ new QThread() };
@ -507,7 +506,7 @@ bool Craplog::checkStuff()
// appears twice in the list
QString msg{ file.name() };
if ( this->dialogs_level == DL_EXPLANATORY ) {
msg += "\n" + QString::fromStdString( file.hash() );
msg += "\n" + QString::fromStdString( file.hash() );
}
const int choice = DialogSec::choiceDuplicateFile( msg );
if ( choice == 0 ) {
@ -720,9 +719,6 @@ void Craplog::hireWorker( const Blacklists& blacklists ) const
void Craplog::stopWorking( const bool successful )
{
this->db_edited = successful;
if ( successful ) {
// insert the hashes of the used files
}
emit this->finishedWorking();
}
@ -793,7 +789,7 @@ void Craplog::updateChartData( const size_t total_size, const size_t total_lines
void Craplog::storeFilesHashes( QWaitCondition* wc, bool* successful) noexcept
{
try {
this->hashOps.insertUsedHashes( this->db_hashes_path, this->used_files_hashes, this->current_web_server );
this->hasher.insertUsedHashes( this->db_hashes_path, this->used_files_hashes, this->current_web_server );
*successful |= true;
} catch (...) {
DialogSec::errFailedInsertUsedHashes();

View File

@ -4,10 +4,10 @@
#include "lib.h"
#include "modules/craplog/modules/hash.h"
#include "modules/craplog/modules/hasher.h"
#include "modules/craplog/modules/formats.h"
#include "modules/craplog/modules/workers/lib.h"
#include "modules/craplog/workers/lib.h"
#include <QtCharts>
@ -240,7 +240,7 @@ public:
//// OPERATIONS ////
// logs usage control
HashOps hashOps;
Hasher hasher;
//////////////

View File

@ -0,0 +1,12 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib.h
${CMAKE_CURRENT_SOURCE_DIR}/donuts.h
${CMAKE_CURRENT_SOURCE_DIR}/donuts.cpp
${CMAKE_CURRENT_SOURCE_DIR}/formats.h
${CMAKE_CURRENT_SOURCE_DIR}/formats.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hasher.h
${CMAKE_CURRENT_SOURCE_DIR}/hasher.cpp
)
add_subdirectory(hasher)

View File

@ -1,5 +1,7 @@
#include "hash.h"
#include "hasher.h"
#include "hasher/sha256.h"
#include "globals/db_names.h"
@ -13,21 +15,19 @@
#include "modules/database/database.h"
#include "sha256.h"
#include <ios>
#include <QVariant>
void HashOps::setDialogLevel( const DialogsLevel new_level ) noexcept
void Hasher::setDialogLevel( const DialogsLevel new_level ) noexcept
{
this->dialogs_level = new_level;
}
// reads the database holding the already used hashes
bool HashOps::loadUsedHashesLists( const std::string& db_path ) noexcept
bool Hasher::loadUsedHashesLists( const std::string& db_path ) noexcept
{
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Hashes ) };
@ -56,7 +56,7 @@ bool HashOps::loadUsedHashesLists( const std::string& db_path ) noexcept
// returns the hash
void HashOps::digestFile( const std::string& file_path, std::string& hash )
void Hasher::digestFile( const std::string& file_path, std::string& hash )
{
std::string content;
try {
@ -109,7 +109,7 @@ void HashOps::digestFile( const std::string& file_path, std::string& hash )
// check if the given hash is from a file which has been used already
bool HashOps::hasBeenUsed( const std::string &file_hash, const WebServer& web_server) const noexcept
bool Hasher::hasBeenUsed( const std::string &file_hash, const WebServer& web_server) const noexcept
{
const auto& ws_hashes{ this->hashes.at( web_server ) };
return std::any_of(
@ -119,7 +119,7 @@ bool HashOps::hasBeenUsed( const std::string &file_hash, const WebServer& web_se
}
void HashOps::insertUsedHashes( const std::string& db_path, const std::vector<std::string>& hashes, const WebServer& web_server )
void Hasher::insertUsedHashes( const std::string& db_path, const std::vector<std::string>& hashes, const WebServer& web_server )
{
const bool explain_msg{ this->dialogs_level > DL_ESSENTIAL };
const bool explain_err{ this->dialogs_level == DL_EXPLANATORY };

View File

@ -1,5 +1,5 @@
#ifndef LOGDOCTOR__CRAPLOG__MODULES__HASH_H
#define LOGDOCTOR__CRAPLOG__MODULES__HASH_H
#ifndef LOGDOCTOR__CRAPLOG__MODULES__HASHER_H
#define LOGDOCTOR__CRAPLOG__MODULES__HASHER_H
#include "main_lib.h"
@ -15,11 +15,11 @@ enum class WebServer;
class QSqlQuery;
//! HashOps
//! Hasher
/*!
Operations for the hashes
Operations on the logs hashes
*/
class HashOps final
class Hasher final
{
public:
@ -83,4 +83,4 @@ private:
};
#endif // LOGDOCTOR__CRAPLOG__MODULES__HASH_H
#endif // LOGDOCTOR__CRAPLOG__MODULES__HASHER_H

View File

@ -0,0 +1,5 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/sha256.h
${CMAKE_CURRENT_SOURCE_DIR}/sha256.cpp
)

View File

@ -13,12 +13,7 @@
File types used to decide whether a file should be considered valid or not
\see LogOps::defineFileType()
*/
enum class LogType
#ifdef _MSC_VER
: __int8
#else
: __INT8_TYPE__
#endif
enum class LogType : int8_t
{
Failed = -1, //!< Failed to determine the type
Discarded = 0, //!< Not a valid file, will be discarded

View File

@ -0,0 +1,7 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/datetime.h
${CMAKE_CURRENT_SOURCE_DIR}/datetime.cpp
${CMAKE_CURRENT_SOURCE_DIR}/logs.h
${CMAKE_CURRENT_SOURCE_DIR}/logs.cpp
)

View File

@ -1,7 +1,7 @@
#include "datetime.h"
#include "lib.h"
#include "modules/craplog/modules/lib.h"
#include "modules/exceptions.h"
#include "utilities/strings.h"

View File

@ -1,5 +1,5 @@
#ifndef LOGDOCTOR__CRAPLOG__MODULES__DATETIME_H
#define LOGDOCTOR__CRAPLOG__MODULES__DATETIME_H
#ifndef LOGDOCTOR__CRAPLOG__UTILITIES__DATETIME_H
#define LOGDOCTOR__CRAPLOG__UTILITIES__DATETIME_H
#include <stdint.h>
@ -29,4 +29,4 @@ std::vector<std::string> processDateTime( std::string_view datetime, const LogsF
} // namespace DateTimeOps
#endif // LOGDOCTOR__CRAPLOG__MODULES__DATETIME_H
#endif // LOGDOCTOR__CRAPLOG__UTILITIES__DATETIME_H

View File

@ -2,7 +2,6 @@
#include "logs.h"
#include "modules/exceptions.h"
#include "modules/craplog/modules/datetime.h"
#include "utilities/strings.h"

View File

@ -1,8 +1,8 @@
#ifndef LOGDOCTOR__CRAPLOG__MODULES__LOGS_H
#define LOGDOCTOR__CRAPLOG__MODULES__LOGS_H
#ifndef LOGDOCTOR__CRAPLOG__UTILITIES__LOGS_H
#define LOGDOCTOR__CRAPLOG__UTILITIES__LOGS_H
#include "lib.h"
#include "modules/craplog/modules/lib.h"
//! LogOps
@ -27,4 +27,4 @@ LogType defineFileType(
} // namespace LogOps
#endif // LOGDOCTOR__CRAPLOG__MODULES__LOGS_H
#endif // LOGDOCTOR__CRAPLOG__UTILITIES__LOGS_H

View File

@ -0,0 +1,10 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib.h
${CMAKE_CURRENT_SOURCE_DIR}/lister.h
${CMAKE_CURRENT_SOURCE_DIR}/lister.cpp
${CMAKE_CURRENT_SOURCE_DIR}/parser.h
${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp
)
add_subdirectory(parser)

View File

@ -0,0 +1,27 @@
#ifndef LOGDOCTOR__CRAPLOG__WORKERS__LIB_H
#define LOGDOCTOR__CRAPLOG__WORKERS__LIB_H
#include <QMetaType>
//! Signals which dialog to show
enum class WorkerDialog {
errGeneric, // 1 arg
errDirNotExists, // 1 arg
errFailedDefiningLogType, // 1 arg
errFailedParsingLogs, // 1 arg
errDatabaseFileNotFound, // 1 arg
errDatabaseFileNotFile, // 1 arg
errDatabaseFileNotReadable, // 1 arg
errDatabaseFileNotWritable, // 1 arg
errDatabaseFailedOpening, // 2 args
errDatabaseFailedExecuting, // 3 args
warnFileNotReadable, // 1 arg
warnEmptyFile, // 1 arg
};
Q_DECLARE_METATYPE(WorkerDialog)
#endif // LOGDOCTOR__CRAPLOG__WORKERS__LIB_H

View File

@ -7,19 +7,19 @@
#include "modules/exceptions.h"
#include "modules/craplog/modules/lib.h"
#include "modules/craplog/modules/hash.h"
#include "modules/craplog/modules/logs.h"
#include "modules/craplog/modules/hasher.h"
#include "modules/craplog/utilities/logs.h"
#include "modules/craplog/modules/workers/lib.h"
#include "modules/craplog/workers/lib.h"
CraplogLister::CraplogLister( const WebServer web_server, const DialogsLevel dialogs_level, const std::string& logs_path, const LogsFormat& logs_format, const HashOps& hashOps, const std::function<bool(const std::string&)> check_filename, QObject* parent )
CraplogLister::CraplogLister( const WebServer web_server, const DialogsLevel dialogs_level, const std::string& logs_path, const LogsFormat& logs_format, const Hasher& hasher, const std::function<bool(const std::string&)> check_filename, QObject* parent )
: QObject { parent }
, web_server { web_server }
, dialogs_level { dialogs_level }
, logs_path { logs_path }
, logs_format { logs_format }
, hashOps { hashOps }
, hasher { hasher }
, check_filename { check_filename }
{
@ -37,8 +37,10 @@ void CraplogLister::work()
const std::string& logs_path{ this->logs_path };
if ( ! IOutils::isDir( logs_path ) ) {
// this directory doesn't exists
emit this->showDialog( WorkerDialog::errDirNotExists,
{QString::fromStdString( logs_path )} );
if ( ! logs_path.empty() ) {
emit this->showDialog( WorkerDialog::errDirNotExists,
{QString::fromStdString( logs_path )} );
}
this->quit();
return;
}
@ -110,7 +112,7 @@ void CraplogLister::work()
std::string hash;
try {
this->hashOps.digestFile( path, hash );
this->hasher.digestFile( path, hash );
} catch ( GenericException& e ) {
// failed to digest
emit this->showDialog( WorkerDialog::errGeneric,
@ -120,7 +122,7 @@ void CraplogLister::work()
// push in the list
emit this->pushLogFile( LogFile{
false, this->hashOps.hasBeenUsed( hash, this->web_server ),
false, this->hasher.hasBeenUsed( hash, this->web_server ),
size, name, hash, path } );
}
this->quit();

View File

@ -8,7 +8,7 @@
struct LogsFormat;
struct LogFile;
class HashOps;
class Hasher;
enum class WorkerDialog;
@ -24,7 +24,7 @@ public:
const DialogsLevel dialogs_level,
const std::string& logs_path,
const LogsFormat& logs_format,
const HashOps& hashOps,
const Hasher& hasher,
const std::function<bool(const std::string&)> check_filename,
QObject* parent=nullptr
);
@ -55,7 +55,7 @@ private:
const LogsFormat& logs_format;
const HashOps& hashOps;
const Hasher& hasher;
const std::function<bool(const std::string&)> check_filename;

View File

@ -1,6 +1,10 @@
#include "parser.h"
#include "parser/logs_data.h"
#include "lib.h"
#include "globals/db_names.h"
#include "utilities/checks.h"
@ -12,8 +16,6 @@
#include "modules/dialogs.h"
#include "modules/exceptions.h"
#include "modules/craplog/modules/workers/lib.h"
#include <QWaitCondition>
#include <QSqlDatabase>
#include <QSqlQuery>

View File

@ -0,0 +1,5 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/logs_data.h
${CMAKE_CURRENT_SOURCE_DIR}/logs_data.cpp
)

View File

@ -1,10 +1,10 @@
#include "../lib.h"
#include "logs_data.h"
#include "modules/exceptions.h"
#include "modules/craplog/modules/lib.h"
#include "modules/craplog/modules/datetime.h"
#include "modules/craplog/utilities/datetime.h"
#include "utilities/strings.h"
#include "utilities/vectors.h"

View File

@ -1,35 +1,20 @@
#ifndef LOGDOCTOR__CRAPLOG__WORKERS__LIB_H
#define LOGDOCTOR__CRAPLOG__WORKERS__LIB_H
#ifndef LOGDOCTOR__CRAPLOG__WORKERS__PARSER__LOGS_DATA_H
#define LOGDOCTOR__CRAPLOG__WORKERS__PARSER__LOGS_DATA_H
#include <QMetaType>
#include <string>
#include <vector>
#ifdef _MSC_VER
enum LogsFormatField : uint32_t;
#else
enum LogsFormatField : __uint32_t;
#endif
struct LogsFormat;
//! Signals which dialog to show
enum class WorkerDialog {
errGeneric, // 1 arg
errDirNotExists, // 1 arg
errFailedDefiningLogType, // 1 arg
errFailedParsingLogs, // 1 arg
errDatabaseFileNotFound, // 1 arg
errDatabaseFileNotFile, // 1 arg
errDatabaseFileNotReadable, // 1 arg
errDatabaseFileNotWritable, // 1 arg
errDatabaseFailedOpening, // 2 args
errDatabaseFailedExecuting, // 3 args
warnFileNotReadable, // 1 arg
warnEmptyFile, // 1 arg
};
Q_DECLARE_METATYPE(WorkerDialog)
//! FieldData
/*!
Holds the data of a single field from a log line
@ -44,7 +29,8 @@ struct FieldData final
~FieldData() noexcept = default;
FieldData(FieldData&& other) noexcept = default;
FieldData& operator=(FieldData&& rhs) noexcept = default;
Q_DISABLE_COPY(FieldData)
FieldData(const FieldData &) = delete;
FieldData &operator=(const FieldData &) = delete;
//! Returns whether the field contains data
inline operator bool() const noexcept
@ -82,7 +68,8 @@ struct LogLineData final
~LogLineData() noexcept = default;
LogLineData(LogLineData&& other) noexcept = default;
LogLineData& operator=(LogLineData&& rhs) noexcept = delete;
Q_DISABLE_COPY(LogLineData)
LogLineData(const LogLineData &) = delete;
LogLineData &operator=(const LogLineData &) = delete;
//! Returns the total size of all the fields' data
size_t size() const noexcept;
@ -141,4 +128,4 @@ private:
};
#endif // LOGDOCTOR__CRAPLOG__WORKERS__LIB_H
#endif // LOGDOCTOR__CRAPLOG__WORKERS__PARSER__LOGS_DATA_H

View File

@ -0,0 +1,8 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/crapup.ui
${CMAKE_CURRENT_SOURCE_DIR}/crapup.h
${CMAKE_CURRENT_SOURCE_DIR}/crapup.cpp
)
add_subdirectory(modules)

View File

@ -0,0 +1,5 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.h
${CMAKE_CURRENT_SOURCE_DIR}/stylesheets.cpp
)

View File

@ -0,0 +1,10 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib.h
${CMAKE_CURRENT_SOURCE_DIR}/crapview.h
${CMAKE_CURRENT_SOURCE_DIR}/crapview.cpp
)
add_subdirectory(datatypes)
add_subdirectory(modules)
add_subdirectory(utilities)

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
#define LOGDOCTOR__CRAPVIEW_H
#include "modules/crapview/modules/query.h"
#include "modules/crapview/modules/fetcher.h"
#include <QtCharts>
@ -41,7 +41,7 @@ public:
//! Sets the new path for the logs Collection database
/*!
\see DbQuery::setDbPath()
\see Fetcher::setDbPath()
*/
void setDbPath( const std::string& path ) noexcept;
@ -61,14 +61,14 @@ public:
void clearDates() noexcept;
//! Returns le list of available years, for the given web server
//! Returns the list of available years, for the given web server
/*!
\param web_server The printable Web Server name
\return The list of yearss which are avaliable
*/
QStringList getYears( const QString& web_server ) const noexcept;
//! Returns le list of available months in the given year, for the given web server
//! Returns the list of available months in the given year, for the given web server
/*!
\param web_server The printable Web Server name
\param year The year
@ -76,7 +76,7 @@ public:
*/
QStringList getMonths( const QString& web_server, const QString& year ) const noexcept;
//! Returns le list of available days in the given month and year, for the given web server
//! Returns the list of available days in the given month and year, for the given web server
/*!
\param web_server The printable Web Server name
\param year The year
@ -107,6 +107,69 @@ public:
QStringList getSpeedHeaderColumns() const noexcept;
//! Sets the time interval for the Speed stats
/*!
\param interval The time interval to use
*/
void setSpeedTimeInterval( const qint64 interval ) noexcept;
//! Returns the current time interval for the Speed stats
/*!
\return The time interval in use
*/
qint64 getSpeedTimeInterval() const noexcept;
//! Sets the time format for the Speed labels on the X-axis
/*!
\param format The format to use
*/
void setSpeedTimeFormat( const QString& format ) noexcept;
//! Returns the current time format for the Speed labels on the X-axis
/*!
\return The time format in use
*/
const QString& getSpeedTimeFormat() const noexcept;
//! Sets the size of the pie chart for the Count stats
/*!
\param size The new size
*/
void setCountPieSize( const qreal size ) noexcept;
//! Returns the current size of the pie chart for the Count stats
/*!
\return The size in use
*/
qreal getCountPieSize() const noexcept;
//! Sets the maximum number of slices of pie chart for the Count stats
/*!
\param value The maximum number of slices
*/
void setCountMaxSlices( const int value ) noexcept;
//! Returns the current maximum number of slices of pie chart for the Count stats
/*!
\return The maximum number of slices in use
*/
int getCountMaxSlices() const noexcept;
//! Sets the time format for the Relational labels on the X-axis
/*!
\param format The format to use
*/
void setRelatTimeFormat( const QString& format ) noexcept;
//! Returns the current time format for the Relational labels on the X-axis
/*!
\return The time format in use
*/
const QString& getRelatTimeFormat() const noexcept;
//! Draws the chart and fills the table for the Warnings stats
/*!
\param table The table widget
@ -144,7 +207,7 @@ public:
\param response The given filter for the Response
*/
void drawSpeed(
QTableWidget* table, QChartView* chart,
QTableWidget*const table, QChartView*const chart,
const QChart::ChartTheme& theme,
const QString web_server,
const QString year, const QString month, const QString day,
@ -164,7 +227,7 @@ public:
\param field The printable log field
*/
void drawCount(
QTableWidget* table, QChartView* chart,
QTableWidget*const table, QChartView*const chart,
const QChart::ChartTheme& theme,
const QString web_server,
const QString year, const QString month, const QString day,
@ -187,7 +250,7 @@ public:
\param filter The give filter string
*/
void drawDay(
QChartView* chart,
QChartView*const chart,
const QChart::ChartTheme& theme,
const QString web_server,
const QString from_year, const QString from_month, const QString from_day,
@ -213,7 +276,7 @@ public:
\param filter_2 The give filter string for the second field
*/
void drawRelat(
QChartView* chart,
QChartView*const chart,
const QChart::ChartTheme& theme,
const QString web_server,
const QString from_year, const QString from_month, const QString from_day,
@ -251,37 +314,42 @@ private:
// quantity of information to display throught dialogs
DialogsLevel dialogs_level{ DL_NORMAL };
// charts theme ID
int charts_theme{ 0 };
const QColor warning_color{ 255, 127, 0, 255 };
const QColor warning_color{ 255, 140, 0, 255 };
DbQuery dbQuery;
Fetcher fetcher;
// collection of available dates
// db_dates_t = std::unordered_map<int, std::unordered_map<int, std::unordered_map<int, std::vector<int>>>>
// { web_server_id : { year : { month : [ days ] } } }
database_dates_t dates;
qint64 speed_interval{ 1ll };
QString speed_time_format{ "hh:mm" };
qreal count_pie_size{ 0.6 };
int count_max_slices{ 15 };
QString relat_time_format{ "hh:mm" };
// converr Web Servers names to Web Server IDs
const QHash<QString, int> WebServer_s2i{
{"apache",11}, {"nginx",12}, {"iis",13} };
const QHash<QString, WebServer> WebServer_s2e{
{"apache",WS_APACHE}, {"nginx",WS_NGINX}, {"iis",WS_IIS} };
// convert months names to months numbers
const QHash<QString, int> Months_s2i{
{QString::fromStdString(this->dbQuery.MONTHS.at(1)), 1},
{QString::fromStdString(this->dbQuery.MONTHS.at(2)), 2},
{QString::fromStdString(this->dbQuery.MONTHS.at(3)), 3},
{QString::fromStdString(this->dbQuery.MONTHS.at(4)), 4},
{QString::fromStdString(this->dbQuery.MONTHS.at(5)), 5},
{QString::fromStdString(this->dbQuery.MONTHS.at(6)), 6},
{QString::fromStdString(this->dbQuery.MONTHS.at(7)), 7},
{QString::fromStdString(this->dbQuery.MONTHS.at(8)), 8},
{QString::fromStdString(this->dbQuery.MONTHS.at(9)), 9},
{QString::fromStdString(this->dbQuery.MONTHS.at(10)), 10},
{QString::fromStdString(this->dbQuery.MONTHS.at(11)), 11},
{QString::fromStdString(this->dbQuery.MONTHS.at(12)), 12}};
{QString::fromStdString(this->fetcher.MONTHS.at(1)), 1},
{QString::fromStdString(this->fetcher.MONTHS.at(2)), 2},
{QString::fromStdString(this->fetcher.MONTHS.at(3)), 3},
{QString::fromStdString(this->fetcher.MONTHS.at(4)), 4},
{QString::fromStdString(this->fetcher.MONTHS.at(5)), 5},
{QString::fromStdString(this->fetcher.MONTHS.at(6)), 6},
{QString::fromStdString(this->fetcher.MONTHS.at(7)), 7},
{QString::fromStdString(this->fetcher.MONTHS.at(8)), 8},
{QString::fromStdString(this->fetcher.MONTHS.at(9)), 9},
{QString::fromStdString(this->fetcher.MONTHS.at(10)), 10},
{QString::fromStdString(this->fetcher.MONTHS.at(11)), 11},
{QString::fromStdString(this->fetcher.MONTHS.at(12)), 12}};
};

View File

@ -0,0 +1,16 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/fwd.h
${CMAKE_CURRENT_SOURCE_DIR}/count_stats.h
${CMAKE_CURRENT_SOURCE_DIR}/count_stats.cpp
${CMAKE_CURRENT_SOURCE_DIR}/daytime_stats.h
${CMAKE_CURRENT_SOURCE_DIR}/daytime_stats.cpp
${CMAKE_CURRENT_SOURCE_DIR}/global_stats.h
${CMAKE_CURRENT_SOURCE_DIR}/relational_stats.h
${CMAKE_CURRENT_SOURCE_DIR}/relational_stats.cpp
${CMAKE_CURRENT_SOURCE_DIR}/speed_stats.h
${CMAKE_CURRENT_SOURCE_DIR}/speed_stats.cpp
${CMAKE_CURRENT_SOURCE_DIR}/warning_stats.h
${CMAKE_CURRENT_SOURCE_DIR}/warning_stats.cpp
${CMAKE_CURRENT_SOURCE_DIR}/typedefs.h
)

View File

@ -0,0 +1,74 @@
#include "count_stats.h"
#include "modules/database/database.h"
#include "modules/crapview/modules/fetcher/utilities.h"
#include <QPieSeries>
#include <QTableWidget>
#include <ranges>
using namespace FetcherPrivate;
bool CountData::buildFromQuery( QueryWrapper& query )
{
QHash<QString, unsigned> aux_data;
if ( const size_t size{ query.size() }; size > 0ul ) {
aux_data.reserve( size * 3 );
} else {
return false;
}
while ( query->next() ) {
const QString item{ toString( query[0] ) };
if ( ! item.isEmpty() ) {
++ aux_data[ item ];
}
}
// morph tha QHash into an ordered map
QHashIterator iter{ aux_data };
while ( iter.hasNext() ) {
iter.next();
data.emplace( iter.value(), iter.key() );
}
return true;
}
void CountData::insertInChart( QPieSeries*const pie, const int max_slices, const QString others_label ) const
{
int n_slices{0}, others_count{0};
for ( const auto& key_value : std::views::reverse( data ) ) {
if ( n_slices < max_slices ) {
pie->append( key_value.second, key_value.first );
} else {
others_count += key_value.first;
}
++ n_slices;
}
if ( others_count > 0 ) {
pie->append( others_label, others_count );
pie->slices().at( max_slices )->setBrush( Qt::gray );
}
}
void CountData::insertInTable( QTableWidget*const table ) const
{
int n_rows{0};
for ( const auto& key_value : std::views::reverse( data ) ) {
table->insertRow( n_rows );
auto*const ic{ new QTableWidgetItem() };
ic->setData( Qt::DisplayRole, key_value.first );
table->setItem( n_rows, 0, ic );
table->setItem( n_rows, 1, new QTableWidgetItem( key_value.second ));
++ n_rows;
}
}

View File

@ -0,0 +1,31 @@
#ifndef LOGDOCTOR__CRAPVIEW__DATATYPES__COUNT_H
#define LOGDOCTOR__CRAPVIEW__DATATYPES__COUNT_H
#include <map>
class QueryWrapper;
class QString;
class QPieSeries;
class QTableWidget;
class CountData final
{
public:
CountData() = default;
bool buildFromQuery( QueryWrapper& query );
void insertInChart( QPieSeries*const pie, const int max_slices, const QString others_label ) const;
void insertInTable( QTableWidget*const table ) const;
private:
std::multimap<unsigned, QString> data;
};
#endif // LOGDOCTOR__CRAPVIEW__DATATYPES__COUNT_H

View File

@ -0,0 +1,103 @@
#include "daytime_stats.h"
#include "modules/database/database.h"
#include "modules/crapview/modules/fetcher/utilities.h"
#include <QBarSet>
#include <QTableWidget>
#include <ranges>
using namespace FetcherPrivate;
DaytimeData::DaytimeData()
: data{ { 0, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{ 1, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{ 2, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{ 3, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{ 4, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{ 5, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{ 6, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{ 7, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{ 8, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{ 9, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{10, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{11, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{12, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{13, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{14, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{15, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{16, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{17, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{18, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{19, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{20, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{21, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{22, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}},
{23, {{0,0},{10,0},{20,0},{30,0},{40,0},{50,0}}} }
{
}
int DaytimeData::buildFromQuery( QueryWrapper& query )
{
if ( query.size() == 0ul ) {
return 0;
}
std::unordered_map<int,int> days_l;
days_l.reserve( 31ul );
while ( query->next() ) {
const int day{ toInt( query[0] ) };
const int hour{ toInt( query[1] ) };
const int minute{ toInt( query[2] ) };
++ data.at( hour ).at( getMinuteGap( minute ) );
++ days_l[ day ];
}
return static_cast<int>(days_l.size());
}
void DaytimeData::adjustCounts( const int n_days )
{
for ( auto& [h,data_] : data ) {
for ( auto& [m,count] : data_ ) {
count /= n_days;
}
}
}
qreal DaytimeData::insertInChart( QList<QBarSet*>& sets ) const
{
qreal count, max_count{0};
const auto check_max_count{ [&count,&max_count](){
if ( count > max_count ) max_count = count;
}};
for ( size_t h{0ul}; h<24ul; ++h ) {
const auto& data_{ data.at( h ) };
count = data_.at( 0ul );
*sets.at( 0ul ) << count;
check_max_count();
count = data_.at( 10ul );
*sets.at( 1ul ) << count;
check_max_count();
count = data_.at( 20ul );
*sets.at( 2ul ) << count;
check_max_count();
count = data_.at( 30ul );
*sets.at( 3ul ) << count;
check_max_count();
count = data_.at( 40ul );
*sets.at( 4ul ) << count;
check_max_count();
count = data_.at( 50ul );
*sets.at( 5ul ) << count;
check_max_count();
}
return max_count;
}

View File

@ -0,0 +1,32 @@
#ifndef LOGDOCTOR__CRAPVIEW__DATATYPES__DAYTIME_H
#define LOGDOCTOR__CRAPVIEW__DATATYPES__DAYTIME_H
#include <QList>
#include <unordered_map>
class QueryWrapper;
class QString;
class QBarSet;
class QTableWidget;
struct DaytimeData final
{
DaytimeData();
int buildFromQuery( QueryWrapper& query );
void adjustCounts( const int n_days );
qreal insertInChart( QList<QBarSet*>& sets ) const;
private:
std::unordered_map<int, std::unordered_map<int, qreal>> data;
};
#endif // LOGDOCTOR__CRAPVIEW__DATATYPES__DAYTIME_H

View File

@ -0,0 +1,15 @@
#ifndef LOGDOCTOR__CRAPVIEW__DATATYPES__FWD_H
#define LOGDOCTOR__CRAPVIEW__DATATYPES__FWD_H
#include "typedefs.h"
#include "warning_stats.h"
#include "speed_stats.h"
#include "count_stats.h"
#include "daytime_stats.h"
#include "relational_stats.h"
#include "global_stats.h"
#endif // LOGDOCTOR__CRAPVIEW__DATATYPES__FWD_H

View File

@ -1,23 +1,13 @@
#ifndef LOGDOCTOR__CRAPVIEW__MODULES__LIB_H
#define LOGDOCTOR__CRAPVIEW__MODULES__LIB_H
#ifndef LOGDOCTOR__CRAPVIEW__DATATYPES__GLOBALS_H
#define LOGDOCTOR__CRAPVIEW__DATATYPES__GLOBALS_H
#include <tuple>
#include <array>
#include <unordered_map>
#include <QHash>
#define CRAPVIEW_DATA_TYPEDEFS\
using stats_dates_t = std::map<int, std::map<int, std::vector<int>>>;\
using stats_warn_items_t = std::vector<std::vector<std::vector<std::array<QString,18>>>>;\
using stats_speed_items_t = std::vector<std::tuple<qint64, std::array<QString,6>>>;\
using stats_day_items_t = std::unordered_map<int, std::unordered_map<int, int>>;\
using stats_relat_items_t = std::vector<std::tuple<qint64, int>>;\
using stats_count_items_t = std::multimap<unsigned, QString>;\
using database_dates_t = std::map<int, stats_dates_t>;
struct RecurrenceData final
{
QHash<QString, size_t> protocol;
@ -65,4 +55,5 @@ struct GlobalsData final
Q_DISABLE_COPY(GlobalsData)
};
#endif // LOGDOCTOR__CRAPVIEW__MODULES__LIB_H
#endif // LOGDOCTOR__CRAPVIEW__DATATYPES__GLOBALS_H

View File

@ -0,0 +1,188 @@
#include "relational_stats.h"
#include "modules/database/database.h"
#include "modules/crapview/modules/fetcher/date_time.h"
#include <QLineSeries>
#include <QTableWidget>
using namespace FetcherPrivate;
RelationalDatum::RelationalDatum( const qint64 timestamp )
: timestamp{ timestamp }
, count{ 0 }
{
}
RelationalDatum::RelationalDatum( const qint64 timestamp, const int count )
: timestamp{ timestamp }
, count{ count }
{
}
void RelationalData::pushEmpty( const IManager& date_time )
{
data.emplace_back( date_time.intervalTimestamp() );
}
void RelationalData::pushDatum( const IManager& date_time, const int count )
{
data.emplace_back( date_time.intervalTimestamp(), count );
}
bool RelationalData::buildFromQuery( QueryWrapper& query, TimeManager&& time )
{
if ( query.size() == 0ul ) {
return false;
}
data.reserve( static_cast<size_t>( 24*(60/(time.intervalStep()/60)) ) );
int count{ 0 };
pushEmpty( time );
while ( query->next() ) {
time.setHourMinute( query );
if ( time.inCurrentInterval() ) {
++ count;
} else {
pushDatum( time, count );
time.increaseInterval();
if ( ! time.inCurrentInterval() ) {
pushEmpty( time );
time.increaseIntervalUntil();
pushEmpty( time );
time.increaseInterval();
}
count = 1;
}
}
pushDatum( time, count );
time.increaseInterval();
pushEmpty( time );
time.setTime( QTime( 23, 59, 59 ) );
if ( time.isAfterIntervalBegin() ) {
time.setIntervalToNextMidnight();
pushEmpty( time );
}
if ( data.capacity() > data.size() ) {
data.shrink_to_fit();
}
return true;
}
bool RelationalData::buildFromQuery( QueryWrapper& query, DateManager&& date, const QDate last_date )
{
if ( const size_t size{query.size()}; size == 0ul ) {
return false;
} else {
data.reserve( size * 2 );
}
date.decreaseInterval();
pushEmpty( date );
date.increaseInterval();
process( query, date, last_date.day()-1 );
date.setIntervalDate( std::move(last_date) );
pushEmpty( date );
if ( data.capacity() > data.size() ) {
data.shrink_to_fit();
}
return true;
}
bool RelationalData::appendFromQuery( QueryWrapper& query, DateManager& date, const QDate initial_date, const QDate final_date, const int last_day )
{
if ( query.size() == 0ul ) {
// no data found for this month
date.setDate( std::move(initial_date) );
pushEmpty( date );
date.setDate( std::move(final_date) );
pushEmpty( date );
return false;
} else {
date.setDate( QDate(initial_date) );
date.setIntervalDate( std::move(initial_date) );
process( query, date, last_day );
return true;
}
}
void RelationalData::process( QueryWrapper& query, DateManager& date, const int last_day )
{
int count{ 0 };
while ( query->next() ) {
date.setDay( query );
if ( date.inCurrentInterval() ) {
++ count;
} else {
pushDatum( date, count );
date.increaseInterval();
if ( ! date.inCurrentInterval() ) {
pushEmpty( date );
date.increaseIntervalUntil();
pushEmpty( date );
date.increaseInterval();
}
count = 1;
}
}
pushDatum( date, count );
if ( date.isIntervalBeforeDay( last_day ) ) {
date.increaseInterval();
pushEmpty( date );
}
}
void RelationalData::reserveSpace( const size_t size )
{
data.reserve( size );
}
void RelationalData::appendFirstEmpty( DateManager& date )
{
date.decreaseInterval();
pushEmpty( date );
date.increaseInterval();
}
void RelationalData::appendLastEmpty( DateManager& date, const QDate&& last_date )
{
date.setIntervalDate( std::move(last_date) );
pushEmpty( date );
}
int RelationalData::insertInChart( QLineSeries*const line ) const
{
int max_count{ 0 };
for ( const RelationalDatum& datum : data ) {
const qint64 time{ datum.timestamp };
const int count{ datum.count };
line->append( static_cast<qreal>(time), static_cast<qreal>(count) );
if ( count > max_count ) {
max_count = count;
}
}
return max_count;
}

View File

@ -0,0 +1,59 @@
#ifndef LOGDOCTOR__CRAPVIEW__DATATYPES__RELATIONAL_H
#define LOGDOCTOR__CRAPVIEW__DATATYPES__RELATIONAL_H
#include <QDateTime>
class QueryWrapper;
namespace FetcherPrivate {
class TimeManager;
class DateManager;
struct IManager;
}
class QLineSeries;
class QTableWidget;
struct RelationalDatum final
{
RelationalDatum( const qint64 timestamp );
RelationalDatum( const qint64 timestamp, const int count );
const qint64 timestamp;
const int count;
};
class RelationalData final
{
using IManager = FetcherPrivate::IManager;
using TimeManager = FetcherPrivate::TimeManager;
using DateManager = FetcherPrivate::DateManager;
public:
RelationalData() = default;
bool buildFromQuery( QueryWrapper& query, TimeManager&& time );
bool buildFromQuery( QueryWrapper& query, DateManager&& date, const QDate last_date );
bool appendFromQuery( QueryWrapper& query, DateManager& date, const QDate initial_date, const QDate final_date, const int last_day );
void reserveSpace( const size_t size );
void appendFirstEmpty( DateManager& date );
void appendLastEmpty( DateManager& date, const QDate&& last_date );
int insertInChart( QLineSeries*const line ) const;
private:
void pushEmpty( const IManager& date_time );
void pushDatum( const IManager& date_time, const int count );
void process( QueryWrapper& query, DateManager& date, const int last_day );
std::vector<RelationalDatum> data;
};
#endif // LOGDOCTOR__CRAPVIEW__DATATYPES__RELATIONAL_H

View File

@ -0,0 +1,181 @@
#include "speed_stats.h"
#include "modules/database/database.h"
#include "modules/crapview/modules/fetcher/date_time.h"
#include <QLineSeries>
#include <QTableWidget>
#include <ranges>
using namespace FetcherPrivate;
SpeedDatum::SpeedDatum( const qint64 chart_timestamp )
: chart_timestamp{ chart_timestamp }
{
}
SpeedDatum::SpeedDatum( const QueryWrapper& query, const TimeManager& time )
: chart_timestamp{ time.intervalTimestamp() }
, time{ time.currentTime() }
, time_taken{ toString( query[3] ) }
, uri{ toString( query[4] ) }
, query{ toString( query[5] ) }
, method{ toString( query[6] ) }
, protocol{ toString( query[7] ) }
, response{ toString( query[8] ) }
{
}
void SpeedData::pushEmpty( const TimeManager& date_time )
{
data.push_back( { date_time.intervalTimestamp() } );
}
void SpeedData::pushDatum( const SpeedDatum datum )
{
data.push_back( std::move(datum) );
}
bool SpeedData::buildFromQuery( QueryWrapper& query, TimeManager&& time )
{
if ( const size_t size{ query.size() }; size > 0ul ) {
data.reserve( size * 3 );
} else {
return false;
}
pushEmpty( time );
while ( query->next() ) {
time.setHourMinuteSecond( query );
const SpeedDatum datum{ query, time };
if ( time.inCurrentInterval() ) {
pushDatum( datum );
} else {
time.increaseInterval();
if ( ! time.inCurrentInterval() ) {
pushEmpty( time );
time.increaseIntervalUntil();
pushEmpty( time );
time.increaseInterval();
}
pushDatum( datum );
}
}
time.increaseInterval();
pushEmpty( time );
time.setTime( std::move(QTime( 23, 59, 59 )) );
if ( time.isAfterIntervalBegin() ) {
time.setIntervalToNextMidnight();
pushEmpty( time );
}
if ( data.capacity() > data.size() ) {
data.shrink_to_fit();
}
return true;
}
int SpeedData::insertInChart( QLineSeries*const line ) const
{
size_t i{ 0 };
const size_t max_i{ data.size() };
int value{0}, count{0}, aux_value, max_value{0};
qint64 time{ -1 };
const auto finalize_value{
[&value,&count]()
{
if ( value == -1 ) {
value = 0;
} else {
value /= count+1;
}
}
};
const auto push_to_line{
[&max_value]( QLineSeries*const line, const qint64 time, const int value )
{
line->append( time, value );
if ( value > max_value ) {
max_value = value;
}
}
};
const auto set_values{
[&time,&value,&count]( const qint64 t, const int v, const int c )
{
time = t; value = v; count = c;
}
};
for ( const SpeedDatum& datum : data ) {
++i;
const qint64 aux_time{ datum.chart_timestamp };
if ( datum.time_taken.isEmpty() ) {
if ( time != -1 ) {
finalize_value();
push_to_line( line, time, value );
}
set_values( aux_time, -1, 0 );
push_to_line( line, time, 0 );
continue;
} else {
aux_value = datum.time_taken.toInt();
if ( aux_time > time ) {
finalize_value();
push_to_line( line, time, value );
set_values( aux_time, aux_value, 0 );
if ( i == max_i ) {
push_to_line( line, time, value );
}
} else {
if ( value == -1 ) {
value = 0;
} else {
++ count;
}
value += aux_value;
if ( i == max_i ) {
value /= count+1;
push_to_line( line, aux_time, value );
}
}
}
}
return max_value;
}
void SpeedData::insertInTable( QTableWidget*const table ) const
{
int n_rows{0};
auto filtered_data{ data | std::views::filter(
[](const SpeedDatum& datum){ return static_cast<bool>(datum); })
};
for ( const SpeedDatum& datum : filtered_data ) {
table->insertRow( n_rows );
auto* tt{ new QTableWidgetItem() };
tt->setData( Qt::DisplayRole, datum.time_taken );
table->setItem( n_rows, 0, tt );
table->setItem( n_rows, 1, new QTableWidgetItem( datum.uri ));
table->setItem( n_rows, 2, new QTableWidgetItem( datum.query ));
table->setItem( n_rows, 3, new QTableWidgetItem( datum.method ));
table->setItem( n_rows, 4, new QTableWidgetItem( datum.protocol ));
table->setItem( n_rows, 5, new QTableWidgetItem( datum.response ));
table->setItem( n_rows, 6, new QTableWidgetItem( datum.time.toString("hh:mm:ss") ));
++ n_rows;
}
}

View File

@ -0,0 +1,60 @@
#ifndef LOGDOCTOR__CRAPVIEW__DATATYPES__SPEED_H
#define LOGDOCTOR__CRAPVIEW__DATATYPES__SPEED_H
#include <QDateTime>
class QueryWrapper;
namespace FetcherPrivate {
class TimeManager;
}
class QLineSeries;
class QTableWidget;
class SpeedDatum final
{
using TimeManager = FetcherPrivate::TimeManager;
public:
SpeedDatum( const qint64 chart_timestamp );
SpeedDatum( const QueryWrapper& query, const TimeManager& time );
explicit operator bool() const { return time.isValid(); }
const qint64 chart_timestamp;
const QTime time;
const QString time_taken;
const QString uri;
const QString query;
const QString method;
const QString protocol;
const QString response;
};
class SpeedData final
{
using TimeManager = FetcherPrivate::TimeManager;
public:
SpeedData() = default;
bool buildFromQuery( QueryWrapper& query, TimeManager&& time );
int insertInChart( QLineSeries*const line ) const;
void insertInTable( QTableWidget*const table ) const;
private:
void pushEmpty( const TimeManager& date_time );
void pushDatum( const SpeedDatum datum );
std::vector<SpeedDatum> data;
};
#endif // LOGDOCTOR__CRAPVIEW__DATATYPES__SPEED_H

View File

@ -0,0 +1,10 @@
#ifndef LOGDOCTOR__CRAPVIEW__DATATYPES__TYPEDEFS_H
#define LOGDOCTOR__CRAPVIEW__DATATYPES__TYPEDEFS_H
#define CRAPVIEW_DATA_TYPEDEFS\
using stats_dates_t = std::map<int, std::map<int, std::vector<int>>>;\
using database_dates_t = std::map<WebServer, stats_dates_t>;
#endif // LOGDOCTOR__CRAPVIEW__DATATYPES__TYPEDEFS_H

View File

@ -0,0 +1,295 @@
#include "warning_stats.h"
#include "modules/crapview/modules/fetcher/utilities.h"
#include "modules/database/database.h"
#include "modules/warnlists/modules/warnlist.h"
#include "utilities/printables.h"
#include "utilities/strings.h"
#include "utilities/vectors.h"
#include <QBarSet>
#include <QTableWidget>
#include <ranges>
using namespace FetcherPrivate;
namespace /*private*/
{
QTableWidgetItem* textualTableItem( const QString& data )
{
return new QTableWidgetItem( data );
}
QTableWidgetItem* numericTableItem( const QString& data )
{
if ( data.isEmpty() ) {
return textualTableItem( data );
} else {
QTableWidgetItem* item{ new QTableWidgetItem() };
item->setData( Qt::DisplayRole, data.toInt() );
return item;
}
}
} // namespace (private)
WarningDatum::WarningDatum( const QueryWrapper& query )
: year{ toInt(query[0]) }
, month{ toInt(query[1]) }
, day{ toInt(query[2]) }
, hour{ toInt(query[3]) }
, minute{ toInt(query[4]) }
, second{ toInt(query[5]) }
, protocol{ toString(query[6]) }
, method{ toString(query[7]) }
, uri{ toString(query[8]) }
, query{ toString(query[9]) }
, response{ toString(query[10]) }
, user_agent{ toString(query[15]) }
, client{ toString(query[14]) }
, cookie{ toString(query[16]) }
, referer{ toString(query[17]) }
, bytes_received{ toString(query[13]) }
, bytes_sent{ toString(query[12]) }
, time_taken{ toString(query[11]) }
{
}
void WarningDatum::checkWarnings( const Warnlist& warnlist )
{
std::vector<int> warning_cols;
warning_cols.reserve(4ul);
if ( warnlist.method.used ) {
if ( VecOps::contains( warnlist.method.list, method.toStdString() ) ) {
warning_cols.push_back( 4 );
}
}
if ( warnlist.uri.used ) {
const auto target{ uri.toStdString() };
const auto& list{ warnlist.uri.list };
if ( std::any_of( list.cbegin(), list.cend(), [&target](std::string_view flag){ return StringOps::startsWith( target, flag ); } ) ) {
warning_cols.push_back( 5 );
}
}
if ( warnlist.user_agent.used ) {
const auto target{ user_agent.toStdString() };
const auto& list{ warnlist.user_agent.list };
if ( std::any_of( list.cbegin(), list.cend(), [&target](std::string_view flag){ return StringOps::startsWith( target, flag ); } ) ) {
warning_cols.push_back( 8 );
}
}
if ( warnlist.client.used ) {
const auto target{ client.toStdString() };
const auto& list{ warnlist.client.list };
if ( std::any_of( list.cbegin(), list.cend(), [&target](std::string_view flag){ return StringOps::startsWith( target, flag ); } ) ) {
warning_cols.push_back( 9 );
}
}
if ( ! warning_cols.empty() ) {
warning_cols.shrink_to_fit();
warning_columns = std::move(warning_cols);
}
}
bool WarningDatum::hasWarnings() const noexcept
{
return ! warning_columns.empty();
}
void WarningDatum::insertInTable( QTableWidget*const table, const QColor& warning_color ) const
{
const bool has_warning{ hasWarnings() };
const int n_rows{ table->rowCount() };
table->insertRow( n_rows );
table->setItem( n_rows, 0, new QTableWidgetItem( PrintSec::printableBool( has_warning )) );
table->setItem( n_rows, 1, new QTableWidgetItem( PrintSec::printableDate( year, month, day )) );
table->setItem( n_rows, 2, new QTableWidgetItem( PrintSec::printableTime( hour, minute, second )) );
table->setItem( n_rows, 3, textualTableItem( protocol ) );
table->setItem( n_rows, 4, textualTableItem( method ) );
table->setItem( n_rows, 5, textualTableItem( uri ) );
table->setItem( n_rows, 6, textualTableItem( query ) );
table->setItem( n_rows, 7, numericTableItem( response ) );
table->setItem( n_rows, 8, textualTableItem( user_agent ) );
table->setItem( n_rows, 9, textualTableItem( client ) );
table->setItem( n_rows, 10, textualTableItem( cookie ) );
table->setItem( n_rows, 11, textualTableItem( referer ) );
table->setItem( n_rows, 12, numericTableItem( bytes_received ) );
table->setItem( n_rows, 13, numericTableItem( bytes_sent ) );
table->setItem( n_rows, 14, numericTableItem( time_taken ) );
if ( has_warning ) {
table->item( n_rows, 0 )->setForeground( warning_color );
for ( const int col : warning_columns ) {
table->item( n_rows, col )->setForeground( warning_color );
}
}
}
void WarningData::setTimelineAsDay()
{
timeline = TimelineType::Day;
data.reserve( 24ul );
for ( size_t h{0ul}; h<24ul; ++h ) {
data.push_back( std::vector<std::vector<WarningDatum>>{} );
auto& aux{ data.back() };
aux.reserve( 6ul );
for ( int m{0}; m<60; m+=10 ) {
aux.push_back( std::vector<WarningDatum>{} );
}
}
}
void WarningData::setTimelineAsHour()
{
timeline = TimelineType::Hour;
data.reserve( 6ul );
for ( size_t g{0ul}; g<6ul; ++g ) {
data.push_back( std::vector<std::vector<WarningDatum>>{} );
auto& aux{ data.back() };
aux.reserve( 10ul );
for ( int m{0}; m<10; ++m ) {
aux.push_back( std::vector<WarningDatum>{} );
}
}
}
bool WarningData::buildFromQuery( QueryWrapper& query )
{
switch ( timeline ) {
case TimelineType::Day:
return buildForDay( query );
case TimelineType::Hour:
return buildForHour( query );
default:
throw DoNotCatchException("WarningData", "unexpected TimelineType");
}
}
bool WarningData::buildForDay( QueryWrapper& query )
{
if ( query.size() == 0ul ) {
return false;
}
while ( query->next() ) {
data.at( static_cast<size_t>( toInt( query[3] ) ) )
.at( static_cast<size_t>( getMinuteGap( toInt( query[4] ) )/10 ) )
.emplace_back( query );
}
return true;
}
bool WarningData::buildForHour( QueryWrapper& query )
{
if ( query.size() == 0ul ) {
return false;
}
while ( query->next() ) {
const int min{ toInt( query[4] ) };
data.at( static_cast<size_t>( getMinuteGap( min )/10 ) )
.at( static_cast<size_t>( min % 10 ) )
.emplace_back( query );
}
return true;
}
void WarningData::checkWarnings( const Warnlist& warnlist )
{
for ( auto& layer1 : data ) {
for ( auto& layer2 : layer1 ) {
std::for_each( layer2.begin(), layer2.end(),
[&warnlist](auto& datum){ datum.checkWarnings(warnlist); } );
}
}
}
int WarningData::insertInChart( std::vector<std::vector<QBarSet*>>& bars ) const
{
switch ( timeline ) {
case TimelineType::Day:
return insertForDay( bars );
case TimelineType::Hour:
return insertForHour( bars );
default:
throw DoNotCatchException("WarningData", "unexpected TimelineType");
}
}
int WarningData::insertForDay( std::vector<std::vector<QBarSet*>>& bars ) const
{
int max_count{ 0 };
for ( int i{0}; i<6; ++i ) {
bars.push_back( std::vector<QBarSet*>() );
bars.back().push_back( new QBarSet("") );
bars.back().push_back( new QBarSet("") );
}
for ( size_t h{0}; h<24ul; ++h ) {
for ( size_t m{0}; m<6ul; ++m ) {
int norm_count{0}, warn_count{0};
for ( const WarningDatum& datum : data.at( h ).at( m ) ) {
datum.hasWarnings() ? ++warn_count : ++norm_count;
}
bars.at( m ).at( 0ul )->append( norm_count );
bars.at( m ).at( 1ul )->append( warn_count );
const int sum_count{ norm_count + warn_count };
if ( sum_count > max_count ) {
max_count = sum_count;
}
}
}
return max_count;
}
int WarningData::insertForHour( std::vector<std::vector<QBarSet*>>& bars ) const
{
int max_count{ 0 };
for ( int i{0}; i<10; ++i ) {
bars.push_back( std::vector<QBarSet*>() );
bars.back().push_back( new QBarSet("") );
bars.back().push_back( new QBarSet("") );
}
for ( size_t g{0ul}; g<6ul; ++g ) {
for ( size_t m{0ul}; m<10ul; ++m ) {
int norm_count{0}, warn_count{0};
for ( const WarningDatum& datum : data.at( g ).at( m ) ) {
datum.hasWarnings() ? ++warn_count : ++norm_count;
}
bars.at( m ).at( 0ul )->append( norm_count );
bars.at( m ).at( 1ul )->append( warn_count );
const int sum_count{ norm_count + warn_count };
if ( sum_count > max_count ) {
max_count = sum_count;
}
}
}
return max_count;
}
void WarningData::insertInTable( QTableWidget*const table, const QColor& warning_color ) const
{
const auto flattened_data{ std::views::join( std::views::join(data) ) };
for ( const WarningDatum& datum : flattened_data ) {
datum.insertInTable( table, warning_color );
}
}

View File

@ -0,0 +1,87 @@
#ifndef LOGDOCTOR__CRAPVIEW__DATATYPES__WARNING_H
#define LOGDOCTOR__CRAPVIEW__DATATYPES__WARNING_H
#include <QString>
#include <vector>
class QueryWrapper;
struct Warnlist;
class QColor;
class QBarSet;
class QTableWidget;
class QTableWidgetItem;
struct WarningDatum final
{
WarningDatum( const QueryWrapper& query );
void checkWarnings( const Warnlist& warnlist );
bool hasWarnings() const noexcept;
void insertInTable( QTableWidget*const table, const QColor& warning_color ) const;
const int year;
const int month;
const int day;
const int hour;
const int minute;
const int second;
const QString protocol;
const QString method;
const QString uri;
const QString query;
const QString response;
const QString user_agent;
const QString client;
const QString cookie;
const QString referer;
const QString bytes_received;
const QString bytes_sent;
const QString time_taken;
private:
std::vector<int> warning_columns;
};
class WarningData final
{
enum class TimelineType {
Hour, Day
};
public:
WarningData() = default;
void setTimelineAsDay();
void setTimelineAsHour();
//! \throw DoNotCatchException
bool buildFromQuery( QueryWrapper& query );
void checkWarnings( const Warnlist& warnlist );
//! \throw DoNotCatchException
int insertInChart( std::vector<std::vector<QBarSet*>>& bars ) const;
void insertInTable( QTableWidget*const table, const QColor& warning_color ) const;
private:
bool buildForDay( QueryWrapper& query );
bool buildForHour( QueryWrapper& query );
int insertForDay( std::vector<std::vector<QBarSet*>>& bars ) const;
int insertForHour( std::vector<std::vector<QBarSet*>>& bars ) const;
TimelineType timeline;
std::vector<std::vector<std::vector<WarningDatum>>> data;
};
#endif // LOGDOCTOR__CRAPVIEW__DATATYPES__WARNING_H

View File

@ -0,0 +1,7 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/fetcher.h
${CMAKE_CURRENT_SOURCE_DIR}/fetcher.cpp
)
add_subdirectory(fetcher)

View File

@ -0,0 +1,563 @@
#include "fetcher.h"
#include "fetcher/date_time.h"
#include "fetcher/queries.h"
#include "fetcher/utilities.h"
#include "modules/crapview/datatypes/fwd.h"
#include "utilities/arrays.h"
#include "utilities/printables.h"
#include "utilities/strings.h"
#include <map>
#include <vector>
using namespace FetcherPrivate;
void Fetcher::setDialogLevel( const DialogsLevel new_level ) noexcept
{
this->dialog_level = new_level;
}
void Fetcher::setDbPath( std::string&& path ) noexcept
{
this->db_path = std::move(path);
this->db_name = QString::fromStdString( this->db_path.substr( this->db_path.find_last_of( '/' ) + 1ul ) );
}
const QString& Fetcher::getDbField( const LogField fld ) const
{
return this->LogFields_to_DbFields.at( fld );
}
const QString& Fetcher::getDbField( QStringView tr_fld ) const
{
for ( const auto& [id,str] : this->FIELDS ) {
if ( TR::tr(str.c_str()) == tr_fld ) {
return this->LogFields_to_DbFields.at( id );
}
}
throw DatabaseException( std::move(QStringLiteral("Unexpected DbField: ").append(tr_fld)) );
}
// get a fresh map of available dates
void Fetcher::fetchAllDates( std::optional<database_dates_t>& result ) noexcept
{
database_dates_t dates{ // std::unordered_map<int, std::unordered_map<int, std::unordered_map<int, std::vector<int>>>>
{WS_APACHE, {}}, {WS_NGINX, {}}, {WS_IIS, {}}
};
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Data, DB_READONLY ) };
db.open( this->db_path, this->dialog_level==DL_EXPLANATORY );
// recursively query years, months and days for every WebServer
static const std::vector<std::tuple<WebServer, QString>> tables{
std::make_tuple( WS_APACHE, QStringLiteral("apache") ),
std::make_tuple( WS_NGINX, QStringLiteral("nginx") ),
std::make_tuple( WS_IIS, QStringLiteral("iis") )
};
for ( const auto& [ws,tbl] : tables ) {
QueryWrapper query{ db.getQuery() };
QueryFactory::allDates( query, tbl );
query();
auto& years = dates.at( ws );
while ( query->next() ) {
years.try_emplace( toInt( query[0] ), std::map<int, std::vector<int>>{} )
.first->second
.try_emplace( toInt( query[1] ), std::vector<int>{} )
.first->second
.emplace_back( toInt( query[2] ) );
}
}
result.emplace( std::move(dates) );
}
// get daytime values for the warnings
void Fetcher::fetchWarningsData( std::optional<WarningData>& result, QStringView web_server, const DateTime& date ) const
{
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Data, DB_READONLY ) };
db.open( this->db_path, this->dialog_level==DL_EXPLANATORY );
QueryWrapper query{ db.getQuery() };
QueryFactory::warningsData( query, web_server, date );
query();
WarningData data;
if ( date.isHourValid() ) {
data.setTimelineAsHour();
} else {
data.setTimelineAsDay();
}
if ( data.buildFromQuery( query ) ) {
result.emplace( std::move(data) );
}
}
// get day-time values for the time-taken field
void Fetcher::fetchSpeedData( std::optional<SpeedData>& result, QStringView web_server, const DateTime& date, QStringView protocol_f, QStringView method_f, QStringView uri_f, QStringView query_f, QStringView response_f, const qint64 time_interval ) const
{
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Data, DB_READONLY ) };
db.open( this->db_path, this->dialog_level==DL_EXPLANATORY );
QueryWrapper query{ db.getQuery() };
QueryFactory::speedData( query, web_server, date, protocol_f, method_f, uri_f, query_f, response_f );
query();
TimeManager time{ date.toTimeManager( time_interval ) };
SpeedData data;
if ( data.buildFromQuery( query, std::move(time) ) ) {
result.emplace( std::move(data) );
}
}
// get, group and count identical items of a specific field in a date
void Fetcher::fetchCountsData( std::optional<CountData>& result, QStringView web_server, const DateTime& date, QStringView log_field ) const
{
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Data, DB_READONLY ) };
db.open( this->db_path, this->dialog_level==DL_EXPLANATORY );
QueryWrapper query{ db.getQuery() };
const QString& field{ this->getDbField( log_field ) };
QueryFactory::countData( query, web_server, field, date );
query();
CountData data;
if ( data.buildFromQuery( query ) ) {
result.emplace( std::move(data) );
}
}
// get and count items with a 10 minutes gap for every hour of the day
void Fetcher::fetchDaytimeData( std::optional<DaytimeData>& result, QStringView web_server, const DateTime& from_date, DateTime to_date, const LogField log_field_, QStringView field_filter ) const
{
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Data, DB_READONLY ) };
db.open( this->db_path, this->dialog_level==DL_EXPLANATORY );
if ( ! to_date.isValid() ) {
to_date = from_date;
}
const QString& log_field{ this->getDbField( log_field_ ) };
int n_days { 0 };
int n_months { from_date.countMonths( to_date ) };
DaytimeData data;
if ( n_months == 1 ) {
QueryWrapper query{ db.getQuery() };
QueryFactory::daytimeDataPartialMonth( query, web_server, from_date, to_date, log_field, field_filter );
query();
n_days += data.buildFromQuery( query );
} else {
int year { from_date.getYear() };
int month { from_date.getMonth() };
const QString query_filter{
!field_filter.isEmpty() ? QStringLiteral(R"( AND "%1"%2)").arg( log_field, field_filter ) : QString()
};
for ( int m{1}; m<=n_months; ++m ) {
QueryWrapper query{ db.getQuery() };
if ( m == 1 ) {
QueryFactory::daytimeDataFirstMonth( query, web_server, year, month, from_date.getDay(), query_filter );
} else if ( m == n_months ) {
QueryFactory::daytimeDataLastMonth( query, web_server, year, month, to_date.getDay(), query_filter );
} else {
QueryFactory::daytimeDataEntireMonth( query, web_server, year, month, query_filter );
}
query();
n_days += data.buildFromQuery( query );
if ( ++month > 12 ) {
month = 1;
++year;
}
}
}
if ( n_days == 0 ) {
return;
}
data.adjustCounts( n_days );
result.emplace( std::move(data) );
}
// get and count how many times a specific item value brought to another
void Fetcher::fetchRelationalDataDay( std::optional<RelationalData>& result, QStringView web_server, const DateTime& date, const LogField log_field_1_, QStringView field_filter_1, const LogField log_field_2_, QStringView field_filter_2 ) const
{
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Data, DB_READONLY ) };
db.open( this->db_path, this->dialog_level==DL_EXPLANATORY );
const QString& log_field_1{ this->getDbField( log_field_1_ ) };
const QString& log_field_2{ this->getDbField( log_field_2_ ) };
QueryWrapper query{ db.getQuery() };
QueryFactory::relationalDataSingleDay( query, web_server, date, log_field_1, field_filter_1, log_field_2, field_filter_2 );
query();
const qint64 time_interval_mins{ 20 };
const qint64 time_interval_secs{ time_interval_mins * 60 };
TimeManager time{ date.toTimeManager( time_interval_secs ) };
RelationalData data;
if ( data.buildFromQuery( query, std::move(time) ) ) {
result.emplace( std::move(data) );
}
}
void Fetcher::fetchRelationalDataPeriod( std::optional<RelationalData>& result, QStringView web_server, const DateTime& from_date, DateTime to_date, const LogField log_field_1_, QStringView field_filter_1, const LogField log_field_2_, QStringView field_filter_2 ) const
{
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Data, DB_READONLY ) };
db.open( this->db_path, this->dialog_level==DL_EXPLANATORY );
if ( ! to_date.isValid() ) {
to_date = from_date;
}
const QString& log_field_1{ this->getDbField( log_field_1_ ) };
const QString& log_field_2{ this->getDbField( log_field_2_ ) };
const int n_months{ from_date.countMonths( to_date ) };
DateManager date{ from_date.toDateManager() };
const auto last_date{ to_date.toQDate().addDays( 1 ) };
if ( n_months == 1 ) {
// 1 month, no need to loop
QueryWrapper query{ db.getQuery() };
QueryFactory::relationalDataPartialMonth( query, web_server, from_date, to_date, log_field_1, field_filter_1, log_field_2, field_filter_2 );
RelationalData data;
if ( data.buildFromQuery( query, std::move(date), std::move(last_date) ) ) {
result.emplace( std::move(data) );
}
} else {
RelationalData data;
data.reserveSpace( from_date.countDays( to_date ) * 2 );
bool data_found{ false };
int year { from_date.getYear() };
int month { from_date.getMonth() };
const QString query_filters{ QStringLiteral("%1%2").arg(
!field_filter_1.isEmpty() ? QStringLiteral(R"( AND "%1"%2)").arg( log_field_1, field_filter_1 ) : QString(),
!field_filter_2.isEmpty() ? QStringLiteral(R"( AND "%1"%2)").arg( log_field_2, field_filter_2 ) : QString())
};
data.appendFirstEmpty( date );
for ( int m{1}; m<=n_months; ++m ) {
const int first_day{ m==1 ? from_date.getDay() : 1 };
const int last_day{ m==n_months ? to_date.getDay() : getMonthDays( year, month ) };
QueryWrapper query{ db.getQuery() };
if ( m == 1 ) {
QueryFactory::relationalDataFirstMonth( query, web_server, year, month, from_date.getDay(), query_filters );
} else if ( m == n_months ) {
QueryFactory::relationalDataLastMonth( query, web_server, year, month, to_date.getDay(), query_filters );
} else {
QueryFactory::relationalDataEntireMonth( query, web_server, year, month, query_filters );
}
query();
const QDate initial_date{ year, month, first_day };
const QDate final_date{ year, month, last_day };
data_found |= data.appendFromQuery( query, date, std::move(initial_date), std::move(final_date), last_day );
// increase the month
if ( ++month > 12 ) {
month = 1;
++year;
}
}
data.appendLastEmpty( date, std::move(last_date) );
if ( data_found ) {
result.emplace( std::move(data) );
}
}
}
void Fetcher::fetchGlobalsData( std::optional<GlobalsData>& result, QStringView web_server, const stats_dates_t& dates ) const
{
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Data, DB_READONLY ) };
db.open( this->db_path, this->dialog_level==DL_EXPLANATORY );
bool no_data{ true };
int max_date_year{0}, max_date_month{0}, max_date_day{0};
double n_days{0.0};
size_t max_date_count{0};
std::array<double, 7> week_days_count{ 0, 0, 0, 0, 0, 0, 0 };
GlobalsData data;
const auto week_day_from{
[](const int y, const int m, const int d)->size_t
{ return static_cast<size_t>( QDate(y,m,d).dayOfWeek()-1 ); }
};
const auto update_perf{
[](Perfs& perf, const int val)
{
if ( val >= 0 ) {
if ( const size_t v{static_cast<size_t>(val)}; v > 0ul) [[likely]] {
if ( v > perf.max ) {
perf.max = v;
}
perf.total += v;
}
++ perf.count;
}
}
};
for ( const auto& [year, dates_] : dates ) {
for ( const auto& [month, dates__] : dates_ ) {
int d{-1}, h{-1}, tt{-1}, bs{-1}, br{-1},
day{-1}, hour{-1};
double hour_count{0};
size_t day_count{0};
QString protocol, method, uri, user_agent;
QueryWrapper query{ db.getQuery() };
QueryFactory::globalsData( query, web_server, year, month );
query();
if ( query.size() == 0ul ) {
// no data in this month
continue;
}
no_data &= false;
while ( query->next() ) {
// day
if ( ! query[0].isNull() ) {
d = toInt( query[0] );
}
// hour
if ( ! query[1].isNull() ) {
h = toInt( query[1] );
}
// protocol
if ( ! query[2].isNull() ) {
protocol = toString( query[2] );
}
// method
if ( ! query[3].isNull() ) {
method = toString( query[3] );
}
// uri
if ( ! query[4].isNull() ) {
uri = toString( query[4] );
}
// user agent
if ( ! query[5].isNull() ) {
user_agent = toString( query[5] );
}
// time taken
if ( ! query[6].isNull() ) {
tt = toInt( query[6] );
}
// bytes sent
if ( ! query[7].isNull() ) {
bs = toInt( query[7] );
}
// bytes received
if ( ! query[8].isNull() ) {
br = toInt( query[8] );
}
// process the day count
if ( d > 0 ) {
if ( day == -1 ) {
day = d;
}
if ( d == day ) {
++ day_count;
} else {
++ n_days;
// sum the day count to the total count
data.req_count += day_count;
// sum the day count to the relative day of the week count
const size_t week_day{ week_day_from(year,month,day) };
data.traf.day[ week_day ] += static_cast<double>(day_count);
++ week_days_count[ week_day ];
// check the max date count
if ( day_count > max_date_count ) {
max_date_count = day_count;
max_date_year = year;
max_date_month = month;
max_date_day = day;
}
day_count = 1;
day = d;
}
}
// process the hour count
if ( h >= 0 ) {
if ( hour == -1 ) {
hour = h;
}
if ( h == hour ) {
++ hour_count;
} else {
data.traf.hour[ hour ] += hour_count;
hour_count = 1;
hour = h;
}
}
// sum the time taken
update_perf( data.perf.time_taken, tt );
// sum the bytes sent
update_perf( data.perf.bytes_sent, bs );
// sum the bytes received
update_perf( data.perf.bytes_recv, br );
// process the protocol
if ( ! protocol.isEmpty() ) {
++ data.recurs.protocol[ protocol ];
}
// process the method
if ( ! method.isEmpty() ) {
++ data.recurs.method[ method ];
}
// process the uri
if ( ! uri.isEmpty() ) {
++ data.recurs.uri[ uri ];
}
// process the user-agent
if ( ! user_agent.isEmpty() ) {
++ data.recurs.user_agent[ user_agent ];
}
}
// complete the remaining stats
// append the last hour
if ( hour >= 0 ) {
data.traf.hour[ hour ] += hour_count;
}
// sum the day count to the total count
data.req_count += day_count;
// sum the day count to the relative day of the week count
const size_t week_day{ week_day_from(year,month,day) };
data.traf.day[ week_day ] += static_cast<double>(day_count);
++ week_days_count[ week_day ];
// check the max date count
if ( day_count > max_date_count ) {
max_date_count = day_count;
max_date_year = year;
max_date_month = month;
max_date_day = day;
}
}
}
if ( no_data ) {
return;
}
// finally process some of the values
// process the hours of the day
if ( n_days > 0.0 ) {
std::transform( data.traf.hour.cbegin(), data.traf.hour.cend(), data.traf.hour.begin(),
[n_days](const double count){ return count / n_days; } );
}
// process the day of the week
/*std::ranges::for_each( std::views::zip( data.traf.day, week_days_count ),
[](auto tc){ if (auto& [t,c]{tc}; c>0.0){ t/=c; } });*/
for ( auto [total,count] : ArrayOps::zip( data.traf.day, week_days_count ) ) {
if ( count > 0.0 ) {
total /= count;
}
}
// make the max-date tuple
data.traf.date = std::make_tuple(
PrintSec::printableDate( max_date_year, max_date_month, max_date_day ),
QString::number( max_date_count ) );
result.emplace( std::move(data) );
}

View File

@ -1,26 +1,32 @@
#ifndef LOGDOCTOR__CRAPVIEW__MODULES__QUERY_H
#define LOGDOCTOR__CRAPVIEW__MODULES__QUERY_H
#include "lib.h"
#ifndef LOGDOCTOR__CRAPVIEW__MODULES__FETCHER_H
#define LOGDOCTOR__CRAPVIEW__MODULES__FETCHER_H
#include "main_lib.h"
#include "modules/shared.h"
#include "modules/crapview/lib.h"
#include "modules/crapview/datatypes/fwd.h"
#include <unordered_map>
#include <optional>
class DbQuery final
class DateTime;
//! Fetcher
/*!
Fetches data for the statistics from the database
*/
class Fetcher final
{
CRAPVIEW_DATA_TYPEDEFS
public:
explicit DbQuery() noexcept {}
Q_DISABLE_COPY_MOVE(DbQuery)
explicit Fetcher() noexcept {}
Q_DISABLE_COPY_MOVE(Fetcher)
// log fields enums to log fields strings
const std::unordered_map<LogField, std::string> FIELDS{
@ -64,24 +70,6 @@ public:
/*const std::string getDbPath( const int web_server );*/
//! Returns the number of months in a given period
/*!
\overload const int getMonthsCount(const int& from_year, const int& from_month, const int& to_year, const int& to_month)
\param from_year The initial year
\param from_month The initial month
\param to_year The final Year
\param to_month The final month
\return The number of months in the period
\throw ConversionException
\throw DateTimeException
*/
int countMonths(
QStringView from_year,
QStringView from_month,
QStringView to_year,
QStringView to_month
) const;
//! Refreshes the dates which are available in the database
/*!
@ -89,28 +77,22 @@ public:
\throw VoidException
\throw ConversionException
*/
void refreshDates( std::optional<database_dates_t>& result ) noexcept;
void fetchAllDates( std::optional<database_dates_t>& result ) noexcept;
//! Retrieves the data needed for the Warnings statistics
/*!
\param result Holds the data only if the operation completed succssfully
\param web_server The ID of the Web Server to use
\param year_ The year
\param month_ The month
\param day_ The day
\param hour_ The hour
\param date The date to use for the wuery (may contain the hour)
\throw VoidException
\throw ConversionException
\throw DateTimeException
*/
void getWarningsData(
std::optional<stats_warn_items_t>& result,
void fetchWarningsData(
std::optional<WarningData>& result,
QStringView web_server,
QStringView year_,
QStringView month_,
QStringView day_,
QStringView hour_
const DateTime& date
) const;
@ -118,30 +100,28 @@ public:
/*!
\param result Holds the data only if the operation completed succssfully
\param web_server The ID of the Web Server to use
\param year_ The year
\param month_ The month
\param day_ The day
\param date The date to use for the wuery
\param protocol_f The filter for the Protocol field
\param method_f The filter for the Method field
\param uri_f The filter for the URI field
\param query_f The filter for the Query field
\param response_f The filter for the Response field
\param time_interval The time interval used to group the values
\throw VoidException
\throw CrapviewException
\throw ConversionException
\throw DateTimeException
*/
void getSpeedData(
std::optional<stats_speed_items_t>& result,
void fetchSpeedData(
std::optional<SpeedData>& result,
QStringView web_server,
QStringView year_,
QStringView month_,
QStringView day_,
const DateTime& date,
QStringView protocol_f,
QStringView method_f,
QStringView uri_f,
QStringView query_f,
QStringView response_f
QStringView response_f,
const qint64 time_interval
) const;
@ -149,20 +129,16 @@ public:
/*!
\param result Holds the data only if the operation completed succssfully
\param web_server The ID of the Web Server to use
\param year The year
\param month The month
\param day The day
\param date The date to use for the wuery
\param log_field The log field
\throw VoidException
\throw CrapviewException
\throw DateTimeException
*/
void getItemsCount(
std::optional<stats_count_items_t>& result,
void fetchCountsData(
std::optional<CountData>& result,
QStringView web_server,
QStringView year,
QStringView month,
QStringView day,
const DateTime& date,
QStringView log_field
) const;
@ -171,12 +147,8 @@ public:
/*!
\param result Holds the data only if the operation completed succssfully
\param web_server The ID of the Web Server to use
\param from_year_ The initial year
\param from_month_ The initial month
\param from_day_ The initial day
\param to_year_ The final year
\param to_month_ The final month
\param to_day_ The final day
\param from_date The initial date to use for the wuery
\param date The final date to use for the wuery (may be invalid)
\param log_field_ The log field to filter
\param field_filter The filter to apply
\throw VoidException
@ -184,11 +156,11 @@ public:
\throw ConversionException
\throw DateTimeException
*/
void getDaytimeCounts(
std::optional<stats_day_items_t>& result,
void fetchDaytimeData(
std::optional<DaytimeData>& result,
QStringView web_server,
QStringView from_year_, QStringView from_month_, QStringView from_day_,
QStringView to_year_, QStringView to_month_, QStringView to_day_,
const DateTime& from_date,
DateTime to_date,
const LogField log_field_, QStringView field_filter
) const;
@ -198,9 +170,7 @@ public:
Used when querying a single day
\param result Holds the data only if the operation completed succssfully
\param web_server The ID of the Web Server to use
\param year_ The year
\param month_ The month
\param day_ The day
\param date The date to use for the wuery
\param log_field_1_ The first log field to filter
\param field_filter_1 The filter to apply to the first field
\param log_field_2_ The second log field to filter
@ -211,10 +181,10 @@ public:
\throw DateTimeException
\see getRelationalCountsPeriod()
*/
void getRelationalCountsDay(
std::optional<stats_relat_items_t>& result,
void fetchRelationalDataDay(
std::optional<RelationalData>& result,
QStringView web_server,
QStringView year_, QStringView month_, QStringView day_,
const DateTime& date,
const LogField log_field_1_, QStringView field_filter_1,
const LogField log_field_2_, QStringView field_filter_2
) const;
@ -224,12 +194,8 @@ public:
Used when querying a period of time
\param result Holds the data only if the operation completed succssfully
\param web_server The ID of the Web Server to use
\param from_year_ The initial year
\param from_month_ The initial month
\param from_day_ The initial day
\param to_year_ The final year
\param to_month_ The final month
\param to_day_ The final day
\param from_date The date to use for the wuery
\param to_date The date to use for the wuery
\param log_field_1_ The first log field to filter
\param field_filter_1 The filter to apply to the first field
\param log_field_2_ The second log field to filter
@ -240,11 +206,11 @@ public:
\throw DateTimeException
\see getRelationalCountsDay()
*/
void getRelationalCountsPeriod(
std::optional<stats_relat_items_t>& result,
void fetchRelationalDataPeriod(
std::optional<RelationalData>& result,
QStringView web_server,
QStringView from_year_, QStringView from_month_, QStringView from_day_,
QStringView to_year_, QStringView to_month_, QStringView to_day_,
const DateTime& from_date,
DateTime to_date,
const LogField log_field_1_, QStringView field_filter_1,
const LogField log_field_2_, QStringView field_filter_2
) const;
@ -259,7 +225,7 @@ public:
\throw CrapviewException
\throw ConversionException
*/
void getGlobalCounts(
void fetchGlobalsData(
std::optional<GlobalsData>& result,
QStringView web_server,
const stats_dates_t& dates
@ -268,17 +234,6 @@ public:
private:
// leave TR::tr here to make them appear in the translatable phrases
const std::string MSG_ERR_UNX_WS{ TR::tr("Unexpected WebServer").toStdString() };
const std::string MSG_ERR_PROCESSING{ TR::tr("An error occured while processing").toStdString() };
const std::string MSG_ERR_PROCESSING_DATES{ TR::tr("An error occured while processing dates").toStdString() };
const std::string MSG_ERR_PARSING_YMD{ TR::tr("An error occured while parsing %1 from the database").toStdString() };
const std::string WORD_YEARS{ TR::tr("Years").toStdString() };
const std::string WORD_MONTHS{ TR::tr("Months").toStdString() };
const std::string WORD_DAYS{ TR::tr("Days").toStdString() };
const std::string MSG_RESPONSIBLE_VALUE{ TR::tr("Value responsible for the error").toStdString() };
const std::string MSG_TABLE_NAME{ TR::tr("Database table name").toStdString() };
// quantity of information to display throught dialogs
DialogsLevel dialog_level{ DL_NORMAL };
@ -317,66 +272,7 @@ private:
\throw CrapviewException
*/
const QString& getDbField( QStringView tr_fld ) const;
//! Returns the minute gap for the given minute with the given gap
/*!
\param minute The minute of the hour
\param gap The gap used to split the hour
\return The gap index
\throw DateTimeException
*/
static int getMinuteGap( const int minute, const int gap=10 );
//! Returns the number of days for a given month
/*!
\param year The year, used to handle leap years
\param month The month
\return The number of days
\throw DateTimeException
*/
static int getMonthDays( const int year, const int month );
//! Returns the month number in the year
/*!
\param month_str The month
\return The month number
\throw DateTimeException
*/
int getMonthNumber( QStringView month_str ) const;
//! Returns the number of days in a given period
/*!
\param from_year The initial year
\param from_month The initial month
\param from_day The initial day
\param to_year The final Year
\param to_month The final month
\param to_day The final day
\return The number of days
\throw DateTimeException
*/
static int countDays(
const int from_year, const int from_month, const int from_day,
const int to_year, const int to_month, const int to_day
);
//! Returns the number of months in a given period
/*!
\param from_year The initial year
\param from_month The initial month
\param to_year The final Year
\param to_month The final month
\return The number of months in the period
*/
static int countMonths(
const int from_year, const int from_month,
const int to_year, const int to_month
) noexcept;
};
#endif // LOGDOCTOR__CRAPVIEW__MODULES__QUERY_H
#endif // LOGDOCTOR__CRAPVIEW__MODULES__FETCHER_H

View File

@ -0,0 +1,7 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/date_time.h
${CMAKE_CURRENT_SOURCE_DIR}/queries.h
${CMAKE_CURRENT_SOURCE_DIR}/utilities.h
${CMAKE_CURRENT_SOURCE_DIR}/utilities.cpp
)

View File

@ -0,0 +1,240 @@
#ifndef LOGDOCTOR__CRAPVIEW__MODULES__FETCHER__DATE_TIME_H
#define LOGDOCTOR__CRAPVIEW__MODULES__FETCHER__DATE_TIME_H
#include "utilities.h"
#include "modules/exceptions.h"
#include "modules/dialogs.h"
#include "modules/database/database.h"
#include <QDateTime>
namespace FetcherPrivate
{
//! IManager
/*!
Interface for the TimeManager and DateManager classes
*/
struct IManager
{
virtual ~IManager() = default;
virtual qint64 intervalTimestamp() const = 0;
};
//! TimeManager
/*!
Manages the time and the time interval used
to group the query data for the stats
*/
class TimeManager final : public IManager
{
QDateTime time;
QDateTime time_interval_beg;
QDateTime time_interval_end;
const qint64 time_interval_step;
public:
explicit TimeManager( const int year, const int month, const int day, const qint64 step )
: time{QDate(year,month,day),QTime(0,0,0)}
, time_interval_beg{time}
, time_interval_end{time.addSecs(step)}
, time_interval_step{step}
{}
Q_DISABLE_COPY(TimeManager)
//! Returns the time interval step, in seconds
inline qint64 intervalStep() const noexcept
{
return time_interval_step;
}
//! Returns the current time
inline QTime currentTime() const
{
return time.time();
}
//! Returns the timestamp of the current interval, in milliseconds since epoch
inline qint64 intervalTimestamp() const override
{
return time_interval_beg.toMSecsSinceEpoch();
}
//! Sets the hour and the minute from the query data
inline void setHourMinute( const QueryWrapper& query )
{
time.setTime( QTime( toInt(query[0]), toInt(query[1]), 0 ) );
}
//! Sets the hour, the minute and the second from the query data
inline void setHourMinuteSecond( const QueryWrapper& query )
{
time.setTime( QTime( toInt(query[0]), toInt(query[1]), toInt(query[2]) ) );
}
//! Sets the time to the given time
inline void setTime( const QTime&& new_time )
{
time.setTime( new_time );
}
//! Sets the interval beginning time and date to the next midnight
inline void setIntervalToNextMidnight()
{
time_interval_beg.setTime( QTime(23,59,59) );
time_interval_beg.setSecsSinceEpoch( time_interval_beg.toSecsSinceEpoch() + 1 );
time_interval_end = time_interval_beg.addSecs( time_interval_step );
}
//! Returns whether the current time is after the beginning of the time interval
inline bool isAfterIntervalBegin() const
{
return time > time_interval_beg;
}
//! Returns whether the time is between the current time interval's begin and eng
inline bool inCurrentInterval() const
{
return time_interval_beg <= time && time < time_interval_end;
}
//! Increases the time interval by one step
inline void increaseInterval()
{
time_interval_beg.setSecsSinceEpoch( time_interval_beg.toSecsSinceEpoch() + time_interval_step );
time_interval_end.setSecsSinceEpoch( time_interval_end.toSecsSinceEpoch() + time_interval_step );
}
//! Increases the time interval until it's one step below the current time
/*!
\throw DoNotCatchException
*/
inline void increaseIntervalUntil()
{
do { increaseInterval(); }
while ( !inCurrentInterval() );
assertValid();
decreaseInterval();
}
private:
//! Decreases the time interval by one step
inline void decreaseInterval()
{
time_interval_beg.setSecsSinceEpoch( time_interval_beg.toSecsSinceEpoch() - time_interval_step );
time_interval_end.setSecsSinceEpoch( time_interval_end.toSecsSinceEpoch() - time_interval_step );
}
//! Asserts that the current time is after the beginning of the current interval
/*!
\throw DoNotCatchException
*/
inline void assertValid() const
{
if ( time < time_interval_beg ) {
throw DoNotCatchException{"Unexpected TimeManager state", "time interval exceeds current time"};
}
}
};
//! DateManager
/*!
Manages the date used
to group the query data for the stats
*/
class DateManager final : public IManager
{
QDateTime date;
QDateTime date_interval;
public:
explicit DateManager( const int year, const int month, const int day )
: date{QDate(year,month,day),QTime(0,0,0)}
, date_interval{date}
{}
Q_DISABLE_COPY(DateManager)
//! Returns the interval's timestamp in milliseconds since epoch
inline qint64 intervalTimestamp() const override
{
return date_interval.toMSecsSinceEpoch();
}
//! Sets the day from the query data
inline void setDay( const QueryWrapper& query )
{
date.setDate( QDate{date.date().year(), date.date().month(), toInt(query[0])} );
}
//! Sets the date to the given date
inline void setDate( const QDate&& new_date )
{
date.setDate( new_date );
}
//! Sets the date to the given date
inline void setIntervalDate( const QDate&& new_date )
{
date_interval.setDate( new_date );
}
//! Returns whether the date fits in the current time interval
inline bool inCurrentInterval() const
{
return date == date_interval;
}
//! Returns whether the time interval is before the given day
inline bool isIntervalBeforeDay( const int day ) const
{
return date_interval.date().day() < day;
}
//! Decreases the time interval by one step
inline void decreaseInterval()
{
date_interval = date_interval.addDays( -1 );
}
//! Increases the time interval by one step
inline void increaseInterval()
{
date_interval = date_interval.addDays( 1 );
}
//! Increases the time interval until it's one step below the current time
/*!
\throw DoNotCatchException
*/
inline void increaseIntervalUntil()
{
do { increaseInterval(); }
while ( !inCurrentInterval() );
assertValid();
decreaseInterval();
}
private:
//! Asserts that the current date is after the beginning of the current interval
/*!
\throw DoNotCatchException
*/
inline void assertValid() const
{
if ( date < date_interval ) {
throw DoNotCatchException{"Unexpected DateManager state", "date interval exceeds current date"};
}
}
};
} // namespace FetcherPrivate
#endif // LOGDOCTOR__CRAPVIEW__MODULES__FETCHER__DATE_TIME_H

View File

@ -0,0 +1,228 @@
#ifndef LOGDOCTOR__CRAPVIEW__MODULES__FETCHER__QUERIES_H
#define LOGDOCTOR__CRAPVIEW__MODULES__FETCHER__QUERIES_H
#include "modules/database/database.h"
#include "modules/crapview/utilities/datetime.h"
namespace QueryFactory
{
void allDates( QueryWrapper& query, QStringView table )
{
query << QStringLiteral(R"(SELECT DISTINCT "year", "month", "day" FROM "%1" ORDER BY "year", "month", "day" ASC;)")
.arg( table );
}
void warningsData( QueryWrapper& query, QStringView web_server, const DateTime& date )
{
query << QStringLiteral(R"(SELECT * FROM "%1" WHERE "year"=%2 AND "month"=%3 AND "day"=%4)")
.arg( web_server )
.arg( date.getYear() )
.arg( date.getMonth() )
.arg( date.getDay() );
if ( date.isHourValid() ) {
query << QStringLiteral(R"( AND "hour"=%1 ORDER BY "minute","second" ASC;)")
.arg( date.getHour() );
} else {
query << R"( ORDER BY "hour","minute","second" ASC;)";
}
}
void speedData( QueryWrapper& query, QStringView web_server, const DateTime& date, QStringView protocol_f, QStringView method_f, QStringView uri_f, QStringView query_f, QStringView response_f )
{
query << QStringLiteral(R"(SELECT "hour","minute","second","time_taken","uri","query","method","protocol","response" FROM "%1" WHERE "year"=%2 AND "month"=%3 AND "day"=%4 AND "time_taken" IS NOT NULL)")
.arg( web_server )
.arg( date.getYear() )
.arg( date.getMonth() )
.arg( date.getDay() );
if ( ! protocol_f.isEmpty() ) {
query << QStringLiteral(R"( AND "protocol")").append( protocol_f );
}
if ( ! method_f.isEmpty() ) {
query << QStringLiteral(R"( AND "method")").append( method_f );
}
if ( ! uri_f.isEmpty() ) {
query << QStringLiteral(R"( AND "uri")").append( uri_f );
}
if ( ! query_f.isEmpty() ) {
query << QStringLiteral(R"( AND "query")").append( query_f );
}
if ( ! response_f.isEmpty() ) {
query << QStringLiteral(R"( AND "response")").append( response_f );
}
query << R"( ORDER BY "hour","minute","second" ASC;)";
}
void countData( QueryWrapper& query, QStringView web_server, QStringView field, const DateTime& date )
{
query << QStringLiteral(R"(SELECT "%1" FROM "%2" WHERE "%3" IS NOT NULL AND "year"=%4 AND "month"=%5 AND "day"=%6;)")
.arg( field, web_server, field )
.arg( date.getYear() )
.arg( date.getMonth() )
.arg( date.getDay() )
.replace(QChar('\''),QLatin1String("''"));
}
void daytimeDataPartialMonth( QueryWrapper& query, QStringView web_server, const DateTime& from_date, const DateTime& to_date, QStringView field, QStringView field_filter )
{
query << QStringLiteral(R"(SELECT "day", "hour", "minute" FROM "%1" WHERE "year"=%2 AND "month"=%3 AND "day">=%4 AND "day"<=%5)")
.arg( web_server )
.arg( from_date.getYear() )
.arg( from_date.getMonth() )
.arg( from_date.getDay() )
.arg( to_date.getDay() );
if ( ! field_filter.isEmpty() ) {
query << QStringLiteral(R"( AND "%1"%2)").arg( field, field_filter );
}
query << ";";
}
void daytimeDataFirstMonth( QueryWrapper& query, QStringView web_server, const int year, const int month, const int day, QStringView field_filter )
{
query << QStringLiteral(R"(SELECT "day", "hour", "minute" FROM "%1" WHERE "year"=%2 AND "month"=%3)")
.arg( web_server )
.arg( year ).arg( month );
query << QStringLiteral(R"( AND "day"<=%1)").arg( day );
if ( ! field_filter.isEmpty() ) {
query << field_filter;
}
query << ";";
}
void daytimeDataLastMonth( QueryWrapper& query, QStringView web_server, const int year, const int month, const int day, QStringView field_filter )
{
query << QStringLiteral(R"(SELECT "day", "hour", "minute" FROM "%1" WHERE "year"=%2 AND "month"=%3)")
.arg( web_server )
.arg( year ).arg( month );
query << QStringLiteral(R"( AND "day">=%1)").arg( day );
if ( ! field_filter.isEmpty() ) {
query << field_filter;
}
query << ";";
}
void daytimeDataEntireMonth( QueryWrapper& query, QStringView web_server, const int year, const int month, QStringView field_filter )
{
query << QStringLiteral(R"(SELECT "day", "hour", "minute" FROM "%1" WHERE "year"=%2 AND "month"=%3)")
.arg( web_server )
.arg( year ).arg( month );
if ( ! field_filter.isEmpty() ) {
query << field_filter;
}
query << ";";
}
void relationalDataSingleDay( QueryWrapper& query, QStringView web_server, const DateTime& date, QStringView field_1, QStringView field_filter_1, QStringView field_2, QStringView field_filter_2 )
{
query << QStringLiteral(R"(SELECT "hour", "minute" FROM "%1" WHERE "year"=%2 AND "month"=%3 AND "day"=%4)")
.arg( web_server )
.arg( date.getYear() )
.arg( date.getMonth() )
.arg( date.getDay() );
if ( ! field_filter_1.isEmpty() ) {
query << QStringLiteral(R"( AND "%1"%2)").arg( field_1, field_filter_1 );
}
if ( ! field_filter_2.isEmpty() ) {
query << QStringLiteral(R"( AND "%1"%2)").arg( field_2, field_filter_2 );
}
query << QStringLiteral(R"( ORDER BY "hour","minute" ASC;)");
}
void relationalDataPartialMonth( QueryWrapper& query, QStringView web_server, const DateTime& from_date, const DateTime& to_date, QStringView field_1, QStringView field_filter_1, QStringView field_2, QStringView field_filter_2 )
{
query << QStringLiteral(R"(SELECT "day" FROM "%1" WHERE "year"=%2 AND "month"=%3 AND "day">=%4 AND "day"<=%5)")
.arg( web_server )
.arg( from_date.getYear() )
.arg( from_date.getMonth() )
.arg( from_date.getDay() )
.arg( to_date.getDay() );
if ( ! field_filter_1.isEmpty() ) {
query << QStringLiteral(R"( AND "%1"%2)").arg( field_1, field_filter_1 );
}
if ( ! field_filter_2.isEmpty() ) {
query << QStringLiteral(R"( AND "%1"%2)").arg( field_2, field_filter_2 );
}
query << R"( ORDER BY "day" ASC;)";
query();
}
void relationalDataFirstMonth( QueryWrapper& query, QStringView web_server, const int year, const int month, const int day, QStringView fields_filters )
{
query << QStringLiteral(R"(SELECT "day" FROM "%1" WHERE "year"=%2 AND "month"=%3)")
.arg( web_server )
.arg( year ).arg( month );
query << QStringLiteral(R"( AND "day">=%1)").arg( day );
if ( ! fields_filters.isEmpty() ) {
query << fields_filters;
}
query << R"( ORDER BY "day" ASC;)";
}
void relationalDataLastMonth( QueryWrapper& query, QStringView web_server, const int year, const int month, const int day, QStringView fields_filters )
{
query << QStringLiteral(R"(SELECT "day" FROM "%1" WHERE "year"=%2 AND "month"=%3)")
.arg( web_server )
.arg( year ).arg( month );
query << QStringLiteral(R"( AND "day"<=%1)").arg( day );
if ( ! fields_filters.isEmpty() ) {
query << fields_filters;
}
query << R"( ORDER BY "day" ASC;)";
}
void relationalDataEntireMonth( QueryWrapper& query, QStringView web_server, const int year, const int month, QStringView fields_filters )
{
query << QStringLiteral(R"(SELECT "day" FROM "%1" WHERE "year"=%2 AND "month"=%3)")
.arg( web_server )
.arg( year ).arg( month );
if ( ! fields_filters.isEmpty() ) {
query << fields_filters;
}
query << R"( ORDER BY "day" ASC;)";
}
void globalsData( QueryWrapper& query, QStringView web_server, const int year, const int month )
{
query << QStringLiteral(R"(SELECT "day","hour","protocol","method","uri","user_agent","time_taken","bytes_sent","bytes_received" FROM "%1" WHERE "year"=%2 AND "month"=%3 ORDER BY "day","hour" ASC;)")
.arg( web_server )
.arg( year ).arg( month );
}
} // namespace QueryFactory
#endif // LOGDOCTOR__CRAPVIEW__MODULES__FETCHER__QUERIES_H

View File

@ -0,0 +1,177 @@
#include "modules/exceptions.h"
#include "modules/dialogs.h"
#include "modules/shared.h"
namespace FetcherPrivate
{
int toInt( QStringView str )
{
bool ok;
const int result{ str.toInt( &ok ) };
if ( ! ok ) {
DialogSec::errConvertingData(
QStringLiteral("QStringView"),
QStringLiteral("int"),
str.toString() );
throw VoidException{};
}
return result;
}
int toInt( const QVariant& var )
{
if ( ! var.canConvert( QMetaType(QMetaType::Int) ) ) {
DialogSec::errConvertingData(
QStringLiteral("QVariant"),
QStringLiteral("int"),
var.toString() );
throw VoidException{};
}
return var.toInt();
}
QString toString( const QVariant& var )
{
if ( ! var.canConvert( QMetaType(QMetaType::QString) ) ) {
DialogSec::errConvertingData(
QStringLiteral("QVariant"),
QStringLiteral("QString"),
QStringLiteral("???") );
throw VoidException{};
}
return var.toString();
}
int getMinuteGap( const int minute, const int gap=10 )
{
int m{ -1 };
if ( minute < 0 || minute >= 60 ) {
// unexpected value
throw DateTimeException( "Unexpected Minute", std::to_string( minute ) );
}
int n{ 0 };
for ( int g{0}; g<60; g+=gap ) {
if ( minute >= g && minute < g+gap ) {
m = gap * n;
break;
}
++n;
}
return m;
}
int getMonthNumber( QStringView month_str )
{
if ( TR::tr( MONTHS__JANUARY.c_str() ) == month_str ) {
return 1;
} else if ( TR::tr( MONTHS__FEBRUARY.c_str() ) == month_str ) {
return 2;
} else if ( TR::tr( MONTHS__MARCH.c_str() ) == month_str ) {
return 3;
} else if ( TR::tr( MONTHS__APRIL.c_str() ) == month_str ) {
return 4;
} else if ( TR::tr( MONTHS__MAY.c_str() ) == month_str ) {
return 5;
} else if ( TR::tr( MONTHS__JUNE.c_str() ) == month_str ) {
return 6;
} else if ( TR::tr( MONTHS__JULY.c_str() ) == month_str ) {
return 7;
} else if ( TR::tr( MONTHS__AUGUST.c_str() ) == month_str ) {
return 8;
} else if ( TR::tr( MONTHS__SEPTEMBER.c_str() ) == month_str ) {
return 9;
} else if ( TR::tr( MONTHS__OCTOBER.c_str() ) == month_str ) {
return 10;
} else if ( TR::tr( MONTHS__NOVEMBER.c_str() ) == month_str ) {
return 11;
} else if ( TR::tr( MONTHS__DECEMBER.c_str() ) == month_str ) {
return 12;
}
throw DateTimeException( "Unexpected Month name", month_str.toString().toStdString() );
}
int getMonthDays( const int year, const int month )
{
int n_days;
switch (month) {
case 1: n_days = 31; break;
case 2: n_days = year%4 == 0 ? 29 : 28 ; break;
case 3: n_days = 31; break;
case 4: n_days = 30; break;
case 5: n_days = 31; break;
case 6: n_days = 30; break;
case 7: n_days = 31; break;
case 8: n_days = 31; break;
case 9: n_days = 30; break;
case 10: n_days = 31; break;
case 11: n_days = 30; break;
case 12: n_days = 31; break;
default:
throw DateTimeException( "Unexpected Month number", std::to_string( month ) );
}
return n_days;
}
int countDays( const int from_year, const int from_month, const int from_day, const int to_year, const int to_month, const int to_day )
{
int n_days{ 1 };
if ( from_year == to_year ) {
if ( from_month == to_month ) {
n_days += to_day - from_day + 1;
} else {
n_days += getMonthDays( from_year, from_month ) - from_day; // first month's days
for ( int month{from_month+1}; month<to_month; ++month ) {
n_days += getMonthDays( from_year, month );
}
n_days += to_day; // last month's days
}
} else {
n_days += getMonthDays( from_year, from_month ) - from_day; // first month's days
if ( from_month < 12 ) {
for ( int month{from_month+1}; month<=12; ++month ) {
n_days += getMonthDays( from_year, month );
}
}
for ( int year{from_year+1}; year<=to_year; ++year ) {
int last_month{ 12 };
if ( year == to_year ) {
last_month = to_month-1;
n_days += to_day; // last month's days
}
for ( int month{1}; month<=last_month; ++month ) {
n_days += getMonthDays( year, month );
}
}
}
return n_days;
}
int countMonths( const int from_year, const int from_month, const int to_year, const int to_month ) noexcept
{
int n_months{ 0 };
if ( from_year == to_year ) {
if ( from_month == to_month ) {
n_months = 1;
} else {
n_months = to_month - from_month + 1;
}
} else {
n_months += 13 - from_month; // months to the end of the first year
n_months += to_month; // months from the beginning of the last year
n_months += 12 * ( to_year - from_year - 1 ); // 12 months for every year in the middle
}
return n_months;
}
} // namespace FetcherPrivate

View File

@ -0,0 +1,92 @@
#ifndef LOGDOCTOR__CRAPVIEW__MODULES__FETCHER__UTILITIES_H
#define LOGDOCTOR__CRAPVIEW__MODULES__FETCHER__UTILITIES_H
#include <QString>
namespace FetcherPrivate
{
//! Converts the given string to int
/*!
\param str The string to convert
\return The resulting integer
\throw VoidException
*/
int toInt( QStringView str );
//! Morphs the given variant into an int
/*!
\param var The variant to convert
\return The resulting integer
\throw VoidException
*/
int toInt( const QVariant& var );
//! Morphs the given variant into a string
/*!
\param var The variant to convert
\return The resulting string
\throw VoidException
*/
QString toString( const QVariant& var );
//! Returns the minute gap for the given minute with the given gap
/*!
\param minute The minute of the hour
\param gap The gap used to split the hour
\return The gap index
\throw DateTimeException
*/
int getMinuteGap( const int minute, const int gap=10 );
//! Returns the month number in the year
/*!
\param month_str The month string (translated)
\return The month number
\throw DateTimeException
*/
int getMonthNumber( QStringView month_str );
//! Returns the number of days for a given month
/*!
\param year The year, used to handle leap years
\param month The month
\return The number of days
\throw DateTimeException
*/
int getMonthDays( const int year, const int month );
//! Returns the number of days in a given period
/*!
\param from_year The initial year
\param from_month The initial month
\param from_day The initial day
\param to_year The final Year
\param to_month The final month
\param to_day The final day
\return The number of days
\throw DateTimeException
*/
int countDays( const int from_year, const int from_month, const int from_day, const int to_year, const int to_month, const int to_day );
//! Returns the number of months in a given period
/*!
\param from_year The initial year
\param from_month The initial month
\param to_year The final Year
\param to_month The final month
\return The number of months in the period
*/
int countMonths( const int from_year, const int from_month, const int to_year, const int to_month ) noexcept;
} // namespace FetcherPrivate
#endif // LOGDOCTOR__CRAPVIEW__MODULES__FETCHER__UTILITIES_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/charts.h
${CMAKE_CURRENT_SOURCE_DIR}/charts.cpp
${CMAKE_CURRENT_SOURCE_DIR}/datetime.h
${CMAKE_CURRENT_SOURCE_DIR}/datetime.cpp
${CMAKE_CURRENT_SOURCE_DIR}/filters.h
${CMAKE_CURRENT_SOURCE_DIR}/filters.cpp
${CMAKE_CURRENT_SOURCE_DIR}/globals.h
)

View File

@ -0,0 +1,268 @@
#include "charts.h"
#include "modules/shared.h"
#include <QValueAxis>
#include <QDateTimeAxis>
#include <QBarCategoryAxis>
#include <QStackedBarSeries>
#include <QLineSeries>
#include <QAreaSeries>
#include <QPieSeries>
#include <QBarSeries>
#include <QBarSet>
namespace ChartOps
{
namespace Warnings
{
void appendToSeries( std::vector<QStackedBarSeries*>& b_series, std::vector<std::vector<QBarSet*>>& sets )
{
b_series.reserve( sets.size() );
const QColor cols[]{ QColor(127,127,127), QColor(237,80,61) };
const size_t max{ sets.size() };
for ( size_t i{0}; i<max; ++i ) {
const auto& set{ sets.at( i ) };
auto* series{ new QStackedBarSeries() };
for ( size_t w{0}; w<2ul; ++w ) {
QBarSet* b{ set.at( w ) };
b->setColor( cols[ w ] );
series->append( b );
}
series->setBarWidth( 1 );
b_series.push_back( series );
}
}
void appendToChart( QChart*const b_chart, const std::vector<QStackedBarSeries*>& b_series )
{
for ( auto* bars : b_series ) {
b_chart->addSeries( bars );
}
}
void setupChart( QChart*const b_chart, const QChart::ChartTheme& theme )
{
b_chart->setTheme( theme );
b_chart->setTitle( TR::tr( "Log Lines Marked as Warning" ) );
b_chart->legend()->setVisible( false );
/*b_chart->legend()->setAlignment( Qt::AlignBottom );
b_chart->setAnimationOptions( QChart::SeriesAnimations );*/
}
void attachXAxis( QChart*const b_chart, std::vector<QStackedBarSeries*>& b_series, const QStringList categories, const QString date )
{
QBarCategoryAxis*const axisX{ new QBarCategoryAxis() };
axisX->append( categories );
axisX->setTitleText( date );
b_chart->addAxis( axisX, Qt::AlignBottom );
for ( auto* s : b_series ) {
s->attachAxis( axisX );
}
}
void attachYAxis( QChart*const b_chart, std::vector<QStackedBarSeries*>& b_series, const int max_count )
{
QValueAxis*const axisY{ new QValueAxis() };
axisY->setLabelFormat( "%d" );
axisY->setTickCount( max_count < 9 ? max_count+1 : 9 );
axisY->setRange( 0, max_count );
b_chart->addAxis( axisY, Qt::AlignLeft );
for ( auto* s : b_series ) {
s->attachAxis( axisY );
}
}
} // namespace Warnings
namespace Speed
{
void applyGradient( QLineSeries*const line )
{
const QColor col1{ Qt::GlobalColor::red };
const QColor col2{ Qt::GlobalColor::green };
const QColor col3{ Qt::GlobalColor::blue };
//area->setColor( col );
QLinearGradient gradient{ QPointF(0, 0), QPointF(0, 1) };
gradient.setColorAt(0.3, col1.lighter( 90 ) );
gradient.setColorAt(0.7, col2.lighter( 90 ) );
gradient.setColorAt(1.0, col3.lighter( 90 ) );
gradient.setCoordinateMode( QGradient::ObjectMode );
QPen pen{ line->pen() };
pen.setBrush( gradient );
pen.setWidth( 1 );
line->setPen(pen);
}
void appendToChart( QChart*const l_chart, QLineSeries*const line )
{
l_chart->addSeries( line );
}
void setupChart( QChart*const l_chart, const QChart::ChartTheme& theme )
{
l_chart->setTheme( theme );
l_chart->setTitle( TR::tr( "Time Taken to Serve Requests" ) );
/*l_chart->legend()->setAlignment( Qt::AlignBottom );*/
l_chart->legend()->setVisible( false );
}
void attachXAxis( QChart*const l_chart, QLineSeries*const line, const QString& time_format, const QString date )
{
QDateTimeAxis*const axisX{ new QDateTimeAxis() };
axisX->setFormat( time_format );
axisX->setTickCount( 25 );
axisX->setTitleText( date );
l_chart->addAxis( axisX, Qt::AlignBottom );
line->attachAxis( axisX );
}
void attachYAxis( QChart*const l_chart, QLineSeries*const line, const int max_value )
{
QValueAxis*const axisY{ new QValueAxis() };
axisY->setLabelFormat( "%d" );
axisY->setTickCount( max_value < 9 ? max_value+1 : 9 );
axisY->setMinorTickCount( 4 );
axisY->setRange( 0, max_value > 1 ? max_value : 0 );
l_chart->addAxis( axisY, Qt::AlignLeft );
line->attachAxis( axisY) ;
}
} // namespace Speed
namespace Count
{
void setupPie( QPieSeries*const pie, const qreal pie_size )
{
pie->setPieSize( pie_size );
pie->setLabelsVisible( false );
}
void appendToChart( QChart*const p_chart, QPieSeries*const pie )
{
p_chart->addSeries( pie );
}
void setupChart( QChart*const p_chart, const QChart::ChartTheme& theme, const QString& title )
{
p_chart->setTheme( theme );
p_chart->setTitle( title );
p_chart->legend()->hide();
}
} // namespace Count
namespace Daytime
{
void setupSeries( QBarSeries*const bars, const QList<QBarSet*>& sets )
{
bars->append( sets );
bars->setBarWidth( 1 );
}
void appendToChart( QChart*const b_chart, QBarSeries*const bars )
{
b_chart->addSeries( bars );
}
void setupChart( QChart*const b_chart, const QChart::ChartTheme& theme, const QString& field_str )
{
b_chart->setTheme( theme );
b_chart->setTitle( QStringLiteral("%1: %2").arg( TR::tr( "Time of Day Count" ), field_str ) );
b_chart->legend()->setVisible( false );
/*b_chart->legend()->setAlignment( Qt::AlignBottom );
b_chart->setAnimationOptions( QChart::SeriesAnimations );*/
}
void attachXAxis( QChart*const b_chart, QBarSeries*const bars, const QStringList& categories, const QString date )
{
QBarCategoryAxis*const axisX{ new QBarCategoryAxis() };
axisX->append( categories );
axisX->setTitleText( date );
b_chart->addAxis( axisX, Qt::AlignBottom );
bars->attachAxis( axisX );
}
void attachYAxis( QChart*const b_chart, QBarSeries*const bars, const int max_count )
{
QValueAxis*const axisY{ new QValueAxis() };
axisY->setLabelFormat( "%d" );
axisY->setTickCount( ( max_count < 9 ) ? max_count+1 : 9 );
axisY->setRange( 0, max_count );
b_chart->addAxis( axisY, Qt::AlignLeft );
bars->attachAxis( axisY );
}
} // namespace Daytime
namespace Relational
{
void applyGradient( QAreaSeries*const area )
{
const QColor col1{ Qt::GlobalColor::red };
const QColor col2{ Qt::GlobalColor::yellow };
const QColor col3{ Qt::GlobalColor::magenta };
//area->setColor( col );
QLinearGradient gradient{ QPointF(0, 0), QPointF(0, 1) };
gradient.setColorAt(0.25, col3.lighter( 70 ) );
gradient.setColorAt(0.5, col1.lighter( 80 ) );
gradient.setColorAt(1.0, col2.lighter( 90 ) );
gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
area->setBrush( gradient );
area->setBorderColor( col1.lighter( 50 ) );
}
void appendToChart( QChart*const a_chart, QAreaSeries*const area )
{
a_chart->addSeries( area );
}
void setupChart( QChart*const a_chart, const QChart::ChartTheme& theme, const QString& field_1_str, const QString& field_2_str )
{
a_chart->setTheme( theme );
a_chart->setTitle( QStringLiteral("%1: %2 -> %3").arg( TR::tr( "Relational Count" ), field_1_str, field_2_str) );
a_chart->legend()->setVisible( false );
/*a_chart->legend()->setFont( fonts.at( "main_small" ) );
a_chart->legend()->setAlignment( Qt::AlignBottom );*/
}
void attachXAxis( QChart*const a_chart, QAreaSeries*const area, const int n_ticks, const QString& time_format, const QString& date )
{
QDateTimeAxis*const axisX{ new QDateTimeAxis() };
axisX->setFormat( time_format );
axisX->setTickCount( n_ticks );
axisX->setTitleText( date );
a_chart->addAxis( axisX, Qt::AlignBottom );
area->attachAxis( axisX );
}
void attachYAxis( QChart*const a_chart, QAreaSeries*const area, const int max_count )
{
QValueAxis*const axisY{ new QValueAxis() };
axisY->setLabelFormat( "%d" );
axisY->setTickCount( ( max_count < 9 ) ? max_count+1 : 9 );
axisY->setRange( 0, max_count );
a_chart->addAxis( axisY, Qt::AlignLeft );
area->attachAxis( axisY) ;
}
} // namespace Relational
} // namespace ChartOps

View File

@ -0,0 +1,102 @@
#ifndef LOGDOCTOR__CRAPVIEW__UTILITIES__CHARTS_H
#define LOGDOCTOR__CRAPVIEW__UTILITIES__CHARTS_H
#include <QChart>
#include <vector>
class QBarSet;
class QBarSeries;
class QPieSeries;
class QLineSeries;
class QAreaSeries;
class QStackedBarSeries;
namespace ChartOps
{
namespace Warnings
{
void appendToSeries( std::vector<QStackedBarSeries*>& b_series, std::vector<std::vector<QBarSet*>>& sets );
void appendToChart( QChart*const b_chart, const std::vector<QStackedBarSeries*>& b_series );
void setupChart( QChart*const b_chart, const QChart::ChartTheme& theme );
void attachXAxis( QChart*const b_chart, std::vector<QStackedBarSeries*>& b_series, const QStringList categories, const QString date );
void attachYAxis( QChart*const b_chart, std::vector<QStackedBarSeries*>& b_series, const int max_count );
} // namespace Warnings
namespace Speed
{
void applyGradient( QLineSeries*const line );
void appendToChart( QChart*const l_chart, QLineSeries*const line );
void setupChart( QChart*const l_chart, const QChart::ChartTheme& theme );
void attachXAxis( QChart*const l_chart, QLineSeries*const line, const QString& time_format, const QString date );
void attachYAxis( QChart*const l_chart, QLineSeries*const line, const int max_value );
} // namespace Speed
namespace Count
{
void setupPie( QPieSeries*const pie, const qreal pie_size );
void appendToChart( QChart*const p_chart, QPieSeries*const pie );
void setupChart( QChart*const p_chart, const QChart::ChartTheme& theme, const QString& title );
} // namespace Count
namespace Daytime
{
void setupSeries( QBarSeries*const bars, const QList<QBarSet*>& sets );
void appendToChart( QChart*const b_chart, QBarSeries*const bars );
void setupChart( QChart*const b_chart, const QChart::ChartTheme& theme, const QString& field_str );
void attachXAxis( QChart*const b_chart, QBarSeries*const bars, const QStringList& categories, const QString date );
void attachYAxis( QChart*const b_chart, QBarSeries*const bars, const int max_count );
} // namespace Daytime
namespace Relational
{
void applyGradient( QAreaSeries*const area );
void appendToChart( QChart*const a_chart, QAreaSeries*const area );
void setupChart( QChart*const a_chart, const QChart::ChartTheme& theme, const QString& field_1_str, const QString& field_2_str );
void attachXAxis( QChart*const a_chart, QAreaSeries*const area, const int n_ticks, const QString& time_format, const QString& date );
void attachYAxis( QChart*const a_chart, QAreaSeries*const area, const int max_count );
} // namespace Relational
} // namespace ChartOps
#endif // LOGDOCTOR__CRAPVIEW__UTILITIES__CHARTS_H

View File

@ -0,0 +1,146 @@
#include "datetime.h"
#include "modules/crapview/modules/fetcher/utilities.h"
#include "modules/exceptions.h"
DateTime::Value::Value() noexcept
: value{-1}
, valid{false}
{
}
DateTime::Value::Value( const int v ) noexcept
: value{v}
, valid{true}
{
}
bool DateTime::Value::operator !=( const DateTime::Value& other ) const noexcept
{
return this->value != other.value;
}
DateTime::DateTime( QStringView year, QStringView month, QStringView day )
{
using namespace FetcherPrivate;
if ( ! year.isEmpty() ) {
this->year = Value( toInt(year) );
}
if ( ! month.isEmpty() ) {
this->month = Value( getMonthNumber(month) );
}
if ( ! day.isEmpty() ) {
this->day = Value( toInt(day) );
}
}
DateTime::DateTime( QStringView year, QStringView month, QStringView day, QStringView hour )
{
using namespace FetcherPrivate;
if ( ! year.isEmpty() ) {
this->year = Value( toInt(year) );
}
if ( ! month.isEmpty() ) {
this->month = Value( getMonthNumber(month) );
}
if ( ! day.isEmpty() ) {
this->day = Value( toInt(day) );
}
if ( ! hour.isEmpty() ) {
this->hour = Value( toInt(hour) );
}
}
bool DateTime::DateTime::operator !=( const DateTime& other ) const noexcept
{
return this->year != other.year
|| this->month != other.month
|| this->day != other.day;
}
bool DateTime::isValid() const noexcept
{
return year.valid && month.valid && day.valid;
}
bool DateTime::isHourValid() const noexcept
{
return hour.valid;
}
int DateTime::getYear() const
{
if ( year.valid ) {
return year.value;
}
throw DoNotCatchException("Invalid DateTime Value", "year");
}
int DateTime::getMonth() const
{
if ( month.valid ) {
return month.value;
}
throw DoNotCatchException("Invalid DateTime Value", "month");
}
int DateTime::getDay() const
{
if ( day.valid ) {
return day.value;
}
throw DoNotCatchException("Invalid DateTime Value", "day");
}
int DateTime::getHour() const
{
if ( hour.valid ) {
return hour.value;
}
throw DoNotCatchException("Invalid DateTime Value", "hour");
}
QDate DateTime::toQDate() const
{
return QDate( getYear(), getMonth(), getDay() );
}
FetcherPrivate::DateManager DateTime::toDateManager() const
{
using namespace FetcherPrivate;
return DateManager( getYear(), getMonth(), getDay() );
}
FetcherPrivate::TimeManager DateTime::toTimeManager( const qint64 interval_step ) const
{
using namespace FetcherPrivate;
return TimeManager( getYear(), getMonth(), getDay(), interval_step );
}
int DateTime::countMonths( const DateTime& other ) const
{
if ( other.isValid() ) {
return FetcherPrivate::countMonths( this->getYear(), this->getMonth(), other.getYear(), other.getMonth() );
} else {
return FetcherPrivate::countMonths( this->getYear(), this->getMonth(), this->getYear(), this->getMonth() );
}
}
int DateTime::countDays( const DateTime& other ) const
{
if ( other.isValid() ) {
return FetcherPrivate::countDays( this->getYear(), this->getMonth(), this->getDay(), other.getYear(), other.getMonth(), other.getDay() );
} else {
return FetcherPrivate::countDays( this->getYear(), this->getMonth(), this->getDay(), this->getYear(), this->getMonth(), this->getDay() );
}
}

View File

@ -0,0 +1,55 @@
#ifndef LOGDOCTOR__CRAPVIEW__UTILITIES__DATETIME_H
#define LOGDOCTOR__CRAPVIEW__UTILITIES__DATETIME_H
#include "modules/crapview/modules/fetcher/date_time.h"
class DateTime final
{
struct Value
{
Value() noexcept;
Value( const int v ) noexcept;
bool operator !=( const Value& other ) const noexcept;
int value;
bool valid;
};
public:
DateTime( QStringView year, QStringView month, QStringView day );
DateTime( QStringView year, QStringView month, QStringView day, QStringView hour );
bool operator !=( const DateTime& other ) const noexcept;
bool isValid() const noexcept;
bool isHourValid() const noexcept;
//! \throw DoNotCatchException
int getYear() const;
//! \throw DoNotCatchException
int getMonth() const;
//! \throw DoNotCatchException
int getDay() const;
//! \throw DoNotCatchException
int getHour() const;
QDate toQDate() const;
FetcherPrivate::DateManager toDateManager() const;
FetcherPrivate::TimeManager toTimeManager( const qint64 interval_step ) const;
int countMonths( const DateTime& other ) const;
int countDays( const DateTime& other ) const;
private:
Value year;
Value month;
Value day;
Value hour;
};
#endif // LOGDOCTOR__CRAPVIEW__UTILITIES__DATETIME_H

View File

@ -1,5 +1,5 @@
#ifndef LOGDOCTOR__CRAPVIEW__MODULES__FILTERS_H
#define LOGDOCTOR__CRAPVIEW__MODULES__FILTERS_H
#ifndef LOGDOCTOR__CRAPVIEW__UTILITIES__FILTERS_H
#define LOGDOCTOR__CRAPVIEW__UTILITIES__FILTERS_H
#include <optional>
@ -48,4 +48,4 @@ std::optional<QString> parseTextualFilter( const QString& filter_str ) noexcept;
}
#endif // LOGDOCTOR__CRAPVIEW__MODULES__FILTERS_H
#endif // LOGDOCTOR__CRAPVIEW__UTILITIES__FILTERS_H

View File

@ -0,0 +1,124 @@
#ifndef LOGDOCTOR__CRAPVIEW__UTILITIES__GLOBALS_H
#define LOGDOCTOR__CRAPVIEW__UTILITIES__GLOBALS_H
#include "modules/crapview/datatypes/global_stats.h"
#include "utilities/arrays.h"
#include <QString>
namespace GlobalsOps
{
inline void appendMostRecurrent( auto& recur_list, const auto& kvr, const QString& __dash )
{
size_t max{ 0 };
QStringView max_str{ __dash };
std::for_each( kvr.begin(), kvr.end(),
[&max,&max_str](const auto sc)
{ if (auto& [s,c]{sc}; c>max){ max=c; max_str=s; } });
recur_list.push_back(
std::make_tuple( max_str.toString(), QString::number(max) ) );
}
inline void appendMostTrafficked( auto& traffic_list, const auto& traf, const size_t max_i, const double max_c, const QString&& value, const QString& __dash, const QString& __zero )
{
if ( max_i == traf.size() ) {
traffic_list.emplace_back( __dash, __zero );
} else {
const size_t f{ static_cast<size_t>(max_c) };
const size_t d{ max_c<10.0 ? static_cast<size_t>(max_c*100.0)%100ul : static_cast<size_t>(max_c*10.0)%10ul };
QString count{ QString::number( f ) };
if ( d > 0 ) {
count += QString::number( d ).prepend(QLatin1Char('.'));
}
traffic_list.emplace_back( value, count );
}
}
inline auto getMaxIndexCount( const auto& traf )
{
double max_c{ 0.0 };
size_t max_i{ traf.size() };
/*std::ranges::for_each( std::views::enumerate(traf),
[&max_c,&max_i](const auto ic)
{ if (auto& [i,c]{ic}; c>max_c){ max_c=c; max_i=i; } });*/
for( const auto [index,count] : ArrayOps::enumerate(traf) ) {
if ( count > max_c ) {
max_c = count;
max_i = index;
}
};
return std::make_tuple( max_i, max_c );
}
inline void appendMeanMaxPerformances( auto& perfs_list, const Perfs& perfs, const QLatin1String suffix )
{
perfs_list.push_back( std::make_tuple(
QStringLiteral("%1 %2")
.arg( perfs.count > 0ul ? perfs.total / perfs.count : perfs.total )
.arg( suffix ),
QStringLiteral("%1 %2")
.arg( perfs.max )
.arg( suffix )
));
}
inline void appendTotalWorkTime( auto& work_list, const Perfs& perfs, const QString& __zero )
{
float t{ static_cast<float>( perfs.total ) };
if ( t < 0.f ) {
work_list.push_back( __zero );
} else {
int h{0}, m{0}, s{0}, ms{0};
if ( t > 1000.f ) {
ms = static_cast<int>( t ) % 1000;
t /= 1000.f;
}
if ( t > 60.f ) {
s = static_cast<int>( t );
s /= 60;
if ( s > 60 ) {
m = s/60;
s %= 60;
if ( m > 60 ) {
h = m/60;
m %= 60;
}
}
}
work_list.push_back( QStringLiteral("%1 h %2 m %3 s %4 ms").arg(h).arg(m).arg(s).arg(ms) );
}
}
inline void appendTotalDataTransfer( auto& work_list, const Perfs& perfs, const QString& __zero )
{
float b{ static_cast<float>( perfs.total ) };
if ( b < 0.f ) {
work_list.push_back( __zero );
} else {
int f{0}, d{0};
QString sfx{ "B" };
if ( b > 1024.f ) {
b /= 1024.f;
sfx = "KiB";
if ( b > 1024.f ) {
b /= 1024.f;
sfx = "MiB";
if ( b > 1024.f ) {
b /= 1024.f;
sfx = "GiB";
}
}
}
f = static_cast<int>( b );
d = static_cast<int>( b*1000.f ) %1000;
work_list.push_back( QStringLiteral("%1.%2 %3").arg(f).arg(d).arg(sfx) );
}
}
} // namespace GlobalsOps
#endif // LOGDOCTOR__CRAPVIEW__UTILITIES__GLOBALS_H

View File

@ -0,0 +1,5 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/database.h
${CMAKE_CURRENT_SOURCE_DIR}/database.cpp
)

View File

@ -116,6 +116,10 @@ public:
inline void operator <<( const QString& text ) noexcept
{ stmt.append(text); }
//! Appends the given text to the internal statement
inline void operator <<( const QStringView text ) noexcept
{ stmt.append(text); }
//! Executes the query using the internal statement
/*!
Throws in case of failure

View File

@ -0,0 +1,12 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/message_dialog.ui
${CMAKE_CURRENT_SOURCE_DIR}/message_dialog.h
${CMAKE_CURRENT_SOURCE_DIR}/message_dialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/boolean_dialog.ui
${CMAKE_CURRENT_SOURCE_DIR}/boolean_dialog.h
${CMAKE_CURRENT_SOURCE_DIR}/boolean_dialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ida_dialog.ui
${CMAKE_CURRENT_SOURCE_DIR}/ida_dialog.h
${CMAKE_CURRENT_SOURCE_DIR}/ida_dialog.cpp
)

View File

@ -13,6 +13,9 @@
#include <unordered_map> // leave this here for clang
namespace /*private*/
{
enum StyleId : uint32_t {
TEXT,
WINDOW,
@ -138,6 +141,8 @@ QString getStylesheet()
"}";
}
} //namespace (private)
DialogMsg::DialogMsg(const QString& title, const QString& text, const QString& additional, const MsgType type, QWidget* parent )
: QDialog{ parent }

View File

@ -0,0 +1,7 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/warnlists.h
${CMAKE_CURRENT_SOURCE_DIR}/warnlists.cpp
)
add_subdirectory(modules)

View File

@ -0,0 +1,8 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/lib.h
${CMAKE_CURRENT_SOURCE_DIR}/warnlist.h
${CMAKE_CURRENT_SOURCE_DIR}/warnlist.cpp
${CMAKE_CURRENT_SOURCE_DIR}/warnlist_item.h
${CMAKE_CURRENT_SOURCE_DIR}/warnlist_item.cpp
)

View File

@ -0,0 +1,4 @@
target_sources(LogDoctor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/resources.qrc
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Some files were not shown because too many files have changed in this diff Show More