diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 00000000..45c5c109 --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,73 @@ +name: Linux + +on: + push: + branches: [main] + pull_request: + +jobs: + build: + name: ${{ matrix.name }} + runs-on: ${{ matrix.runner }} + + strategy: + fail-fast: true + matrix: + include: + - name: x86-64 + runner: ubuntu-24.04 + platform_id: linux-x86_64 + + - name: ARM64 + runner: ubuntu-24.04-arm + platform_id: linux-aarch64 + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Install dependencies + run: | + sudo apt update -qq + sudo apt install -y \ + cmake \ + build-essential \ + qt6-base-dev \ + qt6-tools-dev + + - name: Build dependencies + run: cmake -P external/build_deps.cmake + + - name: Configure + run: cmake -B build -DCMAKE_BUILD_TYPE=Release + + - name: Build + run: cmake --build build + + - name: Upload libxdf artifact + uses: actions/upload-artifact@v7 + with: + name: libxdf-${{ matrix.platform_id }} + path: | + external/lib/libxdf.a + external/include/xdf.h + + - name: Upload libbiosig artifact + uses: actions/upload-artifact@v7 + with: + name: libbiosig-${{ matrix.platform_id }} + path: | + external/lib/libbiosig.a + external/include/biosig.h + external/include/biosig-dev.h + external/include/biosig-network.h + external/include/biosig2.h + external/include/gdftime.h + external/include/mdc_ecg_codes.h + external/include/physicalunits.h + + - name: Upload SigViewer artifact + uses: actions/upload-artifact@v7 + with: + name: sigviewer-${{ matrix.platform_id }} + path: build/sigviewer diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml new file mode 100644 index 00000000..3855e3c7 --- /dev/null +++ b/.github/workflows/macos.yml @@ -0,0 +1,106 @@ +name: macOS + +on: + push: + branches: [main] + pull_request: + +jobs: + build: + name: ARM64 + runs-on: macos-15 + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Cache Homebrew downloads + uses: actions/cache@v5 + with: + path: ~/Library/Caches/Homebrew + key: brew-qt-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('.github/workflows/macos.yml') }} + restore-keys: brew-qt-${{ runner.os }}-${{ runner.arch }}- + + - name: Install dependencies + env: + HOMEBREW_NO_AUTO_UPDATE: "1" + HOMEBREW_NO_INSTALL_CLEANUP: "1" + run: brew install qt cmake + + - name: Build dependencies + run: cmake -P external/build_deps.cmake + + - name: Configure + run: cmake -B build -DCMAKE_BUILD_TYPE=Release + + - name: Build + run: cmake --build build + + - name: Upload libxdf artifact + uses: actions/upload-artifact@v7 + with: + name: libxdf-macos-arm64 + path: | + external/lib/libxdf.a + external/include/xdf.h + + - name: Upload libbiosig artifact + uses: actions/upload-artifact@v7 + with: + name: libbiosig-macos-arm64 + path: | + external/lib/libbiosig.a + external/include/biosig.h + external/include/biosig-dev.h + external/include/biosig-network.h + external/include/biosig2.h + external/include/gdftime.h + external/include/mdc_ecg_codes.h + external/include/physicalunits.h + + - name: Extract version + run: | + VERSION=$(sed -n 's/.*VERSION \([0-9][0-9.]*\).*/\1/p' CMakeLists.txt | head -1) + echo "APP_VERSION=$VERSION" >> "$GITHUB_ENV" + + - name: Deploy Qt frameworks + run: $(brew --prefix qt)/bin/macdeployqt build/SigViewer.app + + - name: Import Developer ID certificate + env: + MACOS_CERT_P12_BASE64: ${{ secrets.MACOS_CERT_P12_BASE64 }} + MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }} + run: | + echo "$MACOS_CERT_P12_BASE64" | base64 --decode > certificate.p12 + security create-keychain -p "" build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p "" build.keychain + security import certificate.p12 -k build.keychain -P "$MACOS_CERT_PASSWORD" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain + + - name: Sign .app bundle + run: 'codesign --deep --force --options runtime --sign "Developer ID Application: CLEMENS BRUNNER (9UC2D22DW3)" build/SigViewer.app' + + - name: Notarize .app bundle + env: + AC_USERNAME: ${{ secrets.AC_USERNAME }} + AC_PASSWORD: ${{ secrets.AC_PASSWORD }} + run: | + ditto -c -k --sequesterRsrc --keepParent build/SigViewer.app build/SigViewer.zip + xcrun notarytool submit build/SigViewer.zip \ + --apple-id "$AC_USERNAME" \ + --password "$AC_PASSWORD" \ + --team-id 9UC2D22DW3 \ + --wait + + - name: Staple .app bundle + run: xcrun stapler staple build/SigViewer.app + + - name: Create DMG + run: hdiutil create -volname "SigViewer" -srcfolder build/SigViewer.app -ov -format UDZO build/SigViewer-${{ env.APP_VERSION }}.dmg + + - name: Upload SigViewer artifact + uses: actions/upload-artifact@v7 + with: + name: sigviewer-macos-arm64 + path: build/SigViewer-${{ env.APP_VERSION }}.dmg diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 00000000..53c77d30 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,95 @@ +name: Windows + +on: + push: + branches: [main] + pull_request: + +jobs: + build: + name: x86-64 + runs-on: windows-2025 + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + cache: true + install: >- + mingw-w64-x86_64-gcc + mingw-w64-x86_64-cmake + mingw-w64-x86_64-ninja + mingw-w64-x86_64-qt6-base + mingw-w64-x86_64-qt6-tools + mingw-w64-x86_64-libiconv + autoconf + automake + make + + - name: Build dependencies + shell: msys2 {0} + run: cmake -P external/build_deps.cmake + + - name: Configure + shell: msys2 {0} + run: cmake -B build -DCMAKE_BUILD_TYPE=Release -G Ninja + + - name: Build + shell: msys2 {0} + run: cmake --build build + + - name: Upload libxdf artifact + uses: actions/upload-artifact@v7 + with: + name: libxdf-windows-x86_64 + path: | + external/lib/libxdf.a + external/include/xdf.h + + - name: Upload libbiosig artifact + uses: actions/upload-artifact@v7 + with: + name: libbiosig-windows-x86_64 + path: | + external/lib/libbiosig.a + external/include/biosig.h + external/include/biosig-dev.h + external/include/biosig-network.h + external/include/biosig2.h + external/include/gdftime.h + external/include/mdc_ecg_codes.h + external/include/physicalunits.h + + - name: Deploy Qt DLLs + shell: msys2 {0} + run: | + mkdir -p build/sigviewer-windows + cp build/sigviewer.exe build/sigviewer-windows/ + cp src/images/sigviewer.ico build/sigviewer-windows/ + windeployqt6 --release build/sigviewer-windows/sigviewer.exe + # Copy all MinGW DLL dependencies (including those of Qt plugin DLLs in subdirectories) + find build/sigviewer-windows \( -name '*.exe' -o -name '*.dll' \) | xargs ldd 2>/dev/null \ + | awk '$3 ~ /\/mingw64\//' \ + | awk '{print $3}' \ + | sort -u \ + | while IFS= read -r dep; do + dest="build/sigviewer-windows/$(basename "$dep")" + [ -f "$dest" ] || cp "$dep" "$dest" + done + + - name: Create installer + shell: pwsh + run: | + $version = (Get-Content CMakeLists.txt | Select-String '^\s+VERSION\s+([\d.]+)').Matches[0].Groups[1].Value + & 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' /Dversion=$version deploy\windows\sigviewer-windows.iss + + - name: Upload SigViewer artifact + uses: actions/upload-artifact@v7 + with: + name: sigviewer-windows-x86_64 + path: build/SigViewer-*.exe diff --git a/.gitignore b/.gitignore index 97a2acf3..b14bf863 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,9 @@ -.directory -.DS_Store -*~ -external/ -sigviewer.pro.user -*.a -*.o -tmp/ -bin/ -.qmake.stash +build/ +CMakeFiles/ +external/include/ +external/lib/ +external/versions.cmake +CMakeCache.txt +cmake_install.cmake +CTestTestfile.cmake Makefile -src/Makefile diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..bc6eefe5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,365 @@ +cmake_minimum_required(VERSION 3.21) + +project(sigviewer + VERSION 0.6.4 + LANGUAGES CXX C +) + +# -- Pinned versions of external dependencies -------------------------------- +# These are the ONLY accepted versions. Change them here (and rebuild the +# pre-built artifacts) when upgrading a dependency. +set(LIBXDF_VERSION "0.99.10") +set(LIBBIOSIG_VERSION "3.9.4") + +# -- Language standards ------------------------------------------------------ +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# -- Qt ---------------------------------------------------------------------- +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Xml LinguistTools) +qt_standard_project_setup() + +# -- External pre-built dependencies ----------------------------------------- +# Override with -DDEPS_DIR= if the libraries were built elsewhere. +set(DEPS_DIR "${CMAKE_SOURCE_DIR}/external" + CACHE PATH "Directory containing built libxdf and libbiosig") + +# The versions.cmake file is written by external/build_deps.cmake and records +# the versions of the libraries that are actually present in DEPS_DIR. +set(_DEPS_VERSIONS_FILE "${DEPS_DIR}/versions.cmake") +if(NOT EXISTS "${_DEPS_VERSIONS_FILE}") + message(FATAL_ERROR + "Dependency version file not found:\n" + " ${_DEPS_VERSIONS_FILE}\n\n" + "Run the following command to build the required libraries:\n" + " cmake -P external/build_deps.cmake\n" + "Or manually place the libraries in\n" + "${DEPS_DIR}\n" + "and create external/versions.cmake with:\n" + " set(LIBXDF_VERSION_INSTALLED \"${LIBXDF_VERSION}\")\n" + " set(LIBBIOSIG_VERSION_INSTALLED \"${LIBBIOSIG_VERSION}\")" + ) +endif() +include("${_DEPS_VERSIONS_FILE}") + +foreach(_lib IN ITEMS LIBXDF LIBBIOSIG) + set(_required "${${_lib}_VERSION}") + set(_found "${${_lib}_VERSION_INSTALLED}") + if(NOT _found STREQUAL _required) + message(FATAL_ERROR + "${_lib} version mismatch.\n" + " Required : ${_required}\n" + " Installed: ${_found}\n\n" + "Run cmake -P external/build_deps.cmake to install the correct version." + ) + endif() +endforeach() +unset(_lib) +unset(_required) +unset(_found) + +# Create IMPORTED targets so consumers get include dirs for free via +# target_link_libraries. +add_library(dep_libxdf STATIC IMPORTED) +set_target_properties(dep_libxdf PROPERTIES + IMPORTED_LOCATION "${DEPS_DIR}/lib/libxdf.a" + INTERFACE_INCLUDE_DIRECTORIES "${DEPS_DIR}/include" +) + +add_library(dep_libbiosig STATIC IMPORTED) +set_target_properties(dep_libbiosig PROPERTIES + IMPORTED_LOCATION "${DEPS_DIR}/lib/libbiosig.a" + INTERFACE_INCLUDE_DIRECTORIES "${DEPS_DIR}/include" +) + +# -- Sources ----------------------------------------------------------------- +qt_add_executable(sigviewer + src/main.cpp + src/application_context_impl.cpp + src/application_context_impl.h + src/command_executer.h + src/file_context.cpp + src/file_context.h + src/tab_context.cpp + src/tab_context.h + + # base + src/base/data_block.cpp + src/base/data_block.h + src/base/exception.cpp + src/base/exception.h + src/base/fixed_data_block.cpp + src/base/fixed_data_block.h + src/base/math_utils.cpp + src/base/math_utils.h + src/base/signal_channel.cpp + src/base/signal_channel.h + src/base/signal_event.cpp + src/base/signal_event.h + src/base/application_states.h + src/base/file_states.h + src/base/sigviewer_user_types.h + src/base/tab_states.h + + # commands + src/commands/convert_file_command.cpp + src/commands/convert_file_command.h + src/commands/open_file_command.cpp + src/commands/open_file_command.h + + # editing_commands + src/editing_commands/change_channel_undo_command.cpp + src/editing_commands/change_channel_undo_command.h + src/editing_commands/change_type_undo_command.cpp + src/editing_commands/change_type_undo_command.h + src/editing_commands/delete_event_undo_command.cpp + src/editing_commands/delete_event_undo_command.h + src/editing_commands/macro_undo_command.cpp + src/editing_commands/macro_undo_command.h + src/editing_commands/new_event_undo_command.cpp + src/editing_commands/new_event_undo_command.h + src/editing_commands/resize_event_undo_command.cpp + src/editing_commands/resize_event_undo_command.h + + # file_handling + src/file_handling/basic_header.cpp + src/file_handling/basic_header.h + src/file_handling/channel_manager.cpp + src/file_handling/channel_manager.h + src/file_handling/event_manager.h + src/file_handling/file_handler_factory.h + src/file_handling/file_signal_reader.cpp + src/file_handling/file_signal_reader.h + src/file_handling/file_signal_reader_factory.cpp + src/file_handling/file_signal_reader_factory.h + src/file_handling/file_signal_writer.h + src/file_handling/file_signal_writer_factory.cpp + src/file_handling/file_signal_writer_factory.h + + # file_handling_impl + src/file_handling_impl/biosig_basic_header.cpp + src/file_handling_impl/biosig_basic_header.h + src/file_handling_impl/biosig_reader.cpp + src/file_handling_impl/biosig_reader.h + src/file_handling_impl/biosig_writer.cpp + src/file_handling_impl/biosig_writer.h + src/file_handling_impl/channel_manager_impl.cpp + src/file_handling_impl/channel_manager_impl.h + src/file_handling_impl/event_manager_impl.cpp + src/file_handling_impl/event_manager_impl.h + src/file_handling_impl/event_table_file_reader.cpp + src/file_handling_impl/event_table_file_reader.h + src/file_handling_impl/evt_writer.cpp + src/file_handling_impl/evt_writer.h + src/file_handling_impl/file_handler_factory_registrator.h + src/file_handling_impl/xdf_reader.cpp + src/file_handling_impl/xdf_reader.h + + # gui + src/gui/application_context.h + src/gui/background_processes.cpp + src/gui/background_processes.h + src/gui/color_manager.cpp + src/gui/color_manager.h + src/gui/event_view.h + src/gui/gui_action_command.cpp + src/gui/gui_action_command.h + src/gui/gui_action_factory.cpp + src/gui/gui_action_factory.h + src/gui/gui_action_factory_registrator.h + src/gui/main_window_model.h + src/gui/progress_bar.h + src/gui/signal_view_settings.cpp + src/gui/signal_view_settings.h + src/gui/signal_visualisation_model.cpp + src/gui/signal_visualisation_model.h + src/gui/signal_visualisation_modes.h + src/gui/signal_visualisation_view.h + + # gui_impl + src/gui_impl/gui_helper_functions.cpp + src/gui_impl/gui_helper_functions.h + src/gui_impl/main_window.cpp + src/gui_impl/main_window.h + src/gui_impl/main_window_model_impl.cpp + src/gui_impl/main_window_model_impl.h + src/gui_impl/processed_signal_channel_manager.cpp + src/gui_impl/processed_signal_channel_manager.h + src/gui_impl/select_shown_channels_dialog.cpp + src/gui_impl/select_shown_channels_dialog.h + src/gui_impl/signal_browser_mouse_handling.cpp + src/gui_impl/signal_browser_mouse_handling.h + src/gui_impl/info_widgets/power_spectrum_info_widget.ui + + # gui_impl/commands + src/gui_impl/commands/adapt_channel_view_gui_command.cpp + src/gui_impl/commands/adapt_channel_view_gui_command.h + src/gui_impl/commands/adapt_event_view_gui_command.cpp + src/gui_impl/commands/adapt_event_view_gui_command.h + src/gui_impl/commands/close_file_gui_command.cpp + src/gui_impl/commands/close_file_gui_command.h + src/gui_impl/commands/event_editing_gui_command.cpp + src/gui_impl/commands/event_editing_gui_command.h + src/gui_impl/commands/help_gui_command.cpp + src/gui_impl/commands/help_gui_command.h + src/gui_impl/commands/mouse_mode_gui_command.cpp + src/gui_impl/commands/mouse_mode_gui_command.h + src/gui_impl/commands/open_file_gui_command.cpp + src/gui_impl/commands/open_file_gui_command.h + src/gui_impl/commands/save_gui_command.cpp + src/gui_impl/commands/save_gui_command.h + src/gui_impl/commands/signal_processing_gui_command.cpp + src/gui_impl/commands/signal_processing_gui_command.h + src/gui_impl/commands/undo_redo_gui_command.cpp + src/gui_impl/commands/undo_redo_gui_command.h + src/gui_impl/commands/zoom_gui_command.cpp + src/gui_impl/commands/zoom_gui_command.h + + # gui_impl/dialogs + src/gui_impl/dialogs/about_dialog.ui + src/gui_impl/dialogs/basic_header_info_dialog.cpp + src/gui_impl/dialogs/basic_header_info_dialog.h + src/gui_impl/dialogs/channel_dialog.ui + src/gui_impl/dialogs/channel_selection_dialog.cpp + src/gui_impl/dialogs/channel_selection_dialog.h + src/gui_impl/dialogs/event_time_selection_dialog.cpp + src/gui_impl/dialogs/event_time_selection_dialog.h + src/gui_impl/dialogs/event_time_selection_dialog.ui + src/gui_impl/dialogs/event_type_selection_dialog.ui + src/gui_impl/dialogs/event_types_selection_dialog.cpp + src/gui_impl/dialogs/event_types_selection_dialog.h + src/gui_impl/dialogs/resampling_dialog.cpp + src/gui_impl/dialogs/resampling_dialog.h + src/gui_impl/dialogs/resampling_dialog.ui + src/gui_impl/dialogs/scale_channel_dialog.cpp + src/gui_impl/dialogs/scale_channel_dialog.h + src/gui_impl/dialogs/scale_channel_dialog.ui + + # gui_impl/event_table + src/gui_impl/event_table/event_table_view_model.cpp + src/gui_impl/event_table/event_table_view_model.h + src/gui_impl/event_table/event_table_widget.cpp + src/gui_impl/event_table/event_table_widget.h + src/gui_impl/event_table/event_table_widget.ui + + # gui_impl/signal_browser + src/gui_impl/signal_browser/adapt_browser_view_widget.cpp + src/gui_impl/signal_browser/adapt_browser_view_widget.h + src/gui_impl/signal_browser/adapt_browser_view_widget.ui + src/gui_impl/signal_browser/event_context_menu.cpp + src/gui_impl/signal_browser/event_context_menu.h + src/gui_impl/signal_browser/event_creation_widget.cpp + src/gui_impl/signal_browser/event_creation_widget.h + src/gui_impl/signal_browser/event_creation_widget.ui + src/gui_impl/signal_browser/event_editing_widget.cpp + src/gui_impl/signal_browser/event_editing_widget.h + src/gui_impl/signal_browser/event_editing_widget.ui + src/gui_impl/signal_browser/event_graphics_item.cpp + src/gui_impl/signal_browser/event_graphics_item.h + src/gui_impl/signal_browser/label_widget.cpp + src/gui_impl/signal_browser/label_widget.h + src/gui_impl/signal_browser/signal_browser_graphics_view.h + src/gui_impl/signal_browser/signal_browser_model_4.cpp + src/gui_impl/signal_browser/signal_browser_model_4.h + src/gui_impl/signal_browser/signal_browser_view.cpp + src/gui_impl/signal_browser/signal_browser_view.h + src/gui_impl/signal_browser/signal_graphics_item.cpp + src/gui_impl/signal_browser/signal_graphics_item.h + src/gui_impl/signal_browser/signal_grid_graphics_item.cpp + src/gui_impl/signal_browser/signal_grid_graphics_item.h + src/gui_impl/signal_browser/x_axis_widget_4.cpp + src/gui_impl/signal_browser/x_axis_widget_4.h + src/gui_impl/signal_browser/y_axis_widget_4.cpp + src/gui_impl/signal_browser/y_axis_widget_4.h + + # signal_processing + src/signal_processing/FFTReal.cpp + src/signal_processing/FFTReal.h + + # tests + src/tests/color_manager_tests.cpp + src/tests/color_manager_tests.h + src/tests/data_block_tests.cpp + src/tests/data_block_tests.h + src/tests/editing_commands_tests.cpp + src/tests/editing_commands_tests.h + src/tests/event_manager_tests.cpp + src/tests/event_manager_tests.h + src/tests/event_table_widget_tests.cpp + src/tests/event_table_widget_tests.h + src/tests/file_handling_tests.cpp + src/tests/file_handling_tests.h + src/tests/gui_tests.cpp + src/tests/gui_tests.h + src/tests/test.cpp + src/tests/test.h + src/tests/tests_dialog.cpp + src/tests/tests_dialog.h + src/tests/tests_dialog.ui + src/tests/tests_factory.h + +) + +qt_add_resources(SIGVIEWER_RESOURCES src/src.qrc) +target_sources(sigviewer PRIVATE ${SIGVIEWER_RESOURCES}) + +# -- Platform-specific sources ----------------------------------------------- +if(APPLE) + target_sources(sigviewer PRIVATE src/sigviewer.icns) + set_source_files_properties(src/sigviewer.icns PROPERTIES + MACOSX_PACKAGE_LOCATION "Resources") + set_target_properties(sigviewer PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_BUNDLE_NAME "SigViewer" + MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}" + MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}" + MACOSX_DEPLOYMENT_TARGET "11" + MACOSX_BUNDLE_ICON_FILE "sigviewer.icns" + OUTPUT_NAME "SigViewer" + ) + target_link_libraries(sigviewer PRIVATE iconv) +elseif(WIN32) + target_sources(sigviewer PRIVATE src/src.rc) + set_target_properties(sigviewer PROPERTIES WIN32_EXECUTABLE TRUE) +endif() + +# -- Compile definitions ----------------------------------------------------- +target_compile_definitions(sigviewer PRIVATE + VERSION_MAJOR=${PROJECT_VERSION_MAJOR} + VERSION_MINOR=${PROJECT_VERSION_MINOR} + VERSION_BUILD=${PROJECT_VERSION_PATCH} + $<$>:QT_NO_DEBUG_OUTPUT> +) + +# -- Include paths and link libraries ---------------------------------------- +target_include_directories(sigviewer PRIVATE src) + +# AUTOUIC needs to know every directory that contains a .ui file. +set_target_properties(sigviewer PROPERTIES + AUTOUIC_SEARCH_PATHS + "${CMAKE_SOURCE_DIR}/src/gui_impl/dialogs;${CMAKE_SOURCE_DIR}/src/gui_impl/event_table;${CMAKE_SOURCE_DIR}/src/gui_impl/signal_browser;${CMAKE_SOURCE_DIR}/src/gui_impl/info_widgets;${CMAKE_SOURCE_DIR}/src/tests" +) + +target_link_libraries(sigviewer PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets + Qt6::Xml + dep_libxdf + dep_libbiosig + # libbiosig is a static library and cannot carry its own transitive + # dependencies. On Windows it uses Winsock (ntohl/htonl/getaddrinfo) + # and libiconv, which must be listed after it so GNU ld can resolve them. + $<$:ws2_32> + $<$:iconv> +) + +# -- Translations ------------------------------------------------------------ +qt_add_translations(sigviewer + TS_FILES + src/translations/sigviewer_de.ts + src/translations/sigviewer_en.ts + src/translations/sigviewer_ru.ts +) diff --git a/README.md b/README.md index 866decea..b77cb360 100755 --- a/README.md +++ b/README.md @@ -1,91 +1,149 @@ -SigViewer -========= +# SigViewer -SigViewer is a viewing application for biosignals such as EEG or MEG time series. In addition to viewing raw data, SigViewer can also create, edit, and display event information (such as annotations or artifact selections). +SigViewer is an application for viewing biosignals such as EEG or MEG time series. In addition to viewing raw data, SigViewer can also create, edit, and display events (such as annotations or artifact selections). -Download --------- - [SigViewer 0.6.4 (Windows)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.4/sigviewer-0.6.4-win64.exe) - [SigViewer 0.6.4 (macOS)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.4/sigviewer-0.6.4-macos.dmg) - [SigViewer 0.6.4 (Linux)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.4/sigviewer-0.6.4-linux.zip) ([Arch](https://aur.archlinux.org/packages/sigviewer/), [Debian](https://tracker.debian.org/pkg/sigviewer), [Ubuntu](https://launchpad.net/ubuntu/+source/sigviewer)) - [SigViewer 0.6.4 (Source)](https://github.com/cbrnr/sigviewer/archive/v0.6.4.zip) -Screenshots ------------ -![screenshot-1](https://github.com/cbrnr/sigviewer/raw/main/screenshot-1.png) -Building SigViewer ------------------- -SigViewer requires a standard-compliant C++11 build toolchain, for example recent versions of [GCC](https://gcc.gnu.org/) or [Clang](https://clang.llvm.org/). Other compilers such as [MSVC](https://en.wikipedia.org/wiki/Visual_C%2B%2B) might work, but are not tested. Furthermore, SigViewer depends on [Qt](https://www.qt.io/). Current SigViewer builds use Qt 5.12 (previous or future versions are not guaranteed to work). +## Building SigViewer -SigViewer also depends on [libbiosig](http://biosig.sourceforge.net/) and [libxdf](https://github.com/xdf-modules/libxdf). There are two options to get these external dependencies for your platform: +SigViewer requires a standard-compliant C++17 build toolchain, for example recent versions of [GCC](https://gcc.gnu.org/) or [Clang](https://clang.llvm.org/). Furthermore, SigViewer depends on [Qt 6](https://www.qt.io/) and [CMake](https://cmake.org/) 3.21 or later. -1. Build these dependencies yourself (see separate descriptions below). -2. Use our pre-built binaries. The corresponding archive contains binary versions of libbiosig and libxdf and must be extracted into SigViewer’s source folder (which we denote as `$sigviewer`). - - [External dependencies (macOS)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.4/external-0.6.4-macos.zip) - - [External dependencies (Linux)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.4/external-0.6.4-linux.zip) - -### Windows -Building SigViewer on Windows is currently not supported. We provide binaries created with the [MXE](https://mxe.cc/) cross compilation environment. +In addition, SigViewer depends on [libbiosig](http://biosig.sourceforge.net/) and [libxdf](https://github.com/xdf-modules/libxdf), which are built from source automatically. ### macOS -SigViewer requires Mac OS X (now renamed to macOS) 10.9 or later. First, install XCode from the App Store. Next, download and install [Qt 5.12.3 for macOS](http://download.qt.io/official_releases/qt/5.12/5.12.3/qt-opensource-mac-x64-5.12.3.dmg) or install Qt via [Homebrew](https://brew.sh/) by running `brew install qt` in a terminal. Make sure that `qmake` is available on the path if you want to build SigViewer in a terminal. Alternatively, you can build SigViewer with Qt Creator (please refer to the description for building SigViewer on Windows). -1. Download and unzip the [SigViewer source](https://github.com/cbrnr/sigviewer/archive/v0.6.4.zip). -1. Provide all external dependencies: - - Either download the [external archive](https://github.com/cbrnr/sigviewer/releases/download/v0.6.4/external-0.6.4-macos.zip) and extract it inside `$sigviewer`. - - Or copy the necessary files from libbiosig and libxdf builds to the corresponding folders as detailed in the build descriptions for libbiosig and libxdf below. -1. In a terminal, change to `$sigviewer` and run `qmake`. -1. Run `make` (or if you want to use more cores to build in parallel, run `make -j4` if you want to use four cores). The SigViewer binary is built in the `bin/release` folder. -1. To create a stand-alone version of SigViewer, open a terminal, change into `$sigviewer/bin/release` and run `macdeployqt sigviewer.app -dmg`. This creates a disk image with the app, which can then be dragged to the Applications folder. +Install the Xcode Command Line Tools by running `xcode-select --install`, then install Qt 6 and CMake via [Homebrew](https://brew.sh/): + +``` +brew install qt cmake +``` + +Then build SigViewer: + +``` +cmake -P external/build_deps.cmake +cmake -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j$(sysctl -n hw.logicalcpu) +``` + +The application bundle is produced at `build/SigViewer.app`. + +To create a disk image that can be distributed, first bundle all required Qt frameworks into the app: + +``` +$(brew --prefix qt)/bin/macdeployqt build/SigViewer.app +``` + +For a production release the app bundle must be **code-signed** with a Developer ID certificate, **notarized** with Apple, and **stapled** before the DMG is created. Distributing an unsigned or un-notarized app will trigger Gatekeeper warnings. The order is: + +1. Sign the `.app` with `codesign` +2. Submit the `.app` (as a zip) to `xcrun notarytool` and wait for approval +3. Staple the notarization ticket to the `.app` with `xcrun stapler` +4. Create the DMG from the stapled `.app` + +See `.github/workflows/build.yml` for the exact commands used in CI. + +Once the app is signed, notarized, and stapled, create the disk image: + +``` +hdiutil create -volname "SigViewer" -srcfolder build/SigViewer.app -ov -format UDZO build/SigViewer-.dmg +``` + ### Linux -Install the GNU build toolchain and Qt 5 with your native package manager. You can either build on the command line or with Qt Creator (which you then need to install). -1. Download and unzip the [SigViewer source](https://github.com/cbrnr/sigviewer/archive/v0.6.4.zip). -1. Provide all external dependencies: - - Either download the [external archive](https://github.com/cbrnr/sigviewer/releases/download/v0.6.4/external-0.6.4-linux.zip) and extract it inside `$sigviewer`. - - Or copy the necessary files from libbiosig and libxdf builds to the corresponding folders as detailed in the build descriptions for libbiosig and libxdf below. -1. In a terminal, change to `$sigviewer` and run `qmake`. -1. Run `make` (or if you want to use more cores to build in parallel, run `make -j 4` if you want to use four cores). The SigViewer binary is built in the `bin/release` folder. +Install a C++ toolchain, Qt 6, and CMake with your package manager. On Debian/Ubuntu: + +``` +sudo apt install cmake build-essential qt6-base-dev qt6-tools-dev +``` + +Then build SigViewer: + +``` +cmake -P external/build_deps.cmake +cmake -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j$(nproc) +``` + +The executable is produced at `build/sigviewer`. + -Building external dependencies ------------------------------- ### Windows -Building libbiosig on Windows is currently not supported. -To build libxdf from source, follow these steps: +Install [MSYS2](https://www.msys2.org/) and open the MINGW64 shell. Install the required dependencies: -1. Download and unzip the [libxdf source](https://github.com/xdf-modules/libxdf/archive/v0.99.zip) (SigViewer 0.6.4 uses libxdf 0.99). -1. On the command line, run `qmake` followed by `mingw32-make` (or build the project with Qt Creator) (instead of `qmake`, you can also run `cmake .`). -2. Copy `xdf.h` into `$sigviewer/external/include` and `libxdf.a` to `$sigviewer/external/lib`. +``` +pacman -S --needed \ + mingw-w64-x86_64-gcc \ + mingw-w64-x86_64-cmake \ + mingw-w64-x86_64-ninja \ + mingw-w64-x86_64-qt6-base \ + mingw-w64-x86_64-qt6-tools \ + mingw-w64-x86_64-libiconv \ + autoconf \ + automake \ + make +``` -### macOS -To build libbiosig from source, follow these steps: +Then build SigViewer from the MINGW64 shell: -1. Download and unzip [BioSig for C/C++](https://sourceforge.net/projects/biosig/files/BioSig%20for%20C_C%2B%2B/src/biosig4c%2B%2B-1.9.4.src.tar.gz) into `$libbiosig` (SigViewer 0.6.4 uses libbiosig 1.9.4). -1. Change line 156 of `Makefile.in` to `CFLAGS += -mmacosx-version-min=10.9` (replace `10.13` with `10.9`). -1. In a terminal, change to `$libbiosig` and run `./configure`. -1. Run `make`. -1. Copy `biosig.h`, `biosig-dev.h`, `gdftime.h`, and `physicalunits.h` to `$sigviewer/external/include` and `libbiosig.a` to `$sigviewer/external/lib`. +``` +cmake -P external/build_deps.cmake +cmake -B build -DCMAKE_BUILD_TYPE=Release -G Ninja +cmake --build build +``` -To build libxdf from source, follow these steps: +The executable is produced at `build/sigviewer.exe`. -1. Download and unzip the [libxdf source](https://github.com/xdf-modules/libxdf/archive/v0.99.zip) to `$libxdf` (SigViewer 0.6.4 uses libxdf 0.99). -1. In a terminal, change to `$libxdf` and run `qmake` followed by `make` (instead of `qmake`, you can also run `cmake .`). -1. Copy `xdf.h` into `$sigviewer/external/include` and `libxdf.a` to `$sigviewer/external/lib`. +Collect the executable together with all required Qt DLLs and MinGW runtime libraries into a staging folder: -### Linux -To build libbiosig from source, follow these steps: +``` +mkdir -p build/sigviewer-windows +cp build/sigviewer.exe build/sigviewer-windows/ +cp src/images/sigviewer.ico build/sigviewer-windows/ +windeployqt6 --release build/sigviewer-windows/sigviewer.exe +# Copy any remaining MinGW DLL dependencies +find build/sigviewer-windows \( -name '*.exe' -o -name '*.dll' \) | xargs ldd 2>/dev/null \ + | awk '$3 ~ /\/mingw64\//' | awk '{print $3}' | sort -u \ + | while IFS= read -r dep; do + dest="build/sigviewer-windows/$(basename "$dep")" + [ -f "$dest" ] || cp "$dep" "$dest" + done +``` + +Then build the installer using [Inno Setup](https://jrsoftware.org/isinfo.php) (available from `winget install JRSoftware.InnoSetup`): + +``` +& 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' /Dversion= deploy\windows\sigviewer-windows.iss +``` + +The installer is written to `build/SigViewer-.exe`. + + +## Updating translations + +SigViewer's UI strings are kept in `.ts` files under `src/translations/`. After adding or changing translatable strings in the source code, update the `.ts` files by running: + +``` +cmake --build build --target sigviewer_lupdate +``` + +The resulting `.ts` files should be committed to the repository. The `.qm` binary files are compiled automatically from them during the regular build. + + +## Updating dependencies + +The script `external/build_deps.cmake` downloads the pinned source releases, builds them, and installs the resulting static libraries into the `external/` directory. You only need to run this once (or again after changing the pinned versions). -1. Download and unzip [BioSig for C/C++](https://sourceforge.net/projects/biosig/files/BioSig%20for%20C_C%2B%2B/src/biosig4c%2B%2B-1.9.4.src.tar.gz) into `$libbiosig` (SigViewer 0.6.4 uses libbiosig 1.9.4). -1. In a terminal, change to `$libbiosig` and run `./configure`. -1. Run `make`. -1. Copy `biosig.h`, `biosig-dev.h`, `gdftime.h`, and `physicalunits.h` to `$sigviewer/external/include` and `libbiosig.a` to `$sigviewer/external/lib`. +The pinned versions are defined in two places that must always be kept in sync: -To build libxdf from source, follow these steps: +- `CMakeLists.txt` (`LIBXDF_VERSION` and `LIBBIOSIG_VERSION` near the top of the file) +- `external/build_deps.cmake` (the same two variables near the top of that file) -1. Download and unzip the [libxdf source](https://github.com/xdf-modules/libxdf/archive/v0.99.zip) to `$libxdf` (SigViewer 0.6.4 uses libxdf 0.99). -1. In a terminal, change to `$libxdf` and run `qmake` followed by `make` (instead of `qmake`, you can also run `cmake .`). -1. Copy `xdf.h` into `$sigviewer/external/include` and `libxdf.a` to `$sigviewer/external/lib`. +To upgrade a dependency, update both of those variables to the new version and re-run `cmake -P external/build_deps.cmake`. Pass `-DFORCE_REBUILD=ON` to force a full rebuild even if the stamp file `external/versions.cmake` already records the same version, or use `-DFORCE_REBUILD_LIBXDF=ON` / `-DFORCE_REBUILD_LIBBIOSIG=ON` to rebuild only one of the two libraries. diff --git a/changelog.txt b/changelog.txt index cef2e146..25e06ecb 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,7 @@ Version X.X.X (*) Switch from Qt5 to Qt6 +(*) Switch to CMake +(*) Building works again on Windows (in addition to Linux and macOS) (B) Fix crash when exporting events to CSV (B) Fix evt import when sampling rates differ diff --git a/create-src.sh b/create-src.sh deleted file mode 100755 index ed809d6c..00000000 --- a/create-src.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -version_major=`sed -n -e 's/^VERSION_MAJOR = \([0-9]*\)$/\1/p' sigviewer.pro` -version_minor=`sed -n -e 's/^VERSION_MINOR = \([0-9]*\)$/\1/p' sigviewer.pro` -version_build=`sed -n -e 's/^VERSION_BUILD = \([0-9]*\)$/\1/p' sigviewer.pro` -version=$version_major.$version_minor.$version_build - -mkdir -p sigviewer-$version-src -cp * sigviewer-$version-src -cp -r deb_building_stuff sigviewer-$version-src -cp -r src sigviewer-$version-src/src - -rm sigviewer-$version-src/*.pro.user -find sigviewer-$version-src -name "Makefile*" -delete - -tar czvf sigviewer-$version-src.tar.gz --exclude=.* sigviewer-$version-src -rm -rf sigviewer-$version-src diff --git a/deploy/windows/README.md b/deploy/windows/README.md deleted file mode 100644 index ea00c793..00000000 --- a/deploy/windows/README.md +++ /dev/null @@ -1,11 +0,0 @@ -Install the [Qt Installer Framework](https://download.qt.io/official_releases/qt-installer-framework/) and make sure its bin folder is added to the path. - -The `sigviewer.exe` binary needs to be present in `$sigviewer/bin/release` - if not, build it. Open a command prompt, change into `$sigviewer/bin/release` and type: - - windeployqt sigviewer.exe - -Next, move the contents of the `$sigviewer/bin/release` folder into `$sigviewer/deploy/windows/packages/org.sigviewer.sigviewer/data`. Furthermore, copy the file `$sigviewer/src/images/sigviewer.ico` to this folder. - -Finally, change into `$sigviewer/deploy/windows` in the command prompt and type: - - binarycreator --offline-only -c config/config.xml -p packages sigviewer diff --git a/deploy/windows/config/config.xml b/deploy/windows/config/config.xml deleted file mode 100755 index 0bea81e1..00000000 --- a/deploy/windows/config/config.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - SigViewer - 0.6.4 - SigViewer - SigViewer Development Team - - SigViewer - @HomeDir@/SigViewer - sigviewer128.png - diff --git a/deploy/windows/config/sigviewer128.png b/deploy/windows/config/sigviewer128.png deleted file mode 100755 index 39893bfa..00000000 Binary files a/deploy/windows/config/sigviewer128.png and /dev/null differ diff --git a/deploy/windows/packages/org.sigviewer.sigviewer/meta/installscript.qs b/deploy/windows/packages/org.sigviewer.sigviewer/meta/installscript.qs deleted file mode 100755 index b0fca450..00000000 --- a/deploy/windows/packages/org.sigviewer.sigviewer/meta/installscript.qs +++ /dev/null @@ -1,17 +0,0 @@ -function Component() -{ - // default constructor - var programFiles = installer.environmentVariable("ProgramFiles"); - if (programFiles !== "") - installer.setValue("TargetDir", programFiles + "\/SigViewer"); -} - -Component.prototype.createOperations = function() -{ - component.createOperations(); - - if (systemInfo.productType === "windows") { - component.addOperation("CreateShortcut", "@TargetDir@/sigviewer.exe", "@StartMenuDir@/SigViewer.lnk", - "workingDirectory=@TargetDir@", "iconPath=@TargetDir@/sigviewer.ico"); - } -} diff --git a/deploy/windows/packages/org.sigviewer.sigviewer/meta/package.xml b/deploy/windows/packages/org.sigviewer.sigviewer/meta/package.xml deleted file mode 100755 index ceb61855..00000000 --- a/deploy/windows/packages/org.sigviewer.sigviewer/meta/package.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - SigViewer - SigViewer is a viewing application for biosignals - 0.6.4 - 2019-04-23 - true - - diff --git a/deploy/windows/sigviewer-windows.iss b/deploy/windows/sigviewer-windows.iss new file mode 100644 index 00000000..2b19e5c7 --- /dev/null +++ b/deploy/windows/sigviewer-windows.iss @@ -0,0 +1,36 @@ +[Setup] +AppId={{3A5B7C8D-1E2F-4A6B-8C9D-0E1F2A3B4C5D} +AppName=SigViewer +AppVersion={#version} +AppVerName=SigViewer {#version} +AppPublisher=SigViewer Developers +AppPublisherURL=https://github.com/cbrnr/sigviewer +AppSupportURL=https://github.com/cbrnr/sigviewer +AppUpdatesURL=https://github.com/cbrnr/sigviewer/releases +DefaultDirName={autopf}\SigViewer +PrivilegesRequired=lowest +PrivilegesRequiredOverridesAllowed=dialog +UsePreviousAppDir=no +DisableProgramGroupPage=yes +OutputBaseFilename=SigViewer-{#version} +OutputDir=..\..\build +Compression=lzma2 +SolidCompression=yes +WizardStyle=modern +SetupIconFile=..\..\src\images\sigviewer.ico + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" + +[Files] +Source: "..\..\build\sigviewer-windows\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs + +[Icons] +Name: "{autoprograms}\SigViewer"; Filename: "{app}\sigviewer.exe" +Name: "{autodesktop}\SigViewer"; Filename: "{app}\sigviewer.exe"; Tasks: desktopicon + +[Run] +Filename: "{app}\sigviewer.exe"; Description: "{cm:LaunchProgram,SigViewer}"; Flags: nowait postinstall skipifsilent diff --git a/external/build_deps.cmake b/external/build_deps.cmake new file mode 100644 index 00000000..f3b39803 --- /dev/null +++ b/external/build_deps.cmake @@ -0,0 +1,260 @@ +# build_deps.cmake +# +# Builds the external dependencies of SigViewer from source: +# libxdf — downloaded from the GitHub releases page and built with CMake +# libbiosig — downloaded from SourceForge and built with autoconf and make +# +# Both are installed into the external/ directory, and external/versions.cmake +# is written so that the main build can confirm the correct versions are present. +# +# Usage (from the repository root): +# +# cmake [-DDEPS_DIR=] [-DFORCE_REBUILD=ON] -P external/build_deps.cmake +# +# DEPS_DIR defaults to /external. Override it if you want the +# artifacts placed elsewhere and will pass the same path via -DDEPS_DIR= +# when configuring the main build. +# +# By default each library is skipped when it is already present at the +# correct version (as recorded in external/versions.cmake). Pass +# -DFORCE_REBUILD=ON to always rebuild everything from scratch, or use +# -DFORCE_REBUILD_LIBXDF=ON / -DFORCE_REBUILD_LIBBIOSIG=ON to force a +# rebuild of just that one library. +# +# Requirements: +# libxdf — CMake, a C++20-capable compiler +# libbiosig — autoconf, make, a C/C++ compiler (Unix, macOS, or MSYS2 on Windows) +# +# -- Maintainer notes -------------------------------------------------------- +# Both libraries are built from source; only the version numbers ever need +# updating when upgrading a dependency. +# +# When upgrading libxdf: +# 1. Update LIBXDF_VERSION below (and in CMakeLists.txt). +# +# When upgrading libbiosig: +# 1. Update LIBBIOSIG_VERSION below (and in CMakeLists.txt). +# ---------------------------------------------------------------------------- + +cmake_minimum_required(VERSION 3.21) + +# -- Pinned versions (must match CMakeLists.txt) ----------------------------- +set(LIBXDF_VERSION "0.99.10") +set(LIBBIOSIG_VERSION "3.9.4") + +# -- Resolve the destination directory --------------------------------------- +if(NOT DEFINED DEPS_DIR) + # This script lives in external/, so its parent directory is DEPS_DIR. + cmake_path(GET CMAKE_CURRENT_LIST_FILE PARENT_PATH DEPS_DIR) +endif() +message(STATUS "Building dependencies into: ${DEPS_DIR}") + +# -- Read the installed version stamp (written at the end of this script) ---- +set(_versions_file "${DEPS_DIR}/versions.cmake") +if(EXISTS "${_versions_file}") + include("${_versions_file}") +else() + set(LIBXDF_VERSION_INSTALLED "") + set(LIBBIOSIG_VERSION_INSTALLED "") +endif() + +# Per-library force flags override the stamp. +if(FORCE_REBUILD OR FORCE_REBUILD_LIBXDF) + set(LIBXDF_VERSION_INSTALLED "") +endif() +if(FORCE_REBUILD OR FORCE_REBUILD_LIBBIOSIG) + set(LIBBIOSIG_VERSION_INSTALLED "") +endif() + +# -- Helper: build libxdf from source ---------------------------------------- +function(_build_libxdf_from_source version dest_dir) + set(_src_url "https://github.com/xdf-modules/libxdf/archive/refs/tags/v${version}.tar.gz") + set(_src_archive "${dest_dir}/_libxdf-${version}-src.tar.gz") + set(_tmp_dir "${dest_dir}/_libxdf-${version}-tmp") + set(_bld_dir "${dest_dir}/_libxdf-${version}-build") + set(_inst_dir "${dest_dir}/_libxdf-${version}-install") + + message(STATUS "Downloading libxdf ${version} source…") + file(DOWNLOAD "${_src_url}" "${_src_archive}" + SHOW_PROGRESS + STATUS _dl_status + ) + list(GET _dl_status 0 _dl_code) + list(GET _dl_status 1 _dl_msg) + if(NOT _dl_code EQUAL 0) + file(REMOVE "${_src_archive}") + message(FATAL_ERROR "Download failed for ${_src_url}:\n ${_dl_msg}") + endif() + + message(STATUS "Extracting libxdf source…") + file(MAKE_DIRECTORY "${_tmp_dir}") + file(ARCHIVE_EXTRACT INPUT "${_src_archive}" DESTINATION "${_tmp_dir}") + file(REMOVE "${_src_archive}") + + # GitHub archives extract into a single subdirectory; find it. + file(GLOB _src_dirs LIST_DIRECTORIES true "${_tmp_dir}/*") + list(GET _src_dirs 0 _src_dir) + + message(STATUS "Configuring libxdf…") + execute_process( + COMMAND "${CMAKE_COMMAND}" + -S "${_src_dir}" + -B "${_bld_dir}" + -DCMAKE_BUILD_TYPE=Release + -DBUILD_SHARED_LIBS=OFF + -DXDF_NO_SYSTEM_PUGIXML=ON + -DCMAKE_INSTALL_PREFIX=${_inst_dir} + RESULT_VARIABLE _cfg_result + ) + if(NOT _cfg_result EQUAL 0) + message(FATAL_ERROR "libxdf configure step failed (exit code ${_cfg_result})") + endif() + + message(STATUS "Building libxdf…") + execute_process( + COMMAND "${CMAKE_COMMAND}" --build "${_bld_dir}" --config Release --parallel + RESULT_VARIABLE _bld_result + ) + if(NOT _bld_result EQUAL 0) + message(FATAL_ERROR "libxdf build step failed (exit code ${_bld_result})") + endif() + + message(STATUS "Installing libxdf…") + execute_process( + COMMAND "${CMAKE_COMMAND}" --install "${_bld_dir}" + RESULT_VARIABLE _inst_result + ) + if(NOT _inst_result EQUAL 0) + message(FATAL_ERROR "libxdf install step failed (exit code ${_inst_result})") + endif() + + # Copy the header and static library into the flat external/{include,lib} layout. + file(GLOB _headers "${_inst_dir}/include/xdf.h") + file(GLOB _libs "${_inst_dir}/lib/libxdf.a" "${_inst_dir}/lib64/libxdf.a") + file(COPY ${_headers} DESTINATION "${dest_dir}/include") + file(COPY ${_libs} DESTINATION "${dest_dir}/lib") + + # Clean up all temporary directories. + file(REMOVE_RECURSE "${_tmp_dir}" "${_bld_dir}" "${_inst_dir}") + + message(STATUS "libxdf ${version} built and installed.") +endfunction() + +# -- Helper: build libbiosig from source ------------------------------------- +function(_build_libbiosig_from_source version dest_dir) + set(_src_url "https://sourceforge.net/projects/biosig/files/BioSig%20for%20C_C%2B%2B/src/biosig-${version}.src.tar.xz/download") + set(_src_archive "${dest_dir}/_libbiosig-${version}-src.tar.xz") + set(_tmp_dir "${dest_dir}/_libbiosig-${version}-tmp") + + message(STATUS "Downloading libbiosig ${version} source…") + file(DOWNLOAD "${_src_url}" "${_src_archive}" + SHOW_PROGRESS + STATUS _dl_status + ) + list(GET _dl_status 0 _dl_code) + list(GET _dl_status 1 _dl_msg) + if(NOT _dl_code EQUAL 0) + file(REMOVE "${_src_archive}") + message(FATAL_ERROR "Download failed for ${_src_url}:\n ${_dl_msg}") + endif() + + message(STATUS "Extracting libbiosig source…") + file(MAKE_DIRECTORY "${_tmp_dir}") + file(ARCHIVE_EXTRACT INPUT "${_src_archive}" DESTINATION "${_tmp_dir}") + file(REMOVE "${_src_archive}") + + # Source tarballs extract into a single subdirectory; find it. + file(GLOB _src_dirs LIST_DIRECTORIES true "${_tmp_dir}/*") + list(GET _src_dirs 0 _src_dir) + + find_program(_sh NAMES sh bash REQUIRED) + + message(STATUS "Configuring libbiosig…") + execute_process( + COMMAND "${_sh}" "${_src_dir}/configure" + WORKING_DIRECTORY "${_src_dir}" + RESULT_VARIABLE _cfg_result + ) + if(NOT _cfg_result EQUAL 0) + message(FATAL_ERROR "libbiosig configure step failed (exit code ${_cfg_result})") + endif() + + find_program(_make_exe NAMES make gmake REQUIRED) + + # GCC 14 made implicit function declarations a hard error. biosig4c++ + # was written for older compilers and has two related problems: + # + # 1. win32/getline.c defines getline() before getdelim(), with no forward + # declaration between them, so GCC sees an implicit declaration of + # getdelim inside getline. Fix: prepend a forward declaration. + # + # 2. Several other source files (e.g. t210/sopen_abf_read.c) call getline() + # without including any header that declares it. Fix: patch the + # hand-written biosig4c++/Makefile to add the flag that downgrades the + # error back to a warning, which is all older GCC ever emitted for this. + if(CMAKE_HOST_WIN32) + set(_getline_c "${_src_dir}/biosig4c++/win32/getline.c") + file(READ "${_getline_c}" _getline_content) + file(WRITE "${_getline_c}" + "#include \n" + "#include \n" + "ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);\n" + "${_getline_content}" + ) + + set(_biosig_mf "${_src_dir}/biosig4c++/Makefile") + file(READ "${_biosig_mf}" _mf_content) + string(REPLACE "-Wno-deprecated" "-Wno-deprecated -Wno-implicit-function-declaration" + _mf_content "${_mf_content}") + file(WRITE "${_biosig_mf}" "${_mf_content}") + endif() + + message(STATUS "Building libbiosig…") + execute_process( + COMMAND "${_make_exe}" lib + WORKING_DIRECTORY "${_src_dir}" + RESULT_VARIABLE _bld_result + ) + if(NOT _bld_result EQUAL 0) + message(FATAL_ERROR "libbiosig build step failed (exit code ${_bld_result})") + endif() + + # Copy libbiosig.a and all public headers into the flat external/{lib,include} + # layout. make lib builds everything inside the biosig4c++ subdirectory. + file(COPY "${_src_dir}/biosig4c++/libbiosig.a" DESTINATION "${dest_dir}/lib") + file(GLOB _biosig_headers "${_src_dir}/biosig4c++/*.h") + file(COPY ${_biosig_headers} DESTINATION "${dest_dir}/include") + + # Clean up the temporary directory. + file(REMOVE_RECURSE "${_tmp_dir}") + + message(STATUS "libbiosig ${version} built and installed.") +endfunction() + +# -- Build each library only when needed ------------------------------------ +file(MAKE_DIRECTORY "${DEPS_DIR}/include" "${DEPS_DIR}/lib") + +if(LIBXDF_VERSION_INSTALLED STREQUAL LIBXDF_VERSION) + message(STATUS "libxdf ${LIBXDF_VERSION} is already up to date — skipping.") +else() + _build_libxdf_from_source("${LIBXDF_VERSION}" "${DEPS_DIR}") +endif() + +if(LIBBIOSIG_VERSION_INSTALLED STREQUAL LIBBIOSIG_VERSION) + message(STATUS "libbiosig ${LIBBIOSIG_VERSION} is already up to date — skipping.") +else() + _build_libbiosig_from_source("${LIBBIOSIG_VERSION}" "${DEPS_DIR}") +endif() + +# -- Write the version stamp file -------------------------------------------- +# This file is read by CMakeLists.txt to verify that the correct versions +# are present before configuring the build. +file(WRITE "${_versions_file}" + "# Auto-generated by build_deps.cmake — do not edit manually.\n" + "set(LIBXDF_VERSION_INSTALLED \"${LIBXDF_VERSION}\")\n" + "set(LIBBIOSIG_VERSION_INSTALLED \"${LIBBIOSIG_VERSION}\")\n" +) + +message(STATUS "") +message(STATUS "Dependencies ready. You can now configure the build:") +message(STATUS " cmake -S . -B build") diff --git a/sigviewer.pro b/sigviewer.pro deleted file mode 100644 index 5d161227..00000000 --- a/sigviewer.pro +++ /dev/null @@ -1,81 +0,0 @@ -TEMPLATE = app -DESTDIR = bin -TARGET = sigviewer - -VERSION_MAJOR = 0 -VERSION_MINOR = 6 -VERSION_BUILD = 4 - -DEFINES += \ - "VERSION_MAJOR=$$VERSION_MAJOR" \ - "VERSION_MINOR=$$VERSION_MINOR" \ - "VERSION_BUILD=$$VERSION_BUILD" - -QT += core gui widgets xml - -BUILD_DIR = $$PWD/tmp -TARGET_DIR = $$PWD/bin - -CONFIG(debug, debug|release) { - DEFINES -= QT_NO_DEBUG_OUTPUT - DESTDIR = $$TARGET_DIR/debug - OBJECTS_DIR = $$BUILD_DIR/debug - MOC_DIR = $$BUILD_DIR/debug - RCC_DIR = $$BUILD_DIR/debug - UI_DIR = $$BUILD_DIR/debug -} -CONFIG(release, debug|release) { - DEFINES += QT_NO_DEBUG_OUTPUT - DESTDIR = $$TARGET_DIR/release - OBJECTS_DIR = $$BUILD_DIR/release - MOC_DIR = $$BUILD_DIR/release - RCC_DIR = $$BUILD_DIR/release - UI_DIR = $$BUILD_DIR/release -} - -CONFIG += warn_on link_prl qt thread c++17 - -macx { - QMAKE_MACOSX_DEPLOYMENT_TARGET = 11 - LIBS += -liconv -} - -INCLUDEPATH += \ - $$PWD/external/include \ - $$PWD/src - -LIBS += \ - -L$$PWD/external/lib \ - -lbiosig -lxdf - -RESOURCES = $$PWD/src/src.qrc -win32:RC_FILE = $$PWD/src/src.rc -ICON = $$PWD/src/sigviewer.icns - -TRANSLATIONS += \ - $$PWD/src/translations/sigviewer_de.ts \ - $$PWD/src/translations/sigviewer_en.ts - -include($$PWD/src/base/base.pri) -include($$PWD/src/signal_processing/signal_processing.pri) -include($$PWD/src/file_handling_impl/file_handling_impl.pri) -include($$PWD/src/file_handling/file_handling.pri) -include($$PWD/src/gui/gui.pri) -include($$PWD/src/gui_impl/gui_impl.pri) -include($$PWD/src/editing_commands/editing_commands.pri) -include($$PWD/src/commands/commands.pri) -include($$PWD/src/tests/tests.pri) - -HEADERS += \ - $$PWD/src/application_context_impl.h \ - $$PWD/src/command_executer.h \ - $$PWD/src/file_context.h \ - $$PWD/src/tab_context.h - -SOURCES += \ - $$PWD/src/main.cpp \ - $$PWD/src/application_context_impl.cpp \ - $$PWD/src/file_context.cpp \ - $$PWD/src/tab_context.cpp - -QMAKE_CFLAGS += -std=c99 diff --git a/src/base/base.pri b/src/base/base.pri deleted file mode 100644 index ba2a3cae..00000000 --- a/src/base/base.pri +++ /dev/null @@ -1,19 +0,0 @@ -HEADERS += \ - $$PWD/application_states.h \ - $$PWD/data_block.h \ - $$PWD/exception.h \ - $$PWD/file_states.h \ - $$PWD/fixed_data_block.h \ - $$PWD/math_utils.h \ - $$PWD/signal_channel.h \ - $$PWD/signal_event.h \ - $$PWD/sigviewer_user_types.h \ - $$PWD/tab_states.h - -SOURCES += \ - $$PWD/data_block.cpp \ - $$PWD/exception.cpp \ - $$PWD/fixed_data_block.cpp \ - $$PWD/math_utils.cpp \ - $$PWD/signal_channel.cpp \ - $$PWD/signal_event.cpp diff --git a/src/commands/commands.pri b/src/commands/commands.pri deleted file mode 100644 index 62d29ddc..00000000 --- a/src/commands/commands.pri +++ /dev/null @@ -1,7 +0,0 @@ -HEADERS += \ - $$PWD/convert_file_command.h \ - $$PWD/open_file_command.h - -SOURCES += \ - $$PWD/convert_file_command.cpp \ - $$PWD/open_file_command.cpp diff --git a/src/editing_commands/editing_commands.pri b/src/editing_commands/editing_commands.pri deleted file mode 100644 index 908a4b50..00000000 --- a/src/editing_commands/editing_commands.pri +++ /dev/null @@ -1,15 +0,0 @@ -HEADERS += \ - $$PWD/change_channel_undo_command.h \ - $$PWD/change_type_undo_command.h \ - $$PWD/delete_event_undo_command.h \ - $$PWD/macro_undo_command.h \ - $$PWD/new_event_undo_command.h \ - $$PWD/resize_event_undo_command.h - -SOURCES += \ - $$PWD/change_channel_undo_command.cpp \ - $$PWD/change_type_undo_command.cpp \ - $$PWD/delete_event_undo_command.cpp \ - $$PWD/macro_undo_command.cpp \ - $$PWD/new_event_undo_command.cpp \ - $$PWD/resize_event_undo_command.cpp diff --git a/src/file_handling/channel_manager.cpp b/src/file_handling/channel_manager.cpp index 674797c6..8f419ec2 100644 --- a/src/file_handling/channel_manager.cpp +++ b/src/file_handling/channel_manager.cpp @@ -65,7 +65,7 @@ float64 ChannelManager::getMinValue (std::set const& channels) const if (!min_max_initialized_) initMinMax(); float64 min = std::numeric_limits::max(); - foreach (ChannelID channel, channels) + for (const auto channel : channels) min = std::min (min, min_values_[channel]); return min; } @@ -77,7 +77,7 @@ float64 ChannelManager::getMaxValue (std::set const& channels) const initMinMax(); float64 max = std::numeric_limits::min(); - foreach (ChannelID channel, channels) + for (const auto channel : channels) max = std::max (max, max_values_[channel]); return max; } @@ -111,7 +111,7 @@ void ChannelManager::initMinMax () const { if (min_max_initialized_) return; - foreach (ChannelID id, getChannels()) + for (const auto id : getChannels()) { QSharedPointer data = getData (id, 0, getNumberSamples ()); max_values_[id] = data->getMax (); diff --git a/src/file_handling/file_handling.pri b/src/file_handling/file_handling.pri deleted file mode 100644 index 6ae9f381..00000000 --- a/src/file_handling/file_handling.pri +++ /dev/null @@ -1,16 +0,0 @@ -HEADERS += \ - $$PWD/basic_header.h \ - $$PWD/channel_manager.h \ - $$PWD/event_manager.h \ - $$PWD/file_handler_factory.h \ - $$PWD/file_signal_reader.h \ - $$PWD/file_signal_reader_factory.h \ - $$PWD/file_signal_writer.h \ - $$PWD/file_signal_writer_factory.h - -SOURCES += \ - $$PWD/basic_header.cpp \ - $$PWD/channel_manager.cpp \ - $$PWD/file_signal_reader_factory.cpp \ - $$PWD/file_signal_writer_factory.cpp \ - $$PWD/file_signal_reader.cpp diff --git a/src/file_handling_impl/biosig_writer.cpp b/src/file_handling_impl/biosig_writer.cpp index 83f2637b..d20a2f61 100644 --- a/src/file_handling_impl/biosig_writer.cpp +++ b/src/file_handling_impl/biosig_writer.cpp @@ -52,7 +52,7 @@ QString BioSigWriter::saveEventsToSignalFile (QSharedPointer QList events; - foreach (EventType type, types) + for (const auto type : types) events.append(event_manager->getEvents(type)); unsigned number_events = events.size(); diff --git a/src/file_handling_impl/event_manager_impl.cpp b/src/file_handling_impl/event_manager_impl.cpp index a3f8beff..34828d63 100644 --- a/src/file_handling_impl/event_manager_impl.cpp +++ b/src/file_handling_impl/event_manager_impl.cpp @@ -29,7 +29,7 @@ EventManagerImpl::EventManagerImpl (FileSignalReader const& reader) QSharedPointer ( new QMutex)); - position_event_map_.insertMulti (signal_events[index]->getPosition (), next_free_id_); + position_event_map_.insert (signal_events[index]->getPosition (), next_free_id_); if (!event_table_reader_.entryExists (signal_events[index]->getType())) event_table_reader_.addEntry (signal_events[index]->getType()); @@ -83,7 +83,7 @@ void EventManagerImpl::updateAndUnlockEvent (EventID id) return; position_event_map_.remove (temp_event_position_map_[id], id); temp_event_position_map_.remove (id); - position_event_map_.insertMulti (event_map_[id]->getPosition (), id); + position_event_map_.insert (event_map_[id]->getPosition (), id); mutex_map_[id]->unlock (); emit eventChanged (id); emit changed (); @@ -107,7 +107,7 @@ QSharedPointer EventManagerImpl::createEvent ( new SignalEvent(pos, type, sample_rate_, stream_id, channel_id, duration, id)); event_map_[id] = new_event; mutex_map_[id] = QSharedPointer (new QMutex); - position_event_map_.insertMulti (pos, id); + position_event_map_.insert (pos, id); emit eventCreated (new_event); emit changed (); diff --git a/src/file_handling_impl/event_table_file_reader.cpp b/src/file_handling_impl/event_table_file_reader.cpp index be82d9cd..40bc8d4e 100644 --- a/src/file_handling_impl/event_table_file_reader.cpp +++ b/src/file_handling_impl/event_table_file_reader.cpp @@ -34,14 +34,14 @@ bool EventTableFileReader::load() char g[10]; uint16_t k; for (k = 0; EventCodeGroups[k].groupid < 0xffff; k++) { - sprintf(g, "0x%04x", EventCodeGroups[k].groupid); + snprintf(g, sizeof(g), "0x%04x", EventCodeGroups[k].groupid); QString group_id = QString(g); group_id2name_[group_id] = QString(EventCodeGroups[k].GroupDescription); event_group_ids_ << group_id; } EventItem item; for (k = 0; ETD[k].typ ; k++) { - sprintf(g, "0x%04x", ETD[k].groupid); + snprintf(g, sizeof(g), "0x%04x", ETD[k].groupid); QString group_id = QString(g); item.name = QString(ETD[k].desc); item.group_id = group_id; diff --git a/src/file_handling_impl/evt_writer.cpp b/src/file_handling_impl/evt_writer.cpp index 61f422b0..037abc19 100644 --- a/src/file_handling_impl/evt_writer.cpp +++ b/src/file_handling_impl/evt_writer.cpp @@ -53,7 +53,7 @@ QString EVTWriter::save(QSharedPointer file_context, { QSharedPointer event_manager = file_context->getEventManager(); QList events; - foreach (EventType type, types) + for (const auto type : types) events.append(event_manager->getEvents(type)); unsigned number_events = events.size(); diff --git a/src/file_handling_impl/file_handling_impl.pri b/src/file_handling_impl/file_handling_impl.pri deleted file mode 100644 index 7b9b9f9a..00000000 --- a/src/file_handling_impl/file_handling_impl.pri +++ /dev/null @@ -1,20 +0,0 @@ -HEADERS += \ - $$PWD/biosig_basic_header.h \ - $$PWD/biosig_reader.h \ - $$PWD/biosig_writer.h \ - $$PWD/channel_manager_impl.h \ - $$PWD/event_manager_impl.h \ - $$PWD/event_table_file_reader.h \ - $$PWD/evt_writer.h \ - $$PWD/file_handler_factory_registrator.h \ - $$PWD/xdf_reader.h - -SOURCES += \ - $$PWD/biosig_basic_header.cpp \ - $$PWD/biosig_reader.cpp \ - $$PWD/biosig_writer.cpp \ - $$PWD/channel_manager_impl.cpp \ - $$PWD/event_manager_impl.cpp \ - $$PWD/event_table_file_reader.cpp \ - $$PWD/evt_writer.cpp \ - $$PWD/xdf_reader.cpp diff --git a/src/file_handling_impl/gdf/gdf_file_signal_writer.cpp b/src/file_handling_impl/gdf/gdf_file_signal_writer.cpp index 017efe04..0b9ab4a1 100644 --- a/src/file_handling_impl/gdf/gdf_file_signal_writer.cpp +++ b/src/file_handling_impl/gdf/gdf_file_signal_writer.cpp @@ -68,7 +68,7 @@ QString GDFFileSignalWriter::saveEventsToSignalFile (QSharedPointersetSamplingRate (event_sampling_rate); QList events; - foreach (EventType type, types) + for (const auto type : types) events.append(event_manager->getEvents(type)); for (int index = 0; index < events.size(); index++) @@ -105,7 +105,7 @@ QString GDFFileSignalWriter::save (QSharedPointer file_contex ChannelManager const& channel_manager = file_context->getChannelManager(); - foreach (ChannelID channel, channel_manager.getChannels()) + for (const auto channel : channel_manager.getChannels()) { writer.createSignal (channel); writer.getSignalHeader(channel).set_label (channel_manager.getChannelLabel (channel).toStdString()); @@ -146,7 +146,7 @@ QString GDFFileSignalWriter::save (QSharedPointer file_contex QString progressbar_string = "Writing samples..."; for (unsigned sample_index = 0; sample_index < channel_manager.getNumberSamples(); sample_index++) { - foreach (ChannelID channel_id, channel_manager.getChannels()) + for (const auto channel_id : channel_manager.getChannels()) { writer.addSamplePhys (channel_id, (*(channel_manager.getData (channel_id, sample_index, 1)))[0]); } diff --git a/src/gui/color_manager.cpp b/src/gui/color_manager.cpp index 7f12daeb..4b9d2389 100644 --- a/src/gui/color_manager.cpp +++ b/src/gui/color_manager.cpp @@ -197,9 +197,11 @@ void ColorManager::loadDefaultEventColors () { QFile color_settings_file (":/color_settings.xml"); QDomDocument color_doc; - QString error_msg; - int error_line; - color_doc.setContent (&color_settings_file, true, &error_msg, &error_line); +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + color_doc.setContent(&color_settings_file, QDomDocument::ParseOption::UseNamespaceProcessing); +#else + color_doc.setContent(&color_settings_file, true); +#endif QDomElement root = color_doc.documentElement(); QDomNodeList default_elements = root.elementsByTagName("default"); diff --git a/src/gui/gui.pri b/src/gui/gui.pri deleted file mode 100644 index bdb9294d..00000000 --- a/src/gui/gui.pri +++ /dev/null @@ -1,22 +0,0 @@ -HEADERS += \ - $$PWD/application_context.h \ - $$PWD/background_processes.h \ - $$PWD/color_manager.h \ - $$PWD/event_view.h \ - $$PWD/gui_action_command.h \ - $$PWD/gui_action_factory.h \ - $$PWD/gui_action_factory_registrator.h \ - $$PWD/main_window_model.h \ - $$PWD/progress_bar.h \ - $$PWD/signal_view_settings.h \ - $$PWD/signal_visualisation_model.h \ - $$PWD/signal_visualisation_modes.h \ - $$PWD/signal_visualisation_view.h - -SOURCES += \ - $$PWD/background_processes.cpp \ - $$PWD/color_manager.cpp \ - $$PWD/gui_action_command.cpp \ - $$PWD/gui_action_factory.cpp \ - $$PWD/signal_view_settings.cpp \ - $$PWD/signal_visualisation_model.cpp diff --git a/src/gui/gui_action_command.cpp b/src/gui/gui_action_command.cpp index ecf702a6..4f78169c 100644 --- a/src/gui/gui_action_command.cpp +++ b/src/gui/gui_action_command.cpp @@ -208,9 +208,10 @@ bool GuiActionCommand::disableIfNoSignalIsVisualised (QStringList const &actions { bool no_signal_is_visualised = currentVisModel().isNull(); - if (no_signal_is_visualised) - foreach (QString action, actions) + if (no_signal_is_visualised) { + for (const auto& action : actions) action_map_[action]->setDisabled (no_signal_is_visualised); + } return no_signal_is_visualised; } diff --git a/src/gui_impl/commands/commands.pri b/src/gui_impl/commands/commands.pri deleted file mode 100644 index 9d0d52c7..00000000 --- a/src/gui_impl/commands/commands.pri +++ /dev/null @@ -1,25 +0,0 @@ -HEADERS += \ - $$PWD/adapt_channel_view_gui_command.h \ - $$PWD/adapt_event_view_gui_command.h \ - $$PWD/close_file_gui_command.h \ - $$PWD/event_editing_gui_command.h \ - $$PWD/help_gui_command.h \ - $$PWD/mouse_mode_gui_command.h \ - $$PWD/open_file_gui_command.h \ - $$PWD/save_gui_command.h \ - $$PWD/signal_processing_gui_command.h \ - $$PWD/undo_redo_gui_command.h \ - $$PWD/zoom_gui_command.h - -SOURCES += \ - $$PWD/adapt_channel_view_gui_command.cpp \ - $$PWD/adapt_event_view_gui_command.cpp \ - $$PWD/close_file_gui_command.cpp \ - $$PWD/event_editing_gui_command.cpp \ - $$PWD/help_gui_command.cpp \ - $$PWD/mouse_mode_gui_command.cpp \ - $$PWD/open_file_gui_command.cpp \ - $$PWD/save_gui_command.cpp \ - $$PWD/signal_processing_gui_command.cpp \ - $$PWD/undo_redo_gui_command.cpp \ - $$PWD/zoom_gui_command.cpp diff --git a/src/gui_impl/commands/save_gui_command.cpp b/src/gui_impl/commands/save_gui_command.cpp index 3aeeabff..68ae1846 100644 --- a/src/gui_impl/commands/save_gui_command.cpp +++ b/src/gui_impl/commands/save_gui_command.cpp @@ -340,8 +340,8 @@ void SaveGuiCommand::exportEventsToCSV () ->getCurrentFileContext()->getEventManager(); struct row { - unsigned long pos; - unsigned long dur; + size_t pos; + size_t dur; int chan; int id; QString name; diff --git a/src/gui_impl/commands/signal_processing_gui_command.cpp b/src/gui_impl/commands/signal_processing_gui_command.cpp index 0bba8d59..833dfc50 100644 --- a/src/gui_impl/commands/signal_processing_gui_command.cpp +++ b/src/gui_impl/commands/signal_processing_gui_command.cpp @@ -94,7 +94,7 @@ void SignalProcessingGuiCommand::calculateMeanAndStandardDeviation () processed_channel_manager->setXAxisUnitLabel(channel_manager.getXAxisUnitLabel()); ChannelID new_channel_id = 0; QList events (event_manager->getEvents(event_dialog->getSelectedEventType ())); - foreach (ChannelID channel_id, event_dialog->getSelectedChannels ()) + for (const auto channel_id : event_dialog->getSelectedChannels ()) { std::list > data; @@ -154,7 +154,7 @@ void SignalProcessingGuiCommand::calculatePowerSpectrum () ProgressBar::instance().initAndShow (event_dialog->getSelectedChannels ().size(), tr("Fourier Transformation"), applicationContext()); - foreach (ChannelID channel_id, event_dialog->getSelectedChannels ()) + for (const auto channel_id : event_dialog->getSelectedChannels ()) { ProgressBar::instance().increaseValue (1, channel_manager.getChannelLabel(channel_id)); std::list > data; diff --git a/src/gui_impl/commands/zoom_gui_command.cpp b/src/gui_impl/commands/zoom_gui_command.cpp index c1f40cd7..3de49b75 100644 --- a/src/gui_impl/commands/zoom_gui_command.cpp +++ b/src/gui_impl/commands/zoom_gui_command.cpp @@ -122,15 +122,15 @@ void ZoomGuiCommand::init () QList zoomInVertical; - zoomInVertical << QKeySequence::ZoomIn << Qt::CTRL + Qt::Key_Equal; + zoomInVertical << QKeySequence::ZoomIn << (Qt::CTRL | Qt::Key_Equal); getQAction(ZOOM_IN_VERTICAL_())->setShortcuts(zoomInVertical); QList zoomInHorizontal; - zoomInHorizontal << Qt::ALT + Qt::Key_Plus << Qt::ALT + Qt::Key_Equal; + zoomInHorizontal << (Qt::ALT | Qt::Key_Plus) << (Qt::ALT | Qt::Key_Equal); getQAction(ZOOM_IN_HORIZONTAL_())->setShortcuts(zoomInHorizontal); setShortcut (ZOOM_OUT_VERTICAL_(), QKeySequence::ZoomOut); - setShortcut (ZOOM_OUT_HORIZONTAL_(), Qt::ALT + Qt::Key_Minus); + setShortcut (ZOOM_OUT_HORIZONTAL_(), Qt::ALT | Qt::Key_Minus); resetActionTriggerSlot (GOTO_(), SLOT(goTo())); resetActionTriggerSlot (ZOOM_IN_VERTICAL_(), SLOT(zoomInVertical())); diff --git a/src/gui_impl/dialogs/channel_selection_dialog.cpp b/src/gui_impl/dialogs/channel_selection_dialog.cpp index ed2747f3..f0d9558d 100644 --- a/src/gui_impl/dialogs/channel_selection_dialog.cpp +++ b/src/gui_impl/dialogs/channel_selection_dialog.cpp @@ -105,7 +105,7 @@ ChannelSelectionDialog::ChannelSelectionDialog(ChannelManager const& channel_man else { int row = 0; - foreach (ChannelID id, channel_manager_.getChannels()) + for (const auto id : channel_manager_.getChannels()) { QTreeWidgetItem* channelItem = new QTreeWidgetItem (ui_.treeWidget); diff --git a/src/gui_impl/dialogs/dialogs.pri b/src/gui_impl/dialogs/dialogs.pri deleted file mode 100644 index 0b27ba5e..00000000 --- a/src/gui_impl/dialogs/dialogs.pri +++ /dev/null @@ -1,23 +0,0 @@ -HEADERS += \ - $$PWD/basic_header_info_dialog.h \ - $$PWD/channel_selection_dialog.h \ - $$PWD/event_time_selection_dialog.h \ - $$PWD/event_types_selection_dialog.h \ - $$PWD/scale_channel_dialog.h \ - $$PWD/resampling_dialog.h - -SOURCES += \ - $$PWD/basic_header_info_dialog.cpp \ - $$PWD/channel_selection_dialog.cpp \ - $$PWD/event_time_selection_dialog.cpp \ - $$PWD/event_types_selection_dialog.cpp \ - $$PWD/scale_channel_dialog.cpp \ - $$PWD/resampling_dialog.cpp - -FORMS += \ - $$PWD/about_dialog.ui \ - $$PWD/channel_dialog.ui \ - $$PWD/event_time_selection_dialog.ui \ - $$PWD/event_type_selection_dialog.ui \ - $$PWD/scale_channel_dialog.ui \ - $$PWD/resampling_dialog.ui diff --git a/src/gui_impl/dialogs/event_time_selection_dialog.cpp b/src/gui_impl/dialogs/event_time_selection_dialog.cpp index 59702049..180c8e26 100644 --- a/src/gui_impl/dialogs/event_time_selection_dialog.cpp +++ b/src/gui_impl/dialogs/event_time_selection_dialog.cpp @@ -24,13 +24,13 @@ EventTimeSelectionDialog::EventTimeSelectionDialog (std::set const& s { ui_.setupUi (this); - foreach (ChannelID channel_id, shown_channels) + for (const auto channel_id : shown_channels) { QListWidgetItem* item = new QListWidgetItem (channel_manager.getChannelLabel(channel_id), ui_.list_widget_); item->setData (Qt::UserRole, channel_id); } - foreach (EventType event_type, shown_event_types_) + for (const auto event_type : shown_event_types_) { if (event_manager_->getEvents (event_type).count ()) ui_.event_combo_box_->addItem (event_manager_->getNameOfEventType(event_type), QVariant(event_type)); diff --git a/src/gui_impl/dialogs/event_types_selection_dialog.cpp b/src/gui_impl/dialogs/event_types_selection_dialog.cpp index f84c622e..7a1ff322 100644 --- a/src/gui_impl/dialogs/event_types_selection_dialog.cpp +++ b/src/gui_impl/dialogs/event_types_selection_dialog.cpp @@ -52,7 +52,7 @@ void EventTypesSelectionDialog::buildTree (bool only_existing_events) if (event_manager_->getFileType().startsWith("xdf", Qt::CaseInsensitive)) { - foreach (EventType event_type, event_manager_->getEventTypes ()) + for (const auto event_type : event_manager_->getEventTypes ()) { if (only_existing_events && !existing_types.count(event_type)) continue; @@ -93,13 +93,13 @@ void EventTypesSelectionDialog::buildTree (bool only_existing_events) { QMap group_id2list_item; - foreach (QString group_id, event_manager_->getEventTypeGroupIDs()) + for (const auto& group_id : event_manager_->getEventTypeGroupIDs()) { QString group_name = group_id; // TODO: event_table_file_reader.getEventGroupName(*group_it); bool show_group = !only_existing_events; - foreach (EventType group_type, event_manager_->getEventTypes (group_id)) + for (const auto group_type : event_manager_->getEventTypes (group_id)) if (existing_types.count(group_type) && only_existing_events) show_group = true; @@ -113,7 +113,7 @@ void EventTypesSelectionDialog::buildTree (bool only_existing_events) group_item->setExpanded (true); group_id2list_item[group_id] = group_item; - foreach (EventType event_type, event_manager_->getEventTypes (group_id)) + for (const auto event_type : event_manager_->getEventTypes (group_id)) { if (only_existing_events && !existing_types.count(event_type)) continue; diff --git a/src/gui_impl/event_table/event_table.pri b/src/gui_impl/event_table/event_table.pri deleted file mode 100644 index 9d2a6ecf..00000000 --- a/src/gui_impl/event_table/event_table.pri +++ /dev/null @@ -1,11 +0,0 @@ -HEADERS += \ - $$PWD/event_table_view_model.h \ - $$PWD/event_table_widget.h - - -SOURCES += \ - $$PWD/event_table_view_model.cpp \ - $$PWD/event_table_widget.cpp - -FORMS += \ - $$PWD/event_table_widget.ui diff --git a/src/gui_impl/gui_helper_functions.cpp b/src/gui_impl/gui_helper_functions.cpp index 23ab6f98..397eb1d3 100644 --- a/src/gui_impl/gui_helper_functions.cpp +++ b/src/gui_impl/gui_helper_functions.cpp @@ -218,7 +218,7 @@ std::set selectChannels (ChannelManager const& channel_manager, bool empty_selection = (pre_selected_channels.size () == 0); - foreach (ChannelID channel_id, channel_manager.getChannels()) + for (const auto channel_id : channel_manager.getChannels()) { bool show_channel = (empty_selection || (pre_selected_channels.count(channel_id) > 0)); @@ -232,7 +232,7 @@ std::set selectChannels (ChannelManager const& channel_manager, return pre_selected_channels; std::set selected_channels; - foreach (ChannelID channel_id, channel_manager.getChannels()) + for (const auto channel_id : channel_manager.getChannels()) { if (channel_dialog.isSelected (channel_id)) selected_channels.insert (channel_id); diff --git a/src/gui_impl/gui_impl.pri b/src/gui_impl/gui_impl.pri deleted file mode 100644 index 5e10e453..00000000 --- a/src/gui_impl/gui_impl.pri +++ /dev/null @@ -1,23 +0,0 @@ -HEADERS += \ - $$PWD/gui_helper_functions.h \ - $$PWD/main_window.h \ - $$PWD/main_window_model_impl.h \ - $$PWD/processed_signal_channel_manager.h \ - $$PWD/signal_browser_mouse_handling.h \ - $$PWD/select_shown_channels_dialog.h - -SOURCES += \ - $$PWD/gui_helper_functions.cpp \ - $$PWD/main_window.cpp \ - $$PWD/main_window_model_impl.cpp \ - $$PWD/processed_signal_channel_manager.cpp \ - $$PWD/select_shown_channels_dialog.cpp \ - $$PWD/signal_browser_mouse_handling.cpp - -FORMS += \ - $$PWD/info_widgets/power_spectrum_info_widget.ui - -include($$PWD/commands/commands.pri) -include($$PWD/dialogs/dialogs.pri) -include($$PWD/event_table/event_table.pri) -include($$PWD/signal_browser/signal_browser.pri) diff --git a/src/gui_impl/signal_browser/event_creation_widget.cpp b/src/gui_impl/signal_browser/event_creation_widget.cpp index df49af32..42269ac6 100644 --- a/src/gui_impl/signal_browser/event_creation_widget.cpp +++ b/src/gui_impl/signal_browser/event_creation_widget.cpp @@ -74,7 +74,7 @@ void EventCreationWidget::updateShownEventTypes (std::set const& show setSelfUpdating (true); ui_.type_combobox_->clear (); int current_index = 0; - foreach (EventType type, shown_event_types) + for (const auto type : shown_event_types) { ui_.type_combobox_->addItem (event_manager_->getNameOfEventType (type), QVariant (type)); diff --git a/src/gui_impl/signal_browser/event_editing_widget.cpp b/src/gui_impl/signal_browser/event_editing_widget.cpp index 3cc497ac..84a3634d 100644 --- a/src/gui_impl/signal_browser/event_editing_widget.cpp +++ b/src/gui_impl/signal_browser/event_editing_widget.cpp @@ -63,7 +63,7 @@ void EventEditingWidget::updateShownEventTypes (std::set const& shown setSelfUpdating (true); ui_.type_combobox_->clear (); - foreach (EventType type, shown_event_types) + for (const auto type : shown_event_types) ui_.type_combobox_->addItem (event_manager_->getNameOfEventType (type), QVariant (type)); diff --git a/src/gui_impl/signal_browser/signal_browser.pri b/src/gui_impl/signal_browser/signal_browser.pri deleted file mode 100644 index 25c106a2..00000000 --- a/src/gui_impl/signal_browser/signal_browser.pri +++ /dev/null @@ -1,33 +0,0 @@ -HEADERS += \ - $$PWD/adapt_browser_view_widget.h \ - $$PWD/event_context_menu.h \ - $$PWD/event_creation_widget.h \ - $$PWD/event_editing_widget.h \ - $$PWD/event_graphics_item.h \ - $$PWD/label_widget.h \ - $$PWD/signal_browser_graphics_view.h \ - $$PWD/signal_browser_model_4.h \ - $$PWD/signal_browser_view.h \ - $$PWD/signal_graphics_item.h \ - $$PWD/signal_grid_graphics_item.h \ - $$PWD/x_axis_widget_4.h \ - $$PWD/y_axis_widget_4.h - -SOURCES += \ - $$PWD/adapt_browser_view_widget.cpp \ - $$PWD/event_context_menu.cpp \ - $$PWD/event_creation_widget.cpp \ - $$PWD/event_editing_widget.cpp \ - $$PWD/event_graphics_item.cpp \ - $$PWD/label_widget.cpp \ - $$PWD/signal_browser_model_4.cpp \ - $$PWD/signal_browser_view.cpp \ - $$PWD/signal_graphics_item.cpp \ - $$PWD/signal_grid_graphics_item.cpp \ - $$PWD/x_axis_widget_4.cpp \ - $$PWD/y_axis_widget_4.cpp - -FORMS += \ - $$PWD/adapt_browser_view_widget.ui \ - $$PWD/event_creation_widget.ui \ - $$PWD/event_editing_widget.ui diff --git a/src/gui_impl/signal_browser/signal_browser_model_4.cpp b/src/gui_impl/signal_browser/signal_browser_model_4.cpp index e3d5d2b7..da7a60f2 100644 --- a/src/gui_impl/signal_browser/signal_browser_model_4.cpp +++ b/src/gui_impl/signal_browser/signal_browser_model_4.cpp @@ -119,7 +119,7 @@ void SignalBrowserModel::setShownChannels (std::set const& getSignalViewSettings()->setChannelHeight (std::max(120, new_channel_height)); - foreach (ChannelID channel, new_shown_channels) + for (const auto channel : new_shown_channels) { ProgressBar::instance().increaseValue (1, tr("Creating view...")); if (channel2signal_item_.count (channel) == 0) diff --git a/src/gui_impl/signal_browser/signal_graphics_item.cpp b/src/gui_impl/signal_browser/signal_graphics_item.cpp index ae330dd2..aab3dfea 100644 --- a/src/gui_impl/signal_browser/signal_graphics_item.cpp +++ b/src/gui_impl/signal_browser/signal_graphics_item.cpp @@ -395,7 +395,7 @@ void SignalGraphicsItem::hoverMoveEvent (QGraphicsSceneHoverEvent* event) std::set events = event_manager_->getEventsAt (sample_pos, id_); std::set shown_types = signal_browser_model_.getShownEventTypes(); QString event_string; - foreach (EventID event, events) + for (const auto event : events) { QSharedPointer signal_event = event_manager_->getEvent(event); if (shown_types.count(signal_event->getType())) diff --git a/src/main.cpp b/src/main.cpp index c00d1282..e623fcc4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,7 +28,7 @@ int main(int argc, char* argv[]) #endif QTranslator translator; - if (translator.load(QLocale::system(), QStringLiteral("sigviewer"), QStringLiteral("_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + if (translator.load(QLocale::system(), QStringLiteral("sigviewer"), QStringLiteral("_"), QLibraryInfo::path(QLibraryInfo::TranslationsPath))) { QCoreApplication::installTranslator(&translator); } diff --git a/src/signal_processing/signal_processing.pri b/src/signal_processing/signal_processing.pri deleted file mode 100644 index 07878afe..00000000 --- a/src/signal_processing/signal_processing.pri +++ /dev/null @@ -1,5 +0,0 @@ -HEADERS += \ - $$PWD/FFTReal.h - -SOURCES += \ - $$PWD/FFTReal.cpp diff --git a/src/tests/file_handling_tests.cpp b/src/tests/file_handling_tests.cpp index 0e083543..f741e114 100644 --- a/src/tests/file_handling_tests.cpp +++ b/src/tests/file_handling_tests.cpp @@ -40,7 +40,7 @@ void FileHandlingTests::cleanup () QString FileHandlingTests::testEventExportingImporting () { QTemporaryFile event_file ("XXXXXX.evt"); - event_file.open(); + (void)event_file.open(); event_file.close(); QSharedPointer writer (FileSignalWriterFactory::getInstance()->getHandler(event_file.fileName())); VERIFY (writer.isNull() == false, "EVT writer not created") @@ -55,7 +55,7 @@ QString FileHandlingTests::testEventExportingImporting () QTemporaryFile event_file_2 ("XXXXXX.evt"); - event_file_2.open(); + (void)event_file_2.open(); event_file_2.close(); QSharedPointer writer_2 (FileSignalWriterFactory::getInstance()->getHandler(event_file_2.fileName())); VERIFY (writer_2.isNull() == false, "EVT writer 2 not created") diff --git a/src/tests/tests.pri b/src/tests/tests.pri deleted file mode 100644 index 20726c76..00000000 --- a/src/tests/tests.pri +++ /dev/null @@ -1,25 +0,0 @@ -HEADERS += \ - $$PWD/color_manager_tests.h \ - $$PWD/data_block_tests.h \ - $$PWD/editing_commands_tests.h \ - $$PWD/event_manager_tests.h \ - $$PWD/event_table_widget_tests.h \ - $$PWD/file_handling_tests.h \ - $$PWD/gui_tests.h \ - $$PWD/test.h \ - $$PWD/tests_dialog.h \ - $$PWD/tests_factory.h - -SOURCES += \ - $$PWD/color_manager_tests.cpp \ - $$PWD/data_block_tests.cpp \ - $$PWD/editing_commands_tests.cpp \ - $$PWD/event_manager_tests.cpp \ - $$PWD/event_table_widget_tests.cpp \ - $$PWD/file_handling_tests.cpp \ - $$PWD/gui_tests.cpp \ - $$PWD/test.cpp \ - $$PWD/tests_dialog.cpp \ - -FORMS += \ - $$PWD/tests_dialog.ui diff --git a/src/translations/sigviewer_en.ts b/src/translations/sigviewer_en.ts index 25b1c81b..1ccca6a8 100644 --- a/src/translations/sigviewer_en.ts +++ b/src/translations/sigviewer_en.ts @@ -1,6 +1,6 @@ - + AdaptBrowserViewWidget diff --git a/update_translations.sh b/update_translations.sh deleted file mode 100755 index 0e9e3bd2..00000000 --- a/update_translations.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -cd "$(git rev-parse --show-toplevel)" - -lupdate-qt5 $(git ls-files | egrep '\.cpp$|\.h$|\.ui$') -ts $(git ls-files | egrep '\.ts$') "${@}"