diff --git a/.github/actions/setup-vcpkg/action.yml b/.github/actions/setup-vcpkg/action.yml new file mode 100644 index 000000000000..b42086db5c39 --- /dev/null +++ b/.github/actions/setup-vcpkg/action.yml @@ -0,0 +1,28 @@ +name: Setup Vcpkg +description: Initialize vcpkg tool, does not checkout the registry + # TODO, set VCPKG_BASE_VERSION based on this + # inputs: + # vcpkg-version: + # description: Enter vcpkg version tag or stable or latest + # required: false + # default: latest + # type: string + +runs: + using: composite + steps: + - name: Setup vcpkg + if: runner.os != 'Windows' + shell: bash + run: | + . <(curl https://aka.ms/vcpkg-init.sh -L) + echo "PATH=$VCPKG_ROOT;$PATH" >> $GITHUB_ENV + + - name: Setup vcpkg + if: runner.os == 'Windows' + shell: powershell + run: | + $env:VCPKG_ROOT = "C:/.vcpkg" + iex (iwr -useb https://aka.ms/vcpkg-init.ps1) + echo "VCPKG_ROOT=$env:VCPKG_ROOT" >> $env:GITHUB_ENV + echo "PATH=$env:VCPKG_ROOT;$env:PATH" >> $env:GITHUB_ENV \ No newline at end of file diff --git a/.github/workflows/windows-qt6.yml b/.github/workflows/windows-qt6.yml new file mode 100644 index 000000000000..8bc0f4a43cd9 --- /dev/null +++ b/.github/workflows/windows-qt6.yml @@ -0,0 +1,112 @@ +--- +name: 🪟 Windows Qt6 +on: + push: + branches: + - master + - release-** + pull_request: + release: + types: ['published'] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + packages: write + +jobs: + build: + name: build (windows) + runs-on: windows-2022 + + steps: + - name: 🐣 Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: 🐩 Install CMake and Ninja + uses: lukka/get-cmake@latest + with: + cmakeVersion: 3.29.2 + + - name: 🧽 Developer Command Prompt for Microsoft Visual C++ + uses: ilammy/msvc-dev-cmd@v1 + with: + # See https://github.com/actions/runner-images/issues/9398 + toolset: 14.39 + + - name: Setup vcpkg + uses: ./.github/actions/setup-vcpkg + + - name: Setup flex/bison + uses: robinraju/release-downloader@v1.10 + with: + repository: 'lexxmark/winflexbison' + fileName: '*.zip' + tag: 'v2.5.24' + extract: true + + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + max-size: 1G + + - name: 🌱 Install dependencies and generate project files + shell: bash + run: | + BUILD_DIR=$( cygpath "${{ github.workspace }}/build" ) + SOURCE_DIR=$( cygpath "${{ github.workspace }}" ) + + cmake -S "${SOURCE_DIR}" \ + -B "${BUILD_DIR}" \ + -G Ninja \ + -D CMAKE_BUILD_TYPE=Release \ + -D WITH_VCPKG=ON \ + -D CREATE_ZIP=ON \ + -D VCPKG_TARGET_TRIPLET=x64-windows-release \ + -D VCPKG_HOST_TRIPLET=x64-windows-release \ + -D WITH_DESKTOP=ON \ + -D WITH_3D=ON \ + -D WITH_BINDINGS=ON \ + -D ENABLE_TESTS=OFF \ + -D BUILD_WITH_QT6=ON \ + -D USE_CCACHE=ON \ + -D FLEX_EXECUTABLE="${SOURCE_DIR}/win_flex.exe" \ + -D BISON_EXECUTABLE="${SOURCE_DIR}/win_bison.exe" \ + -D SIP_BUILD_EXECUTABLE="${BUILD_DIR}\vcpkg_installed\x64-windows-release\tools\python3\Scripts\sip-build.exe" \ + -D PYUIC_PROGRAM="${BUILD_DIR}\vcpkg_installed\x64-windows-release\tools\python3\pyuic5.bat" \ + -D PYRCC_PROGRAM="${BUILD_DIR}\vcpkg_installed\x64-windows-release\tools\python3\pyrcc5.bat" \ + -D CMAKE_C_COMPILER_LAUNCHER=ccache \ + -D CMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -D WITH_QTWEBKIT=OFF \ + -D VCPKG_INSTALL_OPTIONS="--x-buildtrees-root=C:/src" \ + -D NUGET_USERNAME=${{ github.actor }} \ + -D NUGET_TOKEN=${{ secrets.GITHUB_TOKEN }} + + - name: 🌋 Build + shell: bash + run: | + cmake --build "${{ github.workspace }}/build" --config Release + + - name: 📦 Package + shell: bash + run: | + cmake --build "${{ github.workspace }}/build" --target bundle --config Release + + - name: 📑 Upload dep build logs + uses: actions/upload-artifact@v4 + if: failure() + with: + name: build-logs-x64-windows + path: | + C:/src/**/*.log + + - name: 📤 Upload bundle + uses: actions/upload-artifact@v4 + with: + name: qgis-windows-qt6 + path: | + build/*-win64.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index c0c02a97f25d..45392354f7b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,16 @@ endif() # don't relink it only the shared object changes set(CMAKE_LINK_DEPENDS_NO_SHARED ON) +set (WITH_BINDINGS TRUE CACHE BOOL "Determines whether Python bindings should be built") +set (WITH_3D TRUE CACHE BOOL "Determines whether QGIS 3D library should be built") +set (WITH_QGIS_PROCESS TRUE CACHE BOOL "Determines whether the standalone \"qgis_process\" tool should be built") +set (WITH_DESKTOP TRUE CACHE BOOL "Determines whether QGIS desktop should be built") +set (WITH_GUI TRUE CACHE BOOL "Determines whether QGIS GUI library should be built") +set(WITH_VCPKG FALSE CACHE BOOL "Use the vcpkg submodule for dependency management.") + +if(WITH_VCPKG) + include(VcpkgToolchain) +endif() ############################################################# # Project and version set(CPACK_PACKAGE_VERSION_MAJOR "3") @@ -140,7 +150,6 @@ if(WITH_CORE) endif() endforeach (GRASS_SEARCH_VERSION) - set (WITH_GUI TRUE CACHE BOOL "Determines whether QGIS GUI library (and everything built on top of it) should be built") set (WITH_OAUTH2_PLUGIN TRUE CACHE BOOL "Determines whether OAuth2 authentication method plugin should be built") if(WITH_OAUTH2_PLUGIN) @@ -151,7 +160,6 @@ if(WITH_CORE) set (WITH_ANALYSIS TRUE CACHE BOOL "Determines whether QGIS analysis library should be built") - set (WITH_DESKTOP TRUE CACHE BOOL "Determines whether QGIS desktop should be built") if(WITH_DESKTOP) if((WIN32 AND NOT MINGW) OR (UNIX AND NOT APPLE AND NOT ANDROID AND NOT IOS)) @@ -171,17 +179,14 @@ if(WITH_CORE) endif() endif() - set (WITH_3D TRUE CACHE BOOL "Determines whether QGIS 3D library should be built") set (WITH_QUICK FALSE CACHE BOOL "Determines whether QGIS Quick library should be built") - set (WITH_QGIS_PROCESS TRUE CACHE BOOL "Determines whether the standalone \"qgis_process\" tool should be built") set (NATIVE_CRSSYNC_BIN "" CACHE PATH "Path to a natively compiled synccrsdb binary. If set, crssync will not build but use provided bin instead.") mark_as_advanced (NATIVE_CRSSYNC_BIN) # try to configure and build python bindings by default - set (WITH_BINDINGS TRUE CACHE BOOL "Determines whether Python bindings should be built") if (WITH_BINDINGS) # By default bindings will be installed only to QGIS directory # Someone might want to install it to python site-packages directory @@ -1218,39 +1223,8 @@ endif() ############################################################# # Enable packaging if (WITH_CORE) - # Do not warn about runtime libs when building using VS Express - if(NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) - set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON) - endif() - - if(QGIS_INSTALL_SYS_LIBS) - include(InstallRequiredSystemLibraries) - endif() - - set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "QGIS") - set(CPACK_PACKAGE_VENDOR "Open Source Geospatial Foundation") - set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") - set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") - set(CPACK_PACKAGE_INSTALL_DIRECTORY "QGIS ${COMPLETE_VERSION}") - if(WIN32 AND NOT UNIX) - # There is a bug in NSI that does not handle full unix paths properly. Make - # sure there is at least one set of four (4) backslashes. - set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/win_build\\\\sidebar.bmp") - set(CPACK_NSIS_INSTALLED_ICON_NAME "\\\\qgis.exe") - set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} QGIS") - set(CPACK_NSIS_HELP_LINK "http:\\\\\\\\qgis.org") - set(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\qgis.org") - set(CPACK_NSIS_CONTACT "info@qgis.org") - set(CPACK_NSIS_MODIFY_PATH ON) - - # set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS " !include \\\"${CMAKE_SOURCE_DIR}\\\\win_build\\\\extra.nsh\\\"") - else() - #set(CPACK_STRIP_FILES "QGIS") - #set(CPACK_SOURCE_STRIP_FILES "") - endif() - set(CPACK_PACKAGE_EXECUTABLES "qgis" "QGIS") - set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md") - include(CPack) + include(Bundle) + include(VcpkgInstallDeps) endif() if (UNIX AND NOT APPLE) diff --git a/INSTALL.md b/INSTALL.md index b7432de79e78..0c877ef7e6ec 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -36,6 +36,7 @@ Building QGIS from source - step by step * [4.2.1.2. Building the dependencies](#4212-building-the-dependencies) * [4.2.1.3. Cross-Building QGIS](#4213-cross-building-qgis) * [4.2.2. Testing QGIS](#422-testing-qgis) + * [4.3 Building for Qt 6 with VCPKG / Microsoft Visual Studio](#41-building-with-qt6) * [5. Building on MacOS X](#5-building-on-macos-x) * [5.1. Install Developer Tools](#51-install-developer-tools) * [5.2. Install CMake and other build tools](#52-install-cmake-and-other-build-tools) @@ -708,6 +709,13 @@ can also change the build and release directories. Copy and unzip on the Windows machine package produced by the build and launch the qgis binary: no installation is required. +# 4.3 Building with XXX + +- Install Microsoft Visual Studio Community Edition as explained in ... +- Get all dependencies + - Download an SDK + - Build all dependencies yourself + # 5. Building on MacOS X If you want to test QGIS, easiest option is to download and install all-in-one self-containing bundle directly from diff --git a/cmake/Bundle.cmake b/cmake/Bundle.cmake new file mode 100644 index 000000000000..a1ffffd26f4e --- /dev/null +++ b/cmake/Bundle.cmake @@ -0,0 +1,47 @@ +set(CPACK_GENERATOR) +set(CPACK_OUTPUT_CONFIG_FILE "${CMAKE_BINARY_DIR}/BundleConfig.cmake") + +add_custom_target(bundle + COMMAND ${CMAKE_CPACK_COMMAND} "--config" "${CMAKE_BINARY_DIR}/BundleConfig.cmake" + COMMENT "Running CPACK. Please wait..." + DEPENDS qgis) + +if(WIN32 AND NOT UNIX) + set (CREATE_NSIS FALSE CACHE BOOL "Create an installer using NSIS") +endif() +set (CREATE_ZIP FALSE CACHE BOOL "Create a ZIP package") + +# Do not warn about runtime libs when building using VS Express +if(NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) + set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON) +endif() + +if(QGIS_INSTALL_SYS_LIBS) + include(InstallRequiredSystemLibraries) +endif() + +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "QGIS") +set(CPACK_PACKAGE_VENDOR "Open Source Geospatial Foundation") +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "QGIS ${COMPLETE_VERSION}") +set(CPACK_PACKAGE_EXECUTABLES "qgis" "QGIS") +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md") + +if(CREATE_NSIS) + # There is a bug in NSI that does not handle full unix paths properly. Make + # sure there is at least one set of four (4) backslashes. + set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/win_build\\\\sidebar.bmp") + set(CPACK_NSIS_INSTALLED_ICON_NAME "\\\\qgis.exe") + set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} QGIS") + set(CPACK_NSIS_HELP_LINK "http:\\\\\\\\qgis.org") + set(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\qgis.org") + set(CPACK_NSIS_CONTACT "info@qgis.org") + set(CPACK_NSIS_MODIFY_PATH ON) +endif() + +if(CREATE_ZIP) + list(APPEND CPACK_GENERATOR "ZIP") +endif() + +include(CPack) diff --git a/cmake/NuGet.Config.in b/cmake/NuGet.Config.in new file mode 100644 index 000000000000..8b912c3be1e3 --- /dev/null +++ b/cmake/NuGet.Config.in @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/cmake/VcpkgInstallDeps.cmake b/cmake/VcpkgInstallDeps.cmake new file mode 100644 index 000000000000..0d45f584c844 --- /dev/null +++ b/cmake/VcpkgInstallDeps.cmake @@ -0,0 +1,28 @@ +if(NOT WITH_VCPKG) + return() +endif() + +set(VCPKG_BASE_DIR "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}") + +if(MSVC) + # At least python3.dll, qgis_analysis.dll and gsl.dll are missing + # Copy everything + file(GLOB ALL_LIBS + "${VCPKG_BASE_DIR}/bin/*.dll" + ) + install(FILES ${ALL_LIBS} DESTINATION "bin") +endif() + +set(PROJ_DATA_PATH "${VCPKG_BASE_DIR}/share/proj") + +if(NOT EXISTS "${PROJ_DATA_PATH}/proj.db") + message(FATAL_ERROR "proj.db not found at ${PROJ_DATA_PATH}/proj.db") +endif() + +install(DIRECTORY "${PROJ_DATA_PATH}/" DESTINATION "${CMAKE_INSTALL_DATADIR}/proj") +install(DIRECTORY "${VCPKG_BASE_DIR}/share/gdal/" DESTINATION "${CMAKE_INSTALL_DATADIR}/gdal") +install(DIRECTORY "${VCPKG_BASE_DIR}/bin/Qca/" DESTINATION "bin/Qca") # QCA plugins +install(DIRECTORY "${VCPKG_BASE_DIR}/Qt6/" DESTINATION "bin/Qt6") # qt plugins (qml and others) +install(DIRECTORY "${VCPKG_BASE_DIR}/tools/python3/" + DESTINATION "bin" + PATTERN "*.sip" EXCLUDE) diff --git a/cmake/VcpkgToolchain.cmake b/cmake/VcpkgToolchain.cmake new file mode 100644 index 000000000000..cbcf923ceeba --- /dev/null +++ b/cmake/VcpkgToolchain.cmake @@ -0,0 +1,58 @@ +set(NUGET_SOURCE "https://nuget.pkg.github.com/qgis/index.json" CACHE STRING "Nuget source") +set(NUGET_USERNAME "qgis" CACHE STRING "Nuget user") + +# Setup features (dependencies) based on cmake configuration +if(WITH_BINDINGS) + list(APPEND VCPKG_MANIFEST_FEATURES "bindings") +endif() +if(WITH_3D) + list(APPEND VCPKG_MANIFEST_FEATURES "3d") +endif() +if(WITH_GUI) + list(APPEND VCPKG_MANIFEST_FEATURES "gui") +endif() + +# Setup binary cache +if(NOT "${NUGET_TOKEN}" STREQUAL "" AND WIN32) + set(_VCPKG_EXECUTABLE "vcpkg.exe") + + execute_process( + COMMAND ${_VCPKG_EXECUTABLE} fetch nuget + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE _FETCH_NUGET_OUTPUT) + + STRING(REGEX REPLACE "\n" ";" _FETCH_NUGET_OUTPUT "${_FETCH_NUGET_OUTPUT}") + list(GET _FETCH_NUGET_OUTPUT -1 _NUGET_PATH) + + set(_NUGET_EXE ${_NUGET_PATH}) + + set(_CONFIG_PATH "${CMAKE_BINARY_DIR}/github-NuGet.Config") + + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/NuGet.Config.in" + "${_CONFIG_PATH}" + @ONLY) + execute_process( + COMMAND ${_NUGET_EXE} setapikey "${NUGET_TOKEN}" -src ${NUGET_SOURCE} -configfile ${_CONFIG_PATH} + OUTPUT_VARIABLE _OUTPUT + ERROR_VARIABLE _ERROR + RESULT_VARIABLE _RESULT) + if(_RESULT EQUAL 0) + message(STATUS "Setup nuget api key - done") + else() + message(STATUS "Setup nuget api key - failed") + message(STATUS "Output:") + message(STATUS ${_OUTPUT}) + message(STATUS "Error:") + message(STATUS ${_ERROR}) + endif() + + file(TO_NATIVE_PATH "${_CONFIG_PATH}" _CONFIG_PATH_NATIVE) + set(ENV{VCPKG_BINARY_SOURCES} "$ENV{VCPKG_BINARY_SOURCES};nugetconfig,${_CONFIG_PATH_NATIVE},readwrite") +endif() + +set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake") +set(VCPKG_MANIFEST_DIR "${CMAKE_SOURCE_DIR}/vcpkg") +# Copies DLLs built by vcpkg when an install() command is run. +# Only works on Windows and even there not reliably ... +# set(X_VCPKG_APPLOCAL_DEPS_INSTALL ON CACHE BOOL "Copy dependency DLLs on install") diff --git a/external/mdal/frmts/mdal_h2i.cpp b/external/mdal/frmts/mdal_h2i.cpp index 0b2ca0f33dbb..be5b2b6834ad 100644 --- a/external/mdal/frmts/mdal_h2i.cpp +++ b/external/mdal/frmts/mdal_h2i.cpp @@ -137,7 +137,7 @@ bool MDAL::DriverH2i::parseJsonFile( const std::string filePath, MetadataH2i &me metadata.dirPath = MDAL::dirName( filePath ); } - catch ( Json::exception &e ) + catch ( Json::exception & ) { return false; } diff --git a/external/mdal/mdal_utils.cpp b/external/mdal/mdal_utils.cpp index efcbc1b6489a..4691f00b99a8 100644 --- a/external/mdal/mdal_utils.cpp +++ b/external/mdal/mdal_utils.cpp @@ -17,7 +17,9 @@ #include #ifdef _MSC_VER +#ifndef UNICODE #define UNICODE +#endif #include #include #include @@ -1113,12 +1115,12 @@ std::vector MDAL::Library::libraryFilesInDir( const std::string &di { std::vector filesList; #ifdef _WIN32 - WIN32_FIND_DATA data; + WIN32_FIND_DATAA data; HANDLE hFind; std::string pattern = dirPath; pattern.push_back( '*' ); - hFind = FindFirstFile( pattern.c_str(), &data ); + hFind = FindFirstFileA( pattern.c_str(), &data ); if ( hFind == INVALID_HANDLE_VALUE ) return filesList; @@ -1129,7 +1131,7 @@ std::vector MDAL::Library::libraryFilesInDir( const std::string &di if ( !fileName.empty() && fileExtension( fileName ) == ".dll" ) filesList.push_back( fileName ); } - while ( FindNextFile( hFind, &data ) != 0 ); + while ( FindNextFileA( hFind, &data ) != 0 ); FindClose( hFind ); #else @@ -1140,8 +1142,8 @@ std::vector MDAL::Library::libraryFilesInDir( const std::string &di std::string fileName( de->d_name ); if ( !fileName.empty() ) { - std::string extentsion = fileExtension( fileName ); - if ( extentsion == ".so" || extentsion == ".dylib" ) + std::string extension = fileExtension( fileName ); + if ( extension == ".so" || extension == ".dylib" ) filesList.push_back( fileName ); } de = readdir( dir ); @@ -1160,7 +1162,7 @@ bool MDAL::Library::loadLibrary() #ifdef _WIN32 UINT uOldErrorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS ); - d->mLibrary = LoadLibrary( d->mLibraryFile.c_str() ); + d->mLibrary = LoadLibraryA( d->mLibraryFile.c_str() ); SetErrorMode( uOldErrorMode ); #else d->mLibrary = dlopen( d->mLibraryFile.c_str(), RTLD_LAZY ); diff --git a/external/qspatialite/CMakeLists.txt b/external/qspatialite/CMakeLists.txt index 33536dafe913..527f383303c7 100644 --- a/external/qspatialite/CMakeLists.txt +++ b/external/qspatialite/CMakeLists.txt @@ -7,18 +7,18 @@ add_definitions(-DQT_SHARED) include_directories(SYSTEM ${SQLITE3_INCLUDE_DIR} - ${Qt5Sql_PRIVATE_INCLUDE_DIRS} + ${${QT_VERSION_BASE}Sql_PRIVATE_INCLUDE_DIRS} ) -set(QSQLSPATIALITE_SRC qsql_spatialite.cpp smain.cpp) -QT5_WRAP_CPP(QSQLSPATIALITE_SRC qsql_spatialite.h smain.h) +set(QSQLSPATIALITE_SRC qsql_spatialite.cpp smain.cpp qsql_spatialite.h smain.h) add_library(qsqlspatialite SHARED ${QSQLSPATIALITE_SRC}) + target_link_libraries(qsqlspatialite - ${Qt5Core_LIBRARIES} - ${Qt5Sql_LIBRARIES} - spatialite::spatialite - qgis_core + ${QT_VERSION_BASE}::Core + ${QT_VERSION_BASE}::Sql + spatialite::spatialite + qgis_core ) install(TARGETS qsqlspatialite diff --git a/external/qspatialite/qsql_spatialite.cpp b/external/qspatialite/qsql_spatialite.cpp index 0e8f15a25f76..5a75a04748b3 100644 --- a/external/qspatialite/qsql_spatialite.cpp +++ b/external/qspatialite/qsql_spatialite.cpp @@ -632,7 +632,7 @@ bool QSpatiaLiteDriver::open( const QString &db, const QString &, const QString bool openReadOnlyOption = false; bool openUriOption = false; - const auto opts = conOpts.splitRef( QLatin1Char( ';' ) ); + const auto opts = conOpts.split( QLatin1Char( ';' ) ); for ( auto option : opts ) { option = option.trimmed(); diff --git a/external/untwine/api/QgisUntwine_win.cpp b/external/untwine/api/QgisUntwine_win.cpp index 7469655df8f8..47d355ce3675 100644 --- a/external/untwine/api/QgisUntwine_win.cpp +++ b/external/untwine/api/QgisUntwine_win.cpp @@ -28,7 +28,7 @@ bool QgisUntwine::start(Options& options) cmdline += "--" + op.first + " \"" + op.second + "\" "; PROCESS_INFORMATION processInfo; - STARTUPINFO startupInfo; + STARTUPINFOA startupInfo; ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&startupInfo, sizeof(STARTUPINFO)); diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index e9847f5041b6..44f62ba7ea23 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -448,7 +448,11 @@ set(TEST_RCCS ../../tests/testdata/testdata.qrc) if (WIN32) set (QGIS_APP_SRCS ${QGIS_APP_SRCS} main.cpp ${TEST_RCCS}) - set (QGIS_APPMAIN_SRCS mainwin.cpp) + if(BUILD_WITH_QT6) + set (QGIS_APPMAIN_SRCS mainwin.cpp) + else() + set (QGIS_APPMAIN_SRCS mainwinqt5.cpp) + endif() if (NOT MSVC) enable_language(RC) set(CMAKE_RC_COMPILER_INIT ${CMAKE_GENERATOR_RC}) @@ -675,7 +679,7 @@ if (WITH_PDAL) endif() if(MSVC) - install(FILES qgis.ico qgis-mime.ico qgis-qgs.ico qgis-qlr.ico qgis-qml.ico qgis-qpt.ico DESTINATION ${CMAKE_INSTALL_PREFIX}/icons) + install(FILES qgis.ico qgis-mime.ico qgis-qgs.ico qgis-qlr.ico qgis-qml.ico qgis-qpt.ico DESTINATION icons) endif() install(TARGETS qgis_app diff --git a/src/app/main.cpp b/src/app/main.cpp index 5cb8ee81e586..71f0ce0d443d 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -177,10 +177,10 @@ void usage( const QString &appName ) << QStringLiteral( " the PostGIS extension\n" ) ; // OK #ifdef Q_OS_WIN - MessageBox( nullptr, - msg.join( QString() ).toLocal8Bit().constData(), - "QGIS command line options", - MB_OK ); + MessageBoxW( nullptr, + reinterpret_cast( msg.join( QString() ).utf16() ), + L"QGIS command line options", + MB_OK ); #else std::cout << msg.join( QString() ).toLocal8Bit().constData(); #endif @@ -219,7 +219,7 @@ void myPrint( const char *fmt, ... ) #if defined(Q_OS_WIN) char buffer[1024]; vsnprintf( buffer, sizeof buffer, fmt, ap ); - OutputDebugString( buffer ); + OutputDebugStringA( buffer ); #else vfprintf( stderr, fmt, ap ); #endif diff --git a/src/app/mainwin.cpp b/src/app/mainwin.cpp index c90ef7cc88f4..1cb76b18a380 100644 --- a/src/app/mainwin.cpp +++ b/src/app/mainwin.cpp @@ -21,55 +21,55 @@ #include #include -void showError( std::string message, std::string title ) +void showError( std::wstring message, std::wstring title ) { - std::string newmessage = "Oops, looks like an error loading QGIS \n\n Details: \n\n" + message; - MessageBox( + std::wstring newmessage = L"Oops, looks like an error loading QGIS \n\n Details: \n\n" + message; + MessageBoxW( NULL, newmessage.c_str(), title.c_str(), MB_ICONERROR | MB_OK ); - std::cerr << message << std::endl; + std::wcerr << message << std::endl; } -std::string moduleExeBaseName( void ) +std::wstring moduleExeBaseName( void ) { DWORD l = MAX_PATH; - std::unique_ptr filepath; + std::unique_ptr filepath; for ( ;; ) { - filepath.reset( new char[l] ); - if ( GetModuleFileName( nullptr, filepath.get(), l ) < l ) + filepath.reset( new WCHAR[l] ); + if ( GetModuleFileNameW( nullptr, filepath.get(), l ) < l ) break; l += MAX_PATH; } - std::string basename( filepath.get() ); + std::wstring basename( filepath.get() ); return basename; } int CALLBACK WinMain( HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nCmdShow*/ ) { - std::string exename( moduleExeBaseName() ); - std::string basename( exename.substr( 0, exename.size() - 4 ) ); + std::wstring exename( moduleExeBaseName() ); + std::wstring basename( exename.substr( 0, exename.size() - 4 ) ); if ( getenv( "OSGEO4W_ROOT" ) && __argc == 2 && strcmp( __argv[1], "--postinstall" ) == 0 ) { - std::string envfile( basename + ".env" ); + std::wstring envfile( basename + L".env" ); // write or update environment file - if ( _access( envfile.c_str(), 0 ) < 0 || _access( envfile.c_str(), 2 ) == 0 ) + if ( _waccess( envfile.c_str(), 0 ) < 0 || _waccess( envfile.c_str(), 2 ) == 0 ) { - std::list vars; + std::list vars; try { - std::ifstream varfile; - varfile.open( basename + ".vars" ); + std::wifstream varfile; + varfile.open( basename + L".vars" ); - std::string var; + std::wstring var; while ( std::getline( varfile, var ) ) { vars.push_back( var ); @@ -77,28 +77,28 @@ int CALLBACK WinMain( HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPST varfile.close(); } - catch ( std::ifstream::failure &e ) + catch ( std::wifstream::failure &e ) { - std::string message = "Could not read environment variable list " + basename + ".vars" + " [" + e.what() + "]"; - showError( message, "Error loading QGIS" ); + std::wstring message = L"Could not read environment variable list " + basename + L".vars" + L" [" + _wcserror( errno ) + L"]"; + showError( message, L"Error loading QGIS" ); return EXIT_FAILURE; } try { - std::ofstream file; - file.open( envfile, std::ifstream::out ); + std::wofstream file; + file.open( envfile, std::wifstream::out ); - for ( std::list::const_iterator it = vars.begin(); it != vars.end(); ++it ) + for ( std::list::const_iterator it = vars.begin(); it != vars.end(); ++it ) { - if ( getenv( it->c_str() ) ) - file << *it << "=" << getenv( it->c_str() ) << std::endl; + if ( _wgetenv( it->c_str() ) ) + file << *it << "=" << _wgetenv( it->c_str() ) << std::endl; } } - catch ( std::ifstream::failure &e ) + catch ( std::wifstream::failure &e ) { - std::string message = "Could not write environment file " + basename + ".env" + " [" + e.what() + "]"; - showError( message, "Error loading QGIS" ); + std::wstring message = L"Could not write environment file " + basename + L".env" + L" [" + _wcserror( errno ) + L"]"; + showError( message, L"Error loading QGIS" ); return EXIT_FAILURE; } } @@ -108,31 +108,31 @@ int CALLBACK WinMain( HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPST try { - std::ifstream file; - file.open( basename + ".env" ); + std::wifstream file; + file.open( basename + L".env" ); - std::string var; + std::wstring var; while ( std::getline( file, var ) ) { - if ( _putenv( var.c_str() ) < 0 ) + if ( _wputenv( var.c_str() ) < 0 ) { - std::string message = "Could not set environment variable:" + var; - showError( message, "Error loading QGIS" ); + std::wstring message = L"Could not set environment variable:" + var; + showError( message, L"Error loading QGIS" ); return EXIT_FAILURE; } } } - catch ( std::ifstream::failure &e ) + catch ( std::wifstream::failure &e ) { - std::string message = "Could not read environment file " + basename + ".env" + " [" + e.what() + "]"; - showError( message, "Error loading QGIS" ); + std::wstring message = L"Could not read environment file " + basename + L".env" + L" [" + _wcserror( errno ) + L"]"; + showError( message, L"Error loading QGIS" ); return EXIT_FAILURE; } #ifndef _MSC_VER // MinGW #pragma GCC diagnostic ignored "-Wcast-function-type" #endif - HINSTANCE hKernelDLL = LoadLibrary( "kernel32.dll" ); + HINSTANCE hKernelDLL = LoadLibraryW( L"kernel32.dll" ); BOOL ( *SetDefaultDllDirectories )( DWORD ) = hKernelDLL ? reinterpret_cast( GetProcAddress( hKernelDLL, "SetDefaultDllDirectories" ) ) : 0; DLL_DIRECTORY_COOKIE( *AddDllDirectory )( PCWSTR ) = hKernelDLL ? reinterpret_cast( GetProcAddress( hKernelDLL, "AddDllDirectory" ) ) : 0; #ifndef _MSC_VER // MinGW @@ -168,7 +168,7 @@ int CALLBACK WinMain( HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPST #ifdef _MSC_VER - HINSTANCE hGetProcIDDLL = LoadLibrary( "qgis_app.dll" ); + HINSTANCE hGetProcIDDLL = LoadLibraryW( L"qgis_app.dll" ); #else // MinGW HINSTANCE hGetProcIDDLL = LoadLibrary( "libqgis_app.dll" ); @@ -188,9 +188,9 @@ int CALLBACK WinMain( HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPST 0, NULL ); - std::string message = "Could not load qgis_app.dll \n Windows Error: " + std::string( errorText ) - + "\n Help: \n\n Check " + basename + ".env for correct environment paths"; - showError( message, "Error loading QGIS" ); + std::wstring message = L"Could not load qgis_app.dll \n Windows Error: " + std::wstring( errorText ) + + L"\n Help: \n\n Check " + basename + L".env for correct environment paths"; + showError( message, L"Error loading QGIS" ); LocalFree( errorText ); errorText = NULL; @@ -207,7 +207,7 @@ int CALLBACK WinMain( HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPST if ( !realmain ) { - showError( "Could not locate main function in qgis_app.dll", "Error loading QGIS" ); + showError( L"Could not locate main function in qgis_app.dll", L"Error loading QGIS" ); return EXIT_FAILURE; } diff --git a/src/app/mainwinqt5.cpp b/src/app/mainwinqt5.cpp new file mode 100644 index 000000000000..c90ef7cc88f4 --- /dev/null +++ b/src/app/mainwinqt5.cpp @@ -0,0 +1,215 @@ +/*************************************************************************** + mainwin.cpp + --------------------- + begin : February 2017 + copyright : (C) 2017 by Juergen E. Fischer + email : jef at norbit dot de + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#include +#include + +#include +#include +#include +#include +#include + +void showError( std::string message, std::string title ) +{ + std::string newmessage = "Oops, looks like an error loading QGIS \n\n Details: \n\n" + message; + MessageBox( + NULL, + newmessage.c_str(), + title.c_str(), + MB_ICONERROR | MB_OK + ); + std::cerr << message << std::endl; +} + +std::string moduleExeBaseName( void ) +{ + DWORD l = MAX_PATH; + std::unique_ptr filepath; + for ( ;; ) + { + filepath.reset( new char[l] ); + if ( GetModuleFileName( nullptr, filepath.get(), l ) < l ) + break; + + l += MAX_PATH; + } + + std::string basename( filepath.get() ); + return basename; +} + +int CALLBACK WinMain( HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nCmdShow*/ ) +{ + std::string exename( moduleExeBaseName() ); + std::string basename( exename.substr( 0, exename.size() - 4 ) ); + + if ( getenv( "OSGEO4W_ROOT" ) && __argc == 2 && strcmp( __argv[1], "--postinstall" ) == 0 ) + { + std::string envfile( basename + ".env" ); + + // write or update environment file + if ( _access( envfile.c_str(), 0 ) < 0 || _access( envfile.c_str(), 2 ) == 0 ) + { + std::list vars; + + try + { + std::ifstream varfile; + varfile.open( basename + ".vars" ); + + std::string var; + while ( std::getline( varfile, var ) ) + { + vars.push_back( var ); + } + + varfile.close(); + } + catch ( std::ifstream::failure &e ) + { + std::string message = "Could not read environment variable list " + basename + ".vars" + " [" + e.what() + "]"; + showError( message, "Error loading QGIS" ); + return EXIT_FAILURE; + } + + try + { + std::ofstream file; + file.open( envfile, std::ifstream::out ); + + for ( std::list::const_iterator it = vars.begin(); it != vars.end(); ++it ) + { + if ( getenv( it->c_str() ) ) + file << *it << "=" << getenv( it->c_str() ) << std::endl; + } + } + catch ( std::ifstream::failure &e ) + { + std::string message = "Could not write environment file " + basename + ".env" + " [" + e.what() + "]"; + showError( message, "Error loading QGIS" ); + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; + } + + try + { + std::ifstream file; + file.open( basename + ".env" ); + + std::string var; + while ( std::getline( file, var ) ) + { + if ( _putenv( var.c_str() ) < 0 ) + { + std::string message = "Could not set environment variable:" + var; + showError( message, "Error loading QGIS" ); + return EXIT_FAILURE; + } + } + } + catch ( std::ifstream::failure &e ) + { + std::string message = "Could not read environment file " + basename + ".env" + " [" + e.what() + "]"; + showError( message, "Error loading QGIS" ); + return EXIT_FAILURE; + } + +#ifndef _MSC_VER // MinGW +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif + HINSTANCE hKernelDLL = LoadLibrary( "kernel32.dll" ); + BOOL ( *SetDefaultDllDirectories )( DWORD ) = hKernelDLL ? reinterpret_cast( GetProcAddress( hKernelDLL, "SetDefaultDllDirectories" ) ) : 0; + DLL_DIRECTORY_COOKIE( *AddDllDirectory )( PCWSTR ) = hKernelDLL ? reinterpret_cast( GetProcAddress( hKernelDLL, "AddDllDirectory" ) ) : 0; +#ifndef _MSC_VER // MinGW +#pragma GCC diagnostic pop +#endif + + if ( SetDefaultDllDirectories && AddDllDirectory ) + { + SetDefaultDllDirectories( LOAD_LIBRARY_SEARCH_DEFAULT_DIRS ); + + wchar_t windir[MAX_PATH]; + GetWindowsDirectoryW( windir, MAX_PATH ); + wchar_t systemdir[MAX_PATH]; + GetSystemDirectoryW( systemdir, MAX_PATH ); + + wchar_t *path = wcsdup( _wgetenv( L"PATH" ) ); + +#ifdef _UCRT + for ( wchar_t *p = wcstok( path, L";", nullptr ); p; p = wcstok( NULL, L";", nullptr ) ) +#else + for ( wchar_t *p = wcstok( path, L";" ); p; p = wcstok( NULL, L";" ) ) +#endif + { + if ( wcsicmp( p, windir ) == 0 ) + continue; + if ( wcsicmp( p, systemdir ) == 0 ) + continue; + AddDllDirectory( p ); + } + + free( path ); + } + + +#ifdef _MSC_VER + HINSTANCE hGetProcIDDLL = LoadLibrary( "qgis_app.dll" ); +#else +// MinGW + HINSTANCE hGetProcIDDLL = LoadLibrary( "libqgis_app.dll" ); +#endif + + if ( !hGetProcIDDLL ) + { + DWORD error = GetLastError(); + LPTSTR errorText = NULL; + + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), + ( LPTSTR )&errorText, + 0, + NULL ); + + std::string message = "Could not load qgis_app.dll \n Windows Error: " + std::string( errorText ) + + "\n Help: \n\n Check " + basename + ".env for correct environment paths"; + showError( message, "Error loading QGIS" ); + + LocalFree( errorText ); + errorText = NULL; + return EXIT_FAILURE; + } + +#ifndef _MSC_VER // MinGW +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif + int ( *realmain )( int, char *[] ) = ( int ( * )( int, char *[] ) ) GetProcAddress( hGetProcIDDLL, "main" ); +#ifndef _MSC_VER // MinGW +#pragma GCC diagnostic pop +#endif + + if ( !realmain ) + { + showError( "Could not locate main function in qgis_app.dll", "Error loading QGIS" ); + return EXIT_FAILURE; + } + + return realmain( __argc, __argv ); +} diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index c6856c998c8d..4dfb52a021b8 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -13054,7 +13054,7 @@ void QgisApp::openURL( QString url, bool useQgisDocDirectory ) CFRelease( urlRef ); #elif defined(Q_OS_WIN) if ( url.startsWith( "file://", Qt::CaseInsensitive ) ) - ShellExecute( 0, 0, url.mid( 7 ).toLocal8Bit().constData(), 0, 0, SW_SHOWNORMAL ); + ShellExecuteW( 0, 0, reinterpret_cast( url.mid( 7 ).utf16() ), 0, 0, SW_SHOWNORMAL ); else QDesktopServices::openUrl( url ); #else diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 070d417c746f..1b90558d5881 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,13 +1,13 @@ ############################################################ # sources -BISON_TARGET(QgsExpressionParser qgsexpressionparser.yy ${CMAKE_CURRENT_BINARY_DIR}/qgsexpressionparser.cpp COMPILE_FLAGS "-p exp_") +BISON_TARGET(QgsExpressionParser qgsexpressionparser.yy ${CMAKE_CURRENT_BINARY_DIR}/qgsexpressionparser.cpp COMPILE_FLAGS "-p exp_" DEFINES_FILE "${CMAKE_CURRENT_BINARY_DIR}/qgsexpressionparser.h") FLEX_TARGET(QgsExpressionLexer qgsexpressionlexer.ll ${CMAKE_CURRENT_BINARY_DIR}/qgsexpressionlexer.cpp) ADD_FLEX_BISON_DEPENDENCY(QgsExpressionLexer QgsExpressionParser) -BISON_TARGET(QgsSqlStatementParser qgssqlstatementparser.yy ${CMAKE_CURRENT_BINARY_DIR}/qgssqlstatementparser.cpp COMPILE_FLAGS "-p sqlstatement_") +BISON_TARGET(QgsSqlStatementParser qgssqlstatementparser.yy ${CMAKE_CURRENT_BINARY_DIR}/qgssqlstatementparser.cpp COMPILE_FLAGS "-p sqlstatement_" DEFINES_FILE "${CMAKE_CURRENT_BINARY_DIR}/qgssqlstatementparser.h") FLEX_TARGET(QgsSqlStatementLexer qgssqlstatementlexer.ll ${CMAKE_CURRENT_BINARY_DIR}/qgssqlstatementlexer.cpp) ADD_FLEX_BISON_DEPENDENCY(QgsSqlStatementLexer QgsSqlStatementParser) -BISON_TARGET(QgsMeshCalcParser mesh/qgsmeshcalcparser.yy ${CMAKE_CURRENT_BINARY_DIR}/qgsmeshcalcparser.cpp COMPILE_FLAGS "-p mesh_") +BISON_TARGET(QgsMeshCalcParser mesh/qgsmeshcalcparser.yy ${CMAKE_CURRENT_BINARY_DIR}/qgsmeshcalcparser.cpp COMPILE_FLAGS "-p mesh_" DEFINES_FILE "${CMAKE_CURRENT_BINARY_DIR}/qgsmeshcalcparser.h") FLEX_TARGET(QgsMeshCalcLexer mesh/qgsmeshcalclexer.ll ${CMAKE_CURRENT_BINARY_DIR}/qgsmeshcalclexer.cpp) ADD_FLEX_BISON_DEPENDENCY(QgsMeshCalcLexer QgsMeshCalcParser) diff --git a/src/core/mesh/qgsmeshcalclexer.ll b/src/core/mesh/qgsmeshcalclexer.ll index b764872176a6..a469cb586d45 100644 --- a/src/core/mesh/qgsmeshcalclexer.ll +++ b/src/core/mesh/qgsmeshcalclexer.ll @@ -27,7 +27,7 @@ %{ //directly included in the output program #include "qgsmeshcalcnode.h" - #include "qgsmeshcalcparser.hpp" + #include "qgsmeshcalcparser.h" // if not defined, searches for isatty() // which doesn't in MSVC compiler diff --git a/src/core/qgsattributetableconfig.h b/src/core/qgsattributetableconfig.h index ba50862a3312..9daf64a74a2f 100644 --- a/src/core/qgsattributetableconfig.h +++ b/src/core/qgsattributetableconfig.h @@ -48,7 +48,7 @@ class CORE_EXPORT QgsAttributeTableConfig /** * Defines the configuration of a column in the attribute table. */ - struct ColumnConfig + struct CORE_EXPORT ColumnConfig { //! Constructor for ColumnConfig ColumnConfig() = default; diff --git a/src/core/qgsexpressioncontext.cpp b/src/core/qgsexpressioncontext.cpp index b05f99490a5e..8e0b9c2bcedd 100644 --- a/src/core/qgsexpressioncontext.cpp +++ b/src/core/qgsexpressioncontext.cpp @@ -106,7 +106,11 @@ void QgsExpressionContextScope::addVariable( const QgsExpressionContextScope::St bool QgsExpressionContextScope::removeVariable( const QString &name ) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return mVariables.remove( name ); +#else return mVariables.remove( name ) > 0; +#endif } bool QgsExpressionContextScope::hasVariable( const QString &name ) const diff --git a/src/core/qgsexpressionlexer.ll b/src/core/qgsexpressionlexer.ll index d00ce9946aff..7e46463a7e23 100644 --- a/src/core/qgsexpressionlexer.ll +++ b/src/core/qgsexpressionlexer.ll @@ -37,7 +37,7 @@ #include "expression/qgsexpressionnodeimpl.h" #include "qgsexpressionfunction.h" struct expression_parser_context; -#include "qgsexpressionparser.hpp" +#include "qgsexpressionparser.h" #include // if not defined, searches for isatty() diff --git a/src/core/qgsexpressionparser.yy b/src/core/qgsexpressionparser.yy index 80a89b841397..199b81b27401 100644 --- a/src/core/qgsexpressionparser.yy +++ b/src/core/qgsexpressionparser.yy @@ -35,7 +35,7 @@ #define MAX_ERRORS 10 struct expression_parser_context; -#include "qgsexpressionparser.hpp" +#include "qgsexpressionparser.h" //! from lexer typedef void* yyscan_t; diff --git a/src/core/qgssqlstatementlexer.ll b/src/core/qgssqlstatementlexer.ll index f64fa47db9ba..73fccbc0abb1 100644 --- a/src/core/qgssqlstatementlexer.ll +++ b/src/core/qgssqlstatementlexer.ll @@ -31,7 +31,7 @@ #include "qgssqlstatement.h" struct sqlstatement_parser_context; -#include "qgssqlstatementparser.hpp" +#include "qgssqlstatementparser.h" #include // if not defined, searches for isatty() diff --git a/src/core/qgssqlstatementparser.yy b/src/core/qgssqlstatementparser.yy index dc065831edf6..c7ef8f9d4ec9 100644 --- a/src/core/qgssqlstatementparser.yy +++ b/src/core/qgssqlstatementparser.yy @@ -30,7 +30,7 @@ #define YYINCLUDED_STDLIB_H 1 struct sqlstatement_parser_context; -#include "qgssqlstatementparser.hpp" +#include "qgssqlstatementparser.h" //! from lexer typedef void* yyscan_t; diff --git a/src/native/CMakeLists.txt b/src/native/CMakeLists.txt index cedc517814a1..73edb952b1ad 100644 --- a/src/native/CMakeLists.txt +++ b/src/native/CMakeLists.txt @@ -144,7 +144,7 @@ if (UNIX AND NOT APPLE AND NOT ANDROID) target_link_libraries(qgis_native ${QT_VERSION_BASE}::DBus) endif() -if (MSVC) +if (MSVC AND NOT BUILD_WITH_QT6) find_package(${QT_VERSION_BASE}WinExtras) target_link_libraries(qgis_native shell32) diff --git a/src/native/win/qgswinnative.cpp b/src/native/win/qgswinnative.cpp index 008c207a35aa..dbc83f6819b2 100644 --- a/src/native/win/qgswinnative.cpp +++ b/src/native/win/qgswinnative.cpp @@ -23,16 +23,24 @@ #include #include #include +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #include #include #include #include #include +#endif #include "wintoastlib.h" #include #include #include +#ifdef UNICODE +#define _T(x) L##x +#else +#define _T(x) x +#endif + struct LPITEMIDLISTDeleter { @@ -57,6 +65,7 @@ void QgsWinNative::initializeMainWindow( QWindow *window, const QString &version ) { mWindow = window; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if ( mTaskButton ) return; // already initialized! @@ -64,6 +73,7 @@ void QgsWinNative::initializeMainWindow( QWindow *window, mTaskButton->setWindow( window ); mTaskProgress = mTaskButton->progress(); mTaskProgress->setVisible( false ); +#endif QString appName = qgetenv( "QGIS_WIN_APP_NAME" ); if ( appName.isEmpty() ) @@ -126,7 +136,7 @@ void QgsWinNative::showFileProperties( const QString &path ) info.nShow = SW_SHOWNORMAL; info.fMask = SEE_MASK_INVOKEIDLIST; info.lpIDList = pidl.get(); - info.lpVerb = "properties"; + info.lpVerb = _T( "properties" ); ShellExecuteEx( &info ); } @@ -134,24 +144,31 @@ void QgsWinNative::showFileProperties( const QString &path ) void QgsWinNative::showUndefinedApplicationProgress() { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) mTaskProgress->setMaximum( 0 ); mTaskProgress->show(); +#endif } void QgsWinNative::setApplicationProgress( double progress ) { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) mTaskProgress->setMaximum( 100 ); mTaskProgress->show(); mTaskProgress->setValue( static_cast< int >( std::round( progress ) ) ); +#endif } void QgsWinNative::hideApplicationProgress() { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) mTaskProgress->hide(); +#endif } void QgsWinNative::onRecentProjectsChanged( const std::vector &recentProjects ) { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QWinJumpList jumplist; jumplist.recent()->clear(); for ( const RecentProjectProperties &recentProject : recentProjects ) @@ -163,6 +180,7 @@ void QgsWinNative::onRecentProjectsChanged( const std::vectorsetArguments( QStringList( recentProject.path ) ); jumplist.recent()->addItem( newProject ); } +#endif } class NotificationHandler : public WinToastLib::IWinToastHandler @@ -228,7 +246,11 @@ bool QgsWinNative::openTerminalAtPath( const QString &path ) return process.startDetached( &pid ); } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) bool QgsWinNativeEventFilter::nativeEventFilter( const QByteArray &eventType, void *message, long * ) +#else +bool QgsWinNativeEventFilter::nativeEventFilter( const QByteArray &eventType, void *message, qintptr * ) +#endif { static const QByteArray sWindowsGenericMSG{ "windows_generic_MSG" }; if ( !message || eventType != sWindowsGenericMSG ) diff --git a/src/native/win/qgswinnative.h b/src/native/win/qgswinnative.h index 9f0e7479d144..c67902998128 100644 --- a/src/native/win/qgswinnative.h +++ b/src/native/win/qgswinnative.h @@ -15,8 +15,8 @@ * * ***************************************************************************/ -#ifndef QGSMACNATIVE_H -#define QGSMACNATIVE_H +#ifndef QGSWINNATIVE_H +#define QGSWINNATIVE_H #include "qgsnative.h" #include @@ -25,8 +25,10 @@ #include #pragma comment(lib,"Shell32.lib") +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) class QWinTaskbarButton; class QWinTaskbarProgress; +#endif class QWindow; @@ -35,7 +37,11 @@ class QgsWinNativeEventFilter : public QObject, public QAbstractNativeEventFilte Q_OBJECT public: +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) bool nativeEventFilter( const QByteArray &eventType, void *message, long * ) override; +#else + bool nativeEventFilter( const QByteArray &eventType, void *message, qintptr *result ) override; +#endif signals: @@ -70,10 +76,12 @@ class NATIVE_EXPORT QgsWinNative : public QgsNative QWindow *mWindow = nullptr; Capabilities mCapabilities = NativeFilePropertiesDialog | NativeOpenTerminalAtPath; bool mWinToastInitialized = false; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QWinTaskbarButton *mTaskButton = nullptr; QWinTaskbarProgress *mTaskProgress = nullptr; +#endif QgsWinNativeEventFilter *mNativeEventFilter = nullptr; }; -#endif // QGSMACNATIVE_H +#endif // QGSWINNATIVE_H diff --git a/vcpkg/ports/py-qscintilla/fix-static.patch b/vcpkg/ports/py-qscintilla/fix-static.patch new file mode 100644 index 000000000000..ab1cf546d0fc --- /dev/null +++ b/vcpkg/ports/py-qscintilla/fix-static.patch @@ -0,0 +1,29 @@ +diff --git a/src/qscintilla.pro b/src/qscintilla.pro +index 8d0acd2..2246442 100644 +--- a/src/qscintilla.pro ++++ b/src/qscintilla.pro +@@ -37,13 +37,13 @@ CONFIG(debug, debug|release) { + TARGET = qscintilla2_qt$${QT_MAJOR_VERSION} + } + +-macx:!CONFIG(staticlib) { ++macx:!CONFIG(static) { + QMAKE_POST_LINK += install_name_tool -id @rpath/$(TARGET1) $(TARGET) + } + + INCLUDEPATH += . ../scintilla/include ../scintilla/lexlib ../scintilla/src + +-!CONFIG(staticlib) { ++!CONFIG(static) { + DEFINES += QSCINTILLA_MAKE_DLL + + # Comment this in to build a dynamic library supporting multiple +@@ -86,7 +86,7 @@ qsci.files = ../qsci + INSTALLS += qsci + + features.path = $$[QT_HOST_DATA]/mkspecs/features +-CONFIG(staticlib) { ++CONFIG(static) { + features.files = $$PWD/features_staticlib/qscintilla2.prf + } else { + features.files = $$PWD/features/qscintilla2.prf diff --git a/vcpkg/ports/py-qscintilla/portfile.cmake b/vcpkg/ports/py-qscintilla/portfile.cmake new file mode 100644 index 000000000000..7c2ec76ab54b --- /dev/null +++ b/vcpkg/ports/py-qscintilla/portfile.cmake @@ -0,0 +1,62 @@ +vcpkg_download_distfile(ARCHIVE + URLS "https://www.riverbankcomputing.com/static/Downloads/QScintilla/${VERSION}/QScintilla_src-${VERSION}.tar.gz" + FILENAME "QScintilla-${VERSION}.tar.gz" + SHA512 19e2f9e0a14947501c575018df368d24eb7f8c74e74faa5246db36415bf28dc0beee507ed0e73107c02b36a99bbaf55f0ef3349f479d2332e1b92b2c4a32788a +) + +vcpkg_extract_source_archive( + SOURCE_PATH + ARCHIVE ${ARCHIVE} + PATCHES + fix-static.patch +) + +file(RENAME "${SOURCE_PATH}/Python/pyproject-qt5.toml" "${SOURCE_PATH}/Python/pyproject.toml") + +set(SIPBUILD_ARGS + "--qmake" "${CURRENT_INSTALLED_DIR}/tools/Qt6/bin/qmake${VCPKG_HOST_EXECUTABLE_SUFFIX}" + "--api-dir" "${CURRENT_PACKAGES_DIR}/share/Qt6/qsci/api/python" + "--qsci-features-dir" "${SOURCE_PATH}/src/features" + "--qsci-include-dir" "${SITE_PACKAGES}/src" + "--qsci-library-dir" "${SOURCE_PATH}/src" + "--no-make" + "--verbose" + "--build-dir" "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel" + "--target-dir" "${CURRENT_INSTALLED_DIR}/tools/python3/Lib/site-packages/" +) + +# TODO: help it find sip include dirs, manually patched into sipbuild/project.py for now +# "--sip-include-dirs" "${CURRENT_INSTALLED_DIR}/tools/python3/Lib/site-packages/" + +vcpkg_backup_env_variables(VARS PATH) + +vcpkg_add_to_path(PREPEND "${CURRENT_HOST_INSTALLED_DIR}/tools/python3/Scripts/") + +message(STATUS "Running sipbuild...") +vcpkg_execute_required_process( + COMMAND "${PYTHON3}" "-m" "sipbuild.tools.build" ${SIPBUILD_ARGS} + WORKING_DIRECTORY "${SOURCE_PATH}/Python" + LOGNAME "sipbuild-${TARGET_TRIPLET}" +) +message(STATUS "Running sipbuild...finished.") + +# inventory.txt is consumed by the distinfo tool which is run during make and should be run against the package directory +file(TO_NATIVE_PATH "${CURRENT_INSTALLED_DIR}" NATIVE_INSTALLED_DIR) +vcpkg_replace_string("${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/inventory.txt" + "${CURRENT_INSTALLED_DIR}" + "${CURRENT_PACKAGES_DIR}") + vcpkg_replace_string("${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/inventory.txt" + "${NATIVE_INSTALLED_DIR}" + "${CURRENT_PACKAGES_DIR}") + +vcpkg_qmake_build(SKIP_MAKEFILE BUILD_LOGNAME "install" TARGETS "install") + +vcpkg_restore_env_variables(VARS PATH) + +vcpkg_python_test_import(MODULE "PyQt6.Qsci") + +vcpkg_copy_pdbs() + + +# Handle copyright +file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) diff --git a/vcpkg/ports/py-qscintilla/vcpkg.json b/vcpkg/ports/py-qscintilla/vcpkg.json new file mode 100644 index 000000000000..f83167b9637b --- /dev/null +++ b/vcpkg/ports/py-qscintilla/vcpkg.json @@ -0,0 +1,22 @@ +{ + "name": "py-qscintilla", + "version": "2.14.1", + "description": "Python bindings for QScintilla, which is a port to Qt of the Scintilla editing component. Features syntax highlighting, code-completion and much more (Barebone build without python bindings (missing dependeny PyQt) and without QtDesigner plugin)", + "homepage": "https://www.riverbankcomputing.com/software/qscintilla", + "license": "GPL-3.0-or-later", + "supports": "!xbox", + "dependencies": [ + { + "name": "qscintilla" + }, + "py-pyqt6", + { + "name": "vcpkg-python-scripts", + "host": true + }, + { + "name": "vcpkg-qmake", + "host": true + } + ] +} diff --git a/vcpkg/triplets/x64-windows-release.cmake b/vcpkg/triplets/x64-windows-release.cmake new file mode 100644 index 000000000000..755d34d877c9 --- /dev/null +++ b/vcpkg/triplets/x64-windows-release.cmake @@ -0,0 +1,5 @@ +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE dynamic) + +set(VCPKG_BUILD_TYPE release) \ No newline at end of file diff --git a/vcpkg/vcpkg.json b/vcpkg/vcpkg.json new file mode 100644 index 000000000000..144bd0d9cc40 --- /dev/null +++ b/vcpkg/vcpkg.json @@ -0,0 +1,126 @@ +{ + "vcpkg-configuration": { + "default-registry": { + "kind": "git", + "baseline": "090344cfc0b2844466e2251536fbe6c2408e5eb6", + "repository": "https://github.com/microsoft/vcpkg" + }, + "registries": [ + { + "kind": "git", + "baseline": "7d2535039cd5d76570c6fa2822359c16f02a8a0b", + "repository": "https://github.com/open-vcpkg/python-registry", + "packages": [ + "python3", + "py-*", + "gdal", + "swig", + "vcpkg-python-scripts" + ] + } + ], + "overlay-ports": [ + "ports" + ], + "overlay-triplets": [ + "triplets" + ] + }, + "name": "qgis", + "version-string": "current", + "description": "QGIS is a free, open source, cross platform (lin/win/mac) geographical information system (GIS)", + "homepage": "https://qgis.org", + "dependencies": [ + { + "name": "exiv2", + "features": [ + "xmp" + ] + }, + "expat", + { + "name": "gdal", + "default-features": false, + "features": [ + "poppler" + ] + }, + "geos", + "gsl", + "jhasse-poly2tri", + "libpq", + "libspatialindex", + "libspatialite", + { + "name": "libtasn1", + "platform": "ios | osx" + }, + "libxml2", + "libzip", + "pdal", + "proj", + "protobuf", + { + "name": "qca", + "features": [ + "ossl" + ] + }, + "qtbase", + "qtkeychain-qt6", + "qtlocation", + "qtsvg", + "qttools", + "zlib" + ], + "features": { + "3d": { + "description": "Determines whether QGIS 3D library should be built", + "dependencies": [ + "qt3d" + ] + }, + "bindings": { + "description": "Determines whether Python bindings should be built", + "dependencies": [ + { + "name": "gdal", + "features": [ + "python" + ] + }, + "py-pip", + "py-pyqt6", + "py-qscintilla", + "python3" + ] + }, + "gui": { + "description": "Determines whether the QGIS gui should be built", + "dependencies": [ + "qscintilla", + "qtmultimedia", + "qwt" + ] + }, + "opencl": { + "description": "Should OpenCL support be added", + "dependencies": [ + "opencl" + ] + }, + "quick": { + "description": "Build the QGIS quick components for mobile interfaces", + "dependencies": [ + "qtdeclarative", + "qtquickcontrols2" + ] + }, + "server": { + "description": "Determines whether QGIS server should be built", + "dependencies": [ + "fastcgi" + ] + } + } +}