diff --git a/.github/workflows/build-qi-qmp-linux.yml b/.github/workflows/build-qi-qmp-linux.yml index 800f797..a23e8af 100644 --- a/.github/workflows/build-qi-qmp-linux.yml +++ b/.github/workflows/build-qi-qmp-linux.yml @@ -1,12 +1,12 @@ -name: Linux - Build QI-QMP (Qt 6.3.1) +name: Linux - Build QI-QMP on: workflow_call: secrets: - qt_shared_dec_key: - description: 'MEGA decryption key for Qt shared install archive URL' + qt_shared_url: + description: 'MEGA Qt shared install archive URL' required: true - qt_static_dec_key: - description: 'MEGA decryption key for Qt static install archive URL' + qt_static_url: + description: 'MEGA Qt static install archive URL' required: true outputs: qt_shared_artifact_name: @@ -29,10 +29,10 @@ jobs: strategy: matrix: qt_linkage: [shared, static] - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 env: - c_comp: clang - cxx_comp: clang++ + c_comp: clang-12 + cxx_comp: clang++-12 cmake_gen: Ninja Multi-Config outputs: qt_shared_artifact_name: ${{ steps.get_artifact_name.outputs.qt_shared_artifact_name }} @@ -45,22 +45,17 @@ jobs: map: | { "shared": { - "qt_install_name": "qt-Production-6.3.1-linux-clang-x64-shared-release.7z", - "qt_install_url": "https://mega.nz/file/NiIEAITC", - "qt_install_url_key": "${{ secrets.qt_shared_dec_key }}", + "qt_install_url": "${{ secrets.qt_shared_url }}", "artifact_output_var": "qt_shared_artifact_name" }, "static": { - "qt_install_name": "qt-Production-6.3.1-linux-clang-x64-static-release.7z", - "qt_install_url": "https://mega.nz/file/VjJ2CR4R", - "qt_install_url_key": "${{ secrets.qt_static_dec_key }}", + "qt_install_url": "${{ secrets.qt_static_url }}", "artifact_output_var": "qt_static_artifact_name" } } export_to: env,log - name: Set derived variables with shell because GitHub Actions env context sucks run: | - echo "qt_install_dest=${{ env.qt_download_dir }}/${{ env.qt_install_name }}" >> $GITHUB_ENV echo "qi_qmp_package_path=${{ env.qi_qmp_build_dir }}/out/dist" >> $GITHUB_ENV qi_qmp_install_path="${{ env.qi_qmp_build_dir }}/out/install" echo "qi_qmp_install_path=$qi_qmp_install_path" >> $GITHUB_ENV @@ -70,7 +65,7 @@ jobs: uses: actions/cache@v3 with: path: ${{ env.qt_install_dir }} - key: ${{ env.qt_install_name }} + key: ${{ env.qt_install_url }} - name: Install megatools if: steps.cache-qt.outputs.cache-hit != 'true' env: @@ -88,19 +83,19 @@ jobs: run: mkdir -p "${{ env.qt_download_dir }}" - name: Download Qt Install if: steps.cache-qt.outputs.cache-hit != 'true' - run: megatools dl "$qt_install_url#$qt_install_url_key" --path "${{ env.qt_download_dir }}" + run: megatools dl "$qt_install_url" --path "${{ env.qt_download_dir }}" + - name: Determine Qt Install Package Name + if: steps.cache-qt.outputs.cache-hit != 'true' + run: | + qt_install_name=$(ls "${{ env.qt_download_dir }}" | grep "qt-.*7z") + echo "qt_install_dest=${{ env.qt_download_dir }}/$qt_install_name" >> $GITHUB_ENV - name: Extract Qt Install if: steps.cache-qt.outputs.cache-hit != 'true' run: 7z x ${{ env.qt_install_dest }} -o${{ env.qt_install_dir }} - - name: Set clang-12 as preferred - run: | - sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-12 100 - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-12 100 - sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-12 100 - name: Install OpenGL lib run: sudo apt-get install libglu1-mesa-dev - - name: Install XCB-XKB - run: sudo apt-get install libxkbcommon-dev libxcb-xkb-dev + - name: Install XCB Related libs + run: sudo apt-get install libx11-xcb-dev libxkbcommon-dev libxkbcommon-x11-dev libxcb-*-dev - name: Install Doxygen env: doxy_build: doxygen-1.9.4 @@ -116,6 +111,8 @@ jobs: run: sudo apt-get install graphviz - name: Install Ninja run: sudo apt-get install ninja-build + - name: Install Harfbuzz + run: sudo apt-get install libharfbuzz-dev - name: Checkout QI-QMP uses: actions/checkout@v3 with: diff --git a/.github/workflows/build-qi-qmp-windows.yml b/.github/workflows/build-qi-qmp-windows.yml index 1bc1c27..c9302d7 100644 --- a/.github/workflows/build-qi-qmp-windows.yml +++ b/.github/workflows/build-qi-qmp-windows.yml @@ -1,12 +1,12 @@ -name: Windows - Build QI-QMP (Qt 6.3.1) +name: Windows - Build QI-QMP on: workflow_call: secrets: - qt_shared_dec_key: - description: 'MEGA decryption key for Qt shared install archive URL' + qt_shared_url: + description: 'MEGA Qt shared install archive URL' required: true - qt_static_dec_key: - description: 'MEGA decryption key for Qt static install archive URL' + qt_static_url: + description: 'MEGA Qt static install archive URL' required: true outputs: qt_shared_artifact_name: @@ -43,22 +43,17 @@ jobs: map: | { "shared": { - "qt_install_name": "qt-Production-6.3.1-win32-msvc-x64-shared-release.7z", - "qt_install_url": "https://mega.nz/file/QyoQxRiA", - "qt_install_url_key": "${{ secrets.qt_shared_dec_key }}", + "qt_install_url": "${{ secrets.qt_shared_url }}", "artifact_output_var": "qt_shared_artifact_name" }, "static": { - "qt_install_name": "qt-Production-6.3.1-win32-msvc-x64-static-release.7z", - "qt_install_url": "https://mega.nz/file/QupBFJrC", - "qt_install_url_key": "${{ secrets.qt_static_dec_key }}", + "qt_install_url": "${{ secrets.qt_static_url }}", "artifact_output_var": "qt_static_artifact_name" } } export_to: env,log - name: Set derived variables with shell because GitHub Actions env context sucks run: | - echo "qt_install_dest=${{ env.qt_download_dir }}/${{ env.qt_install_name }}" >> $Env:GITHUB_ENV echo "qi_qmp_package_path=${{ env.qi_qmp_build_dir }}/out/dist" >> $Env:GITHUB_ENV $qi_qmp_install_path="${{ env.qi_qmp_build_dir }}/out/install" echo "qi_qmp_install_path=$qi_qmp_install_path" >> $Env:GITHUB_ENV @@ -68,7 +63,7 @@ jobs: uses: actions/cache@v3 with: path: ${{ env.qt_install_dir }} - key: ${{ env.qt_install_name }} + key: ${{ env.qt_install_url }} - name: Install megatools if: steps.cache-qt.outputs.cache-hit != 'true' run: choco install megatools @@ -77,7 +72,12 @@ jobs: run: New-Item -Path "${{ env.qt_download_dir }}" -ItemType "directory" - name: Download Qt Install if: steps.cache-qt.outputs.cache-hit != 'true' - run: megatools dl "${Env:qt_install_url}#${Env:qt_install_url_key}" --path "${{ env.qt_download_dir }}" + run: megatools dl "${Env:qt_install_url}" --path "${{ env.qt_download_dir }}" + - name: Determine Qt Install Package Name + if: steps.cache-qt.outputs.cache-hit != 'true' + run: | + $qt_install_name=(Get-ChildItem -Path "${{ env.qt_download_dir }}" -Name -Filter qt-*.7z) + echo "qt_install_dest=${{ env.qt_download_dir }}/${qt_install_name}" >> $Env:GITHUB_ENV - name: Extract Qt Install if: steps.cache-qt.outputs.cache-hit != 'true' run: 7z x ${{ env.qt_install_dest }} -o${{ env.qt_install_dir }} diff --git a/.github/workflows/master-pull-request-merge-reaction.yml b/.github/workflows/master-pull-request-merge-reaction.yml index 0c37d98..c64fe5e 100644 --- a/.github/workflows/master-pull-request-merge-reaction.yml +++ b/.github/workflows/master-pull-request-merge-reaction.yml @@ -68,8 +68,8 @@ jobs: if: github.event.pull_request.merged == true uses: ./.github/workflows/build-qi-qmp-windows.yml secrets: - qt_shared_dec_key: ${{ secrets.QT_WINDOWS_SHARED_DECRYPT_KEY }} - qt_static_dec_key: ${{ secrets.QT_WINDOWS_STATIC_DECRYPT_KEY }} + qt_shared_url: ${{ secrets.QT_WINDOWS_SHARED_URL }} + qt_static_url: ${{ secrets.QT_WINDOWS_STATIC_URL }} build_qi_qmp_release_linux: name: Build QI-QMP Release (Linux) @@ -77,8 +77,8 @@ jobs: if: github.event.pull_request.merged == true uses: ./.github/workflows/build-qi-qmp-linux.yml secrets: - qt_shared_dec_key: ${{ secrets.QT_LINUX_SHARED_DECRYPT_KEY }} - qt_static_dec_key: ${{ secrets.QT_LINUX_STATIC_DECRYPT_KEY }} + qt_shared_url: ${{ secrets.QT_LINUX_SHARED_URL }} + qt_static_url: ${{ secrets.QT_LINUX_STATIC_URL }} update-docs: name: Update gh-pages diff --git a/.github/workflows/push-reaction.yml b/.github/workflows/push-reaction.yml index 44b928a..d0e19ae 100644 --- a/.github/workflows/push-reaction.yml +++ b/.github/workflows/push-reaction.yml @@ -10,12 +10,12 @@ jobs: name: Build QI-QMP (Windows) uses: ./.github/workflows/build-qi-qmp-windows.yml secrets: - qt_shared_dec_key: ${{ secrets.QT_WINDOWS_SHARED_DECRYPT_KEY }} - qt_static_dec_key: ${{ secrets.QT_WINDOWS_STATIC_DECRYPT_KEY }} + qt_shared_url: ${{ secrets.QT_WINDOWS_SHARED_URL }} + qt_static_url: ${{ secrets.QT_WINDOWS_STATIC_URL }} trigger-linux-build: name: Build QI-QMP (Linux) uses: ./.github/workflows/build-qi-qmp-linux.yml secrets: - qt_shared_dec_key: ${{ secrets.QT_LINUX_SHARED_DECRYPT_KEY }} - qt_static_dec_key: ${{ secrets.QT_LINUX_STATIC_DECRYPT_KEY }} \ No newline at end of file + qt_shared_url: ${{ secrets.QT_LINUX_SHARED_URL }} + qt_static_url: ${{ secrets.QT_LINUX_STATIC_URL }} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b3e9503..d63c3eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ option(QI_QMP_DOCS_TARGET "Build QI-QMP documentation" OFF) # Project # NOTE: DON'T USE TRAILING ZEROS IN VERSIONS -set(QI_QMP_BASE_VERSION 0.1.2.1) # Required for CI/CD +set(QI_QMP_BASE_VERSION 0.1.3) # Required for CI/CD project(QI-QMP VERSION ${QI_QMP_BASE_VERSION} LANGUAGES CXX @@ -113,7 +113,7 @@ find_qt6_package(REQUIRED COMPONENTS ${QT_FIND_COMPONENTS}) # Fetch Qx (build and import from source) include(OB/FetchQx) -fetch_qx("v0.3.1") +fetch_qx("v0.4") # Set lib sources set(INCLUDE_HEADERS diff --git a/include/qi-qmp/qmpi.h b/include/qi-qmp/qmpi.h index 3460e92..2680143 100644 --- a/include/qi-qmp/qmpi.h +++ b/include/qi-qmp/qmpi.h @@ -111,6 +111,7 @@ class Qmpi : public QObject bool stopTransactionTimer(); void reset(); void raiseCommunicationError(CommunicationError error); + void finish(); // Setup void negotiateCapabilities(); diff --git a/src/qmpi.cpp b/src/qmpi.cpp index 1980f56..d02e4c1 100644 --- a/src/qmpi.cpp +++ b/src/qmpi.cpp @@ -116,6 +116,7 @@ Qmpi::Qmpi(quint16 port, QObject* parent) : QObject(parent), mPort(port), + mSocket(this), mState(Disconnected) { // Other init @@ -218,6 +219,12 @@ void Qmpi::raiseCommunicationError(CommunicationError error) mSocket.abort(); } +void Qmpi::finish() +{ + reset(); + emit finished(); +} + void Qmpi::negotiateCapabilities() { changeState(State::Negotiating); @@ -586,6 +593,9 @@ void Qmpi::disconnectFromHost() */ void Qmpi::abort() { + // TODO: May want to have this emit an 'abort' error since QAbstractSocket doesn't do that. + // It would have to be part of CommunicationError + // Bail if already disconnected if(!isConnectionActive()) return; @@ -672,8 +682,23 @@ void Qmpi::handleSocketStateChange(QAbstractSocket::SocketState socketState) break; case QAbstractSocket::SocketState::UnconnectedState: changeState(State::Disconnected); - reset(); - emit finished(); + /* NOTE: The implementation of QAbstractSocket inconstantly fires related stateChanged() and + * errorOccurred() signals, so sometimes an error that caused the socket to change to the + * disconnected state will have its corresponding signal arrive after the state change one, + * meaning that seeing stateChanged(SocketState::UnconnectedState) does not necessarily mean + * the socket is 100% finished and has emitted everything else. To get around this, a + * single shot timer is used to queue `finished()` so that the current routine within + * QAbstractSocket that emitted stateChanged() can finish emitting anything else (since + * they will be via direct connections to here) before the interface emits finished. + * + * This should guarantee that finish() is only emitted after the socket is truly "done", though + * potentially if QAbstractSocket uses internal queued connections and the signals it fires + * after the one that triggered this slot are queued, they would be processed after finished() + * here since it will get queued first. Realistically that shouldn't be the case however. In the + * event this comes to pass, there is no choice but to use the wonky approach that was reverted + * via bfdef954005809a6de527e6dc05b74d1ec51e11f + */ + QTimer::singleShot(0, this, &Qmpi::finish); break; default: break;