From bf6d6a5b4abe2fda1e612111781b5c29b6223688 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 09:26:17 +0330 Subject: [PATCH 01/81] github action #29 --- .github/workflows/cmake-multi-platform.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 257eefe..8d54d19 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Qt Installation + ### Windows Setup with Qt Offline Installation - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -55,23 +55,27 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - - name: Download and Install Qt (Windows) + - name: Download and Install Qt Offline (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | - $installer = "qt-unified-windows-x64-online.exe" - Invoke-WebRequest -Uri "https://download.qt.io/official_releases/online_installers/qt-unified-windows-x64-online.exe" -OutFile $installer -TimeoutSec 1200 + # Define download URL for Qt offline installer + $qtUrl = "https://download.qt.io/official_releases/qt/6.5/6.5.3/qt-opensource-windows-x86-64-6.5.3.exe" + $installer = "qt-offline-installer.exe" + + # Download the Qt installer + Invoke-WebRequest -Uri $qtUrl -OutFile $installer -TimeoutSec 1200 - # Install Qt in a non-interactive mode + # Install Qt in silent mode Start-Process -FilePath $installer -ArgumentList ` - 'install', ` '--platform', 'minimal', ` - '--accept-licenses', ` '--no-default-installations', ` - '--root', 'C:\Qt' ` + '--accept-licenses', ` + '--no-force-installations', ` + '--install-dir', 'C:\Qt' ` -NoNewWindow -Wait - # Verify the Qt installation by checking for installation folders + # Verify Qt installation if (-Not (Test-Path "C:\Qt\6*")) { throw "Qt installation failed!" } else { From 3e775551b747419f89bef17ead28058b8dc9283c Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 09:37:43 +0330 Subject: [PATCH 02/81] github action #30 --- .github/workflows/cmake-multi-platform.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 8d54d19..8668b76 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -59,12 +59,16 @@ jobs: if: matrix.os == 'windows-latest' shell: powershell run: | - # Define download URL for Qt offline installer + # Define the most stable Qt installer URL (update version if necessary) $qtUrl = "https://download.qt.io/official_releases/qt/6.5/6.5.3/qt-opensource-windows-x86-64-6.5.3.exe" $installer = "qt-offline-installer.exe" # Download the Qt installer - Invoke-WebRequest -Uri $qtUrl -OutFile $installer -TimeoutSec 1200 + try { + Invoke-WebRequest -Uri $qtUrl -OutFile $installer -TimeoutSec 1200 + } catch { + throw "Qt offline installer could not be downloaded. Please verify the URL: https://download.qt.io/official_releases/qt/" + } # Install Qt in silent mode Start-Process -FilePath $installer -ArgumentList ` From 0f421a66890d558be1bbc6a1cada516ae8aa1c2d Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 09:48:22 +0330 Subject: [PATCH 03/81] github action #31 --- .github/workflows/cmake-multi-platform.yml | 66 ++-------------------- 1 file changed, 6 insertions(+), 60 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 8668b76..fbd4049 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Qt Offline Installation + ### Windows Setup with Chocolatey to Install Qt - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -55,65 +55,11 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - - name: Download and Install Qt Offline (Windows) + - name: Install Qt with Chocolatey (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | - # Define the most stable Qt installer URL (update version if necessary) - $qtUrl = "https://download.qt.io/official_releases/qt/6.5/6.5.3/qt-opensource-windows-x86-64-6.5.3.exe" - $installer = "qt-offline-installer.exe" - - # Download the Qt installer - try { - Invoke-WebRequest -Uri $qtUrl -OutFile $installer -TimeoutSec 1200 - } catch { - throw "Qt offline installer could not be downloaded. Please verify the URL: https://download.qt.io/official_releases/qt/" - } - - # Install Qt in silent mode - Start-Process -FilePath $installer -ArgumentList ` - '--platform', 'minimal', ` - '--no-default-installations', ` - '--accept-licenses', ` - '--no-force-installations', ` - '--install-dir', 'C:\Qt' ` - -NoNewWindow -Wait - - # Verify Qt installation - if (-Not (Test-Path "C:\Qt\6*")) { - throw "Qt installation failed!" - } else { - Write-Host "Qt installation verified" - } - - - name: Set up MSVC environment (Windows) - if: matrix.os == 'windows-latest' - shell: cmd - run: | - FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ - -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i - IF NOT DEFINED VS_PATH ( - echo Visual Studio Build Tools not found! && exit /b 1 - ) - SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" - CALL "%VS_VARS_CMD%" || exit /b 1 - where cl || (echo cl.exe not found in PATH && exit /b 1) - - # Configure CMake - - name: Configure CMake - run: | - cmake -B "${{ github.workspace }}/build" \ - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ - -DCMAKE_BUILD_TYPE=Release \ - -G "Ninja" \ - -S "${{ github.workspace }}" - - # Build the project - - name: Build - run: cmake --build "${{ github.workspace }}/build" --config Release - - # Run tests - - name: Test - working-directory: "${{ github.workspace }}/build" - run: ctest --output-on-failure --build-config Release + # Install Qt through Chocolatey + choco install qtinstaller -y --version=4.2.1 # Install Qt Installer framework + # Use Qt Maintenance tool if installed or setup a local install for required packages + # Example of local package installs From 610f0f0219f02972f1efe26969aee25406d6664a Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 09:58:46 +0330 Subject: [PATCH 04/81] github action #32 --- .github/workflows/cmake-multi-platform.yml | 42 ++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index fbd4049..1460459 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Chocolatey to Install Qt + ### Windows Setup - Direct Download for Qt - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -55,11 +55,41 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - - name: Install Qt with Chocolatey (Windows) + - name: Download and Install Qt (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | - # Install Qt through Chocolatey - choco install qtinstaller -y --version=4.2.1 # Install Qt Installer framework - # Use Qt Maintenance tool if installed or setup a local install for required packages - # Example of local package installs + $qtInstallerUrl = "https://download.qt.io/official_releases/online_installers/qt-unified-windows-x64-online.exe" + $installerPath = "$env:TEMP\qt-unified-windows-x64-online.exe" + Invoke-WebRequest -Uri $qtInstallerUrl -OutFile $installerPath -TimeoutSec 1200 + + # Install Qt in silent mode without requiring Qt Account credentials + Start-Process -FilePath $installerPath -ArgumentList ` + 'install', ` + '--no-default-installations', ` + '--accept-licenses', ` + '--root', 'C:\Qt' ` + -NoNewWindow -Wait + + # Verify Qt installation by checking if the 'bin' folder exists + if (-Not (Test-Path "C:\Qt\6*")) { + throw "Qt installation failed!" + } else { + Write-Host "Qt installation verified" + } + + - name: Configure CMake + run: | + cmake -B "${{ github.workspace }}/build" \ + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ + -DCMAKE_BUILD_TYPE=Release \ + -G "Ninja" \ + -S "${{ github.workspace }}" + + - name: Build the project + run: cmake --build "${{ github.workspace }}/build" --config Release + + - name: Run tests + working-directory: "${{ github.workspace }}/build" + run: ctest --output-on-failure --build-config Release From 42f66ef1a3bf82a390535def5bddc49b6a4e27c0 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 10:07:35 +0330 Subject: [PATCH 05/81] github action #33 --- .github/workflows/cmake-multi-platform.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 1460459..81243eb 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup - Direct Download for Qt + ### Windows Setup with Basic Qt Installation - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -55,7 +55,7 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - - name: Download and Install Qt (Windows) + - name: Download and Install Qt Essentials (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | @@ -63,12 +63,14 @@ jobs: $installerPath = "$env:TEMP\qt-unified-windows-x64-online.exe" Invoke-WebRequest -Uri $qtInstallerUrl -OutFile $installerPath -TimeoutSec 1200 - # Install Qt in silent mode without requiring Qt Account credentials + # Install only essential components without requiring a Qt Account Start-Process -FilePath $installerPath -ArgumentList ` 'install', ` - '--no-default-installations', ` + '-p', 'qt.qt6.653.win64_msvc2019_64', ` '--accept-licenses', ` - '--root', 'C:\Qt' ` + '--confirm-command', ` + '--root', 'C:\Qt', ` + '--no-force-installations' ` -NoNewWindow -Wait # Verify Qt installation by checking if the 'bin' folder exists From 29605b3d88129a60c67b4e9aaaa586e6fdd2c511 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 10:38:59 +0330 Subject: [PATCH 06/81] github action #34 --- .github/workflows/cmake-multi-platform.yml | 107 +++++++++------------ 1 file changed, 44 insertions(+), 63 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 81243eb..a209d62 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -26,72 +26,53 @@ jobs: cpp_compiler: clang++ steps: - - name: Checkout code - uses: actions/checkout@v4 + - name: Checkout code + uses: actions/checkout@v4 - ### Ubuntu Dependencies - - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get update - sudo apt-get install -y ninja-build \ - qt6-base-dev qt6-tools-dev qt6-tools-dev-tools \ - qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev - echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV + ### Ubuntu Dependencies + - name: Install dependencies (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y ninja-build \ + qt6-base-dev qt6-tools-dev qt6-tools-dev-tools \ + qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev + echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV - ### macOS Dependencies - - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' - run: | - brew install ninja qt - echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV + ### macOS Dependencies + - name: Install dependencies (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install ninja qt + echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Basic Qt Installation - - name: Install dependencies (Windows) - if: matrix.os == 'windows-latest' - shell: powershell - run: | - choco install visualstudio2022buildtools -y - choco install ninja -y - choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y + ### Windows: Install Qt using jurplel/install-qt-action + - name: Install Qt (Windows) + if: matrix.os == 'windows-latest' + uses: jurplel/install-qt-action@v2 + with: + version: '6.5.3' + host: 'windows' + target: 'desktop' + arch: 'win64_msvc2019_64' + modules: qtcharts + setup-python: false - - name: Download and Install Qt Essentials (Windows) - if: matrix.os == 'windows-latest' - shell: powershell - run: | - $qtInstallerUrl = "https://download.qt.io/official_releases/online_installers/qt-unified-windows-x64-online.exe" - $installerPath = "$env:TEMP\qt-unified-windows-x64-online.exe" - Invoke-WebRequest -Uri $qtInstallerUrl -OutFile $installerPath -TimeoutSec 1200 + # Configure CMake + - name: Configure CMake + run: | + cmake -B "${{ github.workspace }}/build" \ + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ + -DCMAKE_BUILD_TYPE=Release \ + -G "Ninja" \ + -S "${{ github.workspace }}" - # Install only essential components without requiring a Qt Account - Start-Process -FilePath $installerPath -ArgumentList ` - 'install', ` - '-p', 'qt.qt6.653.win64_msvc2019_64', ` - '--accept-licenses', ` - '--confirm-command', ` - '--root', 'C:\Qt', ` - '--no-force-installations' ` - -NoNewWindow -Wait + # Build project + - name: Build + run: cmake --build "${{ github.workspace }}/build" --config Release - # Verify Qt installation by checking if the 'bin' folder exists - if (-Not (Test-Path "C:\Qt\6*")) { - throw "Qt installation failed!" - } else { - Write-Host "Qt installation verified" - } - - - name: Configure CMake - run: | - cmake -B "${{ github.workspace }}/build" \ - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ - -DCMAKE_BUILD_TYPE=Release \ - -G "Ninja" \ - -S "${{ github.workspace }}" - - - name: Build the project - run: cmake --build "${{ github.workspace }}/build" --config Release - - - name: Run tests - working-directory: "${{ github.workspace }}/build" - run: ctest --output-on-failure --build-config Release + # Run tests + - name: Test + working-directory: "${{ github.workspace }}/build" + run: ctest --output-on-failure --build-config Release From 8b445f3ac7e9fdbd9e208851e818a2803cdcd1da Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 17:06:52 +0330 Subject: [PATCH 07/81] github action #35 --- .github/workflows/cmake-multi-platform.yml | 99 +++++++++------------- 1 file changed, 42 insertions(+), 57 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index a209d62..75e8291 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -8,71 +8,56 @@ on: jobs: build: - runs-on: ${{ matrix.os }} + runs-on: windows-latest - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - include: - - os: windows-latest - c_compiler: cl - cpp_compiler: cl - - os: ubuntu-latest - c_compiler: gcc - cpp_compiler: g++ - - os: macos-latest - c_compiler: clang - cpp_compiler: clang++ + env: + QT_VERSION: 6.5.3 + QT_INSTALL_DIR: D:/a/Notepad--/Qt + BUILD_DIR: D:/a/Notepad--/Notepad--/build steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v2 - ### Ubuntu Dependencies - - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-latest' + - name: Install Qt + shell: pwsh run: | - sudo apt-get update - sudo apt-get install -y ninja-build \ - qt6-base-dev qt6-tools-dev qt6-tools-dev-tools \ - qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev - echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV + $qtInstallerUrl = "https://download.qt.io/official_releases/online_installers/qt-unified-windows-x64-online.exe" + $installerPath = "$env:TEMP\qt-unified-windows-x64-online.exe" + Invoke-WebRequest -Uri $qtInstallerUrl -OutFile $installerPath -TimeoutSec 1200 + # Run Qt installer + Start-Process -FilePath $installerPath -ArgumentList ` + 'install', '--no-default-installations', '--accept-licenses', ` + '--no-force-installations', '--confirm-command', ` + '-p', "qt.qt${{ env.QT_VERSION }}.win64_msvc2019_64", ` + '--root', "${{ env.QT_INSTALL_DIR }}" ` + -NoNewWindow -Wait + # Verify Qt installation + if (-Not (Test-Path "${{ env.QT_INSTALL_DIR }}\${{ env.QT_VERSION }}")) { + throw "Qt installation failed!" + } else { + Write-Host "Qt installation verified" + } - ### macOS Dependencies - - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' - run: | - brew install ninja qt - echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - - ### Windows: Install Qt using jurplel/install-qt-action - - name: Install Qt (Windows) - if: matrix.os == 'windows-latest' - uses: jurplel/install-qt-action@v2 - with: - version: '6.5.3' - host: 'windows' - target: 'desktop' - arch: 'win64_msvc2019_64' - modules: qtcharts - setup-python: false - - # Configure CMake - name: Configure CMake + shell: pwsh run: | - cmake -B "${{ github.workspace }}/build" \ - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ - -DCMAKE_BUILD_TYPE=Release \ - -G "Ninja" \ + cmake -B "${{ env.BUILD_DIR }}" ` + -DCMAKE_CXX_COMPILER=cl ` + -DCMAKE_C_COMPILER=cl ` + -DCMAKE_BUILD_TYPE=Release ` + -G "Ninja" ` -S "${{ github.workspace }}" - - # Build project - - name: Build - run: cmake --build "${{ github.workspace }}/build" --config Release - - # Run tests - - name: Test - working-directory: "${{ github.workspace }}/build" + env: + Qt6_DIR: ${{ env.QT_INSTALL_DIR }}/6.5.3/msvc2019_64 + QT_PLUGIN_PATH: ${{ env.QT_INSTALL_DIR }}/6.5.3/msvc2019_64/plugins + QML2_IMPORT_PATH: ${{ env.QT_INSTALL_DIR }}/6.5.3/msvc2019_64/qml + + - name: Build project + shell: pwsh + run: cmake --build "${{ env.BUILD_DIR }}" --config Release + + - name: Run tests + working-directory: "${{ env.BUILD_DIR }}" + shell: pwsh run: ctest --output-on-failure --build-config Release From aaae8b8e007b377edf816f370d2c4e30db126fe9 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 17:11:38 +0330 Subject: [PATCH 08/81] github action #36 --- .github/workflows/cmake-multi-platform.yml | 79 ++++++++++++++-------- 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 75e8291..24383fe 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -8,56 +8,81 @@ on: jobs: build: - runs-on: windows-latest + runs-on: ${{ matrix.os }} - env: - QT_VERSION: 6.5.3 - QT_INSTALL_DIR: D:/a/Notepad--/Qt - BUILD_DIR: D:/a/Notepad--/Notepad--/build + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + - os: ubuntu-latest + c_compiler: gcc + cpp_compiler: g++ + - os: macos-latest + c_compiler: clang + cpp_compiler: clang++ steps: - name: Checkout code uses: actions/checkout@v2 - - name: Install Qt + # Ubuntu Dependencies + - name: Install dependencies (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y ninja-build qt6-base-dev qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev + echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV + + # macOS Dependencies + - name: Install dependencies (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install ninja qt + echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV + + # Windows Setup and Qt Installation + - name: Install Qt (Windows) + if: matrix.os == 'windows-latest' shell: pwsh run: | $qtInstallerUrl = "https://download.qt.io/official_releases/online_installers/qt-unified-windows-x64-online.exe" $installerPath = "$env:TEMP\qt-unified-windows-x64-online.exe" Invoke-WebRequest -Uri $qtInstallerUrl -OutFile $installerPath -TimeoutSec 1200 - # Run Qt installer + + # Install Qt in silent mode Start-Process -FilePath $installerPath -ArgumentList ` - 'install', '--no-default-installations', '--accept-licenses', ` - '--no-force-installations', '--confirm-command', ` - '-p', "qt.qt${{ env.QT_VERSION }}.win64_msvc2019_64", ` - '--root', "${{ env.QT_INSTALL_DIR }}" ` + 'install', '--no-default-installations', '--accept-licenses', '--no-force-installations', '--confirm-command', ` + '-p', 'qt.qt6.653.win64_msvc2019_64', '--root', 'C:\Qt' ` -NoNewWindow -Wait + # Verify Qt installation - if (-Not (Test-Path "${{ env.QT_INSTALL_DIR }}\${{ env.QT_VERSION }}")) { + if (-Not (Test-Path "C:\Qt\6*")) { throw "Qt installation failed!" } else { Write-Host "Qt installation verified" - } - - name: Configure CMake + - name: Configure CMake (Windows) + if: matrix.os == 'windows-latest' shell: pwsh run: | - cmake -B "${{ env.BUILD_DIR }}" ` - -DCMAKE_CXX_COMPILER=cl ` - -DCMAKE_C_COMPILER=cl ` - -DCMAKE_BUILD_TYPE=Release ` - -G "Ninja" ` - -S "${{ github.workspace }}" + cmake -B "${{ github.workspace }}\build" -G "Ninja" -S "${{ github.workspace }}" ` + -DCMAKE_CXX_COMPILER=cl -DCMAKE_C_COMPILER=cl -DCMAKE_BUILD_TYPE=Release env: - Qt6_DIR: ${{ env.QT_INSTALL_DIR }}/6.5.3/msvc2019_64 - QT_PLUGIN_PATH: ${{ env.QT_INSTALL_DIR }}/6.5.3/msvc2019_64/plugins - QML2_IMPORT_PATH: ${{ env.QT_INSTALL_DIR }}/6.5.3/msvc2019_64/qml + Qt6_DIR: C:\Qt\6.5.3\msvc2019_64 + QT_PLUGIN_PATH: C:\Qt\6.5.3\msvc2019_64\plugins + QML2_IMPORT_PATH: C:\Qt\6.5.3\msvc2019_64\qml - - name: Build project + - name: Build (Windows) + if: matrix.os == 'windows-latest' shell: pwsh - run: cmake --build "${{ env.BUILD_DIR }}" --config Release + run: cmake --build "${{ github.workspace }}\build" --config Release - - name: Run tests - working-directory: "${{ env.BUILD_DIR }}" + - name: Run tests (Windows) + if: matrix.os == 'windows-latest' shell: pwsh + working-directory: "${{ github.workspace }}\build" run: ctest --output-on-failure --build-config Release From 0d858c4b9012308dab1a86acec6ea7a605a1d1a2 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 17:14:52 +0330 Subject: [PATCH 09/81] github action #37 --- .github/workflows/cmake-multi-platform.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 24383fe..4a040de 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -64,6 +64,7 @@ jobs: throw "Qt installation failed!" } else { Write-Host "Qt installation verified" + } - name: Configure CMake (Windows) if: matrix.os == 'windows-latest' From f6dac472dc97dbddba84e2c2044a6b22ec9e8447 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 17:20:20 +0330 Subject: [PATCH 10/81] github action #38 --- .github/workflows/cmake-multi-platform.yml | 51 ++++++++++++---------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 4a040de..474c3ac 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -29,7 +29,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - # Ubuntu Dependencies + # Install dependencies on Ubuntu - name: Install dependencies (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | @@ -37,47 +37,50 @@ jobs: sudo apt-get install -y ninja-build qt6-base-dev qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV - # macOS Dependencies + # Install dependencies on macOS - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' run: | brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - # Windows Setup and Qt Installation - - name: Install Qt (Windows) + # Build and install Qt from source on Windows + - name: Install dependencies and build Qt from source (Windows) if: matrix.os == 'windows-latest' shell: pwsh run: | - $qtInstallerUrl = "https://download.qt.io/official_releases/online_installers/qt-unified-windows-x64-online.exe" - $installerPath = "$env:TEMP\qt-unified-windows-x64-online.exe" - Invoke-WebRequest -Uri $qtInstallerUrl -OutFile $installerPath -TimeoutSec 1200 + # Step 1: Download Qt source + $qtVersion = "6.5.3" + $qtSourceUrl = "https://download.qt.io/official_releases/qt/6.5/$qtVersion/single/qt-everywhere-src-$qtVersion.zip" + $qtSourcePath = "$env:TEMP\qt-everywhere-src.zip" + Invoke-WebRequest -Uri $qtSourceUrl -OutFile $qtSourcePath -TimeoutSec 1200 - # Install Qt in silent mode - Start-Process -FilePath $installerPath -ArgumentList ` - 'install', '--no-default-installations', '--accept-licenses', '--no-force-installations', '--confirm-command', ` - '-p', 'qt.qt6.653.win64_msvc2019_64', '--root', 'C:\Qt' ` - -NoNewWindow -Wait - - # Verify Qt installation - if (-Not (Test-Path "C:\Qt\6*")) { - throw "Qt installation failed!" - } else { - Write-Host "Qt installation verified" - } + # Step 2: Extract source + Expand-Archive -Path $qtSourcePath -DestinationPath $env:TEMP\qt-source + + # Step 3: Configure and build + cd "$env:TEMP\qt-source\qt-everywhere-src-$qtVersion" + .\configure -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests + nmake + nmake install + + # Set up environment variables + echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $GITHUB_ENV + echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $GITHUB_ENV + echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $GITHUB_ENV - - name: Configure CMake (Windows) + - name: Configure CMake if: matrix.os == 'windows-latest' shell: pwsh run: | cmake -B "${{ github.workspace }}\build" -G "Ninja" -S "${{ github.workspace }}" ` -DCMAKE_CXX_COMPILER=cl -DCMAKE_C_COMPILER=cl -DCMAKE_BUILD_TYPE=Release env: - Qt6_DIR: C:\Qt\6.5.3\msvc2019_64 - QT_PLUGIN_PATH: C:\Qt\6.5.3\msvc2019_64\plugins - QML2_IMPORT_PATH: C:\Qt\6.5.3\msvc2019_64\qml + Qt6_DIR: C:\Qt\lib\cmake\Qt6 + QT_PLUGIN_PATH: C:\Qt\plugins + QML2_IMPORT_PATH: C:\Qt\qml - - name: Build (Windows) + - name: Build project (Windows) if: matrix.os == 'windows-latest' shell: pwsh run: cmake --build "${{ github.workspace }}\build" --config Release From ce45a461b009ebab1c3f26e999960e5c0980ffcc Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 23:47:19 +0330 Subject: [PATCH 11/81] github action #39 --- .github/workflows/cmake-multi-platform.yml | 56 +++++++++++++++------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 474c3ac..01f9dd2 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -9,7 +9,6 @@ on: jobs: build: runs-on: ${{ matrix.os }} - strategy: fail-fast: false matrix: @@ -29,7 +28,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - # Install dependencies on Ubuntu + # Ubuntu setup - name: Install dependencies (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | @@ -37,39 +36,60 @@ jobs: sudo apt-get install -y ninja-build qt6-base-dev qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV - # Install dependencies on macOS + # macOS setup - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' run: | brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - # Build and install Qt from source on Windows - - name: Install dependencies and build Qt from source (Windows) + # Windows setup with caching + - name: Setup and build Qt (Windows) if: matrix.os == 'windows-latest' shell: pwsh + env: + QT_VERSION: 6.5.3 run: | - # Step 1: Download Qt source - $qtVersion = "6.5.3" - $qtSourceUrl = "https://download.qt.io/official_releases/qt/6.5/$qtVersion/single/qt-everywhere-src-$qtVersion.zip" - $qtSourcePath = "$env:TEMP\qt-everywhere-src.zip" - Invoke-WebRequest -Uri $qtSourceUrl -OutFile $qtSourcePath -TimeoutSec 1200 - - # Step 2: Extract source - Expand-Archive -Path $qtSourcePath -DestinationPath $env:TEMP\qt-source + # Set up Visual Studio environment + Write-Host "Setting up Visual Studio environment" + $vsPath = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath + $env:Path += ";$vsPath\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64" + & "$vsPath\Common7\Tools\VsDevCmd.bat" + + # Use cache to avoid re-downloading and re-compiling Qt + Write-Host "Setting up cache for Qt" + $qtCacheKey = "qt-source-${{ env.QT_VERSION }}" + $qtSourceDir = "$env:TEMP\qt-source" + New-Item -ItemType Directory -Path $qtSourceDir + + - name: Cache Qt Source + uses: actions/cache@v3 + with: + path: $qtSourceDir + key: $qtCacheKey + + if (!(Test-Path "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION.zip")) { + Write-Host "Downloading Qt Source" + $qtSourceUrl = "https://download.qt.io/official_releases/qt/6.5/$env:QT_VERSION/single/qt-everywhere-src-$env:QT_VERSION.zip" + Invoke-WebRequest -Uri $qtSourceUrl -OutFile "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION.zip" + Expand-Archive -Path "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION.zip" -DestinationPath $qtSourceDir + } - # Step 3: Configure and build - cd "$env:TEMP\qt-source\qt-everywhere-src-$qtVersion" - .\configure -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests + # Configure and build Qt + Write-Host "Configuring and building Qt" + cd "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION\qtbase" + .\configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc nmake nmake install - # Set up environment variables + # Set environment variables for Qt + Write-Host "Setting Qt environment variables" echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $GITHUB_ENV echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $GITHUB_ENV echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $GITHUB_ENV - - name: Configure CMake + # CMake configuration and build for Windows + - name: Configure CMake (Windows) if: matrix.os == 'windows-latest' shell: pwsh run: | From 162147e76346371c6487801bec369f7ccd3779ba Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 12 Nov 2024 23:52:43 +0330 Subject: [PATCH 12/81] github action #40 --- .github/workflows/cmake-multi-platform.yml | 27 ++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 01f9dd2..726b8c4 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -43,8 +43,18 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - # Windows setup with caching - - name: Setup and build Qt (Windows) + # Cache Qt Source for Windows + - name: Cache Qt Source + if: matrix.os == 'windows-latest' + uses: actions/cache@v3 + with: + path: ${{ runner.temp }}\qt-source + key: qt-source-${{ env.QT_VERSION }} + env: + QT_VERSION: 6.5.3 + + # Windows setup with Visual Studio and Qt + - name: Set up Visual Studio and Download/Build Qt (Windows) if: matrix.os == 'windows-latest' shell: pwsh env: @@ -56,18 +66,11 @@ jobs: $env:Path += ";$vsPath\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64" & "$vsPath\Common7\Tools\VsDevCmd.bat" - # Use cache to avoid re-downloading and re-compiling Qt - Write-Host "Setting up cache for Qt" - $qtCacheKey = "qt-source-${{ env.QT_VERSION }}" + # Define source directory $qtSourceDir = "$env:TEMP\qt-source" - New-Item -ItemType Directory -Path $qtSourceDir - - - name: Cache Qt Source - uses: actions/cache@v3 - with: - path: $qtSourceDir - key: $qtCacheKey + New-Item -ItemType Directory -Path $qtSourceDir -Force + # Download Qt source if not cached if (!(Test-Path "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION.zip")) { Write-Host "Downloading Qt Source" $qtSourceUrl = "https://download.qt.io/official_releases/qt/6.5/$env:QT_VERSION/single/qt-everywhere-src-$env:QT_VERSION.zip" From f13c9a974957920c6645651c3199d58ce6cfc401 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 13 Nov 2024 01:38:25 +0330 Subject: [PATCH 13/81] github action #41 --- .github/workflows/cmake-multi-platform.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 726b8c4..f8b6ace 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: [windows-latest, ubuntu-latest, macos-latest] include: - os: windows-latest c_compiler: cl @@ -78,12 +78,12 @@ jobs: Expand-Archive -Path "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION.zip" -DestinationPath $qtSourceDir } - # Configure and build Qt - Write-Host "Configuring and building Qt" + # Configure and build Qt using Ninja + Write-Host "Configuring and building Qt with Ninja" cd "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION\qtbase" - .\configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc - nmake - nmake install + .\configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cmake --build . --parallel + cmake --install . # Set environment variables for Qt Write-Host "Setting Qt environment variables" From c9f7be87f29416eb9d83625413acb5dc267d9c36 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 13 Nov 2024 10:14:03 +0330 Subject: [PATCH 14/81] github action #42 --- .github/workflows/cmake-multi-platform.yml | 58 ++++------------------ 1 file changed, 9 insertions(+), 49 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index f8b6ace..1ccbdac 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -8,54 +8,17 @@ on: jobs: build: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [windows-latest, ubuntu-latest, macos-latest] - include: - - os: windows-latest - c_compiler: cl - cpp_compiler: cl - - os: ubuntu-latest - c_compiler: gcc - cpp_compiler: g++ - - os: macos-latest - c_compiler: clang - cpp_compiler: clang++ + runs-on: windows-latest steps: - name: Checkout code uses: actions/checkout@v2 - # Ubuntu setup - - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get update - sudo apt-get install -y ninja-build qt6-base-dev qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev - echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV - - # macOS setup - - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' - run: | - brew install ninja qt - echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - - # Cache Qt Source for Windows - - name: Cache Qt Source - if: matrix.os == 'windows-latest' - uses: actions/cache@v3 - with: - path: ${{ runner.temp }}\qt-source - key: qt-source-${{ env.QT_VERSION }} - env: - QT_VERSION: 6.5.3 + - name: Install Ninja + run: choco install ninja -y - # Windows setup with Visual Studio and Qt - - name: Set up Visual Studio and Download/Build Qt (Windows) - if: matrix.os == 'windows-latest' + # Set up Visual Studio and Download/Build Qt + - name: Set up Visual Studio environment and Download/Build Qt shell: pwsh env: QT_VERSION: 6.5.3 @@ -91,9 +54,8 @@ jobs: echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $GITHUB_ENV echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $GITHUB_ENV - # CMake configuration and build for Windows - - name: Configure CMake (Windows) - if: matrix.os == 'windows-latest' + # CMake configuration and build for project + - name: Configure CMake shell: pwsh run: | cmake -B "${{ github.workspace }}\build" -G "Ninja" -S "${{ github.workspace }}" ` @@ -103,13 +65,11 @@ jobs: QT_PLUGIN_PATH: C:\Qt\plugins QML2_IMPORT_PATH: C:\Qt\qml - - name: Build project (Windows) - if: matrix.os == 'windows-latest' + - name: Build project shell: pwsh run: cmake --build "${{ github.workspace }}\build" --config Release - - name: Run tests (Windows) - if: matrix.os == 'windows-latest' + - name: Run tests shell: pwsh working-directory: "${{ github.workspace }}\build" run: ctest --output-on-failure --build-config Release From 971a30129bcfb6490cf2e4090555c2d7d62ea6d3 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 13 Nov 2024 10:21:31 +0330 Subject: [PATCH 15/81] gitub action #43 --- .github/workflows/cmake-multi-platform.yml | 54 ++++++++++++---------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 1ccbdac..7f09de2 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -8,32 +8,45 @@ on: jobs: build: - runs-on: windows-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] steps: - name: Checkout code uses: actions/checkout@v2 - - name: Install Ninja + - name: Set up Qt on Ubuntu and macOS + if: runner.os != 'Windows' + run: | + sudo apt-get update -y || brew update + sudo apt-get install -y qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools || brew install qt + env: + Qt6_DIR: /usr/local/opt/qt/lib/cmake/Qt6 + QT_PLUGIN_PATH: /usr/local/opt/qt/plugins + QML2_IMPORT_PATH: /usr/local/opt/qt/qml + + - name: Install Ninja on Windows + if: runner.os == 'Windows' run: choco install ninja -y - # Set up Visual Studio and Download/Build Qt - - name: Set up Visual Studio environment and Download/Build Qt + - name: Set up and Build Qt on Windows + if: runner.os == 'Windows' shell: pwsh env: QT_VERSION: 6.5.3 run: | # Set up Visual Studio environment - Write-Host "Setting up Visual Studio environment" $vsPath = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath $env:Path += ";$vsPath\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64" & "$vsPath\Common7\Tools\VsDevCmd.bat" - # Define source directory + # Define source directory for caching $qtSourceDir = "$env:TEMP\qt-source" New-Item -ItemType Directory -Path $qtSourceDir -Force - # Download Qt source if not cached + # Check cache and download Qt source if necessary if (!(Test-Path "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION.zip")) { Write-Host "Downloading Qt Source" $qtSourceUrl = "https://download.qt.io/official_releases/qt/6.5/$env:QT_VERSION/single/qt-everywhere-src-$env:QT_VERSION.zip" @@ -42,34 +55,27 @@ jobs: } # Configure and build Qt using Ninja - Write-Host "Configuring and building Qt with Ninja" cd "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION\qtbase" .\configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . # Set environment variables for Qt - Write-Host "Setting Qt environment variables" echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $GITHUB_ENV echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $GITHUB_ENV echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $GITHUB_ENV - # CMake configuration and build for project + # CMake configuration for all OSes - name: Configure CMake - shell: pwsh - run: | - cmake -B "${{ github.workspace }}\build" -G "Ninja" -S "${{ github.workspace }}" ` - -DCMAKE_CXX_COMPILER=cl -DCMAKE_C_COMPILER=cl -DCMAKE_BUILD_TYPE=Release + run: cmake -B build -G "Ninja" -S . -DCMAKE_BUILD_TYPE=Release env: - Qt6_DIR: C:\Qt\lib\cmake\Qt6 - QT_PLUGIN_PATH: C:\Qt\plugins - QML2_IMPORT_PATH: C:\Qt\qml + Qt6_DIR: ${{ runner.os == 'Windows' && 'C:\Qt\lib\cmake\Qt6' || '/usr/local/opt/qt/lib/cmake/Qt6' }} + QT_PLUGIN_PATH: ${{ runner.os == 'Windows' && 'C:\Qt\plugins' || '/usr/local/opt/qt/plugins' }} + QML2_IMPORT_PATH: ${{ runner.os == 'Windows' && 'C:\Qt\qml' || '/usr/local/opt/qt/qml' }} - - name: Build project - shell: pwsh - run: cmake --build "${{ github.workspace }}\build" --config Release + - name: Build Project + run: cmake --build build --config Release - - name: Run tests - shell: pwsh - working-directory: "${{ github.workspace }}\build" - run: ctest --output-on-failure --build-config Release + - name: Run Tests + working-directory: build + run: ctest --output-on-failure From 40b535ce6fb3305dbba394eb916e30f310d3b801 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 13 Nov 2024 10:31:13 +0330 Subject: [PATCH 16/81] github action #44 --- .github/workflows/cmake-multi-platform.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 7f09de2..52a93cf 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -17,11 +17,17 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - - name: Set up Qt on Ubuntu and macOS + # Install Ninja and Qt on Ubuntu and macOS + - name: Install dependencies on Ubuntu and macOS if: runner.os != 'Windows' run: | - sudo apt-get update -y || brew update - sudo apt-get install -y qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools || brew install qt + if [[ "$RUNNER_OS" == "Linux" ]]; then + sudo apt-get update -y + sudo apt-get install -y ninja-build qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools + elif [[ "$RUNNER_OS" == "macOS" ]]; then + brew update + brew install ninja qt + fi env: Qt6_DIR: /usr/local/opt/qt/lib/cmake/Qt6 QT_PLUGIN_PATH: /usr/local/opt/qt/plugins @@ -31,6 +37,7 @@ jobs: if: runner.os == 'Windows' run: choco install ninja -y + # Set up and Build Qt on Windows - name: Set up and Build Qt on Windows if: runner.os == 'Windows' shell: pwsh From b4c98e4ddf7c56092f230d329d7b8b0ec4948b43 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 13 Nov 2024 10:48:19 +0330 Subject: [PATCH 17/81] github action #45 --- .github/workflows/cmake-multi-platform.yml | 157 +++++++++++++-------- 1 file changed, 95 insertions(+), 62 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 52a93cf..1fe8fa9 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -9,80 +9,113 @@ on: jobs: build: runs-on: ${{ matrix.os }} + strategy: + fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-latest, windows-latest, macos-latest] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + - os: ubuntu-latest + c_compiler: gcc + cpp_compiler: g++ + - os: macos-latest + c_compiler: clang + cpp_compiler: clang++ steps: - - name: Checkout code - uses: actions/checkout@v2 + - name: Checkout code + uses: actions/checkout@v4 + + ### Ubuntu Dependencies + - name: Install dependencies (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y ninja-build \ + qt6-base-dev qt6-tools-dev qt6-tools-dev-tools \ + qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev + echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV - # Install Ninja and Qt on Ubuntu and macOS - - name: Install dependencies on Ubuntu and macOS - if: runner.os != 'Windows' - run: | - if [[ "$RUNNER_OS" == "Linux" ]]; then - sudo apt-get update -y - sudo apt-get install -y ninja-build qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools - elif [[ "$RUNNER_OS" == "macOS" ]]; then - brew update - brew install ninja qt - fi - env: - Qt6_DIR: /usr/local/opt/qt/lib/cmake/Qt6 - QT_PLUGIN_PATH: /usr/local/opt/qt/plugins - QML2_IMPORT_PATH: /usr/local/opt/qt/qml + ### macOS Dependencies + - name: Install dependencies (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install ninja qt + echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - - name: Install Ninja on Windows - if: runner.os == 'Windows' - run: choco install ninja -y + ### Windows Setup with Qt Source Compilation and Caching + - name: Install dependencies (Windows) + if: matrix.os == 'windows-latest' + shell: powershell + run: | + choco install visualstudio2022buildtools -y + choco install ninja -y + choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - # Set up and Build Qt on Windows - - name: Set up and Build Qt on Windows - if: runner.os == 'Windows' - shell: pwsh - env: - QT_VERSION: 6.5.3 - run: | - # Set up Visual Studio environment - $vsPath = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath - $env:Path += ";$vsPath\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64" - & "$vsPath\Common7\Tools\VsDevCmd.bat" + - name: Cache Qt Source (Windows) + if: matrix.os == 'windows-latest' + uses: actions/cache@v3 + with: + path: ${{ runner.temp }}/qt-source + key: qt-source-6.5.3 - # Define source directory for caching - $qtSourceDir = "$env:TEMP\qt-source" + - name: Download Qt Source (Windows) + if: matrix.os == 'windows-latest' + shell: powershell + run: | + $qtSourceDir = "$env:TEMP\qt-source" + $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" + if (-Not (Test-Path $qtZip)) { + Write-Host "Downloading Qt Source" New-Item -ItemType Directory -Path $qtSourceDir -Force + Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip + Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir + } - # Check cache and download Qt source if necessary - if (!(Test-Path "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION.zip")) { - Write-Host "Downloading Qt Source" - $qtSourceUrl = "https://download.qt.io/official_releases/qt/6.5/$env:QT_VERSION/single/qt-everywhere-src-$env:QT_VERSION.zip" - Invoke-WebRequest -Uri $qtSourceUrl -OutFile "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION.zip" - Expand-Archive -Path "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION.zip" -DestinationPath $qtSourceDir - } + - name: Build and Install Qt (Windows) + if: matrix.os == 'windows-latest' + shell: cmd + run: | + FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ + -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i + IF NOT DEFINED VS_PATH ( + echo Visual Studio Build Tools not found! && exit /b 1 + ) + SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" + CALL "%VS_VARS_CMD%" || exit /b 1 - # Configure and build Qt using Ninja - cd "$qtSourceDir\qt-everywhere-src-$env:QT_VERSION\qtbase" - .\configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build . --parallel - cmake --install . + # Configure and build Qt with Ninja + cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase + configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cmake --build . --parallel + cmake --install . - # Set environment variables for Qt - echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $GITHUB_ENV - echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $GITHUB_ENV - echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $GITHUB_ENV + - name: Set Qt Environment Variables (Windows) + if: matrix.os == 'windows-latest' + shell: powershell + run: | + echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $env:GITHUB_ENV + echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV + echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV - # CMake configuration for all OSes - - name: Configure CMake - run: cmake -B build -G "Ninja" -S . -DCMAKE_BUILD_TYPE=Release - env: - Qt6_DIR: ${{ runner.os == 'Windows' && 'C:\Qt\lib\cmake\Qt6' || '/usr/local/opt/qt/lib/cmake/Qt6' }} - QT_PLUGIN_PATH: ${{ runner.os == 'Windows' && 'C:\Qt\plugins' || '/usr/local/opt/qt/plugins' }} - QML2_IMPORT_PATH: ${{ runner.os == 'Windows' && 'C:\Qt\qml' || '/usr/local/opt/qt/qml' }} + # Configure CMake + - name: Configure CMake + run: | + cmake -B "${{ github.workspace }}/build" \ + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ + -DCMAKE_BUILD_TYPE=Release \ + -G "Ninja" \ + -S "${{ github.workspace }}" - - name: Build Project - run: cmake --build build --config Release + # Build the project + - name: Build + run: cmake --build "${{ github.workspace }}/build" --config Release - - name: Run Tests - working-directory: build - run: ctest --output-on-failure + # Run tests + - name: Test + working-directory: "${{ github.workspace }}/build" + run: ctest --output-on-failure --build-config Release From b7b715003e0b51f5eb3448d211ebd46bf80b0959 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 13 Nov 2024 17:07:21 +0330 Subject: [PATCH 18/81] github action #46 --- .github/workflows/cmake-multi-platform.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 1fe8fa9..e09f048 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -75,7 +75,7 @@ jobs: Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } - - name: Build and Install Qt (Windows) + - name: Set up MSVC environment (Windows) if: matrix.os == 'windows-latest' shell: cmd run: | @@ -87,8 +87,14 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - # Configure and build Qt with Ninja + - name: Build and Install Qt (Windows) + if: matrix.os == 'windows-latest' + shell: cmd + run: | cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase + IF NOT EXIST configure.bat ( + echo "configure.bat not found!" && exit /b 1 + ) configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From c5c1f5f174e907a31a792fa17fefb0f0fadd95bb Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 13 Nov 2024 22:16:16 +0330 Subject: [PATCH 19/81] github action #47 --- .github/workflows/cmake-multi-platform.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index e09f048..b6609c9 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -74,6 +74,10 @@ jobs: Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } + # Confirm that configure.bat exists + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + throw "configure.bat not found after extraction!" + } - name: Set up MSVC environment (Windows) if: matrix.os == 'windows-latest' @@ -92,9 +96,6 @@ jobs: shell: cmd run: | cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase - IF NOT EXIST configure.bat ( - echo "configure.bat not found!" && exit /b 1 - ) configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From f7af3e5326f11f29ee01fa3c39eb7636a56fdf49 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 14 Nov 2024 04:16:19 +0330 Subject: [PATCH 20/81] github action #48 --- .github/workflows/cmake-multi-platform.yml | 29 ++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index b6609c9..e164398 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -59,24 +59,24 @@ jobs: if: matrix.os == 'windows-latest' uses: actions/cache@v3 with: - path: ${{ runner.temp }}/qt-source + path: ${{ runner.temp }}\qt-source key: qt-source-6.5.3 - - name: Download Qt Source (Windows) + - name: Download and Extract Qt Source (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | $qtSourceDir = "$env:TEMP\qt-source" $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path $qtZip)) { - Write-Host "Downloading Qt Source" - New-Item -ItemType Directory -Path $qtSourceDir -Force - Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip - Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir - } - # Confirm that configure.bat exists + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - throw "configure.bat not found after extraction!" + Write-Host "Qt source not cached or incomplete. Downloading and extracting..." + if (-Not (Test-Path $qtZip)) { + Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip + } + Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir + } else { + Write-Host "Using cached Qt source." } - name: Set up MSVC environment (Windows) @@ -96,6 +96,9 @@ jobs: shell: cmd run: | cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase + IF NOT EXIST configure.bat ( + echo "configure.bat not found!" && exit /b 1 + ) configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . @@ -111,7 +114,7 @@ jobs: # Configure CMake - name: Configure CMake run: | - cmake -B "${{ github.workspace }}/build" \ + cmake -B "${{ github.workspace }}\build" \ -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ -DCMAKE_BUILD_TYPE=Release \ @@ -120,9 +123,9 @@ jobs: # Build the project - name: Build - run: cmake --build "${{ github.workspace }}/build" --config Release + run: cmake --build "${{ github.workspace }}\build" --config Release # Run tests - name: Test - working-directory: "${{ github.workspace }}/build" + working-directory: "${{ github.workspace }}\build" run: ctest --output-on-failure --build-config Release From 855d2b553bd8b349da284c1eac601b1fe0e3cfd7 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 14 Nov 2024 04:22:20 +0330 Subject: [PATCH 21/81] github action #49 --- .github/workflows/cmake-multi-platform.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index e164398..c6c0e16 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -29,7 +29,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - ### Ubuntu Dependencies + ### Ubuntu Dependencies (Unchanged) - name: Install dependencies (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | @@ -39,14 +39,14 @@ jobs: qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV - ### macOS Dependencies + ### macOS Dependencies (Unchanged) - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' run: | brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Qt Source Compilation and Caching + ### Windows Setup with Qt Source Compilation and Caching (Fixed) - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -111,7 +111,7 @@ jobs: echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV - # Configure CMake + # Configure CMake (Unchanged) - name: Configure CMake run: | cmake -B "${{ github.workspace }}\build" \ @@ -121,11 +121,11 @@ jobs: -G "Ninja" \ -S "${{ github.workspace }}" - # Build the project + # Build the project (Unchanged) - name: Build run: cmake --build "${{ github.workspace }}\build" --config Release - # Run tests + # Run tests (Unchanged) - name: Test working-directory: "${{ github.workspace }}\build" run: ctest --output-on-failure --build-config Release From 92b65c97a450db74eff63be3c7c046837b20b035 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 14 Nov 2024 04:36:10 +0330 Subject: [PATCH 22/81] github action #50 --- .github/workflows/cmake-multi-platform.yml | 29 ++++++++-------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index c6c0e16..7ba2cf2 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Qt Source Compilation and Caching (Fixed) + ### Windows Setup with Qt Source Compilation and Caching (Modified) - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -62,24 +62,20 @@ jobs: path: ${{ runner.temp }}\qt-source key: qt-source-6.5.3 - - name: Download and Extract Qt Source (Windows) + - name: Download Qt Source (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | $qtSourceDir = "$env:TEMP\qt-source" $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - Write-Host "Qt source not cached or incomplete. Downloading and extracting..." - if (-Not (Test-Path $qtZip)) { - Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip - } + if (-Not (Test-Path $qtZip)) { + Write-Host "Downloading Qt Source" + New-Item -ItemType Directory -Path $qtSourceDir -Force + Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir - } else { - Write-Host "Using cached Qt source." } - - name: Set up MSVC environment (Windows) + - name: Build and Install Qt (Windows) if: matrix.os == 'windows-latest' shell: cmd run: | @@ -91,10 +87,7 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - - name: Build and Install Qt (Windows) - if: matrix.os == 'windows-latest' - shell: cmd - run: | + # Configure and build Qt with Ninja cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase IF NOT EXIST configure.bat ( echo "configure.bat not found!" && exit /b 1 @@ -114,7 +107,7 @@ jobs: # Configure CMake (Unchanged) - name: Configure CMake run: | - cmake -B "${{ github.workspace }}\build" \ + cmake -B "${{ github.workspace }}/build" \ -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ -DCMAKE_BUILD_TYPE=Release \ @@ -123,9 +116,9 @@ jobs: # Build the project (Unchanged) - name: Build - run: cmake --build "${{ github.workspace }}\build" --config Release + run: cmake --build "${{ github.workspace }}/build" --config Release # Run tests (Unchanged) - name: Test - working-directory: "${{ github.workspace }}\build" + working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release From ec022d47e655f5276ee011372544c7206a6764a8 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 14 Nov 2024 14:21:38 +0330 Subject: [PATCH 23/81] github action #51 --- .github/workflows/cmake-multi-platform.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 7ba2cf2..c8946a7 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -79,6 +79,7 @@ jobs: if: matrix.os == 'windows-latest' shell: cmd run: | + # Locate Visual Studio Build Tools FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i IF NOT DEFINED VS_PATH ( @@ -92,7 +93,7 @@ jobs: IF NOT EXIST configure.bat ( echo "configure.bat not found!" && exit /b 1 ) - configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From da6e71081e1c615352fb5fcf823af5b5be1c05c5 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 14 Nov 2024 20:04:36 +0330 Subject: [PATCH 24/81] github action #52 --- .github/workflows/cmake-multi-platform.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index c8946a7..0f3c9fb 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Qt Source Compilation and Caching (Modified) + ### Windows Setup with Qt Source Compilation and Caching - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -79,7 +79,6 @@ jobs: if: matrix.os == 'windows-latest' shell: cmd run: | - # Locate Visual Studio Build Tools FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i IF NOT DEFINED VS_PATH ( @@ -88,7 +87,6 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - # Configure and build Qt with Ninja cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase IF NOT EXIST configure.bat ( echo "configure.bat not found!" && exit /b 1 From deededd7166a403aee7029121375b772a51799e7 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 15 Nov 2024 01:38:36 +0330 Subject: [PATCH 25/81] github action #53 --- .github/workflows/cmake-multi-platform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 0f3c9fb..baa72b3 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -68,7 +68,7 @@ jobs: run: | $qtSourceDir = "$env:TEMP\qt-source" $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path $qtZip)) { + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3")) { Write-Host "Downloading Qt Source" New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip From f4f66be332e3a83f45d13d63f6b074faf0fcb92b Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 15 Nov 2024 11:39:18 +0330 Subject: [PATCH 26/81] github action #54 --- .github/workflows/cmake-multi-platform.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index baa72b3..6b3d647 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -29,7 +29,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - ### Ubuntu Dependencies (Unchanged) + ### Ubuntu Dependencies - name: Install dependencies (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | @@ -39,7 +39,7 @@ jobs: qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV - ### macOS Dependencies (Unchanged) + ### macOS Dependencies - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' run: | @@ -59,7 +59,7 @@ jobs: if: matrix.os == 'windows-latest' uses: actions/cache@v3 with: - path: ${{ runner.temp }}\qt-source + path: ${{ runner.temp }}/qt-source key: qt-source-6.5.3 - name: Download Qt Source (Windows) @@ -68,7 +68,7 @@ jobs: run: | $qtSourceDir = "$env:TEMP\qt-source" $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3")) { + if (-Not (Test-Path $qtZip)) { Write-Host "Downloading Qt Source" New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip @@ -79,6 +79,7 @@ jobs: if: matrix.os == 'windows-latest' shell: cmd run: | + REM Locate Visual Studio Build Tools FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i IF NOT DEFINED VS_PATH ( @@ -87,6 +88,7 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 + REM Configure and build Qt cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase IF NOT EXIST configure.bat ( echo "configure.bat not found!" && exit /b 1 @@ -103,7 +105,7 @@ jobs: echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV - # Configure CMake (Unchanged) + # Configure CMake - name: Configure CMake run: | cmake -B "${{ github.workspace }}/build" \ @@ -113,11 +115,11 @@ jobs: -G "Ninja" \ -S "${{ github.workspace }}" - # Build the project (Unchanged) + # Build the project - name: Build run: cmake --build "${{ github.workspace }}/build" --config Release - # Run tests (Unchanged) + # Run tests - name: Test working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release From c0eec14ae52f0a3ab119d6cd80af9ad8ecb25633 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 15 Nov 2024 17:50:05 +0330 Subject: [PATCH 27/81] github action #55 --- .github/workflows/cmake-multi-platform.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 6b3d647..0a98972 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -74,6 +74,9 @@ jobs: Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + throw "configure.bat not found in $qtSourceDir" + } - name: Build and Install Qt (Windows) if: matrix.os == 'windows-latest' From dfbe1b6dd494e4fdc2019ab2b6ac2fa3859266e6 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 15 Nov 2024 23:45:45 +0330 Subject: [PATCH 28/81] github action #56 --- .github/workflows/cmake-multi-platform.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 0a98972..89a7398 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -74,9 +74,6 @@ jobs: Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - throw "configure.bat not found in $qtSourceDir" - } - name: Build and Install Qt (Windows) if: matrix.os == 'windows-latest' @@ -91,11 +88,13 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 + REM Check if Qt source directory exists + IF NOT EXIST "%TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase\configure.bat" ( + echo "configure.bat not found in %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase" && exit /b 1 + ) + REM Configure and build Qt cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase - IF NOT EXIST configure.bat ( - echo "configure.bat not found!" && exit /b 1 - ) call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From 061ccd4d5b89ca903be0bc5badac096ca3301bf6 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sat, 16 Nov 2024 06:11:38 +0330 Subject: [PATCH 29/81] github action#57 --- .github/workflows/cmake-multi-platform.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 89a7398..34b9641 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -74,6 +74,9 @@ jobs: Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + throw "configure.bat not found in $qtSourceDir\qt-everywhere-src-6.5.3\qtbase" + } - name: Build and Install Qt (Windows) if: matrix.os == 'windows-latest' @@ -88,7 +91,7 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - REM Check if Qt source directory exists + REM Check if configure.bat exists IF NOT EXIST "%TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase\configure.bat" ( echo "configure.bat not found in %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase" && exit /b 1 ) From 85106da4d34127931363ba3c3ed8b22a6177e736 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sat, 16 Nov 2024 12:01:33 +0330 Subject: [PATCH 30/81] github action #58 --- .github/workflows/cmake-multi-platform.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 34b9641..0690f6e 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -91,14 +91,15 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - REM Check if configure.bat exists - IF NOT EXIST "%TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase\configure.bat" ( - echo "configure.bat not found in %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase" && exit /b 1 + REM Ensure configure.bat is accessible + SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase + IF NOT EXIST "%QT_SOURCE%\configure.bat" ( + echo "configure.bat not found in %QT_SOURCE%" && exit /b 1 ) REM Configure and build Qt - cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cd "%QT_SOURCE%" + call "%QT_SOURCE%\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From acdf24af420b56438f7972a282f85eadd0485350 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sat, 16 Nov 2024 16:16:42 +0330 Subject: [PATCH 31/81] github action #59 --- .github/workflows/cmake-multi-platform.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 0690f6e..5b555c6 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -91,17 +91,12 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - REM Ensure configure.bat is accessible - SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase - IF NOT EXIST "%QT_SOURCE%\configure.bat" ( - echo "configure.bat not found in %QT_SOURCE%" && exit /b 1 - ) - REM Configure and build Qt - cd "%QT_SOURCE%" - call "%QT_SOURCE%\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build . --parallel - cmake --install . + SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 + cd "%QT_SOURCE%\qtbase" + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cmake --build "%QT_SOURCE%" --parallel + cmake --install "%QT_SOURCE%" - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From 7ae59ec1df4010df680bc6c2ca5afcbc627f26fd Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sat, 16 Nov 2024 21:42:05 +0330 Subject: [PATCH 32/81] github action #60 --- .github/workflows/cmake-multi-platform.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 5b555c6..a28762f 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -94,9 +94,12 @@ jobs: REM Configure and build Qt SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 cd "%QT_SOURCE%\qtbase" + IF NOT EXIST configure.bat ( + echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 + ) call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build "%QT_SOURCE%" --parallel - cmake --install "%QT_SOURCE%" + cmake --build "%QT_SOURCE%\qtbase" --parallel + cmake --install "%QT_SOURCE%\qtbase" - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From 547634c51cb6a789019906e278c5c670a2852fb2 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sun, 17 Nov 2024 10:25:37 +0330 Subject: [PATCH 33/81] github action #61 --- .github/workflows/cmake-multi-platform.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index a28762f..898dd6c 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -62,21 +62,18 @@ jobs: path: ${{ runner.temp }}/qt-source key: qt-source-6.5.3 - - name: Download Qt Source (Windows) + - name: Download and Extract Qt Source (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | $qtSourceDir = "$env:TEMP\qt-source" $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path $qtZip)) { + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { Write-Host "Downloading Qt Source" New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - throw "configure.bat not found in $qtSourceDir\qt-everywhere-src-6.5.3\qtbase" - } - name: Build and Install Qt (Windows) if: matrix.os == 'windows-latest' @@ -93,10 +90,10 @@ jobs: REM Configure and build Qt SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 - cd "%QT_SOURCE%\qtbase" - IF NOT EXIST configure.bat ( + IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) + cd "%QT_SOURCE%\qtbase" call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build "%QT_SOURCE%\qtbase" --parallel cmake --install "%QT_SOURCE%\qtbase" From d547ef0e118cb9e2344567ccd9119693a604e45f Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sun, 17 Nov 2024 15:14:35 +0330 Subject: [PATCH 34/81] github action #62 --- .github/workflows/cmake-multi-platform.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 898dd6c..7af6371 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -74,6 +74,9 @@ jobs: Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + throw "configure.bat is missing after extraction. Verify the source archive and extraction process." + } - name: Build and Install Qt (Windows) if: matrix.os == 'windows-latest' From a1e8acea417e18f47deb15d5982a78e5c0f6c82a Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sun, 17 Nov 2024 23:29:40 +0330 Subject: [PATCH 35/81] github action #63 --- .github/workflows/cmake-multi-platform.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 7af6371..5d03f7c 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -75,7 +75,9 @@ jobs: Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - throw "configure.bat is missing after extraction. Verify the source archive and extraction process." + Write-Host "Error: configure.bat is missing in $qtSourceDir after extraction." + dir "$qtSourceDir" + throw "configure.bat not found. Verify extraction process." } - name: Build and Install Qt (Windows) From e524a5ce3a559d782dcba8a16601c1f2808fe0b5 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Mon, 18 Nov 2024 03:00:08 +0330 Subject: [PATCH 36/81] v0.0.48 --- .github/workflows/cmake-multi-platform.yml | 24 +- CHANGELOG.md | 5 + CMakeLists.txt | 23 +- CMakeLists.txt.user | 22 +- src/codeeditor.cpp | 78 +++++- src/codeeditor.h | 4 +- src/find/finddialog.h | 12 +- src/find/finddialog.ui | 2 +- src/helpers.cpp | 67 +++++ src/helpers.h | 3 + src/main.cpp | 42 +++ src/mainwindow.cpp | 83 +++++- src/mainwindow.h | 7 + src/mainwindow.ui | 6 + src/replace/replacedialog.h | 13 +- src/replace/replacedialog.ui | 7 +- src/search/filesearchworker.cpp | 55 ++++ src/search/filesearchworker.h | 25 ++ src/search/searchoptions.h | 27 +- src/systemfind/richtextdelegate.cpp | 71 +++++ src/systemfind/richtextdelegate.h | 11 + src/systemfind/systemfind.cpp | 3 + src/systemfind/systemfind.h | 8 + src/systemfind/systemfinddialog.cpp | 293 ++++++++++++++++++++- src/systemfind/systemfinddialog.h | 58 +++- src/systemfind/systemfinddialog.ui | 182 ++++++++----- src/systemreplace/systemreplace.cpp | 3 + src/systemreplace/systemreplace.h | 8 + src/systemreplace/systemreplacedialog.cpp | 211 ++++++++++++++- src/systemreplace/systemreplacedialog.h | 35 ++- src/systemreplace/systemreplacedialog.ui | 226 +++++++++------- src/systemsearchresultdialog.cpp | 117 ++++++++ src/systemsearchresultdialog.h | 37 +++ src/systemsearchresultdialog.ui | 24 ++ src/systemtextdelegate.cpp | 69 +++++ src/systemtextdelegate.h | 14 + 36 files changed, 1646 insertions(+), 229 deletions(-) create mode 100644 src/search/filesearchworker.cpp create mode 100644 src/search/filesearchworker.h create mode 100644 src/systemfind/richtextdelegate.cpp create mode 100644 src/systemfind/richtextdelegate.h create mode 100644 src/systemfind/systemfind.cpp create mode 100644 src/systemfind/systemfind.h create mode 100644 src/systemreplace/systemreplace.cpp create mode 100644 src/systemreplace/systemreplace.h create mode 100644 src/systemsearchresultdialog.cpp create mode 100644 src/systemsearchresultdialog.h create mode 100644 src/systemsearchresultdialog.ui create mode 100644 src/systemtextdelegate.cpp create mode 100644 src/systemtextdelegate.h diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 5d03f7c..1fe8fa9 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -62,29 +62,23 @@ jobs: path: ${{ runner.temp }}/qt-source key: qt-source-6.5.3 - - name: Download and Extract Qt Source (Windows) + - name: Download Qt Source (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | $qtSourceDir = "$env:TEMP\qt-source" $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + if (-Not (Test-Path $qtZip)) { Write-Host "Downloading Qt Source" New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - Write-Host "Error: configure.bat is missing in $qtSourceDir after extraction." - dir "$qtSourceDir" - throw "configure.bat not found. Verify extraction process." - } - name: Build and Install Qt (Windows) if: matrix.os == 'windows-latest' shell: cmd run: | - REM Locate Visual Studio Build Tools FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i IF NOT DEFINED VS_PATH ( @@ -93,15 +87,11 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - REM Configure and build Qt - SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 - IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( - echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 - ) - cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build "%QT_SOURCE%\qtbase" --parallel - cmake --install "%QT_SOURCE%\qtbase" + # Configure and build Qt with Ninja + cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase + configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cmake --build . --parallel + cmake --install . - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' diff --git a/CHANGELOG.md b/CHANGELOG.md index dab8eda..2ba5f06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 0.0.48 + +- Implemented: +- Search Menu -> Find System (partially) + ## 0.0.47 - Implemented: diff --git a/CMakeLists.txt b/CMakeLists.txt index a6a51de..bfabcca 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ set(PROJECT_UI src/indentation/indentationdialog.ui src/systemfind/systemfinddialog.ui src/systemreplace/systemreplacedialog.ui + src/systemsearchresultdialog.ui ) set(PROJECT_SOURCES @@ -76,19 +77,29 @@ set(PROJECT_SOURCES src/find/finddialog.h src/replace/replacedialog.cpp src/replace/replacedialog.h - src/systemfind/systemfinddialog.cpp - src/systemfind/systemfinddialog.h - src/systemreplace/systemreplacedialog.cpp - src/systemreplace/systemreplacedialog.h src/replace/replace.cpp src/replace/replace.h src/find/find.cpp src/find/find.h src/search/search.cpp src/search/search.h - - src/search/searchoptions.h + src/systemfind/systemfinddialog.cpp + src/systemfind/systemfinddialog.h + src/systemreplace/systemreplacedialog.cpp + src/systemreplace/systemreplacedialog.h + src/systemfind/systemfind.cpp + src/systemfind/systemfind.h + src/systemreplace/systemreplace.cpp + src/systemreplace/systemreplace.h + src/systemsearchresultdialog.cpp + src/systemsearchresultdialog.h + src/search/filesearchworker.cpp + src/search/filesearchworker.h + src/systemfind/richtextdelegate.cpp + src/systemfind/richtextdelegate.h + src/systemtextdelegate.cpp + src/systemtextdelegate.h ${PROJECT_UI} ) diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index 52e2b56..a84fe63 100755 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -102,14 +102,14 @@ 2 false - -DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake -DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_BUILD_TYPE:STRING=Debug +-DCMAKE_BUILD_TYPE:STRING=Debug +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} /data/Code/Qt/Notepad-- 0 /data/Code/Qt/Notepad--/build/Desktop-Debug @@ -160,14 +160,14 @@ 2 false - -DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} + -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake -DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_BUILD_TYPE:STRING=Release +-DCMAKE_BUILD_TYPE:STRING=Release +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} /data/Code/Qt/Notepad-- /data/Code/Qt/Notepad--/build/Desktop-Release diff --git a/src/codeeditor.cpp b/src/codeeditor.cpp index 02a5e46..e9adf5e 100755 --- a/src/codeeditor.cpp +++ b/src/codeeditor.cpp @@ -1,6 +1,7 @@ #include "codeeditor.h" #include #include +#include #include "helpers.h" CodeEditor::CodeEditor(QWidget *parent) @@ -153,10 +154,83 @@ void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event) { } void CodeEditor::applyIndentation(bool useTabs, int indentationWidth) { - // TODO: Implement indentation - qDebug() << "Indentation. Use Tabs: " << useTabs << ". Indentation width: " << indentationWidth; + QTextCursor cursor = textCursor(); + QString indentation = useTabs ? "\t" : QString(indentationWidth, ' '); + cursor.insertText(indentation); } QTabWidget* CodeEditor::DocumentsTab() { return m_documentsTab; } + +void CodeEditor::highlightAllOccurrences(const QString& keyword) { + QList extraSelections; + + QTextCursor cursor(document()); + QTextCursor highlightCursor(document()); + QTextCharFormat highlightFormat; + highlightFormat.setBackground(Qt::cyan); + + while (!cursor.isNull() && !cursor.atEnd()) { + cursor = document()->find(keyword, cursor); + if (!cursor.isNull()) { + QTextEdit::ExtraSelection selection; + selection.cursor = cursor; + selection.format = highlightFormat; + extraSelections.append(selection); + } + } + + setExtraSelections(extraSelections); +} + +void CodeEditor::goToLine(int lineNumber) { + if (lineNumber < 1 || lineNumber > document()->blockCount()) { + qWarning() << "Line number" << lineNumber << "is out of range."; + return; + } + + QTextCursor cursor(document()->findBlockByNumber(lineNumber - 1)); + setTextCursor(cursor); + centerCursor(); // Ensure the cursor is centered in the view + + qDebug() << "Moved to line:" << lineNumber; + + // Log current cursor position + qDebug() << "Cursor position after move:" << textCursor().position(); +} + +/* +void CodeEditor::goToLine(int lineNumber) { + // Validate line number range + if (lineNumber < 1 || lineNumber > document()->blockCount()) { + qWarning() << "Line number" << lineNumber << "is out of range. Valid range: 1 to" << document()->blockCount(); + return; + } + + // Find the text block corresponding to the line number + QTextBlock block = document()->findBlockByNumber(lineNumber - 1); + if (!block.isValid()) { + qWarning() << "Invalid block for line number:" << lineNumber; + return; + } + + // Set the text cursor to the block + QTextCursor cursor(block); + setTextCursor(cursor); + + // Scroll to the block manually + QRectF blockRect = blockBoundingGeometry(block).translated(contentOffset()); + verticalScrollBar()->setValue(static_cast(blockRect.top())); + + // Ensure the editor has focus (optional) + if (!hasFocus()) { + setFocus(); + } + + qDebug() << "Moved to line:" << lineNumber; + qDebug() << "Block position:" << block.position() + << "Block geometry:" << blockRect + << "Viewport height:" << viewport()->height(); +} +*/ diff --git a/src/codeeditor.h b/src/codeeditor.h index a38e937..a5b9ef5 100755 --- a/src/codeeditor.h +++ b/src/codeeditor.h @@ -21,12 +21,14 @@ class CodeEditor : public QPlainTextEdit { void highlightCurrentLine(); void applyIndentation(bool useTabs, int indentationWidth); QTabWidget* DocumentsTab(); + void highlightAllOccurrences(const QString& keyword); + void goToLine(int lineNumber); protected: void resizeEvent(QResizeEvent *event) override; signals: - void textChanged(); + void textChanged(); // FIXME: Remove this line. private slots: void updateLineNumberAreaWidth(int newBlockCount); diff --git a/src/find/finddialog.h b/src/find/finddialog.h index ab8b857..f1b05b3 100644 --- a/src/find/finddialog.h +++ b/src/find/finddialog.h @@ -4,6 +4,7 @@ #include #include "find.h" #include "../codeeditor.h" +#include "../search/searchoptions.h" namespace Ui { class FindDialog; @@ -17,13 +18,6 @@ class FindDialog : public QDialog explicit FindDialog(QWidget *parent = nullptr); ~FindDialog(); - enum FindMode { - PlainText, - RegularExpression, - SpecialCharacters - }; - - void performFind(); static void showDialog(QWidget *parent = nullptr); QString getFindText() const; bool findPlainTextSelected() const; @@ -37,7 +31,7 @@ class FindDialog : public QDialog SearchOptions* getSearchOptions(); signals: - void findRequested(const QString& findText, bool matchCase, bool matchWholeWord, FindDialog::FindMode mode); + void findRequested(const QString& findText, bool matchCase, bool matchWholeWord, FindMethod mode); private slots: @@ -69,7 +63,7 @@ private slots: private: Ui::FindDialog *ui; - FindMode selectedFindMode() const; + FindMethod selectedFindMethod() const; SearchOptions* m_searchOptions; Find* m_find; CodeEditor* m_editor = nullptr; diff --git a/src/find/finddialog.ui b/src/find/finddialog.ui index 063dea9..42fc781 100644 --- a/src/find/finddialog.ui +++ b/src/find/finddialog.ui @@ -175,7 +175,7 @@ 16 150 - 91 + 101 23 diff --git a/src/helpers.cpp b/src/helpers.cpp index f3091dc..58255a0 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -10,6 +10,7 @@ #include "helpers.h" #include "document.h" #include "codeeditor.h" +#include "search/searchoptions.h" bool Helpers::isUntitledDocument(const QString& title) { // Static QRegularExpression to avoid repeated creation @@ -176,7 +177,73 @@ bool Helpers::isValidRegularExpression(const QString& pattern) { return regex.isValid(); } +int Helpers::countKeywordsInLine(const QString& line, const SearchOptions& options) { + QString keyword = options.keyword; + if (keyword.isEmpty()) { + return 0; + } + + QString pattern = options.matchWholeWord + ? QString("\\b%1\\b").arg(QRegularExpression::escape(keyword)) + : QRegularExpression::escape(keyword); + + QRegularExpression regex(pattern, options.matchCase + ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption); + + int count = 0; + QRegularExpressionMatchIterator it = regex.globalMatch(line); + while (it.hasNext()) { + it.next(); + count++; + } + + return count; +} + +// FIXME: If user search for "hello" and a match found as "Hello" in retun string "hello" would return. +QString Helpers::highlightKeywords(const QString& line, const SearchOptions& options) { + QString keyword = options.keyword; + if (keyword.isEmpty()) { + return line; // No keyword to highlight + } + // Build the regex pattern + QString pattern = options.matchWholeWord + ? QString("\\b%1\\b").arg(QRegularExpression::escape(keyword)) // Whole word matching + : QRegularExpression::escape(keyword); // Partial match + // Configure case sensitivity + QRegularExpression regex(pattern, options.matchCase + ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption); + // Process the line and replace matches with highlighted versions + QString highlightedLine; + int lastIndex = 0; + QRegularExpressionMatchIterator it = regex.globalMatch(line); + while (it.hasNext()) { + QRegularExpressionMatch match = it.next(); + + // Append the part before the match + highlightedLine.append(line.mid(lastIndex, match.capturedStart() - lastIndex)); + + // Append the highlighted match + highlightedLine.append(""); + highlightedLine.append(match.captured()); + highlightedLine.append(""); + + // Update the last index to the end of the match + lastIndex = match.capturedEnd(); + } + + // Append the remaining part of the line + highlightedLine.append(line.mid(lastIndex)); + + // Ensure no `` tags exist + highlightedLine.replace("", ""); + highlightedLine.replace("", ""); + + return highlightedLine; +} diff --git a/src/helpers.h b/src/helpers.h index f2c7982..d4f75b0 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -8,6 +8,7 @@ #include #include #include "document.h" +#include "search/searchoptions.h" class Document; @@ -25,6 +26,8 @@ class Helpers { static void gotoLineInText(QWidget* parent, CodeEditor* editor); static void gotoLineInEditor(QWidget* parent, CodeEditor* editor); static bool isValidRegularExpression(const QString& pattern); + static int countKeywordsInLine(const QString &line, const SearchOptions &searchOptions); + static QString highlightKeywords(const QString& line, const SearchOptions& options); private: bool validateDocument(Document* doc, QWidget* parent); diff --git a/src/main.cpp b/src/main.cpp index b8b0831..ee8e38b 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,45 @@ #include "mainwindow.h" #include +#define COLOR_RESET "\033[0m" +#define COLOR_RED "\033[31m" // For errors or warnings +#define COLOR_GREEN "\033[32m" // For success messages +#define COLOR_YELLOW "\033[33m" // For warnings +#define COLOR_BLUE "\033[34m" // For informational messages +#define COLOR_MAGENTA "\033[35m" +#define COLOR_CYAN "\033[36m" + +void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + QByteArray localMsg = msg.toLocal8Bit(); + const char *file = context.file ? context.file : ""; + const char *function = context.function ? context.function : ""; + int line = context.line; + + switch (type) { + case QtDebugMsg: + fprintf(stderr, "%s[DEBUG]%s %s (%s:%d, %s)\n", + COLOR_BLUE, COLOR_RESET, localMsg.constData(), file, line, function); + break; + case QtInfoMsg: + fprintf(stderr, "%s[INFO]%s %s (%s:%d, %s)\n", + COLOR_CYAN, COLOR_RESET, localMsg.constData(), file, line, function); + break; + case QtWarningMsg: + fprintf(stderr, "%s[WARNING]%s %s (%s:%d, %s)\n", + COLOR_YELLOW, COLOR_RESET, localMsg.constData(), file, line, function); + break; + case QtCriticalMsg: + fprintf(stderr, "%s[CRITICAL]%s %s (%s:%d, %s)\n", + COLOR_RED, COLOR_RESET, localMsg.constData(), file, line, function); + break; + case QtFatalMsg: + fprintf(stderr, "%s[FATAL]%s %s (%s:%d, %s)\n", + COLOR_MAGENTA, COLOR_RESET, localMsg.constData(), file, line, function); + abort(); + } +} + int main(int argc, char *argv[]) { QApplication app(argc, argv); @@ -10,5 +49,8 @@ int main(int argc, char *argv[]) MainWindow w; w.show(); + qInstallMessageHandler(customMessageHandler); return app.exec(); } + + diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e78efaf..a8c8117 100755 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -14,6 +15,8 @@ #include "indentation/indentationdialog.h" #include "find/finddialog.h" #include "replace/replacedialog.h" +#include "systemfind/systemfinddialog.h" +#include "systemreplace/systemreplacedialog.h" MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), @@ -342,26 +345,63 @@ void MainWindow::on_action_Replace_triggered() void MainWindow::on_actionReplace_N_ext_triggered() { - qDebug() << "Implement on_actionReplace_N_ext_triggered"; - // TODO: Implement + if (!replaceDialog->getReplace()) { + qDebug() << "replaceDialog is null."; + return; + } + + replaceDialog->getReplace()->replaceNext(); } void MainWindow::on_actionReplace_P_revious_triggered() { - qDebug() << "Implement on_actionReplace_P_revious_triggered"; - // TODO: Implement + if (!replaceDialog->getReplace()) { + qDebug() << "findDialog is null."; + return; + } + + replaceDialog->getReplace()->replacePrevious(); } -void MainWindow::on_actionFind_System_triggered() -{ - qDebug() << "Implement on_actionFind_System_triggered"; - // TODO: Implement +void MainWindow::on_actionFind_System_triggered() { + if (!m_systemFindDialog) { + // Create SystemFindDialog only if it doesn't already exist + m_systemFindDialog = new SystemFindDialog(this); + m_systemFindDialog->setWindowModality(Qt::NonModal); + m_systemFindDialog->show(); + } else { + // Bring existing SystemFindDialog to the front + m_systemFindDialog->raise(); + m_systemFindDialog->activateWindow(); + } + + // Check for SystemSearchResultDialog existence dynamically + QTimer::singleShot(0, this, [this]() { + SystemSearchResultDialog* m_systemSearchResultDialog = + m_systemFindDialog->findChild("SystemSearchResultDialog"); + if (m_systemSearchResultDialog) { + qDebug() << "SystemSearchResultDialog found:" << m_systemSearchResultDialog; + + // Ensure the connection is made only once + static bool isConnected = false; + if (!isConnected) { + connect(m_systemSearchResultDialog, &SystemSearchResultDialog::openFileAtMatch, + this, &MainWindow::openSearchResult); + qDebug() << "Signal-Slot Connection Successful"; + isConnected = true; + } + } else { + qDebug() << "SystemSearchResultDialog not found yet. Will retry..."; + QTimer::singleShot(100, this, &MainWindow::on_actionFind_System_triggered); + } + }); } void MainWindow::on_actionReplace_S_ystem_triggered() { - qDebug() << "Implement on_actionReplace_S_ystem_triggered"; - // TODO: Implement + SystemReplaceDialog* systemReplaceDialog = new SystemReplaceDialog(this); + systemReplaceDialog->setWindowModality(Qt::NonModal); + systemReplaceDialog->show(); } void MainWindow::on_actionGo_to_Line_in_Text_triggered() @@ -405,6 +445,29 @@ void MainWindow::on_action_Find_triggered() { +void MainWindow::openSearchResult(const QString &filePath, int lineNumber) { + qDebug() << "openSearchResult called. File Path:" << filePath << ", Line Number:" << lineNumber; + fileOperations->openDocument(filePath); + Document* doc = getCurrentDocument(); + if (doc && doc->editor()) { // FIXME: Document resets to first line. + doc->editor()->goToLine(lineNumber); + doc->editor()->highlightCurrentLine(); + } else { + qWarning() << "Document or editor is null."; + } +} + + + + + + + + + + + + void MainWindow::onActionZ80Triggered() { diff --git a/src/mainwindow.h b/src/mainwindow.h index 7e38ec0..6e9664f 100755 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -12,6 +12,8 @@ #include "mainwindow/fileoperations.h" #include "mainwindow/textoperations.h" #include "indentation/indentationmanager.h" +#include "systemfind/systemfinddialog.h" +#include "systemsearchresultdialog.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -39,6 +41,9 @@ class MainWindow : public QMainWindow { protected: void closeEvent(QCloseEvent* event) override; +public slots: + void openSearchResult(const QString &filePath, int lineNumber); + private slots: void on_action_New_triggered(); void on_action_Open_triggered(); @@ -159,6 +164,8 @@ private slots: void saveIndentationSetting(const QString& setting); // Save the selected option void loadIndentationSetting(); // Load and apply the saved setting IndentationManager* indentationManager; + SystemFindDialog* m_systemFindDialog = nullptr; + SystemSearchResultDialog* m_systemSearchResultDialog; FindDialog* findDialog; ReplaceDialog* replaceDialog; SearchOptions* m_searchOptions; diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 1df02d9..c91e5b8 100755 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1989,11 +1989,17 @@ Find &System + + F5 + Replace S&ystem + + Shift+F5 + diff --git a/src/replace/replacedialog.h b/src/replace/replacedialog.h index 8b625ca..8329019 100644 --- a/src/replace/replacedialog.h +++ b/src/replace/replacedialog.h @@ -4,6 +4,7 @@ #include #include "replace.h" #include "../codeeditor.h" +#include "../search/searchoptions.h" namespace Ui { class ReplaceDialog; @@ -17,13 +18,6 @@ class ReplaceDialog : public QDialog explicit ReplaceDialog(QWidget *parent = nullptr); ~ReplaceDialog(); - enum ReplaceMode { - PlainText, - RegularExpression, - SpecialCharacters - }; - - void performReplace(); static void showDialog(QWidget *parent = nullptr); QString getFindText() const; QString getReplaceText() const; @@ -38,10 +32,11 @@ class ReplaceDialog : public QDialog SearchOptions* getSearchOptions(); signals: - void replaceRequested(const QString& replaceText, bool matchCase, bool matchWholeWord, ReplaceDialog::ReplaceMode mode); + void replaceRequested(const QString& replaceText, bool matchCase, bool matchWholeWord, FindMethod mode); private slots: void toggleAdvancedOptions(bool checked); + void onAdvancedOptionsToggled(bool checked); void on_findNext_clicked(); @@ -78,7 +73,7 @@ private slots: private: Ui::ReplaceDialog *ui; - ReplaceMode selectedReplaceMode() const; + FindMethod selectedFindMode() const; SearchOptions* m_searchOptions; Replace* m_replace; CodeEditor* m_editor = nullptr; diff --git a/src/replace/replacedialog.ui b/src/replace/replacedialog.ui index 18641b6..d8f6f95 100644 --- a/src/replace/replacedialog.ui +++ b/src/replace/replacedialog.ui @@ -120,20 +120,23 @@ 18 32 - 121 + 131 23 Replace &plain text + + true + 17 60 - 221 + 231 23 diff --git a/src/search/filesearchworker.cpp b/src/search/filesearchworker.cpp new file mode 100644 index 0000000..ea795aa --- /dev/null +++ b/src/search/filesearchworker.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include "filesearchworker.h" + +FileSearchWorker::FileSearchWorker(const QString& filePath, const SearchOptions& options) + : m_filePath(filePath), m_options(options) { + setAutoDelete(true); +} + +void FileSearchWorker::run() { + QMimeDatabase mimeDb; + QMimeType mimeType = mimeDb.mimeTypeForFile(m_filePath); + if (mimeType.name().startsWith("text/")) { + FileSearchResults result = searchInFile(); + if (result.matchCount > 0) { + emit fileProcessed(result); + } + } +} + +FileSearchResults FileSearchWorker::searchInFile() { + FileSearchResults result; + result.filePath = m_filePath; + result.matchCount = 0; + + QFile file(m_filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return result; + + QTextStream in(&file); + QRegularExpression pattern(m_options.keyword, + m_options.matchCase ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption); + + int lineNumber = 0; + while (!in.atEnd()) { + QString line = in.readLine(); + QRegularExpressionMatchIterator it = pattern.globalMatch(line); + bool hasMatch = false; + + while (it.hasNext()) { + QRegularExpressionMatch match = it.next(); + result.matchingLines.append(highlightMatches(line, pattern)); + result.matchCount++; + hasMatch = true; + } + + if (!hasMatch) lineNumber++; + } + return result; +} + +QString FileSearchWorker::highlightMatches(const QString& line, const QRegularExpression& pattern) { + QString highlighted = line; + return highlighted.replace(pattern, "" + m_options.keyword + ""); +} diff --git a/src/search/filesearchworker.h b/src/search/filesearchworker.h new file mode 100644 index 0000000..6353f65 --- /dev/null +++ b/src/search/filesearchworker.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include +#include +#include "searchoptions.h" + +class FileSearchWorker : public QObject, public QRunnable { + Q_OBJECT + +public: + FileSearchWorker(const QString& filePath, const SearchOptions& options); + void run() override; + +signals: + void fileProcessed(const FileSearchResults& result); + +private: + FileSearchResults searchInFile(); + QString highlightMatches(const QString& line, const QRegularExpression& pattern); + + QString m_filePath; + SearchOptions m_options; +}; diff --git a/src/search/searchoptions.h b/src/search/searchoptions.h index 2a61793..5b06f3e 100644 --- a/src/search/searchoptions.h +++ b/src/search/searchoptions.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include // Enum to represent the search method enum class FindMethod { @@ -13,13 +15,34 @@ enum class FindMethod { struct SearchOptions { QString keyword; // The search keyword QString replaceText; // Text to replace with + QString location; // The path to look for files + QString pattern; // The comma deliminated file patterns by * and ? FindMethod findMethod; // The search method (simple text, regex, special characters) bool matchWholeWord; // Flag to indicate if we match the whole word bool matchCase; // Flag to indicate case sensitivity bool allTabs; // Flag to search through all open tabs + bool includeSubdirectories; // Flag to search through all subdirectories // Default constructor SearchOptions() - : keyword(""), findMethod(FindMethod::SimpleText), matchWholeWord(false), - matchCase(false), allTabs(false) {} + : keyword(""), replaceText(""), location(""), pattern(""), findMethod(FindMethod::SimpleText), + matchWholeWord(false), matchCase(false), allTabs(false), includeSubdirectories(false) {} }; + +struct SearchResult { + QString filePath; // Path of the file containing matches + QVector> matches; // List of pairs indicating start and end positions of each match +}; + +struct SearchProgress { + int processedFiles = 0; // Number of files processed + int totalFiles = 0; // Total files to process +}; + +struct FileSearchResults { + QString filePath; // Path of the file + int matchCount; // Number of matches in the file + QVector matchingLines; // Lines containing matches, with keywords highlighted + QVector> matches; // Pairs of (line number, line text) for each match +}; + diff --git a/src/systemfind/richtextdelegate.cpp b/src/systemfind/richtextdelegate.cpp new file mode 100644 index 0000000..544d02c --- /dev/null +++ b/src/systemfind/richtextdelegate.cpp @@ -0,0 +1,71 @@ +#include "richtextdelegate.h" +#include +#include + +RichTextDelegate::RichTextDelegate(QObject *parent) + : QStyledItemDelegate(parent) {} + +void RichTextDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + painter->save(); + + QString text = index.data().toString(); + + // Replace tags with HTML for yellow background highlight + text.replace("", ""); + text.replace("", ""); + + QTextDocument doc; + doc.setHtml(text); + doc.setDefaultFont(option.font); + + // Calculate indentation based on item level and apply line spacing + int indentLevel = index.model()->data(index, Qt::UserRole + 1).toInt(); // Assumed indent level stored in UserRole + 1 + int indentWidth = 20; // Adjust width per indent level + int spacing = 30; // Space between lines to prevent overlap + + QRect rect = option.rect; + rect.adjust(indentLevel * indentWidth, 0, 0, 0); // Offset based on indentation level + + // Draw the selection background if the item is selected + if (option.state & QStyle::State_Selected) { + painter->fillRect(option.rect, option.palette.highlight()); + } + + // Set document width to fit within item rect + doc.setTextWidth(rect.width()); + + // Draw each line separately with adjusted line spacing + int yOffset = rect.top(); + for (int i = 0; i < doc.lineCount(); ++i) { + QRect lineRect = rect; + lineRect.moveTop(yOffset); + + // Draw the document content + painter->translate(lineRect.topLeft()); + doc.drawContents(painter, QRectF(0, 0, lineRect.width(), spacing)); + painter->translate(-lineRect.topLeft()); // Reset translation for next line + + // Update yOffset for the next line + yOffset += spacing; + } + + painter->restore(); +} + +QSize RichTextDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { + QTextDocument doc; + QString text = index.data().toString(); + + // Set HTML with line spacing + text.replace("", ""); + text.replace("", ""); + doc.setHtml(text); + + int indentLevel = index.model()->data(index, Qt::UserRole + 1).toInt(); + int indentWidth = 20; + int spacing = 30; + + // Account for indent and extra spacing in the height + QSize baseSize(doc.idealWidth(), doc.size().height()); + return QSize(baseSize.width() + indentLevel * indentWidth, baseSize.height() + spacing); +} diff --git a/src/systemfind/richtextdelegate.h b/src/systemfind/richtextdelegate.h new file mode 100644 index 0000000..1984a07 --- /dev/null +++ b/src/systemfind/richtextdelegate.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +class RichTextDelegate : public QStyledItemDelegate { + Q_OBJECT +public: + explicit RichTextDelegate(QObject *parent = nullptr); + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; +}; diff --git a/src/systemfind/systemfind.cpp b/src/systemfind/systemfind.cpp new file mode 100644 index 0000000..4e809c1 --- /dev/null +++ b/src/systemfind/systemfind.cpp @@ -0,0 +1,3 @@ +#include "systemfind.h" + +SystemFind::SystemFind() {} diff --git a/src/systemfind/systemfind.h b/src/systemfind/systemfind.h new file mode 100644 index 0000000..068ab38 --- /dev/null +++ b/src/systemfind/systemfind.h @@ -0,0 +1,8 @@ +#pragma once + +class SystemFind +{ +public: + SystemFind(); +}; + diff --git a/src/systemfind/systemfinddialog.cpp b/src/systemfind/systemfinddialog.cpp index 277026e..b768493 100644 --- a/src/systemfind/systemfinddialog.cpp +++ b/src/systemfind/systemfinddialog.cpp @@ -1,3 +1,294 @@ +#include +#include +#include +#include +#include +#include #include "systemfinddialog.h" +#include "../search/filesearchworker.h" +#include "ui_systemfinddialog.h" +#include "../systemsearchresultdialog.h" +#include "../settings.h" + +SystemFindDialog::SystemFindDialog(QWidget *parent) + : QDialog(parent) + , ui(new Ui::SystemFindDialog), + m_searchOptions(new SearchOptions()), + m_totalFiles(0), m_processedFiles(0), + m_find(nullptr), m_systemSearchResultDialog(nullptr) +{ + ui->setupUi(this); + + connect(this, &SystemFindDialog::updateProgress, this, &SystemFindDialog::updateProgressDisplay); + + const int move = 220; + const int reduceHeight = 210; + + // Adjust the vertical positions of the buttons to move them up + ui->findNext->move(ui->findNext->x(), ui->findNext->y() - move); + ui->findPrevious->move(ui->findPrevious->x(), ui->findPrevious->y() - move); + ui->selectAll->move(ui->selectAll->x(), ui->selectAll->y() - move); + ui->m_statusLabel->move(ui->m_statusLabel->x(), ui->m_statusLabel->y() - move); + ui->m_progressBar->move(ui->m_progressBar->x(), ui->m_progressBar->y() - move); + + // Initially hide the advanced options and decrease the form and tabWidget height + ui->groupBoxAdvanced->hide(); + resize(width(), height() - reduceHeight); + + // Connect advancedOptions checkbox to toggle advanced options visibility + connect(ui->advancedOptions, &QCheckBox::toggled, this, &SystemFindDialog::toggleAdvancedOptions); + + m_searchOptions->findMethod = FindMethod::SimpleText; // default method + + ui->comboBoxFind->installEventFilter(this); + ui->comboBoxLocation->installEventFilter(this); + ui->comboBoxPattern->installEventFilter(this); +} + +SystemFindDialog::~SystemFindDialog() +{ + delete ui; + delete m_find; + delete m_searchOptions; +} + +bool SystemFindDialog::eventFilter(QObject *watched, QEvent *event) { + if (watched == ui->comboBoxFind && event->type() == QEvent::Show) { + populateComboBoxFind(); + } else if (watched == ui->comboBoxLocation && event->type() == QEvent::Show) { + populateComboBoxLocation(); + } else if (watched == ui->comboBoxPattern && event->type() == QEvent::Show) { + populateComboBoxPattern(); + } + return QDialog::eventFilter(watched, event); +} + +void SystemFindDialog::populateComboBoxFind() { + QStringList keywords = Settings::instance()->loadSetting("Find", "Keywords", QStringList()).toStringList(); + + ui->comboBoxFind->clear(); + ui->comboBoxFind->addItems(keywords); + ui->comboBoxFind->setCurrentText(""); // Ensure the display is empty until the user types or selects +} + +void SystemFindDialog::populateComboBoxLocation() { + QStringList keywords = Settings::instance()->loadSetting("Location", "Keywords", QStringList()).toStringList(); + + ui->comboBoxLocation->clear(); + ui->comboBoxLocation->addItems(keywords); + ui->comboBoxLocation->setCurrentText(""); // Ensure the display is empty until the user types or selects +} + +void SystemFindDialog::populateComboBoxPattern() { + QStringList keywords = Settings::instance()->loadSetting("Pattern", "Keywords", QStringList()).toStringList(); + + ui->comboBoxPattern->clear(); + ui->comboBoxPattern->addItems(keywords); + ui->comboBoxPattern->setCurrentText(""); // Ensure the display is empty until the user types or selects +} + +void SystemFindDialog::saveKeyword(const QString& keyword) +{ + if (keyword.isEmpty()) return; + QStringList keywords = Settings::instance()->loadSetting("Find", "Keywords", QStringList()).toStringList(); + + if (!keywords.contains(keyword)) { + keywords.prepend(keyword); // Add keyword to the top of history list + if (keywords.size() > 10) { + keywords = keywords.mid(0, 10); // Limit history to 10 items + } + Settings::instance()->saveSetting("Find", "Keywords", keywords); + + // Update combobox without triggering text change + ui->comboBoxFind->blockSignals(true); + ui->comboBoxFind->clear(); + ui->comboBoxFind->addItems(keywords); + ui->comboBoxFind->blockSignals(false); + } +} + +void SystemFindDialog::saveLocation(const QString& location) +{ + if (location.isEmpty()) return; + QStringList locations = Settings::instance()->loadSetting("Location", "Keywords", QStringList()).toStringList(); + + if (!locations.contains(location)) { + locations.prepend(location); // Add keyword to the top of history list + if (locations.size() > 10) { + locations = locations.mid(0, 10); // Limit history to 10 items + } + Settings::instance()->saveSetting("Location", "Keywords", locations); + + // Update combobox without triggering text change + ui->comboBoxLocation->blockSignals(true); + ui->comboBoxLocation->clear(); + ui->comboBoxLocation->addItems(locations); + ui->comboBoxLocation->blockSignals(false); + } +} + +void SystemFindDialog::savePattern(const QString& pattern) +{ + if (pattern.isEmpty()) return; + QStringList patterns = Settings::instance()->loadSetting("Pattern", "Keywords", QStringList()).toStringList(); + + if (!patterns.contains(pattern)) { + patterns.prepend(pattern); // Add keyword to the top of history list + if (patterns.size() > 10) { + patterns = patterns.mid(0, 10); // Limit history to 10 items + } + Settings::instance()->saveSetting("Pattern", "Keywords", patterns); + + // Update combobox without triggering text change + ui->comboBoxPattern->blockSignals(true); + ui->comboBoxPattern->clear(); + ui->comboBoxPattern->addItems(patterns); + ui->comboBoxPattern->blockSignals(false); + } +} + +void SystemFindDialog::onAdvancedOptionsToggled(bool checked) { + ui->groupBoxAdvanced->setVisible(checked); +} + +void SystemFindDialog::toggleAdvancedOptions(bool checked) { + const int move = 220; + const int increaseHeight = 210; + + if (checked) { + // Move buttons down, resize form and tabWidget, and show advanced options + ui->findNext->move(ui->findNext->x(), ui->findNext->y() + move); + ui->findPrevious->move(ui->findPrevious->x(), ui->findPrevious->y() + move); + ui->selectAll->move(ui->selectAll->x(), ui->selectAll->y() + move); + ui->m_statusLabel->move(ui->m_statusLabel->x(), ui->m_statusLabel->y() + move); + ui->m_progressBar->move(ui->m_progressBar->x(), ui->m_progressBar->y() + move); + + resize(width(), height() + increaseHeight); + + ui->groupBoxAdvanced->show(); + } else { + // Return to compact layout with buttons moved up and form resized + ui->findNext->move(ui->findNext->x(), ui->findNext->y() - move); + ui->findPrevious->move(ui->findPrevious->x(), ui->findPrevious->y() - move); + ui->selectAll->move(ui->selectAll->x(), ui->selectAll->y() - move); + ui->m_statusLabel->move(ui->m_statusLabel->x(), ui->m_statusLabel->y() - move); + ui->m_progressBar->move(ui->m_progressBar->x(), ui->m_progressBar->y() - move); + + resize(width(), height() - increaseHeight); + + ui->groupBoxAdvanced->hide(); + } +} + +void SystemFindDialog::on_pushButtonBrowse_clicked() +{ + QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory")); + if (!dir.isEmpty()) { + ui->comboBoxLocation->addItem(dir); + ui->comboBoxLocation->setCurrentText(dir); + } +} + +void SystemFindDialog::startSearch(const SearchOptions& options) { + if (!m_searchOptions) { + m_searchOptions = new SearchOptions(); + } + *m_searchOptions = options; + m_processedFiles = 0; + m_totalFiles = 0; + + ui->m_progressBar->setValue(0); + countTextFiles(m_searchOptions->location); + ui->m_progressBar->setMaximum(m_totalFiles); + + QDirIterator::IteratorFlags flags = m_searchOptions->includeSubdirectories ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; + QDirIterator it(m_searchOptions->location, QDir::Files, flags); + + while (it.hasNext()) { + QString filePath = it.next(); + processFile(filePath); + } +} + +void SystemFindDialog::countTextFiles(const QString& directory) { + QMimeDatabase mimeDb; + QDirIterator it(directory, QDir::Files, QDirIterator::Subdirectories); + + while (it.hasNext()) { + QString filePath = it.next(); + QMimeType mimeType = mimeDb.mimeTypeForFile(filePath); + if (mimeType.name().startsWith("text/")) { + m_totalFiles++; + } + } +} + +void SystemFindDialog::processFile(const QString& filePath) { + auto* worker = new FileSearchWorker(filePath, *m_searchOptions); + connect(worker, &FileSearchWorker::fileProcessed, this, &SystemFindDialog::handleFileProcessed); + m_threadPool.start(worker); +} + +void SystemFindDialog::handleFileProcessed(const FileSearchResults& result) { + m_processedFiles++; + emit updateProgress(m_processedFiles, m_totalFiles); + + // Ensure the result dialog is open in non-modal mode + if (!m_systemSearchResultDialog) { + m_systemSearchResultDialog = new SystemSearchResultDialog(this); + m_systemSearchResultDialog->setWindowModality(Qt::NonModal); + m_systemSearchResultDialog->show(); + } + + // Add each result to the tree view in the dialog + m_systemSearchResultDialog->addSearchResult(result); +} + +void SystemFindDialog::updateProgressDisplay(int processedFiles, int totalFiles) { + ui->m_progressBar->setValue(processedFiles); + ui->m_statusLabel->setText(QString("Searching Files... %1/%2").arg(processedFiles).arg(totalFiles)); +} + +void SystemFindDialog::UpdateSearchOptions() { + if (!m_searchOptions) return; + m_searchOptions->keyword = ui->comboBoxFind->currentText(); + m_searchOptions->location = ui->comboBoxLocation->currentText(); + m_searchOptions->pattern = ui->comboBoxPattern->currentText(); + if (ui->findPlainText->isChecked()) m_searchOptions->findMethod = FindMethod::SimpleText; + if (ui->findRegularExpression->isChecked()) m_searchOptions->findMethod = FindMethod::RegularExpression; + if (ui->findSpecialCharachters->isChecked()) m_searchOptions->findMethod = FindMethod::SpecialCharacters; + m_searchOptions->matchWholeWord = ui->matchWholeWord->isChecked(); + m_searchOptions->matchCase = ui->matchCase->isChecked(); + m_searchOptions->includeSubdirectories = ui->includeSubdirectories->isChecked(); + + if (m_systemSearchResultDialog) { + m_systemSearchResultDialog->setSearchOptions(*m_searchOptions); + } else { + qWarning() << "Cannot set search options for search result dialog."; + } +} + +void SystemFindDialog::showResultDialog() { + if (!m_systemSearchResultDialog) { + // Create and show the dialog in non-modal mode only if it's not already created + m_systemSearchResultDialog = new SystemSearchResultDialog(this); + m_systemSearchResultDialog->setWindowModality(Qt::NonModal); + m_systemSearchResultDialog->show(); + } else { + // Bring the existing dialog to the front + m_systemSearchResultDialog->raise(); + m_systemSearchResultDialog->activateWindow(); + } + UpdateSearchOptions(); +} + +void SystemFindDialog::on_findNext_clicked() +{ + UpdateSearchOptions(); + showResultDialog(); + startSearch(*m_searchOptions); +} + + + -SystemFindDialog::SystemFindDialog() {} diff --git a/src/systemfind/systemfinddialog.h b/src/systemfind/systemfinddialog.h index 73ce393..b063422 100644 --- a/src/systemfind/systemfinddialog.h +++ b/src/systemfind/systemfinddialog.h @@ -1,11 +1,65 @@ #pragma once #include +#include +#include "systemfind.h" +#include "../search/searchoptions.h" +#include "../systemsearchresultdialog.h" -class SystemFindDialog +namespace Ui { +class SystemFindDialog; +} + +class QProgressBar; +class QLabel; + +class SystemFindDialog : public QDialog { + Q_OBJECT + public: - SystemFindDialog(); + explicit SystemFindDialog(QWidget *parent = nullptr); + ~SystemFindDialog(); + + void startSearch(const SearchOptions& options); + +signals: + void updateProgress(int processedFiles, int totalFiles); + +private slots: + void handleFileProcessed(const FileSearchResults& result); + + void updateProgressDisplay(int processedFiles, int totalFiles); + + void onAdvancedOptionsToggled(bool checked); + + void toggleAdvancedOptions(bool checked); + + void on_findNext_clicked(); + + void on_pushButtonBrowse_clicked(); + +private: + Ui::SystemFindDialog *ui; + + FindMethod selectedFindMethod() const; + SearchOptions* m_searchOptions; + void populateComboBoxFind(); + void populateComboBoxLocation(); + void populateComboBoxPattern(); + void saveKeyword(const QString& keyword); + void saveLocation(const QString& location); + void savePattern(const QString& pattern); + bool eventFilter(QObject *watched, QEvent *event); + void UpdateSearchOptions(); + void showResultDialog(); + void countTextFiles(const QString& directory); + void processFile(const QString& filePath); + int m_totalFiles = 0; + int m_processedFiles = 0; + QThreadPool m_threadPool; + SystemFind* m_find; + SystemSearchResultDialog* m_systemSearchResultDialog; }; diff --git a/src/systemfind/systemfinddialog.ui b/src/systemfind/systemfinddialog.ui index 73b0128..b52b4c0 100644 --- a/src/systemfind/systemfinddialog.ui +++ b/src/systemfind/systemfinddialog.ui @@ -1,23 +1,23 @@ - FindDialog - + SystemFindDialog + 0 0 - 503 - 382 + 506 + 470 - System Find + Find System - 76 - 11 + 77 + 19 411 25 @@ -29,75 +29,88 @@ - + - 20 - 345 - 151 + 76 + 57 + 371 25 - - Find + + true - - + + + + + 16 + 102 + 54 + 17 + + + + Pattern - + - 339 - 347 - 151 + 74 + 98 + 411 25 - - Select all + + true + + + + + + *ext1, *ext2 - + - 19 - 14 - 31 - 17 + 20 + 141 + 171 + 23 - Find + Show advanced options - + - 179 - 346 - 151 + 456 + 58 + 31 25 - Find - - - + ... - + - 19 - 90 - 171 - 23 + 20 + 22 + 31 + 17 - Show advanced options + Find @@ -106,8 +119,8 @@ - 26 - 124 + 27 + 178 461 211 @@ -127,6 +140,9 @@ Find &plain text + + true + @@ -180,25 +196,28 @@ Match case - + 15 180 - 82 + 171 23 - All Tabs + Include Subdirectories + + + false - 10 - 50 + 16 + 60 54 17 @@ -207,30 +226,75 @@ Location - + - 74 - 49 - 371 + 21 + 399 + 151 25 - - true + + Find + + + - + - 455 - 50 - 31 + 340 + 401 + 151 25 - ... + Select all + + + + + + 180 + 400 + 151 + 25 + + + + Find + + + + + + + + + 21 + 440 + 221 + 17 + + + + Ready + + + + + + 250 + 437 + 241 + 23 + + + + 0 diff --git a/src/systemreplace/systemreplace.cpp b/src/systemreplace/systemreplace.cpp new file mode 100644 index 0000000..fb54e28 --- /dev/null +++ b/src/systemreplace/systemreplace.cpp @@ -0,0 +1,3 @@ +#include "systemreplace.h" + +SystemReplace::SystemReplace() {} diff --git a/src/systemreplace/systemreplace.h b/src/systemreplace/systemreplace.h new file mode 100644 index 0000000..1ac8f71 --- /dev/null +++ b/src/systemreplace/systemreplace.h @@ -0,0 +1,8 @@ +#pragma once + +class SystemReplace +{ +public: + SystemReplace(); +}; + diff --git a/src/systemreplace/systemreplacedialog.cpp b/src/systemreplace/systemreplacedialog.cpp index 3db01e1..5f9efcb 100644 --- a/src/systemreplace/systemreplacedialog.cpp +++ b/src/systemreplace/systemreplacedialog.cpp @@ -1,3 +1,212 @@ #include "systemreplacedialog.h" +#include "ui_systemreplacedialog.h" +#include "../settings.h" + +SystemReplaceDialog::SystemReplaceDialog(QWidget *parent) + : QDialog(parent), + ui(new Ui::SystemReplaceDialog), + m_searchOptions(new SearchOptions()), + m_replace(nullptr) +{ + ui->setupUi(this); + + const int move = 220; + const int reduceHeight = 210; + + // Adjust the vertical positions of the buttons to move them up + ui->findNext->move(ui->findNext->x(), ui->findNext->y() - move); + ui->findPrevious->move(ui->findPrevious->x(), ui->findPrevious->y() - move); + ui->replaceNext->move(ui->replaceNext->x(), ui->replaceNext->y() - move); + ui->replacePrevious->move(ui->replacePrevious->x(), ui->replacePrevious->y() - move); + ui->selectAll->move(ui->selectAll->x(), ui->selectAll->y() - move); + ui->replaceAll->move(ui->replaceAll->x(), ui->replaceAll->y() - move); + + // Initially hide the advanced options and decrease the form and tabWidget height + ui->groupBoxAdvanced->hide(); + resize(width(), height() - reduceHeight); + + // Connect advancedOptions checkbox to toggle advanced options visibility + connect(ui->advancedOptions, &QCheckBox::toggled, this, &SystemReplaceDialog::toggleAdvancedOptions); + + m_searchOptions->findMethod = FindMethod::SimpleText; // default method + + ui->comboBoxFind->installEventFilter(this); + ui->comboBoxReplace->installEventFilter(this); + ui->comboBoxLocation->installEventFilter(this); + ui->comboBoxPattern->installEventFilter(this); +} + +SystemReplaceDialog::~SystemReplaceDialog() +{ + delete ui; + delete m_replace; +} + +bool SystemReplaceDialog::eventFilter(QObject *watched, QEvent *event) { + if (watched == ui->comboBoxFind && event->type() == QEvent::Show) { + populateComboBoxFind(); + } else if (watched == ui->comboBoxReplace && event->type() == QEvent::Show) { + populateComboBoxReplace(); + } else if (watched == ui->comboBoxLocation && event->type() == QEvent::Show) { + populateComboBoxLocation(); + } else if (watched == ui->comboBoxPattern && event->type() == QEvent::Show) { + populateComboBoxPattern(); + } + return QDialog::eventFilter(watched, event); +} + +// Populate comboBoxFind with recent keywords from settings +void SystemReplaceDialog::populateComboBoxFind() { + QStringList keywords = Settings::instance()->loadSetting("Find", "Keywords", QStringList()).toStringList(); + ui->comboBoxFind->clear(); + ui->comboBoxFind->addItems(keywords); + ui->comboBoxFind->setCurrentText(""); // Ensure it starts empty for new input +} + +// Populate comboBoxReplace with recent replace terms from settings +void SystemReplaceDialog::populateComboBoxReplace() { + QStringList replaceWiths = Settings::instance()->loadSetting("Replace", "ReplaceWiths", QStringList()).toStringList(); + ui->comboBoxReplace->clear(); + ui->comboBoxReplace->addItems(replaceWiths); + ui->comboBoxReplace->setCurrentText(""); // Ensure it starts empty for new input +} + +void SystemReplaceDialog::populateComboBoxLocation() { + QStringList locations = Settings::instance()->loadSetting("Location", "Keywords", QStringList()).toStringList(); + ui->comboBoxLocation->clear(); + ui->comboBoxLocation->addItems(locations); + ui->comboBoxLocation->setCurrentText(""); // Ensure it starts empty for new input +} + +void SystemReplaceDialog::populateComboBoxPattern() { + QStringList patterns = Settings::instance()->loadSetting("Pattern", "Keywords", QStringList()).toStringList(); + ui->comboBoxPattern->clear(); + ui->comboBoxPattern->addItems(patterns); + ui->comboBoxPattern->setCurrentText(""); // Ensure it starts empty for new input +} + +void SystemReplaceDialog::saveKeyword(const QString& keyword) +{ + if (keyword.isEmpty()) return; + QStringList keywords = Settings::instance()->loadSetting("Find", "Keywords", QStringList()).toStringList(); + + if (!keywords.contains(keyword)) { + keywords.prepend(keyword); // Add keyword to the top of history list + if (keywords.size() > 10) { + keywords = keywords.mid(0, 10); // Limit history to 10 items + } + Settings::instance()->saveSetting("Find", "Keywords", keywords); + + // Update combobox without triggering text change + ui->comboBoxFind->blockSignals(true); + ui->comboBoxFind->clear(); + ui->comboBoxFind->addItems(keywords); + ui->comboBoxFind->blockSignals(false); + } +} + +void SystemReplaceDialog::saveReplaceWith(const QString& replaceWith) { + if (replaceWith.isEmpty()) return; + QStringList replaceWiths = Settings::instance()->loadSetting("Replace", "ReplaceWiths", QStringList()).toStringList(); + + if (!replaceWiths.contains(replaceWith)) { + replaceWiths.prepend(replaceWith); // Add replaceWith to the top of history list + if (replaceWiths.size() > 10) { + replaceWiths = replaceWiths.mid(0, 10); // Limit history to 10 items + } + Settings::instance()->saveSetting("Replace", "ReplaceWiths", replaceWiths); + + // Update combobox without triggering text change + ui->comboBoxReplace->blockSignals(true); + ui->comboBoxReplace->clear(); + ui->comboBoxReplace->addItems(replaceWiths); + ui->comboBoxReplace->blockSignals(false); + } +} + +void SystemReplaceDialog::saveLocation(const QString& location) +{ + if (location.isEmpty()) return; + QStringList locations = Settings::instance()->loadSetting("Location", "Keywords", QStringList()).toStringList(); + + if (!locations.contains(location)) { + locations.prepend(location); // Add keyword to the top of history list + if (locations.size() > 10) { + locations = locations.mid(0, 10); // Limit history to 10 items + } + Settings::instance()->saveSetting("Location", "Keywords", locations); + + // Update combobox without triggering text change + ui->comboBoxLocation->blockSignals(true); + ui->comboBoxLocation->clear(); + ui->comboBoxLocation->addItems(locations); + ui->comboBoxLocation->blockSignals(false); + } +} + +void SystemReplaceDialog::savePattern(const QString& pattern) +{ + if (pattern.isEmpty()) return; + QStringList patterns = Settings::instance()->loadSetting("Pattern", "Keywords", QStringList()).toStringList(); + + if (!patterns.contains(pattern)) { + patterns.prepend(pattern); // Add keyword to the top of history list + if (patterns.size() > 10) { + patterns = patterns.mid(0, 10); // Limit history to 10 items + } + Settings::instance()->saveSetting("Pattern", "Keywords", patterns); + + // Update combobox without triggering text change + ui->comboBoxPattern->blockSignals(true); + ui->comboBoxPattern->clear(); + ui->comboBoxPattern->addItems(patterns); + ui->comboBoxPattern->blockSignals(false); + } +} + +void SystemReplaceDialog::onAdvancedOptionsToggled(bool checked) { + ui->groupBoxAdvanced->setVisible(checked); +} + +void SystemReplaceDialog::toggleAdvancedOptions(bool checked) { + const int move = 220; + const int increaseHeight = 210; + + if (checked) { + // Move buttons down, resize form, and show advanced options + ui->findNext->move(ui->findNext->x(), ui->findNext->y() + move); + ui->findPrevious->move(ui->findPrevious->x(), ui->findPrevious->y() + move); + ui->replaceNext->move(ui->replaceNext->x(), ui->replaceNext->y() + move); + ui->replacePrevious->move(ui->replacePrevious->x(), ui->replacePrevious->y() + move); + ui->selectAll->move(ui->selectAll->x(), ui->selectAll->y() + move); + ui->replaceAll->move(ui->replaceAll->x(), ui->replaceAll->y() + move); + + resize(width(), height() + increaseHeight); + + ui->groupBoxAdvanced->show(); + } else { + // Return to compact layout with buttons moved up and form resized + ui->findNext->move(ui->findNext->x(), ui->findNext->y() - move); + ui->findPrevious->move(ui->findPrevious->x(), ui->findPrevious->y() - move); + ui->replaceNext->move(ui->replaceNext->x(), ui->replaceNext->y() - move); + ui->replacePrevious->move(ui->replacePrevious->x(), ui->replacePrevious->y() - move); + ui->selectAll->move(ui->selectAll->x(), ui->selectAll->y() - move); + ui->replaceAll->move(ui->replaceAll->x(), ui->replaceAll->y() - move); + + resize(width(), height() - increaseHeight); + + ui->groupBoxAdvanced->hide(); + } +} + + + + + + + + + + + -SystemReplaceDialog::SystemReplaceDialog() {} diff --git a/src/systemreplace/systemreplacedialog.h b/src/systemreplace/systemreplacedialog.h index 3473845..6476389 100644 --- a/src/systemreplace/systemreplacedialog.h +++ b/src/systemreplace/systemreplacedialog.h @@ -1,8 +1,39 @@ #pragma once +#include +#include "systemreplace.h" +#include "../search/searchoptions.h" -class SystemReplaceDialog +namespace Ui { +class SystemReplaceDialog; +} + +class SystemReplaceDialog : public QDialog { + Q_OBJECT + public: - SystemReplaceDialog(); + explicit SystemReplaceDialog(QWidget *parent = nullptr); + ~SystemReplaceDialog(); + +private slots: + void onAdvancedOptionsToggled(bool checked); + + void toggleAdvancedOptions(bool checked); + +private: + Ui::SystemReplaceDialog *ui; + + FindMethod selectedFindMode() const; + SearchOptions* m_searchOptions; + SystemReplace* m_replace; + bool eventFilter(QObject *watched, QEvent *event); + void saveKeyword(const QString& keyword); + void saveReplaceWith(const QString& replaceWith); + void saveLocation(const QString& location); + void savePattern(const QString& pattern); + void populateComboBoxFind(); + void populateComboBoxReplace(); + void populateComboBoxLocation(); + void populateComboBoxPattern(); }; diff --git a/src/systemreplace/systemreplacedialog.ui b/src/systemreplace/systemreplacedialog.ui index 96b3b8a..38a6079 100644 --- a/src/systemreplace/systemreplacedialog.ui +++ b/src/systemreplace/systemreplacedialog.ui @@ -1,103 +1,103 @@ - ReplaceDialog - + SystemReplaceDialog + 0 0 - 503 - 453 + 493 + 490 - System Replace + Replace System - + - 100 - 10 - 391 + 93 + 82 + 351 25 true - - - - + - 18 - 413 + 330 + 452 151 25 - Replace - - - + Replace all - + - 337 - 415 + 170 + 451 151 25 - Replace all + Replace + + + - + - 16 - 48 - 81 - 17 + 93 + 12 + 391 + 25 - - Replace with + + true + + + - + - 177 - 414 + 170 + 417 151 25 - Replace + Find - + - 27 - 123 - 171 - 23 + 36 + 124 + 54 + 17 - Show advanced options + Pattern @@ -106,8 +106,8 @@ - 23 - 155 + 16 + 192 461 211 @@ -120,20 +120,23 @@ 18 32 - 121 + 141 23 Replace &plain text + + true + 17 60 - 221 + 251 23 @@ -172,7 +175,7 @@ 16 150 - 91 + 111 23 @@ -180,54 +183,41 @@ Match case - + 14 179 - 82 + 181 23 - All Tabs + Include Subdirectories + + + false - + - 63 - 14 - 31 + 9 + 50 + 81 17 - Find - - - - - - 100 - 45 - 391 - 25 - - - - true - - - + Replace with - 19 - 380 + 12 + 417 151 25 @@ -239,27 +229,24 @@ - + - 177 - 380 - 151 - 25 + 30 + 86 + 61 + 17 - Find - - - + Location - 338 - 381 + 331 + 418 151 25 @@ -268,37 +255,75 @@ Select all - + - 37 - 84 - 61 - 17 + 11 + 450 + 151 + 25 - Location + Replace + + + - + - 100 - 80 - 351 + 92 + 121 + 391 + 25 + + + + true + + + + + + *ext1, *ext2 + + + + + + 93 + 47 + 391 25 true + + + + + + + + 56 + 16 + 31 + 17 + + + + Find + - 459 - 80 + 452 + 82 31 25 @@ -307,6 +332,19 @@ ... + + + + 20 + 159 + 171 + 23 + + + + Show advanced options + + diff --git a/src/systemsearchresultdialog.cpp b/src/systemsearchresultdialog.cpp new file mode 100644 index 0000000..e65c156 --- /dev/null +++ b/src/systemsearchresultdialog.cpp @@ -0,0 +1,117 @@ +#include "systemsearchresultdialog.h" +#include "ui_systemsearchresultdialog.h" +#include "helpers.h" +#include "systemtextdelegate.h" +#include +#include +#include + +SystemSearchResultDialog::SystemSearchResultDialog(QWidget *parent) + : QDialog(parent) + , ui(new Ui::SystemSearchResultDialog) + , m_resultModel(new QStandardItemModel(this)) +{ + ui->setupUi(this); + // FIXME: treeview is not selectable and should be. + + m_treeModel = new QStandardItemModel(this); + ui->resultTreeView->setModel(m_treeModel); + + // Set up the model for the tree view + m_resultModel->setHorizontalHeaderLabels({"File Path", "Matches"}); + ui->resultTreeView->setModel(m_resultModel); + + // Enable interactive resizing and allow moving columns + ui->resultTreeView->header()->setSectionResizeMode(QHeaderView::Interactive); // Enable user resizing + ui->resultTreeView->header()->setStretchLastSection(false); // Allow resizing of all columns + + // Adjust column widths and make them proportional + QHeaderView *header = ui->resultTreeView->header(); + header->setSectionResizeMode(0, QHeaderView::Stretch); // File Path column stretches + header->setSectionResizeMode(1, QHeaderView::Interactive); // Matches column fixed but adjustable + header->setStretchLastSection(false); + header->setSectionsMovable(true); + header->resizeSection(0, width() * 0.8); // Set initial size for 80% width for File Path + header->resizeSection(1, width() * 0.2); // Set initial size for 20% width for Matches + + + // Prevent editing and set double-click expansion + ui->resultTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->resultTreeView->setItemsExpandable(true); + ui->resultTreeView->setExpandsOnDoubleClick(true); + ui->resultTreeView->setTextElideMode(Qt::ElideNone); + + // Apply the custom text delegate + ui->resultTreeView->setItemDelegate(new SystemTextDelegate(this)); + ui->resultTreeView->setUniformRowHeights(false); // Allow rows to have variable heights + ui->resultTreeView->resizeColumnToContents(0); // Ensure columns fit the content + ui->resultTreeView->doItemsLayout(); + + connect(ui->resultTreeView, &QTreeView::doubleClicked, this, &SystemSearchResultDialog::handleDoubleClick); +} + +SystemSearchResultDialog::~SystemSearchResultDialog() +{ + delete ui; +} + +void SystemSearchResultDialog::addSearchResult(const FileSearchResults &result) { + QStandardItem *filePathItem = new QStandardItem(result.filePath); + int calculatedTotalMatchCount = 0; + int lineNumber = 1; + + for (const QString &line : result.matchingLines) { + int keywordCount = Helpers::countKeywordsInLine(line, m_searchOptions); + if (keywordCount > 0) { + calculatedTotalMatchCount += keywordCount; + QString highlightedLine = Helpers::highlightKeywords(line, m_searchOptions); + QStandardItem *lineItem = new QStandardItem(); + lineItem->setData(highlightedLine, Qt::DisplayRole); + lineItem->setData(lineNumber, Qt::UserRole); + + QStandardItem *matchesItem = new QStandardItem(QString::number(keywordCount)); + filePathItem->appendRow({lineItem, matchesItem}); + } + lineNumber++; + } + + QStandardItem *matchCountItem = new QStandardItem(QString::number(calculatedTotalMatchCount)); + m_resultModel->appendRow({filePathItem, matchCountItem}); + + qDebug() << "File:" << result.filePath + << "Reported matches:" << result.matchCount + << "Calculated matches (subtree sum):" << calculatedTotalMatchCount; +} + +void SystemSearchResultDialog::handleDoubleClick(const QModelIndex &index) { + if (!index.isValid()) return; + + // Debug: Log the clicked index + qDebug() << "Double-click detected at index:" << index; + + // Check if it's a sub-item + QModelIndex parentIndex = index.parent(); + if (!parentIndex.isValid()) { + qDebug() << "Double-clicked on a top-level item."; + return; + } + + // Retrieve the file path from the parent item + QString filePath = m_resultModel->itemFromIndex(parentIndex)->text(); + + // Retrieve the line number from the clicked sub-item + int lineNumber = index.data(Qt::UserRole).toInt(); + qDebug() << "Retrieved Line Number:" << lineNumber; + + if (lineNumber > 0) { + //QMessageBox::information(this, "Double Click", QString("File: %1\nLine: %2").arg(filePath).arg(lineNumber)); + qDebug() << "Emitting openFileAtMatch signal with File Path:" << filePath << "Line Number:" << lineNumber; + emit openFileAtMatch(filePath, lineNumber); + } else { + qWarning() << "Line number conversion failed for index:" << index; + } +} + +void SystemSearchResultDialog::setSearchOptions(SearchOptions searchOptions) { + m_searchOptions = searchOptions; +} diff --git a/src/systemsearchresultdialog.h b/src/systemsearchresultdialog.h new file mode 100644 index 0000000..fdecdac --- /dev/null +++ b/src/systemsearchresultdialog.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include +#include "search/searchoptions.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class SystemSearchResultDialog; } +QT_END_NAMESPACE + +class SystemSearchResultDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SystemSearchResultDialog(QWidget *parent = nullptr); + ~SystemSearchResultDialog(); + + void addSearchResult(const FileSearchResults &result); + void setSearchOptions(SearchOptions searchOptions); + +signals: + void openFileAtMatch(const QString &filePath, int lineNumber); + +private slots: + void handleDoubleClick(const QModelIndex &index); + +private: + int extractLineNumber(const QString &line) const; + + Ui::SystemSearchResultDialog *ui; + QStandardItemModel* m_resultModel; + SearchOptions m_searchOptions; + QStandardItemModel* m_treeModel; +}; diff --git a/src/systemsearchresultdialog.ui b/src/systemsearchresultdialog.ui new file mode 100644 index 0000000..887f97f --- /dev/null +++ b/src/systemsearchresultdialog.ui @@ -0,0 +1,24 @@ + + + SystemSearchResultDialog + + + + 0 + 0 + 811 + 445 + + + + Result + + + + + + + + + + diff --git a/src/systemtextdelegate.cpp b/src/systemtextdelegate.cpp new file mode 100644 index 0000000..47f849a --- /dev/null +++ b/src/systemtextdelegate.cpp @@ -0,0 +1,69 @@ +#include "systemtextdelegate.h" +#include +#include +#include + +SystemTextDelegate::SystemTextDelegate(QObject *parent) + : QStyledItemDelegate(parent) {} + +void SystemTextDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + if (!index.isValid()) return; + + // Retrieve content from the model + QString content = index.data(Qt::DisplayRole).toString(); + QString keyword = index.data(Qt::UserRole).toString(); + + // Highlight keywords dynamically if plain text + if (!content.contains("%1").arg(keyword), + Qt::CaseInsensitive); + } + + painter->save(); + + // Clip the painter to the item's rectangle to prevent overlapping + QRect rect = option.rect; + painter->setClipRect(rect); + + if (content.contains("translate(rect.topLeft()); + doc.drawContents(painter); + } else { + // Elide plain text if it exceeds the available space + QFontMetrics metrics(option.font); + QString elidedText = metrics.elidedText(content, Qt::ElideRight, rect.width()); + + // Draw the elided text + painter->drawText(rect, Qt::AlignVCenter | Qt::AlignLeft, elidedText); + } + + painter->restore(); +} + +QSize SystemTextDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { + if (!index.isValid()) return QStyledItemDelegate::sizeHint(option, index); + + // Retrieve content from the model + QString content = index.data(Qt::DisplayRole).toString(); + + if (content.contains(" +#include + +class SystemTextDelegate : public QStyledItemDelegate { + Q_OBJECT + +public: + explicit SystemTextDelegate(QObject *parent = nullptr); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; +}; From 5c1ceb4524bdfb8b51655154d01931d311d55f81 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Mon, 18 Nov 2024 10:55:12 +0330 Subject: [PATCH 37/81] github action #64 --- .github/workflows/cmake-multi-platform.yml | 24 +++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 1fe8fa9..10a2c2f 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -62,23 +62,29 @@ jobs: path: ${{ runner.temp }}/qt-source key: qt-source-6.5.3 - - name: Download Qt Source (Windows) + - name: Download and Extract Qt Source (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | $qtSourceDir = "$env:TEMP\qt-source" $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path $qtZip)) { + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { Write-Host "Downloading Qt Source" New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + Write-Host "Error: configure.bat is missing in $qtSourceDir after extraction." + dir "$qtSourceDir" + throw "configure.bat not found. Verify extraction process." + } - name: Build and Install Qt (Windows) if: matrix.os == 'windows-latest' shell: cmd run: | + REM Locate Visual Studio Build Tools FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i IF NOT DEFINED VS_PATH ( @@ -87,11 +93,15 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - # Configure and build Qt with Ninja - cd %TEMP%\qt-source\qt-everywhere-src-6.5.3\qtbase - configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build . --parallel - cmake --install . + REM Configure and build Qt + SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 + IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( + echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 + ) + cd "%QT_SOURCE%\qtbase" + call "%QT_SOURCE%\qtbase\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cmake --build "%QT_SOURCE%\qtbase" --parallel + cmake --install "%QT_SOURCE%\qtbase" - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From 9641f3b5ead9f91def6152e2b78c75c208081f1c Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Mon, 18 Nov 2024 15:13:39 +0330 Subject: [PATCH 38/81] github action #65 --- .github/workflows/cmake-multi-platform.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 10a2c2f..d5affed 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -62,7 +62,7 @@ jobs: path: ${{ runner.temp }}/qt-source key: qt-source-6.5.3 - - name: Download and Extract Qt Source (Windows) + - name: Download Qt Source (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | @@ -99,9 +99,9 @@ jobs: echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) cd "%QT_SOURCE%\qtbase" - call "%QT_SOURCE%\qtbase\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build "%QT_SOURCE%\qtbase" --parallel - cmake --install "%QT_SOURCE%\qtbase" + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cmake --build . --parallel + cmake --install . - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From fc867991a28e80e28b19c78d3df67ea58fdb6e42 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Mon, 18 Nov 2024 20:23:16 +0330 Subject: [PATCH 39/81] github action #66 --- .github/workflows/cmake-multi-platform.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index d5affed..e3b98be 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -74,11 +74,7 @@ jobs: Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - Write-Host "Error: configure.bat is missing in $qtSourceDir after extraction." - dir "$qtSourceDir" - throw "configure.bat not found. Verify extraction process." - } + dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" - name: Build and Install Qt (Windows) if: matrix.os == 'windows-latest' @@ -98,6 +94,7 @@ jobs: IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) + dir "%QT_SOURCE%\qtbase" cd "%QT_SOURCE%\qtbase" call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel From 0d0f908f33cab944f9ab2c146963da3bed4a1e7a Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Mon, 18 Nov 2024 22:24:14 +0330 Subject: [PATCH 40/81] v0.0.49 --- CHANGELOG.md | 5 ++ CMakeLists.txt.user | 14 ++--- src/codeeditor.cpp | 47 +++++---------- src/codeeditor.h | 3 +- src/helpers.cpp | 50 ---------------- src/helpers.h | 2 - src/mainwindow.cpp | 88 +++++++++++++++++++---------- src/mainwindow.h | 1 + src/mainwindow/fileoperations.cpp | 9 +-- src/mainwindow/fileoperations.h | 2 +- src/systemfind/systemfinddialog.cpp | 5 ++ src/systemfind/systemfinddialog.h | 11 ++++ src/systemsearchresultdialog.cpp | 83 +++++++++++++++++++++------ src/systemsearchresultdialog.h | 11 ++++ src/systemtextdelegate.cpp | 12 ++++ 15 files changed, 197 insertions(+), 146 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ba5f06..371aeeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 0.0.49 + +- Implemented: +- Search Menu -> Find System (partially 2) + ## 0.0.48 - Implemented: diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index a84fe63..a289ff5 100755 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -102,14 +102,14 @@ 2 false - -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} + -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} -DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} -DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} /data/Code/Qt/Notepad-- 0 /data/Code/Qt/Notepad--/build/Desktop-Debug @@ -160,14 +160,14 @@ 2 false - -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} + -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} -DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} -DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} /data/Code/Qt/Notepad-- /data/Code/Qt/Notepad--/build/Desktop-Release diff --git a/src/codeeditor.cpp b/src/codeeditor.cpp index e9adf5e..3c067ff 100755 --- a/src/codeeditor.cpp +++ b/src/codeeditor.cpp @@ -184,9 +184,9 @@ void CodeEditor::highlightAllOccurrences(const QString& keyword) { setExtraSelections(extraSelections); } -void CodeEditor::goToLine(int lineNumber) { +void CodeEditor::goToLineInText(int lineNumber) { if (lineNumber < 1 || lineNumber > document()->blockCount()) { - qWarning() << "Line number" << lineNumber << "is out of range."; + qWarning() << "Line number: " << lineNumber << ". Line number is out of range."; return; } @@ -200,37 +200,16 @@ void CodeEditor::goToLine(int lineNumber) { qDebug() << "Cursor position after move:" << textCursor().position(); } -/* -void CodeEditor::goToLine(int lineNumber) { - // Validate line number range - if (lineNumber < 1 || lineNumber > document()->blockCount()) { - qWarning() << "Line number" << lineNumber << "is out of range. Valid range: 1 to" << document()->blockCount(); - return; - } - - // Find the text block corresponding to the line number - QTextBlock block = document()->findBlockByNumber(lineNumber - 1); - if (!block.isValid()) { - qWarning() << "Invalid block for line number:" << lineNumber; - return; - } - - // Set the text cursor to the block - QTextCursor cursor(block); - setTextCursor(cursor); - - // Scroll to the block manually - QRectF blockRect = blockBoundingGeometry(block).translated(contentOffset()); - verticalScrollBar()->setValue(static_cast(blockRect.top())); - - // Ensure the editor has focus (optional) - if (!hasFocus()) { - setFocus(); +void CodeEditor::gotoLineInEditor(int lineNumber) { + // Ensure the line number is within the valid range + if (lineNumber > 0 && lineNumber <= blockCount()) { + QTextCursor cursor = textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, lineNumber - 1); + setTextCursor(cursor); + centerCursor(); + } else { + qWarning() << "Invalid Line Number: " << lineNumber << " .The specified line is out of range."; } - - qDebug() << "Moved to line:" << lineNumber; - qDebug() << "Block position:" << block.position() - << "Block geometry:" << blockRect - << "Viewport height:" << viewport()->height(); } -*/ + diff --git a/src/codeeditor.h b/src/codeeditor.h index a5b9ef5..00bc0d2 100755 --- a/src/codeeditor.h +++ b/src/codeeditor.h @@ -22,7 +22,8 @@ class CodeEditor : public QPlainTextEdit { void applyIndentation(bool useTabs, int indentationWidth); QTabWidget* DocumentsTab(); void highlightAllOccurrences(const QString& keyword); - void goToLine(int lineNumber); + void goToLineInText(int lineNumber); + void gotoLineInEditor(int lineNumber); protected: void resizeEvent(QResizeEvent *event) override; diff --git a/src/helpers.cpp b/src/helpers.cpp index 58255a0..7de51ea 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -122,56 +122,6 @@ void Helpers::notImplemented(QWidget* parent) { QMessageBox::information(parent, "Information", hardcodedMessage, QMessageBox::Ok); } -void Helpers::gotoLineInText(QWidget* parent, CodeEditor* editor) { - if (!editor) { - QMessageBox::warning(parent, "Error", "No active editor found."); - return; - } - - // Prompt user for line number input - int lineNumber = QInputDialog::getInt(parent, "Go to Line in Text", "Enter line number:"); - - QTextDocument* document = editor->document(); - int currentLine = 1; - QTextBlock block = document->begin(); - - // Iterate through text blocks to find the requested line - while (block.isValid() && currentLine < lineNumber) { - currentLine++; - block = block.next(); - } - - if (currentLine == lineNumber) { - QTextCursor cursor = editor->textCursor(); - cursor.setPosition(block.position()); - editor->setTextCursor(cursor); - editor->centerCursor(); - } else { - QMessageBox::information(parent, "Line Not Found", "The specified line exceeds the document length."); - } -} - -void Helpers::gotoLineInEditor(QWidget* parent, CodeEditor* editor) { - if (!editor) { - QMessageBox::warning(parent, "Error", "No active editor found."); - return; - } - - // Prompt user for line number input - int lineNumber = QInputDialog::getInt(parent, "Go to Line in Editor", "Enter line number:"); - - // Ensure the line number is within the valid range - if (lineNumber > 0 && lineNumber <= editor->blockCount()) { - QTextCursor cursor = editor->textCursor(); - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, lineNumber - 1); - editor->setTextCursor(cursor); - editor->centerCursor(); - } else { - QMessageBox::information(parent, "Invalid Line Number", "The specified line is out of range."); - } -} - bool Helpers::isValidRegularExpression(const QString& pattern) { QRegularExpression regex(pattern); return regex.isValid(); diff --git a/src/helpers.h b/src/helpers.h index d4f75b0..07541b0 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -23,8 +23,6 @@ class Helpers { static Document* getCurrentDocument(QTabWidget* documentsTab); static void showInformationMessage(const QString& message); static void notImplemented(QWidget* parent = nullptr); - static void gotoLineInText(QWidget* parent, CodeEditor* editor); - static void gotoLineInEditor(QWidget* parent, CodeEditor* editor); static bool isValidRegularExpression(const QString& pattern); static int countKeywordsInLine(const QString &line, const SearchOptions &searchOptions); static QString highlightKeywords(const QString& line, const SearchOptions& options); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a8c8117..52ec2e8 100755 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2,7 +2,9 @@ #include #include #include +#include #include +#include #include #include "mainwindow.h" #include "codeeditor.h" @@ -364,35 +366,48 @@ void MainWindow::on_actionReplace_P_revious_triggered() } void MainWindow::on_actionFind_System_triggered() { + qDebug() << "on_actionFind_System_triggered called"; + if (!m_systemFindDialog) { - // Create SystemFindDialog only if it doesn't already exist + qDebug() << "Creating new SystemFindDialog"; + m_systemFindDialog = new SystemFindDialog(this); m_systemFindDialog->setWindowModality(Qt::NonModal); + m_systemFindDialog->setAttribute(Qt::WA_DeleteOnClose); + + // Reset pointer when dialog is destroyed + connect(m_systemFindDialog, &QObject::destroyed, this, [this]() { + qDebug() << "SystemFindDialog destroyed. Resetting pointer."; + m_systemFindDialog = nullptr; + }); + + // Ensure connections are established + setupSearchResultDialogConnections(); + m_systemFindDialog->show(); } else { - // Bring existing SystemFindDialog to the front + qDebug() << "SystemFindDialog already exists. Bringing it to the front."; m_systemFindDialog->raise(); m_systemFindDialog->activateWindow(); } +} - // Check for SystemSearchResultDialog existence dynamically +void MainWindow::setupSearchResultDialogConnections() { QTimer::singleShot(0, this, [this]() { SystemSearchResultDialog* m_systemSearchResultDialog = m_systemFindDialog->findChild("SystemSearchResultDialog"); + if (m_systemSearchResultDialog) { qDebug() << "SystemSearchResultDialog found:" << m_systemSearchResultDialog; - // Ensure the connection is made only once - static bool isConnected = false; - if (!isConnected) { - connect(m_systemSearchResultDialog, &SystemSearchResultDialog::openFileAtMatch, - this, &MainWindow::openSearchResult); - qDebug() << "Signal-Slot Connection Successful"; - isConnected = true; - } + // Re-establish the signal-slot connection + connect(m_systemSearchResultDialog, &SystemSearchResultDialog::openFileAtMatch, + this, &MainWindow::openSearchResult, Qt::UniqueConnection); + + qDebug() << "Signal-Slot Connection for SystemSearchResultDialog re-established."; } else { - qDebug() << "SystemSearchResultDialog not found yet. Will retry..."; - QTimer::singleShot(100, this, &MainWindow::on_actionFind_System_triggered); + qDebug() << "SystemSearchResultDialog not found. Retrying..."; + QTimer::singleShot(100, this, &MainWindow::setupSearchResultDialogConnections); } }); } @@ -406,12 +421,22 @@ void MainWindow::on_actionReplace_S_ystem_triggered() void MainWindow::on_actionGo_to_Line_in_Text_triggered() { - Helpers::gotoLineInText(this, getCurrentDocument()->editor()); + int lineNumber = QInputDialog::getInt(this, "Go to Line in Text", "Enter line number:"); + if (lineNumber < 1) { + QMessageBox::warning(this, "Warning", "Enter a valid number.", QMessageBox::Ok); + } else { + getCurrentDocument()->editor()->goToLineInText(lineNumber); + } } void MainWindow::on_actionGo_to_Line_in_Editor_triggered() { - Helpers::gotoLineInEditor(this, getCurrentDocument()->editor()); + int lineNumber = QInputDialog::getInt(this, "Go to Line in Editor", "Enter line number:"); + if (lineNumber < 1) { + QMessageBox::warning(this, "Warning", "Enter a valid number.", QMessageBox::Ok); + } else { + getCurrentDocument()->editor()->gotoLineInEditor(lineNumber); + } } void MainWindow::on_action_Find_triggered() { @@ -445,26 +470,32 @@ void MainWindow::on_action_Find_triggered() { -void MainWindow::openSearchResult(const QString &filePath, int lineNumber) { - qDebug() << "openSearchResult called. File Path:" << filePath << ", Line Number:" << lineNumber; - fileOperations->openDocument(filePath); - Document* doc = getCurrentDocument(); - if (doc && doc->editor()) { // FIXME: Document resets to first line. - doc->editor()->goToLine(lineNumber); - doc->editor()->highlightCurrentLine(); - } else { - qWarning() << "Document or editor is null."; - } -} - - +/* Helper Functions */ +// FIXME: Wrong line selected +void MainWindow::openSearchResult(const QString &filePath, int lineNumber) { + qInfo() << "openSearchResult called. File Path:" << filePath << ", Line Number:" << lineNumber; + Document* doc = fileOperations->openDocument(filePath); + if (!doc || !doc->editor()) { + qFatal() << "Document or editor is null."; + return; + } + // Use a weak pointer to ensure the document is still valid when the timer fires + QPointer safeDoc(doc); + QTimer::singleShot(200, this, [lineNumber, safeDoc]() { + if (safeDoc && safeDoc->editor()) { + safeDoc->editor()->goToLineInText(lineNumber); + } else { + qWarning() << "Document or editor is no longer available."; + } + }); +} @@ -476,7 +507,6 @@ void MainWindow::onActionZ80Triggered() - // helper function void MainWindow::connectSignals(Document *doc) { diff --git a/src/mainwindow.h b/src/mainwindow.h index 6e9664f..e210862 100755 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -156,6 +156,7 @@ private slots: void applyColorCoding(Document* doc, bool isModified); void setActiveDocumentEditorInFindDialog(); void setActiveDocumentEditorInReplaceDialog(); + void setupSearchResultDialogConnections(); void setupIndentationMenu(); QAction* action_Custom; diff --git a/src/mainwindow/fileoperations.cpp b/src/mainwindow/fileoperations.cpp index f72e5fb..aece057 100644 --- a/src/mainwindow/fileoperations.cpp +++ b/src/mainwindow/fileoperations.cpp @@ -54,27 +54,27 @@ void FileOperations::openDocumentTriggered() { } } -void FileOperations::openDocument(const QString& filePath) { +Document* FileOperations::openDocument(const QString& filePath) { qDebug() << "Opening document: " << filePath; // Ensure m_mainWindow is valid if (!m_mainWindow) { qDebug() << "Error: MainWindow instance is null!"; - return; + return nullptr; } // Ensure UI and documentsTab are valid auto ui = m_mainWindow->getUi(); if (!ui || !ui->documentsTab) { qDebug() << "Error: UI or documentsTab is not initialized!"; - return; + return nullptr; } QFile file(filePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Error: Unable to open file: " << filePath; QMessageBox::warning(m_mainWindow, tr("Error"), tr("Failed to open the file.")); - return; + return nullptr; } if (ui->documentsTab->count() > 0) { @@ -108,6 +108,7 @@ void FileOperations::openDocument(const QString& filePath) { // Set the new document as the current tab ui->documentsTab->setCurrentWidget(newDoc); + return newDoc; } void FileOperations::newDocument() { diff --git a/src/mainwindow/fileoperations.h b/src/mainwindow/fileoperations.h index 3ef1a0b..3296743 100644 --- a/src/mainwindow/fileoperations.h +++ b/src/mainwindow/fileoperations.h @@ -17,7 +17,7 @@ class FileOperations : public QObject { static bool closeDocument(Document* doc); // This method moves the logic for opening a document from MainWindow - void openDocument(const QString& filePath); + Document* openDocument(const QString& filePath); void openDocumentTriggered(); void newDocument(); void openFolder(MainWindow* mainWindow); diff --git a/src/systemfind/systemfinddialog.cpp b/src/systemfind/systemfinddialog.cpp index b768493..e61b7dc 100644 --- a/src/systemfind/systemfinddialog.cpp +++ b/src/systemfind/systemfinddialog.cpp @@ -50,6 +50,11 @@ SystemFindDialog::~SystemFindDialog() delete ui; delete m_find; delete m_searchOptions; + delete m_systemSearchResultDialog; +} + +void SystemFindDialog::cleanupResources() { + qInfo() << "Cleaning up resources. Closing window..."; } bool SystemFindDialog::eventFilter(QObject *watched, QEvent *event) { diff --git a/src/systemfind/systemfinddialog.h b/src/systemfind/systemfinddialog.h index b063422..9f1830f 100644 --- a/src/systemfind/systemfinddialog.h +++ b/src/systemfind/systemfinddialog.h @@ -1,7 +1,9 @@ #pragma once +#include #include #include +#include #include "systemfind.h" #include "../search/searchoptions.h" #include "../systemsearchresultdialog.h" @@ -23,6 +25,14 @@ class SystemFindDialog : public QDialog void startSearch(const SearchOptions& options); +protected: + void closeEvent(QCloseEvent *event) override { + qWarning() << "Window is closing. Cleaning up resources..."; + cleanupResources(); + // Optionally accept or ignore the event + event->accept(); // or event->ignore(); + } + signals: void updateProgress(int processedFiles, int totalFiles); @@ -42,6 +52,7 @@ private slots: private: Ui::SystemFindDialog *ui; + void cleanupResources(); FindMethod selectedFindMethod() const; SearchOptions* m_searchOptions; void populateComboBoxFind(); diff --git a/src/systemsearchresultdialog.cpp b/src/systemsearchresultdialog.cpp index e65c156..a718db0 100644 --- a/src/systemsearchresultdialog.cpp +++ b/src/systemsearchresultdialog.cpp @@ -34,6 +34,8 @@ SystemSearchResultDialog::SystemSearchResultDialog(QWidget *parent) header->resizeSection(0, width() * 0.8); // Set initial size for 80% width for File Path header->resizeSection(1, width() * 0.2); // Set initial size for 20% width for Matches + ui->resultTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->resultTreeView->setSelectionMode(QAbstractItemView::SingleSelection); // Prevent editing and set double-click expansion ui->resultTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -55,60 +57,105 @@ SystemSearchResultDialog::~SystemSearchResultDialog() delete ui; } +void SystemSearchResultDialog::cleanupResources() { + qInfo() << "Cleaning up resources. Closing window..."; +} + void SystemSearchResultDialog::addSearchResult(const FileSearchResults &result) { QStandardItem *filePathItem = new QStandardItem(result.filePath); + filePathItem->setFlags(filePathItem->flags() | Qt::ItemIsSelectable); + int calculatedTotalMatchCount = 0; - int lineNumber = 1; + int firstKeywordLineNumber = -1; // Initialize to "not found" + int currentLineNumber = 1; // Start counting lines from 1 for (const QString &line : result.matchingLines) { + // Count occurrences of the keyword in the line int keywordCount = Helpers::countKeywordsInLine(line, m_searchOptions); + if (keywordCount > 0) { calculatedTotalMatchCount += keywordCount; + + // Highlight keywords in the line QString highlightedLine = Helpers::highlightKeywords(line, m_searchOptions); + + // Track the first line containing a keyword + if (firstKeywordLineNumber == -1) { + firstKeywordLineNumber = currentLineNumber; + } + + // Create tree view items for the line and keyword count QStandardItem *lineItem = new QStandardItem(); + lineItem->setFlags(lineItem->flags() | Qt::ItemIsSelectable); lineItem->setData(highlightedLine, Qt::DisplayRole); - lineItem->setData(lineNumber, Qt::UserRole); + lineItem->setData(currentLineNumber, Qt::UserRole); QStandardItem *matchesItem = new QStandardItem(QString::number(keywordCount)); + matchesItem->setFlags(matchesItem->flags() | Qt::ItemIsSelectable); + + // Append the line and matches to the file path item filePathItem->appendRow({lineItem, matchesItem}); } - lineNumber++; + + currentLineNumber++; // Increment the line counter } + // Add total matches as a separate item QStandardItem *matchCountItem = new QStandardItem(QString::number(calculatedTotalMatchCount)); + matchCountItem->setFlags(matchCountItem->flags() | Qt::ItemIsSelectable); m_resultModel->appendRow({filePathItem, matchCountItem}); - qDebug() << "File:" << result.filePath - << "Reported matches:" << result.matchCount - << "Calculated matches (subtree sum):" << calculatedTotalMatchCount; + // Emit signal for the first keyword line if found + if (firstKeywordLineNumber != -1) { + qDebug() << "First keyword line number calculated:" << firstKeywordLineNumber + << "for file:" << result.filePath; + emit openFileAtMatch(result.filePath, firstKeywordLineNumber); + } else { + qDebug() << "No keywords found in file:" << result.filePath; + } } +// FIXME: Line number is wrong void SystemSearchResultDialog::handleDoubleClick(const QModelIndex &index) { - if (!index.isValid()) return; + if (!index.isValid()) { + qWarning() << "Invalid index detected in handleDoubleClick."; + return; + } - // Debug: Log the clicked index - qDebug() << "Double-click detected at index:" << index; + // Debug: Log the clicked index details + qDebug() << "Double-click detected at index:" << index << "Data:" << index.data(Qt::DisplayRole); - // Check if it's a sub-item + // Check if it's a sub-item by verifying its parent index QModelIndex parentIndex = index.parent(); if (!parentIndex.isValid()) { - qDebug() << "Double-clicked on a top-level item."; + qDebug() << "Double-clicked on a top-level item (file path), ignoring."; return; } // Retrieve the file path from the parent item - QString filePath = m_resultModel->itemFromIndex(parentIndex)->text(); + QStandardItem *parentItem = m_resultModel->itemFromIndex(parentIndex); + if (!parentItem) { + qWarning() << "Failed to retrieve parent item for index:" << index; + return; + } + QString filePath = parentItem->text(); // Retrieve the line number from the clicked sub-item - int lineNumber = index.data(Qt::UserRole).toInt(); - qDebug() << "Retrieved Line Number:" << lineNumber; + QVariant lineData = index.data(Qt::UserRole); + if (!lineData.isValid()) { + qWarning() << "No valid line number data for index:" << index; + return; + } + + int lineNumber = lineData.toInt(); + qDebug() << "File Path:" << filePath << "Retrieved Line Number:" << lineNumber; - if (lineNumber > 0) { - //QMessageBox::information(this, "Double Click", QString("File: %1\nLine: %2").arg(filePath).arg(lineNumber)); - qDebug() << "Emitting openFileAtMatch signal with File Path:" << filePath << "Line Number:" << lineNumber; + if (lineNumber > 0) { // TODO: Remove MessageBox + QMessageBox::information(this, "Double Click", QString("File: %1\nLine: %2").arg(filePath).arg(lineNumber)); + qDebug() << "Emitting openFileAtMatch signal for File Path:" << filePath << "Line Number:" << lineNumber; emit openFileAtMatch(filePath, lineNumber); } else { - qWarning() << "Line number conversion failed for index:" << index; + qWarning() << "Invalid line number detected for index:" << index; } } diff --git a/src/systemsearchresultdialog.h b/src/systemsearchresultdialog.h index fdecdac..b8b855c 100644 --- a/src/systemsearchresultdialog.h +++ b/src/systemsearchresultdialog.h @@ -1,9 +1,11 @@ #pragma once +#include #include #include #include #include +#include #include "search/searchoptions.h" QT_BEGIN_NAMESPACE @@ -21,6 +23,14 @@ class SystemSearchResultDialog : public QDialog void addSearchResult(const FileSearchResults &result); void setSearchOptions(SearchOptions searchOptions); +protected: + void closeEvent(QCloseEvent *event) override { + qWarning() << "Window is closing. Cleaning up resources..."; + cleanupResources(); + // Optionally accept or ignore the event + event->accept(); // or event->ignore(); + } + signals: void openFileAtMatch(const QString &filePath, int lineNumber); @@ -31,6 +41,7 @@ private slots: int extractLineNumber(const QString &line) const; Ui::SystemSearchResultDialog *ui; + void cleanupResources(); QStandardItemModel* m_resultModel; SearchOptions m_searchOptions; QStandardItemModel* m_treeModel; diff --git a/src/systemtextdelegate.cpp b/src/systemtextdelegate.cpp index 47f849a..a98385d 100644 --- a/src/systemtextdelegate.cpp +++ b/src/systemtextdelegate.cpp @@ -27,6 +27,11 @@ void SystemTextDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op QRect rect = option.rect; painter->setClipRect(rect); + // Handle selection background + if (option.state & QStyle::State_Selected) { + painter->fillRect(rect, option.palette.highlight()); + } + if (content.contains("setPen(option.palette.highlightedText().color()); + } else { + painter->setPen(option.palette.text().color()); + } + // Draw the elided text painter->drawText(rect, Qt::AlignVCenter | Qt::AlignLeft, elidedText); } From 941ac2228fd51c9c5e4fce9792747bf3fbd14e26 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 08:54:26 +0330 Subject: [PATCH 41/81] github action #67 --- .github/workflows/cmake-multi-platform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index e3b98be..edfcb89 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -96,7 +96,7 @@ jobs: ) dir "%QT_SOURCE%\qtbase" cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + call "%CD%\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From d31ce9d209bd6c563380b488f14d066c076bc74b Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 09:28:24 +0330 Subject: [PATCH 42/81] github action #68 --- .github/workflows/cmake-multi-platform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index edfcb89..e3b98be 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -96,7 +96,7 @@ jobs: ) dir "%QT_SOURCE%\qtbase" cd "%QT_SOURCE%\qtbase" - call "%CD%\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From d0401e826e0a2b701adf55f18e58c7691d5167b4 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 09:57:55 +0330 Subject: [PATCH 43/81] github action #69 --- .github/workflows/cmake-multi-platform.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index e3b98be..3c90c40 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -89,6 +89,9 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 + REM Set the PATH to include the Qt directory + SET PATH=%QT_SOURCE%\qtbase;%PATH% + REM Configure and build Qt SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( From ad2c9c15a933aa119cd853b8fb0d4b4135951bf3 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 10:05:28 +0330 Subject: [PATCH 44/81] github action #70 --- .github/workflows/cmake-multi-platform.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 3c90c40..e3b98be 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -89,9 +89,6 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - REM Set the PATH to include the Qt directory - SET PATH=%QT_SOURCE%\qtbase;%PATH% - REM Configure and build Qt SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( From cd6193e4054b7eab5db4df954a5b856fd0e3311f Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 10:10:42 +0330 Subject: [PATCH 45/81] github action #71 --- .github/workflows/cmake-multi-platform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index e3b98be..edfcb89 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -96,7 +96,7 @@ jobs: ) dir "%QT_SOURCE%\qtbase" cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + call "%CD%\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From 9655b6550ef79a35311bef77225418e0ff47938f Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 11:24:27 +0330 Subject: [PATCH 46/81] github action #72 --- .github/workflows/cmake-multi-platform.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index edfcb89..506dc33 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -96,9 +96,11 @@ jobs: ) dir "%QT_SOURCE%\qtbase" cd "%QT_SOURCE%\qtbase" - call "%CD%\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build . --parallel - cmake --install . + call configure.bat -top-level ^ + -prefix C:\Qt -release -opensource -confirm-license ^ + -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja || exit /b 1 + cmake --build . --parallel || exit /b 1 + cmake --install . || exit /b 1 - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From 1d2b451fdd3392d610f89ddd9ae17012aa52f9ce Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 11:29:53 +0330 Subject: [PATCH 47/81] github action #73 --- .github/workflows/cmake-multi-platform.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 506dc33..edfcb89 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -96,11 +96,9 @@ jobs: ) dir "%QT_SOURCE%\qtbase" cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level ^ - -prefix C:\Qt -release -opensource -confirm-license ^ - -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja || exit /b 1 - cmake --build . --parallel || exit /b 1 - cmake --install . || exit /b 1 + call "%CD%\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cmake --build . --parallel + cmake --install . - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From e804fba697d56daf60724667318de1766db9c793 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 16:34:46 +0330 Subject: [PATCH 48/81] Find System (partially 3) --- CHANGELOG.md | 5 ++ CMakeLists.txt.user | 26 ++++---- src/search/filesearchworker.cpp | 21 ++++++- src/systemfind/systemfinddialog.cpp | 95 ++++++++++++++++++++++++++--- src/systemfind/systemfinddialog.h | 7 ++- src/systemfind/systemfinddialog.ui | 2 +- src/systemsearchresultdialog.cpp | 90 ++++++++++++++------------- 7 files changed, 175 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 371aeeb..5ac6548 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 0.0.50 + +- Implemented: +- Search Menu -> Find System (partially 3) + ## 0.0.49 - Implemented: diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index a289ff5..8246c4a 100755 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -102,14 +102,14 @@ 2 false - -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_GENERATOR:STRING=Ninja + -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} -DCMAKE_BUILD_TYPE:STRING=Debug --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} /data/Code/Qt/Notepad-- 0 /data/Code/Qt/Notepad--/build/Desktop-Debug @@ -160,14 +160,14 @@ 2 false - -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_GENERATOR:STRING=Ninja + -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} -DCMAKE_BUILD_TYPE:STRING=Release --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} /data/Code/Qt/Notepad-- /data/Code/Qt/Notepad--/build/Desktop-Release diff --git a/src/search/filesearchworker.cpp b/src/search/filesearchworker.cpp index ea795aa..930940e 100644 --- a/src/search/filesearchworker.cpp +++ b/src/search/filesearchworker.cpp @@ -29,7 +29,8 @@ FileSearchResults FileSearchWorker::searchInFile() { QTextStream in(&file); QRegularExpression pattern(m_options.keyword, - m_options.matchCase ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption); + m_options.matchCase ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption); int lineNumber = 0; while (!in.atEnd()) { @@ -37,15 +38,29 @@ FileSearchResults FileSearchWorker::searchInFile() { QRegularExpressionMatchIterator it = pattern.globalMatch(line); bool hasMatch = false; + QString highlightedLine = line; // For highlighting + while (it.hasNext()) { QRegularExpressionMatch match = it.next(); - result.matchingLines.append(highlightMatches(line, pattern)); + + // Highlight the keywords in the line + highlightedLine = highlightMatches(line, pattern); + + // Add the line number and the full line to `matches` + result.matches.append(qMakePair(lineNumber, highlightedLine)); + result.matchCount++; hasMatch = true; } - if (!hasMatch) lineNumber++; + if (hasMatch) { + // Append to `matchingLines` only if a match exists + result.matchingLines.append(highlightedLine); + } + + lineNumber++; } + return result; } diff --git a/src/systemfind/systemfinddialog.cpp b/src/systemfind/systemfinddialog.cpp index e61b7dc..0d7b2c3 100644 --- a/src/systemfind/systemfinddialog.cpp +++ b/src/systemfind/systemfinddialog.cpp @@ -194,35 +194,108 @@ void SystemFindDialog::on_pushButtonBrowse_clicked() } } -void SystemFindDialog::startSearch(const SearchOptions& options) { +void SystemFindDialog::startSearchNext(const SearchOptions& options) { if (!m_searchOptions) { m_searchOptions = new SearchOptions(); } *m_searchOptions = options; + m_processedFiles = 0; m_totalFiles = 0; + // Unescape the pattern provided by the user + QString unescapedPattern = m_searchOptions->pattern.replace("\\\\", "\\"); + qDebug() << "[INFO] Search Options->Unescaped Pattern:" << unescapedPattern; + + // Declare a static QRegularExpression + static QRegularExpression regex; + if (regex.pattern() != unescapedPattern || !regex.isValid()) { + regex.setPattern(unescapedPattern); + if (!regex.isValid()) { + qWarning() << "Invalid regex pattern:" << regex.errorString(); + return; + } + } + ui->m_progressBar->setValue(0); - countTextFiles(m_searchOptions->location); + countTextFiles(m_searchOptions->location, regex); ui->m_progressBar->setMaximum(m_totalFiles); - QDirIterator::IteratorFlags flags = m_searchOptions->includeSubdirectories ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; + QDirIterator::IteratorFlags flags = m_searchOptions->includeSubdirectories + ? QDirIterator::Subdirectories + : QDirIterator::NoIteratorFlags; + QDirIterator it(m_searchOptions->location, QDir::Files, flags); while (it.hasNext()) { QString filePath = it.next(); - processFile(filePath); + QString fileName = QFileInfo(filePath).fileName(); + + if (regex.match(fileName).hasMatch()) { + processFile(filePath); + } + } +} + +void SystemFindDialog::startSearchPrevious(const SearchOptions& options) { + if (!m_searchOptions) { + m_searchOptions = new SearchOptions(); + } + *m_searchOptions = options; + + m_processedFiles = 0; + m_totalFiles = 0; + + // Unescape the pattern provided by the user + QString unescapedPattern = m_searchOptions->pattern.replace("\\\\", "\\"); + qDebug() << "[INFO] Search Options->Unescaped Pattern:" << unescapedPattern; + + // Declare a static QRegularExpression + static QRegularExpression regex; + if (regex.pattern() != unescapedPattern || !regex.isValid()) { + regex.setPattern(unescapedPattern); + if (!regex.isValid()) { + qWarning() << "Invalid regex pattern:" << regex.errorString(); + return; + } + } + + ui->m_progressBar->setValue(0); + countTextFiles(m_searchOptions->location, regex); + ui->m_progressBar->setMaximum(m_totalFiles); + + QDirIterator::IteratorFlags flags = m_searchOptions->includeSubdirectories + ? QDirIterator::Subdirectories + : QDirIterator::NoIteratorFlags; + + // Collect all files matching the pattern + QStringList matchingFiles; + QDirIterator it(m_searchOptions->location, QDir::Files, flags); + while (it.hasNext()) { + QString filePath = it.next(); + QString fileName = QFileInfo(filePath).fileName(); + if (regex.match(fileName).hasMatch()) { + matchingFiles.append(filePath); + } + } + + // Reverse iterate through the list of matching files for "find previous" + for (auto filePath = matchingFiles.crbegin(); filePath != matchingFiles.crend(); ++filePath) { + processFile(*filePath); } } -void SystemFindDialog::countTextFiles(const QString& directory) { +void SystemFindDialog::countTextFiles(const QString& directory, const QRegularExpression& pattern) { QMimeDatabase mimeDb; QDirIterator it(directory, QDir::Files, QDirIterator::Subdirectories); while (it.hasNext()) { QString filePath = it.next(); + QString fileName = QFileInfo(filePath).fileName(); QMimeType mimeType = mimeDb.mimeTypeForFile(filePath); - if (mimeType.name().startsWith("text/")) { + + // Match file name against the pattern + if (mimeType.name().startsWith("text/") && pattern.match(fileName).hasMatch()) { m_totalFiles++; } } @@ -291,9 +364,13 @@ void SystemFindDialog::on_findNext_clicked() { UpdateSearchOptions(); showResultDialog(); - startSearch(*m_searchOptions); + startSearchNext(*m_searchOptions); } - - +void SystemFindDialog::on_findPrevious_clicked() +{ + UpdateSearchOptions(); + showResultDialog(); + startSearchPrevious(*m_searchOptions); +} diff --git a/src/systemfind/systemfinddialog.h b/src/systemfind/systemfinddialog.h index 9f1830f..adc50a3 100644 --- a/src/systemfind/systemfinddialog.h +++ b/src/systemfind/systemfinddialog.h @@ -23,7 +23,8 @@ class SystemFindDialog : public QDialog explicit SystemFindDialog(QWidget *parent = nullptr); ~SystemFindDialog(); - void startSearch(const SearchOptions& options); + void startSearchNext(const SearchOptions& options); + void startSearchPrevious(const SearchOptions& options); protected: void closeEvent(QCloseEvent *event) override { @@ -49,6 +50,8 @@ private slots: void on_pushButtonBrowse_clicked(); + void on_findPrevious_clicked(); + private: Ui::SystemFindDialog *ui; @@ -65,7 +68,7 @@ private slots: void UpdateSearchOptions(); void showResultDialog(); - void countTextFiles(const QString& directory); + void countTextFiles(const QString& directory, const QRegularExpression& pattern); void processFile(const QString& filePath); int m_totalFiles = 0; int m_processedFiles = 0; diff --git a/src/systemfind/systemfinddialog.ui b/src/systemfind/systemfinddialog.ui index b52b4c0..50b4edb 100644 --- a/src/systemfind/systemfinddialog.ui +++ b/src/systemfind/systemfinddialog.ui @@ -71,7 +71,7 @@ - *ext1, *ext2 + .*\\.txt$, .*\\.cpp$ diff --git a/src/systemsearchresultdialog.cpp b/src/systemsearchresultdialog.cpp index a718db0..44fe9fa 100644 --- a/src/systemsearchresultdialog.cpp +++ b/src/systemsearchresultdialog.cpp @@ -12,7 +12,6 @@ SystemSearchResultDialog::SystemSearchResultDialog(QWidget *parent) , m_resultModel(new QStandardItemModel(this)) { ui->setupUi(this); - // FIXME: treeview is not selectable and should be. m_treeModel = new QStandardItemModel(this); ui->resultTreeView->setModel(m_treeModel); @@ -61,60 +60,65 @@ void SystemSearchResultDialog::cleanupResources() { qInfo() << "Cleaning up resources. Closing window..."; } +// TODO: Pass SearchOptions to this function so it can highlight all keywords. void SystemSearchResultDialog::addSearchResult(const FileSearchResults &result) { + if (result.matches.isEmpty()) { + qWarning() << "No matches found for file:" << result.filePath; + return; + } + QStandardItem *filePathItem = new QStandardItem(result.filePath); filePathItem->setFlags(filePathItem->flags() | Qt::ItemIsSelectable); - int calculatedTotalMatchCount = 0; - int firstKeywordLineNumber = -1; // Initialize to "not found" - int currentLineNumber = 1; // Start counting lines from 1 - - for (const QString &line : result.matchingLines) { - // Count occurrences of the keyword in the line - int keywordCount = Helpers::countKeywordsInLine(line, m_searchOptions); - - if (keywordCount > 0) { - calculatedTotalMatchCount += keywordCount; - - // Highlight keywords in the line - QString highlightedLine = Helpers::highlightKeywords(line, m_searchOptions); - - // Track the first line containing a keyword - if (firstKeywordLineNumber == -1) { - firstKeywordLineNumber = currentLineNumber; - } - - // Create tree view items for the line and keyword count - QStandardItem *lineItem = new QStandardItem(); - lineItem->setFlags(lineItem->flags() | Qt::ItemIsSelectable); - lineItem->setData(highlightedLine, Qt::DisplayRole); - lineItem->setData(currentLineNumber, Qt::UserRole); - - QStandardItem *matchesItem = new QStandardItem(QString::number(keywordCount)); - matchesItem->setFlags(matchesItem->flags() | Qt::ItemIsSelectable); + QStandardItem *matchCountItem = new QStandardItem(QString::number(result.matchCount)); + matchCountItem->setFlags(matchCountItem->flags() | Qt::ItemIsSelectable); - // Append the line and matches to the file path item - filePathItem->appendRow({lineItem, matchesItem}); + int firstKeywordLineNumber = -1; // To track the first match line number + + // Iterate through the matches to populate the result model + for (const auto &[lineNumber, lineContent] : result.matches) { + // Highlight keywords with cyan + QString highlightedLine = lineContent; + QString pattern = QStringLiteral("%1"); + highlightedLine.replace( + QRegularExpression(QString("\\b%1\\b").arg(QRegularExpression::escape(m_searchOptions.keyword)), + m_searchOptions.matchCase + ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption), + pattern.arg(m_searchOptions.keyword)); + + QStandardItem *lineItem = new QStandardItem(); + lineItem->setFlags(lineItem->flags() | Qt::ItemIsSelectable); + lineItem->setData(highlightedLine, Qt::DisplayRole); // Highlighted line content + lineItem->setData(lineNumber + 1, Qt::UserRole); // Line number (1-based) + + QStandardItem *matchesItem = new QStandardItem(QString::number(1)); + matchesItem->setFlags(matchesItem->flags() | Qt::ItemIsSelectable); + + filePathItem->appendRow({lineItem, matchesItem}); + + // Store the first keyword's line number (1-based) + if (firstKeywordLineNumber == -1) { + firstKeywordLineNumber = lineNumber + 1; // Convert to 1-based } - - currentLineNumber++; // Increment the line counter } - // Add total matches as a separate item - QStandardItem *matchCountItem = new QStandardItem(QString::number(calculatedTotalMatchCount)); - matchCountItem->setFlags(matchCountItem->flags() | Qt::ItemIsSelectable); + // Add the file path and match count as a top-level item m_resultModel->appendRow({filePathItem, matchCountItem}); - // Emit signal for the first keyword line if found - if (firstKeywordLineNumber != -1) { - qDebug() << "First keyword line number calculated:" << firstKeywordLineNumber - << "for file:" << result.filePath; - emit openFileAtMatch(result.filePath, firstKeywordLineNumber); - } else { - qDebug() << "No keywords found in file:" << result.filePath; + qDebug() << "File:" << result.filePath + << "Reported matches:" << result.matchCount + << "First keyword line number:" << firstKeywordLineNumber; + + // If needed, handle the first keyword line highlighting + if (firstKeywordLineNumber > 0) { + qDebug() << "First keyword found at line:" << firstKeywordLineNumber << "in file:" << result.filePath; + // Call the highlighting function here, if necessary + // Example: highlightLineInView(result.filePath, firstKeywordLineNumber); } } + // FIXME: Line number is wrong void SystemSearchResultDialog::handleDoubleClick(const QModelIndex &index) { if (!index.isValid()) { @@ -151,7 +155,7 @@ void SystemSearchResultDialog::handleDoubleClick(const QModelIndex &index) { qDebug() << "File Path:" << filePath << "Retrieved Line Number:" << lineNumber; if (lineNumber > 0) { // TODO: Remove MessageBox - QMessageBox::information(this, "Double Click", QString("File: %1\nLine: %2").arg(filePath).arg(lineNumber)); + //QMessageBox::information(this, "Double Click", QString("File: %1\nLine: %2").arg(filePath).arg(lineNumber)); qDebug() << "Emitting openFileAtMatch signal for File Path:" << filePath << "Line Number:" << lineNumber; emit openFileAtMatch(filePath, lineNumber); } else { From c34f69323304dc8cb7146af2da4a1004001765e5 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 16:36:37 +0330 Subject: [PATCH 49/81] github action #74 --- .github/workflows/cmake-multi-platform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index edfcb89..e3b98be 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -96,7 +96,7 @@ jobs: ) dir "%QT_SOURCE%\qtbase" cd "%QT_SOURCE%\qtbase" - call "%CD%\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From 294844f360132f7a69cfd4a89edbcb91a48781b3 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 21:25:15 +0330 Subject: [PATCH 50/81] github action #75 --- .github/workflows/cmake-multi-platform.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index e3b98be..520fa6c 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -94,9 +94,8 @@ jobs: IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) - dir "%QT_SOURCE%\qtbase" cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + call "%QT_SOURCE%\qtbase\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja cmake --build . --parallel cmake --install . From 62e90fb94b7dac77d82e5b6b2104202034c27fa0 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Tue, 19 Nov 2024 21:35:16 +0330 Subject: [PATCH 51/81] github action #76 --- .github/workflows/cmake-multi-platform.yml | 57 +--------------------- 1 file changed, 1 insertion(+), 56 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 520fa6c..3825846 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Qt Source Compilation and Caching + ### Windows Setup - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -55,59 +55,6 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - - name: Cache Qt Source (Windows) - if: matrix.os == 'windows-latest' - uses: actions/cache@v3 - with: - path: ${{ runner.temp }}/qt-source - key: qt-source-6.5.3 - - - name: Download Qt Source (Windows) - if: matrix.os == 'windows-latest' - shell: powershell - run: | - $qtSourceDir = "$env:TEMP\qt-source" - $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - Write-Host "Downloading Qt Source" - New-Item -ItemType Directory -Path $qtSourceDir -Force - Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip - Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir - } - dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" - - - name: Build and Install Qt (Windows) - if: matrix.os == 'windows-latest' - shell: cmd - run: | - REM Locate Visual Studio Build Tools - FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ - -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i - IF NOT DEFINED VS_PATH ( - echo Visual Studio Build Tools not found! && exit /b 1 - ) - SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" - CALL "%VS_VARS_CMD%" || exit /b 1 - - REM Configure and build Qt - SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 - IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( - echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 - ) - cd "%QT_SOURCE%\qtbase" - call "%QT_SOURCE%\qtbase\configure.bat" -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build . --parallel - cmake --install . - - - name: Set Qt Environment Variables (Windows) - if: matrix.os == 'windows-latest' - shell: powershell - run: | - echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $env:GITHUB_ENV - echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV - echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV - - # Configure CMake - name: Configure CMake run: | cmake -B "${{ github.workspace }}/build" \ @@ -117,11 +64,9 @@ jobs: -G "Ninja" \ -S "${{ github.workspace }}" - # Build the project - name: Build run: cmake --build "${{ github.workspace }}/build" --config Release - # Run tests - name: Test working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release From c404aefceb806f536cc51d179089d708a34b862c Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 03:32:20 +0330 Subject: [PATCH 52/81] v0.0.50 --- CHANGELOG.md | 5 ++ CMakeLists.txt.user | 26 ++++----- src/mainwindow.cpp | 2 +- src/systemfind/systemfinddialog.cpp | 82 +++++++++++++++++++++++++++-- src/systemfind/systemfinddialog.h | 4 ++ 5 files changed, 102 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ac6548..e7bb73e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 0.0.51 + +- Implemented: +- Search Menu -> Find System (partially 4) + ## 0.0.50 - Implemented: diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index 8246c4a..04850a2 100755 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -102,14 +102,14 @@ 2 false - -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_BUILD_TYPE:STRING=Debug --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake + -DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_BUILD_TYPE:STRING=Debug +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} /data/Code/Qt/Notepad-- 0 /data/Code/Qt/Notepad--/build/Desktop-Debug @@ -160,14 +160,14 @@ 2 false - -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_BUILD_TYPE:STRING=Release --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake + -DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_BUILD_TYPE:STRING=Release +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} /data/Code/Qt/Notepad-- /data/Code/Qt/Notepad--/build/Desktop-Release diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 52ec2e8..30c59f2 100755 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -481,7 +481,7 @@ void MainWindow::openSearchResult(const QString &filePath, int lineNumber) { qInfo() << "openSearchResult called. File Path:" << filePath << ", Line Number:" << lineNumber; Document* doc = fileOperations->openDocument(filePath); if (!doc || !doc->editor()) { - qFatal() << "Document or editor is null."; + qFatal("Document or editor is null."); return; } diff --git a/src/systemfind/systemfinddialog.cpp b/src/systemfind/systemfinddialog.cpp index 0d7b2c3..c8dfa7a 100644 --- a/src/systemfind/systemfinddialog.cpp +++ b/src/systemfind/systemfinddialog.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "systemfinddialog.h" #include "../search/filesearchworker.h" #include "ui_systemfinddialog.h" @@ -118,7 +119,7 @@ void SystemFindDialog::saveLocation(const QString& location) QStringList locations = Settings::instance()->loadSetting("Location", "Keywords", QStringList()).toStringList(); if (!locations.contains(location)) { - locations.prepend(location); // Add keyword to the top of history list + locations.prepend(location); // Add location to the top of history list if (locations.size() > 10) { locations = locations.mid(0, 10); // Limit history to 10 items } @@ -138,7 +139,7 @@ void SystemFindDialog::savePattern(const QString& pattern) QStringList patterns = Settings::instance()->loadSetting("Pattern", "Keywords", QStringList()).toStringList(); if (!patterns.contains(pattern)) { - patterns.prepend(pattern); // Add keyword to the top of history list + patterns.prepend(pattern); // Add pattern to the top of history list if (patterns.size() > 10) { patterns = patterns.mid(0, 10); // Limit history to 10 items } @@ -152,6 +153,27 @@ void SystemFindDialog::savePattern(const QString& pattern) } } +void SystemFindDialog::saveHistory() { + QString keyword = ui->comboBoxFind->currentText().trimmed(); + if (keyword.isEmpty()) { + QMessageBox::warning(this, "Warning", "Please enter a search keyword."); + return; + } + saveKeyword(keyword); + + QString location = ui->comboBoxLocation->currentText().trimmed(); + if (location.isEmpty()) { + QMessageBox::warning(this, "Warning", "Please select a location."); + return; + } + saveLocation(location); + + QString pattern = ui->comboBoxPattern->currentText().trimmed(); + if (!pattern.isEmpty()) { + savePattern(pattern); + } +} + void SystemFindDialog::onAdvancedOptionsToggled(bool checked) { ui->groupBoxAdvanced->setVisible(checked); } @@ -205,7 +227,7 @@ void SystemFindDialog::startSearchNext(const SearchOptions& options) { // Unescape the pattern provided by the user QString unescapedPattern = m_searchOptions->pattern.replace("\\\\", "\\"); - qDebug() << "[INFO] Search Options->Unescaped Pattern:" << unescapedPattern; + qDebug() << "Search Options->Unescaped Pattern:" << unescapedPattern; // Declare a static QRegularExpression static QRegularExpression regex; @@ -285,6 +307,49 @@ void SystemFindDialog::startSearchPrevious(const SearchOptions& options) { } } +void SystemFindDialog::selectAll(const SearchOptions& options) { + if (!m_searchOptions) { + m_searchOptions = new SearchOptions(); + } + *m_searchOptions = options; + + m_processedFiles = 0; + m_totalFiles = 0; + + // Unescape the pattern provided by the user + QString unescapedPattern = m_searchOptions->pattern.replace("\\\\", "\\"); + qDebug() << "Search Options->Unescaped Pattern:" << unescapedPattern; + + // Declare a static QRegularExpression + static QRegularExpression regex; + if (regex.pattern() != unescapedPattern || !regex.isValid()) { + regex.setPattern(unescapedPattern); + if (!regex.isValid()) { + qWarning() << "Invalid regex pattern:" << regex.errorString(); + return; + } + } + + ui->m_progressBar->setValue(0); + countTextFiles(m_searchOptions->location, regex); + ui->m_progressBar->setMaximum(m_totalFiles); + + QDirIterator::IteratorFlags flags = m_searchOptions->includeSubdirectories + ? QDirIterator::Subdirectories + : QDirIterator::NoIteratorFlags; + + QDirIterator it(m_searchOptions->location, QDir::Files, flags); + + while (it.hasNext()) { + QString filePath = it.next(); + QString fileName = QFileInfo(filePath).fileName(); + + if (regex.match(fileName).hasMatch()) { + processFile(filePath); + } + } +} + void SystemFindDialog::countTextFiles(const QString& directory, const QRegularExpression& pattern) { QMimeDatabase mimeDb; QDirIterator it(directory, QDir::Files, QDirIterator::Subdirectories); @@ -322,6 +387,7 @@ void SystemFindDialog::handleFileProcessed(const FileSearchResults& result) { m_systemSearchResultDialog->addSearchResult(result); } +// FIXME: ProgressBar doesn't work properly. void SystemFindDialog::updateProgressDisplay(int processedFiles, int totalFiles) { ui->m_progressBar->setValue(processedFiles); ui->m_statusLabel->setText(QString("Searching Files... %1/%2").arg(processedFiles).arg(totalFiles)); @@ -363,6 +429,7 @@ void SystemFindDialog::showResultDialog() { void SystemFindDialog::on_findNext_clicked() { UpdateSearchOptions(); + saveHistory(); showResultDialog(); startSearchNext(*m_searchOptions); } @@ -370,7 +437,16 @@ void SystemFindDialog::on_findNext_clicked() void SystemFindDialog::on_findPrevious_clicked() { UpdateSearchOptions(); + saveHistory(); showResultDialog(); startSearchPrevious(*m_searchOptions); } +void SystemFindDialog::on_selectAll_clicked() +{ + UpdateSearchOptions(); + saveHistory(); + showResultDialog(); + selectAll(*m_searchOptions); +} + diff --git a/src/systemfind/systemfinddialog.h b/src/systemfind/systemfinddialog.h index adc50a3..cea6627 100644 --- a/src/systemfind/systemfinddialog.h +++ b/src/systemfind/systemfinddialog.h @@ -25,6 +25,7 @@ class SystemFindDialog : public QDialog void startSearchNext(const SearchOptions& options); void startSearchPrevious(const SearchOptions& options); + void selectAll(const SearchOptions& options); protected: void closeEvent(QCloseEvent *event) override { @@ -52,6 +53,8 @@ private slots: void on_findPrevious_clicked(); + void on_selectAll_clicked(); + private: Ui::SystemFindDialog *ui; @@ -64,6 +67,7 @@ private slots: void saveKeyword(const QString& keyword); void saveLocation(const QString& location); void savePattern(const QString& pattern); + void saveHistory(); bool eventFilter(QObject *watched, QEvent *event); void UpdateSearchOptions(); void showResultDialog(); From 5b393113993d6e49aab23d4b4f22926277fd25c9 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 03:40:30 +0330 Subject: [PATCH 53/81] github action #77 --- .github/workflows/cmake-multi-platform.yml | 24 ++++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 3825846..dbedc1c 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup + ### Windows Dependencies - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -55,18 +55,24 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y + ### Configure CMake - name: Configure CMake + shell: cmd run: | - cmake -B "${{ github.workspace }}/build" \ - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ - -DCMAKE_BUILD_TYPE=Release \ - -G "Ninja" \ - -S "${{ github.workspace }}" + cmake -B "%GITHUB_WORKSPACE%/build" ^ + -DCMAKE_CXX_COMPILER=cl ^ + -DCMAKE_C_COMPILER=cl ^ + -DCMAKE_BUILD_TYPE=Release ^ + -G "Ninja" ^ + -S "%GITHUB_WORKSPACE%" + ### Build the Project - name: Build - run: cmake --build "${{ github.workspace }}/build" --config Release + shell: cmd + run: cmake --build "%GITHUB_WORKSPACE%/build" --config Release + ### Run Tests - name: Test - working-directory: "${{ github.workspace }}/build" + shell: cmd + working-directory: "%GITHUB_WORKSPACE%/build" run: ctest --output-on-failure --build-config Release From 6debc227a43400fc65c50ea48a17e998761e0634 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 03:50:09 +0330 Subject: [PATCH 54/81] github action #78 --- .github/workflows/cmake-multi-platform.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index dbedc1c..8b996b5 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Dependencies + ### Windows Setup - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -55,8 +55,8 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - ### Configure CMake - name: Configure CMake + if: matrix.os == 'windows-latest' shell: cmd run: | cmake -B "%GITHUB_WORKSPACE%/build" ^ @@ -66,13 +66,13 @@ jobs: -G "Ninja" ^ -S "%GITHUB_WORKSPACE%" - ### Build the Project - name: Build + if: matrix.os == 'windows-latest' shell: cmd run: cmake --build "%GITHUB_WORKSPACE%/build" --config Release - ### Run Tests - name: Test + if: matrix.os == 'windows-latest' shell: cmd working-directory: "%GITHUB_WORKSPACE%/build" run: ctest --output-on-failure --build-config Release From 61bb39e9f0ba0f7b5a4652b7b192cf9f90ef3584 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 04:46:56 +0330 Subject: [PATCH 55/81] github action #79 --- .github/workflows/cmake-multi-platform.yml | 28 ++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 8b996b5..8d0067c 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -49,30 +49,44 @@ jobs: ### Windows Setup - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' - shell: powershell + shell: cmd run: | choco install visualstudio2022buildtools -y choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - - name: Configure CMake + - name: Set up MSVC environment (Windows) + if: matrix.os == 'windows-latest' + shell: cmd + run: | + REM Locate Visual Studio installation + FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ + -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i + IF NOT DEFINED VS_PATH ( + echo Visual Studio Build Tools not found! && exit /b 1 + ) + SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" + CALL "%VS_VARS_CMD%" || exit /b 1 + where cl || (echo cl.exe not found in PATH && exit /b 1) + + - name: Configure CMake (Windows) if: matrix.os == 'windows-latest' shell: cmd run: | - cmake -B "%GITHUB_WORKSPACE%/build" ^ + cmake -B "%GITHUB_WORKSPACE%\build" ^ -DCMAKE_CXX_COMPILER=cl ^ -DCMAKE_C_COMPILER=cl ^ -DCMAKE_BUILD_TYPE=Release ^ -G "Ninja" ^ -S "%GITHUB_WORKSPACE%" - - name: Build + - name: Build (Windows) if: matrix.os == 'windows-latest' shell: cmd - run: cmake --build "%GITHUB_WORKSPACE%/build" --config Release + run: cmake --build "%GITHUB_WORKSPACE%\build" --config Release - - name: Test + - name: Test (Windows) if: matrix.os == 'windows-latest' shell: cmd - working-directory: "%GITHUB_WORKSPACE%/build" + working-directory: "%GITHUB_WORKSPACE%\build" run: ctest --output-on-failure --build-config Release From 71b5dd8d4c04469435d9f9315df1fe50dd61d7a8 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 04:51:52 +0330 Subject: [PATCH 56/81] github action #80 --- .github/workflows/cmake-multi-platform.yml | 65 +++++++++++++++------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 8d0067c..852006c 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -49,17 +49,31 @@ jobs: ### Windows Setup - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' - shell: cmd + shell: powershell run: | choco install visualstudio2022buildtools -y choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - - name: Set up MSVC environment (Windows) + - name: Download Qt Source (Windows) + if: matrix.os == 'windows-latest' + shell: powershell + run: | + $qtSourceDir = "$env:TEMP\qt-source" + $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + Write-Host "Downloading Qt Source" + New-Item -ItemType Directory -Path $qtSourceDir -Force + Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip + Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir + } + dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" + + - name: Build and Install Qt from Source (Windows) if: matrix.os == 'windows-latest' shell: cmd run: | - REM Locate Visual Studio installation + REM Locate Visual Studio Build Tools FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i IF NOT DEFINED VS_PATH ( @@ -67,26 +81,37 @@ jobs: ) SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - where cl || (echo cl.exe not found in PATH && exit /b 1) - - name: Configure CMake (Windows) + REM Build Qt from source + SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 + IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( + echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 + ) + cd "%QT_SOURCE%\qtbase" + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cmake --build . --parallel + cmake --install . + + - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' - shell: cmd + shell: powershell run: | - cmake -B "%GITHUB_WORKSPACE%\build" ^ - -DCMAKE_CXX_COMPILER=cl ^ - -DCMAKE_C_COMPILER=cl ^ - -DCMAKE_BUILD_TYPE=Release ^ - -G "Ninja" ^ - -S "%GITHUB_WORKSPACE%" + echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $env:GITHUB_ENV + echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV + echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV - - name: Build (Windows) - if: matrix.os == 'windows-latest' - shell: cmd - run: cmake --build "%GITHUB_WORKSPACE%\build" --config Release + - name: Configure CMake + run: | + cmake -B "${{ github.workspace }}/build" \ + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ + -DCMAKE_BUILD_TYPE=Release \ + -G "Ninja" \ + -S "${{ github.workspace }}" - - name: Test (Windows) - if: matrix.os == 'windows-latest' - shell: cmd - working-directory: "%GITHUB_WORKSPACE%\build" + - name: Build + run: cmake --build "${{ github.workspace }}/build" --config Release + + - name: Test + working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release From 2fd3e6ba0c26ea3173d97c78435973023c44b5c7 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 04:57:45 +0330 Subject: [PATCH 57/81] github action #81 --- .github/workflows/cmake-multi-platform.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 852006c..a18e226 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -55,7 +55,14 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - - name: Download Qt Source (Windows) + - name: Cache Qt Source (Windows) + if: matrix.os == 'windows-latest' + uses: actions/cache@v3 + with: + path: ${{ runner.temp }}/qt-source + key: qt-source-6.5.3 + + - name: Download Qt Source if Not Cached (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | From 98261ea68d8c04e3b62684863ee90a832c763a5e Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 12:32:08 +0330 Subject: [PATCH 58/81] github action #82 --- .github/workflows/cmake-multi-platform.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index a18e226..5bafa1d 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup + ### Windows Setup with Qt Source Compilation and Caching - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -62,7 +62,7 @@ jobs: path: ${{ runner.temp }}/qt-source key: qt-source-6.5.3 - - name: Download Qt Source if Not Cached (Windows) + - name: Download Qt Source (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | @@ -89,15 +89,15 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - REM Build Qt from source + REM Configure and Build Qt SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build . --parallel - cmake --install . + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja || exit /b 1 + cmake --build . --parallel || exit /b 1 + cmake --install . || exit /b 1 - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' @@ -107,6 +107,7 @@ jobs: echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV + ### Configure CMake - name: Configure CMake run: | cmake -B "${{ github.workspace }}/build" \ @@ -116,9 +117,11 @@ jobs: -G "Ninja" \ -S "${{ github.workspace }}" + ### Build Project - name: Build run: cmake --build "${{ github.workspace }}/build" --config Release + ### Run Tests - name: Test working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release From 6606a43233a7a3fe1f601a95ece9bd1c01df3dac Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 12:51:29 +0330 Subject: [PATCH 59/81] github action #83 --- .github/workflows/cmake-multi-platform.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 5bafa1d..80c409e 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -46,7 +46,7 @@ jobs: brew install ninja qt echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Qt Source Compilation and Caching + ### Windows Setup with Cached Qt Source Compilation - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell @@ -59,14 +59,14 @@ jobs: if: matrix.os == 'windows-latest' uses: actions/cache@v3 with: - path: ${{ runner.temp }}/qt-source + path: D:\qt-source key: qt-source-6.5.3 - name: Download Qt Source (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | - $qtSourceDir = "$env:TEMP\qt-source" + $qtSourceDir = "D:\qt-source" $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { Write-Host "Downloading Qt Source" @@ -89,15 +89,15 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - REM Configure and Build Qt - SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 + REM Configure and build Qt + SET QT_SOURCE=D:\qt-source\qt-everywhere-src-6.5.3 IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja || exit /b 1 - cmake --build . --parallel || exit /b 1 - cmake --install . || exit /b 1 + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + cmake --build . --parallel + cmake --install . - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' @@ -107,7 +107,7 @@ jobs: echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV - ### Configure CMake + # Configure CMake - name: Configure CMake run: | cmake -B "${{ github.workspace }}/build" \ @@ -117,11 +117,11 @@ jobs: -G "Ninja" \ -S "${{ github.workspace }}" - ### Build Project + # Build the project - name: Build run: cmake --build "${{ github.workspace }}/build" --config Release - ### Run Tests + # Run tests - name: Test working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release From 75aed5971a9069e5c2ed16d080d33bfcbfff7b73 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 16:45:52 +0330 Subject: [PATCH 60/81] github action #84 --- .github/workflows/cmake-multi-platform.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 80c409e..b6d220d 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -96,7 +96,11 @@ jobs: ) cd "%QT_SOURCE%\qtbase" call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build . --parallel + cmake --build . --parallel || ( + echo "Handling ninja build error: regenerating build files" && + cmake -G "Ninja" -S "%QT_SOURCE%\qtbase" -B "%QT_SOURCE%\qtbase\build" && + cmake --build "%QT_SOURCE%\qtbase\build" --parallel + ) cmake --install . - name: Set Qt Environment Variables (Windows) From bcf184a47893dfcd67a71af68fa1e88d50fc0fc3 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 17:06:52 +0330 Subject: [PATCH 61/81] github action #85 --- .github/workflows/cmake-multi-platform.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index b6d220d..8770971 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -60,7 +60,7 @@ jobs: uses: actions/cache@v3 with: path: D:\qt-source - key: qt-source-6.5.3 + key: ${{ runner.os }}-qt-source-6.5.3 - name: Download Qt Source (Windows) if: matrix.os == 'windows-latest' @@ -68,11 +68,14 @@ jobs: run: | $qtSourceDir = "D:\qt-source" $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - Write-Host "Downloading Qt Source" + Write-Host "Qt source not found in cache. Downloading..." New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir + } else { + Write-Host "Qt source found in cache." } dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" @@ -96,11 +99,7 @@ jobs: ) cd "%QT_SOURCE%\qtbase" call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build . --parallel || ( - echo "Handling ninja build error: regenerating build files" && - cmake -G "Ninja" -S "%QT_SOURCE%\qtbase" -B "%QT_SOURCE%\qtbase\build" && - cmake --build "%QT_SOURCE%\qtbase\build" --parallel - ) + cmake --build . --parallel cmake --install . - name: Set Qt Environment Variables (Windows) From 0a73b58306d0c5f1bbf576fdee7edf67cd891e1f Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Wed, 20 Nov 2024 21:06:48 +0330 Subject: [PATCH 62/81] github action #86 --- .github/workflows/cmake-multi-platform.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 8770971..1027768 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -99,8 +99,8 @@ jobs: ) cd "%QT_SOURCE%\qtbase" call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja - cmake --build . --parallel - cmake --install . + ninja || exit /b 1 + ninja install || exit /b 1 - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From a9dc549225ad748f19295cc63ee8f148e1a8b21d Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 21 Nov 2024 02:50:43 +0330 Subject: [PATCH 63/81] github action #87 --- .github/workflows/cmake-multi-platform.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 1027768..bbb83de 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -53,6 +53,7 @@ jobs: run: | choco install visualstudio2022buildtools -y choco install ninja -y + choco install python3 -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - name: Cache Qt Source (Windows) @@ -98,7 +99,10 @@ jobs: echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja || exit /b 1 + IF NOT EXIST build.ninja ( + echo "build.ninja not generated. Exiting." && exit /b 1 + ) ninja || exit /b 1 ninja install || exit /b 1 From d4f3a3eff41431f899234d9ad3b42bda32933853 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 21 Nov 2024 03:10:56 +0330 Subject: [PATCH 64/81] github action #88 --- .github/workflows/cmake-multi-platform.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index bbb83de..4aa0d5b 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -60,17 +60,17 @@ jobs: if: matrix.os == 'windows-latest' uses: actions/cache@v3 with: - path: D:\qt-source - key: ${{ runner.os }}-qt-source-6.5.3 + path: D:/qt-source + key: windows-qt-source-6.5.3 - name: Download Qt Source (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | - $qtSourceDir = "D:\qt-source" - $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" + $qtSourceDir = "D:/qt-source" + $qtZip = "$qtSourceDir/qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + if (-Not (Test-Path "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase/configure.bat")) { Write-Host "Qt source not found in cache. Downloading..." New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip @@ -78,7 +78,7 @@ jobs: } else { Write-Host "Qt source found in cache." } - dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" + dir "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase" - name: Build and Install Qt from Source (Windows) if: matrix.os == 'windows-latest' @@ -94,7 +94,7 @@ jobs: CALL "%VS_VARS_CMD%" || exit /b 1 REM Configure and build Qt - SET QT_SOURCE=D:\qt-source\qt-everywhere-src-6.5.3 + SET QT_SOURCE=D:/qt-source/qt-everywhere-src-6.5.3 IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) From 3aa3881e30b9448d24badc39efd815ea57427533 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 21 Nov 2024 09:56:25 +0330 Subject: [PATCH 65/81] github action #89 --- .github/workflows/cmake-multi-platform.yml | 23 +++++----------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 4aa0d5b..960c4cf 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -29,23 +29,6 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - ### Ubuntu Dependencies - - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get update - sudo apt-get install -y ninja-build \ - qt6-base-dev qt6-tools-dev qt6-tools-dev-tools \ - qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev - echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV - - ### macOS Dependencies - - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' - run: | - brew install ninja qt - echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - ### Windows Setup with Cached Qt Source Compilation - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' @@ -55,6 +38,8 @@ jobs: choco install ninja -y choco install python3 -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y + choco install llvm -y + pip install html5lib - name: Cache Qt Source (Windows) if: matrix.os == 'windows-latest' @@ -99,7 +84,9 @@ jobs: echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja || exit /b 1 + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ + -DFEATURE_clang=ON ^ + -DFEATURE_clangcpp=ON || exit /b 1 IF NOT EXIST build.ninja ( echo "build.ninja not generated. Exiting." && exit /b 1 ) From ea1b572177ee4e613665151f784e5d0d202761c1 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 21 Nov 2024 10:03:28 +0330 Subject: [PATCH 66/81] github action #90 --- .github/workflows/cmake-multi-platform.yml | 52 +++++++++++++--------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 960c4cf..0e128c3 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -29,41 +29,54 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - ### Windows Setup with Cached Qt Source Compilation + ### Ubuntu Dependencies + - name: Install dependencies (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y ninja-build \ + qt6-base-dev qt6-tools-dev qt6-tools-dev-tools \ + qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev + echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV + + ### macOS Dependencies + - name: Install dependencies (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install ninja qt + echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV + + ### Windows Setup - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | choco install visualstudio2022buildtools -y choco install ninja -y - choco install python3 -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - choco install llvm -y + choco install python3 -y pip install html5lib - name: Cache Qt Source (Windows) if: matrix.os == 'windows-latest' uses: actions/cache@v3 with: - path: D:/qt-source - key: windows-qt-source-6.5.3 + path: ${{ runner.temp }}/qt-source + key: qt-source-6.5.3 - - name: Download Qt Source (Windows) + - name: Download Qt Source if Not Cached (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | - $qtSourceDir = "D:/qt-source" - $qtZip = "$qtSourceDir/qt-everywhere-src-6.5.3.zip" - - if (-Not (Test-Path "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase/configure.bat")) { - Write-Host "Qt source not found in cache. Downloading..." + $qtSourceDir = "$env:TEMP\qt-source" + $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + Write-Host "Downloading Qt Source" New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir - } else { - Write-Host "Qt source found in cache." } - dir "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase" + dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" - name: Build and Install Qt from Source (Windows) if: matrix.os == 'windows-latest' @@ -78,8 +91,8 @@ jobs: SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" CALL "%VS_VARS_CMD%" || exit /b 1 - REM Configure and build Qt - SET QT_SOURCE=D:/qt-source/qt-everywhere-src-6.5.3 + REM Build Qt from source + SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) @@ -87,11 +100,8 @@ jobs: call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ -DFEATURE_clang=ON ^ -DFEATURE_clangcpp=ON || exit /b 1 - IF NOT EXIST build.ninja ( - echo "build.ninja not generated. Exiting." && exit /b 1 - ) - ninja || exit /b 1 - ninja install || exit /b 1 + cmake --build . --parallel + cmake --install . - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From 58c4fab07b9b6a58eb97d1c606466810ca571b61 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 21 Nov 2024 10:12:26 +0330 Subject: [PATCH 67/81] github action #91 --- .github/workflows/cmake-multi-platform.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 0e128c3..ec51d6b 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -57,26 +57,26 @@ jobs: choco install python3 -y pip install html5lib - - name: Cache Qt Source (Windows) + - name: Restore Qt Source Cache (Windows) if: matrix.os == 'windows-latest' uses: actions/cache@v3 with: - path: ${{ runner.temp }}/qt-source + path: D:/qt-source key: qt-source-6.5.3 - - name: Download Qt Source if Not Cached (Windows) + - name: Download Qt Source if Cache Miss (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | - $qtSourceDir = "$env:TEMP\qt-source" - $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + $qtSourceDir = "D:/qt-source" + $qtZip = "$qtSourceDir/qt-everywhere-src-6.5.3.zip" + if (-Not (Test-Path "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase/configure.bat")) { Write-Host "Downloading Qt Source" New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir } - dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" + dir "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase" - name: Build and Install Qt from Source (Windows) if: matrix.os == 'windows-latest' @@ -92,7 +92,7 @@ jobs: CALL "%VS_VARS_CMD%" || exit /b 1 REM Build Qt from source - SET QT_SOURCE=%TEMP%\qt-source\qt-everywhere-src-6.5.3 + SET QT_SOURCE=D:/qt-source/qt-everywhere-src-6.5.3 IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) From 10d41bf4e626a5c52e80de432fe9ec103fa3ac0f Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Thu, 21 Nov 2024 19:18:01 +0330 Subject: [PATCH 68/81] github action # --- .github/workflows/cmake-multi-platform.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index ec51d6b..99c7fed 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -55,6 +55,8 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y choco install python3 -y + choco install gperf -y + choco install llvm -y pip install html5lib - name: Restore Qt Source Cache (Windows) @@ -100,8 +102,8 @@ jobs: call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ -DFEATURE_clang=ON ^ -DFEATURE_clangcpp=ON || exit /b 1 - cmake --build . --parallel - cmake --install . + cmake --build . --parallel || exit /b 1 + cmake --install . || exit /b 1 - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From ed861c7a5d5a4aee88d0cb103f02df8973abd6a0 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 22 Nov 2024 01:08:42 +0330 Subject: [PATCH 69/81] github action #93 --- .github/workflows/cmake-multi-platform.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 99c7fed..1388eda 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -55,7 +55,7 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y choco install python3 -y - choco install gperf -y + choco install bison -y choco install llvm -y pip install html5lib @@ -102,8 +102,15 @@ jobs: call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ -DFEATURE_clang=ON ^ -DFEATURE_clangcpp=ON || exit /b 1 - cmake --build . --parallel || exit /b 1 - cmake --install . || exit /b 1 + + REM Verify if build.ninja exists + IF NOT EXIST build.ninja ( + echo "Error: build.ninja not generated. Check configuration step for issues." && exit /b 1 + ) + + REM Proceed with the build and install steps + ninja || exit /b 1 + ninja install || exit /b 1 - name: Set Qt Environment Variables (Windows) if: matrix.os == 'windows-latest' From e396cc72052b94e795a3e30afd1c07f19ea8de35 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 22 Nov 2024 01:34:02 +0330 Subject: [PATCH 70/81] github action #94 --- .github/workflows/cmake-multi-platform.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 1388eda..41a1926 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -73,10 +73,12 @@ jobs: $qtSourceDir = "D:/qt-source" $qtZip = "$qtSourceDir/qt-everywhere-src-6.5.3.zip" if (-Not (Test-Path "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase/configure.bat")) { - Write-Host "Downloading Qt Source" + Write-Host "Cache not found. Downloading Qt Source..." New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir + } else { + Write-Host "Qt source found in cache." } dir "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase" From 16fccd252c7be4c617047a3bdb9a35c16df9eb26 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 22 Nov 2024 02:15:40 +0330 Subject: [PATCH 71/81] github action #95 --- .github/workflows/cmake-multi-platform.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 41a1926..74213e6 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -63,16 +63,16 @@ jobs: if: matrix.os == 'windows-latest' uses: actions/cache@v3 with: - path: D:/qt-source + path: D:\qt-source key: qt-source-6.5.3 - name: Download Qt Source if Cache Miss (Windows) if: matrix.os == 'windows-latest' shell: powershell run: | - $qtSourceDir = "D:/qt-source" - $qtZip = "$qtSourceDir/qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase/configure.bat")) { + $qtSourceDir = "D:\qt-source" + $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { Write-Host "Cache not found. Downloading Qt Source..." New-Item -ItemType Directory -Path $qtSourceDir -Force Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip @@ -80,7 +80,7 @@ jobs: } else { Write-Host "Qt source found in cache." } - dir "$qtSourceDir/qt-everywhere-src-6.5.3/qtbase" + dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" - name: Build and Install Qt from Source (Windows) if: matrix.os == 'windows-latest' @@ -96,7 +96,7 @@ jobs: CALL "%VS_VARS_CMD%" || exit /b 1 REM Build Qt from source - SET QT_SOURCE=D:/qt-source/qt-everywhere-src-6.5.3 + SET QT_SOURCE=D:\qt-source\qt-everywhere-src-6.5.3 IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 ) @@ -134,9 +134,9 @@ jobs: # Build the project - name: Build - run: cmake --build "${{ github.workspace }}/build" --config Release + run: cmake --build "${{ github.workspace }}\build" --config Release # Run tests - name: Test - working-directory: "${{ github.workspace }}/build" + working-directory: "${{ github.workspace }}\build" run: ctest --output-on-failure --build-config Release From fdadff1769ff5e0040e9a7414d1cca4b23f8486a Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 22 Nov 2024 02:22:29 +0330 Subject: [PATCH 72/81] github action #96 --- .github/workflows/cmake-multi-platform.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 74213e6..b53a5ca 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -134,9 +134,9 @@ jobs: # Build the project - name: Build - run: cmake --build "${{ github.workspace }}\build" --config Release + run: cmake --build "${{ github.workspace }}/build" --config Release # Run tests - name: Test - working-directory: "${{ github.workspace }}\build" + working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release From b3e5a17ed265a31180f72b09bb0e0a4adbcaa27b Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 22 Nov 2024 10:16:34 +0330 Subject: [PATCH 73/81] github action #97 --- .github/workflows/cmake-multi-platform.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index b53a5ca..1b67c5c 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -55,7 +55,7 @@ jobs: choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y choco install python3 -y - choco install bison -y + choco install gperf -y choco install llvm -y pip install html5lib @@ -103,7 +103,8 @@ jobs: cd "%QT_SOURCE%\qtbase" call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ -DFEATURE_clang=ON ^ - -DFEATURE_clangcpp=ON || exit /b 1 + -DFEATURE_clangcpp=ON ^ + -DLLVM_INSTALL_DIR="C:\Program Files\LLVM" || exit /b 1 REM Verify if build.ninja exists IF NOT EXIST build.ninja ( From 22c4d0060698ba66aef64bd5e32916ecc93bbcba Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 22 Nov 2024 19:37:48 +0330 Subject: [PATCH 74/81] github action #98 --- .github/workflows/cmake-multi-platform.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 1b67c5c..0479076 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -104,7 +104,8 @@ jobs: call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ -DFEATURE_clang=ON ^ -DFEATURE_clangcpp=ON ^ - -DLLVM_INSTALL_DIR="C:\Program Files\LLVM" || exit /b 1 + -DLLVM_INSTALL_DIR=C:/Program Files/LLVM ^ + -Wno-dev || exit /b 1 REM Verify if build.ninja exists IF NOT EXIST build.ninja ( From 15c4167f684fa0290216d6ac9130c67d04deac48 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Fri, 22 Nov 2024 23:35:02 +0330 Subject: [PATCH 75/81] github action #99 --- .github/workflows/cmake-multi-platform.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 0479076..3264352 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -65,6 +65,7 @@ jobs: with: path: D:\qt-source key: qt-source-6.5.3 + enableCrossOsArchive: false - name: Download Qt Source if Cache Miss (Windows) if: matrix.os == 'windows-latest' @@ -104,7 +105,7 @@ jobs: call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ -DFEATURE_clang=ON ^ -DFEATURE_clangcpp=ON ^ - -DLLVM_INSTALL_DIR=C:/Program Files/LLVM ^ + -DLLVM_INSTALL_DIR="C:/Program Files/LLVM" ^ -Wno-dev || exit /b 1 REM Verify if build.ninja exists From a3f0c7fe8c8076b929c238716f92ef52d6e9ca43 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sat, 23 Nov 2024 16:37:33 +0330 Subject: [PATCH 76/81] github action #100 --- .github/workflows/cmake-multi-platform.yml | 1 + assets/count_text_files.sh | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100755 assets/count_text_files.sh diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 3264352..80bcf7a 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -56,6 +56,7 @@ jobs: choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y choco install python3 -y choco install gperf -y + choco install bison -y choco install llvm -y pip install html5lib diff --git a/assets/count_text_files.sh b/assets/count_text_files.sh new file mode 100755 index 0000000..d75ca37 --- /dev/null +++ b/assets/count_text_files.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Check if a path is provided +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +# Assign the provided path to a variable +DIR="$1" + +# Check if the provided path is a valid directory +if [ ! -d "$DIR" ]; then + echo "Error: $DIR is not a valid directory." + exit 1 +fi + +# Find files, check MIME type, and count text files +total_text_files=$(find "$DIR" -type f -exec file --mime-type {} + | grep -c "text/") + +# Output the result +echo "Total text files in '$DIR' and its subdirectories: $total_text_files" From c2394bc4cbef4d83d776aa396ecbc7df36b3b5a0 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sat, 23 Nov 2024 22:19:32 +0330 Subject: [PATCH 77/81] v0.0.52 --- .github/workflows/cmake-multi-platform.yml | 74 ------ CHANGELOG.md | 5 + CMakeLists.txt | 20 +- CMakeLists.txt.user | 22 +- src/find/find.cpp | 169 +------------ src/find/find.h | 29 +-- src/find/finddialog.cpp | 6 +- src/mainwindow.cpp | 4 +- src/replace/replace.cpp | 62 +---- src/replace/replace.h | 10 +- src/replace/replacedialog.cpp | 18 +- src/search/search.cpp | 272 ++++++++++++++++++--- src/search/search.h | 15 +- src/search/searchoptions.h | 13 +- src/systemfind/systemfinddialog.cpp | 205 ++++++++++------ src/systemfind/systemfinddialog.h | 11 +- src/systemfind/systemfinddialog.ui | 2 +- src/systemreplace/systemreplacedialog.cpp | 6 + src/systemreplace/systemreplacedialog.h | 2 + src/systemsearchresultdialog.cpp | 8 +- src/systemsearchresultdialog.h | 8 +- 21 files changed, 467 insertions(+), 494 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 80bcf7a..3825846 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -54,79 +54,7 @@ jobs: choco install visualstudio2022buildtools -y choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - choco install python3 -y - choco install gperf -y - choco install bison -y - choco install llvm -y - pip install html5lib - - name: Restore Qt Source Cache (Windows) - if: matrix.os == 'windows-latest' - uses: actions/cache@v3 - with: - path: D:\qt-source - key: qt-source-6.5.3 - enableCrossOsArchive: false - - - name: Download Qt Source if Cache Miss (Windows) - if: matrix.os == 'windows-latest' - shell: powershell - run: | - $qtSourceDir = "D:\qt-source" - $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - Write-Host "Cache not found. Downloading Qt Source..." - New-Item -ItemType Directory -Path $qtSourceDir -Force - Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip - Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir - } else { - Write-Host "Qt source found in cache." - } - dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" - - - name: Build and Install Qt from Source (Windows) - if: matrix.os == 'windows-latest' - shell: cmd - run: | - REM Locate Visual Studio Build Tools - FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ - -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i - IF NOT DEFINED VS_PATH ( - echo Visual Studio Build Tools not found! && exit /b 1 - ) - SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" - CALL "%VS_VARS_CMD%" || exit /b 1 - - REM Build Qt from source - SET QT_SOURCE=D:\qt-source\qt-everywhere-src-6.5.3 - IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( - echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 - ) - cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ - -DFEATURE_clang=ON ^ - -DFEATURE_clangcpp=ON ^ - -DLLVM_INSTALL_DIR="C:/Program Files/LLVM" ^ - -Wno-dev || exit /b 1 - - REM Verify if build.ninja exists - IF NOT EXIST build.ninja ( - echo "Error: build.ninja not generated. Check configuration step for issues." && exit /b 1 - ) - - REM Proceed with the build and install steps - ninja || exit /b 1 - ninja install || exit /b 1 - - - name: Set Qt Environment Variables (Windows) - if: matrix.os == 'windows-latest' - shell: powershell - run: | - echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $env:GITHUB_ENV - echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV - echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV - - # Configure CMake - name: Configure CMake run: | cmake -B "${{ github.workspace }}/build" \ @@ -136,11 +64,9 @@ jobs: -G "Ninja" \ -S "${{ github.workspace }}" - # Build the project - name: Build run: cmake --build "${{ github.workspace }}/build" --config Release - # Run tests - name: Test working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release diff --git a/CHANGELOG.md b/CHANGELOG.md index e7bb73e..0c12d13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 0.0.52 + +- Implemented: +- Search Menu -> Find System completed + ## 0.0.51 - Implemented: diff --git a/CMakeLists.txt b/CMakeLists.txt index bfabcca..5ece581 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,31 +73,31 @@ set(PROJECT_SOURCES src/indentation/indentationdialog.h src/indentation/indentationmanager.cpp src/indentation/indentationmanager.h - src/find/finddialog.cpp - src/find/finddialog.h src/replace/replacedialog.cpp src/replace/replacedialog.h src/replace/replace.cpp src/replace/replace.h - src/find/find.cpp - src/find/find.h src/search/search.cpp src/search/search.h src/search/searchoptions.h + src/search/filesearchworker.cpp + src/search/filesearchworker.h + src/find/finddialog.cpp + src/find/finddialog.h + src/find/find.cpp + src/find/find.h + src/systemfind/systemfind.cpp + src/systemfind/systemfind.h src/systemfind/systemfinddialog.cpp src/systemfind/systemfinddialog.h + src/systemfind/richtextdelegate.cpp + src/systemfind/richtextdelegate.h src/systemreplace/systemreplacedialog.cpp src/systemreplace/systemreplacedialog.h - src/systemfind/systemfind.cpp - src/systemfind/systemfind.h src/systemreplace/systemreplace.cpp src/systemreplace/systemreplace.h src/systemsearchresultdialog.cpp src/systemsearchresultdialog.h - src/search/filesearchworker.cpp - src/search/filesearchworker.h - src/systemfind/richtextdelegate.cpp - src/systemfind/richtextdelegate.h src/systemtextdelegate.cpp src/systemtextdelegate.h ${PROJECT_UI} diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index 04850a2..7f1dff6 100755 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -102,14 +102,14 @@ 2 false - -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} + -DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_BUILD_TYPE:STRING=Debug +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} -DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_GENERATOR:STRING=Ninja /data/Code/Qt/Notepad-- 0 /data/Code/Qt/Notepad--/build/Desktop-Debug @@ -160,14 +160,14 @@ 2 false - -DCMAKE_GENERATOR:STRING=Ninja --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} + -DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_BUILD_TYPE:STRING=Release +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} -DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_GENERATOR:STRING=Ninja /data/Code/Qt/Notepad-- /data/Code/Qt/Notepad--/build/Desktop-Release diff --git a/src/find/find.cpp b/src/find/find.cpp index 0569fd9..4a4db51 100644 --- a/src/find/find.cpp +++ b/src/find/find.cpp @@ -1,168 +1,3 @@ -#include "find.h" -#include -#include -#include -#include -#include -#include +#include "../search/search.h" -Find::Find(CodeEditor* editor) - : m_editor(editor), m_cursor(editor ? editor->document() : nullptr) {} - -void Find::setEditor(CodeEditor* editor) { - m_editor = editor; - m_cursor = m_editor ? QTextCursor(m_editor->document()) : QTextCursor(); -} - -void Find::setSearchOptions(const SearchOptions& options) { - m_options = options; -} - -QString Find::expandSpecialCharacters(const QString& input) const { - QString result = input; - - result.replace("\\n", "\n"); - result.replace("\\r", "\r"); - result.replace("\\t", "\t"); - result.replace("\\\\", "\\"); - result.replace("\\0", "\0"); - - qDebug() << "Expanded search keyword:" << result; - return result; -} - -QTextDocument::FindFlags Find::buildFlags(bool backward) const { - QTextDocument::FindFlags flags; - if (m_options.matchCase) { - flags |= QTextDocument::FindCaseSensitively; - } - if (m_options.matchWholeWord) { - flags |= QTextDocument::FindWholeWords; - } - if (backward) { - flags |= QTextDocument::FindBackward; - } - return flags; -} - -bool Find::search(bool backward) { - if (!m_editor) { - qWarning() << "Error: m_editor is null!"; - return false; - } - - QTextDocument::FindFlags flags = buildFlags(backward); - QString keyword = expandSpecialCharacters(m_options.keyword); - - // Perform the search - m_cursor = m_editor->document()->find(keyword, m_cursor, flags); - - bool found = !m_cursor.isNull(); - if (found) { - m_editor->setTextCursor(m_cursor); - } - - return found; -} - -bool Find::findNext() { - return search(false); -} - -bool Find::findPrevious() { - return search(true); -} - -void Find::selectAll() { - if (!m_editor) { - qWarning() << "Error: m_editor is null!"; - return; - } - - QTextDocument* document = m_editor->document(); - QTextCursor cursor(document); - cursor.movePosition(QTextCursor::Start); - QString keyword = expandSpecialCharacters(m_options.keyword); - - QTextDocument::FindFlags flags = buildFlags(false); - QList extraSelections; - - while (true) { - cursor = document->find(keyword, cursor, flags); - - if (cursor.isNull()) { - break; - } - - QTextEdit::ExtraSelection selection; - selection.cursor = cursor; - selection.format.setBackground(Qt::yellow); - extraSelections.append(selection); - } - - m_editor->setExtraSelections(extraSelections); -} - -bool Find::iterateOverTabs(bool backward) { - if (!m_editor) { - qWarning() << "Error: m_editor is null!"; - return false; - } - - // Get the tab widget (DocumentsTab) from the current editor - QTabWidget* tabWidget = m_editor->DocumentsTab(); - if (!tabWidget) { - qWarning() << "Error: No DocumentsTab available!"; - return false; - } - - int tabCount = tabWidget->count(); - if (tabCount == 0) { - qWarning() << "No tabs available for search!"; - return false; - } - - int currentIndex = tabWidget->currentIndex(); - int startIndex = currentIndex; // Store the starting tab to avoid infinite loops - - qDebug() << "Starting search across all tabs. Total tabs:" << tabCount; - - do { - qDebug() << "Switching to tab index:" << currentIndex; - - // Switch to the current tab - tabWidget->setCurrentIndex(currentIndex); - QCoreApplication::processEvents(); // Ensure the UI reflects the active tab change - - // Retrieve the CodeEditor for the active tab - QWidget* currentWidget = tabWidget->currentWidget(); - if (!currentWidget) { - qWarning() << "No widget found in tab index:" << currentIndex; - continue; - } - - CodeEditor* editor = qobject_cast(currentWidget); - if (!editor) { - qWarning() << "Widget is not a CodeEditor at tab index:" << currentIndex; - continue; - } - - // Set the editor for the Find object and reset the cursor - setEditor(editor); - m_cursor = QTextCursor(m_editor->document()); - - qDebug() << "Searching in tab index:" << currentIndex; - if (search(backward)) { - qDebug() << "Match found in tab index:" << currentIndex; - return true; // Stop if a match is found - } - - // Move to the next or previous tab - currentIndex = backward ? (currentIndex - 1 + tabCount) % tabCount - : (currentIndex + 1) % tabCount; - - } while (currentIndex != startIndex); - - qDebug() << "No matches found across all tabs."; - return false; // No matches found -} +class Find : public Search {}; diff --git a/src/find/find.h b/src/find/find.h index 067be31..9baac6b 100644 --- a/src/find/find.h +++ b/src/find/find.h @@ -1,30 +1,9 @@ #pragma once -#include -#include -#include "../codeeditor.h" -#include "../search/searchoptions.h" +#include "../search/search.h" -class Find { -public: - explicit Find(CodeEditor* editor = nullptr); - - void setEditor(CodeEditor* editor); - void setSearchOptions(const SearchOptions& options); - - bool findNext(); // Search forward - bool findPrevious(); // Search backward - void selectAll(); // Highlight all occurrences of the keyword - bool searchAcrossAllTabs(bool backward); - bool iterateOverTabs(bool backward); +class Find : public Search { -private: - QString expandSpecialCharacters(const QString& input) const; - bool performSearch(bool backward); - QTextDocument::FindFlags buildFlags(bool backward) const; - bool search(bool backward); - - CodeEditor* m_editor; - QTextCursor m_cursor; - SearchOptions m_options; +public: + using Search::Search; }; diff --git a/src/find/finddialog.cpp b/src/find/finddialog.cpp index e2a0436..8455ac2 100644 --- a/src/find/finddialog.cpp +++ b/src/find/finddialog.cpp @@ -146,7 +146,7 @@ void FindDialog::on_findNext_clicked() { if (!m_find) return; - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; @@ -161,7 +161,7 @@ void FindDialog::on_findPrevious_clicked() { if (!m_find) return; - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; @@ -176,7 +176,7 @@ void FindDialog::on_selectAll_clicked() { if (!m_find) return; - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 30c59f2..ede93a1 100755 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -314,7 +314,7 @@ bool MainWindow::isSmartIndentChecked() const { void MainWindow::on_actionFind_Next_triggered() { if (!findDialog->getFind()) { - qDebug() << "findDialog is null. Searching for keyword:" << findDialog->getSearchOptions()->keyword; + qDebug() << "findDialog is null."; return; } @@ -324,7 +324,7 @@ void MainWindow::on_actionFind_Next_triggered() void MainWindow::on_actionFind_previoud_triggered() { if (!findDialog->getFind()) { - qDebug() << "findDialog is null. Searching for keyword:" << findDialog->getSearchOptions()->keyword; + qDebug() << "findDialog is null."; return; } diff --git a/src/replace/replace.cpp b/src/replace/replace.cpp index 8348054..ae6d6c8 100644 --- a/src/replace/replace.cpp +++ b/src/replace/replace.cpp @@ -1,62 +1,20 @@ #include "replace.h" -Replace::Replace(CodeEditor* editor) - : Search(editor) {} - bool Replace::replaceNext() { - if (findNext()) { - m_cursor.insertText(m_options.replaceText); // Replace the found text - return true; - } - return false; + m_searchOptions->role = Role::ReplaceNext; + setSearchOptions(*m_searchOptions); + return search(); } bool Replace::replacePrevious() { - if (findPrevious()) { - m_cursor.insertText(m_options.replaceText); // Replace the found text - return true; - } - return false; + m_searchOptions->role = Role::ReplacePrevious; + setSearchOptions(*m_searchOptions); + return search(); } void Replace::replaceAll() { - m_cursor.movePosition(QTextCursor::Start); - while (replaceNext()) { - // Loop to replace all occurrences - } + m_searchOptions->role = Role::ReplaceNext; // Using ReplaceNext to replace all until fixing replaceAll(). + setSearchOptions(*m_searchOptions); + // replaceAll(); // FIXME: replaceAll causes segmentation fault. + while(search()) QCoreApplication::processEvents(); } - -void Replace::selectAll() { - if (!m_editor) { - qWarning() << "Error: m_editor is null!"; - return; - } - - QTextDocument *document = m_editor->document(); - QTextCursor cursor(document); - cursor.movePosition(QTextCursor::Start); - QString keyword = expandSpecialCharacters(m_options.keyword); - - QTextDocument::FindFlags flags; - if (m_options.matchCase) { - flags |= QTextDocument::FindCaseSensitively; - } - if (m_options.matchWholeWord) { - flags |= QTextDocument::FindWholeWords; - } - - QList extraSelections; - - while (!cursor.isNull() && !cursor.atEnd()) { - cursor = document->find(keyword, cursor, flags); - if (!cursor.isNull()) { - QTextEdit::ExtraSelection selection; - selection.cursor = cursor; - selection.format.setBackground(Qt::yellow); // Highlight color - extraSelections.append(selection); - } - } - - m_editor->setExtraSelections(extraSelections); -} - diff --git a/src/replace/replace.h b/src/replace/replace.h index 592126b..11517ac 100644 --- a/src/replace/replace.h +++ b/src/replace/replace.h @@ -1,12 +1,12 @@ #pragma once + #include "../search/search.h" class Replace : public Search { public: - explicit Replace(CodeEditor* editor = nullptr); + using Search::Search; - bool replaceNext(); // Replace and find next occurrence - bool replacePrevious(); // Replace and find previous occurrence - void replaceAll(); // Replace all occurrences in the document - void selectAll(); + bool replaceNext(); + bool replacePrevious(); + void replaceAll(); }; diff --git a/src/replace/replacedialog.cpp b/src/replace/replacedialog.cpp index ce60106..be09a06 100644 --- a/src/replace/replacedialog.cpp +++ b/src/replace/replacedialog.cpp @@ -189,7 +189,7 @@ void ReplaceDialog::on_findNext_clicked() { if (!m_replace) return; - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; @@ -204,7 +204,7 @@ void ReplaceDialog::on_replaceNext_clicked() { if (!m_replace) return; - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; @@ -212,7 +212,7 @@ void ReplaceDialog::on_replaceNext_clicked() saveKeyword(keyword); // Save without modifying UI - QString replaceWith = ui->comboBoxReplace->currentText().trimmed(); + QString replaceWith = ui->comboBoxReplace->currentText(); if (replaceWith.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a replace keyword."); return; @@ -227,7 +227,7 @@ void ReplaceDialog::on_findPrevious_clicked() { if (!m_replace) return; - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; @@ -242,7 +242,7 @@ void ReplaceDialog::on_replacePrevious_clicked() { if (!m_replace) return; - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; @@ -250,7 +250,7 @@ void ReplaceDialog::on_replacePrevious_clicked() saveKeyword(keyword); // Save without modifying UI - QString replaceWith = ui->comboBoxReplace->currentText().trimmed(); + QString replaceWith = ui->comboBoxReplace->currentText(); if (replaceWith.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a replace keyword."); return; @@ -265,7 +265,7 @@ void ReplaceDialog::on_selectAll_clicked() { if (!m_replace) return; - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; @@ -280,7 +280,7 @@ void ReplaceDialog::on_replaceAll_clicked() { if (!m_replace) return; - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; @@ -288,7 +288,7 @@ void ReplaceDialog::on_replaceAll_clicked() saveKeyword(keyword); // Save without modifying UI - QString replaceWith = ui->comboBoxReplace->currentText().trimmed(); + QString replaceWith = ui->comboBoxReplace->currentText(); if (replaceWith.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a replace keyword."); return; diff --git a/src/search/search.cpp b/src/search/search.cpp index 8225bd6..ef2ef09 100644 --- a/src/search/search.cpp +++ b/src/search/search.cpp @@ -1,11 +1,166 @@ #include +#include #include "search.h" #include "../search/searchoptions.h" -Search::Search(CodeEditor* editor) - : m_editor(editor), m_cursor(editor ? editor->document() : nullptr) {} +Search::Search(CodeEditor* editor, SearchOptions* options) + : m_editor(editor) + , m_cursor(editor ? editor->document() : nullptr) + , m_searchOptions(new SearchOptions()) { -Search::~Search() = default; + if (options) m_searchOptions = options; +} + +bool Search::findNext() { + m_searchOptions->role = Role::FindNext; + setSearchOptions(*m_searchOptions); + return search(); +} + +bool Search::findPrevious() { + m_searchOptions->role = Role::FindPrevious; + setSearchOptions(*m_searchOptions); + return search(); +} + +void Search::selectAll() { + m_searchOptions->role = Role::SelectAll; + setSearchOptions(*m_searchOptions); + + if (!m_editor || !m_searchOptions || !m_editor->document()) { + return; // Ensure the editor, options, and document are valid + } + + // Check the role (must be SelectAll) + if (m_searchOptions->role != Role::SelectAll) { + return; // Exit if the role is not SelectAll + } + + QTextDocument* document = m_editor->document(); + QTextCursor cursor(document); + + // Prepare the keyword or regex pattern + QString pattern; + if (m_searchOptions->findMethod == FindMethod::RegularExpression) { + pattern = m_searchOptions->keyword; + } else if (m_searchOptions->findMethod == FindMethod::SpecialCharacters) { + // Handle special characters like \n, \t, \r + pattern = QRegularExpression::escape(m_searchOptions->keyword) + .replace("\\n", "\n").replace("\\t", "\t") + .replace("\\r", "\r").replace("\\0", "\0").replace("\\\\", "\\"); + } else { // Simple text search + pattern = QRegularExpression::escape(m_searchOptions->keyword); + } + + // Add whole word boundaries if needed + if (m_searchOptions->matchWholeWord) { + pattern = "\\b" + pattern + "\\b"; + } + + // Compile the regular expression + QRegularExpression regex(pattern); + if (!regex.isValid()) { + return; // Invalid regex, do nothing + } + + // Case sensitivity + QRegularExpression::PatternOptions regexOptions = QRegularExpression::NoPatternOption; + if (!m_searchOptions->matchCase) { + regexOptions |= QRegularExpression::CaseInsensitiveOption; + } + regex.setPatternOptions(regexOptions); + + // Highlighting format + QTextCharFormat highlightFormat; + highlightFormat.setBackground(Qt::yellow); + highlightFormat.setForeground(Qt::black); + + // Start iterating over the document to find and highlight matches + cursor.movePosition(QTextCursor::Start); // Start from the beginning of the document + while (!cursor.isNull() && !cursor.atEnd()) { + cursor = document->find(regex, cursor); // Find the next match + if (!cursor.isNull()) { + cursor.mergeCharFormat(highlightFormat); // Apply highlight to matched text + } + } +} + +// FIXME: replaceAll causes segmentation fault. +void Search::replaceAll() { + m_searchOptions->role = Role::ReplaceAll; + setSearchOptions(*m_searchOptions); + + if (!m_editor || !m_searchOptions || !m_editor->document()) { + qDebug() << "Editor, search options, or document is invalid."; + return; + } + + QTextDocument* document = m_editor->document(); + if (!document) { + qDebug() << "Document is null."; + return; + } + + QSignalBlocker blocker(m_editor); // Block signals during the operation + + // Extract plain text from the document + QString documentText = document->toPlainText(); + if (documentText.isEmpty()) { + qDebug() << "Document is empty."; + return; + } + + // Prepare the regex pattern + QString pattern; + if (m_searchOptions->findMethod == FindMethod::RegularExpression) { + pattern = m_searchOptions->keyword; + } else if (m_searchOptions->findMethod == FindMethod::SpecialCharacters) { + pattern = QRegularExpression::escape(m_searchOptions->keyword) + .replace("\\n", "\n") + .replace("\\t", "\t") + .replace("\\r", "\r") + .replace("\\0", "\0") + .replace("\\\\", "\\"); + } else { + pattern = QRegularExpression::escape(m_searchOptions->keyword); + } + + if (m_searchOptions->matchWholeWord) { + pattern = "\\b" + pattern + "\\b"; + } + + QRegularExpression regex(pattern); + if (!regex.isValid()) { + qDebug() << "Invalid regex pattern."; + return; + } + + QRegularExpression::PatternOptions regexOptions = QRegularExpression::NoPatternOption; + if (!m_searchOptions->matchCase) { + regexOptions |= QRegularExpression::CaseInsensitiveOption; + } + regex.setPatternOptions(regexOptions); + + QString replacement = m_searchOptions->replaceText; + + // Replace matches in memory + QString updatedText = documentText; + QRegularExpressionMatchIterator it = regex.globalMatch(documentText); + int replaceCount = 0; + + while (it.hasNext()) { + QRegularExpressionMatch match = it.next(); + if (match.hasMatch()) { + updatedText.replace(match.capturedStart(), match.capturedLength(), replacement); + ++replaceCount; + } + } + + // Update the document with the modified text + document->setPlainText(updatedText); + + qDebug() << "Replacement complete. Replaced" << replaceCount << "occurrences."; +} void Search::setEditor(CodeEditor* editor) { m_editor = editor; @@ -13,61 +168,74 @@ void Search::setEditor(CodeEditor* editor) { } void Search::setSearchOptions(const SearchOptions& options) { - m_options = options; + clearHighlights(); + *m_searchOptions = options; } -bool Search::findNext() { - if (!m_editor) { - qWarning() << "Error: m_editor is null!"; - return false; +bool Search::search() { + if (!m_editor || !m_searchOptions || m_cursor.isNull()) { + return false; // Ensure valid editor, cursor, and search options } QTextDocument::FindFlags flags; - if (m_options.matchCase) { - flags |= QTextDocument::FindCaseSensitively; - } - if (m_options.matchWholeWord) { - flags |= QTextDocument::FindWholeWords; - } - QString keyword = m_options.keyword; - m_cursor = m_editor->document()->find(keyword, m_cursor, flags); - - bool found = !m_cursor.isNull(); - if (found) { - m_editor->setTextCursor(m_cursor); + // Determine direction based on Role + if (m_searchOptions->role == Role::FindPrevious || m_searchOptions->role == Role::ReplacePrevious) { + flags |= QTextDocument::FindBackward; // Backward search for previous roles + } else if (m_searchOptions->role == Role::FindNext || m_searchOptions->role == Role::ReplaceNext) { + // No flag needed for forward search (default behavior) } else { - qDebug() << "No further occurrences found."; + return false; // Invalid role for search } - return found; -} + if (m_searchOptions->matchCase) { + flags |= QTextDocument::FindCaseSensitively; // Case sensitivity + } -bool Search::findPrevious() { - if (!m_editor) { - qWarning() << "Error: m_editor is null!"; - return false; + // Prepare the keyword based on FindMethod + QString keyword; + if (m_searchOptions->findMethod == FindMethod::SpecialCharacters) { + keyword = expandSpecialCharacters(m_searchOptions->keyword); + } else if (m_searchOptions->findMethod == FindMethod::RegularExpression) { + keyword = m_searchOptions->keyword; // Use directly for regex + } else { // Simple text search + keyword = QRegularExpression::escape(m_searchOptions->keyword); } - QTextDocument::FindFlags flags = QTextDocument::FindBackward; - if (m_options.matchCase) { - flags |= QTextDocument::FindCaseSensitively; + if (m_searchOptions->matchWholeWord) { + // Add whole word boundaries + keyword = "\\b" + keyword + "\\b"; } - if (m_options.matchWholeWord) { - flags |= QTextDocument::FindWholeWords; + + // Compile regex + QRegularExpression regex(keyword); + if (!regex.isValid()) { + qDebug() << "Invalid regex in search: " << regex; + return false; // Invalid regex, do nothing } + regex.setPatternOptions(m_searchOptions->matchCase ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption); - QString keyword = m_options.keyword; - m_cursor = m_editor->document()->find(keyword, m_cursor, flags); + // Perform the search + QTextCursor resultCursor = m_editor->document()->find(regex, m_cursor, flags); - bool found = !m_cursor.isNull(); - if (found) { - m_editor->setTextCursor(m_cursor); - } else { - qDebug() << "No further occurrences found."; + if (!resultCursor.isNull()) { + // Handle replacement if Role is ReplaceNext or ReplacePrevious + if (m_searchOptions->role == Role::ReplaceNext || m_searchOptions->role == Role::ReplacePrevious) { + if (!m_searchOptions->replaceText.isEmpty()) { + resultCursor.insertText(m_searchOptions->replaceText); + } + } else if (m_searchOptions->role == Role::FindNext || m_searchOptions->role == Role::FindPrevious) { + m_editor->setTextCursor(resultCursor); // Move the cursor for Find roles + } + + // Update m_cursor for the next operation + m_cursor = resultCursor; + + return true; // Match found (and optionally replaced) } - return found; + return false; // No match found } QString Search::expandSpecialCharacters(const QString& input) const { @@ -81,3 +249,27 @@ QString Search::expandSpecialCharacters(const QString& input) const { return result; } +void Search::clearHighlights() { + if (!m_editor || !m_editor->document()) { + return; + } + + QTextDocument* document = m_editor->document(); + QTextCursor cursor(document); + + // Select the entire document + cursor.select(QTextCursor::Document); + + // Create a default format with no background or text color + QTextCharFormat defaultFormat; + defaultFormat.clearBackground(); // Removes background color + defaultFormat.clearForeground(); // Resets text color to default + + // Apply the default format to the entire document + cursor.setCharFormat(defaultFormat); +} + + + + + diff --git a/src/search/search.h b/src/search/search.h index 61005b6..7035067 100644 --- a/src/search/search.h +++ b/src/search/search.h @@ -6,18 +6,25 @@ class Search { public: - explicit Search(CodeEditor* editor = nullptr); - virtual ~Search(); + explicit Search(CodeEditor* editor = nullptr, SearchOptions* options = nullptr); + virtual ~Search() = default; void setSearchOptions(const SearchOptions& options); void setEditor(CodeEditor* editor); // Add setEditor declaration virtual bool findNext(); virtual bool findPrevious(); + virtual void selectAll(); + virtual void replaceAll(); protected: - SearchOptions m_options; - CodeEditor* m_editor; // Editor pointer of type CodeEditor + bool search(); + void clearHighlights(); + + CodeEditor* m_editor; QTextCursor m_cursor; + SearchOptions* m_searchOptions; + +private: QString expandSpecialCharacters(const QString& input) const; }; diff --git a/src/search/searchoptions.h b/src/search/searchoptions.h index 5b06f3e..92bc5d1 100644 --- a/src/search/searchoptions.h +++ b/src/search/searchoptions.h @@ -4,6 +4,16 @@ #include #include +// Enum to represent the role +enum class Role { + FindNext, + FindPrevious, + SelectAll, + ReplaceNext, + ReplacePrevious, + ReplaceAll +}; + // Enum to represent the search method enum class FindMethod { SimpleText, @@ -13,10 +23,11 @@ enum class FindMethod { // Struct to hold search options struct SearchOptions { + Role role; // Search role QString keyword; // The search keyword QString replaceText; // Text to replace with QString location; // The path to look for files - QString pattern; // The comma deliminated file patterns by * and ? + QString pattern; // The regex for file name FindMethod findMethod; // The search method (simple text, regex, special characters) bool matchWholeWord; // Flag to indicate if we match the whole word bool matchCase; // Flag to indicate case sensitivity diff --git a/src/systemfind/systemfinddialog.cpp b/src/systemfind/systemfinddialog.cpp index c8dfa7a..44d9a17 100644 --- a/src/systemfind/systemfinddialog.cpp +++ b/src/systemfind/systemfinddialog.cpp @@ -10,13 +10,12 @@ #include "ui_systemfinddialog.h" #include "../systemsearchresultdialog.h" #include "../settings.h" +#include "../helpers.h" SystemFindDialog::SystemFindDialog(QWidget *parent) - : QDialog(parent) - , ui(new Ui::SystemFindDialog), - m_searchOptions(new SearchOptions()), - m_totalFiles(0), m_processedFiles(0), - m_find(nullptr), m_systemSearchResultDialog(nullptr) + : QDialog(parent), ui(new Ui::SystemFindDialog) + , m_searchOptions(new SearchOptions()), m_files() + , m_processedFiles(0), m_find(nullptr), m_systemSearchResultDialog(nullptr) { ui->setupUi(this); @@ -154,21 +153,21 @@ void SystemFindDialog::savePattern(const QString& pattern) } void SystemFindDialog::saveHistory() { - QString keyword = ui->comboBoxFind->currentText().trimmed(); + QString keyword = ui->comboBoxFind->currentText(); if (keyword.isEmpty()) { QMessageBox::warning(this, "Warning", "Please enter a search keyword."); return; } saveKeyword(keyword); - QString location = ui->comboBoxLocation->currentText().trimmed(); + QString location = ui->comboBoxLocation->currentText(); if (location.isEmpty()) { QMessageBox::warning(this, "Warning", "Please select a location."); return; } saveLocation(location); - QString pattern = ui->comboBoxPattern->currentText().trimmed(); + QString pattern = ui->comboBoxPattern->currentText(); if (!pattern.isEmpty()) { savePattern(pattern); } @@ -222,137 +221,169 @@ void SystemFindDialog::startSearchNext(const SearchOptions& options) { } *m_searchOptions = options; + // Reset processed files count m_processedFiles = 0; - m_totalFiles = 0; - - // Unescape the pattern provided by the user - QString unescapedPattern = m_searchOptions->pattern.replace("\\\\", "\\"); - qDebug() << "Search Options->Unescaped Pattern:" << unescapedPattern; + m_files.clear(); + ui->m_progressBar->setValue(0); - // Declare a static QRegularExpression - static QRegularExpression regex; - if (regex.pattern() != unescapedPattern || !regex.isValid()) { - regex.setPattern(unescapedPattern); + // Compile the regex pattern if it's not empty + QRegularExpression regex; + if (!m_searchOptions->pattern.isEmpty()) { + regex.setPattern(m_searchOptions->pattern); if (!regex.isValid()) { - qWarning() << "Invalid regex pattern:" << regex.errorString(); + qWarning() << "Invalid regex pattern: " << regex.errorString(); return; } + qDebug() << "Using pattern: " << m_searchOptions->pattern; + } else { + qDebug() << "No pattern provided. All files will be considered."; } - ui->m_progressBar->setValue(0); - countTextFiles(m_searchOptions->location, regex); - ui->m_progressBar->setMaximum(m_totalFiles); - + // Prepare flags for QDirIterator QDirIterator::IteratorFlags flags = m_searchOptions->includeSubdirectories ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; - QDirIterator it(m_searchOptions->location, QDir::Files, flags); + QDir::Filters dirFilters = QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot; + + // Process files in the directory + QMimeDatabase mimeDb; + QDirIterator it(m_searchOptions->location, dirFilters, flags); while (it.hasNext()) { QString filePath = it.next(); QString fileName = QFileInfo(filePath).fileName(); + QMimeType mimeType = mimeDb.mimeTypeForFile(filePath); - if (regex.match(fileName).hasMatch()) { + // Match MIME type and (if present) regex pattern + if (mimeType.name().startsWith("text/") && + (m_searchOptions->pattern.isEmpty() || regex.match(fileName).hasMatch())) { + qInfo() << "Matched file: " << filePath; processFile(filePath); } } + + qInfo() << "Search completed. Total processed files: " << m_processedFiles; + ui->m_progressBar->setMaximum(m_processedFiles); } void SystemFindDialog::startSearchPrevious(const SearchOptions& options) { + // Store the search options if (!m_searchOptions) { m_searchOptions = new SearchOptions(); } *m_searchOptions = options; + // Reset processed files count m_processedFiles = 0; - m_totalFiles = 0; - - // Unescape the pattern provided by the user - QString unescapedPattern = m_searchOptions->pattern.replace("\\\\", "\\"); - qDebug() << "[INFO] Search Options->Unescaped Pattern:" << unescapedPattern; + m_files.clear(); + ui->m_progressBar->setValue(0); - // Declare a static QRegularExpression - static QRegularExpression regex; - if (regex.pattern() != unescapedPattern || !regex.isValid()) { - regex.setPattern(unescapedPattern); + // Compile the regex pattern if it's not empty + QRegularExpression regex; + if (!m_searchOptions->pattern.isEmpty()) { + regex.setPattern(m_searchOptions->pattern); if (!regex.isValid()) { - qWarning() << "Invalid regex pattern:" << regex.errorString(); + qWarning() << "Invalid regex pattern: " << regex.errorString(); return; } + qDebug() << "Using pattern: " << m_searchOptions->pattern; + } else { + qDebug() << "No pattern provided. All files will be considered."; } - ui->m_progressBar->setValue(0); - countTextFiles(m_searchOptions->location, regex); - ui->m_progressBar->setMaximum(m_totalFiles); - + // Prepare flags for QDirIterator QDirIterator::IteratorFlags flags = m_searchOptions->includeSubdirectories ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; - // Collect all files matching the pattern - QStringList matchingFiles; - QDirIterator it(m_searchOptions->location, QDir::Files, flags); + QDir::Filters dirFilters = QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot; + + // Collect all matching files in a QList + QMimeDatabase mimeDb; + QList matchingFiles; + + QDirIterator it(m_searchOptions->location, dirFilters, flags); while (it.hasNext()) { QString filePath = it.next(); QString fileName = QFileInfo(filePath).fileName(); - if (regex.match(fileName).hasMatch()) { + QMimeType mimeType = mimeDb.mimeTypeForFile(filePath); + + // Match MIME type and (if present) regex pattern + if (mimeType.name().startsWith("text/") && + (m_searchOptions->pattern.isEmpty() || regex.match(fileName).hasMatch())) { matchingFiles.append(filePath); } } - // Reverse iterate through the list of matching files for "find previous" - for (auto filePath = matchingFiles.crbegin(); filePath != matchingFiles.crend(); ++filePath) { - processFile(*filePath); + // Reverse iterate through the list of matching files + for (auto it = matchingFiles.rbegin(); it != matchingFiles.rend(); ++it) { + QString filePath = *it; + qDebug() << "Processing file (reverse): " << filePath; + processFile(filePath); } + + qInfo() << "Search completed. Total processed files: " << m_processedFiles; + ui->m_progressBar->setMaximum(m_processedFiles); } void SystemFindDialog::selectAll(const SearchOptions& options) { + // Store the search options if (!m_searchOptions) { m_searchOptions = new SearchOptions(); } *m_searchOptions = options; + // Reset processed files count m_processedFiles = 0; - m_totalFiles = 0; - - // Unescape the pattern provided by the user - QString unescapedPattern = m_searchOptions->pattern.replace("\\\\", "\\"); - qDebug() << "Search Options->Unescaped Pattern:" << unescapedPattern; + m_files.clear(); + ui->m_progressBar->setValue(0); - // Declare a static QRegularExpression - static QRegularExpression regex; - if (regex.pattern() != unescapedPattern || !regex.isValid()) { - regex.setPattern(unescapedPattern); + // Compile the regex pattern from SearchOptions->pattern + QRegularExpression regex; + if (!m_searchOptions->pattern.isEmpty()) { + regex.setPattern(m_searchOptions->pattern.replace("\\\\", "\\")); if (!regex.isValid()) { - qWarning() << "Invalid regex pattern:" << regex.errorString(); + qWarning() << "Invalid regex pattern: " << regex.errorString(); return; } + qDebug() << "Using pattern: " << m_searchOptions->pattern; + } else { + qDebug() << "No pattern provided. Selecting all files."; } - ui->m_progressBar->setValue(0); - countTextFiles(m_searchOptions->location, regex); - ui->m_progressBar->setMaximum(m_totalFiles); - + // Prepare flags for QDirIterator to include hidden subdirectories QDirIterator::IteratorFlags flags = m_searchOptions->includeSubdirectories ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; - QDirIterator it(m_searchOptions->location, QDir::Files, flags); + QDir::Filters dirFilters = QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot; + + // Process files in the directory + QMimeDatabase mimeDb; + QDirIterator it(m_searchOptions->location, dirFilters, flags); while (it.hasNext()) { QString filePath = it.next(); QString fileName = QFileInfo(filePath).fileName(); + QMimeType mimeType = mimeDb.mimeTypeForFile(filePath); - if (regex.match(fileName).hasMatch()) { + // Match MIME type and pattern (if provided) + if (mimeType.name().startsWith("text/") && + (m_searchOptions->pattern.isEmpty() || regex.match(fileName).hasMatch())) { + qInfo() << "Selected file: " << filePath; processFile(filePath); } } + + qInfo() << "Select All completed. Total files processed: " << m_processedFiles; } -void SystemFindDialog::countTextFiles(const QString& directory, const QRegularExpression& pattern) { +void SystemFindDialog::countTextFiles(const QString& directory, bool includeSubdirectories, const QRegularExpression& pattern) { QMimeDatabase mimeDb; - QDirIterator it(directory, QDir::Files, QDirIterator::Subdirectories); + QDirIterator::IteratorFlags iteratorFlags = includeSubdirectories ? + QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; + QDirIterator it(directory, QDir::Files, iteratorFlags); while (it.hasNext()) { QString filePath = it.next(); @@ -361,21 +392,30 @@ void SystemFindDialog::countTextFiles(const QString& directory, const QRegularEx // Match file name against the pattern if (mimeType.name().startsWith("text/") && pattern.match(fileName).hasMatch()) { - m_totalFiles++; + m_files.insert(filePath); } } } + void SystemFindDialog::processFile(const QString& filePath) { + m_files.insert(filePath); + qInfo() << "*** Included new file: " << filePath; + + m_processedFiles++; + emit updateProgress(m_processedFiles, m_files.count()); + auto* worker = new FileSearchWorker(filePath, *m_searchOptions); connect(worker, &FileSearchWorker::fileProcessed, this, &SystemFindDialog::handleFileProcessed); m_threadPool.start(worker); } -void SystemFindDialog::handleFileProcessed(const FileSearchResults& result) { - m_processedFiles++; - emit updateProgress(m_processedFiles, m_totalFiles); +void SystemFindDialog::updateProgressDisplay(int processedFiles) { + ui->m_progressBar->setValue(processedFiles); + ui->m_statusLabel->setText(QString("Searching Files... %1/%2").arg(processedFiles).arg(m_files.count())); +} +void SystemFindDialog::handleFileProcessed(const FileSearchResults& result) { // Ensure the result dialog is open in non-modal mode if (!m_systemSearchResultDialog) { m_systemSearchResultDialog = new SystemSearchResultDialog(this); @@ -387,20 +427,22 @@ void SystemFindDialog::handleFileProcessed(const FileSearchResults& result) { m_systemSearchResultDialog->addSearchResult(result); } -// FIXME: ProgressBar doesn't work properly. -void SystemFindDialog::updateProgressDisplay(int processedFiles, int totalFiles) { - ui->m_progressBar->setValue(processedFiles); - ui->m_statusLabel->setText(QString("Searching Files... %1/%2").arg(processedFiles).arg(totalFiles)); -} - void SystemFindDialog::UpdateSearchOptions() { if (!m_searchOptions) return; m_searchOptions->keyword = ui->comboBoxFind->currentText(); m_searchOptions->location = ui->comboBoxLocation->currentText(); m_searchOptions->pattern = ui->comboBoxPattern->currentText(); if (ui->findPlainText->isChecked()) m_searchOptions->findMethod = FindMethod::SimpleText; - if (ui->findRegularExpression->isChecked()) m_searchOptions->findMethod = FindMethod::RegularExpression; - if (ui->findSpecialCharachters->isChecked()) m_searchOptions->findMethod = FindMethod::SpecialCharacters; + if (ui->findRegularExpression->isChecked()){ + if (!Helpers::isValidRegularExpression(ui->comboBoxFind->currentText())) { + QMessageBox::critical(this, "Error", "Invalid RegularExpression."); + } + m_searchOptions->findMethod = FindMethod::RegularExpression; + } + if (ui->findSpecialCharachters->isChecked()) { + Helpers::notImplemented(this); + m_searchOptions->findMethod = FindMethod::SpecialCharacters; + } m_searchOptions->matchWholeWord = ui->matchWholeWord->isChecked(); m_searchOptions->matchCase = ui->matchCase->isChecked(); m_searchOptions->includeSubdirectories = ui->includeSubdirectories->isChecked(); @@ -414,20 +456,25 @@ void SystemFindDialog::UpdateSearchOptions() { void SystemFindDialog::showResultDialog() { if (!m_systemSearchResultDialog) { - // Create and show the dialog in non-modal mode only if it's not already created m_systemSearchResultDialog = new SystemSearchResultDialog(this); m_systemSearchResultDialog->setWindowModality(Qt::NonModal); + + connect(m_systemSearchResultDialog, &SystemSearchResultDialog::dialogClosed, this, [this]() { + m_systemSearchResultDialog = nullptr; + }); + m_systemSearchResultDialog->show(); } else { - // Bring the existing dialog to the front m_systemSearchResultDialog->raise(); m_systemSearchResultDialog->activateWindow(); } + UpdateSearchOptions(); } void SystemFindDialog::on_findNext_clicked() { + m_searchOptions->role = Role::FindNext; UpdateSearchOptions(); saveHistory(); showResultDialog(); @@ -436,6 +483,8 @@ void SystemFindDialog::on_findNext_clicked() void SystemFindDialog::on_findPrevious_clicked() { + m_files.clear(); + m_searchOptions->role = Role::FindPrevious; UpdateSearchOptions(); saveHistory(); showResultDialog(); @@ -444,6 +493,8 @@ void SystemFindDialog::on_findPrevious_clicked() void SystemFindDialog::on_selectAll_clicked() { + m_files.clear(); + m_searchOptions->role = Role::SelectAll; UpdateSearchOptions(); saveHistory(); showResultDialog(); diff --git a/src/systemfind/systemfinddialog.h b/src/systemfind/systemfinddialog.h index cea6627..8bea16c 100644 --- a/src/systemfind/systemfinddialog.h +++ b/src/systemfind/systemfinddialog.h @@ -5,6 +5,7 @@ #include #include #include "systemfind.h" +#include #include "../search/searchoptions.h" #include "../systemsearchresultdialog.h" @@ -41,7 +42,7 @@ class SystemFindDialog : public QDialog private slots: void handleFileProcessed(const FileSearchResults& result); - void updateProgressDisplay(int processedFiles, int totalFiles); + void updateProgressDisplay(int processedFiles); void onAdvancedOptionsToggled(bool checked); @@ -68,14 +69,14 @@ private slots: void saveLocation(const QString& location); void savePattern(const QString& pattern); void saveHistory(); - bool eventFilter(QObject *watched, QEvent *event); + bool eventFilter(QObject *watched, QEvent *event) override; void UpdateSearchOptions(); void showResultDialog(); - void countTextFiles(const QString& directory, const QRegularExpression& pattern); + void countTextFiles(const QString& directory, bool includeSubdirectories, const QRegularExpression& pattern); void processFile(const QString& filePath); - int m_totalFiles = 0; - int m_processedFiles = 0; + QSet m_files; + std::atomic m_processedFiles{0}; QThreadPool m_threadPool; SystemFind* m_find; SystemSearchResultDialog* m_systemSearchResultDialog; diff --git a/src/systemfind/systemfinddialog.ui b/src/systemfind/systemfinddialog.ui index 50b4edb..36333f7 100644 --- a/src/systemfind/systemfinddialog.ui +++ b/src/systemfind/systemfinddialog.ui @@ -71,7 +71,7 @@ - .*\\.txt$, .*\\.cpp$ + ".*\\.txt$" diff --git a/src/systemreplace/systemreplacedialog.cpp b/src/systemreplace/systemreplacedialog.cpp index 5f9efcb..f85f760 100644 --- a/src/systemreplace/systemreplacedialog.cpp +++ b/src/systemreplace/systemreplacedialog.cpp @@ -210,3 +210,9 @@ void SystemReplaceDialog::toggleAdvancedOptions(bool checked) { + +void SystemReplaceDialog::on_findNext_clicked() +{ + +} + diff --git a/src/systemreplace/systemreplacedialog.h b/src/systemreplace/systemreplacedialog.h index 6476389..f8b9471 100644 --- a/src/systemreplace/systemreplacedialog.h +++ b/src/systemreplace/systemreplacedialog.h @@ -20,6 +20,8 @@ private slots: void toggleAdvancedOptions(bool checked); + void on_findNext_clicked(); + private: Ui::SystemReplaceDialog *ui; diff --git a/src/systemsearchresultdialog.cpp b/src/systemsearchresultdialog.cpp index 44fe9fa..b243b39 100644 --- a/src/systemsearchresultdialog.cpp +++ b/src/systemsearchresultdialog.cpp @@ -56,8 +56,10 @@ SystemSearchResultDialog::~SystemSearchResultDialog() delete ui; } -void SystemSearchResultDialog::cleanupResources() { - qInfo() << "Cleaning up resources. Closing window..."; +void SystemSearchResultDialog::closeEvent(QCloseEvent* event) { + emit dialogClosed(); + QDialog::closeEvent(event); + event->accept(); } // TODO: Pass SearchOptions to this function so it can highlight all keywords. @@ -166,3 +168,5 @@ void SystemSearchResultDialog::handleDoubleClick(const QModelIndex &index) { void SystemSearchResultDialog::setSearchOptions(SearchOptions searchOptions) { m_searchOptions = searchOptions; } + + diff --git a/src/systemsearchresultdialog.h b/src/systemsearchresultdialog.h index b8b855c..8dd2293 100644 --- a/src/systemsearchresultdialog.h +++ b/src/systemsearchresultdialog.h @@ -24,14 +24,10 @@ class SystemSearchResultDialog : public QDialog void setSearchOptions(SearchOptions searchOptions); protected: - void closeEvent(QCloseEvent *event) override { - qWarning() << "Window is closing. Cleaning up resources..."; - cleanupResources(); - // Optionally accept or ignore the event - event->accept(); // or event->ignore(); - } + void closeEvent(QCloseEvent *event) override; signals: + void dialogClosed(); void openFileAtMatch(const QString &filePath, int lineNumber); private slots: From 6534474c2a894ac314969cb6260ac2015aaa6b83 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sat, 23 Nov 2024 23:45:02 +0330 Subject: [PATCH 78/81] github action #101 --- .github/workflows/cmake-multi-platform.yml | 145 +++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 3825846..bb72e25 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -70,3 +70,148 @@ jobs: - name: Test working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release +name: CI Build + +on: + push: + branches: [main, dev] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + - os: ubuntu-latest + c_compiler: gcc + cpp_compiler: g++ + - os: macos-latest + c_compiler: clang + cpp_compiler: clang++ + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + ### Ubuntu Dependencies + - name: Install dependencies (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y ninja-build \ + qt6-base-dev qt6-tools-dev qt6-tools-dev-tools \ + qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev + echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV + + ### macOS Dependencies + - name: Install dependencies (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install ninja qt + echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV + + ### Windows Setup + - name: Install dependencies (Windows) + if: matrix.os == 'windows-latest' + shell: powershell + run: | + choco install visualstudio2022buildtools -y + choco install ninja -y + choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y + choco install python3 -y + choco install bison -y + choco install llvm -y + pip install html5lib + + - name: Restore Qt Source Cache (Windows) + if: matrix.os == 'windows-latest' + uses: actions/cache@v3 + with: + path: D:\qt-source + key: qt-source-6.5.3 + enableCrossOsArchive: false + + - name: Download Qt Source if Cache Miss (Windows) + if: matrix.os == 'windows-latest' + shell: powershell + run: | + $qtSourceDir = "D:\qt-source" + $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" + if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { + Write-Host "Cache not found. Downloading Qt Source..." + New-Item -ItemType Directory -Path $qtSourceDir -Force + Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip + Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir + } else { + Write-Host "Qt source found in cache." + } + dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" + + - name: Build and Install Qt from Source (Windows) + if: matrix.os == 'windows-latest' + shell: cmd + run: | + REM Locate Visual Studio Build Tools + FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ + -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i + IF NOT DEFINED VS_PATH ( + echo Visual Studio Build Tools not found! && exit /b 1 + ) + SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" + CALL "%VS_VARS_CMD%" || exit /b 1 + + REM Build Qt from source + SET QT_SOURCE=D:\qt-source\qt-everywhere-src-6.5.3 + IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( + echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 + ) + cd "%QT_SOURCE%\qtbase" + call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ + -DFEATURE_clang=ON ^ + -DFEATURE_clangcpp=ON ^ + -DLLVM_INSTALL_DIR="C:/Program Files/LLVM" ^ + -Wno-dev || exit /b 1 + + REM Verify if build.ninja exists + IF NOT EXIST build.ninja ( + echo "Error: build.ninja not generated. Check configuration step for issues." && exit /b 1 + ) + + REM Proceed with the build and install steps + ninja || exit /b 1 + ninja install || exit /b 1 + + - name: Set Qt Environment Variables (Windows) + if: matrix.os == 'windows-latest' + shell: powershell + run: | + echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $env:GITHUB_ENV + echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV + echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV + + # Configure CMake + - name: Configure CMake + run: | + cmake -B "${{ github.workspace }}/build" \ + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ + -DCMAKE_BUILD_TYPE=Release \ + -G "Ninja" \ + -S "${{ github.workspace }}" + + # Build the project + - name: Build + run: cmake --build "${{ github.workspace }}/build" --config Release + + # Run tests + - name: Test + working-directory: "${{ github.workspace }}/build" + run: ctest --output-on-failure --build-config Release From 7b118e4eed5b7847f3f14e3b1d1ee3dc41f53a25 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sat, 23 Nov 2024 23:47:32 +0330 Subject: [PATCH 79/81] github action #102 --- .github/workflows/cmake-multi-platform.yml | 72 ---------------------- 1 file changed, 72 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index bb72e25..6ef7918 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -1,77 +1,5 @@ name: CI Build -on: - push: - branches: [main, dev] - pull_request: - branches: [main] - -jobs: - build: - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - include: - - os: windows-latest - c_compiler: cl - cpp_compiler: cl - - os: ubuntu-latest - c_compiler: gcc - cpp_compiler: g++ - - os: macos-latest - c_compiler: clang - cpp_compiler: clang++ - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - ### Ubuntu Dependencies - - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get update - sudo apt-get install -y ninja-build \ - qt6-base-dev qt6-tools-dev qt6-tools-dev-tools \ - qt6-l10n-tools libgl1-mesa-dev libglu1-mesa-dev - echo "CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt6" >> $GITHUB_ENV - - ### macOS Dependencies - - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' - run: | - brew install ninja qt - echo "CMAKE_PREFIX_PATH=$(brew --prefix qt)" >> $GITHUB_ENV - - ### Windows Setup - - name: Install dependencies (Windows) - if: matrix.os == 'windows-latest' - shell: powershell - run: | - choco install visualstudio2022buildtools -y - choco install ninja -y - choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - - - name: Configure CMake - run: | - cmake -B "${{ github.workspace }}/build" \ - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ - -DCMAKE_BUILD_TYPE=Release \ - -G "Ninja" \ - -S "${{ github.workspace }}" - - - name: Build - run: cmake --build "${{ github.workspace }}/build" --config Release - - - name: Test - working-directory: "${{ github.workspace }}/build" - run: ctest --output-on-failure --build-config Release -name: CI Build - on: push: branches: [main, dev] From a6b405bb1c4941c3693cb578496b0053f59235d7 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sat, 23 Nov 2024 23:55:10 +0330 Subject: [PATCH 80/81] fix github action #102 --- src/replace/replace.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/replace/replace.cpp b/src/replace/replace.cpp index ae6d6c8..d47ee70 100644 --- a/src/replace/replace.cpp +++ b/src/replace/replace.cpp @@ -1,3 +1,4 @@ +#include #include "replace.h" bool Replace::replaceNext() { From d72ef2ab903e25fd61373eb9f5c289a1a7c46177 Mon Sep 17 00:00:00 2001 From: Remisa Yousefvand Date: Sun, 24 Nov 2024 02:34:23 +0330 Subject: [PATCH 81/81] v0.0.53 --- .github/workflows/cmake-multi-platform.yml | 73 ------------------- CHANGELOG.md | 6 ++ CMakeLists.txt.user | 22 +++--- src/systemfind/systemfinddialog.cpp | 13 +++- src/systemsearchresultdialog.cpp | 82 +++++++++++++++++++++- src/systemsearchresultdialog.h | 1 + 6 files changed, 107 insertions(+), 90 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 6ef7918..3825846 100755 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -54,78 +54,7 @@ jobs: choco install visualstudio2022buildtools -y choco install ninja -y choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System' -y - choco install python3 -y - choco install bison -y - choco install llvm -y - pip install html5lib - - name: Restore Qt Source Cache (Windows) - if: matrix.os == 'windows-latest' - uses: actions/cache@v3 - with: - path: D:\qt-source - key: qt-source-6.5.3 - enableCrossOsArchive: false - - - name: Download Qt Source if Cache Miss (Windows) - if: matrix.os == 'windows-latest' - shell: powershell - run: | - $qtSourceDir = "D:\qt-source" - $qtZip = "$qtSourceDir\qt-everywhere-src-6.5.3.zip" - if (-Not (Test-Path "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase\configure.bat")) { - Write-Host "Cache not found. Downloading Qt Source..." - New-Item -ItemType Directory -Path $qtSourceDir -Force - Invoke-WebRequest -Uri "https://download.qt.io/official_releases/qt/6.5/6.5.3/single/qt-everywhere-src-6.5.3.zip" -OutFile $qtZip - Expand-Archive -Path $qtZip -DestinationPath $qtSourceDir - } else { - Write-Host "Qt source found in cache." - } - dir "$qtSourceDir\qt-everywhere-src-6.5.3\qtbase" - - - name: Build and Install Qt from Source (Windows) - if: matrix.os == 'windows-latest' - shell: cmd - run: | - REM Locate Visual Studio Build Tools - FOR /F "tokens=*" %%i IN ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" ^ - -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') DO SET VS_PATH=%%i - IF NOT DEFINED VS_PATH ( - echo Visual Studio Build Tools not found! && exit /b 1 - ) - SET "VS_VARS_CMD=%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat" - CALL "%VS_VARS_CMD%" || exit /b 1 - - REM Build Qt from source - SET QT_SOURCE=D:\qt-source\qt-everywhere-src-6.5.3 - IF NOT EXIST "%QT_SOURCE%\qtbase\configure.bat" ( - echo "configure.bat not found in %QT_SOURCE%\qtbase" && exit /b 1 - ) - cd "%QT_SOURCE%\qtbase" - call configure.bat -top-level -prefix C:\Qt -release -opensource -confirm-license -nomake examples -nomake tests -platform win32-msvc -cmake-generator Ninja ^ - -DFEATURE_clang=ON ^ - -DFEATURE_clangcpp=ON ^ - -DLLVM_INSTALL_DIR="C:/Program Files/LLVM" ^ - -Wno-dev || exit /b 1 - - REM Verify if build.ninja exists - IF NOT EXIST build.ninja ( - echo "Error: build.ninja not generated. Check configuration step for issues." && exit /b 1 - ) - - REM Proceed with the build and install steps - ninja || exit /b 1 - ninja install || exit /b 1 - - - name: Set Qt Environment Variables (Windows) - if: matrix.os == 'windows-latest' - shell: powershell - run: | - echo "Qt6_DIR=C:\Qt\lib\cmake\Qt6" >> $env:GITHUB_ENV - echo "QT_PLUGIN_PATH=C:\Qt\plugins" >> $env:GITHUB_ENV - echo "QML2_IMPORT_PATH=C:\Qt\qml" >> $env:GITHUB_ENV - - # Configure CMake - name: Configure CMake run: | cmake -B "${{ github.workspace }}/build" \ @@ -135,11 +64,9 @@ jobs: -G "Ninja" \ -S "${{ github.workspace }}" - # Build the project - name: Build run: cmake --build "${{ github.workspace }}/build" --config Release - # Run tests - name: Test working-directory: "${{ github.workspace }}/build" run: ctest --output-on-failure --build-config Release diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c12d13..9530c09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 0.0.53 + +- Implemented: +- Search Menu -> Find System revised + + ## 0.0.52 - Implemented: diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index 7f1dff6..5a9dd14 100755 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -102,14 +102,14 @@ 2 false - -DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} + -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_BUILD_TYPE:STRING=Debug +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} -DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_BUILD_TYPE:STRING=Debug --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake /data/Code/Qt/Notepad-- 0 /data/Code/Qt/Notepad--/build/Desktop-Debug @@ -160,14 +160,14 @@ 2 false - -DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} + -DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_BUILD_TYPE:STRING=Release +-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} +-DCMAKE_GENERATOR:STRING=Ninja -DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} -DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_BUILD_TYPE:STRING=Release --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DCMAKE_GENERATOR:STRING=Ninja +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake /data/Code/Qt/Notepad-- /data/Code/Qt/Notepad--/build/Desktop-Release diff --git a/src/systemfind/systemfinddialog.cpp b/src/systemfind/systemfinddialog.cpp index 44d9a17..bd1144a 100644 --- a/src/systemfind/systemfinddialog.cpp +++ b/src/systemfind/systemfinddialog.cpp @@ -477,18 +477,25 @@ void SystemFindDialog::on_findNext_clicked() m_searchOptions->role = Role::FindNext; UpdateSearchOptions(); saveHistory(); + if (!m_systemSearchResultDialog) { + startSearchNext(*m_searchOptions); + } else { + m_systemSearchResultDialog->traverseKeywords(false); + } showResultDialog(); - startSearchNext(*m_searchOptions); } void SystemFindDialog::on_findPrevious_clicked() { - m_files.clear(); m_searchOptions->role = Role::FindPrevious; UpdateSearchOptions(); saveHistory(); + if (!m_systemSearchResultDialog) { + startSearchPrevious(*m_searchOptions); + } else { + m_systemSearchResultDialog->traverseKeywords(true); + } showResultDialog(); - startSearchPrevious(*m_searchOptions); } void SystemFindDialog::on_selectAll_clicked() diff --git a/src/systemsearchresultdialog.cpp b/src/systemsearchresultdialog.cpp index b243b39..e6bec6f 100644 --- a/src/systemsearchresultdialog.cpp +++ b/src/systemsearchresultdialog.cpp @@ -29,9 +29,10 @@ SystemSearchResultDialog::SystemSearchResultDialog(QWidget *parent) header->setSectionResizeMode(0, QHeaderView::Stretch); // File Path column stretches header->setSectionResizeMode(1, QHeaderView::Interactive); // Matches column fixed but adjustable header->setStretchLastSection(false); + header->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); header->setSectionsMovable(true); - header->resizeSection(0, width() * 0.8); // Set initial size for 80% width for File Path - header->resizeSection(1, width() * 0.2); // Set initial size for 20% width for Matches + header->resizeSection(0, width() * 0.9); // Set initial size for 90% width for File Path + header->resizeSection(1, width() * 0.1); // Set initial size for 10% width for Matches ui->resultTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); ui->resultTreeView->setSelectionMode(QAbstractItemView::SingleSelection); @@ -120,7 +121,6 @@ void SystemSearchResultDialog::addSearchResult(const FileSearchResults &result) } } - // FIXME: Line number is wrong void SystemSearchResultDialog::handleDoubleClick(const QModelIndex &index) { if (!index.isValid()) { @@ -169,4 +169,80 @@ void SystemSearchResultDialog::setSearchOptions(SearchOptions searchOptions) { m_searchOptions = searchOptions; } +void SystemSearchResultDialog::traverseKeywords(bool backward) { + static int currentKeywordIndex = -1; // Tracks the current keyword index + static QModelIndex previousItemIndex; // Tracks the previously highlighted index + + // Reset the highlight of the previous item if it exists + if (previousItemIndex.isValid()) { + QStandardItem* previousItem = m_resultModel->itemFromIndex(previousItemIndex); + if (previousItem) { + QString originalText = previousItem->data(Qt::UserRole + 1).toString(); + if (!originalText.isEmpty()) { + previousItem->setData(originalText, Qt::EditRole); // Restore original text + } + } + } + + // Count total matches to handle wraparound + int totalMatches = 0; + for (int row = 0; row < m_resultModel->rowCount(); ++row) { + QStandardItem* fileItem = m_resultModel->item(row, 0); + if (!fileItem) continue; + totalMatches += fileItem->rowCount(); + } + + // Adjust the keyword index based on the traversal direction + if (backward) { + currentKeywordIndex--; + if (currentKeywordIndex < 0) { + currentKeywordIndex = totalMatches - 1; // Wrap around to the last match + } + } else { + currentKeywordIndex++; + if (currentKeywordIndex >= totalMatches) { + currentKeywordIndex = 0; // Wrap around to the first match + } + } + + // Find and highlight the corresponding match + int matchCounter = 0; + QModelIndex nextItemIndex; + for (int row = 0; row < m_resultModel->rowCount(); ++row) { + QStandardItem* fileItem = m_resultModel->item(row, 0); + if (!fileItem) continue; + for (int subRow = 0; subRow < fileItem->rowCount(); ++subRow) { + QStandardItem* lineItem = fileItem->child(subRow, 0); + if (!lineItem) continue; + + if (matchCounter == currentKeywordIndex) { + nextItemIndex = m_resultModel->indexFromItem(lineItem); + + // Highlight the keyword with a cyan background + QString lineText = lineItem->data(Qt::EditRole).toString(); + QString originalText = lineItem->data(Qt::UserRole + 1).toString(); + if (originalText.isEmpty()) { + originalText = lineText; + lineItem->setData(originalText, Qt::UserRole + 1); // Store original text + } + + QString highlightedLine = originalText; + highlightedLine.replace( + QRegularExpression(QString("\\b%1\\b").arg(QRegularExpression::escape(m_searchOptions.keyword))), + QString("%1").arg(m_searchOptions.keyword)); + + lineItem->setData(highlightedLine, Qt::EditRole); + + // Scroll to and select the highlighted item + ui->resultTreeView->scrollTo(nextItemIndex); + ui->resultTreeView->setCurrentIndex(nextItemIndex); + + previousItemIndex = nextItemIndex; // Save the current item for the next call + return; + } + + matchCounter++; + } + } +} diff --git a/src/systemsearchresultdialog.h b/src/systemsearchresultdialog.h index 8dd2293..dfb9647 100644 --- a/src/systemsearchresultdialog.h +++ b/src/systemsearchresultdialog.h @@ -22,6 +22,7 @@ class SystemSearchResultDialog : public QDialog void addSearchResult(const FileSearchResults &result); void setSearchOptions(SearchOptions searchOptions); + void traverseKeywords(bool backward); protected: void closeEvent(QCloseEvent *event) override;