diff --git a/.github/workflows/sub_lint.yml b/.github/workflows/sub_lint.yml index f16e21ed34..ab28e819da 100644 --- a/.github/workflows/sub_lint.yml +++ b/.github/workflows/sub_lint.yml @@ -83,7 +83,7 @@ on: -build/endif_comment, +build/explicit_make_pair, -build/forward_decl, - +build/header_guard, + -build/header_guard, +build/include, -build/include_subdir, -build/include_alpha, @@ -91,9 +91,10 @@ on: +build/include_what_you_use, +build/namespaces_headers, +build/namespaces_literals, - +build/namespaces, + -build/namespaces, +build/printf_format, +build/storage_class, + -legal/copyright, +readability/alt_tokens, -readability/braces, +readability/casting, @@ -442,7 +443,7 @@ jobs: blackFails=0 pip install --break-system-packages black set +e - black --check ${{ inputs.changedPythonFiles }} &> ${{ env.logdir }}black.log + black --line-length 100 --check ${{ inputs.changedPythonFiles }} &> ${{ env.logdir }}black.log exitCode=$? set -e # If black has run successfully, write the Log to the console with the Problem Matchers @@ -728,14 +729,19 @@ jobs: - name: Clazy if: inputs.checkClazy && inputs.changedCppFiles != '' && always() continue-on-error: ${{ inputs.clazyFailSilent }} + env: + CLAZY_HEADER_FILTER: "^$" run: | clazyErrors=0 clazyWarnings=0 clazyNotes=0 sudo apt-get install -y --no-install-recommends clazy #TODO: check where this "clazy.yaml" goes ; shall this be put in the fixes ? - # Run clazy on all cpp files - clazy-standalone --export-fixes=clazy.yaml -checks=${{ inputs.clazyChecks }} -p build/ ${{ inputs.changedCppFiles }} &>> ${{ env.logdir }}clazy.log || true + # Run clazy on all changed cpp files, ignoring any included headers + for file in ${{ inputs.changedCppFiles }} + do + clazy-standalone --export-fixes=clazy.yaml -checks=${{ inputs.clazyChecks }} -p build/compile_commands.json $file &>> ${{ env.logdir }}clazy.log || true + done # If clazy has run successfully, write the Log to the console with the Problem Matchers if [ -f ${{ env.logdir }}clazy.log ] then diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 023bc14284..4654bbb76a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,7 +62,7 @@ repos: - id: check-added-large-files - id: mixed-line-ending - repo: https://github.com/psf/black - rev: 1b2427a2b785cc4aac97c19bb4b9a0de063f9547 # frozen: 24.10.0 + rev: 8a737e727ac5ab2f1d4cf5876720ed276dc8dc4b # frozen: 25.1.0 hooks: - id: black args: ['--line-length', '100'] diff --git a/CMakeLists.txt b/CMakeLists.txt index d2c106b426..f4dd28e0c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,7 @@ if(NOT FREECAD_LIBPACK_USE OR FREECAD_LIBPACK_CHECKFILE_CLBUNDLER OR FREECAD_LIB if(BUILD_GUI) SetupCoin3D() + SetupPivy() SetupSpaceball() SetupShibokenAndPyside() SetupMatplotlib() diff --git a/cMake/FindKDL.cmake b/cMake/FindKDL.cmake index 0bc567329c..789d0ffab2 100644 --- a/cMake/FindKDL.cmake +++ b/cMake/FindKDL.cmake @@ -9,7 +9,7 @@ IF ( CMAKE_PKGCONFIG_EXECUTABLE ) MESSAGE( STATUS "Detecting KDL" ) - + SET(ENV{PKG_CONFIG_PATH} "${KDL_INSTALL}/lib/pkgconfig/") MESSAGE( "Looking for KDL in: ${KDL_INSTALL}") PKGCONFIG( "orocos-kdl >= 1.4.0" KDL_FOUND KDL_INCLUDE_DIRS KDL_DEFINES KDL_LINK_DIRS KDL_LIBS ) diff --git a/cMake/FreeCAD_Helpers/CompilerChecksAndSetups.cmake b/cMake/FreeCAD_Helpers/CompilerChecksAndSetups.cmake index feb517c756..9fa104f6df 100644 --- a/cMake/FreeCAD_Helpers/CompilerChecksAndSetups.cmake +++ b/cMake/FreeCAD_Helpers/CompilerChecksAndSetups.cmake @@ -82,6 +82,15 @@ macro(CompilerChecksAndSetups) endif() endif() endif(BUILD_DYNAMIC_LINK_PYTHON) + + if(BUILD_USE_LIBCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + endif() + + if(BUILD_ENABLE_TIME_TRACE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftime-trace") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftime-trace") + endif() endif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX) if(CMAKE_COMPILER_IS_CLANGXX) diff --git a/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake b/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake index 606df314b7..56d95da9a7 100644 --- a/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake +++ b/cMake/FreeCAD_Helpers/InitializeFreeCADBuildOptions.cmake @@ -147,7 +147,7 @@ macro(InitializeFreeCADBuildOptions) set(FREECAD_3DCONNEXION_SUPPORT "NavLib" CACHE STRING "Select version of the 3Dconnexion device integration") set_property(CACHE FREECAD_3DCONNEXION_SUPPORT PROPERTY STRINGS "None" "NavLib" "Legacy" "Both") else(MSVC OR APPLE) - set(FREECAD_USE_3DCONNEXION_LEGACY ON) + option(FREECAD_USE_3DCONNEXION_LEGACY "Enable support for 3Dconnexion devices." ON) endif(MSVC OR APPLE) if(FREECAD_3DCONNEXION_SUPPORT STREQUAL "NavLib") diff --git a/cMake/FreeCAD_Helpers/SetupBoost.cmake b/cMake/FreeCAD_Helpers/SetupBoost.cmake index 0bb1343c3f..4e07e2e7c0 100644 --- a/cMake/FreeCAD_Helpers/SetupBoost.cmake +++ b/cMake/FreeCAD_Helpers/SetupBoost.cmake @@ -3,7 +3,7 @@ macro(SetupBoost) set(_boost_TEST_VERSIONS ${Boost_ADDITIONAL_VERSIONS}) - set (BOOST_COMPONENTS filesystem program_options regex system thread date_time) + set (BOOST_COMPONENTS program_options regex system thread date_time) find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED) diff --git a/cMake/FreeCAD_Helpers/SetupCoin3D.cmake b/cMake/FreeCAD_Helpers/SetupCoin3D.cmake index d271ba8940..ef159ac749 100644 --- a/cMake/FreeCAD_Helpers/SetupCoin3D.cmake +++ b/cMake/FreeCAD_Helpers/SetupCoin3D.cmake @@ -30,6 +30,10 @@ macro(SetupCoin3D) set(COIN3D_MICRO_VERSION "${CMAKE_MATCH_1}") set(COIN3D_VERSION "${COIN3D_MAJOR_VERSION}.${COIN3D_MINOR_VERSION}.${COIN3D_MICRO_VERSION}") ENDIF () +endmacro(SetupCoin3D) + +macro(SetupPivy) + # -------------------------------- Pivy -------------------------------- IF (NOT PIVY_VERSION) message(STATUS "Checking Pivy version by importing it in a Python program...") @@ -44,4 +48,30 @@ macro(SetupCoin3D) endif () ENDIF () -endmacro(SetupCoin3D) + message(STATUS "Checking Pivy Coin3D version by importing it in a Python program...") + execute_process( + COMMAND ${Python3_EXECUTABLE} -c "import pivy as p; print(p.SoDB.getVersion(),end='')" + OUTPUT_VARIABLE PIVY_COIN_VERSION + RESULT_VARIABLE RETURN_CODE) + if (RETURN_CODE EQUAL 0) + message(STATUS "Found Pivy Coin3D ${PIVY_COIN_VERSION}") + else () + message(ERROR "Failed to get Pivy Coin3D version using ${Python3_EXECUTABLE}") + endif () + + if (${PIVY_COIN_VERSION} MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)") + set(PIVY_COIN_MAJOR_VERSION ${CMAKE_MATCH_1}) + set(PIVY_COIN_MINOR_VERSION ${CMAKE_MATCH_2}) + set(PIVY_COIN_MICRO_VERSION ${CMAKE_MATCH_3}) + set(PIVY_COIN_VERSION "${PIVY_COIN_MAJOR_VERSION}.${PIVY_COIN_MINOR_VERSION}.${PIVY_COIN_MICRO_VERSION}") + else () + message(FATAL_ERROR "Failed to match Pivy Coin3D version string output") + endif () + + if (NOT ( + (${COIN3D_MAJOR_VERSION} EQUAL ${PIVY_COIN_MAJOR_VERSION}) AND + (${COIN3D_MINOR_VERSION} EQUAL ${PIVY_COIN_MINOR_VERSION}) AND + (${COIN3D_MICRO_VERSION} EQUAL ${PIVY_COIN_MICRO_VERSION}))) + message(FATAL_ERROR "Coin3D version ${COIN3D_VERSION} mismatches Pivy Coin3D ${PIVY_COIN_VERSION}.") + endif () +endmacro(SetupPivy) diff --git a/cMake/FreeCadMacros.cmake b/cMake/FreeCadMacros.cmake index 351909a1b1..f7ad80837a 100644 --- a/cMake/FreeCadMacros.cmake +++ b/cMake/FreeCadMacros.cmake @@ -126,7 +126,7 @@ ENDMACRO(fc_target_copy_resource_flat) # It would be a bit cleaner to generate these files in ${CMAKE_CURRENT_BINARY_DIR} macro(generate_from_xml BASE_NAME) - set(TOOL_PATH "${CMAKE_SOURCE_DIR}/src/Tools/generate.py") + set(TOOL_PATH "${CMAKE_SOURCE_DIR}/src/Tools/bindings/generate.py") file(TO_NATIVE_PATH "${TOOL_PATH}" TOOL_NATIVE_PATH) file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${BASE_NAME}.xml" SOURCE_NATIVE_PATH) @@ -147,7 +147,7 @@ macro(generate_from_xml BASE_NAME) COMMAND ${PYTHON_EXECUTABLE} "${TOOL_NATIVE_PATH}" --outputPath "${OUTPUT_NATIVE_PATH}" ${BASE_NAME}.xml MAIN_DEPENDENCY "${BASE_NAME}.xml" DEPENDS - "${CMAKE_SOURCE_DIR}/src/Tools/generateTemplates/templateClassPyExport.py" + "${CMAKE_SOURCE_DIR}/src/Tools/bindings/templates/templateClassPyExport.py" "${TOOL_PATH}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMENT "Building ${BASE_NAME}.h/.cpp out of ${BASE_NAME}.xml" diff --git a/contrib/clion/pixi/pixi-default.bash b/contrib/clion/pixi/pixi-default.bash new file mode 100755 index 0000000000..b14ef9cd8c --- /dev/null +++ b/contrib/clion/pixi/pixi-default.bash @@ -0,0 +1,10 @@ +#!/bin/bash + +# Change to the directory of this script (any subdirectory in the repository should work) +cd "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)" + +# If the line above does not work then try uncommenting the line below and insert the absolute path to your FreeCAD repository +# cd "absolute/path/to/FreeCAD" + +# Activate pixi default environment +eval "$(pixi shell-hook)" diff --git a/contrib/clion/pixi/pixi-default.bat b/contrib/clion/pixi/pixi-default.bat new file mode 100644 index 0000000000..559711a83f --- /dev/null +++ b/contrib/clion/pixi/pixi-default.bat @@ -0,0 +1,10 @@ +@echo off +REM Change to the directory of this script (any subdirectory in the repository should work) +cd /d "%~dp0" + +REM Activate pixi default environment +REM Write the output of pixi shell-hook to a temporary batch file and execute it +set TEMP_BATCH_FILE=%TEMP%\pixi_shell_hook_freecad.bat +pixi shell-hook > "%TEMP_BATCH_FILE%" +call "%TEMP_BATCH_FILE%" +del "%TEMP_BATCH_FILE%" \ No newline at end of file diff --git a/src/3rdParty/OndselSolver b/src/3rdParty/OndselSolver index 2e3659c4bc..09d6175a2b 160000 --- a/src/3rdParty/OndselSolver +++ b/src/3rdParty/OndselSolver @@ -1 +1 @@ -Subproject commit 2e3659c4bce3e6885269e0cb3d640261b2a91108 +Subproject commit 09d6175a2ba69e7016fcecc4f384946a2f84f92d diff --git a/src/3rdParty/salomesmesh/src/DriverSTL/SMESH_File.cpp b/src/3rdParty/salomesmesh/src/DriverSTL/SMESH_File.cpp index 481110f4b2..08794202cd 100644 --- a/src/3rdParty/salomesmesh/src/DriverSTL/SMESH_File.cpp +++ b/src/3rdParty/salomesmesh/src/DriverSTL/SMESH_File.cpp @@ -34,9 +34,10 @@ #include #endif -#include +#include +#include -namespace boofs = boost::filesystem; +namespace stdfs = std::filesystem; //================================================================================ /*! @@ -168,8 +169,8 @@ bool SMESH_File::remove() { close(); - boost::system::error_code err; - boofs::remove( _name, err ); + std::error_code err; + stdfs::remove( _name, err ); _error = err.message(); return !err; @@ -185,8 +186,8 @@ long SMESH_File::size() { if ( _size >= 0 ) return _size; // size of an open file - boost::system::error_code err; - boost::uintmax_t size = boofs::file_size( _name, err ); + std::error_code err; + std::uintmax_t size = stdfs::file_size( _name, err ); _error = err.message(); return err ? -1 : (long) size; @@ -200,8 +201,8 @@ long SMESH_File::size() bool SMESH_File::exists() { - boost::system::error_code err; - bool res = boofs::exists( _name, err ); + std::error_code err; + bool res = stdfs::exists( _name, err ); _error = err.message(); return err ? false : res; @@ -215,8 +216,8 @@ bool SMESH_File::exists() bool SMESH_File::isDirectory() { - boost::system::error_code err; - bool res = boofs::is_directory( _name, err ); + std::error_code err; + bool res = stdfs::is_directory( _name, err ); _error = err.message(); return err ? false : res; diff --git a/src/3rdParty/salomesmesh/src/SMESH/DriverGMF.cpp b/src/3rdParty/salomesmesh/src/SMESH/DriverGMF.cpp index f108cbbcb2..372ea90d50 100644 --- a/src/3rdParty/salomesmesh/src/SMESH/DriverGMF.cpp +++ b/src/3rdParty/salomesmesh/src/SMESH/DriverGMF.cpp @@ -25,7 +25,7 @@ #include "DriverGMF.hxx" -#include +#include extern "C" { @@ -55,7 +55,7 @@ namespace DriverGMF bool isExtensionCorrect( const std::string& fileName ) { - std::string ext = boost::filesystem::path(fileName).extension().string(); + std::string ext = std::filesystem::path(fileName).extension().string(); switch ( ext.size() ) { case 5: return ( ext == ".mesh" || ext == ".solb" ); case 6: return ( ext == ".meshb" ); diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 967bf5bcb2..90b69881cc 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -35,8 +35,10 @@ # endif # include # include +# include # include # include +# include #endif #ifdef FC_OS_WIN32 @@ -452,7 +454,7 @@ void Application::renameDocument(const char *OldName, const char *NewName) throw Base::RuntimeError("Renaming document internal name is no longer allowed!"); } -Document* Application::newDocument(const char * Name, const char * UserName, bool createView, bool tempDoc) +Document* Application::newDocument(const char * Name, const char * UserName, DocumentCreateFlags CreateFlags) { auto getNameAndLabel = [this](const char * Name, const char * UserName) -> std::tuple { bool defaultName = (!Name || Name[0] == '\0'); @@ -486,10 +488,10 @@ Document* Application::newDocument(const char * Name, const char * UserName, boo auto tuple = getNameAndLabel(Name, UserName); std::string name = std::get<0>(tuple); std::string userName = std::get<1>(tuple); - name = getUniqueDocumentName(name.c_str(), tempDoc); + name = getUniqueDocumentName(name.c_str(), CreateFlags.temporary); // return the temporary document if it exists - if (tempDoc) { + if (CreateFlags.temporary) { auto it = DocMap.find(name); if (it != DocMap.end() && it->second->testStatus(Document::TempDoc)) return it->second; @@ -497,7 +499,7 @@ Document* Application::newDocument(const char * Name, const char * UserName, boo // create the FreeCAD document std::unique_ptr newDoc(new Document(name.c_str())); - newDoc->setStatus(Document::TempDoc, tempDoc); + newDoc->setStatus(Document::TempDoc, CreateFlags.temporary); auto oldActiveDoc = _pActiveDoc; auto doc = newDoc.release(); // now owned by the Application @@ -538,13 +540,13 @@ Document* Application::newDocument(const char * Name, const char * UserName, boo Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"), active); } - signalNewDocument(*_pActiveDoc, createView); + signalNewDocument(*_pActiveDoc, CreateFlags.createView); // set the UserName after notifying all observers _pActiveDoc->Label.setValue(userName); // set the old document active again if the new is temporary - if (tempDoc && oldActiveDoc) + if (CreateFlags.temporary && oldActiveDoc) setActiveDocument(oldActiveDoc); return doc; @@ -700,9 +702,9 @@ public: } }; -Document* Application::openDocument(const char * FileName, bool createView) { +Document* Application::openDocument(const char * FileName, DocumentCreateFlags createFlags) { std::vector filenames(1,FileName); - auto docs = openDocuments(filenames, nullptr, nullptr, nullptr, createView); + auto docs = openDocuments(filenames, nullptr, nullptr, nullptr, createFlags); if(!docs.empty()) return docs.front(); return nullptr; @@ -747,7 +749,7 @@ std::vector Application::openDocuments(const std::vector const std::vector *paths, const std::vector *labels, std::vector *errs, - bool createView) + DocumentCreateFlags createFlags) { std::vector res(filenames.size(), nullptr); if (filenames.empty()) @@ -811,7 +813,7 @@ std::vector Application::openDocuments(const std::vector label = (*labels)[count].c_str(); } - auto doc = openDocumentPrivate(path, name.c_str(), label, isMainDoc, createView, std::move(objNames)); + auto doc = openDocumentPrivate(path, name.c_str(), label, isMainDoc, createFlags, std::move(objNames)); FC_DURATION_PLUS(timing.d1,t1); if (doc) { timings[doc].d1 += timing.d1; @@ -950,7 +952,7 @@ std::vector Application::openDocuments(const std::vector Document* Application::openDocumentPrivate(const char * FileName, const char *propFileName, const char *label, - bool isMainDoc, bool createView, + bool isMainDoc, DocumentCreateFlags createFlags, std::vector &&objNames) { FileInfo File(FileName); @@ -1021,8 +1023,8 @@ Document* Application::openDocumentPrivate(const char * FileName, // to only contain valid ASCII characters but the user name will be kept. if(!label) label = name.c_str(); - Document* newDoc = newDocument(name.c_str(),label,isMainDoc && createView); + Document* newDoc = newDocument(name.c_str(), label, createFlags); newDoc->FileName.setValue(propFileName==FileName?File.filePath():propFileName); try { @@ -1144,6 +1146,17 @@ std::string Application::getExecutableName() return mConfig["ExeName"]; } +std::string Application::getNameWithVersion() +{ + auto appname = QCoreApplication::applicationName().toStdString(); + auto config = App::Application::Config(); + auto major = config["BuildVersionMajor"]; + auto minor = config["BuildVersionMinor"]; + auto point = config["BuildVersionPoint"]; + auto suffix = config["BuildVersionSuffix"]; + return fmt::format("{} {}.{}.{}{}", appname, major, minor, point, suffix); +} + std::string Application::getTempPath() { return mConfig["AppTempPath"]; @@ -2060,6 +2073,7 @@ void Application::initTypes() App::PropertyElectricalInductance ::init(); App::PropertyElectricalResistance ::init(); App::PropertyElectricCharge ::init(); + App::PropertySurfaceChargeDensity ::init(); App::PropertyElectricCurrent ::init(); App::PropertyElectricPotential ::init(); App::PropertyElectromagneticPotential ::init(); @@ -2420,11 +2434,6 @@ void processProgramOptions(const variables_map& vm, std::map Mods = vm["module-path"].as< vector >(); string temp; @@ -2590,7 +2599,7 @@ void Application::initConfig(int argc, char ** argv) // Now it's time to read-in the file branding.xml if it exists Branding brand; QString binDir = QString::fromUtf8((mConfig["AppHomePath"] + "bin").c_str()); - QFileInfo fi(binDir, QString::fromLatin1("branding.xml")); + QFileInfo fi(binDir, QStringLiteral("branding.xml")); if (fi.exists() && brand.readFile(fi.absoluteFilePath())) { Branding::XmlConfig cfg = brand.getUserDefines(); for (Branding::XmlConfig::iterator it = cfg.begin(); it != cfg.end(); ++it) { @@ -2599,7 +2608,17 @@ void Application::initConfig(int argc, char ** argv) } variables_map vm; - parseProgramOptions(argc, argv, mConfig["ExeName"], vm); + { + BOOST_SCOPE_EXIT_ALL(&) { + // console-mode needs to be set (if possible) also in case parseProgramOptions + // throws, as it's needed when reporting such exceptions + if (vm.count("console")) { + mConfig["Console"] = "1"; + mConfig["RunMode"] = "Cmd"; + } + }; + parseProgramOptions(argc, argv, mConfig["ExeName"], vm); + } if (vm.count("keep-deprecated-paths")) { mConfig["KeepDeprecatedPaths"] = "1"; @@ -3136,7 +3155,7 @@ QString getOldGenericDataLocation(QString home) return QString::fromStdString(converter.to_bytes(szPath)); } #elif defined(FC_OS_MACOSX) - QFileInfo fi(home, QString::fromLatin1("Library/Preferences")); + QFileInfo fi(home, QStringLiteral("Library/Preferences")); home = fi.absoluteFilePath(); #endif @@ -3202,7 +3221,7 @@ QString findUserHomePath(const QString& userHome) * Returns the path where to store application files to. * If \a customHome is not empty it will be used, otherwise a path starting from \a stdHome will be used. */ -boost::filesystem::path findPath(const QString& stdHome, const QString& customHome, +std::filesystem::path findPath(const QString& stdHome, const QString& customHome, const std::vector& paths, bool create) { QString dataPath = customHome; @@ -3210,7 +3229,7 @@ boost::filesystem::path findPath(const QString& stdHome, const QString& customHo dataPath = stdHome; } - boost::filesystem::path appData(Base::FileInfo::stringToPath(dataPath.toStdString())); + std::filesystem::path appData(Base::FileInfo::stringToPath(dataPath.toStdString())); // If a custom user home path is given then don't modify it if (customHome.isEmpty()) { @@ -3219,10 +3238,10 @@ boost::filesystem::path findPath(const QString& stdHome, const QString& customHo } // In order to write to our data path, we must create some directories, first. - if (create && !boost::filesystem::exists(appData) && !Py_IsInitialized()) { + if (create && !std::filesystem::exists(appData) && !Py_IsInitialized()) { try { - boost::filesystem::create_directories(appData); - } catch (const boost::filesystem::filesystem_error& e) { + std::filesystem::create_directories(appData); + } catch (const std::filesystem::filesystem_error& e) { throw Base::FileSystemError("Could not create directories. Failed with: " + e.code().message()); } } @@ -3243,9 +3262,9 @@ boost::filesystem::path findPath(const QString& stdHome, const QString& customHo std::tuple getCustomPaths() { QProcessEnvironment env(QProcessEnvironment::systemEnvironment()); - QString userHome = env.value(QString::fromLatin1("FREECAD_USER_HOME")); - QString userData = env.value(QString::fromLatin1("FREECAD_USER_DATA")); - QString userTemp = env.value(QString::fromLatin1("FREECAD_USER_TEMP")); + QString userHome = env.value(QStringLiteral("FREECAD_USER_HOME")); + QString userData = env.value(QStringLiteral("FREECAD_USER_DATA")); + QString userTemp = env.value(QStringLiteral("FREECAD_USER_TEMP")); auto toNativePath = [](QString& path) { if (!path.isEmpty()) { @@ -3270,8 +3289,8 @@ std::tuple getCustomPaths() // if FREECAD_USER_HOME is set but not FREECAD_USER_TEMP if (!userHome.isEmpty() && userTemp.isEmpty()) { QDir dir(userHome); - dir.mkdir(QString::fromLatin1("temp")); - QFileInfo fi(dir, QString::fromLatin1("temp")); + dir.mkdir(QStringLiteral("temp")); + QFileInfo fi(dir, QStringLiteral("temp")); userTemp = fi.absoluteFilePath(); } @@ -3354,13 +3373,13 @@ void Application::ExtractUserPath() // User data path // - boost::filesystem::path data = findPath(dataHome, customData, subdirs, true); + std::filesystem::path data = findPath(dataHome, customData, subdirs, true); mConfig["UserAppData"] = Base::FileInfo::pathToString(data) + PATHSEP; // User config path // - boost::filesystem::path config = findPath(configHome, customHome, subdirs, true); + std::filesystem::path config = findPath(configHome, customHome, subdirs, true); mConfig["UserConfigPath"] = Base::FileInfo::pathToString(config) + PATHSEP; @@ -3368,14 +3387,14 @@ void Application::ExtractUserPath() // std::vector cachedirs = subdirs; cachedirs.emplace_back("Cache"); - boost::filesystem::path cache = findPath(cacheHome, customTemp, cachedirs, true); + std::filesystem::path cache = findPath(cacheHome, customTemp, cachedirs, true); mConfig["UserCachePath"] = Base::FileInfo::pathToString(cache) + PATHSEP; // Set application tmp. directory // std::vector empty; - boost::filesystem::path tmp = findPath(tempPath, customTemp, empty, true); + std::filesystem::path tmp = findPath(tempPath, customTemp, empty, true); mConfig["AppTempPath"] = Base::FileInfo::pathToString(tmp) + PATHSEP; @@ -3383,7 +3402,7 @@ void Application::ExtractUserPath() // std::vector macrodirs = subdirs; macrodirs.emplace_back("Macro"); - boost::filesystem::path macro = findPath(dataHome, customData, macrodirs, true); + std::filesystem::path macro = findPath(dataHome, customData, macrodirs, true); mConfig["UserMacroPath"] = Base::FileInfo::pathToString(macro) + PATHSEP; } diff --git a/src/App/Application.h b/src/App/Application.h index e2a32adefe..2646737233 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -69,6 +69,10 @@ enum class MessageOption { Throw, /**< Throw an exception. */ }; +struct DocumentCreateFlags { + bool createView {true}; + bool temporary {false}; +}; /** The Application * The root of the whole application @@ -94,13 +98,13 @@ public: * the user and stored in the App::Document::Name property. */ App::Document* newDocument(const char * Name=nullptr, const char * UserName=nullptr, - bool createView=true, bool tempDoc=false); + DocumentCreateFlags CreateFlags=DocumentCreateFlags()); /// Closes the document \a name and removes it from the application. bool closeDocument(const char* name); /// find a unique document name std::string getUniqueDocumentName(const char *Name, bool tempDoc=false) const; /// Open an existing document from a file - App::Document* openDocument(const char * FileName=nullptr, bool createView=true); + App::Document* openDocument(const char * FileName=nullptr, DocumentCreateFlags createFlags = DocumentCreateFlags{}); /** Open multiple documents * * @param filenames: input file names @@ -122,7 +126,7 @@ public: const std::vector *paths=nullptr, const std::vector *labels=nullptr, std::vector *errs=nullptr, - bool createView = true); + DocumentCreateFlags createFlags = DocumentCreateFlags{}); /// Retrieve the active document App::Document* getActiveDocument() const; /// Retrieve a named document @@ -409,6 +413,7 @@ public: //@{ static std::string getHomePath(); static std::string getExecutableName(); + static std::string getNameWithVersion(); /*! Returns the temporary directory. By default, this is set to the system's temporary directory but can be customized by the user. @@ -486,7 +491,7 @@ protected: /// open single document only App::Document* openDocumentPrivate(const char * FileName, const char *propFileName, - const char *label, bool isMainDoc, bool createView, std::vector &&objNames); + const char *label, bool isMainDoc, DocumentCreateFlags createFlags, std::vector &&objNames); /// Helper class for App::Document to signal on close/abort transaction class AppExport TransactionSignaller { diff --git a/src/App/ApplicationPy.cpp b/src/App/ApplicationPy.cpp index 7303d7e56c..42d8942b33 100644 --- a/src/App/ApplicationPy.cpp +++ b/src/App/ApplicationPy.cpp @@ -149,12 +149,13 @@ PyMethodDef Application::Methods[] = { {"openDocument", reinterpret_cast(reinterpret_cast(Application::sOpenDocument)), METH_VARARGS | METH_KEYWORDS, - "openDocument(filepath,hidden=False) -> object\n" + "openDocument(filepath,hidden=False,temporary=False) -> object\n" "Create a document and load the project file into the document.\n\n" "filepath: file path to an existing file. If the file doesn't exist\n" " or the file cannot be loaded an I/O exception is thrown.\n" " In this case the document is kept alive.\n" - "hidden: whether to hide document 3D view."}, + "hidden: whether to hide document 3D view.\n" + "temporary: whether to hide document in the tree view."}, // {"saveDocument", (PyCFunction) Application::sSaveDocument, METH_VARARGS, // "saveDocument(string) -- Save the document to a file."}, // {"saveDocumentAs", (PyCFunction) Application::sSaveDocumentAs, METH_VARARGS}, @@ -339,23 +340,30 @@ PyObject* Application::sOpenDocument(PyObject* /*self*/, PyObject* args, PyObjec { char* Name; PyObject* hidden = Py_False; - static const std::array kwlist {"name", "hidden", nullptr}; + PyObject* temporary = Py_False; + static const std::array kwlist {"name", "hidden", "temporary", nullptr}; if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, - "et|O!", + "et|O!O!", kwlist, "utf-8", &Name, &PyBool_Type, - &hidden)) { + &hidden, + &PyBool_Type, + &temporary)) { return nullptr; } std::string EncodedName = std::string(Name); PyMem_Free(Name); try { + DocumentCreateFlags createFlags; + createFlags.createView = !Base::asBoolean(hidden); + createFlags.temporary = Base::asBoolean(temporary); + // return new document return (GetApplication() - .openDocument(EncodedName.c_str(), !Base::asBoolean(hidden)) + .openDocument(EncodedName.c_str(), createFlags) ->getPyObject()); } catch (const Base::Exception& e) { @@ -393,11 +401,13 @@ PyObject* Application::sNewDocument(PyObject* /*self*/, PyObject* args, PyObject PY_TRY { + DocumentCreateFlags createFlags; + createFlags.createView = !Base::asBoolean(hidden); + createFlags.temporary = Base::asBoolean(temp); + App::Document* doc = GetApplication().newDocument(docName, usrName, - !Base::asBoolean(hidden), - Base::asBoolean(temp)); - PyMem_Free(docName); + createFlags); PyMem_Free(usrName); return doc->getPyObject(); } @@ -1032,7 +1042,7 @@ PyObject* Application::sCheckLinkDepth(PyObject* /*self*/, PyObject* args) PY_TRY { return Py::new_reference_to( - Py::Int(GetApplication().checkLinkDepth(depth, MessageOption::Throw))); + Py::Long(GetApplication().checkLinkDepth(depth, MessageOption::Throw))); } PY_CATCH; } @@ -1122,7 +1132,7 @@ PyObject* Application::sSetActiveTransaction(PyObject* /*self*/, PyObject* args) PY_TRY { - Py::Int ret(GetApplication().setActiveTransaction(name, Base::asBoolean(persist))); + Py::Long ret(GetApplication().setActiveTransaction(name, Base::asBoolean(persist))); return Py::new_reference_to(ret); } PY_CATCH; @@ -1143,7 +1153,7 @@ PyObject* Application::sGetActiveTransaction(PyObject* /*self*/, PyObject* args) } Py::Tuple ret(2); ret.setItem(0, Py::String(name)); - ret.setItem(1, Py::Int(id)); + ret.setItem(1, Py::Long(id)); return Py::new_reference_to(ret); } PY_CATCH; diff --git a/src/App/ComplexGeoDataPy.xml b/src/App/ComplexGeoDataPy.xml index 7b094cb3dd..00fb61f10b 100644 --- a/src/App/ComplexGeoDataPy.xml +++ b/src/App/ComplexGeoDataPy.xml @@ -117,7 +117,7 @@ Geometry Tag - + @@ -129,7 +129,7 @@ Get the current element map size - + diff --git a/src/App/ComplexGeoDataPyImp.cpp b/src/App/ComplexGeoDataPyImp.cpp index 878876d9c4..768229a569 100644 --- a/src/App/ComplexGeoDataPyImp.cpp +++ b/src/App/ComplexGeoDataPyImp.cpp @@ -110,9 +110,9 @@ PyObject* ComplexGeoDataPy::getFacesFromSubElement(PyObject* args) Py::List facet; for (const auto& it : facets) { Py::Tuple f(3); - f.setItem(0, Py::Int(int(it.I1))); - f.setItem(1, Py::Int(int(it.I2))); - f.setItem(2, Py::Int(int(it.I3))); + f.setItem(0, Py::Long(int(it.I1))); + f.setItem(1, Py::Long(int(it.I2))); + f.setItem(2, Py::Long(int(it.I3))); facet.append(f); } tuple.setItem(1, facet); @@ -147,8 +147,8 @@ PyObject* ComplexGeoDataPy::getLinesFromSubElement(PyObject* args) Py::List line; for (const auto& it : lines) { Py::Tuple l(2); - l.setItem(0, Py::Int((int)it.I1)); - l.setItem(1, Py::Int((int)it.I2)); + l.setItem(0, Py::Long((int)it.I1)); + l.setItem(1, Py::Long((int)it.I2)); line.append(l); } tuple.setItem(1, line); @@ -213,8 +213,8 @@ PyObject* ComplexGeoDataPy::getLines(PyObject* args) Py::List line; for (const auto& it : lines) { Py::Tuple l(2); - l.setItem(0, Py::Int((int)it.I1)); - l.setItem(1, Py::Int((int)it.I2)); + l.setItem(0, Py::Long((int)it.I1)); + l.setItem(1, Py::Long((int)it.I2)); line.append(l); } tuple.setItem(1, line); @@ -247,9 +247,9 @@ PyObject* ComplexGeoDataPy::getFaces(PyObject* args) Py::List facet; for (const auto& it : facets) { Py::Tuple f(3); - f.setItem(0, Py::Int((int)it.I1)); - f.setItem(1, Py::Int((int)it.I2)); - f.setItem(2, Py::Int((int)it.I3)); + f.setItem(0, Py::Long((int)it.I1)); + f.setItem(1, Py::Long((int)it.I2)); + f.setItem(2, Py::Long((int)it.I3)); facet.append(f); } tuple.setItem(1, facet); @@ -509,9 +509,9 @@ Py::Dict ComplexGeoDataPy::getElementReverseMap() const return ret; } -Py::Int ComplexGeoDataPy::getElementMapSize() const +Py::Long ComplexGeoDataPy::getElementMapSize() const { - return Py::Int((long)getComplexGeoDataPtr()->getElementMapSize()); + return Py::Long((long)getComplexGeoDataPtr()->getElementMapSize()); } void ComplexGeoDataPy::setHasher(Py::Object obj) @@ -575,12 +575,12 @@ Py::String ComplexGeoDataPy::getElementMapVersion() const } -Py::Int ComplexGeoDataPy::getTag() const +Py::Long ComplexGeoDataPy::getTag() const { - return Py::Int(getComplexGeoDataPtr()->Tag); + return Py::Long(getComplexGeoDataPtr()->Tag); } -void ComplexGeoDataPy::setTag(Py::Int tag) +void ComplexGeoDataPy::setTag(Py::Long tag) { getComplexGeoDataPtr()->Tag = tag; } diff --git a/src/App/Datums.cpp b/src/App/Datums.cpp index 1d08929297..251f347111 100644 --- a/src/App/Datums.cpp +++ b/src/App/Datums.cpp @@ -156,7 +156,7 @@ App::DatumElement* LocalCoordinateSystem::getDatumElement(const char* role) cons { const auto& features = OriginFeatures.getValues(); auto featIt = std::find_if(features.begin(), features.end(), [role](App::DocumentObject* obj) { - return obj->isDerivedFrom(App::DatumElement::getClassTypeId()) + return obj->isDerivedFrom() && strcmp(static_cast(obj)->Role.getValue(), role) == 0; }); if (featIt != features.end()) { @@ -171,7 +171,7 @@ App::DatumElement* LocalCoordinateSystem::getDatumElement(const char* role) cons App::Line* LocalCoordinateSystem::getAxis(const char* role) const { App::DatumElement* feat = getDatumElement(role); - if (feat->isDerivedFrom(App::Line::getClassTypeId())) { + if (feat->isDerivedFrom()) { return static_cast(feat); } std::stringstream err; @@ -183,7 +183,7 @@ App::Line* LocalCoordinateSystem::getAxis(const char* role) const App::Plane* LocalCoordinateSystem::getPlane(const char* role) const { App::DatumElement* feat = getDatumElement(role); - if (feat->isDerivedFrom(App::Plane::getClassTypeId())) { + if (feat->isDerivedFrom()) { return static_cast(feat); } std::stringstream err; @@ -195,7 +195,7 @@ App::Plane* LocalCoordinateSystem::getPlane(const char* role) const App::Point* LocalCoordinateSystem::getPoint(const char* role) const { App::DatumElement* feat = getDatumElement(role); - if (feat->isDerivedFrom(App::Point::getClassTypeId())) { + if (feat->isDerivedFrom()) { return static_cast(feat); } std::stringstream err; @@ -262,7 +262,7 @@ DatumElement* LocalCoordinateSystem::createDatum(const SetupData& data) std::string objName = doc->getUniqueObjectName(data.role); App::DocumentObject* featureObj = doc->addObject(data.type.getName(), objName.c_str()); - assert(featureObj && featureObj->isDerivedFrom(App::DatumElement::getClassTypeId())); + assert(featureObj && featureObj->isDerivedFrom()); QByteArray byteArray = data.label.toUtf8(); featureObj->Label.setValue(byteArray.constData()); diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 6dc25c8fe3..9b583183c0 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -60,7 +60,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #ifndef _PreComp_ #include #include -#include +#include #endif #include @@ -131,7 +131,7 @@ using namespace zipios; #define FC_LOGFEATUREUPDATE #endif -namespace fs = boost::filesystem; +namespace fs = std::filesystem; namespace App { @@ -835,7 +835,7 @@ void Document::onChanged(const Property* prop) void Document::onBeforeChangeProperty(const TransactionalObject* Who, const Property* What) { - if (Who->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (Who->isDerivedFrom()) { signalBeforeChangeObject(*static_cast(Who), *What); } if (!d->rollback && !globalIsRelabeling) { @@ -3544,7 +3544,7 @@ DocumentObject* Document::addObject(const char* sType, const char* viewType, bool isPartial) { - Base::Type type = + const Base::Type type = Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true); if (type.isBad()) { std::stringstream str; @@ -3557,8 +3557,7 @@ DocumentObject* Document::addObject(const char* sType, return nullptr; } - App::DocumentObject* pcObject = static_cast(typeInstance); - + auto* pcObject = static_cast(typeInstance); pcObject->setDocument(this); // do no transactions if we do a rollback! @@ -3571,15 +3570,8 @@ DocumentObject* Document::addObject(const char* sType, } // get Unique name - string ObjectName; - - if (pObjectName && pObjectName[0] != '\0') { - ObjectName = getUniqueObjectName(pObjectName); - } - else { - ObjectName = getUniqueObjectName(sType); - } - + const bool hasName = pObjectName && pObjectName[0] != '\0'; + const string ObjectName = getUniqueObjectName(hasName ? pObjectName : type.getName()); d->activeObject = pcObject; @@ -4338,7 +4330,7 @@ std::vector Document::getObjectsOfType(const Base::Type& typeId { std::vector Objects; for (auto it : d->objectArray) { - if (it->getTypeId().isDerivedFrom(typeId)) { + if (it->isDerivedFrom(typeId)) { Objects.push_back(it); } } @@ -4376,7 +4368,7 @@ Document::findObjects(const Base::Type& typeId, const char* objname, const char* std::vector Objects; DocumentObject* found = nullptr; for (auto it : d->objectArray) { - if (it->getTypeId().isDerivedFrom(typeId)) { + if (it->isDerivedFrom(typeId)) { found = it; if (!rx_name.empty() && !boost::regex_search(it->getNameInDocument(), what, rx_name)) { @@ -4398,7 +4390,7 @@ Document::findObjects(const Base::Type& typeId, const char* objname, const char* int Document::countObjectsOfType(const Base::Type& typeId) const { return std::count_if(d->objectMap.begin(), d->objectMap.end(), [&](const auto& it) { - return it.second->getTypeId().isDerivedFrom(typeId); + return it.second->isDerivedFrom(typeId); }); } diff --git a/src/App/Document.h b/src/App/Document.h index b13b206bd0..cdabf8efce 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -268,6 +268,21 @@ public: bool isNew = true, const char* viewType = nullptr, bool isPartial = false); + //@{ + /** Add a feature of T type with sName (ASCII) to this document and set it active. + * Unicode names are set through the Label property. + * @param pObjectName if nonNULL use that name otherwise generate a new unique name based on the + * \a sType + * @param isNew if false don't call the \c DocumentObject::setupObject() callback (default + * is true) + * @param viewType override object's view provider name + * @param isPartial indicate if this object is meant to be partially loaded + */ + template + T* addObject(const char* pObjectName = nullptr, + bool isNew = true, + const char* viewType = nullptr, + bool isPartial = false); /** Add an array of features of the given types and names. * Unicode names are set through the Label property. * @param sType The type of created object @@ -662,6 +677,12 @@ inline int Document::countObjectsOfType() const return this->countObjectsOfType(T::getClassTypeId()); } +template +T* Document::addObject(const char* pObjectName, bool isNew, const char* viewType, bool isPartial) +{ + static_assert(std::is_base_of::value, "T must be derived from DocumentObject"); + return static_cast(addObject(T::getClassName(), pObjectName, isNew, viewType, isPartial)); +} } // namespace App diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index bd2b3b395e..17f2b83ce8 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -759,7 +759,7 @@ bool DocumentObject::removeDynamicProperty(const char* name) return false; } - if (prop->isDerivedFrom(PropertyLinkBase::getClassTypeId())) { + if (prop->isDerivedFrom()) { clearOutListCache(); } diff --git a/src/App/DocumentObjectExtension.cpp b/src/App/DocumentObjectExtension.cpp index 85e3922839..c98e0d9f74 100644 --- a/src/App/DocumentObjectExtension.cpp +++ b/src/App/DocumentObjectExtension.cpp @@ -76,14 +76,14 @@ PyObject* DocumentObjectExtension::getExtensionPyObject() const DocumentObject* DocumentObjectExtension::getExtendedObject() const { - assert(getExtendedContainer()->isDerivedFrom(DocumentObject::getClassTypeId())); + assert(getExtendedContainer()->isDerivedFrom()); return static_cast(getExtendedContainer()); } DocumentObject* DocumentObjectExtension::getExtendedObject() { - assert(getExtendedContainer()->isDerivedFrom(DocumentObject::getClassTypeId())); + assert(getExtendedContainer()->isDerivedFrom()); return static_cast(getExtendedContainer()); } diff --git a/src/App/DocumentObjectPy.xml b/src/App/DocumentObjectPy.xml index cb93c974db..ea63126b17 100644 --- a/src/App/DocumentObjectPy.xml +++ b/src/App/DocumentObjectPy.xml @@ -305,7 +305,7 @@ or None if the GUI is not up The unique identifier (among its document) of this object - + diff --git a/src/App/DocumentObjectPyImp.cpp b/src/App/DocumentObjectPyImp.cpp index c6e2e32b20..5ca4a9185b 100644 --- a/src/App/DocumentObjectPyImp.cpp +++ b/src/App/DocumentObjectPyImp.cpp @@ -898,9 +898,9 @@ int DocumentObjectPy::setCustomAttributes(const char*, PyObject*) return 0; } -Py::Int DocumentObjectPy::getID() const +Py::Long DocumentObjectPy::getID() const { - return Py::Int(getDocumentObjectPtr()->getID()); + return Py::Long(getDocumentObjectPtr()->getID()); } Py::Boolean DocumentObjectPy::getRemoving() const diff --git a/src/App/DocumentObserver.cpp b/src/App/DocumentObserver.cpp index 78b8574302..0bbb616a52 100644 --- a/src/App/DocumentObserver.cpp +++ b/src/App/DocumentObserver.cpp @@ -177,7 +177,7 @@ void DocumentObjectT::operator=(const DocumentObject* obj) void DocumentObjectT::operator=(const Property* prop) { if (!prop || !prop->hasName() || !prop->getContainer() - || !prop->getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + || !prop->getContainer()->isDerivedFrom()) { object.clear(); label.clear(); document.clear(); diff --git a/src/App/DocumentPy.xml b/src/App/DocumentPy.xml index 2e929d7ac1..798994b3c8 100644 --- a/src/App/DocumentPy.xml +++ b/src/App/DocumentPy.xml @@ -136,15 +136,15 @@ viewType (String): override the view provider type directly, only effective when Remove an object from the document - + -copyObject(object, with_dependencies=False, return_all=False) +copyObject(object, recursive=False, return_all=False) Copy an object or objects from another document to this document. object: can either a single object or sequence of objects -with_dependencies: if True, all internal dependent objects are copied too. -return_all: if True, return all copied objects, or else return only the copied +recursive: if True, also recursively copies internal objects. +return_all: if True, returns all copied objects, or else return only the copied object corresponding to the input objects. @@ -313,25 +313,25 @@ sort: whether to topologically sort the return list The Undo mode of the Document (0 = no Undo, 1 = Undo/Redo) - + The size of the Undo stack in byte - + Number of possible Undos - + Number of possible Redos - + diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index c10db56c8c..1c7d8a03fe 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -388,7 +388,7 @@ PyObject* DocumentPy::addObject(PyObject* args, PyObject* kwd) pyvp = Py::Object(view); } if (pyvp.isNone()) { - pyvp = Py::Int(1); + pyvp = Py::Long(1); } // 'pyvp' is the python class with the implementation for ViewProvider if (pyvp.hasAttr("__vobject__")) { @@ -426,10 +426,21 @@ PyObject* DocumentPy::removeObject(PyObject* args) } } -PyObject* DocumentPy::copyObject(PyObject* args) +PyObject* DocumentPy::copyObject(PyObject* args, PyObject* kwd) { - PyObject *obj, *rec = Py_False, *retAll = Py_False; - if (!PyArg_ParseTuple(args, "O|O!O!", &obj, &PyBool_Type, &rec, &PyBool_Type, &retAll)) { + PyObject* obj; + PyObject* rec = Py_False; + PyObject* retAll = Py_False; + static constexpr std::array kwlist {"object", "recursive", "return_all", nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwd, + "O|O!O!", + kwlist, + &obj, + &PyBool_Type, + &rec, + &PyBool_Type, + &retAll)) { return nullptr; } @@ -695,7 +706,7 @@ PyObject* DocumentPy::recompute(PyObject* args) return nullptr; } - return Py::new_reference_to(Py::Int(objectCount)); + return Py::new_reference_to(Py::Long(objectCount)); } PY_CATCH; } @@ -890,30 +901,30 @@ Py::List DocumentPy::getRootObjectsIgnoreLinks() const return res; } -Py::Int DocumentPy::getUndoMode() const +Py::Long DocumentPy::getUndoMode() const { - return Py::Int(getDocumentPtr()->getUndoMode()); + return Py::Long(getDocumentPtr()->getUndoMode()); } -void DocumentPy::setUndoMode(Py::Int arg) +void DocumentPy::setUndoMode(Py::Long arg) { getDocumentPtr()->setUndoMode(arg); } -Py::Int DocumentPy::getUndoRedoMemSize() const +Py::Long DocumentPy::getUndoRedoMemSize() const { - return Py::Int((long)getDocumentPtr()->getUndoMemSize()); + return Py::Long((long)getDocumentPtr()->getUndoMemSize()); } -Py::Int DocumentPy::getUndoCount() const +Py::Long DocumentPy::getUndoCount() const { - return Py::Int((long)getDocumentPtr()->getAvailableUndos()); + return Py::Long((long)getDocumentPtr()->getAvailableUndos()); } -Py::Int DocumentPy::getRedoCount() const +Py::Long DocumentPy::getRedoCount() const { - return Py::Int((long)getDocumentPtr()->getAvailableRedos()); + return Py::Long((long)getDocumentPtr()->getAvailableRedos()); } Py::List DocumentPy::getUndoNames() const diff --git a/src/App/Expression.cpp b/src/App/Expression.cpp index a6169b9697..596930a0bc 100644 --- a/src/App/Expression.cpp +++ b/src/App/Expression.cpp @@ -2016,7 +2016,7 @@ Py::Object FunctionExpression::evalAggregate( } for (auto &arg : args) { - if (arg->isDerivedFrom(RangeExpression::getClassTypeId())) { + if (arg->isDerivedFrom()) { Range range(static_cast(*arg).getRange()); do { @@ -2159,7 +2159,7 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std switch (f) { case LIST: { - if (args.size() == 1 && args[0]->isDerivedFrom(RangeExpression::getClassTypeId())) + if (args.size() == 1 && args[0]->isDerivedFrom()) return args[0]->getPyValue(); Py::List list(args.size()); int i = 0; @@ -2168,7 +2168,7 @@ Py::Object FunctionExpression::evaluate(const Expression *expr, int f, const std return list; } case TUPLE: { - if (args.size() == 1 && args[0]->isDerivedFrom(RangeExpression::getClassTypeId())) + if (args.size() == 1 && args[0]->isDerivedFrom()) return Py::Tuple(args[0]->getPyValue()); Py::Tuple tuple(args.size()); int i = 0; diff --git a/src/App/ExtensionContainer.h b/src/App/ExtensionContainer.h index 0910125ca9..7972ba4975 100644 --- a/src/App/ExtensionContainer.h +++ b/src/App/ExtensionContainer.h @@ -239,7 +239,7 @@ private: std::map _extensions; }; -#define PROPERTY_HEADER_WITH_EXTENSIONS(_class_) PROPERTY_HEADER_WITH_OVERRIDE(_class) +#define PROPERTY_HEADER_WITH_EXTENSIONS(_class_) PROPERTY_HEADER_WITH_OVERRIDE(_class_) /// We make sure that the PropertyData of the container is not connected to the one of the extension #define PROPERTY_SOURCE_WITH_EXTENSIONS(_class_, _parentclass_) \ diff --git a/src/App/FeaturePython.cpp b/src/App/FeaturePython.cpp index fdb7640821..c4188223c9 100644 --- a/src/App/FeaturePython.cpp +++ b/src/App/FeaturePython.cpp @@ -278,14 +278,14 @@ bool FeaturePythonImp::getSubObject(DocumentObject*& ret, subname = ""; } args.setItem(1, Py::String(subname)); - args.setItem(2, Py::Int(pyObj ? 2 : 1)); + args.setItem(2, Py::Long(pyObj ? 2 : 1)); Base::MatrixPy* pyMat = new Base::MatrixPy(new Base::Matrix4D); if (_mat) { *pyMat->getMatrixPtr() = *_mat; } args.setItem(3, Py::asObject(pyMat)); args.setItem(4, Py::Boolean(transform)); - args.setItem(5, Py::Int(depth)); + args.setItem(5, Py::Long(depth)); Py::Object res(Base::pyCall(py_getSubObject.ptr(), args.ptr())); if (res.isNone()) { @@ -343,7 +343,7 @@ bool FeaturePythonImp::getSubObjects(std::vector& ret, int reason) try { Py::Tuple args(2); args.setItem(0, Py::Object(object->getPyObject(), true)); - args.setItem(1, Py::Int(reason)); + args.setItem(1, Py::Long(reason)); Py::Object res(Base::pyCall(py_getSubObjects.ptr(), args.ptr())); if (!res.isTrue()) { return true; @@ -390,7 +390,7 @@ bool FeaturePythonImp::getLinkedObject(DocumentObject*& ret, } args.setItem(2, Py::asObject(pyMat)); args.setItem(3, Py::Boolean(transform)); - args.setItem(4, Py::Int(depth)); + args.setItem(4, Py::Long(depth)); Py::Object res(Base::pyCall(py_getLinkedObject.ptr(), args.ptr())); if (!res.isTrue()) { @@ -466,7 +466,7 @@ int FeaturePythonImp::isElementVisible(const char* element) const Py::Tuple args(2); args.setItem(0, Py::Object(object->getPyObject(), true)); args.setItem(1, Py::String(element ? element : "")); - return Py::Int(Base::pyCall(py_isElementVisible.ptr(), args.ptr())); + return Py::Long(Base::pyCall(py_isElementVisible.ptr(), args.ptr())); } catch (Py::Exception&) { if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) { @@ -488,7 +488,7 @@ int FeaturePythonImp::setElementVisible(const char* element, bool visible) args.setItem(0, Py::Object(object->getPyObject(), true)); args.setItem(1, Py::String(element ? element : "")); args.setItem(2, Py::Boolean(visible)); - return Py::Int(Base::pyCall(py_setElementVisible.ptr(), args.ptr())); + return Py::Long(Base::pyCall(py_setElementVisible.ptr(), args.ptr())); } catch (Py::Exception&) { if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) { @@ -568,7 +568,7 @@ int FeaturePythonImp::canLoadPartial() const try { Py::Tuple args(1); args.setItem(0, Py::Object(object->getPyObject(), true)); - Py::Int ret(Base::pyCall(py_canLoadPartial.ptr(), args.ptr())); + Py::Long ret(Base::pyCall(py_canLoadPartial.ptr(), args.ptr())); return ret; } catch (Py::Exception&) { diff --git a/src/App/GeoFeatureGroupExtension.cpp b/src/App/GeoFeatureGroupExtension.cpp index dc8808adf9..c7bc8252e3 100644 --- a/src/App/GeoFeatureGroupExtension.cpp +++ b/src/App/GeoFeatureGroupExtension.cpp @@ -55,7 +55,7 @@ GeoFeatureGroupExtension::~GeoFeatureGroupExtension() = default; void GeoFeatureGroupExtension::initExtension(ExtensionContainer* obj) { - if (!obj->isDerivedFrom(App::GeoFeature::getClassTypeId())) { + if (!obj->isDerivedFrom()) { throw Base::RuntimeError("GeoFeatureGroupExtension can only be applied to GeoFeatures"); } @@ -88,7 +88,7 @@ DocumentObject* GeoFeatureGroupExtension::getGroupOfObject(const DocumentObject* } // we will find origins, but not origin features - if (obj->isDerivedFrom(App::DatumElement::getClassTypeId())) { + if (obj->isDerivedFrom()) { return OriginGroupExtension::getGroupOfObject(obj); } @@ -307,8 +307,8 @@ void GeoFeatureGroupExtension::getCSOutList(const App::DocumentObject* obj, //we remove all links to origin features and origins, they belong to a CS too and can't be moved result.erase(std::remove_if(result.begin(), result.end(), [](App::DocumentObject* obj)->bool { - return (obj->isDerivedFrom(App::DatumElement::getClassTypeId()) || - obj->isDerivedFrom(App::Origin::getClassTypeId())); + return (obj->isDerivedFrom() || + obj->isDerivedFrom()); }), result.end()); vec.insert(vec.end(), result.begin(), result.end()); @@ -483,7 +483,7 @@ bool GeoFeatureGroupExtension::isLinkValid(App::Property* prop) } // get the object that holds the property - if (!prop->getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (!prop->getContainer()->isDerivedFrom()) { return true; // this link comes not from a document object, scopes are meaningless } auto obj = static_cast(prop->getContainer()); diff --git a/src/App/Graphviz.cpp b/src/App/Graphviz.cpp index 5a09a9e3ee..f2765da4b3 100644 --- a/src/App/Graphviz.cpp +++ b/src/App/Graphviz.cpp @@ -301,7 +301,7 @@ void Document::exportGraphviz(std::ostream& out) const if (!sgraph) { auto group = GeoFeatureGroupExtension::getGroupOfObject(docObj); if (group) { - if (docObj->isDerivedFrom(App::DatumElement::getClassTypeId())) { + if (docObj->isDerivedFrom()) { sgraph = GraphList[group->getExtensionByType() ->Origin.getValue()]; } @@ -311,7 +311,7 @@ void Document::exportGraphviz(std::ostream& out) const } } if (!sgraph) { - if (docObj->isDerivedFrom(DatumElement::getClassTypeId())) { + if (docObj->isDerivedFrom()) { auto* lcs = static_cast(docObj)->getLCS(); if (lcs) { sgraph = GraphList[lcs]; @@ -453,7 +453,7 @@ void Document::exportGraphviz(std::ostream& out) const // ignore groups inside other groups, these will be processed in one of the next // recursive calls. App::Origin now has the GeoFeatureGroupExtension but it // should not move its group symbol outside its parent - if (!objectIt->isDerivedFrom(Origin::getClassTypeId()) + if (!objectIt->isDerivedFrom() && objectIt->hasExtension( GeoFeatureGroupExtension::getExtensionClassTypeId()) && GeoFeatureGroupExtension::getGroupOfObject(objectIt) == nullptr) { @@ -571,7 +571,7 @@ void Document::exportGraphviz(std::ostream& out) const // Add edges between document objects for (const auto& It : d->objectMap) { - if (omitGeoFeatureGroups && It.second->isDerivedFrom(Origin::getClassTypeId())) { + if (omitGeoFeatureGroups && It.second->isDerivedFrom()) { continue; } diff --git a/src/App/GroupExtension.cpp b/src/App/GroupExtension.cpp index 6e017b82f9..ed10599419 100644 --- a/src/App/GroupExtension.cpp +++ b/src/App/GroupExtension.cpp @@ -296,7 +296,7 @@ std::vector GroupExtension::getObjectsOfType(const Base::Type& std::vector type; const std::vector& grp = Group.getValues(); for (auto it : grp) { - if (it->getTypeId().isDerivedFrom(typeId)) { + if (it->isDerivedFrom(typeId)) { type.push_back(it); } } @@ -309,7 +309,7 @@ int GroupExtension::countObjectsOfType(const Base::Type& typeId) const int type = 0; const std::vector& grp = Group.getValues(); for (auto it : grp) { - if (it->getTypeId().isDerivedFrom(typeId)) { + if (it->isDerivedFrom(typeId)) { type++; } } diff --git a/src/App/GroupExtension.h b/src/App/GroupExtension.h index 4130023d23..8fa14f3eed 100644 --- a/src/App/GroupExtension.h +++ b/src/App/GroupExtension.h @@ -51,6 +51,11 @@ public: * append it to this group as well. */ virtual DocumentObject* addObject(const char* sType, const char* pObjectName); + /** Adds an object of \a T with \a pObjectName to the document this group belongs to and + * append it to this group as well. + */ + template + T* addObject(const char* pObjectName); /* Adds the object \a obj to this group. Returns all objects that have been added. */ virtual std::vector addObject(DocumentObject* obj); @@ -151,6 +156,13 @@ private: }; +template +T* GroupExtension::addObject(const char* pObjectName) +{ + static_assert(std::is_base_of::value, "T must be derived from DocumentObject"); + return static_cast(addObject(T::getClassName(), pObjectName)); +} + template class GroupExtensionPythonT: public ExtensionT { diff --git a/src/App/Link.cpp b/src/App/Link.cpp index c520d43a20..5703c39f00 100644 --- a/src/App/Link.cpp +++ b/src/App/Link.cpp @@ -409,7 +409,7 @@ App::DocumentObjectExecReturn* LinkBaseExtension::extensionExecute() else { const auto& elements = _getElementListValue(); for (int i = 0; i < _getElementCountValue(); ++i) { - args.setItem(2, Py::Int(i)); + args.setItem(2, Py::Long(i)); if (i < (int)elements.size()) { args.setItem(3, Py::asObject(elements[i]->getPyObject())); } @@ -1167,7 +1167,7 @@ int LinkBaseExtension::extensionIsElementVisible(const char* element) const DocumentObject* LinkBaseExtension::getContainer() const { auto ext = getExtendedContainer(); - if (!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) { + if (!ext || !ext->isDerivedFrom()) { LINK_THROW(Base::RuntimeError, "Link: container not derived from document object"); } return static_cast(ext); @@ -1176,7 +1176,7 @@ const DocumentObject* LinkBaseExtension::getContainer() const DocumentObject* LinkBaseExtension::getContainer() { auto ext = getExtendedContainer(); - if (!ext || !ext->isDerivedFrom(DocumentObject::getClassTypeId())) { + if (!ext || !ext->isDerivedFrom()) { LINK_THROW(Base::RuntimeError, "Link: container not derived from document object"); } return static_cast(ext); diff --git a/src/App/LinkBaseExtensionPyImp.cpp b/src/App/LinkBaseExtensionPyImp.cpp index 5cf44fea82..16b900fae5 100644 --- a/src/App/LinkBaseExtensionPyImp.cpp +++ b/src/App/LinkBaseExtensionPyImp.cpp @@ -258,7 +258,7 @@ PyObject* LinkBaseExtensionPy::setLink(PyObject* _args) PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(pcObj, &pos, &key, &value)) { - parseLink(ext, Py::Int(key), value); + parseLink(ext, Py::Long(key), value); } } else if (PySequence_Check(pcObj)) { diff --git a/src/App/Metadata.cpp b/src/App/Metadata.cpp index 4e9df6f5fe..d91817624f 100644 --- a/src/App/Metadata.cpp +++ b/src/App/Metadata.cpp @@ -57,7 +57,7 @@ directly. If you did not intend to use a system-defined macro #endif using namespace App; -namespace fs = boost::filesystem; +namespace fs = std::filesystem; #ifndef XERCES_CPP_NAMESPACE_BEGIN #define XERCES_CPP_NAMESPACE_QUALIFIER using namespace XERCES_CPP_NAMESPACE; @@ -158,7 +158,7 @@ void Metadata::loadFromInputSource(const InputSource& source) throw Base::XMLBaseException( "Malformed package.xml document: Root group not found"); } - auto formatVersion = XMLString::parseInt(_dom->getAttribute(XUTF8Str("format").unicodeForm())); + auto formatVersion = XMLString::parseInt(_dom->getAttribute(XUTF8StrLiteral("format").unicodeForm())); switch (formatVersion) { case 1: parseVersion1(_dom); @@ -246,7 +246,7 @@ std::string Metadata::classname() const return _classname; } -boost::filesystem::path Metadata::subdirectory() const +std::filesystem::path Metadata::subdirectory() const { return _subdirectory; } @@ -370,7 +370,7 @@ void Metadata::setClassname(const std::string& name) _classname = name; } -void Metadata::setSubdirectory(const boost::filesystem::path& path) +void Metadata::setSubdirectory(const std::filesystem::path& path) { _subdirectory = path; } @@ -475,7 +475,7 @@ void Metadata::removeTag(const std::string& tag) _tag.erase(new_end, _tag.end()); } -void Metadata::removeFile(const boost::filesystem::path& path) +void Metadata::removeFile(const std::filesystem::path& path) { auto new_end = std::remove(_file.begin(), _file.end(), path); _file.erase(new_end, _file.end()); @@ -560,10 +560,10 @@ void addAttribute(DOMElement* node, const std::string& key, const std::string& v void addAttribute(DOMElement* node, const std::string& key, bool value) { if (value) { - node->setAttribute(XUTF8Str(key.c_str()).unicodeForm(), XUTF8Str("True").unicodeForm()); + node->setAttribute(XUTF8Str(key.c_str()).unicodeForm(), XUTF8StrLiteral("True").unicodeForm()); } else { - node->setAttribute(XUTF8Str(key.c_str()).unicodeForm(), XUTF8Str("False").unicodeForm()); + node->setAttribute(XUTF8Str(key.c_str()).unicodeForm(), XUTF8StrLiteral("False").unicodeForm()); } } @@ -608,13 +608,13 @@ void addDependencyNode(DOMElement* root, const std::string& name, const Meta::De void Metadata::write(const fs::path& file) const { DOMImplementation* impl = - DOMImplementationRegistry::getDOMImplementation(XUTF8Str("Core LS").unicodeForm()); + DOMImplementationRegistry::getDOMImplementation(XUTF8StrLiteral("Core LS").unicodeForm()); - DOMDocument* doc = impl->createDocument(nullptr, XUTF8Str("package").unicodeForm(), nullptr); + DOMDocument* doc = impl->createDocument(nullptr, XUTF8StrLiteral("package").unicodeForm(), nullptr); DOMElement* root = doc->getDocumentElement(); - root->setAttribute(XUTF8Str("format").unicodeForm(), XUTF8Str("1").unicodeForm()); - root->setAttribute(XUTF8Str("xmlns").unicodeForm(), - XUTF8Str("https://wiki.freecad.org/Package_Metadata").unicodeForm()); + root->setAttribute(XUTF8StrLiteral("format").unicodeForm(), XUTF8StrLiteral("1").unicodeForm()); + root->setAttribute(XUTF8StrLiteral("xmlns").unicodeForm(), + XUTF8StrLiteral("https://wiki.freecad.org/Package_Metadata").unicodeForm()); appendToElement(root); @@ -852,7 +852,7 @@ void Metadata::appendToElement(DOMElement* root) const if (!_content.empty()) { auto doc = root->getOwnerDocument(); - DOMElement* contentRootElement = doc->createElement(XUTF8Str("content").unicodeForm()); + DOMElement* contentRootElement = doc->createElement(XUTF8StrLiteral("content").unicodeForm()); root->appendChild(contentRootElement); for (const auto& content : _content) { DOMElement* contentElement = @@ -982,7 +982,7 @@ Meta::Contact::Contact(const XERCES_CPP_NAMESPACE::DOMElement* elem) if (!elem) { return; } - auto emailAttribute = elem->getAttribute(XUTF8Str("email").unicodeForm()); + auto emailAttribute = elem->getAttribute(XUTF8StrLiteral("email").unicodeForm()); name = StrXUTF8(elem->getTextContent()).str; email = StrXUTF8(emailAttribute).str; } @@ -1004,7 +1004,7 @@ Meta::License::License(const XERCES_CPP_NAMESPACE::DOMElement* elem) if (!elem) { return; } - auto fileAttribute = elem->getAttribute(XUTF8Str("file").unicodeForm()); + auto fileAttribute = elem->getAttribute(XUTF8StrLiteral("file").unicodeForm()); if (XMLString::stringLen(fileAttribute) > 0) { file = fs::path(StrXUTF8(fileAttribute).str); } @@ -1033,7 +1033,7 @@ Meta::Url::Url(const XERCES_CPP_NAMESPACE::DOMElement* elem) if (!elem) { return; } - auto typeAttribute = StrXUTF8(elem->getAttribute(XUTF8Str("type").unicodeForm())).str; + auto typeAttribute = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("type").unicodeForm())).str; if (typeAttribute.empty() || typeAttribute == "website") { type = UrlType::website; } @@ -1057,7 +1057,7 @@ Meta::Url::Url(const XERCES_CPP_NAMESPACE::DOMElement* elem) } if (type == UrlType::repository) { - branch = StrXUTF8(elem->getAttribute(XUTF8Str("branch").unicodeForm())).str; + branch = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("branch").unicodeForm())).str; } location = StrXUTF8(elem->getTextContent()).str; } @@ -1083,13 +1083,13 @@ App::Meta::Dependency::Dependency(std::string pkg) Meta::Dependency::Dependency(const XERCES_CPP_NAMESPACE::DOMElement* elem) { - version_lt = StrXUTF8(elem->getAttribute(XUTF8Str("version_lt").unicodeForm())).str; - version_lte = StrXUTF8(elem->getAttribute(XUTF8Str("version_lte").unicodeForm())).str; - version_eq = StrXUTF8(elem->getAttribute(XUTF8Str("version_eq").unicodeForm())).str; - version_gte = StrXUTF8(elem->getAttribute(XUTF8Str("version_gte").unicodeForm())).str; - version_gt = StrXUTF8(elem->getAttribute(XUTF8Str("version_gt").unicodeForm())).str; - condition = StrXUTF8(elem->getAttribute(XUTF8Str("condition").unicodeForm())).str; - std::string opt_string = StrXUTF8(elem->getAttribute(XUTF8Str("optional").unicodeForm())).str; + version_lt = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("version_lt").unicodeForm())).str; + version_lte = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("version_lte").unicodeForm())).str; + version_eq = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("version_eq").unicodeForm())).str; + version_gte = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("version_gte").unicodeForm())).str; + version_gt = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("version_gt").unicodeForm())).str; + condition = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("condition").unicodeForm())).str; + std::string opt_string = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("optional").unicodeForm())).str; if (opt_string == "true" || opt_string == "True") { // Support Python capitalization in this one case... optional = true; @@ -1097,7 +1097,7 @@ Meta::Dependency::Dependency(const XERCES_CPP_NAMESPACE::DOMElement* elem) else { optional = false; } - std::string type_string = StrXUTF8(elem->getAttribute(XUTF8Str("type").unicodeForm())).str; + std::string type_string = StrXUTF8(elem->getAttribute(XUTF8StrLiteral("type").unicodeForm())).str; if (type_string == "automatic" || type_string.empty()) { dependencyType = Meta::DependencyType::automatic; } diff --git a/src/App/Metadata.h b/src/App/Metadata.h index 868315e638..271a112483 100644 --- a/src/App/Metadata.h +++ b/src/App/Metadata.h @@ -25,7 +25,7 @@ #include "FCConfig.h" -#include +#include #include #include @@ -67,11 +67,11 @@ struct AppExport Contact struct AppExport License { License() = default; - License(std::string name, boost::filesystem::path file); + License(std::string name, std::filesystem::path file); explicit License(const XERCES_CPP_NAMESPACE::DOMElement* elem); std::string name; //< Short name of license, e.g. "LGPL2", "MIT", "Mozilla Public License", etc. - boost::filesystem::path + std::filesystem::path file; //< Optional path to the license file, relative to the XML file's location bool operator==(const License& rhs) const; }; @@ -205,7 +205,7 @@ public: * This constructor takes a path to an XML file and loads the XML from that file as * metadata. */ - explicit Metadata(const boost::filesystem::path& metadataFile); + explicit Metadata(const std::filesystem::path& metadataFile); /** * Construct a Metadata object from a DOM node. @@ -248,12 +248,12 @@ public: std::vector replace() const; //< Zero or more packages this package is intended to replace. std::vector tag() const; //< Zero or more text tags related to this package. - boost::filesystem::path icon() const; //< Path to an icon file. + std::filesystem::path icon() const; //< Path to an icon file. std::string classname() const; //< Recognized for convenience -- generally only used by Workbenches. - boost::filesystem::path + std::filesystem::path subdirectory() const; //< Optional, override the default subdirectory name for this item. - std::vector + std::vector file() const; //< Arbitrary files associated with this package or content item. Meta::Version freecadmin() const; //< The minimum FreeCAD version. Meta::Version freecadmax() const; //< The maximum FreeCAD version. @@ -307,10 +307,10 @@ public: void addConflict(const Meta::Dependency& dep); void addReplace(const Meta::Dependency& dep); void addTag(const std::string& tag); - void setIcon(const boost::filesystem::path& path); + void setIcon(const std::filesystem::path& path); void setClassname(const std::string& name); - void setSubdirectory(const boost::filesystem::path& path); - void addFile(const boost::filesystem::path& path); + void setSubdirectory(const std::filesystem::path& path); + void addFile(const std::filesystem::path& path); void addContentItem(const std::string& tag, const Metadata& item); void setFreeCADMin(const Meta::Version& version); void setFreeCADMax(const Meta::Version& version); @@ -327,7 +327,7 @@ public: void removeConflict(const Meta::Dependency& dep); void removeReplace(const Meta::Dependency& dep); void removeTag(const std::string& tag); - void removeFile(const boost::filesystem::path& path); + void removeFile(const std::filesystem::path& path); // Utility functions to clear lists void clearContent(); @@ -344,7 +344,7 @@ public: /** * Write the metadata to an XML file */ - void write(const boost::filesystem::path& file) const; + void write(const std::filesystem::path& file) const; /** * Determine whether this package satisfies the given dependency @@ -371,10 +371,10 @@ private: std::vector _conflict; std::vector _replace; std::vector _tag; - boost::filesystem::path _icon; + std::filesystem::path _icon; std::string _classname; - boost::filesystem::path _subdirectory; - std::vector _file; + std::filesystem::path _subdirectory; + std::vector _file; Meta::Version _freecadmin; Meta::Version _freecadmax; Meta::Version _pythonmin; diff --git a/src/App/ObjectIdentifier.cpp b/src/App/ObjectIdentifier.cpp index 92593f0a80..28637d638a 100644 --- a/src/App/ObjectIdentifier.cpp +++ b/src/App/ObjectIdentifier.cpp @@ -692,7 +692,7 @@ Py::Object ObjectIdentifier::Component::get(const Py::Object& pyobj) const } else if (isArray()) { if (pyobj.isMapping()) { - res = Py::Mapping(pyobj).getItem(Py::Int(begin)); + res = Py::Mapping(pyobj).getItem(Py::Long(begin)); } else { res = Py::Sequence(pyobj).getItem(begin); @@ -703,9 +703,9 @@ Py::Object ObjectIdentifier::Component::get(const Py::Object& pyobj) const } else { assert(isRange()); - Py::Object slice(PySlice_New(Py::Int(begin).ptr(), - end != INT_MAX ? Py::Int(end).ptr() : nullptr, - step != 1 ? Py::Int(step).ptr() : nullptr), + Py::Object slice(PySlice_New(Py::Long(begin).ptr(), + end != INT_MAX ? Py::Long(end).ptr() : nullptr, + step != 1 ? Py::Long(step).ptr() : nullptr), true); PyObject* r = PyObject_GetItem(pyobj.ptr(), slice.ptr()); if (!r) { @@ -731,7 +731,7 @@ void ObjectIdentifier::Component::set(Py::Object& pyobj, const Py::Object& value } else if (isArray()) { if (pyobj.isMapping()) { - Py::Mapping(pyobj).setItem(Py::Int(begin), value); + Py::Mapping(pyobj).setItem(Py::Long(begin), value); } else { Py::Sequence(pyobj).setItem(begin, value); @@ -742,9 +742,9 @@ void ObjectIdentifier::Component::set(Py::Object& pyobj, const Py::Object& value } else { assert(isRange()); - Py::Object slice(PySlice_New(Py::Int(begin).ptr(), - end != INT_MAX ? Py::Int(end).ptr() : nullptr, - step != 1 ? Py::Int(step).ptr() : nullptr), + Py::Object slice(PySlice_New(Py::Long(begin).ptr(), + end != INT_MAX ? Py::Long(end).ptr() : nullptr, + step != 1 ? Py::Long(step).ptr() : nullptr), true); if (PyObject_SetItem(pyobj.ptr(), slice.ptr(), value.ptr()) < 0) { Base::PyException::ThrowException(); @@ -759,7 +759,7 @@ void ObjectIdentifier::Component::del(Py::Object& pyobj) const } else if (isArray()) { if (pyobj.isMapping()) { - Py::Mapping(pyobj).delItem(Py::Int(begin)); + Py::Mapping(pyobj).delItem(Py::Long(begin)); } else { PySequence_DelItem(pyobj.ptr(), begin); @@ -770,9 +770,9 @@ void ObjectIdentifier::Component::del(Py::Object& pyobj) const } else { assert(isRange()); - Py::Object slice(PySlice_New(Py::Int(begin).ptr(), - end != INT_MAX ? Py::Int(end).ptr() : nullptr, - step != 1 ? Py::Int(step).ptr() : nullptr), + Py::Object slice(PySlice_New(Py::Long(begin).ptr(), + end != INT_MAX ? Py::Long(end).ptr() : nullptr, + step != 1 ? Py::Long(step).ptr() : nullptr), true); if (PyObject_DelItem(pyobj.ptr(), slice.ptr()) < 0) { Base::PyException::ThrowException(); @@ -1828,7 +1828,7 @@ ObjectIdentifier::access(const ResolveResults& result, Py::Object* value, Depend auto container = result.resolvedProperty->getContainer(); if (container && container != result.resolvedDocumentObject && container != result.resolvedSubObject) { - if (!container->isDerivedFrom(DocumentObject::getClassTypeId())) { + if (!container->isDerivedFrom()) { FC_WARN("Invalid property container"); } else { diff --git a/src/App/OriginGroupExtension.cpp b/src/App/OriginGroupExtension.cpp index 369db51bad..5b8a9a0163 100644 --- a/src/App/OriginGroupExtension.cpp +++ b/src/App/OriginGroupExtension.cpp @@ -62,7 +62,7 @@ App::Origin* OriginGroupExtension::getOrigin() const err << "Can't find Origin for \"" << getExtendedObject()->getFullName() << "\""; throw Base::RuntimeError(err.str().c_str()); } - else if (!originObj->isDerivedFrom(App::Origin::getClassTypeId())) { + else if (!originObj->isDerivedFrom()) { std::stringstream err; err << "Bad object \"" << originObj->getFullName() << "\"(" << originObj->getTypeId().getName() << ") linked to the Origin of \"" @@ -114,7 +114,7 @@ App::DocumentObject* OriginGroupExtension::getGroupOfObject(const DocumentObject return nullptr; } - bool isOriginFeature = obj->isDerivedFrom(App::DatumElement::getClassTypeId()); + bool isOriginFeature = obj->isDerivedFrom(); auto list = obj->getInList(); for (auto o : list) { @@ -122,7 +122,7 @@ App::DocumentObject* OriginGroupExtension::getGroupOfObject(const DocumentObject return o; } else if (isOriginFeature - && o->isDerivedFrom(App::LocalCoordinateSystem::getClassTypeId())) { + && o->isDerivedFrom()) { auto result = getGroupOfObject(o); if (result) { return result; @@ -158,7 +158,7 @@ App::DocumentObjectExecReturn* OriginGroupExtension::extensionExecute() App::DocumentObject* OriginGroupExtension::getLocalizedOrigin(App::Document* doc) { - App::DocumentObject* originObject = doc->addObject("App::Origin", "Origin"); + auto* originObject = doc->addObject("Origin"); QByteArray byteArray = tr("Origin").toUtf8(); originObject->Label.setValue(byteArray.constData()); return originObject; @@ -170,7 +170,7 @@ void OriginGroupExtension::onExtendedSetupObject() App::DocumentObject* originObj = getLocalizedOrigin(doc); - assert(originObj && originObj->isDerivedFrom(App::Origin::getClassTypeId())); + assert(originObj && originObj->isDerivedFrom()); Origin.setValue(originObj); GeoFeatureGroupExtension::onExtendedSetupObject(); diff --git a/src/App/Part.cpp b/src/App/Part.cpp index 68feeaa88b..b43b60db24 100644 --- a/src/App/Part.cpp +++ b/src/App/Part.cpp @@ -75,7 +75,7 @@ static App::Part* _getPartOfObject(const DocumentObject* obj, } auto group = inObj->getExtensionByType(true); if (group && group->hasObject(obj)) { - if (inObj->isDerivedFrom(App::Part::getClassTypeId())) { + if (inObj->isDerivedFrom()) { return static_cast(inObj); } else if (objset) { diff --git a/src/App/PreCompiled.h b/src/App/PreCompiled.h index 57cafc2a35..0523bf5744 100644 --- a/src/App/PreCompiled.h +++ b/src/App/PreCompiled.h @@ -100,6 +100,9 @@ #include #include #include +#include + +#include #endif //_PreComp_ diff --git a/src/App/ProjectFile.cpp b/src/App/ProjectFile.cpp index 03dbac3df1..7cc7490100 100644 --- a/src/App/ProjectFile.cpp +++ b/src/App/ProjectFile.cpp @@ -84,12 +84,12 @@ public: std::map propMap = initMap(); - DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStr("Properties").unicodeForm()); + DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStrLiteral("Properties").unicodeForm()); for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { auto elem = static_cast(node); // NOLINT - DOMNodeList* propList = elem->getElementsByTagName(XStr("Property").unicodeForm()); + DOMNodeList* propList = elem->getElementsByTagName(XStrLiteral("Property").unicodeForm()); for (XMLSize_t j = 0; j < propList->getLength(); j++) { DOMNode* propNode = propList->item(j); readProperty(propNode, propMap); @@ -105,12 +105,12 @@ private: void readProgramVersion() { if (DOMNodeList* nodes = - xmlDocument->getElementsByTagName(XStr("Document").unicodeForm())) { + xmlDocument->getElementsByTagName(XStrLiteral("Document").unicodeForm())) { for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { DOMNode* nameAttr = - node->getAttributes()->getNamedItem(XStr("ProgramVersion").unicodeForm()); + node->getAttributes()->getNamedItem(XStrLiteral("ProgramVersion").unicodeForm()); if (nameAttr) { std::string value = StrX(nameAttr->getNodeValue()).c_str(); metadata.programVersion = value; @@ -153,7 +153,7 @@ private: static void readProperty(DOMNode* propNode, std::map& propMap) { - DOMNode* nameAttr = propNode->getAttributes()->getNamedItem(XStr("name").unicodeForm()); + DOMNode* nameAttr = propNode->getAttributes()->getNamedItem(XStrLiteral("name").unicodeForm()); if (nameAttr) { std::string name = StrX(nameAttr->getNodeValue()).c_str(); auto it = propMap.find(name); @@ -169,7 +169,7 @@ private: if (DOMElement* child = static_cast(node)->getFirstElementChild()) { // NOLINT if (DOMNode* nameAttr = - child->getAttributes()->getNamedItem(XStr("value").unicodeForm())) { + child->getAttributes()->getNamedItem(XStrLiteral("value").unicodeForm())) { std::string value = StrX(nameAttr->getNodeValue()).c_str(); return value; } @@ -260,18 +260,18 @@ std::list ProjectFile::getObjects() const return names; } - DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStr("Objects").unicodeForm()); + DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStrLiteral("Objects").unicodeForm()); for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { DOMNodeList* objectList = static_cast(node)->getElementsByTagName( - XStr("Object").unicodeForm()); // NOLINT + XStrLiteral("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* typeAttr = - objectNode->getAttributes()->getNamedItem(XStr("type").unicodeForm()); + objectNode->getAttributes()->getNamedItem(XStrLiteral("type").unicodeForm()); DOMNode* nameAttr = - objectNode->getAttributes()->getNamedItem(XStr("name").unicodeForm()); + objectNode->getAttributes()->getNamedItem(XStrLiteral("name").unicodeForm()); if (typeAttr && nameAttr) { Object obj; obj.name = StrX(nameAttr->getNodeValue()).c_str(); @@ -292,18 +292,18 @@ std::list ProjectFile::getObjectsOfType(const Base::Type& typeId) c return names; } - DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStr("Objects").unicodeForm()); + DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStrLiteral("Objects").unicodeForm()); for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { DOMNodeList* objectList = static_cast(node)->getElementsByTagName( - XStr("Object").unicodeForm()); // NOLINT + XStrLiteral("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* typeAttr = - objectNode->getAttributes()->getNamedItem(XStr("type").unicodeForm()); + objectNode->getAttributes()->getNamedItem(XStrLiteral("type").unicodeForm()); DOMNode* nameAttr = - objectNode->getAttributes()->getNamedItem(XStr("name").unicodeForm()); + objectNode->getAttributes()->getNamedItem(XStrLiteral("name").unicodeForm()); if (typeAttr && nameAttr) { if (Base::Type::fromName(StrX(typeAttr->getNodeValue()).c_str()) == typeId) { names.emplace_back(StrX(nameAttr->getNodeValue()).c_str()); @@ -366,18 +366,18 @@ Base::Type ProjectFile::getTypeId(const std::string& name) const return Base::Type::badType(); } - DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStr("Objects").unicodeForm()); + DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStrLiteral("Objects").unicodeForm()); for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { DOMNodeList* objectList = static_cast(node)->getElementsByTagName( - XStr("Object").unicodeForm()); // NOLINT + XStrLiteral("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* typeAttr = - objectNode->getAttributes()->getNamedItem(XStr("type").unicodeForm()); + objectNode->getAttributes()->getNamedItem(XStrLiteral("type").unicodeForm()); DOMNode* nameAttr = - objectNode->getAttributes()->getNamedItem(XStr("name").unicodeForm()); + objectNode->getAttributes()->getNamedItem(XStrLiteral("name").unicodeForm()); if (typeAttr && nameAttr) { if (strcmp(name.c_str(), StrX(nameAttr->getNodeValue()).c_str()) == 0) { std::string typeId = StrX(typeAttr->getNodeValue()).c_str(); @@ -407,16 +407,16 @@ std::list ProjectFile::getPropertyFiles(const std::st } std::list files; - DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStr("ObjectData").unicodeForm()); + DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStrLiteral("ObjectData").unicodeForm()); for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { DOMNodeList* objectList = static_cast(node)->getElementsByTagName( - XStr("Object").unicodeForm()); // NOLINT + XStrLiteral("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* nameAttr = - objectNode->getAttributes()->getNamedItem(XStr("name").unicodeForm()); + objectNode->getAttributes()->getNamedItem(XStrLiteral("name").unicodeForm()); if (nameAttr && strcmp(name.c_str(), StrX(nameAttr->getNodeValue()).c_str()) == 0) { // now go recursively through the sub-tree (i.e. the properties) and collect // every file attribute @@ -434,18 +434,18 @@ void ProjectFile::findFiles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node, { if (node->hasAttributes()) { ProjectFile::PropertyFile prop; - DOMNode* fileAttr = node->getAttributes()->getNamedItem(XStr("file").unicodeForm()); + DOMNode* fileAttr = node->getAttributes()->getNamedItem(XStrLiteral("file").unicodeForm()); if (fileAttr) { DOMNode* parentNode = node->getParentNode(); if (parentNode) { DOMNode* nameAttr = - parentNode->getAttributes()->getNamedItem(XStr("name").unicodeForm()); + parentNode->getAttributes()->getNamedItem(XStrLiteral("name").unicodeForm()); if (nameAttr) { prop.name = StrX(nameAttr->getNodeValue()).c_str(); } DOMNode* typeAttr = - parentNode->getAttributes()->getNamedItem(XStr("type").unicodeForm()); + parentNode->getAttributes()->getNamedItem(XStrLiteral("type").unicodeForm()); if (typeAttr) { prop.type = Base::Type::fromName(StrX(typeAttr->getNodeValue()).c_str()); } @@ -486,16 +486,16 @@ std::list ProjectFile::getInputFiles(const std::string& name) const } std::list files; - DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStr("ObjectData").unicodeForm()); + DOMNodeList* nodes = xmlDocument->getElementsByTagName(XStrLiteral("ObjectData").unicodeForm()); for (XMLSize_t i = 0; i < nodes->getLength(); i++) { DOMNode* node = nodes->item(i); if (node->getNodeType() == DOMNode::ELEMENT_NODE) { DOMNodeList* objectList = static_cast(node)->getElementsByTagName( - XStr("Object").unicodeForm()); // NOLINT + XStrLiteral("Object").unicodeForm()); // NOLINT for (XMLSize_t j = 0; j < objectList->getLength(); j++) { DOMNode* objectNode = objectList->item(j); DOMNode* nameAttr = - objectNode->getAttributes()->getNamedItem(XStr("name").unicodeForm()); + objectNode->getAttributes()->getNamedItem(XStrLiteral("name").unicodeForm()); if (nameAttr && strcmp(name.c_str(), StrX(nameAttr->getNodeValue()).c_str()) == 0) { // now go recursively through the sub-tree (i.e. the properties) and collect // every file attribute @@ -512,7 +512,7 @@ void ProjectFile::findFiles(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node, std::list& files) const { if (node->hasAttributes()) { - DOMNode* fileAttr = node->getAttributes()->getNamedItem(XStr("file").unicodeForm()); + DOMNode* fileAttr = node->getAttributes()->getNamedItem(XStrLiteral("file").unicodeForm()); if (fileAttr) { files.emplace_back(StrX(fileAttr->getNodeValue()).c_str()); } diff --git a/src/App/PropertyContainer.h b/src/App/PropertyContainer.h index 819e4d8c1f..5a6b7647ae 100644 --- a/src/App/PropertyContainer.h +++ b/src/App/PropertyContainer.h @@ -305,6 +305,49 @@ private: \ /// Like PROPERTY_HEADER, but with overridden methods declared as such #define PROPERTY_HEADER_WITH_OVERRIDE(_class_) \ TYPESYSTEM_HEADER_WITH_OVERRIDE(); \ +public: \ + static constexpr const char* getClassName() {\ + /* + TODO: When c++20 is available \ + - Use consteval to ensure the function is evaluated at compile time \ + - Move bulk of the function to a template `validate()` \ + - Use `starts_with` when checking namespace in path \ + */ \ + \ + static_assert(sizeof(_class_) > 0, "Class is not complete"); \ + \ + constexpr const char* sClass = #_class_; \ + constexpr std::string_view vClass {sClass}; \ + static_assert(vClass[0] != '\0', "Class name must not be empty"); \ + static_assert(std::is_base_of::value, \ + "Class must be derived from App::PropertyContainer"); \ + \ + constexpr bool isSubClassOfDocObj = std::is_base_of::value && \ + !std::is_same::value; \ + if constexpr (isSubClassOfDocObj) { \ + constexpr auto pos = vClass.find("::"); \ + static_assert(pos != std::string_view::npos, \ + "Class name must be fully qualified for document object derived classes"); \ + static_assert(pos != 0, "Namespace must not be empty"); \ + \ + constexpr auto vNamespace = vClass.substr(0, pos); \ + constexpr std::string_view filePath = __FILE__; \ + constexpr auto posAfterSrcMod = filePath.find("/src/Mod/"); \ + if constexpr (constexpr bool hasSrcModInPath = posAfterSrcMod != std::string_view::npos) { \ + constexpr auto pathAfterSrcMod = filePath.substr(posAfterSrcMod + 9); \ + /* some workarounds are needed, if CI is ok in the future, remove these: \ + - isSubClassOfDocObj shouldn't be needed, but it is for some compilers \ + - allowing `Path` until it's been properly renamed */ \ + constexpr bool workarounds = !isSubClassOfDocObj || vNamespace == "Path"; \ + /* TODO: use `starts_with` instead of `find` when c++20 is available */ \ + constexpr bool isPathOk = pathAfterSrcMod.find(vNamespace) != std::string_view::npos; \ + static_assert(workarounds || isPathOk, \ + "Classes in `src/Mod` needs to be in a directory with the same name as" \ + " the namespace in order to load correctly"); \ + } \ + } \ + return sClass; \ + } \ protected: \ static const App::PropertyData * getPropertyDataPtr(void); \ const App::PropertyData &getPropertyData(void) const override; \ diff --git a/src/App/PropertyContainerPyImp.cpp b/src/App/PropertyContainerPyImp.cpp index 4700b5a090..6cff166d53 100644 --- a/src/App/PropertyContainerPyImp.cpp +++ b/src/App/PropertyContainerPyImp.cpp @@ -86,7 +86,7 @@ PyObject* PropertyContainerPy::getPropertyTouchList(PyObject* args) } App::Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr); - if (prop && prop->isDerivedFrom(PropertyLists::getClassTypeId())) { + if (prop && prop->isDerivedFrom()) { const auto& touched = static_cast(prop)->getTouchList(); Py::Tuple ret(touched.size()); int i = 0; @@ -284,7 +284,7 @@ PyObject* PropertyContainerPy::setPropertyStatus(PyObject* args) status.set(it->second, value); } else if (item.isNumeric()) { - int v = Py::Int(item); + int v = Py::Long(item); if (v < 0) { value = false; v = -v; @@ -345,7 +345,7 @@ PyObject* PropertyContainerPy::getPropertyStatus(PyObject* args) } } if (!found) { - ret.append(Py::Int(static_cast(i))); + ret.append(Py::Long(static_cast(i))); } } } @@ -647,7 +647,7 @@ PyObject* PropertyContainerPy::getCustomAttributes(const char* attr) const } /// FIXME: For v0.20: Do not use stuff from Part module here! if (Base::streq(attr, "Shape") - && getPropertyContainerPtr()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + && getPropertyContainerPtr()->isDerivedFrom()) { // Special treatment of Shape property static PyObject* _getShape = nullptr; if (!_getShape) { diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index eec521f391..103e7d5246 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -78,7 +78,7 @@ std::string PropertyFileIncluded::getDocTransientPath() const { std::string path; PropertyContainer* co = getContainer(); - if (co->isDerivedFrom(DocumentObject::getClassTypeId())) { + if (co->isDerivedFrom()) { path = static_cast(co)->getDocument()->TransientDir.getValue(); std::replace(path.begin(), path.end(), '\\', '/'); } diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index 3ba3b5984f..4e62852138 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -99,7 +99,7 @@ bool PropertyLinkBase::isSame(const Property& other) const if (&other == this) { return true; } - if (other.isDerivedFrom(PropertyLinkBase::getClassTypeId()) + if (other.isDerivedFrom() || getScope() != static_cast(&other)->getScope()) { return false; } @@ -692,7 +692,7 @@ void PropertyLink::resetLink() #ifndef USE_OLD_DAG // maintain the back link in the DocumentObject class if it is from a document object if (_pcScope != LinkScope::Hidden && _pcLink && getContainer() - && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + && getContainer()->isDerivedFrom()) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers @@ -741,7 +741,7 @@ App::DocumentObject* PropertyLink::getValue() const App::DocumentObject* PropertyLink::getValue(Base::Type t) const { - return (_pcLink && _pcLink->getTypeId().isDerivedFrom(t)) ? _pcLink : nullptr; + return (_pcLink && _pcLink->isDerivedFrom(t)) ? _pcLink : nullptr; } PyObject* PropertyLink::getPyObject() @@ -817,7 +817,7 @@ Property* PropertyLink::Copy() const void PropertyLink::Paste(const Property& from) { - if (!from.isDerivedFrom(PropertyLink::getClassTypeId())) { + if (!from.isDerivedFrom()) { throw Base::TypeError("Incompatible property to paste to"); } @@ -897,7 +897,7 @@ PropertyLinkList::~PropertyLinkList() #ifndef USE_OLD_DAG // maintain the back link in the DocumentObject class if (_pcScope != LinkScope::Hidden && !_lValueList.empty() && getContainer() - && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + && getContainer()->isDerivedFrom()) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers @@ -955,7 +955,7 @@ void PropertyLinkList::set1Value(int idx, DocumentObject* const& value) _nameMap.clear(); #ifndef USE_OLD_DAG - if (getContainer() && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (getContainer() && getContainer()->isDerivedFrom()) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers @@ -1150,7 +1150,7 @@ Property* PropertyLinkList::Copy() const void PropertyLinkList::Paste(const Property& from) { - if (!from.isDerivedFrom(PropertyLinkList::getClassTypeId())) { + if (!from.isDerivedFrom()) { throw Base::TypeError("Incompatible property to paste to"); } @@ -1299,7 +1299,7 @@ PropertyLinkSub::~PropertyLinkSub() // in case this property is dynamically removed #ifndef USE_OLD_DAG if (_pcLinkSub && getContainer() - && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + && getContainer()->isDerivedFrom()) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers @@ -1430,7 +1430,7 @@ std::vector PropertyLinkSub::getSubValuesStartsWith(const char* sta App::DocumentObject* PropertyLinkSub::getValue(Base::Type t) const { - return (_pcLinkSub && _pcLinkSub->getTypeId().isDerivedFrom(t)) ? _pcLinkSub : nullptr; + return (_pcLinkSub && _pcLinkSub->isDerivedFrom(t)) ? _pcLinkSub : nullptr; } PyObject* PropertyLinkSub::getPyObject() @@ -2054,7 +2054,7 @@ Property* PropertyLinkSub::Copy() const void PropertyLinkSub::Paste(const Property& from) { - if (!from.isDerivedFrom(PropertyLinkSub::getClassTypeId())) { + if (!from.isDerivedFrom()) { throw Base::TypeError("Incompatible property to paste to"); } auto& link = static_cast(from); @@ -2178,7 +2178,7 @@ PropertyLinkSubList::~PropertyLinkSubList() #ifndef USE_OLD_DAG // maintain backlinks if (!_lValueList.empty() && getContainer() - && getContainer()->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + && getContainer()->isDerivedFrom()) { App::DocumentObject* parent = static_cast(getContainer()); // before accessing internals make sure the object is not about to be destroyed // otherwise the backlink contains dangling pointers @@ -3112,7 +3112,7 @@ Property* PropertyLinkSubList::Copy() const void PropertyLinkSubList::Paste(const Property& from) { - if (!from.isDerivedFrom(PropertyLinkSubList::getClassTypeId())) { + if (!from.isDerivedFrom()) { throw Base::TypeError("Incompatible property to paste to"); } auto& link = static_cast(from); @@ -4430,7 +4430,7 @@ Property* PropertyXLink::Copy() const void PropertyXLink::Paste(const Property& from) { - if (!from.isDerivedFrom(PropertyXLink::getClassTypeId())) { + if (!from.isDerivedFrom()) { throw Base::TypeError("Incompatible property to paste to"); } @@ -4461,9 +4461,9 @@ void PropertyXLink::Paste(const Property& from) bool PropertyXLink::supportXLink(const App::Property* prop) { - return prop->isDerivedFrom(PropertyXLink::getClassTypeId()) - || prop->isDerivedFrom(PropertyXLinkSubList::getClassTypeId()) - || prop->isDerivedFrom(PropertyXLinkContainer::getClassTypeId()); + return prop->isDerivedFrom() + || prop->isDerivedFrom() + || prop->isDerivedFrom(); } bool PropertyXLink::hasXLink(const App::Document* doc) @@ -5299,7 +5299,7 @@ Property* PropertyXLinkSubList::Copy() const void PropertyXLinkSubList::Paste(const Property& from) { - if (!from.isDerivedFrom(PropertyXLinkSubList::getClassTypeId())) { + if (!from.isDerivedFrom()) { throw Base::TypeError("Incompatible property to paste to"); } diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index 96e3984005..238df5d8b5 100644 --- a/src/App/PropertyStandard.cpp +++ b/src/App/PropertyStandard.cpp @@ -177,7 +177,7 @@ PropertyPath::~PropertyPath() = default; //************************************************************************** // Setter/getter for the property -void PropertyPath::setValue(const boost::filesystem::path& Path) +void PropertyPath::setValue(const std::filesystem::path& Path) { aboutToSetValue(); _cValue = Path; @@ -187,15 +187,11 @@ void PropertyPath::setValue(const boost::filesystem::path& Path) void PropertyPath::setValue(const char* Path) { aboutToSetValue(); -#if (BOOST_FILESYSTEM_VERSION == 2) - _cValue = boost::filesystem::path(Path, boost::filesystem::no_check); -#else - _cValue = boost::filesystem::path(Path); -#endif + _cValue = std::filesystem::path(Path); hasSetValue(); } -const boost::filesystem::path& PropertyPath::getValue() const +const std::filesystem::path& PropertyPath::getValue() const { return _cValue; } @@ -491,7 +487,7 @@ void PropertyEnumeration::setPyObject(PyObject* value) if (seq.size() == 2) { Py::Object v(seq[0].ptr()); if (!v.isString() && v.isSequence()) { - idx = Py::Int(seq[1].ptr()); + idx = Py::Long(seq[1].ptr()); seq = v; } } @@ -608,7 +604,7 @@ bool PropertyEnumeration::getPyPathValue(const ObjectIdentifier& path, Py::Objec else { Py::Tuple tuple(2); tuple.setItem(0, res); - tuple.setItem(1, Py::Int(getValue())); + tuple.setItem(1, Py::Long(getValue())); r = tuple; } } @@ -617,7 +613,7 @@ bool PropertyEnumeration::getPyPathValue(const ObjectIdentifier& path, Py::Objec r = Py::String(v ? v : ""); } else { - r = Py::Int(getValue()); + r = Py::Long(getValue()); } return true; } @@ -1970,17 +1966,14 @@ PyObject* PropertyMap::getPyObject() void PropertyMap::setPyObject(PyObject* value) { - if (PyDict_Check(value)) { - + if (PyMapping_Check(value)) { std::map values; // get key and item list - PyObject* keyList = PyDict_Keys(value); - - PyObject* itemList = PyDict_Values(value); + PyObject* keyList = PyMapping_Keys(value); + PyObject* itemList = PyMapping_Values(value); Py_ssize_t nSize = PyList_Size(keyList); for (Py_ssize_t i = 0; i < nSize; ++i) { - // check on the key: std::string keyStr; PyObject* key = PyList_GetItem(keyList, i); @@ -1988,7 +1981,7 @@ void PropertyMap::setPyObject(PyObject* value) keyStr = PyUnicode_AsUTF8(key); } else { - std::string error("type of the key need to be unicode or string, not"); + std::string error("type of the key need to be string, not "); error += key->ob_type->tp_name; throw Base::TypeError(error); } @@ -1999,16 +1992,19 @@ void PropertyMap::setPyObject(PyObject* value) values[keyStr] = PyUnicode_AsUTF8(item); } else { - std::string error("type in list must be string or unicode, not "); + std::string error("type in values must be string, not "); error += item->ob_type->tp_name; throw Base::TypeError(error); } } + Py_XDECREF(itemList); + Py_XDECREF(keyList); + setValues(values); } else { - std::string error("type must be a dict object"); + std::string error("type must be a dict or object with mapping protocol, not "); error += value->ob_type->tp_name; throw Base::TypeError(error); } diff --git a/src/App/PropertyStandard.h b/src/App/PropertyStandard.h index d592935d62..e85f985323 100644 --- a/src/App/PropertyStandard.h +++ b/src/App/PropertyStandard.h @@ -117,7 +117,7 @@ public: /** Sets the property */ - void setValue(const boost::filesystem::path&); + void setValue(const std::filesystem::path&); /** Sets the property */ @@ -125,7 +125,7 @@ public: /** This method returns a string representation of the property */ - const boost::filesystem::path& getValue() const; + const std::filesystem::path& getValue() const; const char* getEditorName() const override { @@ -153,7 +153,7 @@ public: } protected: - boost::filesystem::path _cValue; + std::filesystem::path _cValue; }; /// Property wrapper around an Enumeration object. diff --git a/src/App/PropertyUnits.cpp b/src/App/PropertyUnits.cpp index b18ea6b65f..b4ed219cd9 100644 --- a/src/App/PropertyUnits.cpp +++ b/src/App/PropertyUnits.cpp @@ -392,6 +392,17 @@ PropertyElectricCharge::PropertyElectricCharge() setUnit(Base::Unit::ElectricCharge); } +//************************************************************************** +// PropertySurfaceChargeDensity +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPESYSTEM_SOURCE(App::PropertySurfaceChargeDensity, App::PropertyQuantity) + +PropertySurfaceChargeDensity::PropertySurfaceChargeDensity() +{ + setUnit(Base::Unit::SurfaceChargeDensity); +} + //************************************************************************** // PropertyElectricCurrent //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/src/App/PropertyUnits.h b/src/App/PropertyUnits.h index 8a19ead0ce..e81a8fd9c3 100644 --- a/src/App/PropertyUnits.h +++ b/src/App/PropertyUnits.h @@ -361,6 +361,19 @@ public: ~PropertyElectricCharge() override = default; }; +/** SurfaceChargeDensity property + * This is a property for representing surface charge density. It is basically a float + * property. On the Gui it has a quantity like C/m^2. + */ +class AppExport PropertySurfaceChargeDensity: public PropertyQuantity +{ + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + +public: + PropertySurfaceChargeDensity(); + ~PropertySurfaceChargeDensity() override = default; +}; + /** ElectricCurrent property * This is a property for representing electric currents. It is basically a * float property. On the Gui it has a quantity like A. diff --git a/src/App/StringHasher.cpp b/src/App/StringHasher.cpp index 7cdc892dd1..3e2a211841 100644 --- a/src/App/StringHasher.cpp +++ b/src/App/StringHasher.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include "MappedElement.h" diff --git a/src/App/StringHasherPy.xml b/src/App/StringHasherPy.xml index ff7d8e1dbf..dc37148184 100644 --- a/src/App/StringHasherPy.xml +++ b/src/App/StringHasherPy.xml @@ -40,13 +40,13 @@ base64: indicate if the input 'txt' is base64 encoded binary data Return count of used hashes - + Return the size of the hashes - + @@ -58,7 +58,7 @@ base64: indicate if the input 'txt' is base64 encoded binary data Data length exceed this threshold will be hashed before storing - + diff --git a/src/App/StringIDPy.xml b/src/App/StringIDPy.xml index de77d7c97a..acee95d628 100644 --- a/src/App/StringIDPy.xml +++ b/src/App/StringIDPy.xml @@ -24,7 +24,7 @@ Return the integer value of this ID - + @@ -54,7 +54,7 @@ Geometry index. Only meaningful for geometry element name - + private: friend class StringID; diff --git a/src/Base/BaseClass.h b/src/Base/BaseClass.h index df658b6513..33d7ced2f2 100644 --- a/src/Base/BaseClass.h +++ b/src/Base/BaseClass.h @@ -156,16 +156,10 @@ public: } template - bool is() const - { - return getTypeId() == T::getClassTypeId(); - } + bool is() const; template - bool isDerivedFrom() const - { - return getTypeId().isDerivedFrom(T::getClassTypeId()); - } + bool isDerivedFrom() const; private: static Type classTypeId; // NOLINT @@ -187,6 +181,20 @@ public: virtual ~BaseClass(); }; +template +bool BaseClass::is() const +{ + static_assert(std::is_base_of::value, "T must be derived from Base::BaseClass"); + return getTypeId() == T::getClassTypeId(); +} + +template +bool BaseClass::isDerivedFrom() const +{ + static_assert(std::is_base_of::value, "T must be derived from Base::BaseClass"); + return getTypeId().isDerivedFrom(T::getClassTypeId()); +} + /** * Template that works just like dynamic_cast, but expects the argument to * inherit from Base::BaseClass. @@ -195,6 +203,8 @@ public: template T* freecad_dynamic_cast(Base::BaseClass* type) { + static_assert(std::is_base_of::value, "T must be derived from Base::BaseClass"); + if (type && type->isDerivedFrom(T::getClassTypeId())) { return static_cast(type); } @@ -210,6 +220,8 @@ T* freecad_dynamic_cast(Base::BaseClass* type) template const T* freecad_dynamic_cast(const Base::BaseClass* type) { + static_assert(std::is_base_of::value, "T must be derived from Base::BaseClass"); + if (type && type->isDerivedFrom(T::getClassTypeId())) { return static_cast(type); } diff --git a/src/Base/BoundBoxPy.xml b/src/Base/BoundBoxPy.xml index 0af425be10..86e04940ba 100644 --- a/src/Base/BoundBoxPy.xml +++ b/src/Base/BoundBoxPy.xml @@ -64,7 +64,7 @@ max : Base.Vector, tuple Invalidate the bounding box. - + isValid() -> bool @@ -90,9 +90,9 @@ z : float Value to enlarge at z-direction. - + - getPoint(index) ->Base.Vector + getPoint(index) -> Base.Vector Get the point of the given index. The index must be in the range of [0, 7]. @@ -100,7 +100,7 @@ The index must be in the range of [0, 7]. index : int - + getEdge(index) -> tuple of Base.Vector @@ -110,7 +110,7 @@ The index must be in the range of [0, 11]. index : int - + closestPoint(point) -> Base.Vector closestPoint(x, y, z) -> Base.Vector diff --git a/src/Base/FileInfo.cpp b/src/Base/FileInfo.cpp index e5669ca658..d10a3c65b1 100644 --- a/src/Base/FileInfo.cpp +++ b/src/Base/FileInfo.cpp @@ -208,18 +208,18 @@ std::string FileInfo::getTempFileName(const char* FileName, const char* Path) #endif } -boost::filesystem::path FileInfo::stringToPath(const std::string& str) +std::filesystem::path FileInfo::stringToPath(const std::string& str) { #if defined(FC_OS_WIN32) std::wstring_convert> converter; - boost::filesystem::path path(converter.from_bytes(str)); + std::filesystem::path path(converter.from_bytes(str)); #else - boost::filesystem::path path(str); + std::filesystem::path path(str); #endif return path; } -std::string FileInfo::pathToString(const boost::filesystem::path& path) +std::string FileInfo::pathToString(const std::filesystem::path& path) { #if defined(FC_OS_WIN32) std::wstring_convert> converter; @@ -583,14 +583,14 @@ bool FileInfo::createDirectory() const bool FileInfo::createDirectories() const { try { - boost::filesystem::path path(stringToPath(FileName)); - if (boost::filesystem::exists(path)) { + std::filesystem::path path(stringToPath(FileName)); + if (std::filesystem::exists(path)) { return true; } - boost::filesystem::create_directories(path); + std::filesystem::create_directories(path); return true; } - catch (const boost::filesystem::filesystem_error&) { + catch (const std::filesystem::filesystem_error&) { return false; } } diff --git a/src/Base/FileInfo.h b/src/Base/FileInfo.h index 502dec3f4a..7e0ddbb9a4 100644 --- a/src/Base/FileInfo.h +++ b/src/Base/FileInfo.h @@ -25,7 +25,7 @@ #ifndef BASE_FILEINFO_H #define BASE_FILEINFO_H -#include +#include #include #include #include @@ -158,9 +158,9 @@ public: /// Get the path to the dir which is considered to temp files static const std::string& getTempPath(); /// Convert from filesystem path to string - static std::string pathToString(const boost::filesystem::path& path); + static std::string pathToString(const std::filesystem::path& path); /// Convert from string to filesystem path - static boost::filesystem::path stringToPath(const std::string& str); + static std::filesystem::path stringToPath(const std::string& str); //@} private: diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp index 2bdc54ccff..41f592e4b8 100644 --- a/src/Base/Interpreter.cpp +++ b/src/Base/Interpreter.cpp @@ -557,7 +557,7 @@ const char* InterpreterSingleton::init(int argc, char* argv[]) PyRun_SimpleString( "# Check for virtualenv, and activate if present.\n" "# See " - "https://virtualenv.pypa.io/en/latest/userguide/" + "https://virtualenv.pypa.io/en/latest/" "#using-virtualenv-without-bin-python\n" "import os\n" "import sys\n" diff --git a/src/Base/MatrixPy.xml b/src/Base/MatrixPy.xml index cd70049b76..e3bd475120 100644 --- a/src/Base/MatrixPy.xml +++ b/src/Base/MatrixPy.xml @@ -99,7 +99,8 @@ tol : float - decompose() -> Base.Matrix, Base.Matrix, Base.Matrix, Base.Matrix\n + decompose() -> Base.Matrix, Base.Matrix, Base.Matrix, Base.Matrix + Return a tuple of matrices representing shear, scale, rotation and move. So that matrix = move * rotation * scale * shear. diff --git a/src/Base/MatrixPyImp.cpp b/src/Base/MatrixPyImp.cpp index fbd21b4688..029f57af2c 100644 --- a/src/Base/MatrixPyImp.cpp +++ b/src/Base/MatrixPyImp.cpp @@ -212,7 +212,7 @@ PyObject* MatrixPy::number_power_handler(PyObject* self, PyObject* other, PyObje Base::Matrix4D a = static_cast(self)->value(); - long b = Py::Int(other); + long b = Py::Long(other); if (b == 0) { return new MatrixPy(Matrix4D()); } @@ -363,7 +363,7 @@ PyObject* MatrixPy::hasScale(PyObject* args) ScaleType type = getMatrixPtr()->hasScale(tol); Py::Module mod("FreeCAD"); return Py::new_reference_to( - mod.callMemberFunction("ScaleType", Py::TupleN(Py::Int(static_cast(type))))); + mod.callMemberFunction("ScaleType", Py::TupleN(Py::Long(static_cast(type))))); } PyObject* MatrixPy::decompose(PyObject* args) diff --git a/src/Base/Parameter.cpp b/src/Base/Parameter.cpp index b2308a7804..3e02aae6e6 100644 --- a/src/Base/Parameter.cpp +++ b/src/Base/Parameter.cpp @@ -362,8 +362,9 @@ ParameterGrp::CreateElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start, const char* Type, const char* Name) { - if (XMLString::compareString(Start->getNodeName(), XStr("FCParamGroup").unicodeForm()) != 0 - && XMLString::compareString(Start->getNodeName(), XStr("FCParameters").unicodeForm()) + if (XMLString::compareString(Start->getNodeName(), XStrLiteral("FCParamGroup").unicodeForm()) + != 0 + && XMLString::compareString(Start->getNodeName(), XStrLiteral("FCParameters").unicodeForm()) != 0) { Base::Console().Warning("CreateElement: %s cannot have the element %s of type %s\n", StrX(Start->getNodeName()).c_str(), @@ -380,7 +381,7 @@ ParameterGrp::CreateElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* pDocument = Start->getOwnerDocument(); auto pcElem = pDocument->createElement(XStr(Type).unicodeForm()); - pcElem->setAttribute(XStr("Name").unicodeForm(), XStr(Name).unicodeForm()); + pcElem->setAttribute(XStrLiteral("Name").unicodeForm(), XStr(Name).unicodeForm()); Start->appendChild(pcElem); return pcElem; @@ -488,9 +489,10 @@ std::vector> ParameterGrp::GetGroups() DOMElement* pcTemp = FindElement(_pGroupNode, "FCParamGroup"); while (pcTemp) { - Name = - StrX(pcTemp->getAttributes()->getNamedItem(XStr("Name").unicodeForm())->getNodeValue()) - .c_str(); + Name = StrX(pcTemp->getAttributes() + ->getNamedItem(XStrLiteral("Name").unicodeForm()) + ->getNodeValue()) + .c_str(); // already created? if (!(rParamGrp = _GroupMap[Name]).isValid()) { rParamGrp = Base::Reference(new ParameterGrp(pcTemp, Name.c_str(), this)); @@ -630,7 +632,7 @@ const char* ParameterGrp::GetAttribute(ParamType Type, Value = GetASCII(Name, Default); } else if (Type != ParamType::FCGroup) { - Value = StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str(); + Value = StrX(pcElem->getAttribute(XStrLiteral("Value").unicodeForm())).c_str(); } return Value.c_str(); } @@ -654,7 +656,7 @@ ParameterGrp::GetAttributeMap(ParamType Type, const char* sFilter) const while (pcTemp) { Name = StrX(static_cast(pcTemp) ->getAttributes() - ->getNamedItem(XStr("Name").unicodeForm()) + ->getNamedItem(XStrLiteral("Name").unicodeForm()) ->getNodeValue()) .c_str(); // check on filter condition @@ -665,7 +667,7 @@ ParameterGrp::GetAttributeMap(ParamType Type, const char* sFilter) const else { res.emplace_back(Name, StrX(static_cast(pcTemp)->getAttribute( - XStr("Value").unicodeForm())) + XStrLiteral("Value").unicodeForm())) .c_str()); } } @@ -731,7 +733,8 @@ bool ParameterGrp::GetBool(const char* Name, bool bPreset) const } // if yes check the value and return - return (strcmp(StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str(), "1") == 0); + return (strcmp(StrX(pcElem->getAttribute(XStrLiteral("Value").unicodeForm())).c_str(), "1") + == 0); } void ParameterGrp::SetBool(const char* Name, bool bValue) @@ -750,10 +753,11 @@ std::vector ParameterGrp::GetBools(const char* sFilter) const DOMElement* pcTemp = FindElement(_pGroupNode, "FCBool"); while (pcTemp) { - Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrX(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { - if (strcmp(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str(), "1") != 0) { + if (strcmp(StrX(pcTemp->getAttribute(XStrLiteral("Value").unicodeForm())).c_str(), "1") + != 0) { vrValues.push_back(false); } else { @@ -777,10 +781,11 @@ std::vector> ParameterGrp::GetBoolMap(const char* s DOMElement* pcTemp = FindElement(_pGroupNode, "FCBool"); while (pcTemp) { - Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrX(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { - if (strcmp(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str(), "1") != 0) { + if (strcmp(StrX(pcTemp->getAttribute(XStrLiteral("Value").unicodeForm())).c_str(), "1") + != 0) { vrValues.emplace_back(Name, false); } else { @@ -806,7 +811,7 @@ long ParameterGrp::GetInt(const char* Name, long lPreset) const return lPreset; } // if yes check the value and return - return atol(StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str()); + return atol(StrX(pcElem->getAttribute(XStrLiteral("Value").unicodeForm())).c_str()); } void ParameterGrp::SetInt(const char* Name, long lValue) @@ -826,11 +831,11 @@ std::vector ParameterGrp::GetInts(const char* sFilter) const DOMElement* pcTemp = FindElement(_pGroupNode, "FCInt"); while (pcTemp) { - Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrX(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { vrValues.push_back( - atol(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str())); + atol(StrX(pcTemp->getAttribute(XStrLiteral("Value").unicodeForm())).c_str())); } pcTemp = FindNextElement(pcTemp, "FCInt"); } @@ -849,12 +854,12 @@ std::vector> ParameterGrp::GetIntMap(const char* sF DOMElement* pcTemp = FindElement(_pGroupNode, "FCInt"); while (pcTemp) { - Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrX(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { vrValues.emplace_back( Name, - (atol(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str()))); + (atol(StrX(pcTemp->getAttribute(XStrLiteral("Value").unicodeForm())).c_str()))); } pcTemp = FindNextElement(pcTemp, "FCInt"); } @@ -877,7 +882,9 @@ unsigned long ParameterGrp::GetUnsigned(const char* Name, unsigned long lPreset) // if yes check the value and return const int base = 10; - return strtoul(StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str(), nullptr, base); + return strtoul(StrX(pcElem->getAttribute(XStrLiteral("Value").unicodeForm())).c_str(), + nullptr, + base); } void ParameterGrp::SetUnsigned(const char* Name, unsigned long lValue) @@ -898,11 +905,11 @@ std::vector ParameterGrp::GetUnsigneds(const char* sFilter) const DOMElement* pcTemp = FindElement(_pGroupNode, "FCUInt"); while (pcTemp) { - Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrX(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { vrValues.push_back( - strtoul(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str(), + strtoul(StrX(pcTemp->getAttribute(XStrLiteral("Value").unicodeForm())).c_str(), nullptr, base)); } @@ -925,12 +932,12 @@ ParameterGrp::GetUnsignedMap(const char* sFilter) const DOMElement* pcTemp = FindElement(_pGroupNode, "FCUInt"); while (pcTemp) { - Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrX(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { vrValues.emplace_back( Name, - (strtoul(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str(), + (strtoul(StrX(pcTemp->getAttribute(XStrLiteral("Value").unicodeForm())).c_str(), nullptr, base))); } @@ -953,7 +960,7 @@ double ParameterGrp::GetFloat(const char* Name, double dPreset) const return dPreset; } // if yes check the value and return - return atof(StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str()); + return atof(StrX(pcElem->getAttribute(XStrLiteral("Value").unicodeForm())).c_str()); } void ParameterGrp::SetFloat(const char* Name, double dValue) @@ -974,11 +981,11 @@ std::vector ParameterGrp::GetFloats(const char* sFilter) const DOMElement* pcTemp = FindElement(_pGroupNode, "FCFloat"); while (pcTemp) { - Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrX(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { vrValues.push_back( - atof(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str())); + atof(StrX(pcTemp->getAttribute(XStrLiteral("Value").unicodeForm())).c_str())); } pcTemp = FindNextElement(pcTemp, "FCFloat"); } @@ -997,12 +1004,12 @@ std::vector> ParameterGrp::GetFloatMap(const char DOMElement* pcTemp = FindElement(_pGroupNode, "FCFloat"); while (pcTemp) { - Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrX(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { vrValues.emplace_back( Name, - (atof(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str()))); + (atof(StrX(pcTemp->getAttribute(XStrLiteral("Value").unicodeForm())).c_str()))); } pcTemp = FindNextElement(pcTemp, "FCFloat"); } @@ -1086,7 +1093,7 @@ std::vector ParameterGrp::GetASCIIs(const char* sFilter) const DOMElement* pcTemp = FindElement(_pGroupNode, "FCText"); while (pcTemp) { - Name = StrXUTF8(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrXUTF8(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { // retrieve the text element @@ -1116,7 +1123,7 @@ ParameterGrp::GetASCIIMap(const char* sFilter) const DOMElement* pcTemp = FindElement(_pGroupNode, "FCText"); while (pcTemp) { - Name = StrXUTF8(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str(); + Name = StrXUTF8(pcTemp->getAttribute(XStrLiteral("Name").unicodeForm())).c_str(); // check on filter condition if (!sFilter || Name.find(sFilter) != std::string::npos) { // retrieve the text element @@ -1299,7 +1306,7 @@ bool ParameterGrp::RenameGrp(const char* OldName, const char* NewName) // check if Element in group DOMElement* pcElem = FindElement(_pGroupNode, "FCParamGroup", OldName); if (pcElem) { - pcElem->setAttribute(XStr("Name").unicodeForm(), XStr(NewName).unicodeForm()); + pcElem->setAttribute(XStrLiteral("Name").unicodeForm(), XStr(NewName).unicodeForm()); } _Notify(ParamType::FCGroup, NewName, OldName); @@ -1349,7 +1356,7 @@ void ParameterGrp::Clear(bool notify) if (type != ParamType::FCInvalid && type != ParamType::FCGroup) { params.emplace_back(type, StrX(child->getAttributes() - ->getNamedItem(XStr("Name").unicodeForm()) + ->getNamedItem(XStrLiteral("Name").unicodeForm()) ->getNodeValue()) .c_str()); } @@ -1387,8 +1394,9 @@ ParameterGrp::FindElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start, const char* Type, const char* Name) const { - if (XMLString::compareString(Start->getNodeName(), XStr("FCParamGroup").unicodeForm()) != 0 - && XMLString::compareString(Start->getNodeName(), XStr("FCParameters").unicodeForm()) + if (XMLString::compareString(Start->getNodeName(), XStrLiteral("FCParamGroup").unicodeForm()) + != 0 + && XMLString::compareString(Start->getNodeName(), XStrLiteral("FCParameters").unicodeForm()) != 0) { Base::Console().Warning("FindElement: %s cannot have the element %s of type %s\n", StrX(Start->getNodeName()).c_str(), @@ -1396,15 +1404,20 @@ ParameterGrp::FindElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start, Type); return nullptr; } + const XStr xType(Type); + const XStr xName(Name); for (DOMNode* clChild = Start->getFirstChild(); clChild != nullptr; clChild = clChild->getNextSibling()) { if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) { // the right node Type - if (!strcmp(Type, StrX(clChild->getNodeName()).c_str())) { - if (clChild->getAttributes()->getLength() > 0) { + if (!XMLString::compareString(xType.unicodeForm(), clChild->getNodeName())) { + auto attrs = clChild->getAttributes(); + if (attrs->getLength() > 0) { if (Name) { - DOMNode* attr = FindAttribute(clChild, "Name"); - if (attr && !strcmp(Name, StrX(attr->getNodeValue()).c_str())) { + DOMNode* attr = attrs->getNamedItem(XStrLiteral("Name").unicodeForm()); + if (attr + && !XMLString::compareString(xName.unicodeForm(), + attr->getNodeValue())) { return dynamic_cast(clChild); } } @@ -1426,10 +1439,11 @@ ParameterGrp::FindNextElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* Prev, cons return nullptr; } + const XStr xType(Type); while ((clChild = clChild->getNextSibling()) != nullptr) { if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) { // the right node Type - if (!strcmp(Type, StrX(clChild->getNodeName()).c_str())) { + if (!XMLString::compareString(xType.unicodeForm(), clChild->getNodeName())) { return dynamic_cast(clChild); } } @@ -1479,7 +1493,7 @@ ParameterGrp::GetParameterNames(const char* sFilter) const if (Type != ParamType::FCInvalid && Type != ParamType::FCGroup) { if (clChild->getAttributes()->getLength() > 0) { StrX name(clChild->getAttributes() - ->getNamedItem(XStr("Name").unicodeForm()) + ->getNamedItem(XStrLiteral("Name").unicodeForm()) ->getNodeValue()); if (!sFilter || strstr(name.c_str(), sFilter)) { res.emplace_back(Type, name.c_str()); @@ -1970,16 +1984,17 @@ void ParameterManager::CreateDocument() { // creating a document from screatch DOMImplementation* impl = - DOMImplementationRegistry::getDOMImplementation(XStr("Core").unicodeForm()); + DOMImplementationRegistry::getDOMImplementation(XStrLiteral("Core").unicodeForm()); delete _pDocument; - _pDocument = impl->createDocument(nullptr, // root element namespace URI. - XStr("FCParameters").unicodeForm(), // root element name - nullptr); // document type object (DTD). + _pDocument = + impl->createDocument(nullptr, // root element namespace URI. + XStrLiteral("FCParameters").unicodeForm(), // root element name + nullptr); // document type object (DTD). // creating the node for the root group DOMElement* rootElem = _pDocument->getDocumentElement(); - _pGroupNode = _pDocument->createElement(XStr("FCParamGroup").unicodeForm()); - _pGroupNode->setAttribute(XStr("Name").unicodeForm(), XStr("Root").unicodeForm()); + _pGroupNode = _pDocument->createElement(XStrLiteral("FCParamGroup").unicodeForm()); + _pGroupNode->setAttribute(XStrLiteral("Name").unicodeForm(), XStrLiteral("Root").unicodeForm()); rootElem->appendChild(_pGroupNode); } @@ -2090,14 +2105,15 @@ DOMPrintFilter::DOMPrintFilter(ShowType whatToShow) DOMPrintFilter::FilterAction DOMPrintFilter::acceptNode(const DOMNode* node) const { - if (XMLString::compareString(node->getNodeName(), XStr("FCParameters").unicodeForm()) == 0) { + if (XMLString::compareString(node->getNodeName(), XStrLiteral("FCParameters").unicodeForm()) + == 0) { // This node is supposed to have a single FCParamGroup and two text nodes. // Over time it can happen that the text nodes collect extra newlines. const DOMNodeList* children = node->getChildNodes(); for (XMLSize_t i = 0; i < children->getLength(); i++) { DOMNode* child = children->item(i); if (child->getNodeType() == DOMNode::TEXT_NODE) { - child->setNodeValue(XStr("\n").unicodeForm()); + child->setNodeValue(XStrLiteral("\n").unicodeForm()); } } } @@ -2110,7 +2126,7 @@ DOMPrintFilter::FilterAction DOMPrintFilter::acceptNode(const DOMNode* node) con // there. auto parent = node->getParentNode(); if (parent && XMLString::compareString(parent->getNodeName(), - XStr("FCParamGroup").unicodeForm()) == 0) { + XStrLiteral("FCParamGroup").unicodeForm()) == 0) { return DOMNodeFilter::FILTER_REJECT; } return DOMNodeFilter::FILTER_ACCEPT; diff --git a/src/Base/Parameter.h b/src/Base/Parameter.h index 92a9fcb7d4..3579b0d767 100644 --- a/src/Base/Parameter.h +++ b/src/Base/Parameter.h @@ -164,18 +164,64 @@ public: }; static const char* TypeName(ParamType type); static ParamType TypeValue(const char*); + + /** + * Sets the value of an attribute. + * + * @param[in] Type The type of the attribute. + * @param[in] Name The name of the attribute. + * @param[in] Value The value to be set. + */ void SetAttribute(ParamType Type, const char* Name, const char* Value); + + /** + * Removes an attribute. + * + * @param[in] Type The type of the attribute. + * @param[in] Name The name of the attribute. + */ void RemoveAttribute(ParamType Type, const char* Name); + + /** + * Returns the value of the attribute. + * + * If the attribute can't be found, \n + * the fallback value is returned. + * + * @param[in] Type The type of the attribute. + * @param[in] Name The name of the attribute. + * @param[out] Value The value of attribute or the fallback value. + * @param[in] Default The fallback value. + */ const char* GetAttribute(ParamType Type, const char* Name, std::string& Value, const char* Default) const; + + /** + * Returns all attributes with the given type. + * + * Optionally filters them to only include attributes \n + * with names that contain a certain string. + * + * @param[in] Type The type of attributes to be returned + * @param[in] sFilter String that has to be present in the names of the attributes. + * @returns Vector of attribute name & value pairs. + */ std::vector> GetAttributeMap(ParamType Type, const char* sFilter = nullptr) const; - /** Return the type and name of all parameters with optional filter - * @param sFilter only strings which name includes sFilter are put in the vector - * @return std::vector of pair(type, name) + + + /** + * Returns all parameters. + * + * Optionally filters them to only include attributes \n + * with names that contain a certain string. + * + * @param[in] sFilter String that has to be present in the names of the attributes. + * @returns Vector of attribute type & name pairs. */ std::vector> GetParameterNames(const char* sFilter = nullptr) const; + //@} /** @name methods for bool handling */ diff --git a/src/Base/PersistencePy.xml b/src/Base/PersistencePy.xml index 4638e43e01..d8ffbd55cf 100644 --- a/src/Base/PersistencePy.xml +++ b/src/Base/PersistencePy.xml @@ -26,7 +26,7 @@ Class to dump and restore the content of an object. Memory size of the object in bytes. - + diff --git a/src/Base/PersistencePyImp.cpp b/src/Base/PersistencePyImp.cpp index 3c9f72d323..7e98b25631 100644 --- a/src/Base/PersistencePyImp.cpp +++ b/src/Base/PersistencePyImp.cpp @@ -52,9 +52,9 @@ Py::String PersistencePy::getContent() const return {writer.getString()}; } -Py::Int PersistencePy::getMemSize() const +Py::Long PersistencePy::getMemSize() const { - return Py::Int((long)getPersistencePtr()->getMemSize()); + return Py::Long((long)getPersistencePtr()->getMemSize()); } PyObject* PersistencePy::dumpContent(PyObject* args, PyObject* kwds) diff --git a/src/Base/PyObjectBase.h b/src/Base/PyObjectBase.h index c916703c93..18237d4604 100644 --- a/src/Base/PyObjectBase.h +++ b/src/Base/PyObjectBase.h @@ -163,18 +163,18 @@ namespace Base { -/** The PyObjectBase class, exports the class as a python type +/** The PyObjectBase class, exports the class as a Python type * PyObjectBase is the base class for all C++ classes which - * need to get exported into the python namespace. This class is + * need to get exported into the Python namespace. This class is * very important because nearly all important classes in FreeCAD - * are visible in python for macro recording and automation purpose. - * The class App::Document is a good expample for an exported class. + * are visible in Python for macro recording and automation purpose. + * The class App::Document is a good example for an exported class. * There are some convenience macros to make it easier to inherit - * from this class and defining new methods exported to python. + * from this class and defining new methods exported to Python. * PYFUNCDEF_D defines a new exported method. * PYFUNCIMP_D defines the implementation of the new exported method. * In the implementation you can use Py_Return, Py_Error, Py_Try and Py_Assert. - * PYMETHODEDEF makes the entry in the python method table. + * PYMETHODEDEF makes the entry in the Python method table. * @see Document * @see PYFUNCDEF_D * @see PYFUNCIMP_D diff --git a/src/Base/QuantityPy.xml b/src/Base/QuantityPy.xml index 881b58a70b..0a874e8b3d 100644 --- a/src/Base/QuantityPy.xml +++ b/src/Base/QuantityPy.xml @@ -29,38 +29,36 @@ Quantity(string) -- arbitrary mixture of numbers and chars defining a Quantity - - toStr([decimals]) - returns a string representation rounded to number of decimals. If no decimals are specified then - the internal precision is used + toStr([decimals]) + +Returns a string representation rounded to number of decimals. If no decimals are specified then +the internal precision is used - returns a quantity with the translation factor and a string with the prevered unit + Returns a quantity with the translation factor and a string with the prevered unit - - returns a floating point value as the provided unit + Returns a floating point value as the provided unit - Following parameters are allowed: - getValueAs('m/s') # unit string to parse - getValueAs(2.45,1) # translation value and unit signature - getValueAs(FreeCAD.Units.Pascal) # predefined standard units - getValueAs(Qantity('N/m^2')) # a quantity - getValueAs(Unit(0,1,0,0,0,0,0,0)) # a unit +Following parameters are allowed: +getValueAs('m/s') # unit string to parse +getValueAs(2.45,1) # translation value and unit signature +getValueAs(FreeCAD.Units.Pascal) # predefined standard units +getValueAs(Qantity('N/m^2')) # a quantity +getValueAs(Unit(0,1,0,0,0,0,0,0)) # a unit - -Return the Integral closest to x, rounding half toward even. + Returns the Integral closest to x, rounding half toward even. When an argument is passed, work like built-in round(x, ndigits). diff --git a/src/Base/QuantityPyImp.cpp b/src/Base/QuantityPyImp.cpp index 5cf7514852..85078c38f6 100644 --- a/src/Base/QuantityPyImp.cpp +++ b/src/Base/QuantityPyImp.cpp @@ -641,9 +641,9 @@ Py::Dict QuantityPy::getFormat() const QuantityFormat fmt = getQuantityPtr()->getFormat(); Py::Dict dict; - dict.setItem("Precision", Py::Int(fmt.precision)); + dict.setItem("Precision", Py::Long(fmt.precision)); dict.setItem("NumberFormat", Py::Char(fmt.toFormat())); - dict.setItem("Denominator", Py::Int(fmt.denominator)); + dict.setItem("Denominator", Py::Long(fmt.denominator)); return dict; } @@ -652,14 +652,14 @@ void QuantityPy::setFormat(Py::Dict arg) QuantityFormat fmt = getQuantityPtr()->getFormat(); if (arg.hasKey("Precision")) { - Py::Int prec(arg.getItem("Precision")); + Py::Long prec(arg.getItem("Precision")); fmt.precision = static_cast(prec); } if (arg.hasKey("NumberFormat")) { Py::Object item = arg.getItem("NumberFormat"); if (item.isNumeric()) { - int format = static_cast(Py::Int(item)); + int format = static_cast(Py::Long(item)); if (format < 0 || format > QuantityFormat::Scientific) { throw Py::ValueError("Invalid format value"); } @@ -681,7 +681,7 @@ void QuantityPy::setFormat(Py::Dict arg) } if (arg.hasKey("Denominator")) { - Py::Int denom(arg.getItem("Denominator")); + Py::Long denom(arg.getItem("Denominator")); int fracInch = static_cast(denom); // check that the value is positive and a power of 2 if (fracInch <= 0) { diff --git a/src/Base/RotationPy.xml b/src/Base/RotationPy.xml index 53c8a3104a..9c86e4cfe0 100644 --- a/src/Base/RotationPy.xml +++ b/src/Base/RotationPy.xml @@ -88,7 +88,7 @@ coef : sequence of float Sets the rotation to its inverse. - + inverted() -> Base.Rotation @@ -232,12 +232,11 @@ tol : float - - public: - RotationPy(const Rotation & mat, PyTypeObject *T = &Type) - :PyObjectBase(new Rotation(mat),T){} - Rotation value() const - { return *(getRotationPtr()); } + public: + RotationPy(const Rotation & mat, PyTypeObject *T = &Type) + :PyObjectBase(new Rotation(mat),T){} + Rotation value() const + { return *(getRotationPtr()); } diff --git a/src/Base/Type.cpp b/src/Base/Type.cpp index 51b2128c1e..f12c041aaf 100644 --- a/src/Base/Type.cpp +++ b/src/Base/Type.cpp @@ -59,7 +59,7 @@ map Type::typemap; vector Type::typedata; set Type::loadModuleSet; -void* Type::createInstance() +void* Type::createInstance() const { instantiationMethod method = typedata[index]->instMethod; return method ? (*method)() : nullptr; @@ -90,30 +90,33 @@ void* Type::createInstanceByName(const char* TypeName, bool bLoadModule) void Type::importModule(const char* TypeName) { // cut out the module name - string Mod = getModuleName(TypeName); + const string mod = getModuleName(TypeName); + // ignore base modules - if (Mod != "App" && Mod != "Gui" && Mod != "Base") { - // remember already loaded modules - set::const_iterator pos = loadModuleSet.find(Mod); - if (pos == loadModuleSet.end()) { - Interpreter().loadModule(Mod.c_str()); -#ifdef FC_LOGLOADMODULE - Console().Log("Act: Module %s loaded through class %s \n", Mod.c_str(), TypeName); -#endif - loadModuleSet.insert(Mod); - } + if (mod == "App" || mod == "Gui" || mod == "Base") { + return; } + + // remember already loaded modules + const auto pos = loadModuleSet.find(mod); + if (pos != loadModuleSet.end()) { + return; + } + + // lets load the module + Interpreter().loadModule(mod.c_str()); +#ifdef FC_LOGLOADMODULE + Console().Log("Act: Module %s loaded through class %s \n", Mod.c_str(), TypeName); +#endif + loadModuleSet.insert(mod); } string Type::getModuleName(const char* ClassName) { - string temp(ClassName); - std::string::size_type pos = temp.find_first_of("::"); + string_view classNameView(ClassName); + auto pos = classNameView.find("::"); - if (pos != std::string::npos) { - return {temp, 0, pos}; - } - return {}; + return pos != string_view::npos ? string(classNameView.substr(0, pos)) : string(); } Type Type::badType() diff --git a/src/Base/Type.h b/src/Base/Type.h index 3f580724e2..fad31905db 100644 --- a/src/Base/Type.h +++ b/src/Base/Type.h @@ -88,7 +88,7 @@ public: ~Type() = default; /// creates a instance of this type - void* createInstance(); + void* createInstance() const; /// Checks whether this type can instantiate bool canInstantiate() const; /// creates a instance of the named type diff --git a/src/Base/TypePy.xml b/src/Base/TypePy.xml index 25e868a6ac..f1be79b63b 100644 --- a/src/Base/TypePy.xml +++ b/src/Base/TypePy.xml @@ -19,7 +19,7 @@ namespace Base { This is the Type class BaseTypePy class. - This class provides functionality related to type management in the Base module. It's not intended for direct instantiation but for accessing type information and creating instances of various types. Instantiation is possible for classes that inherit from the Base::BaseClass class and are not abstract. +This class provides functionality related to type management in the Base module. It's not intended for direct instantiation but for accessing type information and creating instances of various types. Instantiation is possible for classes that inherit from the Base::BaseClass class and are not abstract. diff --git a/src/Base/Unit.cpp b/src/Base/Unit.cpp index a3c2a12c87..45a53dedb1 100644 --- a/src/Base/Unit.cpp +++ b/src/Base/Unit.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -587,7 +588,7 @@ std::string Unit::getString() const std::string Unit::getTypeString() const { - static std::array, 55> unitSpecs {{ + static std::array, 56> unitSpecs {{ { Unit::Acceleration, "Acceleration" }, { Unit::AmountOfSubstance, "AmountOfSubstance" }, { Unit::Angle, "Angle" }, @@ -603,6 +604,7 @@ std::string Unit::getTypeString() const { Unit::ElectricalInductance, "ElectricalInductance" }, { Unit::ElectricalResistance, "ElectricalResistance" }, { Unit::ElectricCharge, "ElectricCharge" }, + { Unit::SurfaceChargeDensity, "SurfaceChargeDensity" }, { Unit::ElectricCurrent, "ElectricCurrent" }, { Unit::ElectricPotential, "ElectricPotential" }, { Unit::ElectromagneticPotential, "ElectromagneticPotential" }, @@ -681,6 +683,7 @@ const Unit Unit::ElectricalConductivity (-3, -1, 3, 2); const Unit Unit::ElectricalInductance (2, 1, -2, -2); const Unit Unit::ElectricalResistance (2, 1, -3, -2); const Unit Unit::ElectricCharge (0, 0, 1, 1); +const Unit Unit::SurfaceChargeDensity (-2, 0, 1, 1); const Unit Unit::ElectricPotential (2, 1, -3, -1); const Unit Unit::ElectromagneticPotential (1, 1, -2, -1); const Unit Unit::Force (1, 1, -2); diff --git a/src/Base/Unit.h b/src/Base/Unit.h index 670cf67526..b47d5c26ae 100644 --- a/src/Base/Unit.h +++ b/src/Base/Unit.h @@ -110,6 +110,7 @@ public: static const Unit ElectricCurrent; static const Unit ElectricPotential; static const Unit ElectricCharge; + static const Unit SurfaceChargeDensity; static const Unit MagneticFieldStrength; static const Unit MagneticFlux; static const Unit MagneticFluxDensity; diff --git a/src/Base/UnitPy.xml b/src/Base/UnitPy.xml index 09ac932889..866b3536c8 100644 --- a/src/Base/UnitPy.xml +++ b/src/Base/UnitPy.xml @@ -15,16 +15,15 @@ FatherNamespace="Base"> - - Unit - defines a unit type, calculate and compare. + Unit +defines a unit type, calculate and compare. - The following constructors are supported: - Unit() -- empty constructor - Unit(i1,i2,i3,i4,i5,i6,i7,i8) -- unit signature - Unit(Quantity) -- copy unit from Quantity - Unit(Unit) -- copy constructor - Unit(string) -- parse the string for units +The following constructors are supported: +Unit() -- empty constructor +Unit(i1,i2,i3,i4,i5,i6,i7,i8) -- unit signature +Unit(Quantity) -- copy unit from Quantity +Unit(Unit) -- copy constructor +Unit(string) -- parse the string for units Unit diff --git a/src/Base/UnitsSchemaInternal.cpp b/src/Base/UnitsSchemaInternal.cpp index 63e543d205..1d67455bab 100644 --- a/src/Base/UnitsSchemaInternal.cpp +++ b/src/Base/UnitsSchemaInternal.cpp @@ -364,6 +364,10 @@ UnitsSchemaInternal::schemaTranslate(const Quantity& quant, double& factor, std: unitString = "C"; factor = 1.0; } + else if (unit == Unit::SurfaceChargeDensity) { + unitString = "C/m^2"; + factor = 1e-6; + } else if (unit == Unit::CurrentDensity) { if (UnitValue <= 1e3) { unitString = "A/m^2"; diff --git a/src/Base/UnitsSchemaMKS.cpp b/src/Base/UnitsSchemaMKS.cpp index 98ef0545eb..241e3eba9b 100644 --- a/src/Base/UnitsSchemaMKS.cpp +++ b/src/Base/UnitsSchemaMKS.cpp @@ -312,6 +312,10 @@ UnitsSchemaMKS::schemaTranslate(const Quantity& quant, double& factor, std::stri unitString = "C"; factor = 1.0; } + else if (unit == Unit::SurfaceChargeDensity) { + unitString = "C/m^2"; + factor = 1e-6; + } else if (unit == Unit::CurrentDensity) { if (UnitValue <= 1e3) { unitString = "A/m^2"; diff --git a/src/Base/UnitsSchemaMeterDecimal.cpp b/src/Base/UnitsSchemaMeterDecimal.cpp index e80bd7af7f..8d7337bdac 100644 --- a/src/Base/UnitsSchemaMeterDecimal.cpp +++ b/src/Base/UnitsSchemaMeterDecimal.cpp @@ -44,7 +44,7 @@ std::string UnitsSchemaMeterDecimal::schemaTranslate(const Base::Quantity& quant std::string& unitString) { static std::array>, 7> unitSpecs {{ - {Unit::Length, {"m", 1e0}}, + {Unit::Length, {"m", 1e3}}, {Unit::Area, {"m^2", 1e6}}, {Unit::Volume, {"m^3", 1e9}}, {Unit::Power, {"W", 1000000}}, diff --git a/src/Base/XMLTools.h b/src/Base/XMLTools.h index 798b975d8c..cc17d1b336 100644 --- a/src/Base/XMLTools.h +++ b/src/Base/XMLTools.h @@ -174,6 +174,15 @@ inline XStr::~XStr() XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&fUnicodeForm); } +// Uses the compiler to create a cache of transcoded string literals so that each subsequent call +// can re-use the data from the lambda's initial creation. Permits the same usage as +// XStr("literal").unicodeForm() +#define XStrLiteral(literal) \ + ([]() -> const XStr& { \ + static const XStr str {literal}; \ + return str; \ + }()) + // ----------------------------------------------------------------------- // Getter methods @@ -210,6 +219,14 @@ inline XUTF8Str::XUTF8Str(const char* const fromTranscode) inline XUTF8Str::~XUTF8Str() = default; +// Uses the compiler to create a cache of transcoded string literals so that each subsequent call +// can re-use the data from the lambda's initial creation. Permits the same usage as +// XStr("literal").unicodeForm() +#define XUTF8StrLiteral(literal) \ + ([]() -> const XUTF8Str& { \ + static const XUTF8Str str {literal}; \ + return str; \ + }()) // ----------------------------------------------------------------------- // Getter methods diff --git a/src/Ext/freecad/utils.py b/src/Ext/freecad/utils.py index 01bb923e50..0230a2b0ad 100644 --- a/src/Ext/freecad/utils.py +++ b/src/Ext/freecad/utils.py @@ -31,7 +31,7 @@ import FreeCAD def get_python_exe() -> str: """Find Python. In preference order - A) The value of the PythonExecutableForPip user preference + A) The value of the BaseApp/Preferences/PythonConsole/ExternalPythonExecutable user preference B) The executable located in the same bin directory as FreeCAD and called "python3" C) The executable located in the same bin directory as FreeCAD and called "python" D) The result of a shutil search for your system's "python3" executable diff --git a/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp b/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp index b244b59973..86237942bb 100644 --- a/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp +++ b/src/Gui/3Dconnexion/navlib/NavlibPivot.cpp @@ -43,7 +43,7 @@ #include #include -#include +#include #include #include #include @@ -57,7 +57,7 @@ long NavlibInterface::GetSelectionTransform(navlib::matrix_t&) const long NavlibInterface::GetIsSelectionEmpty(navlib::bool_t& empty) const { - empty = !Gui::SelectionSingleton::instance().hasSelection(); + empty = !Gui::Selection().hasSelection(); return 0; } diff --git a/src/Gui/Action.cpp b/src/Gui/Action.cpp index ecf1c143fe..2c940ca0a7 100644 --- a/src/Gui/Action.cpp +++ b/src/Gui/Action.cpp @@ -46,7 +46,7 @@ #include "Action.h" #include "BitmapFactory.h" #include "Command.h" -#include "DlgUndoRedo.h" +#include "Dialogs/DlgUndoRedo.h" #include "PreferencePages/DlgSettingsWorkbenchesImp.h" #include "Document.h" #include "EditorView.h" @@ -331,10 +331,10 @@ QString Action::createToolTip(QString helpText, helpText.resize(helpText.size() - shortcut.size()); } if (!shortcut.isEmpty()) { - shortcut = QString::fromLatin1(" (%1)").arg(shortcut); + shortcut = QStringLiteral(" (%1)").arg(shortcut); } - QString tooltip = QString::fromLatin1( + QString tooltip = QStringLiteral( "

%1%2

").arg( text.toHtmlEscaped(), shortcut.toHtmlEscaped()); @@ -371,12 +371,11 @@ QString Action::createToolTip(QString helpText, return tooltip + helpText + cmdName; } - tooltip += QString::fromLatin1( - "

"); + tooltip += QStringLiteral("

"); // If the user supplied tooltip contains line break, we shall honour it. if (helpText.indexOf(QLatin1Char('\n')) >= 0) { - tooltip += helpText.toHtmlEscaped() + QString::fromLatin1("

") ; + tooltip += helpText.toHtmlEscaped() + QStringLiteral("

") ; } else { // If not, try to end the non wrapping paragraph at some pre defined @@ -385,7 +384,7 @@ QString Action::createToolTip(QString helpText, QFontMetrics fm(font); int width = QtTools::horizontalAdvance(fm, helpText); if (width <= tipWidth) { - tooltip += helpText.toHtmlEscaped() + QString::fromLatin1("

") ; + tooltip += helpText.toHtmlEscaped() + QStringLiteral("

") ; } else { int index = tipWidth / width * helpText.size(); @@ -396,7 +395,7 @@ QString Action::createToolTip(QString helpText, } } tooltip += helpText.left(index).toHtmlEscaped() - + QString::fromLatin1("

") + + QStringLiteral("

") + helpText.right(helpText.size()-index).trimmed().toHtmlEscaped(); } } @@ -475,7 +474,7 @@ void ActionGroup::addTo(QWidget *widget) widget->addAction(action()); QToolButton* tb = widget->findChildren().constLast(); tb->setPopupMode(QToolButton::MenuButtonPopup); - tb->setObjectName(QString::fromLatin1("qt_toolbutton_menubutton")); + tb->setObjectName(QStringLiteral("qt_toolbutton_menubutton")); QList acts = groupAction()->actions(); auto menu = new QMenu(tb); menu->addActions(acts); @@ -692,7 +691,7 @@ void WorkbenchGroup::refreshWorkbenchList() action->setToolTip(tip); action->setStatusTip(tr("Select the '%1' workbench").arg(name)); if (index < 9) { - action->setShortcut(QKeySequence(QString::fromUtf8("W,%1").arg(index + 1))); + action->setShortcut(QKeySequence(QStringLiteral("W,%1").arg(index + 1))); } if (wbName.toStdString() == activeWbName) { action->setChecked(true); @@ -850,10 +849,10 @@ void RecentFilesAction::appendFile(const QString& filename) static QString numberToLabel(int number) { if (number > 0 && number < 10) { // NOLINT: *-magic-numbers - return QString::fromLatin1("&%1").arg(number); + return QStringLiteral("&%1").arg(number); } if (number == 10) { // NOLINT: *-magic-numbers - return QString::fromLatin1("1&0"); + return QStringLiteral("1&0"); } // If we have a number greater than 10, we start using the alphabet. // So 11 becomes 'A' and so on. @@ -861,10 +860,10 @@ static QString numberToLabel(int number) { constexpr char lettersEnd = lettersStart + ('Z' - 'A'); if (number >= lettersStart && number < lettersEnd) { QChar letter = QChar::fromLatin1('A' + (number - lettersStart)); - return QString::fromLatin1("%1 (&%2)").arg(number).arg(letter); + return QStringLiteral("%1 (&%2)").arg(number).arg(letter); } // Not enough accelerators to cover this number. - return QString::fromLatin1("%1").arg(number); + return QStringLiteral("%1").arg(number); } /** @@ -879,7 +878,7 @@ void RecentFilesAction::setFiles(const QStringList& files) for (int index = 0; index < numRecentFiles; index++) { QString numberLabel = numberToLabel(index + 1); QFileInfo fi(files[index]); - recentFiles[index]->setText(QString::fromLatin1("%1 %2").arg(numberLabel).arg(fi.fileName())); + recentFiles[index]->setText(QStringLiteral("%1 %2").arg(numberLabel).arg(fi.fileName())); recentFiles[index]->setStatusTip(tr("Open file %1").arg(files[index])); recentFiles[index]->setToolTip(files[index]); // set the full name that we need later for saving recentFiles[index]->setData(QVariant(index)); @@ -977,7 +976,7 @@ void RecentFilesAction::save() QList recentFiles = groupAction()->actions(); int num = std::min(count, recentFiles.count()); for (int index = 0; index < num; index++) { - QString key = QString::fromLatin1("MRU%1").arg(index); + QString key = QStringLiteral("MRU%1").arg(index); QString value = recentFiles[index]->toolTip(); if (value.isEmpty()) { break; @@ -1041,7 +1040,7 @@ void RecentMacrosAction::setFiles(const QStringList& files) for (int index = 0; index < numRecentFiles; index++) { QFileInfo fi(files[index]); QString numberLabel = numberToLabel(index + 1); - recentFiles[index]->setText(QString::fromLatin1("%1 %2").arg(numberLabel).arg(fi.completeBaseName())); + recentFiles[index]->setText(QStringLiteral("%1 %2").arg(numberLabel).arg(fi.completeBaseName())); recentFiles[index]->setToolTip(files[index]); // set the full name that we need later for saving recentFiles[index]->setData(QVariant(index)); QString accel(tr("none")); @@ -1192,7 +1191,7 @@ void RecentMacrosAction::save() QList recentFiles = groupAction()->actions(); int num = std::min(count, recentFiles.count()); for (int index = 0; index < num; index++) { - QString key = QString::fromLatin1("MRU%1").arg(index); + QString key = QStringLiteral("MRU%1").arg(index); QString value = recentFiles[index]->toolTip(); if (value.isEmpty()) { break; diff --git a/src/Gui/ActiveObjectList.cpp b/src/Gui/ActiveObjectList.cpp index 0fc064cdb6..1690e116d3 100644 --- a/src/Gui/ActiveObjectList.cpp +++ b/src/Gui/ActiveObjectList.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include "ActiveObjectList.h" diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index dec82e9aa0..5a13553bf4 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -2457,22 +2457,22 @@ QString Application::replaceVariablesInQss(QString qssText) // convert them to hex. // Note: the ulong contains alpha channels so 8 hex characters when we need 6 here. - QString accentColor1 = QString::fromLatin1("#%1") + QString accentColor1 = QStringLiteral("#%1") .arg(longAccentColor1, 8, 16, QLatin1Char('0')) .toUpper() .mid(0, 7); - QString accentColor2 = QString::fromLatin1("#%1") + QString accentColor2 = QStringLiteral("#%1") .arg(longAccentColor2, 8, 16, QLatin1Char('0')) .toUpper() .mid(0, 7); - QString accentColor3 = QString::fromLatin1("#%1") + QString accentColor3 = QStringLiteral("#%1") .arg(longAccentColor3, 8, 16, QLatin1Char('0')) .toUpper() .mid(0, 7); - qssText = qssText.replace(QString::fromLatin1("@ThemeAccentColor1"), accentColor1); - qssText = qssText.replace(QString::fromLatin1("@ThemeAccentColor2"), accentColor2); - qssText = qssText.replace(QString::fromLatin1("@ThemeAccentColor3"), accentColor3); + qssText = qssText.replace(QStringLiteral("@ThemeAccentColor1"), accentColor1); + qssText = qssText.replace(QStringLiteral("@ThemeAccentColor2"), accentColor2); + qssText = qssText.replace(QStringLiteral("@ThemeAccentColor3"), accentColor3); // Base::Console().Warning("%s\n", qssText.toStdString()); return qssText; @@ -2562,7 +2562,9 @@ App::Document* Application::reopen(App::Document* doc) } for (auto& file : docs) { - App::GetApplication().openDocument(file.c_str(), false); + App::DocumentCreateFlags createFlags; + createFlags.createView = false; + App::GetApplication().openDocument(file.c_str(), createFlags); } } diff --git a/src/Gui/ApplicationPy.cpp b/src/Gui/ApplicationPy.cpp index 1db7e93df4..16dc543900 100644 --- a/src/Gui/ApplicationPy.cpp +++ b/src/Gui/ApplicationPy.cpp @@ -48,7 +48,7 @@ #include "ApplicationPy.h" #include "BitmapFactory.h" #include "Command.h" -#include "DlgPreferencesImp.h" +#include "Dialogs/DlgPreferencesImp.h" #include "Document.h" #include "DocumentObserverPython.h" #include "DownloadManager.h" @@ -773,10 +773,11 @@ PyObject* ApplicationPy::sExport(PyObject * /*self*/, PyObject *args) view3d->viewAll(); } QPrinter printer(QPrinter::ScreenResolution); - // setPdfVersion sets the printied PDF Version to comply with PDF/A-1b, more details under: https://www.kdab.com/creating-pdfa-documents-qt/ + // setPdfVersion sets the printed PDF Version to comply with PDF/A-1b, more details under: https://www.kdab.com/creating-pdfa-documents-qt/ printer.setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName(fileName); + printer.setCreator(QString::fromStdString(App::Application::getNameWithVersion())); view->print(&printer); } } diff --git a/src/Gui/AutoSaver.cpp b/src/Gui/AutoSaver.cpp index 8ff9a9013f..576ebeedbb 100644 --- a/src/Gui/AutoSaver.cpp +++ b/src/Gui/AutoSaver.cpp @@ -146,7 +146,7 @@ void AutoSaver::saveDocument(const std::string& name, AutoSaveProperty& saver) saver.dirName = dirName; // Write recovery meta file - QFile file(QString::fromLatin1("%1/fc_recovery_file.xml") + QFile file(QStringLiteral("%1/fc_recovery_file.xml") .arg(QString::fromUtf8(doc->TransientDir.getValue()))); if (file.open(QFile::WriteOnly)) { QTextStream str(&file); @@ -293,13 +293,13 @@ bool RecoveryWriter::shouldWrite(const std::string& name, const Base::Persistenc { // Property files of a view provider can always be written because // these are rather small files. - if (object->isDerivedFrom(App::Property::getClassTypeId())) { + if (object->isDerivedFrom()) { const auto* prop = static_cast(object); const App::PropertyContainer* parent = prop->getContainer(); - if (parent && parent->isDerivedFrom(Gui::ViewProvider::getClassTypeId())) + if (parent && parent->isDerivedFrom()) return true; } - else if (object->isDerivedFrom(Gui::Document::getClassTypeId())) { + else if (object->isDerivedFrom()) { return true; } @@ -333,7 +333,7 @@ public: dirName = QString::fromUtf8(dir); fileName = QString::fromUtf8(file); - tmpName = QString::fromLatin1("%1.tmp%2").arg(fileName).arg(rand()); + tmpName = QStringLiteral("%1.tmp%2").arg(fileName).arg(rand()); writer.putNextEntry(tmpName.toUtf8().constData()); } ~RecoveryRunnable() override @@ -385,7 +385,7 @@ void RecoveryWriter::writeFiles() } // For properties a copy can be created and then this can be written to disk in a thread - if (entry.Object->isDerivedFrom(App::Property::getClassTypeId())) { + if (entry.Object->isDerivedFrom()) { const auto* prop = static_cast(entry.Object); QThreadPool::globalInstance()->start(new RecoveryRunnable(getModes(), DirName.c_str(), entry.FileName.c_str(), prop)); } diff --git a/src/Gui/BitmapFactory.cpp b/src/Gui/BitmapFactory.cpp index 1fd92ab83e..a51178fef3 100644 --- a/src/Gui/BitmapFactory.cpp +++ b/src/Gui/BitmapFactory.cpp @@ -75,8 +75,8 @@ BitmapFactoryInst& BitmapFactoryInst::instance() } _pcSingleton->addPath(path); } - _pcSingleton->addPath(QString::fromLatin1("%1/icons").arg(QString::fromStdString(App::Application::getHomePath()))); - _pcSingleton->addPath(QString::fromLatin1("%1/icons").arg(QString::fromStdString(App::Application::getUserAppDataDir()))); + _pcSingleton->addPath(QStringLiteral("%1/icons").arg(QString::fromStdString(App::Application::getHomePath()))); + _pcSingleton->addPath(QStringLiteral("%1/icons").arg(QString::fromStdString(App::Application::getUserAppDataDir()))); _pcSingleton->addPath(QLatin1String(":/icons/")); _pcSingleton->addPath(QLatin1String(":/Icons/")); } @@ -124,22 +124,22 @@ void Gui::BitmapFactoryInst::configureUseIconTheme() void BitmapFactoryInst::addPath(const QString& path) { - QDir::addSearchPath(QString::fromLatin1("icons"), path); + QDir::addSearchPath(QStringLiteral("icons"), path); } void BitmapFactoryInst::removePath(const QString& path) { - QStringList iconPaths = QDir::searchPaths(QString::fromLatin1("icons")); + QStringList iconPaths = QDir::searchPaths(QStringLiteral("icons")); int pos = iconPaths.indexOf(path); if (pos != -1) { iconPaths.removeAt(pos); - QDir::setSearchPaths(QString::fromLatin1("icons"), iconPaths); + QDir::setSearchPaths(QStringLiteral("icons"), iconPaths); } } QStringList BitmapFactoryInst::getPaths() const { - return QDir::searchPaths(QString::fromLatin1("icons")); + return QDir::searchPaths(QStringLiteral("icons")); } QStringList BitmapFactoryInst::findIconFiles() const @@ -147,9 +147,9 @@ QStringList BitmapFactoryInst::findIconFiles() const QStringList files, filters; QList formats = QImageReader::supportedImageFormats(); for (QList::iterator it = formats.begin(); it != formats.end(); ++it) - filters << QString::fromLatin1("*.%1").arg(QString::fromLatin1(*it).toLower()); + filters << QStringLiteral("*.%1").arg(QString::fromLatin1(*it).toLower()); - QStringList paths = QDir::searchPaths(QString::fromLatin1("icons")); + QStringList paths = QDir::searchPaths(QStringLiteral("icons")); paths.removeDuplicates(); for (QStringList::Iterator pt = paths.begin(); pt != paths.end(); ++pt) { QDir d(*pt); @@ -252,11 +252,11 @@ QPixmap BitmapFactoryInst::pixmap(const char* name) const QList formats = QImageReader::supportedImageFormats(); formats.prepend("SVG"); // check first for SVG to use special import mechanism - QString fileName = QString::fromLatin1("icons:") + fn; + QString fileName = QStringLiteral("icons:") + fn; if (!loadPixmap(fileName, icon)) { // Go through supported file formats for (QList::iterator fm = formats.begin(); fm != formats.end(); ++fm) { - QString path = QString::fromLatin1("%1.%2").arg(fileName, + QString path = QStringLiteral("%1.%2").arg(fileName, QString::fromLatin1((*fm).toLower().constData())); if (loadPixmap(path, icon)) { break; @@ -286,7 +286,7 @@ QPixmap BitmapFactoryInst::pixmapFromSvg(const char* name, const QSizeF& size, // try to find it in the 'icons' search paths if (iconPath.isEmpty()) { - QString fileName = QString::fromLatin1("icons:") + fn; + QString fileName = QStringLiteral("icons:") + fn; QFileInfo fi(fileName); if (fi.exists()) { iconPath = fi.filePath(); @@ -328,8 +328,8 @@ QPixmap BitmapFactoryInst::pixmapFromSvg(const QByteArray& originalContents, con for ( const auto &colorToColor : colorMapping ) { ulong fromColor = colorToColor.first; ulong toColor = colorToColor.second; - QString fromColorString = QString::fromLatin1(":#%1;").arg(fromColor, 6, 16, QChar::fromLatin1('0')); - QString toColorString = QString::fromLatin1(":#%1;").arg(toColor, 6, 16, QChar::fromLatin1('0')); + QString fromColorString = QStringLiteral(":#%1;").arg(fromColor, 6, 16, QChar::fromLatin1('0')); + QString toColorString = QStringLiteral(":#%1;").arg(toColor, 6, 16, QChar::fromLatin1('0')); stringContents = stringContents.replace(fromColorString, toColorString); } QByteArray contents = stringContents.toUtf8(); diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 45053fa6b4..cb7fa1890e 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -19,14 +19,14 @@ IF(CMAKE_BUILD_TYPE) add_definitions(-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}") ENDIF(CMAKE_BUILD_TYPE) -if (FREECAD_USE_3DCONNEXION_LEGACY) +if (FREECAD_USE_3DCONNEXION_LEGACY AND (MSVC OR APPLE)) add_definitions(-D_USE_3DCONNEXION_SDK) if(APPLE) set(3DCONNEXION_LINKFLAGS "-F/Library/Frameworks -weak_framework 3DconnexionClient") list(APPEND 3DCONNEXION_INCLUDE_DIR ${3DCONNEXIONCLIENT_FRAMEWORK}/Headers ${3DCONNEXIONCLIENT_FRAMEWORK}/Headers/3DconnexionClient ) endif(APPLE) -endif(FREECAD_USE_3DCONNEXION_LEGACY) +endif(FREECAD_USE_3DCONNEXION_LEGACY AND (MSVC OR APPLE)) if(FREECAD_USE_3DCONNEXION_NAVLIB AND (MSVC OR APPLE)) add_definitions(-DUSE_3DCONNEXION_NAVLIB) @@ -48,6 +48,8 @@ include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Quarter + ${CMAKE_CURRENT_SOURCE_DIR}/PreferencePages + ${CMAKE_CURRENT_SOURCE_DIR}/Selection ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/.. @@ -138,7 +140,8 @@ if(${Qt5WinExtras_FOUND}) ) endif() -IF(SPNAV_FOUND) +IF(SPNAV_FOUND AND FREECAD_USE_3DCONNEXION_LEGACY) + add_definitions(-D_USE_3DCONNEXION_SDK) if(SPNAV_USE_X11) add_definitions(-DSPNAV_USE_X11) if (FREECAD_QT_MAJOR_VERSION EQUAL 5 AND UNIX AND NOT APPLE) @@ -186,7 +189,7 @@ IF(SPNAV_FOUND) list(APPEND FreeCADGui_LIBS ${SPNAV_LIBRARIES} ) -ENDIF(SPNAV_FOUND) +ENDIF(SPNAV_FOUND AND FREECAD_USE_3DCONNEXION_LEGACY) IF(OCULUS_FOUND) add_definitions(-DOCULUS_FOUND) @@ -254,12 +257,12 @@ generate_from_xml(ViewProviderDocumentObjectPy) generate_from_xml(ViewProviderGeometryObjectPy) generate_from_xml(ViewProviderExtensionPy) generate_from_xml(WorkbenchPy) -generate_from_xml(SelectionObjectPy) +generate_from_xml(Selection/SelectionObjectPy) generate_from_xml(LinkViewPy) generate_from_xml(ViewProviderLinkPy) generate_from_xml(AxisOriginPy) generate_from_xml(CommandPy) -generate_from_xml(NavigationStylePy) +generate_from_xml(Navigation/NavigationStylePy) generate_from_py(FreeCADGuiInit GuiInitScript.h) @@ -271,7 +274,7 @@ SET(FreeCADGui_XML_SRCS ViewProviderExtensionPy.xml PythonWorkbenchPy.xml WorkbenchPy.xml - SelectionObjectPy.xml + Selection/SelectionObjectPy.xml DocumentPy.xml LinkViewPy.xml ViewProviderLinkPy.xml @@ -354,37 +357,37 @@ set_property(SOURCE GraphvizView.cpp APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURR set_property(SOURCE GraphvizView.h APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/moc_GraphvizView.cpp) SET(Gui_UIC_SRCS - AboutApplication.ui + Dialogs/AboutApplication.ui Clipping.ui DemoMode.ui - DlgActions.ui - DlgActivateWindow.ui - DlgUnitsCalculator.ui - DlgAuthorization.ui - DlgChooseIcon.ui - DlgCreateNewPreferencePack.ui - DlgInputDialog.ui - DlgKeyboard.ui - DlgMacroExecute.ui - DlgRunExternal.ui - DlgMacroRecord.ui - DlgMaterialProperties.ui - DlgOnlineHelp.ui - DlgParameter.ui - DlgParameterFind.ui - DlgPreferencePackManagement.ui - DlgPreferences.ui - DlgProjectInformation.ui - DlgProjectUtility.ui - DlgPropertyLink.ui - DlgRevertToBackupConfig.ui + Dialogs/DlgActions.ui + Dialogs/DlgActivateWindow.ui + Dialogs/DlgUnitsCalculator.ui + Dialogs/DlgAuthorization.ui + Dialogs/DlgChooseIcon.ui + Dialogs/DlgCreateNewPreferencePack.ui + Dialogs/DlgInputDialog.ui + Dialogs/DlgKeyboard.ui + Dialogs/DlgMacroExecute.ui + Dialogs/DlgRunExternal.ui + Dialogs/DlgMacroRecord.ui + Dialogs/DlgMaterialProperties.ui + Dialogs/DlgOnlineHelp.ui + Dialogs/DlgParameter.ui + Dialogs/DlgParameterFind.ui + Dialogs/DlgPreferencePackManagement.ui + Dialogs/DlgPreferences.ui + Dialogs/DlgProjectInformation.ui + Dialogs/DlgProjectUtility.ui + Dialogs/DlgPropertyLink.ui + Dialogs/DlgRevertToBackupConfig.ui PreferencePages/DlgSettings3DView.ui PreferencePages/DlgSettingsCacheDirectory.ui - DlgSettingsColorGradient.ui + Dialogs/DlgSettingsColorGradient.ui PreferencePages/DlgSettingsDocument.ui PreferencePages/DlgSettingsEditor.ui PreferencePages/DlgSettingsGeneral.ui - DlgSettingsImage.ui + Dialogs/DlgSettingsImage.ui PreferencePages/DlgSettingsLightSources.ui PreferencePages/DlgSettingsMacro.ui PreferencePages/DlgSettingsNavigation.ui @@ -395,15 +398,15 @@ SET(Gui_UIC_SRCS PreferencePages/DlgSettingsUI.ui PreferencePages/DlgSettingsViewColor.ui PreferencePages/DlgSettingsWorkbenches.ui - DlgCheckableMessageBox.ui - DlgToolbars.ui - DlgTreeWidget.ui - DlgLocationAngle.ui - DlgLocationPos.ui + Dialogs/DlgCheckableMessageBox.ui + Dialogs/DlgToolbars.ui + Dialogs/DlgTreeWidget.ui + Dialogs/DlgLocationAngle.ui + Dialogs/DlgLocationPos.ui DocumentRecovery.ui DownloadManager.ui DownloadItem.ui - DlgExpressionInput.ui + Dialogs/DlgExpressionInput.ui MouseButtons.ui SceneInspector.ui InputVector.ui @@ -415,14 +418,14 @@ SET(Gui_UIC_SRCS TaskView/TaskImage.ui TaskView/TaskSelectLinkProperty.ui TaskElementColors.ui - DlgObjectSelection.ui - DlgAddProperty.ui - DlgAddPropertyVarSet.ui + Dialogs/DlgObjectSelection.ui + Dialogs/DlgAddProperty.ui + Dialogs/DlgAddPropertyVarSet.ui VectorListEditor.ui ) if(FREECAD_USE_3DCONNEXION_LEGACY) - list(APPEND Gui_UIC_SRCS DlgCustomizeSpNavSettings.ui) + list(APPEND Gui_UIC_SRCS Dialogs/DlgCustomizeSpNavSettings.ui) endif(FREECAD_USE_3DCONNEXION_LEGACY) set (FreeCAD_TR_QRC ${CMAKE_CURRENT_BINARY_DIR}/Language/FreeCAD_translation.qrc) @@ -475,28 +478,28 @@ SOURCE_GROUP("Command" FILES ${Command_SRCS}) SET(Dialog_CPP_SRCS Clipping.cpp DemoMode.cpp - DlgAbout.cpp - DlgActivateWindowImp.cpp - DlgCreateNewPreferencePackImp.cpp - DlgUnitsCalculatorImp.cpp - DlgInputDialogImp.cpp - DlgMacroExecuteImp.cpp - DlgRunExternal.cpp - DlgEditFileIncludePropertyExternal.cpp - DlgMacroRecordImp.cpp - DlgMaterialPropertiesImp.cpp - DlgParameterImp.cpp - DlgParameterFind.cpp - DlgPreferencePackManagementImp.cpp - DlgProjectInformationImp.cpp - DlgProjectUtility.cpp - DlgPropertyLink.cpp - DlgRevertToBackupConfigImp.cpp - DlgExpressionInput.cpp + Dialogs/DlgAbout.cpp + Dialogs/DlgActivateWindowImp.cpp + Dialogs/DlgCreateNewPreferencePackImp.cpp + Dialogs/DlgUnitsCalculatorImp.cpp + Dialogs/DlgInputDialogImp.cpp + Dialogs/DlgMacroExecuteImp.cpp + Dialogs/DlgRunExternal.cpp + Dialogs/DlgEditFileIncludePropertyExternal.cpp + Dialogs/DlgMacroRecordImp.cpp + Dialogs/DlgMaterialPropertiesImp.cpp + Dialogs/DlgParameterImp.cpp + Dialogs/DlgParameterFind.cpp + Dialogs/DlgPreferencePackManagementImp.cpp + Dialogs/DlgProjectInformationImp.cpp + Dialogs/DlgProjectUtility.cpp + Dialogs/DlgPropertyLink.cpp + Dialogs/DlgRevertToBackupConfigImp.cpp + Dialogs/DlgExpressionInput.cpp TaskDlgRelocation.cpp - DlgCheckableMessageBox.cpp + Dialogs/DlgCheckableMessageBox.cpp TaskCSysDragger.cpp - DlgUndoRedo.cpp + Dialogs/DlgUndoRedo.cpp InputVector.cpp Placement.cpp PropertyPage.cpp @@ -507,37 +510,37 @@ SET(Dialog_CPP_SRCS DownloadManager.cpp DocumentRecovery.cpp TaskElementColors.cpp - DlgObjectSelection.cpp - DlgAddProperty.cpp - DlgAddPropertyVarSet.cpp + Dialogs/DlgObjectSelection.cpp + Dialogs/DlgAddProperty.cpp + Dialogs/DlgAddPropertyVarSet.cpp VectorListEditor.cpp ) SET(Dialog_HPP_SRCS Clipping.h DemoMode.h - DlgAbout.h - DlgActivateWindowImp.h - DlgCreateNewPreferencePackImp.h - DlgUnitsCalculatorImp.h - DlgInputDialogImp.h - DlgMacroExecuteImp.h - DlgRunExternal.h - DlgEditFileIncludePropertyExternal.h - DlgMacroRecordImp.h - DlgMaterialPropertiesImp.h - DlgParameterImp.h - DlgParameterFind.h - DlgPreferencePackManagementImp.h - DlgProjectInformationImp.h - DlgProjectUtility.h - DlgPropertyLink.h - DlgRevertToBackupConfigImp.h - DlgCheckableMessageBox.h - DlgExpressionInput.h + Dialogs/DlgAbout.h + Dialogs/DlgActivateWindowImp.h + Dialogs/DlgCreateNewPreferencePackImp.h + Dialogs/DlgUnitsCalculatorImp.h + Dialogs/DlgInputDialogImp.h + Dialogs/DlgMacroExecuteImp.h + Dialogs/DlgRunExternal.h + Dialogs/DlgEditFileIncludePropertyExternal.h + Dialogs/DlgMacroRecordImp.h + Dialogs/DlgMaterialPropertiesImp.h + Dialogs/DlgParameterImp.h + Dialogs/DlgParameterFind.h + Dialogs/DlgPreferencePackManagementImp.h + Dialogs/DlgProjectInformationImp.h + Dialogs/DlgProjectUtility.h + Dialogs/DlgPropertyLink.h + Dialogs/DlgRevertToBackupConfigImp.h + Dialogs/DlgCheckableMessageBox.h + Dialogs/DlgExpressionInput.h TaskDlgRelocation.h TaskCSysDragger.h - DlgUndoRedo.h + Dialogs/DlgUndoRedo.h InputVector.h Placement.h PropertyPage.h @@ -548,40 +551,40 @@ SET(Dialog_HPP_SRCS DownloadManager.h DocumentRecovery.h TaskElementColors.h - DlgObjectSelection.h - DlgAddProperty.h - DlgAddPropertyVarSet.h + Dialogs/DlgObjectSelection.h + Dialogs/DlgAddProperty.h + Dialogs/DlgAddPropertyVarSet.h VectorListEditor.h ) SET(Dialog_SRCS ${Dialog_CPP_SRCS} ${Dialog_HPP_SRCS} - AboutApplication.ui + Dialogs/AboutApplication.ui Clipping.ui DemoMode.ui - DlgActivateWindow.ui - DlgUnitsCalculator.ui - DlgAuthorization.ui - DlgInputDialog.ui - DlgAddProperty.ui - DlgLocationAngle.ui - DlgLocationPos.ui - DlgMacroExecute.ui - DlgRunExternal.ui - DlgMacroRecord.ui - DlgMaterialProperties.ui - DlgParameter.ui - DlgParameterFind.ui - DlgPreferencePackManagement.ui - DlgProjectInformation.ui - DlgProjectUtility.ui - DlgPropertyLink.ui - DlgRevertToBackupConfig.ui - DlgCheckableMessageBox.ui - DlgTreeWidget.ui - DlgExpressionInput.ui - DlgCreateNewPreferencePack.ui + Dialogs/DlgActivateWindow.ui + Dialogs/DlgUnitsCalculator.ui + Dialogs/DlgAuthorization.ui + Dialogs/DlgInputDialog.ui + Dialogs/DlgAddProperty.ui + Dialogs/DlgLocationAngle.ui + Dialogs/DlgLocationPos.ui + Dialogs/DlgMacroExecute.ui + Dialogs/DlgRunExternal.ui + Dialogs/DlgMacroRecord.ui + Dialogs/DlgMaterialProperties.ui + Dialogs/DlgParameter.ui + Dialogs/DlgParameterFind.ui + Dialogs/DlgPreferencePackManagement.ui + Dialogs/DlgProjectInformation.ui + Dialogs/DlgProjectUtility.ui + Dialogs/DlgPropertyLink.ui + Dialogs/DlgRevertToBackupConfig.ui + Dialogs/DlgCheckableMessageBox.ui + Dialogs/DlgTreeWidget.ui + Dialogs/DlgExpressionInput.ui + Dialogs/DlgCreateNewPreferencePack.ui DownloadManager.ui DownloadItem.ui DocumentRecovery.ui @@ -591,58 +594,58 @@ SET(Dialog_SRCS SceneInspector.ui TextureMapping.ui TaskElementColors.ui - DlgObjectSelection.ui + Dialogs/DlgObjectSelection.ui VectorListEditor.ui ) SOURCE_GROUP("Dialog" FILES ${Dialog_SRCS}) # The customize dialog sources SET(Dialog_Customize_CPP_SRCS - DlgActionsImp.cpp - DlgCustomizeImp.cpp - DlgKeyboardImp.cpp - DlgToolbarsImp.cpp - ListWidgetDragBugFix.cpp + Dialogs/DlgActionsImp.cpp + Dialogs/DlgCustomizeImp.cpp + Dialogs/DlgKeyboardImp.cpp + Dialogs/DlgToolbarsImp.cpp + PreferencePages/ListWidgetDragBugFix.cpp ) SET(Dialog_Customize_HPP_SRCS - DlgActionsImp.h - DlgCustomizeImp.h - DlgKeyboardImp.h - DlgToolbarsImp.h - ListWidgetDragBugFix.h + Dialogs/DlgActionsImp.h + Dialogs/DlgCustomizeImp.h + Dialogs/DlgKeyboardImp.h + Dialogs/DlgToolbarsImp.h + PreferencePages/ListWidgetDragBugFix.h ) if(FREECAD_USE_3DCONNEXION_LEGACY) - list(APPEND Dialog_Customize_CPP_SRCS DlgCustomizeSpaceball.cpp DlgCustomizeSpNavSettings.cpp) - list(APPEND Dialog_Customize_HPP_SRCS DlgCustomizeSpaceball.h DlgCustomizeSpNavSettings.h) + list(APPEND Dialog_Customize_CPP_SRCS Dialogs/DlgCustomizeSpaceball.cpp Dialogs/DlgCustomizeSpNavSettings.cpp) + list(APPEND Dialog_Customize_HPP_SRCS Dialogs/DlgCustomizeSpaceball.h Dialogs/DlgCustomizeSpNavSettings.h) endif(FREECAD_USE_3DCONNEXION_LEGACY) SET(Dialog_Customize_SRCS ${Dialog_Customize_CPP_SRCS} ${Dialog_Customize_HPP_SRCS} - DlgActions.ui - DlgChooseIcon.ui - DlgKeyboard.ui - DlgToolbars.ui + Dialogs/DlgActions.ui + Dialogs/DlgChooseIcon.ui + Dialogs/DlgKeyboard.ui + Dialogs/DlgToolbars.ui ) if(FREECAD_USE_3DCONNEXION_LEGACY) - list(APPEND Dialog_Customize_SRCS DlgCustomizeSpNavSettings.ui) + list(APPEND Dialog_Customize_SRCS Dialogs/DlgCustomizeSpNavSettings.ui) endif(FREECAD_USE_3DCONNEXION_LEGACY) SOURCE_GROUP("Dialog\\Customize" FILES ${Dialog_Customize_SRCS}) # The settings dialog sources SET(Dialog_Settings_CPP_SRCS - DlgOnlineHelpImp.cpp - DlgPreferencesImp.cpp + Dialogs/DlgOnlineHelpImp.cpp + Dialogs/DlgPreferencesImp.cpp PreferencePages/DlgSettings3DViewImp.cpp PreferencePages/DlgSettingsCacheDirectory.cpp - DlgSettingsColorGradientImp.cpp + Dialogs/DlgSettingsColorGradientImp.cpp PreferencePages/DlgSettingsDocumentImp.cpp PreferencePages/DlgSettingsEditor.cpp PreferencePages/DlgSettingsGeneral.cpp - DlgSettingsImageImp.cpp + Dialogs/DlgSettingsImageImp.cpp PreferencePages/DlgSettingsLightSources.cpp PreferencePages/DlgSettingsMacroImp.cpp PreferencePages/DlgSettingsNavigation.cpp @@ -656,15 +659,15 @@ SET(Dialog_Settings_CPP_SRCS PreferencePages/DlgSettingsAdvanced.cpp ) SET(Dialog_Settings_HPP_SRCS - DlgOnlineHelpImp.h - DlgPreferencesImp.h + Dialogs/DlgOnlineHelpImp.h + Dialogs/DlgPreferencesImp.h PreferencePages/DlgSettings3DViewImp.h PreferencePages/DlgSettingsCacheDirectory.h - DlgSettingsColorGradientImp.h + Dialogs/DlgSettingsColorGradientImp.h PreferencePages/DlgSettingsDocumentImp.h PreferencePages/DlgSettingsEditor.h PreferencePages/DlgSettingsGeneral.h - DlgSettingsImageImp.h + Dialogs/DlgSettingsImageImp.h PreferencePages/DlgSettingsLightSources.h PreferencePages/DlgSettingsMacroImp.h PreferencePages/DlgSettingsNavigation.h @@ -680,15 +683,15 @@ SET(Dialog_Settings_HPP_SRCS SET(Dialog_Settings_SRCS ${Dialog_Settings_CPP_SRCS} ${Dialog_Settings_HPP_SRCS} - DlgOnlineHelp.ui - DlgPreferences.ui + Dialogs/DlgOnlineHelp.ui + Dialogs/DlgPreferences.ui PreferencePages/DlgSettings3DView.ui PreferencePages/DlgSettingsCacheDirectory.ui - DlgSettingsColorGradient.ui + Dialogs/DlgSettingsColorGradient.ui PreferencePages/DlgSettingsDocument.ui PreferencePages/DlgSettingsEditor.ui PreferencePages/DlgSettingsGeneral.ui - DlgSettingsImage.ui + Dialogs/DlgSettingsImage.ui PreferencePages/DlgSettingsLightSources.ui PreferencePages/DlgSettingsMacro.ui PreferencePages/DlgSettingsNavigation.ui @@ -708,7 +711,7 @@ SET(Dock_Windows_CPP_SRCS DockWindow.cpp PropertyView.cpp ReportView.cpp - SelectionView.cpp + Selection/SelectionView.cpp ToolBox.cpp Tree.cpp TreeView.cpp @@ -723,7 +726,7 @@ SET(Dock_Windows_HPP_SRCS DockWindow.h PropertyView.h ReportView.h - SelectionView.h + Selection/SelectionView.h ToolBox.h Tree.h TreeView.h @@ -892,18 +895,6 @@ SET(View3D_CPP_SRCS GLPainter.cpp Multisample.cpp MouseSelection.cpp - NavigationStyle.cpp - NavigationStylePyImp.cpp - InventorNavigationStyle.cpp - CADNavigationStyle.cpp - RevitNavigationStyle.cpp - BlenderNavigationStyle.cpp - MayaGestureNavigationStyle.cpp - OpenCascadeNavigationStyle.cpp - OpenSCADNavigationStyle.cpp - TinkerCADNavigationStyle.cpp - TouchpadNavigationStyle.cpp - GestureNavigationStyle.cpp SplitView3DInventor.cpp View.cpp View3DInventor.cpp @@ -915,8 +906,6 @@ SET(View3D_CPP_SRCS View3DPy.cpp View3DViewerPy.cpp NaviCube.cpp - NavigationAnimator.cpp - NavigationAnimation.cpp ) SET(View3D_SRCS ${View3D_CPP_SRCS} @@ -926,9 +915,6 @@ SET(View3D_SRCS GLPainter.h Multisample.h MouseSelection.h - NavigationStyle.h - NavigationStylePy.xml - GestureNavigationStyle.h SplitView3DInventor.h View.h View3DInventor.h @@ -940,11 +926,35 @@ SET(View3D_SRCS CoinRiftWidget.h View3DViewerPy.h NaviCube.h - NavigationAnimator.h - NavigationAnimation.h ) SOURCE_GROUP("View3D" FILES ${View3D_SRCS}) +SET(Navigation_CPP_SRCS + Navigation/NavigationStyle.cpp + Navigation/NavigationStylePyImp.cpp + Navigation/InventorNavigationStyle.cpp + Navigation/CADNavigationStyle.cpp + Navigation/RevitNavigationStyle.cpp + Navigation/BlenderNavigationStyle.cpp + Navigation/MayaGestureNavigationStyle.cpp + Navigation/OpenCascadeNavigationStyle.cpp + Navigation/OpenSCADNavigationStyle.cpp + Navigation/TinkerCADNavigationStyle.cpp + Navigation/TouchpadNavigationStyle.cpp + Navigation/GestureNavigationStyle.cpp + Navigation/NavigationAnimator.cpp + Navigation/NavigationAnimation.cpp +) +SET(Navigation_SRCS + ${Navigation_CPP_SRCS} + Navigation/NavigationStyle.h + Navigation/NavigationStylePy.xml + Navigation/GestureNavigationStyle.h + Navigation/NavigationAnimator.h + Navigation/NavigationAnimation.h +) +SOURCE_GROUP("Navigation" FILES ${Navigation_SRCS}) + #quarter sources FILE(GLOB_RECURSE Quarter_CPP_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} Quarter/*.cpp) FILE(GLOB_RECURSE Quarter_H_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} Quarter/*.h) @@ -1069,10 +1079,10 @@ SET(Inventor_CPP_SRCS SoFCInteractiveElement.cpp SoFCOffscreenRenderer.cpp SoQtOffscreenRendererPy.cpp - SoFCSelection.cpp - SoFCUnifiedSelection.cpp - SoFCSelectionContext.cpp - SoFCSelectionAction.cpp + Selection/SoFCSelection.cpp + Selection/SoFCUnifiedSelection.cpp + Selection/SoFCSelectionContext.cpp + Selection/SoFCSelectionAction.cpp SoFCVectorizeSVGAction.cpp SoFCVectorizeU3DAction.cpp SoDevicePixelRatioElement.cpp @@ -1101,10 +1111,10 @@ SET(Inventor_SRCS SoFCInteractiveElement.h SoFCOffscreenRenderer.h SoQtOffscreenRendererPy.h - SoFCSelection.h - SoFCUnifiedSelection.h - SoFCSelectionContext.h - SoFCSelectionAction.h + Selection/SoFCSelection.h + Selection/SoFCUnifiedSelection.h + Selection/SoFCSelectionContext.h + Selection/SoFCSelectionAction.h SoFCVectorizeSVGAction.h SoFCVectorizeU3DAction.h SoDevicePixelRatioElement.h @@ -1136,6 +1146,9 @@ SET(Widget_CPP_SRCS Widgets.cpp Window.cpp WorkbenchSelector.cpp + ElideLabel.cpp + ElideCheckBox.cpp + FontScaledSVG.cpp ) SET(Widget_HPP_SRCS FileDialog.h @@ -1157,6 +1170,9 @@ SET(Widget_HPP_SRCS Widgets.h Window.h WorkbenchSelector.h + ElideLabel.h + ElideCheckBox.h + FontScaledSVG.h ) SET(Widget_SRCS ${Widget_CPP_SRCS} @@ -1241,19 +1257,19 @@ SET(Workbench_SRCS SOURCE_GROUP("Workbench" FILES ${Workbench_SRCS}) SET(Selection_SRCS - SelectionObjectPyImp.cpp - SelectionObject.h - SelectionObject.cpp - Selection.h - Selection.cpp - SelectionFilter.h - SelectionFilter.cpp - SelectionFilterPy.h - SelectionFilterPy.cpp - SelectionFilter.y - SelectionFilter.l - SelectionObserverPython.cpp - SelectionObserverPython.h + Selection/SelectionObjectPyImp.cpp + Selection/SelectionObject.h + Selection/SelectionObject.cpp + Selection/Selection.h + Selection/Selection.cpp + Selection/SelectionFilter.h + Selection/SelectionFilter.cpp + Selection/SelectionFilterPy.h + Selection/SelectionFilterPy.cpp + Selection/SelectionFilter.y + Selection/SelectionFilter.l + Selection/SelectionObserverPython.cpp + Selection/SelectionObserverPython.h ) SOURCE_GROUP("Selection" FILES ${Selection_SRCS}) @@ -1357,6 +1373,7 @@ SET(FreeCADGui_SRCS ${Resource_SRCS} ${Quarter_SRCS} ${View3D_SRCS} + ${Navigation_SRCS} ${Viewprovider_SRCS} ${Widget_SRCS} ${Params_SRCS} @@ -1411,7 +1428,7 @@ if (EIGEN3_NO_DEPRECATED_COPY) NaviCube.cpp Inventor/SoAutoZoomTranslation.cpp SoFCOffscreenRenderer.cpp - SoFCSelectionAction.cpp + Selection/SoFCSelectionAction.cpp SoFCCSysDragger.cpp Quarter/QuarterWidget.cpp View3DInventorViewer.cpp diff --git a/src/Gui/Command.cpp b/src/Gui/Command.cpp index 750cd4fbf0..5fb02b32bc 100644 --- a/src/Gui/Command.cpp +++ b/src/Gui/Command.cpp @@ -50,7 +50,7 @@ #include "Application.h" #include "BitmapFactory.h" #include "Control.h" -#include "DlgUndoRedo.h" +#include "Dialogs/DlgUndoRedo.h" #include "Document.h" #include "frameobject.h" #include "Macro.h" @@ -251,7 +251,7 @@ bool Command::isViewOfType(Base::Type t) const Gui::BaseView *v = d->getActiveView(); if (!v) return false; - if (v->getTypeId().isDerivedFrom(t)) + if (v->isDerivedFrom(t)) return true; else return false; @@ -1079,7 +1079,7 @@ Action * GroupCommand::createAction() { for(auto &v : cmds) { if(!v.first) - pcAction->addAction(QString::fromLatin1(""))->setSeparator(true); + pcAction->addAction(QStringLiteral(""))->setSeparator(true); else v.first->addToGroup(pcAction); } @@ -1175,7 +1175,7 @@ void MacroCommand::activated(int iMsg) d = QDir(QString::fromUtf8(cMacroPath.c_str())); } else { - QString dirstr = QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro"); + QString dirstr = QString::fromStdString(App::Application::getHomePath()) + QStringLiteral("Macro"); d = QDir(dirstr); } @@ -1560,7 +1560,7 @@ void PythonGroupCommand::activated(int iMsg) if (cmd.hasAttr("Activated")) { Py::Callable call(cmd.getAttr("Activated")); Py::Tuple args(1); - args.setItem(0, Py::Int(iMsg)); + args.setItem(0, Py::Long(iMsg)); Py::Object ret = call.apply(args); } // If the command group doesn't implement the 'Activated' method then invoke the command directly @@ -1640,7 +1640,7 @@ Action * PythonGroupCommand::createAction() if (cmd.hasAttr("GetDefaultCommand")) { Py::Callable call2(cmd.getAttr("GetDefaultCommand")); - Py::Int def(call2.apply(args)); + Py::Long def(call2.apply(args)); defaultId = static_cast(def); } diff --git a/src/Gui/Command.h b/src/Gui/Command.h index b8f975eeca..661d1b1c75 100644 --- a/src/Gui/Command.h +++ b/src/Gui/Command.h @@ -1117,7 +1117,7 @@ protected: \ virtual bool isActive(void)\ {\ Gui::MDIView* view = Gui::getMainWindow()->activeWindow();\ - return view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId());\ + return view && view->isDerivedFrom();\ }\ private:\ X(const X&) = delete;\ diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index a61512d16c..6d9274b69a 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -55,13 +55,13 @@ #include "FileDialog.h" #include "MainWindow.h" #include "Selection.h" -#include "DlgObjectSelection.h" -#include "DlgProjectInformationImp.h" -#include "DlgProjectUtility.h" +#include "Dialogs/DlgObjectSelection.h" +#include "Dialogs/DlgProjectInformationImp.h" +#include "Dialogs/DlgProjectUtility.h" #include "GraphvizView.h" #include "ManualAlignment.h" #include "MergeDocuments.h" -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "Placement.h" #include "Transform.h" #include "View3DInventor.h" @@ -638,7 +638,7 @@ void StdCmdExportDependencyGraph::activated(int iMsg) { Q_UNUSED(iMsg); App::Document* doc = App::GetApplication().getActiveDocument(); - QString format = QString::fromLatin1("%1 (*.gv)").arg(Gui::GraphvizView::tr("Graphviz format")); + QString format = QStringLiteral("%1 (*.gv)").arg(Gui::GraphvizView::tr("Graphviz format")); QString fn = Gui::FileDialog::getSaveFileName(Gui::getMainWindow(), Gui::GraphvizView::tr("Export graph"), QString(), format); if (!fn.isEmpty()) { QFile file(fn); @@ -679,7 +679,7 @@ void StdCmdNew::activated(int iMsg) { Q_UNUSED(iMsg); QString cmd; - cmd = QString::fromLatin1("App.newDocument()"); + cmd = QStringLiteral("App.newDocument()"); runCommand(Command::Doc,cmd.toUtf8()); doCommand(Command::Gui,"Gui.activeDocument().activeView().viewDefaultOrientation()"); @@ -1385,6 +1385,11 @@ void StdCmdDelete::activated(int iMsg) bool autoDeletion = true; for(auto &sel : sels) { auto obj = sel.getObject(); + if (obj == nullptr){ + Base::Console().DeveloperWarning("StdCmdDelete::activated", + "App::DocumentObject pointer is nullptr\n"); + continue; + } for(auto parent : obj->getInList()) { if(!Selection().isSelected(parent)) { ViewProvider* vp = Application::Instance->getViewProvider(parent); @@ -1396,7 +1401,7 @@ void StdCmdDelete::activated(int iMsg) else label = QLatin1String(parent->getNameInDocument()); if(parent->Label.getStrValue() != parent->getNameInDocument()) - label += QString::fromLatin1(" (%1)").arg( + label += QStringLiteral(" (%1)").arg( QString::fromUtf8(parent->Label.getValue())); affectedLabels.insert(label); if(affectedLabels.size()>=10) { @@ -1462,7 +1467,7 @@ void StdCmdDelete::activated(int iMsg) e.ReportException(); } catch (...) { QMessageBox::critical(getMainWindow(), QObject::tr("Delete failed"), - QString::fromLatin1("Unknown error")); + QStringLiteral("Unknown error")); } commitCommand(); Gui::getMainWindow()->setUpdatesEnabled(true); @@ -1728,7 +1733,7 @@ void StdCmdEdit::activated(int iMsg) { Q_UNUSED(iMsg); Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); - if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + if (view && view->isDerivedFrom()) { Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); if (viewer->isEditingViewProvider()) { doCommand(Command::Gui,"Gui.activeDocument().resetEdit()"); diff --git a/src/Gui/CommandFeat.cpp b/src/Gui/CommandFeat.cpp index 4f42511030..de54763b75 100644 --- a/src/Gui/CommandFeat.cpp +++ b/src/Gui/CommandFeat.cpp @@ -244,30 +244,30 @@ void StdCmdSendToPythonConsole::activated(int iMsg) // clear variables from previous run, if any QString cmd = QLatin1String("try:\n del(doc,lnk,obj,shp,sub,subs)\nexcept Exception:\n pass\n"); Gui::Command::runCommand(Gui::Command::Gui,cmd.toLatin1()); - cmd = QString::fromLatin1("doc = App.getDocument(\"%1\")").arg(docname); + cmd = QStringLiteral("doc = App.getDocument(\"%1\")").arg(docname); Gui::Command::runCommand(Gui::Command::Gui,cmd.toLatin1()); //support links if (obj->isDerivedFrom()) { - cmd = QString::fromLatin1("lnk = doc.getObject(\"%1\")").arg(objname); + cmd = QStringLiteral("lnk = doc.getObject(\"%1\")").arg(objname); Gui::Command::runCommand(Gui::Command::Gui,cmd.toLatin1()); - cmd = QString::fromLatin1("obj = lnk.getLinkedObject()"); + cmd = QStringLiteral("obj = lnk.getLinkedObject()"); Gui::Command::runCommand(Gui::Command::Gui,cmd.toLatin1()); const auto link = static_cast(obj); obj = link->getLinkedObject(); } else { - cmd = QString::fromLatin1("obj = doc.getObject(\"%1\")").arg(objname); + cmd = QStringLiteral("obj = doc.getObject(\"%1\")").arg(objname); Gui::Command::runCommand(Gui::Command::Gui,cmd.toLatin1()); } if (obj->isDerivedFrom()) { const auto geoObj = static_cast(obj); const App::PropertyGeometry* geo = geoObj->getPropertyOfGeometry(); if (geo){ - cmd = QString::fromLatin1("shp = obj.") + QLatin1String(geo->getName()); //"Shape", "Mesh", "Points", etc. + cmd = QStringLiteral("shp = obj.") + QLatin1String(geo->getName()); //"Shape", "Mesh", "Points", etc. Gui::Command::runCommand(Gui::Command::Gui, cmd.toLatin1()); if (sels[0].hasSubNames()) { std::vector subnames = sels[0].getSubNames(); QString subname = QString::fromLatin1(subnames[0].c_str()); - cmd = QString::fromLatin1("sub = obj.getSubObject(\"%1\")").arg(subname); + cmd = QStringLiteral("sub = obj.getSubObject(\"%1\")").arg(subname); Gui::Command::runCommand(Gui::Command::Gui,cmd.toLatin1()); if (subnames.size() > 1) { std::ostringstream strm; diff --git a/src/Gui/CommandLink.cpp b/src/Gui/CommandLink.cpp index 875f5b093b..eddb113e8a 100644 --- a/src/Gui/CommandLink.cpp +++ b/src/Gui/CommandLink.cpp @@ -413,7 +413,7 @@ static void linkConvert(bool unlink) { continue; }else{ auto name = doc->getUniqueObjectName("Link"); - auto link = static_cast(doc->addObject("App::Link",name.c_str())); + auto link = doc->addObject(name.c_str()); if(!link) FC_THROWM(Base::RuntimeError,"Failed to create link"); link->setLink(-1,obj); diff --git a/src/Gui/CommandMacro.cpp b/src/Gui/CommandMacro.cpp index f192213ae8..ed022cde1a 100644 --- a/src/Gui/CommandMacro.cpp +++ b/src/Gui/CommandMacro.cpp @@ -29,8 +29,8 @@ #include "Action.h" #include "Application.h" #include "BitmapFactory.h" -#include "DlgMacroExecuteImp.h" -#include "DlgMacroRecordImp.h" +#include "Dialogs/DlgMacroExecuteImp.h" +#include "Dialogs/DlgMacroRecordImp.h" #include "Macro.h" #include "MainWindow.h" #include "PythonDebugger.h" diff --git a/src/Gui/CommandPyImp.cpp b/src/Gui/CommandPyImp.cpp index 57d6b9bac2..048b88bb1e 100644 --- a/src/Gui/CommandPyImp.cpp +++ b/src/Gui/CommandPyImp.cpp @@ -100,7 +100,7 @@ PyObject* CommandPy::listByShortcut(PyObject *args) for (Command* c : cmds) { Action* action = c->getAction(); if (action) { - QString spc = QString::fromLatin1(" "); + QString spc = QStringLiteral(" "); if (Base::asBoolean(bIsRegularExp)) { QRegularExpression re(QString::fromLatin1(shortcut_to_find), QRegularExpression::CaseInsensitiveOption); if (!re.isValid()) { diff --git a/src/Gui/CommandStd.cpp b/src/Gui/CommandStd.cpp index 67536d6d62..d48a784e63 100644 --- a/src/Gui/CommandStd.cpp +++ b/src/Gui/CommandStd.cpp @@ -42,11 +42,11 @@ #include "Action.h" #include "BitmapFactory.h" #include "Command.h" -#include "DlgAbout.h" -#include "DlgCustomizeImp.h" -#include "DlgParameterImp.h" -#include "DlgPreferencesImp.h" -#include "DlgUnitsCalculatorImp.h" +#include "Dialogs/DlgAbout.h" +#include "Dialogs/DlgCustomizeImp.h" +#include "Dialogs/DlgParameterImp.h" +#include "Dialogs/DlgPreferencesImp.h" +#include "Dialogs/DlgUnitsCalculatorImp.h" #include "GuiConsole.h" #include "MainWindow.h" #include "OnlineDocumentation.h" @@ -358,7 +358,7 @@ void StdCmdRestartInSafeMode::activated(int iMsg) { QStringList args = QApplication::arguments(); args.pop_front(); - auto const safeModeArgument = QString::fromLatin1("--safe-mode"); + auto const safeModeArgument = QStringLiteral("--safe-mode"); if (!args.contains(safeModeArgument)) { args.append(safeModeArgument); } @@ -534,7 +534,7 @@ StdCmdOnlineHelp::StdCmdOnlineHelp() void StdCmdOnlineHelp::activated(int iMsg) { Q_UNUSED(iMsg); - Gui::getMainWindow()->showDocumentation(QString::fromLatin1("Online_Help_Startpage")); + Gui::getMainWindow()->showDocumentation(QStringLiteral("Online_Help_Startpage")); } //=========================================================================== @@ -885,8 +885,8 @@ Gui::Action * StdCmdUserEditMode::createAction() QAction* act = pcAction->addAction(QString()); auto modeName = QString::fromStdString(uem.second.first).remove(QChar::fromLatin1('&')); act->setCheckable(true); - act->setIcon(BitmapFactory().iconFromTheme(qPrintable(QString::fromLatin1("Std_UserEditMode")+modeName))); - act->setObjectName(QString::fromLatin1("Std_UserEditMode")+modeName); + act->setIcon(BitmapFactory().iconFromTheme(qPrintable(QStringLiteral("Std_UserEditMode")+modeName))); + act->setObjectName(QStringLiteral("Std_UserEditMode")+modeName); act->setWhatsThis(QString::fromLatin1(getWhatsThis())); act->setToolTip(QString::fromStdString(uem.second.second)); diff --git a/src/Gui/CommandTest.cpp b/src/Gui/CommandTest.cpp index 0a86fa47a7..00f3888803 100644 --- a/src/Gui/CommandTest.cpp +++ b/src/Gui/CommandTest.cpp @@ -70,8 +70,8 @@ void Std_TestQM::activated(int iMsg) { Q_UNUSED(iMsg); QStringList files = QFileDialog::getOpenFileNames(getMainWindow(), - QString::fromLatin1("Test translation"), QString(), - QString::fromLatin1("Translation (*.qm)")); + QStringLiteral("Test translation"), QString(), + QStringLiteral("Translation (*.qm)")); if (!files.empty()) { Translator::instance()->activateLanguage("English"); QList i18n = qApp->findChildren(); diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index 672c4862c6..04fe6742ae 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -61,14 +61,14 @@ #include "Control.h" #include "Clipping.h" #include "DemoMode.h" -#include "DlgSettingsImageImp.h" +#include "Dialogs/DlgSettingsImageImp.h" #include "Document.h" #include "FileDialog.h" #include "ImageView.h" #include "Inventor/SoAxisCrossKit.h" #include "Macro.h" #include "MainWindow.h" -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "OverlayParams.h" #include "OverlayManager.h" #include "SceneInspector.h" @@ -339,19 +339,19 @@ Action * StdCmdFreezeViews::createAction() saveView->setWhatsThis(QString::fromLatin1(getWhatsThis())); QAction* loadView = pcAction->addAction(QObject::tr("&Load views...")); loadView->setWhatsThis(QString::fromLatin1(getWhatsThis())); - pcAction->addAction(QString::fromLatin1(""))->setSeparator(true); + pcAction->addAction(QStringLiteral(""))->setSeparator(true); freezeView = pcAction->addAction(QObject::tr("F&reeze view")); freezeView->setShortcut(QString::fromLatin1(getAccel())); freezeView->setWhatsThis(QString::fromLatin1(getWhatsThis())); clearView = pcAction->addAction(QObject::tr("&Clear views")); clearView->setWhatsThis(QString::fromLatin1(getWhatsThis())); - separator = pcAction->addAction(QString::fromLatin1("")); + separator = pcAction->addAction(QStringLiteral("")); separator->setSeparator(true); offset = pcAction->actions().count(); // allow up to 50 views for (int i=0; iaddAction(QString::fromLatin1(""))->setVisible(false); + pcAction->addAction(QStringLiteral(""))->setVisible(false); return pcAction; } @@ -394,7 +394,7 @@ void StdCmdFreezeViews::activated(int iMsg) (*it)->setToolTip(QString::fromLatin1(ppReturn)); (*it)->setVisible(true); if (index < 10) { - (*it)->setShortcut(QKeySequence(QString::fromLatin1("CTRL+%1").arg(index))); + (*it)->setShortcut(QKeySequence(QStringLiteral("CTRL+%1").arg(index))); } break; } @@ -410,7 +410,7 @@ void StdCmdFreezeViews::activated(int iMsg) // Activate a view QList acts = pcAction->actions(); QString data = acts[iMsg]->toolTip(); - QString send = QString::fromLatin1("SetCamera %1").arg(data); + QString send = QStringLiteral("SetCamera %1").arg(data); getGuiApplication()->sendMsgToActiveView(send.toLatin1()); } } @@ -419,7 +419,7 @@ void StdCmdFreezeViews::onSaveViews() { // Save the views to an XML file QString fn = FileDialog::getSaveFileName(getMainWindow(), QObject::tr("Save frozen views"), - QString(), QString::fromLatin1("%1 (*.cam)").arg(QObject::tr("Frozen views"))); + QString(), QStringLiteral("%1 (*.cam)").arg(QObject::tr("Frozen views"))); if (fn.isEmpty()) return; QFile file(fn); @@ -440,11 +440,11 @@ void StdCmdFreezeViews::onSaveViews() // remove the first line because it's a comment like '#Inventor V2.1 ascii' QString viewPos; if (!data.isEmpty()) { - QStringList lines = data.split(QString::fromLatin1("\n")); + QStringList lines = data.split(QStringLiteral("\n")); if (lines.size() > 1) { lines.pop_front(); } - viewPos = lines.join(QString::fromLatin1(" ")); + viewPos = lines.join(QStringLiteral(" ")); } str << " \n"; @@ -469,7 +469,7 @@ void StdCmdFreezeViews::onRestoreViews() // Restore the views from an XML file QString fn = FileDialog::getOpenFileName(getMainWindow(), QObject::tr("Restore frozen views"), - QString(), QString::fromLatin1("%1 (*.cam)").arg(QObject::tr("Frozen views"))); + QString(), QStringLiteral("%1 (*.cam)").arg(QObject::tr("Frozen views"))); if (fn.isEmpty()) return; QFile file(fn); @@ -500,19 +500,19 @@ void StdCmdFreezeViews::onRestoreViews() } bool ok; - int scheme = root.attribute(QString::fromLatin1("SchemaVersion")).toInt(&ok); + int scheme = root.attribute(QStringLiteral("SchemaVersion")).toInt(&ok); if (!ok) return; // SchemeVersion "1" if (scheme == 1) { // read the views, ignore the attribute 'Count' - QDomElement child = root.firstChildElement(QString::fromLatin1("Views")); - QDomElement views = child.firstChildElement(QString::fromLatin1("Camera")); + QDomElement child = root.firstChildElement(QStringLiteral("Views")); + QDomElement views = child.firstChildElement(QStringLiteral("Camera")); QStringList cameras; while (!views.isNull()) { - QString setting = views.attribute(QString::fromLatin1("settings")); + QString setting = views.attribute(QStringLiteral("settings")); cameras << setting; - views = views.nextSiblingElement(QString::fromLatin1("Camera")); + views = views.nextSiblingElement(QStringLiteral("Camera")); } // use this rather than the attribute 'Count' because it could be @@ -533,7 +533,7 @@ void StdCmdFreezeViews::onRestoreViews() acts[i+offset]->setToolTip(setting); acts[i+offset]->setVisible(true); if (i < 9) { - acts[i+offset]->setShortcut(QKeySequence(QString::fromLatin1("CTRL+%1").arg(i+1))); + acts[i+offset]->setShortcut(QKeySequence(QStringLiteral("CTRL+%1").arg(i+1))); } } @@ -668,44 +668,44 @@ Gui::Action * StdCmdDrawStyle::createAction() a0->setCheckable(true); a0->setIcon(BitmapFactory().iconFromTheme("DrawStyleAsIs")); a0->setChecked(true); - a0->setObjectName(QString::fromLatin1("Std_DrawStyleAsIs")); - a0->setShortcut(QKeySequence(QString::fromUtf8("V,1"))); + a0->setObjectName(QStringLiteral("Std_DrawStyleAsIs")); + a0->setShortcut(QKeySequence(QStringLiteral("V,1"))); a0->setWhatsThis(QString::fromLatin1(getWhatsThis())); QAction* a1 = pcAction->addAction(QString()); a1->setCheckable(true); a1->setIcon(BitmapFactory().iconFromTheme("DrawStylePoints")); - a1->setObjectName(QString::fromLatin1("Std_DrawStylePoints")); - a1->setShortcut(QKeySequence(QString::fromUtf8("V,2"))); + a1->setObjectName(QStringLiteral("Std_DrawStylePoints")); + a1->setShortcut(QKeySequence(QStringLiteral("V,2"))); a1->setWhatsThis(QString::fromLatin1(getWhatsThis())); QAction* a2 = pcAction->addAction(QString()); a2->setCheckable(true); a2->setIcon(BitmapFactory().iconFromTheme("DrawStyleWireFrame")); - a2->setObjectName(QString::fromLatin1("Std_DrawStyleWireframe")); - a2->setShortcut(QKeySequence(QString::fromUtf8("V,3"))); + a2->setObjectName(QStringLiteral("Std_DrawStyleWireframe")); + a2->setShortcut(QKeySequence(QStringLiteral("V,3"))); a2->setWhatsThis(QString::fromLatin1(getWhatsThis())); QAction* a3 = pcAction->addAction(QString()); a3->setCheckable(true); a3->setIcon(BitmapFactory().iconFromTheme("DrawStyleHiddenLine")); - a3->setObjectName(QString::fromLatin1("Std_DrawStyleHiddenLine")); - a3->setShortcut(QKeySequence(QString::fromUtf8("V,4"))); + a3->setObjectName(QStringLiteral("Std_DrawStyleHiddenLine")); + a3->setShortcut(QKeySequence(QStringLiteral("V,4"))); a3->setWhatsThis(QString::fromLatin1(getWhatsThis())); QAction* a4 = pcAction->addAction(QString()); a4->setCheckable(true); a4->setIcon(BitmapFactory().iconFromTheme("DrawStyleNoShading")); - a4->setObjectName(QString::fromLatin1("Std_DrawStyleNoShading")); - a4->setShortcut(QKeySequence(QString::fromUtf8("V,5"))); + a4->setObjectName(QStringLiteral("Std_DrawStyleNoShading")); + a4->setShortcut(QKeySequence(QStringLiteral("V,5"))); a4->setWhatsThis(QString::fromLatin1(getWhatsThis())); QAction* a5 = pcAction->addAction(QString()); a5->setCheckable(true); a5->setIcon(BitmapFactory().iconFromTheme("DrawStyleShaded")); - a5->setObjectName(QString::fromLatin1("Std_DrawStyleShaded")); - a5->setShortcut(QKeySequence(QString::fromUtf8("V,6"))); + a5->setObjectName(QStringLiteral("Std_DrawStyleShaded")); + a5->setShortcut(QKeySequence(QStringLiteral("V,6"))); a5->setWhatsThis(QString::fromLatin1(getWhatsThis())); QAction* a6 = pcAction->addAction(QString()); a6->setCheckable(true); a6->setIcon(BitmapFactory().iconFromTheme("DrawStyleFlatLines")); - a6->setObjectName(QString::fromLatin1("Std_DrawStyleFlatLines")); - a6->setShortcut(QKeySequence(QString::fromUtf8("V,7"))); + a6->setObjectName(QStringLiteral("Std_DrawStyleFlatLines")); + a6->setShortcut(QKeySequence(QStringLiteral("V,7"))); a6->setWhatsThis(QString::fromLatin1(getWhatsThis())); pcAction->setIcon(a0->icon()); @@ -931,7 +931,7 @@ void StdCmdToggleTransparency::activated(int iMsg) App::Document* doc = obj->getDocument(); Gui::ViewProvider* view = Application::Instance->getDocument(doc)->getViewProvider(obj); App::Property* prop = view->getPropertyByName("Transparency"); - if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) { + if (prop && prop->isDerivedFrom()) { // To prevent toggling the tip of a PD body (see #11353), we check if the parent has a // Tip prop. const std::vector parents = obj->getInList(); @@ -942,7 +942,7 @@ void StdCmdToggleTransparency::activated(int iMsg) if (parentProp) { // Make sure it has a transparency prop too parentProp = parentView->getPropertyByName("Transparency"); - if (parentProp && parentProp->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) { + if (parentProp && parentProp->isDerivedFrom()) { view = parentView; } } @@ -967,7 +967,7 @@ void StdCmdToggleTransparency::activated(int iMsg) bool oneTransparent = false; for (auto* view : viewsToToggle) { App::Property* prop = view->getPropertyByName("Transparency"); - if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) { + if (prop && prop->isDerivedFrom()) { auto* transparencyProp = dynamic_cast(prop); int transparency = transparencyProp->getValue(); if (transparency != 0) { @@ -984,7 +984,7 @@ void StdCmdToggleTransparency::activated(int iMsg) for (auto* view : viewsToToggle) { App::Property* prop = view->getPropertyByName("Transparency"); - if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) { + if (prop && prop->isDerivedFrom()) { auto* transparencyProp = dynamic_cast(prop); transparencyProp->setValue(transparency); } @@ -1033,7 +1033,7 @@ void StdCmdToggleSelectability::activated(int iMsg) for (const auto & ft : sel) { ViewProvider *pr = pcDoc->getViewProviderByName(ft->getNameInDocument()); - if (pr && pr->isDerivedFrom(ViewProviderGeometryObject::getClassTypeId())){ + if (pr && pr->isDerivedFrom()){ if (static_cast(pr)->Selectable.getValue()) doCommand(Gui,"Gui.getDocument(\"%s\").getObject(\"%s\").Selectable=False" , doc->getName(), ft->getNameInDocument()); @@ -1959,7 +1959,7 @@ void StdViewScreenShot::activated(int iMsg) QStringList filter; QString selFilter; for (QStringList::Iterator it = formats.begin(); it != formats.end(); ++it) { - filter << QString::fromLatin1("%1 %2 (*.%3)").arg((*it).toUpper(), + filter << QStringLiteral("%1 %2 (*.%3)").arg((*it).toUpper(), QObject::tr("files"), (*it).toLower()); if (ext == *it) selFilter = filter.last(); @@ -2121,8 +2121,8 @@ void StdViewLoadImage::activated(int iMsg) QFileDialog dialog(Gui::getMainWindow()); dialog.setWindowTitle(QObject::tr("Choose an image file to open")); dialog.setMimeTypeFilters(mimeTypeFilters); - dialog.selectMimeTypeFilter(QString::fromLatin1("image/png")); - dialog.setDefaultSuffix(QString::fromLatin1("png")); + dialog.selectMimeTypeFilter(QStringLiteral("image/png")); + dialog.setDefaultSuffix(QStringLiteral("png")); dialog.setAcceptMode(QFileDialog::AcceptOpen); dialog.setOption(QFileDialog::DontUseNativeDialog); @@ -2187,7 +2187,7 @@ void StdCmdToggleNavigation::activated(int iMsg) { Q_UNUSED(iMsg); Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); - if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + if (view && view->isDerivedFrom()) { Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); SbBool toggle = viewer->isRedirectedToSceneGraph(); viewer->setRedirectToSceneGraph(!toggle); @@ -2203,7 +2203,7 @@ bool StdCmdToggleNavigation::isActive() if (Gui::Control().activeDialog()) return false; Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); - if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + if (view && view->isDerivedFrom()) { Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); return viewer->isEditing() && viewer->isRedirectToSceneGraphEnabled(); } @@ -3203,7 +3203,7 @@ void StdCmdTextureMapping::activated(int iMsg) bool StdCmdTextureMapping::isActive() { Gui::MDIView* view = getMainWindow()->activeWindow(); - return view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId()) + return view && view->isDerivedFrom() && (!(Gui::Control().activeDialog())); } diff --git a/src/Gui/CommandWindow.cpp b/src/Gui/CommandWindow.cpp index c8ee5c24ed..b4e925aee5 100644 --- a/src/Gui/CommandWindow.cpp +++ b/src/Gui/CommandWindow.cpp @@ -34,7 +34,7 @@ #include "MainWindow.h" #include "View.h" #include "Document.h" -#include "DlgActivateWindowImp.h" +#include "Dialogs/DlgActivateWindowImp.h" #include "DockWindowManager.h" #include "ToolBarManager.h" diff --git a/src/Gui/DAGView/DAGFilter.cpp b/src/Gui/DAGView/DAGFilter.cpp index 57bc3915af..e331d52d2e 100644 --- a/src/Gui/DAGView/DAGFilter.cpp +++ b/src/Gui/DAGView/DAGFilter.cpp @@ -31,7 +31,7 @@ using namespace Gui; using namespace DAG; -FilterBase::FilterBase() : name(QString::fromLatin1("empty name")) +FilterBase::FilterBase() : name(QStringLiteral("empty name")) { } diff --git a/src/Gui/DAGView/DAGModel.cpp b/src/Gui/DAGView/DAGModel.cpp index 2db0d5fea4..9dc8a902a9 100644 --- a/src/Gui/DAGView/DAGModel.cpp +++ b/src/Gui/DAGView/DAGModel.cpp @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include #include "DAGModel.h" @@ -315,7 +315,7 @@ void Model::slotChangeObject(const ViewProviderDocumentObject &VPDObjectIn, cons text->setPlainText(QString::fromUtf8(record.DObject->Label.getValue())); } } - else if (propertyIn.isDerivedFrom(App::PropertyLinkBase::getClassTypeId())) + else if (propertyIn.isDerivedFrom()) { if (hasRecord(&VPDObjectIn, *graphLink)) { diff --git a/src/Gui/DAGView/DAGView.h b/src/Gui/DAGView/DAGView.h index 9b9ccd75e9..23fc7b4677 100644 --- a/src/Gui/DAGView/DAGView.h +++ b/src/Gui/DAGView/DAGView.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include "DAGModel.h" diff --git a/src/Gui/DemoMode.cpp b/src/Gui/DemoMode.cpp index 861e1bf86f..e253246b3d 100644 --- a/src/Gui/DemoMode.cpp +++ b/src/Gui/DemoMode.cpp @@ -143,12 +143,8 @@ void DemoMode::hideEvent(QHideEvent*) Gui::View3DInventor* DemoMode::activeView() const { - Document* doc = Application::Instance->activeDocument(); - if (doc) { - MDIView* view = doc->getActiveView(); - if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { - return static_cast(view); - } + if (Document* doc = Application::Instance->activeDocument()) { + return Base::freecad_dynamic_cast(doc->getActiveView()); } return nullptr; diff --git a/src/Gui/AboutApplication.ui b/src/Gui/Dialogs/AboutApplication.ui similarity index 99% rename from src/Gui/AboutApplication.ui rename to src/Gui/Dialogs/AboutApplication.ui index 61787e56c1..d8b4daa7fd 100644 --- a/src/Gui/AboutApplication.ui +++ b/src/Gui/Dialogs/AboutApplication.ui @@ -33,7 +33,7 @@ - :/icons/freecadsplash.png + :/icons/freecadsplash.png Qt::AlignCenter @@ -398,7 +398,7 @@ p, li { white-space: pre-wrap; } - + diff --git a/src/Gui/DlgAbout.cpp b/src/Gui/Dialogs/DlgAbout.cpp similarity index 83% rename from src/Gui/DlgAbout.cpp rename to src/Gui/Dialogs/DlgAbout.cpp index 74ec04eaee..8a1808333f 100644 --- a/src/Gui/DlgAbout.cpp +++ b/src/Gui/Dialogs/DlgAbout.cpp @@ -45,21 +45,22 @@ #include #include #include +#include #include -#include +#include #include #include #include "BitmapFactory.h" -#include "DlgAbout.h" +#include "Dialogs/DlgAbout.h" #include "MainWindow.h" #include "SplashScreen.h" #include "ui_AboutApplication.h" using namespace Gui; using namespace Gui::Dialog; -namespace fs = boost::filesystem; +namespace fs = std::filesystem; static QString prettyProductInfoWrapper() { @@ -67,7 +68,7 @@ static QString prettyProductInfoWrapper() #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) #ifdef FC_OS_MACOSX auto macosVersionFile = - QString::fromUtf8("/System/Library/CoreServices/.SystemVersionPlatform.plist"); + QStringLiteral("/System/Library/CoreServices/.SystemVersionPlatform.plist"); auto fi = QFileInfo(macosVersionFile); if (fi.exists() && fi.isReadable()) { auto plistFile = QFile(macosVersionFile); @@ -77,10 +78,10 @@ static QString prettyProductInfoWrapper() if (line.contains("ProductUserVisibleVersion")) { auto nextLine = plistFile.readLine(); if (nextLine.contains("")) { - QRegularExpression re(QString::fromUtf8("\\s*(.*)")); + QRegularExpression re(QStringLiteral("\\s*(.*)")); auto matches = re.match(QString::fromUtf8(nextLine)); if (matches.hasMatch()) { - productName = QString::fromUtf8("macOS ") + matches.captured(1); + productName = QStringLiteral("macOS ") + matches.captured(1); break; } } @@ -91,22 +92,22 @@ static QString prettyProductInfoWrapper() #endif #ifdef FC_OS_WIN64 QSettings regKey { - QString::fromUtf8("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), + QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat}; - if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) { - auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt(); + if (regKey.contains(QStringLiteral("CurrentBuildNumber"))) { + auto buildNumber = regKey.value(QStringLiteral("CurrentBuildNumber")).toInt(); if (buildNumber > 0) { if (buildNumber < 9200) { - productName = QString::fromUtf8("Windows 7 build %1").arg(buildNumber); + productName = QStringLiteral("Windows 7 build %1").arg(buildNumber); } else if (buildNumber < 10240) { - productName = QString::fromUtf8("Windows 8 build %1").arg(buildNumber); + productName = QStringLiteral("Windows 8 build %1").arg(buildNumber); } else if (buildNumber < 22000) { - productName = QString::fromUtf8("Windows 10 build %1").arg(buildNumber); + productName = QStringLiteral("Windows 10 build %1").arg(buildNumber); } else { - productName = QString::fromUtf8("Windows 11 build %1").arg(buildNumber); + productName = QStringLiteral("Windows 11 build %1").arg(buildNumber); } } } @@ -210,7 +211,7 @@ QPixmap AboutDialog::aboutImage() const { // See if we have a custom About screen image set QPixmap about_image; - QFileInfo fi(QString::fromLatin1("images:about_image.png")); + QFileInfo fi(QStringLiteral("images:about_image.png")); if (fi.isFile() && fi.exists()) { about_image.load(fi.filePath(), "PNG"); } @@ -250,7 +251,7 @@ void AboutDialog::setupLabels() #endif // avoid overriding user set style sheet if (qApp->styleSheet().isEmpty()) { - setStyleSheet(QString::fromLatin1("Gui--Dialog--AboutDialog QLabel {font-size: %1pt;}") + setStyleSheet(QStringLiteral("Gui--Dialog--AboutDialog QLabel {font-size: %1pt;}") .arg(fontSize)); } @@ -271,41 +272,41 @@ void AboutDialog::setupLabels() // gets replaced to "FreeCAD", for example QString author = ui->labelAuthor->text(); - author.replace(QString::fromLatin1("Unknown Application"), exeName); - author.replace(QString::fromLatin1("(c) Unknown Author"), banner); + author.replace(QStringLiteral("Unknown Application"), exeName); + author.replace(QStringLiteral("(c) Unknown Author"), banner); ui->labelAuthor->setText(author); ui->labelAuthor->setUrl(mturl); if (qApp->styleSheet().isEmpty()) { - ui->labelAuthor->setStyleSheet(QString::fromLatin1( + ui->labelAuthor->setStyleSheet(QStringLiteral( "Gui--UrlLabel {color: #0000FF;text-decoration: underline;font-weight: 600;}")); } QString version = ui->labelBuildVersion->text(); - version.replace(QString::fromLatin1("Unknown"), - QString::fromLatin1("%1.%2.%3%4").arg(major, minor, point, suffix)); + version.replace(QStringLiteral("Unknown"), + QStringLiteral("%1.%2.%3%4").arg(major, minor, point, suffix)); ui->labelBuildVersion->setText(version); QString revision = ui->labelBuildRevision->text(); - revision.replace(QString::fromLatin1("Unknown"), build); + revision.replace(QStringLiteral("Unknown"), build); ui->labelBuildRevision->setText(revision); QString date = ui->labelBuildDate->text(); - date.replace(QString::fromLatin1("Unknown"), disda); + date.replace(QStringLiteral("Unknown"), disda); ui->labelBuildDate->setText(date); QString os = ui->labelBuildOS->text(); - os.replace(QString::fromLatin1("Unknown"), prettyProductInfoWrapper()); + os.replace(QStringLiteral("Unknown"), prettyProductInfoWrapper()); ui->labelBuildOS->setText(os); QString architecture = ui->labelBuildRunArchitecture->text(); if (QSysInfo::buildCpuArchitecture() == QSysInfo::currentCpuArchitecture()) { - architecture.replace(QString::fromLatin1("Unknown"), QSysInfo::buildCpuArchitecture()); + architecture.replace(QStringLiteral("Unknown"), QSysInfo::buildCpuArchitecture()); } else { architecture.replace( - QString::fromLatin1("Unknown"), - QString::fromLatin1("%1 (running on: %2)") + QStringLiteral("Unknown"), + QStringLiteral("%1 (running on: %2)") .arg(QSysInfo::buildCpuArchitecture(), QSysInfo::currentCpuArchitecture())); } ui->labelBuildRunArchitecture->setText(architecture); @@ -314,7 +315,7 @@ void AboutDialog::setupLabels() it = config.find("BuildRevisionBranch"); if (it != config.end()) { QString branch = ui->labelBuildBranch->text(); - branch.replace(QString::fromLatin1("Unknown"), QString::fromStdString(it->second)); + branch.replace(QStringLiteral("Unknown"), QString::fromStdString(it->second)); ui->labelBuildBranch->setText(branch); } else { @@ -327,7 +328,7 @@ void AboutDialog::setupLabels() if (it != config.end()) { QString hash = ui->labelBuildHash->text(); hash.replace( - QString::fromLatin1("Unknown"), + QStringLiteral("Unknown"), QString::fromStdString(it->second).left(7)); // Use the 7-char abbreviated hash ui->labelBuildHash->setText(hash); if (auto url_itr = config.find("BuildRepositoryURL"); url_itr != config.end()) { @@ -337,15 +338,15 @@ void AboutDialog::setupLabels() url = url.left(space); // Strip off the branch information to get just the repo } - if (url == QString::fromUtf8("Unknown")) { - url = QString::fromUtf8("https://github.com/FreeCAD/FreeCAD"); // Just take a guess + if (url == QStringLiteral("Unknown")) { + url = QStringLiteral("https://github.com/FreeCAD/FreeCAD"); // Just take a guess } // This may only create valid URLs for Github, but some other hosts use the same format // so give it a shot... - auto https = url.replace(QString::fromUtf8("git://"), QString::fromUtf8("https://")); - https.replace(QString::fromUtf8(".git"), QString::fromUtf8("")); - ui->labelBuildHash->setUrl(https + QString::fromUtf8("/commit/") + auto https = url.replace(QStringLiteral("git://"), QStringLiteral("https://")); + https.replace(QStringLiteral(".git"), QStringLiteral("")); + ui->labelBuildHash->setUrl(https + QStringLiteral("/commit/") + QString::fromStdString(it->second)); } } @@ -365,26 +366,26 @@ void AboutDialog::showCredits() } auto tab_credits = new QWidget(); - tab_credits->setObjectName(QString::fromLatin1("tab_credits")); + tab_credits->setObjectName(QStringLiteral("tab_credits")); ui->tabWidget->addTab(tab_credits, tr("Credits")); auto hlayout = new QVBoxLayout(tab_credits); auto textField = new QTextBrowser(tab_credits); textField->setOpenExternalLinks(true); hlayout->addWidget(textField); - QString creditsHTML = QString::fromLatin1("

"); + QString creditsHTML = QStringLiteral("

"); //: Header for bgbsww creditsHTML += tr("This version of FreeCAD is dedicated to the memory of Brad McLean, aka bgbsww."); //: Header for the Credits tab of the About screen - creditsHTML += QString::fromLatin1("

"); + creditsHTML += QStringLiteral("

"); creditsHTML += tr("Credits"); - creditsHTML += QString::fromLatin1("

"); + creditsHTML += QStringLiteral("

"); creditsHTML += tr("FreeCAD would not be possible without the contributions of"); - creditsHTML += QString::fromLatin1(":

"); + creditsHTML += QStringLiteral(":

"); //: Header for the list of individual people in the Credits list. creditsHTML += tr("Individuals"); - creditsHTML += QString::fromLatin1("

    "); + creditsHTML += QStringLiteral("
      "); QTextStream stream(&creditsFile); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -393,37 +394,37 @@ void AboutDialog::showCredits() QString line; while (stream.readLineInto(&line)) { if (!line.isEmpty()) { - if (line == QString::fromLatin1("Firms")) { - creditsHTML += QString::fromLatin1("

    "); + if (line == QStringLiteral("Firms")) { + creditsHTML += QStringLiteral("

"); //: Header for the list of companies/organizations in the Credits list. creditsHTML += tr("Organizations"); - creditsHTML += QString::fromLatin1("

    "); + creditsHTML += QStringLiteral("
      "); } else { - creditsHTML += QString::fromLatin1("
    • ") + line + QString::fromLatin1("
    • "); + creditsHTML += QStringLiteral("
    • ") + line + QStringLiteral("
    • "); } } } - creditsHTML += QString::fromLatin1("
    "); + creditsHTML += QStringLiteral("
"); textField->setHtml(creditsHTML); } void AboutDialog::showLicenseInformation() { - QString licenseFileURL = QString::fromLatin1("%1/LICENSE.html") + QString licenseFileURL = QStringLiteral("%1/LICENSE.html") .arg(QString::fromStdString(App::Application::getHelpDir())); QFile licenseFile(licenseFileURL); if (licenseFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QString licenseHTML = QString::fromUtf8(licenseFile.readAll()); const auto placeholder = - QString::fromUtf8(""); + QStringLiteral(""); licenseHTML.replace(placeholder, getAdditionalLicenseInformation()); ui->tabWidget->removeTab(1); // Hide the license placeholder widget auto tab_license = new QWidget(); - tab_license->setObjectName(QString::fromLatin1("tab_license")); + tab_license->setObjectName(QStringLiteral("tab_license")); ui->tabWidget->addTab(tab_license, tr("License")); auto hlayout = new QVBoxLayout(tab_license); auto textField = new QTextBrowser(tab_license); @@ -437,7 +438,7 @@ void AboutDialog::showLicenseInformation() QString info(QLatin1String("SUCH DAMAGES.
")); info += getAdditionalLicenseInformation(); QString lictext = ui->textBrowserLicense->toHtml(); - lictext.replace(QString::fromLatin1("SUCH DAMAGES.
"), info); + lictext.replace(QStringLiteral("SUCH DAMAGES.
"), info); ui->textBrowserLicense->setHtml(lictext); } } @@ -449,7 +450,7 @@ QString AboutDialog::getAdditionalLicenseInformation() const // and add an
tag at the end to nicely separate license blocks QString info; #ifdef _USE_3DCONNEXION_SDK - info += QString::fromUtf8( + info += QStringLiteral( "

3D Mouse Support

" "

Development tools and related technology provided under license from 3Dconnexion.
" "Copyright © 1992–2012 3Dconnexion. All rights reserved.

" @@ -461,7 +462,7 @@ QString AboutDialog::getAdditionalLicenseInformation() const void AboutDialog::showLibraryInformation() { auto tab_library = new QWidget(); - tab_library->setObjectName(QString::fromLatin1("tab_library")); + tab_library->setObjectName(QStringLiteral("tab_library")); ui->tabWidget->addTab(tab_library, tr("Libraries")); auto hlayout = new QVBoxLayout(tab_library); auto textField = new QTextBrowser(tab_library); @@ -469,7 +470,7 @@ void AboutDialog::showLibraryInformation() textField->setOpenLinks(false); hlayout->addWidget(textField); - QString baseurl = QString::fromLatin1("file:///%1/ThirdPartyLibraries.html") + QString baseurl = QStringLiteral("file:///%1/ThirdPartyLibraries.html") .arg(QString::fromStdString(App::Application::getHelpDir())); textField->setSource(QUrl(baseurl)); @@ -484,7 +485,7 @@ void AboutDialog::showCollectionInformation() } auto tab_collection = new QWidget(); - tab_collection->setObjectName(QString::fromLatin1("tab_collection")); + tab_collection->setObjectName(QStringLiteral("tab_collection")); ui->tabWidget->addTab(tab_collection, tr("Collection")); auto hlayout = new QVBoxLayout(tab_collection); auto textField = new QTextBrowser(tab_collection); @@ -503,7 +504,7 @@ void AboutDialog::showPrivacyPolicy() } auto text = QString::fromUtf8(policyFile.readAll()); auto tabPrivacyPolicy = new QWidget(); - tabPrivacyPolicy->setObjectName(QString::fromLatin1("tabPrivacyPolicy")); + tabPrivacyPolicy->setObjectName(QStringLiteral("tabPrivacyPolicy")); ui->tabWidget->addTab(tabPrivacyPolicy, tr("Privacy Policy")); auto hLayout = new QVBoxLayout(tabPrivacyPolicy); auto textField = new QTextBrowser(tabPrivacyPolicy); @@ -527,7 +528,7 @@ void AboutDialog::linkActivated(const QUrl& link) QString fragment = link.fragment(); if (fragment.startsWith(QLatin1String("_Toc"))) { QString prefix = fragment.mid(4); - title = QString::fromLatin1("%1 %2").arg(prefix, title); + title = QStringLiteral("%1 %2").arg(prefix, title); } licenseView->setWindowTitle(title); getMainWindow()->addWindow(licenseView); @@ -547,8 +548,8 @@ void AboutDialog::addModuleInfo(QTextStream& str, const QString& modPath, bool& str << " * " << (mod.isDir() ? QDir(modPath).dirName() : mod.fileName()); try { auto metadataFile = - boost::filesystem::path(mod.absoluteFilePath().toStdString()) / "package.xml"; - if (boost::filesystem::exists(metadataFile)) { + std::filesystem::path(mod.absoluteFilePath().toStdString()) / "package.xml"; + if (std::filesystem::exists(metadataFile)) { App::Metadata metadata(metadataFile); if (metadata.version() != App::Meta::Version()) { str << QLatin1String(" ") + QString::fromStdString(metadata.version().str()); @@ -560,7 +561,7 @@ void AboutDialog::addModuleInfo(QTextStream& str, const QString& modPath, bool& QChar::fromLatin1(' ')); str << " (Malformed metadata: " << what << ")"; } - QFileInfo disablingFile(mod.absoluteFilePath(), QString::fromLatin1("ADDON_DISABLED")); + QFileInfo disablingFile(mod.absoluteFilePath(), QStringLiteral("ADDON_DISABLED")); if (disablingFile.exists()) { str << " (Disabled)"; } @@ -652,6 +653,28 @@ void AboutDialog::copyToClipboard() str << "Qt " << QT_VERSION_STR << ", "; str << "Coin " << COIN_VERSION << ", "; str << "Vtk " << fcVtkVersion << ", "; + + const char* cmd = "import ifcopenshell\n" + "version = ifcopenshell.version"; + PyObject * ifcopenshellVer = nullptr; + + try { + ifcopenshellVer = Base::Interpreter().getValue(cmd, "version"); + } + catch (const Base::Exception& e) { + Base::Console().Log("%s (safe to ignore, unless using the BIM workbench and IFC).\n", e.what()); + } + + if (ifcopenshellVer) { + const char* ifcopenshellVerAsStr = PyUnicode_AsUTF8(ifcopenshellVer); + + if (ifcopenshellVerAsStr) { + str << "IfcOpenShell " << ifcopenshellVerAsStr << ", "; + Py_DECREF(ifcopenshellVerAsStr); + } + Py_DECREF(ifcopenshellVer); + } + #if defined(HAVE_OCC_VERSION) str << "OCC " << OCC_VERSION_MAJOR << "." << OCC_VERSION_MINOR << "." << OCC_VERSION_MAINTENANCE #ifdef OCC_VERSION_DEVELOPMENT @@ -709,6 +732,13 @@ void AboutDialog::copyToClipboard() str << "Stylesheet/Theme/QtStyle: " << QString::fromStdString(styleSheet) << "/" << QString::fromStdString(theme) << "/" << QString::fromStdString(style) << "\n"; + // Add DPI information + str << "Logical/physical DPI: " + << QApplication::primaryScreen()->logicalDotsPerInch() + << "/" + << QApplication::primaryScreen()->physicalDotsPerInch() + << "\n"; + // Add installed module information: auto modDir = fs::path(App::Application::getUserAppDataDir()) / "Mod"; bool firstMod = true; diff --git a/src/Gui/DlgAbout.h b/src/Gui/Dialogs/DlgAbout.h similarity index 100% rename from src/Gui/DlgAbout.h rename to src/Gui/Dialogs/DlgAbout.h diff --git a/src/Gui/DlgActions.ui b/src/Gui/Dialogs/DlgActions.ui similarity index 100% rename from src/Gui/DlgActions.ui rename to src/Gui/Dialogs/DlgActions.ui diff --git a/src/Gui/DlgActionsImp.cpp b/src/Gui/Dialogs/DlgActionsImp.cpp similarity index 96% rename from src/Gui/DlgActionsImp.cpp rename to src/Gui/Dialogs/DlgActionsImp.cpp index a1c72702e5..42ec839db5 100644 --- a/src/Gui/DlgActionsImp.cpp +++ b/src/Gui/Dialogs/DlgActionsImp.cpp @@ -33,7 +33,7 @@ #include #endif -#include "DlgActionsImp.h" +#include "Dialogs/DlgActionsImp.h" #include "ui_DlgActions.h" #include "Action.h" #include "Application.h" @@ -73,7 +73,7 @@ DlgCustomActionsImp::DlgCustomActionsImp(QWidget* parent) } QString systemMacroDirStr = - QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro"); + QString::fromStdString(App::Application::getHomePath()) + QStringLiteral("Macro"); d = QDir(systemMacroDirStr, QLatin1String("*.FCMacro *.py")); if (d.exists()) { for (unsigned int i = 0; i < d.count(); i++) { @@ -483,7 +483,7 @@ void IconDialog::onAddIconPath() QStringList filters; QList formats = QImageReader::supportedImageFormats(); for (const auto& format : formats) { - filters << QString::fromLatin1("*.%1").arg( + filters << QStringLiteral("*.%1").arg( QString::fromLatin1(format).toLower()); } QDir d(path); diff --git a/src/Gui/DlgActionsImp.h b/src/Gui/Dialogs/DlgActionsImp.h similarity index 100% rename from src/Gui/DlgActionsImp.h rename to src/Gui/Dialogs/DlgActionsImp.h diff --git a/src/Gui/DlgActivateWindow.ui b/src/Gui/Dialogs/DlgActivateWindow.ui similarity index 100% rename from src/Gui/DlgActivateWindow.ui rename to src/Gui/Dialogs/DlgActivateWindow.ui diff --git a/src/Gui/DlgActivateWindowImp.cpp b/src/Gui/Dialogs/DlgActivateWindowImp.cpp similarity index 96% rename from src/Gui/DlgActivateWindowImp.cpp rename to src/Gui/Dialogs/DlgActivateWindowImp.cpp index 1a7abd4829..8449fe9069 100644 --- a/src/Gui/DlgActivateWindowImp.cpp +++ b/src/Gui/Dialogs/DlgActivateWindowImp.cpp @@ -26,7 +26,7 @@ # include #endif -#include "DlgActivateWindowImp.h" +#include "Dialogs/DlgActivateWindowImp.h" #include "ui_DlgActivateWindow.h" #include "MainWindow.h" #include "MDIView.h" diff --git a/src/Gui/DlgActivateWindowImp.h b/src/Gui/Dialogs/DlgActivateWindowImp.h similarity index 100% rename from src/Gui/DlgActivateWindowImp.h rename to src/Gui/Dialogs/DlgActivateWindowImp.h diff --git a/src/Gui/DlgAddProperty.cpp b/src/Gui/Dialogs/DlgAddProperty.cpp similarity index 97% rename from src/Gui/DlgAddProperty.cpp rename to src/Gui/Dialogs/DlgAddProperty.cpp index 1454fec98a..f307dbf8bd 100644 --- a/src/Gui/DlgAddProperty.cpp +++ b/src/Gui/Dialogs/DlgAddProperty.cpp @@ -31,7 +31,7 @@ #include #include -#include "DlgAddProperty.h" +#include "Dialogs/DlgAddProperty.h" #include "ui_DlgAddProperty.h" #include "MainWindow.h" #include "ViewProviderDocumentObject.h" diff --git a/src/Gui/DlgAddProperty.h b/src/Gui/Dialogs/DlgAddProperty.h similarity index 100% rename from src/Gui/DlgAddProperty.h rename to src/Gui/Dialogs/DlgAddProperty.h diff --git a/src/Gui/DlgAddProperty.ui b/src/Gui/Dialogs/DlgAddProperty.ui similarity index 100% rename from src/Gui/DlgAddProperty.ui rename to src/Gui/Dialogs/DlgAddProperty.ui diff --git a/src/Gui/DlgAddPropertyVarSet.cpp b/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp similarity index 98% rename from src/Gui/DlgAddPropertyVarSet.cpp rename to src/Gui/Dialogs/DlgAddPropertyVarSet.cpp index adbd4a3504..312666ded2 100644 --- a/src/Gui/DlgAddPropertyVarSet.cpp +++ b/src/Gui/Dialogs/DlgAddPropertyVarSet.cpp @@ -34,7 +34,7 @@ #include #include -#include "DlgAddPropertyVarSet.h" +#include "Dialogs/DlgAddPropertyVarSet.h" #include "ui_DlgAddPropertyVarSet.h" #include "MainWindow.h" #include "ViewProviderVarSet.h" @@ -69,7 +69,7 @@ DlgAddPropertyVarSet::~DlgAddPropertyVarSet() = default; void DlgAddPropertyVarSet::initializeGroup() { - comboBoxGroup.setObjectName(QString::fromUtf8("comboBoxGroup")); + comboBoxGroup.setObjectName(QStringLiteral("comboBoxGroup")); comboBoxGroup.setInsertPolicy(QComboBox::InsertAtTop); comboBoxGroup.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); auto formLayout = qobject_cast(layout()); @@ -253,7 +253,7 @@ void DlgAddPropertyVarSet::addEditor(PropertyEditor::PropertyItem* propertyItem, })); propertyItem->setEditorData(editor.get(), QVariant()); editor->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - editor->setObjectName(QString::fromUtf8("editor")); + editor->setObjectName(QStringLiteral("editor")); auto formLayout = qobject_cast(layout()); formLayout->setWidget(3, QFormLayout::FieldRole, editor.get()); @@ -433,7 +433,7 @@ void DlgAddPropertyVarSet::checkGroup() { critical(QObject::tr("Invalid name"), QObject::tr("The group name must only contain alpha numericals,\n" "underscore, and must not start with a digit.")); - comboBoxGroup.setEditText(QString::fromUtf8("Base")); + comboBoxGroup.setEditText(QStringLiteral("Base")); throw CreatePropertyException("Invalid name"); } } diff --git a/src/Gui/DlgAddPropertyVarSet.h b/src/Gui/Dialogs/DlgAddPropertyVarSet.h similarity index 100% rename from src/Gui/DlgAddPropertyVarSet.h rename to src/Gui/Dialogs/DlgAddPropertyVarSet.h diff --git a/src/Gui/DlgAddPropertyVarSet.ui b/src/Gui/Dialogs/DlgAddPropertyVarSet.ui similarity index 100% rename from src/Gui/DlgAddPropertyVarSet.ui rename to src/Gui/Dialogs/DlgAddPropertyVarSet.ui diff --git a/src/Gui/DlgAuthorization.ui b/src/Gui/Dialogs/DlgAuthorization.ui similarity index 100% rename from src/Gui/DlgAuthorization.ui rename to src/Gui/Dialogs/DlgAuthorization.ui diff --git a/src/Gui/DlgCheckableMessageBox.cpp b/src/Gui/Dialogs/DlgCheckableMessageBox.cpp similarity index 98% rename from src/Gui/DlgCheckableMessageBox.cpp rename to src/Gui/Dialogs/DlgCheckableMessageBox.cpp index 815281ec2b..c326c739aa 100644 --- a/src/Gui/DlgCheckableMessageBox.cpp +++ b/src/Gui/Dialogs/DlgCheckableMessageBox.cpp @@ -35,7 +35,7 @@ #include -#include "DlgCheckableMessageBox.h" +#include "Dialogs/DlgCheckableMessageBox.h" #include "ui_DlgCheckableMessageBox.h" #include "MainWindow.h" @@ -44,7 +44,7 @@ namespace Gui { namespace Dialog { QByteArray toParamEntry(QString name) { - name.replace(QString::fromLatin1(" "), QString::fromLatin1("_")); + name.replace(QStringLiteral(" "), QStringLiteral("_")); return name.toLatin1(); } diff --git a/src/Gui/DlgCheckableMessageBox.h b/src/Gui/Dialogs/DlgCheckableMessageBox.h similarity index 98% rename from src/Gui/DlgCheckableMessageBox.h rename to src/Gui/Dialogs/DlgCheckableMessageBox.h index da268fb99a..443bf54ba7 100644 --- a/src/Gui/DlgCheckableMessageBox.h +++ b/src/Gui/Dialogs/DlgCheckableMessageBox.h @@ -104,11 +104,11 @@ public: /// It shows a dialog with header and message provided and a checkbox in check state with the message provided. /// It uses a parameter in path "User parameter:BaseApp/CheckMessages" derived from the header test, defaulting to false, /// to store the status of the checkbox, when the user exits the modal dialog. - static void showMessage(const QString& header, const QString& message, bool check = false, const QString& checkText = QString::fromLatin1("Don't show me again")); + static void showMessage(const QString& header, const QString& message, bool check = false, const QString& checkText = QStringLiteral("Don't show me again")); /// Same as showMessage above, but it checks the specific preference path and parameter provided, defaulting to entryDefault value if the parameter is not present. static void showMessage(const QString& header, const QString& message, const QString& prefPath, const QString& paramEntry, bool entryDefault = false, - bool check = false, const QString& checkText = QString::fromLatin1("Don't show me again")); + bool check = false, const QString& checkText = QStringLiteral("Don't show me again")); private Q_SLOTS: void slotClicked(QAbstractButton *b); diff --git a/src/Gui/DlgCheckableMessageBox.ui b/src/Gui/Dialogs/DlgCheckableMessageBox.ui similarity index 100% rename from src/Gui/DlgCheckableMessageBox.ui rename to src/Gui/Dialogs/DlgCheckableMessageBox.ui diff --git a/src/Gui/DlgChooseIcon.ui b/src/Gui/Dialogs/DlgChooseIcon.ui similarity index 100% rename from src/Gui/DlgChooseIcon.ui rename to src/Gui/Dialogs/DlgChooseIcon.ui diff --git a/src/Gui/DlgCreateNewPreferencePack.ui b/src/Gui/Dialogs/DlgCreateNewPreferencePack.ui similarity index 100% rename from src/Gui/DlgCreateNewPreferencePack.ui rename to src/Gui/Dialogs/DlgCreateNewPreferencePack.ui diff --git a/src/Gui/DlgCreateNewPreferencePackImp.cpp b/src/Gui/Dialogs/DlgCreateNewPreferencePackImp.cpp similarity index 98% rename from src/Gui/DlgCreateNewPreferencePackImp.cpp rename to src/Gui/Dialogs/DlgCreateNewPreferencePackImp.cpp index 5f0656ea38..a811b78e49 100644 --- a/src/Gui/DlgCreateNewPreferencePackImp.cpp +++ b/src/Gui/Dialogs/DlgCreateNewPreferencePackImp.cpp @@ -29,7 +29,7 @@ # include #endif -#include "DlgCreateNewPreferencePackImp.h" +#include "Dialogs/DlgCreateNewPreferencePackImp.h" #include "ui_DlgCreateNewPreferencePack.h" #include "FileDialog.h" @@ -49,7 +49,7 @@ DlgCreateNewPreferencePackImp::DlgCreateNewPreferencePackImp(QWidget* parent) { ui->setupUi(this); - QRegularExpression validNames(QString::fromUtf8(R"([^/\\?%*:|"<>]+)")); + QRegularExpression validNames(QStringLiteral(R"([^/\\?%*:|"<>]+)")); _nameValidator.setRegularExpression(validNames); ui->lineEdit->setValidator(&_nameValidator); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); diff --git a/src/Gui/DlgCreateNewPreferencePackImp.h b/src/Gui/Dialogs/DlgCreateNewPreferencePackImp.h similarity index 100% rename from src/Gui/DlgCreateNewPreferencePackImp.h rename to src/Gui/Dialogs/DlgCreateNewPreferencePackImp.h diff --git a/src/Gui/DlgCustomizeImp.cpp b/src/Gui/Dialogs/DlgCustomizeImp.cpp similarity index 94% rename from src/Gui/DlgCustomizeImp.cpp rename to src/Gui/Dialogs/DlgCustomizeImp.cpp index c1109d25c5..e35382ecb6 100644 --- a/src/Gui/DlgCustomizeImp.cpp +++ b/src/Gui/Dialogs/DlgCustomizeImp.cpp @@ -29,7 +29,7 @@ # include #endif -#include "DlgCustomizeImp.h" +#include "Dialogs/DlgCustomizeImp.h" #include "MainWindow.h" #include "WidgetFactory.h" @@ -79,7 +79,7 @@ DlgCustomizeImp::DlgCustomizeImp(QWidget* parent, Qt::WindowFlags fl) customLayout->addLayout( layout, 1, 0 ); tabWidget = new QTabWidget( this ); - tabWidget->setObjectName(QString::fromLatin1("Gui__Dialog__TabWidget"));//so we can find it in DlgMacroExecuteImp + tabWidget->setObjectName(QStringLiteral("Gui__Dialog__TabWidget"));//so we can find it in DlgMacroExecuteImp // make sure that pages are ready to create GetWidgetFactorySupplier(); diff --git a/src/Gui/DlgCustomizeImp.h b/src/Gui/Dialogs/DlgCustomizeImp.h similarity index 100% rename from src/Gui/DlgCustomizeImp.h rename to src/Gui/Dialogs/DlgCustomizeImp.h diff --git a/src/Gui/DlgCustomizeSpNavSettings.cpp b/src/Gui/Dialogs/DlgCustomizeSpNavSettings.cpp similarity index 99% rename from src/Gui/DlgCustomizeSpNavSettings.cpp rename to src/Gui/Dialogs/DlgCustomizeSpNavSettings.cpp index 3840d0b20e..8ee96ead45 100644 --- a/src/Gui/DlgCustomizeSpNavSettings.cpp +++ b/src/Gui/Dialogs/DlgCustomizeSpNavSettings.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" -#include "DlgCustomizeSpNavSettings.h" +#include "Dialogs/DlgCustomizeSpNavSettings.h" #include "ui_DlgCustomizeSpNavSettings.h" #include "Application.h" #include "GuiApplicationNativeEventAware.h" diff --git a/src/Gui/DlgCustomizeSpNavSettings.h b/src/Gui/Dialogs/DlgCustomizeSpNavSettings.h similarity index 100% rename from src/Gui/DlgCustomizeSpNavSettings.h rename to src/Gui/Dialogs/DlgCustomizeSpNavSettings.h diff --git a/src/Gui/DlgCustomizeSpNavSettings.ui b/src/Gui/Dialogs/DlgCustomizeSpNavSettings.ui similarity index 96% rename from src/Gui/DlgCustomizeSpNavSettings.ui rename to src/Gui/Dialogs/DlgCustomizeSpNavSettings.ui index 6784470029..06665c5de3 100644 --- a/src/Gui/DlgCustomizeSpNavSettings.ui +++ b/src/Gui/Dialogs/DlgCustomizeSpNavSettings.ui @@ -140,7 +140,7 @@
- :/icons/SpNav-PanLR + :/icons/SpNav-PanLR @@ -150,7 +150,7 @@ - :/icons/SpNav-PanUD + :/icons/SpNav-PanUD @@ -160,7 +160,7 @@ - :/icons/SpNav-Zoom + :/icons/SpNav-Zoom @@ -170,7 +170,7 @@ - :/icons/SpNav-Tilt + :/icons/SpNav-Tilt @@ -180,7 +180,7 @@ - :/icons/SpNav-Roll + :/icons/SpNav-Roll @@ -190,7 +190,7 @@ - :/icons/SpNav-Spin + :/icons/SpNav-Spin @@ -528,7 +528,7 @@ - + diff --git a/src/Gui/DlgCustomizeSpaceball.cpp b/src/Gui/Dialogs/DlgCustomizeSpaceball.cpp similarity index 99% rename from src/Gui/DlgCustomizeSpaceball.cpp rename to src/Gui/Dialogs/DlgCustomizeSpaceball.cpp index aa4a00cca6..5336840d02 100644 --- a/src/Gui/DlgCustomizeSpaceball.cpp +++ b/src/Gui/Dialogs/DlgCustomizeSpaceball.cpp @@ -39,7 +39,7 @@ #include "Base/Console.h" #include "Command.h" -#include "DlgCustomizeSpaceball.h" +#include "Dialogs/DlgCustomizeSpaceball.h" #include "Application.h" #include "BitmapFactory.h" #include "GuiApplicationNativeEventAware.h" @@ -282,7 +282,7 @@ QString ButtonModel::getLabel(const int &number) const GetGroup(numberString.toLatin1())-> GetASCII("Description","")); if (desc.length()) - desc = QString::fromUtf8(" \"") + desc + QString::fromUtf8("\""); + desc = QStringLiteral(" \"") + desc + QStringLiteral("\""); return tr("Button %1").arg(number + 1) + desc; } else return tr("Out Of Range"); @@ -492,7 +492,7 @@ CommandNode* CommandModel::nodeFromIndex(const QModelIndex &index) const void CommandModel::goAddMacro(const QByteArray ¯oName) { - QModelIndexList indexList(this->match(this->index(0,0), Qt::UserRole, QVariant(QString::fromLatin1("Macros")), + QModelIndexList indexList(this->match(this->index(0,0), Qt::UserRole, QVariant(QStringLiteral("Macros")), 1, Qt::MatchWrap | Qt::MatchRecursive)); QModelIndex macrosIndex; if (indexList.empty()) @@ -500,7 +500,7 @@ void CommandModel::goAddMacro(const QByteArray ¯oName) //this is the first macro and we have to add the Macros item. //figure out where to insert it. Should be in the command groups now. QStringList groups = orderedGroups(); - int location(groups.indexOf(QString::fromLatin1("Macros"))); + int location(groups.indexOf(QStringLiteral("Macros"))); if (location == -1) location = groups.size(); //add row diff --git a/src/Gui/DlgCustomizeSpaceball.h b/src/Gui/Dialogs/DlgCustomizeSpaceball.h similarity index 100% rename from src/Gui/DlgCustomizeSpaceball.h rename to src/Gui/Dialogs/DlgCustomizeSpaceball.h diff --git a/src/Gui/DlgEditFileIncludePropertyExternal.cpp b/src/Gui/Dialogs/DlgEditFileIncludePropertyExternal.cpp similarity index 95% rename from src/Gui/DlgEditFileIncludePropertyExternal.cpp rename to src/Gui/Dialogs/DlgEditFileIncludePropertyExternal.cpp index f273a21611..803372e5b2 100644 --- a/src/Gui/DlgEditFileIncludePropertyExternal.cpp +++ b/src/Gui/Dialogs/DlgEditFileIncludePropertyExternal.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" -#include "DlgEditFileIncludePropertyExternal.h" +#include "Dialogs/DlgEditFileIncludePropertyExternal.h" #include "Application.h" #include "FileDialog.h" diff --git a/src/Gui/DlgEditFileIncludePropertyExternal.h b/src/Gui/Dialogs/DlgEditFileIncludePropertyExternal.h similarity index 96% rename from src/Gui/DlgEditFileIncludePropertyExternal.h rename to src/Gui/Dialogs/DlgEditFileIncludePropertyExternal.h index 9826c4c047..d31101ce5b 100644 --- a/src/Gui/DlgEditFileIncludePropertyExternal.h +++ b/src/Gui/Dialogs/DlgEditFileIncludePropertyExternal.h @@ -24,7 +24,7 @@ #ifndef GUI_DIALOG_DlgEditFileIncludePropertyExternal_H #define GUI_DIALOG_DlgEditFileIncludePropertyExternal_H -#include "DlgRunExternal.h" +#include "Dialogs/DlgRunExternal.h" #include namespace Gui { diff --git a/src/Gui/DlgExpressionInput.cpp b/src/Gui/Dialogs/DlgExpressionInput.cpp similarity index 99% rename from src/Gui/DlgExpressionInput.cpp rename to src/Gui/Dialogs/DlgExpressionInput.cpp index 61798c8fa4..98e279af6a 100644 --- a/src/Gui/DlgExpressionInput.cpp +++ b/src/Gui/Dialogs/DlgExpressionInput.cpp @@ -37,7 +37,7 @@ #include #include -#include "DlgExpressionInput.h" +#include "Dialogs/DlgExpressionInput.h" #include "ui_DlgExpressionInput.h" #include "Application.h" #include "Command.h" diff --git a/src/Gui/DlgExpressionInput.h b/src/Gui/Dialogs/DlgExpressionInput.h similarity index 100% rename from src/Gui/DlgExpressionInput.h rename to src/Gui/Dialogs/DlgExpressionInput.h diff --git a/src/Gui/DlgExpressionInput.ui b/src/Gui/Dialogs/DlgExpressionInput.ui similarity index 100% rename from src/Gui/DlgExpressionInput.ui rename to src/Gui/Dialogs/DlgExpressionInput.ui diff --git a/src/Gui/DlgInputDialog.ui b/src/Gui/Dialogs/DlgInputDialog.ui similarity index 100% rename from src/Gui/DlgInputDialog.ui rename to src/Gui/Dialogs/DlgInputDialog.ui diff --git a/src/Gui/DlgInputDialogImp.cpp b/src/Gui/Dialogs/DlgInputDialogImp.cpp similarity index 95% rename from src/Gui/DlgInputDialogImp.cpp rename to src/Gui/Dialogs/DlgInputDialogImp.cpp index 5f70de8a6c..b386dd0151 100644 --- a/src/Gui/DlgInputDialogImp.cpp +++ b/src/Gui/Dialogs/DlgInputDialogImp.cpp @@ -26,7 +26,7 @@ # include #endif -#include "DlgInputDialogImp.h" +#include "Dialogs/DlgInputDialogImp.h" #include "ui_DlgInputDialog.h" #include "SpinBox.h" diff --git a/src/Gui/DlgInputDialogImp.h b/src/Gui/Dialogs/DlgInputDialogImp.h similarity index 100% rename from src/Gui/DlgInputDialogImp.h rename to src/Gui/Dialogs/DlgInputDialogImp.h diff --git a/src/Gui/DlgKeyboard.ui b/src/Gui/Dialogs/DlgKeyboard.ui similarity index 100% rename from src/Gui/DlgKeyboard.ui rename to src/Gui/Dialogs/DlgKeyboard.ui diff --git a/src/Gui/DlgKeyboardImp.cpp b/src/Gui/Dialogs/DlgKeyboardImp.cpp similarity index 97% rename from src/Gui/DlgKeyboardImp.cpp rename to src/Gui/Dialogs/DlgKeyboardImp.cpp index fe703f5a44..6a90b7950c 100644 --- a/src/Gui/DlgKeyboardImp.cpp +++ b/src/Gui/Dialogs/DlgKeyboardImp.cpp @@ -34,7 +34,7 @@ #include #include -#include "DlgKeyboardImp.h" +#include "Dialogs/DlgKeyboardImp.h" #include "ui_DlgKeyboard.h" #include "Action.h" #include "Application.h" diff --git a/src/Gui/DlgKeyboardImp.h b/src/Gui/Dialogs/DlgKeyboardImp.h similarity index 97% rename from src/Gui/DlgKeyboardImp.h rename to src/Gui/Dialogs/DlgKeyboardImp.h index a52a67282a..1cdc954439 100644 --- a/src/Gui/DlgKeyboardImp.h +++ b/src/Gui/Dialogs/DlgKeyboardImp.h @@ -24,7 +24,7 @@ #ifndef GUI_DIALOG_DLGKEYBOARD_IMP_H #define GUI_DIALOG_DLGKEYBOARD_IMP_H -#include +#include #include #include #include diff --git a/src/Gui/DlgLocationAngle.ui b/src/Gui/Dialogs/DlgLocationAngle.ui similarity index 100% rename from src/Gui/DlgLocationAngle.ui rename to src/Gui/Dialogs/DlgLocationAngle.ui diff --git a/src/Gui/DlgLocationPos.ui b/src/Gui/Dialogs/DlgLocationPos.ui similarity index 100% rename from src/Gui/DlgLocationPos.ui rename to src/Gui/Dialogs/DlgLocationPos.ui diff --git a/src/Gui/DlgMacroExecute.ui b/src/Gui/Dialogs/DlgMacroExecute.ui similarity index 100% rename from src/Gui/DlgMacroExecute.ui rename to src/Gui/Dialogs/DlgMacroExecute.ui diff --git a/src/Gui/DlgMacroExecuteImp.cpp b/src/Gui/Dialogs/DlgMacroExecuteImp.cpp similarity index 93% rename from src/Gui/DlgMacroExecuteImp.cpp rename to src/Gui/Dialogs/DlgMacroExecuteImp.cpp index 24ac9e982d..4822c6df75 100644 --- a/src/Gui/DlgMacroExecuteImp.cpp +++ b/src/Gui/Dialogs/DlgMacroExecuteImp.cpp @@ -34,13 +34,13 @@ #include #include -#include "DlgMacroExecuteImp.h" +#include "Dialogs/DlgMacroExecuteImp.h" #include "ui_DlgMacroExecute.h" #include "Application.h" #include "BitmapFactory.h" #include "Command.h" -#include "DlgCustomizeImp.h" -#include "DlgToolbarsImp.h" +#include "Dialogs/DlgCustomizeImp.h" +#include "Dialogs/DlgToolbarsImp.h" #include "Document.h" #include "EditorView.h" #include "Macro.h" @@ -265,7 +265,7 @@ void DlgMacroExecuteImp::fillUpList() fillUpListForDir(this->macroPath, false); QString dirstr = - QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro"); + QString::fromStdString(App::Application::getHomePath()) + QStringLiteral("Macro"); fillUpListForDir(dirstr, true); auto& config = App::Application::Config(); @@ -432,7 +432,7 @@ void DlgMacroExecuteImp::onEditButtonClicked() auto mitem = static_cast(item); QDir dir(mitem->dirPath); - QString file = QString::fromLatin1("%1/%2").arg(dir.absolutePath(), item->text(0)); + QString file = QStringLiteral("%1/%2").arg(dir.absolutePath(), item->text(0)); auto editor = new PythonEditor(); editor->setWindowIcon(Gui::BitmapFactory().iconFromTheme("applications-python")); auto edit = new PythonEditorView(editor, getMainWindow()); @@ -445,7 +445,7 @@ void DlgMacroExecuteImp::onEditButtonClicked() if (mitem->systemWide) { editor->setReadOnly(true); QString shownName; - shownName = QString::fromLatin1("%1[*] - [%2]").arg(item->text(0), tr("Read-only")); + shownName = QStringLiteral("%1[*] - [%2]").arg(item->text(0), tr("Read-only")); edit->setWindowTitle(shownName); } close(); @@ -505,7 +505,7 @@ void DlgMacroExecuteImp::onCreateButtonClicked() auto edit = new PythonEditorView(editor, getMainWindow()); edit->open(fi.absoluteFilePath()); getMainWindow()->appendRecentMacro(fi.absoluteFilePath()); - edit->setWindowTitle(QString::fromLatin1("%1[*]").arg(fn)); + edit->setWindowTitle(QStringLiteral("%1[*]").arg(fn)); edit->resize(400, 300); getMainWindow()->addWindow(edit); close(); @@ -569,6 +569,7 @@ void DlgMacroExecuteImp::onToolbarButtonClicked() QAbstractButton* doNotShowAgainButton = msgBox.addButton(tr("Do not show again"), QMessageBox::YesRole); msgBox.setText(tr("Guided Walkthrough")); + msgBox.setObjectName(QStringLiteral("macroGuideWalkthrough")); msgBox.setInformativeText(tr("This will guide you in setting up this macro in a custom \ global toolbar. Instructions will be in red text inside the dialog.\n\ \n\ @@ -626,14 +627,14 @@ Note: your changes will be applied when you next switch workbenches\n")); /** title is normally "Customize" **/ dlg.setWindowTitle(tr("Walkthrough, dialog 1 of 2")); - tabWidget = dlg.findChild(QString::fromLatin1("Gui__Dialog__TabWidget")); + tabWidget = dlg.findChild(QStringLiteral("Gui__Dialog__TabWidget")); if (!tabWidget) { std::cerr << "Toolbar walkthrough error: Unable to find tabwidget" << std::endl; return; } auto setupCustomMacrosPage = - tabWidget->findChild(QString::fromLatin1("Gui__Dialog__DlgCustomActions")); + tabWidget->findChild(QStringLiteral("Gui__Dialog__DlgCustomActions")); if (!setupCustomMacrosPage) { std::cerr << "Toolbar walkthrough error: Unable to find setupCustomMacrosPage" << std::endl; @@ -642,7 +643,7 @@ Note: your changes will be applied when you next switch workbenches\n")); tabWidget->setCurrentWidget(setupCustomMacrosPage); auto groupBox7 = - setupCustomMacrosPage->findChild(QString::fromLatin1("GroupBox7")); + setupCustomMacrosPage->findChild(QStringLiteral("GroupBox7")); if (!groupBox7) { Base::Console().Warning("Toolbar walkthrough: Unable to find groupBox7\n"); // just warn when not a fatal error @@ -651,20 +652,20 @@ Note: your changes will be applied when you next switch workbenches\n")); /** normally the groupbox title is "Setup Custom Macros", but we change it here **/ groupBox7->setTitle(tr("Walkthrough instructions: Fill in missing fields (optional) " "then click Add, then Close")); - groupBox7->setStyleSheet(QString::fromLatin1("QGroupBox::title {color:red}")); + groupBox7->setStyleSheet(QStringLiteral("QGroupBox::title {color:red}")); } auto buttonAddAction = - setupCustomMacrosPage->findChild(QString::fromLatin1("buttonAddAction")); + setupCustomMacrosPage->findChild(QStringLiteral("buttonAddAction")); if (!buttonAddAction) { Base::Console().Warning("Toolbar walkthrough: Unable to find buttonAddAction\n"); } else { - buttonAddAction->setStyleSheet(QString::fromLatin1("color:red")); + buttonAddAction->setStyleSheet(QStringLiteral("color:red")); } auto macroListBox = - setupCustomMacrosPage->findChild(QString::fromLatin1("actionMacros")); + setupCustomMacrosPage->findChild(QStringLiteral("actionMacros")); if (!macroListBox) { Base::Console().Warning("Toolbar walkthrough: Unable to find actionMacros combo box\n"); } @@ -675,7 +676,7 @@ Note: your changes will be applied when you next switch workbenches\n")); } auto menuText = - setupCustomMacrosPage->findChild(QString::fromLatin1("actionMenu")); + setupCustomMacrosPage->findChild(QStringLiteral("actionMenu")); if (!menuText) { Base::Console().Warning("Toolbar walkthrough: Unable to find actionMenu menuText\n"); } @@ -693,7 +694,7 @@ Note: your changes will be applied when you next switch workbenches\n")); : tr("Walkthrough, dialog 2 of 2")); tabWidget = nullptr; - tabWidget = dlg.findChild(QString::fromLatin1("Gui__Dialog__TabWidget")); + tabWidget = dlg.findChild(QStringLiteral("Gui__Dialog__TabWidget")); if (!tabWidget) { std::cerr << "Toolbar walkthrough: Unable to find tabWidget Gui__Dialog__TabWidget" << std::endl; @@ -701,7 +702,7 @@ Note: your changes will be applied when you next switch workbenches\n")); } auto setupToolbarPage = tabWidget->findChild( - QString::fromLatin1("Gui__Dialog__DlgCustomToolbars")); + QStringLiteral("Gui__Dialog__DlgCustomToolbars")); if (!setupToolbarPage) { std::cerr << "Toolbar walkthrough: Unable to find setupToolbarPage Gui__Dialog__DlgCustomToolbars" @@ -711,12 +712,12 @@ Note: your changes will be applied when you next switch workbenches\n")); tabWidget->setCurrentWidget(setupToolbarPage); auto moveActionRightButton = - setupToolbarPage->findChild(QString::fromLatin1("moveActionRightButton")); + setupToolbarPage->findChild(QStringLiteral("moveActionRightButton")); if (!moveActionRightButton) { Base::Console().Warning("Toolbar walkthrough: Unable to find moveActionRightButton\n"); } else { - moveActionRightButton->setStyleSheet(QString::fromLatin1("background-color: red")); + moveActionRightButton->setStyleSheet(QStringLiteral("background-color: red")); } /** tailor instructions depending on whether user already has custom toolbar created * if not, they need to click New button to create one first @@ -725,14 +726,14 @@ Note: your changes will be applied when you next switch workbenches\n")); QString instructions2 = tr("Walkthrough instructions: Select macro from list, then click right arrow button (->), then Close."); auto workbenchBox = - setupToolbarPage->findChild(QString::fromLatin1("workbenchBox")); + setupToolbarPage->findChild(QStringLiteral("workbenchBox")); if (!workbenchBox) { Base::Console().Warning("Toolbar walkthrough: Unable to find workbenchBox\n"); } else { /** find the Global workbench and select it for the user **/ - int globalIdx = workbenchBox->findData(QString::fromLatin1("Global")); + int globalIdx = workbenchBox->findData(QStringLiteral("Global")); if (globalIdx != -1) { workbenchBox->setCurrentIndex(globalIdx); setupToolbarPage->activateWorkbenchBox(globalIdx); @@ -743,12 +744,12 @@ Note: your changes will be applied when you next switch workbenches\n")); if (!hasCustomToolbar) { auto newButton = - setupToolbarPage->findChild(QString::fromLatin1("newButton")); + setupToolbarPage->findChild(QStringLiteral("newButton")); if (!newButton) { Base::Console().Warning("Toolbar walkthrough: Unable to find newButton\n"); } else { - newButton->setStyleSheet(QString::fromLatin1("color:red")); + newButton->setStyleSheet(QStringLiteral("color:red")); instructions2 = tr("Walkthrough instructions: Click New, select macro, then right arrow (->) " "button, then Close."); } @@ -757,17 +758,17 @@ Note: your changes will be applied when you next switch workbenches\n")); /** "label" normally says "Note: the changes become active the next time you load the * appropriate workbench" **/ - auto label = setupToolbarPage->findChild(QString::fromLatin1("label")); + auto label = setupToolbarPage->findChild(QStringLiteral("label")); if (!label) { Base::Console().Warning("Toolbar walkthrough: Unable to find label\n"); } else { label->setText(instructions2); - label->setStyleSheet(QString::fromLatin1("color:red")); + label->setStyleSheet(QStringLiteral("color:red")); } /** find Macros category and select it for the user **/ - auto categoryBox = setupToolbarPage->findChild(QString::fromLatin1("categoryBox")); + auto categoryBox = setupToolbarPage->findChild(QStringLiteral("categoryBox")); if (!categoryBox) { Base::Console().Warning("Toolbar walkthrough: Unable to find categoryBox\n"); } @@ -783,7 +784,7 @@ Note: your changes will be applied when you next switch workbenches\n")); /** expand custom toolbar items **/ auto toolbarTreeWidget = - setupToolbarPage->findChild(QString::fromLatin1("toolbarTreeWidget")); + setupToolbarPage->findChild(QStringLiteral("toolbarTreeWidget")); if (!toolbarTreeWidget) { Base::Console().Warning("Toolbar walkthrough: Unable to find toolbarTreeWidget\n"); } @@ -796,7 +797,7 @@ Note: your changes will be applied when you next switch workbenches\n")); **/ QTimer::singleShot(500, [=]() { auto commandTreeWidget = - setupToolbarPage->findChild(QString::fromLatin1("commandTreeWidget")); + setupToolbarPage->findChild(QStringLiteral("commandTreeWidget")); if (!commandTreeWidget) { Base::Console().Warning("Toolbar walkthrough: Unable to find commandTreeWidget\n"); } diff --git a/src/Gui/DlgMacroExecuteImp.h b/src/Gui/Dialogs/DlgMacroExecuteImp.h similarity index 100% rename from src/Gui/DlgMacroExecuteImp.h rename to src/Gui/Dialogs/DlgMacroExecuteImp.h diff --git a/src/Gui/DlgMacroRecord.ui b/src/Gui/Dialogs/DlgMacroRecord.ui similarity index 100% rename from src/Gui/DlgMacroRecord.ui rename to src/Gui/Dialogs/DlgMacroRecord.ui diff --git a/src/Gui/DlgMacroRecordImp.cpp b/src/Gui/Dialogs/DlgMacroRecordImp.cpp similarity index 96% rename from src/Gui/DlgMacroRecordImp.cpp rename to src/Gui/Dialogs/DlgMacroRecordImp.cpp index 9e0f6b3d1b..01ae153a2b 100644 --- a/src/Gui/DlgMacroRecordImp.cpp +++ b/src/Gui/Dialogs/DlgMacroRecordImp.cpp @@ -28,7 +28,7 @@ #include #endif -#include "DlgMacroRecordImp.h" +#include "Dialogs/DlgMacroRecordImp.h" #include "ui_DlgMacroRecord.h" #include "Application.h" #include "FileDialog.h" diff --git a/src/Gui/DlgMacroRecordImp.h b/src/Gui/Dialogs/DlgMacroRecordImp.h similarity index 100% rename from src/Gui/DlgMacroRecordImp.h rename to src/Gui/Dialogs/DlgMacroRecordImp.h diff --git a/src/Gui/DlgMaterialProperties.ui b/src/Gui/Dialogs/DlgMaterialProperties.ui similarity index 100% rename from src/Gui/DlgMaterialProperties.ui rename to src/Gui/Dialogs/DlgMaterialProperties.ui diff --git a/src/Gui/DlgMaterialPropertiesImp.cpp b/src/Gui/Dialogs/DlgMaterialPropertiesImp.cpp similarity index 96% rename from src/Gui/DlgMaterialPropertiesImp.cpp rename to src/Gui/Dialogs/DlgMaterialPropertiesImp.cpp index 77defe6836..a121928968 100644 --- a/src/Gui/DlgMaterialPropertiesImp.cpp +++ b/src/Gui/Dialogs/DlgMaterialPropertiesImp.cpp @@ -24,7 +24,7 @@ #include -#include "DlgMaterialPropertiesImp.h" +#include "Dialogs/DlgMaterialPropertiesImp.h" #include "ui_DlgMaterialProperties.h" #include "ViewProvider.h" diff --git a/src/Gui/DlgMaterialPropertiesImp.h b/src/Gui/Dialogs/DlgMaterialPropertiesImp.h similarity index 100% rename from src/Gui/DlgMaterialPropertiesImp.h rename to src/Gui/Dialogs/DlgMaterialPropertiesImp.h diff --git a/src/Gui/DlgObjectSelection.cpp b/src/Gui/Dialogs/DlgObjectSelection.cpp similarity index 99% rename from src/Gui/DlgObjectSelection.cpp rename to src/Gui/Dialogs/DlgObjectSelection.cpp index 1392ab3b47..89869fc7f8 100644 --- a/src/Gui/DlgObjectSelection.cpp +++ b/src/Gui/Dialogs/DlgObjectSelection.cpp @@ -30,7 +30,7 @@ #include #include -#include "DlgObjectSelection.h" +#include "Dialogs/DlgObjectSelection.h" #include "ui_DlgObjectSelection.h" #include "Application.h" #include "MainWindow.h" diff --git a/src/Gui/DlgObjectSelection.h b/src/Gui/Dialogs/DlgObjectSelection.h similarity index 100% rename from src/Gui/DlgObjectSelection.h rename to src/Gui/Dialogs/DlgObjectSelection.h diff --git a/src/Gui/DlgObjectSelection.ui b/src/Gui/Dialogs/DlgObjectSelection.ui similarity index 100% rename from src/Gui/DlgObjectSelection.ui rename to src/Gui/Dialogs/DlgObjectSelection.ui diff --git a/src/Gui/DlgOnlineHelp.ui b/src/Gui/Dialogs/DlgOnlineHelp.ui similarity index 100% rename from src/Gui/DlgOnlineHelp.ui rename to src/Gui/Dialogs/DlgOnlineHelp.ui diff --git a/src/Gui/DlgOnlineHelpImp.cpp b/src/Gui/Dialogs/DlgOnlineHelpImp.cpp similarity index 92% rename from src/Gui/DlgOnlineHelpImp.cpp rename to src/Gui/Dialogs/DlgOnlineHelpImp.cpp index a16cf2ec1e..94f0808b98 100644 --- a/src/Gui/DlgOnlineHelpImp.cpp +++ b/src/Gui/Dialogs/DlgOnlineHelpImp.cpp @@ -28,7 +28,7 @@ #include -#include "DlgOnlineHelpImp.h" +#include "Dialogs/DlgOnlineHelpImp.h" #include "ui_DlgOnlineHelp.h" @@ -49,7 +49,7 @@ DlgOnlineHelpImp::DlgOnlineHelpImp( QWidget* parent ) { ui->setupUi(this); - ui->prefStartPage->setFilter(QString::fromLatin1("%1 (*.html *.htm)").arg(tr("HTML files"))); + ui->prefStartPage->setFilter(QStringLiteral("%1 (*.html *.htm)").arg(tr("HTML files"))); if (ui->prefStartPage->fileName().isEmpty()) { ui->prefStartPage->setFileName(getStartpage()); } @@ -69,7 +69,7 @@ DlgOnlineHelpImp::~DlgOnlineHelpImp() = default; QString DlgOnlineHelpImp::getStartpage() { QDir docdir = QDir(QString::fromUtf8(App::Application::getHelpDir().c_str())); - return docdir.absoluteFilePath(QString::fromUtf8("Start_Page.html")); + return docdir.absoluteFilePath(QStringLiteral("Start_Page.html")); } void DlgOnlineHelpImp::saveSettings() diff --git a/src/Gui/DlgOnlineHelpImp.h b/src/Gui/Dialogs/DlgOnlineHelpImp.h similarity index 100% rename from src/Gui/DlgOnlineHelpImp.h rename to src/Gui/Dialogs/DlgOnlineHelpImp.h diff --git a/src/Gui/DlgParameter.ui b/src/Gui/Dialogs/DlgParameter.ui similarity index 100% rename from src/Gui/DlgParameter.ui rename to src/Gui/Dialogs/DlgParameter.ui diff --git a/src/Gui/DlgParameterFind.cpp b/src/Gui/Dialogs/DlgParameterFind.cpp similarity index 99% rename from src/Gui/DlgParameterFind.cpp rename to src/Gui/Dialogs/DlgParameterFind.cpp index 9ec5c46dbf..1fb2dcdc8c 100644 --- a/src/Gui/DlgParameterFind.cpp +++ b/src/Gui/Dialogs/DlgParameterFind.cpp @@ -26,9 +26,9 @@ #include #endif -#include "DlgParameterFind.h" +#include "Dialogs/DlgParameterFind.h" #include "ui_DlgParameterFind.h" -#include "DlgParameterImp.h" +#include "Dialogs/DlgParameterImp.h" using namespace Gui::Dialog; diff --git a/src/Gui/DlgParameterFind.h b/src/Gui/Dialogs/DlgParameterFind.h similarity index 100% rename from src/Gui/DlgParameterFind.h rename to src/Gui/Dialogs/DlgParameterFind.h diff --git a/src/Gui/DlgParameterFind.ui b/src/Gui/Dialogs/DlgParameterFind.ui similarity index 100% rename from src/Gui/DlgParameterFind.ui rename to src/Gui/Dialogs/DlgParameterFind.ui diff --git a/src/Gui/DlgParameterImp.cpp b/src/Gui/Dialogs/DlgParameterImp.cpp similarity index 95% rename from src/Gui/DlgParameterImp.cpp rename to src/Gui/Dialogs/DlgParameterImp.cpp index 51cc3e861f..c33cfd1aa2 100644 --- a/src/Gui/DlgParameterImp.cpp +++ b/src/Gui/Dialogs/DlgParameterImp.cpp @@ -36,11 +36,11 @@ #include #include -#include "DlgParameterImp.h" +#include "Dialogs/DlgParameterImp.h" #include "ui_DlgParameter.h" #include "BitmapFactory.h" -#include "DlgParameterFind.h" -#include "DlgInputDialogImp.h" +#include "Dialogs/DlgParameterFind.h" +#include "Dialogs/DlgInputDialogImp.h" #include "FileDialog.h" #include "SpinBox.h" @@ -224,7 +224,7 @@ void DlgParameterImp::onFindGroupTtextChanged(const QString& SearchStr) } else { // Set red background to indicate no matching - QString styleSheet = QString::fromLatin1(" QLineEdit {\n" + QString styleSheet = QStringLiteral(" QLineEdit {\n" " background-color: rgb(221,144,161);\n" " }\n"); ui->findGroupLE->setStyleSheet(styleSheet); @@ -610,7 +610,7 @@ void ParameterGroup::onExportToFile() QString file = FileDialog::getSaveFileName(this, tr("Export parameter to file"), QString(), - QString::fromLatin1("XML (*.FCParam)")); + QStringLiteral("XML (*.FCParam)")); if (!file.isEmpty()) { QTreeWidgetItem* item = currentItem(); if (item && item->isSelected()) { @@ -626,7 +626,7 @@ void ParameterGroup::onImportFromFile() QString file = FileDialog::getOpenFileName(this, tr("Import parameter from file"), QString(), - QString::fromLatin1("XML (*.FCParam)")); + QStringLiteral("XML (*.FCParam)")); if (!file.isEmpty()) { QTreeWidgetItem* item = currentItem(); if (item && item->isSelected()) { @@ -989,7 +989,7 @@ void ParameterValue::onCreateBoolItem() } QStringList list; - list << QString::fromLatin1("true") << QString::fromLatin1("false"); + list << QStringLiteral("true") << QStringLiteral("false"); QString val = QInputDialog::getItem(this, QObject::tr("New boolean item"), QObject::tr("Choose an item:"), @@ -1138,7 +1138,7 @@ ParameterText::ParameterText(QTreeWidget* parent, { setIcon(0, BitmapFactory().iconFromTheme("Param_Text")); setText(0, label); - setText(1, QString::fromLatin1("Text")); + setText(1, QStringLiteral("Text")); setText(2, QString::fromUtf8(value)); } @@ -1187,8 +1187,8 @@ ParameterInt::ParameterInt(QTreeWidget* parent, { setIcon(0, BitmapFactory().iconFromTheme("Param_Int")); setText(0, label); - setText(1, QString::fromLatin1("Integer")); - setText(2, QString::fromLatin1("%1").arg(value)); + setText(1, QStringLiteral("Integer")); + setText(2, QStringLiteral("%1").arg(value)); } ParameterInt::~ParameterInt() = default; @@ -1206,7 +1206,7 @@ void ParameterInt::changeValue() &ok, Qt::MSWindowsFixedSizeDialogHint); if (ok) { - setText(2, QString::fromLatin1("%1").arg(num)); + setText(2, QStringLiteral("%1").arg(num)); _hcGrp->SetInt(text(0).toLatin1(), (long)num); } } @@ -1238,8 +1238,8 @@ ParameterUInt::ParameterUInt(QTreeWidget* parent, { setIcon(0, BitmapFactory().iconFromTheme("Param_UInt")); setText(0, label); - setText(1, QString::fromLatin1("Unsigned")); - setText(2, QString::fromLatin1("%1").arg(value)); + setText(1, QStringLiteral("Unsigned")); + setText(2, QStringLiteral("%1").arg(value)); } ParameterUInt::~ParameterUInt() = default; @@ -1260,7 +1260,7 @@ void ParameterUInt::changeValue() unsigned long num = value.toULong(&ok); if (ok) { - setText(2, QString::fromLatin1("%1").arg(num)); + setText(2, QStringLiteral("%1").arg(num)); _hcGrp->SetUnsigned(text(0).toLatin1(), (unsigned long)num); } } @@ -1293,8 +1293,8 @@ ParameterFloat::ParameterFloat(QTreeWidget* parent, { setIcon(0, BitmapFactory().iconFromTheme("Param_Float")); setText(0, label); - setText(1, QString::fromLatin1("Float")); - setText(2, QString::fromLatin1("%1").arg(value)); + setText(1, QStringLiteral("Float")); + setText(2, QStringLiteral("%1").arg(value)); } ParameterFloat::~ParameterFloat() = default; @@ -1312,7 +1312,7 @@ void ParameterFloat::changeValue() &ok, Qt::MSWindowsFixedSizeDialogHint); if (ok) { - setText(2, QString::fromLatin1("%1").arg(num)); + setText(2, QStringLiteral("%1").arg(num)); _hcGrp->SetFloat(text(0).toLatin1(), num); } } @@ -1344,7 +1344,7 @@ ParameterBool::ParameterBool(QTreeWidget* parent, { setIcon(0, BitmapFactory().iconFromTheme("Param_Bool")); setText(0, label); - setText(1, QString::fromLatin1("Boolean")); + setText(1, QStringLiteral("Boolean")); setText(2, QString::fromLatin1((value ? "true" : "false"))); } @@ -1354,7 +1354,7 @@ void ParameterBool::changeValue() { bool ok; QStringList list; - list << QString::fromLatin1("true") << QString::fromLatin1("false"); + list << QStringLiteral("true") << QStringLiteral("false"); int pos = (text(2) == list[0] ? 0 : 1); QString txt = QInputDialog::getItem(treeWidget(), diff --git a/src/Gui/DlgParameterImp.h b/src/Gui/Dialogs/DlgParameterImp.h similarity index 100% rename from src/Gui/DlgParameterImp.h rename to src/Gui/Dialogs/DlgParameterImp.h diff --git a/src/Gui/DlgPreferencePackManagement.ui b/src/Gui/Dialogs/DlgPreferencePackManagement.ui similarity index 100% rename from src/Gui/DlgPreferencePackManagement.ui rename to src/Gui/Dialogs/DlgPreferencePackManagement.ui diff --git a/src/Gui/DlgPreferencePackManagementImp.cpp b/src/Gui/Dialogs/DlgPreferencePackManagementImp.cpp similarity index 99% rename from src/Gui/DlgPreferencePackManagementImp.cpp rename to src/Gui/Dialogs/DlgPreferencePackManagementImp.cpp index 437f6105ba..e310ce0708 100644 --- a/src/Gui/DlgPreferencePackManagementImp.cpp +++ b/src/Gui/Dialogs/DlgPreferencePackManagementImp.cpp @@ -25,7 +25,7 @@ # include #endif -#include "DlgPreferencePackManagementImp.h" +#include "Dialogs/DlgPreferencePackManagementImp.h" #include "ui_DlgPreferencePackManagement.h" #include "Application.h" #include "Command.h" @@ -33,7 +33,7 @@ using namespace Gui::Dialog; -namespace fs = boost::filesystem; +namespace fs = std::filesystem; /* TRANSLATOR Gui::Dialog::DlgPreferencePackManagementImp */ diff --git a/src/Gui/DlgPreferencePackManagementImp.h b/src/Gui/Dialogs/DlgPreferencePackManagementImp.h similarity index 98% rename from src/Gui/DlgPreferencePackManagementImp.h rename to src/Gui/Dialogs/DlgPreferencePackManagementImp.h index f4a41bdb03..49bd8c7d4d 100644 --- a/src/Gui/DlgPreferencePackManagementImp.h +++ b/src/Gui/Dialogs/DlgPreferencePackManagementImp.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include diff --git a/src/Gui/DlgPreferences.ui b/src/Gui/Dialogs/DlgPreferences.ui similarity index 100% rename from src/Gui/DlgPreferences.ui rename to src/Gui/Dialogs/DlgPreferences.ui diff --git a/src/Gui/DlgPreferencesImp.cpp b/src/Gui/Dialogs/DlgPreferencesImp.cpp similarity index 96% rename from src/Gui/DlgPreferencesImp.cpp rename to src/Gui/Dialogs/DlgPreferencesImp.cpp index c4e2c95eb6..23d968e365 100644 --- a/src/Gui/DlgPreferencesImp.cpp +++ b/src/Gui/Dialogs/DlgPreferencesImp.cpp @@ -47,7 +47,7 @@ #include #include -#include "DlgPreferencesImp.h" +#include "Dialogs/DlgPreferencesImp.h" #include "ui_DlgPreferences.h" #include "BitmapFactory.h" #include "MainWindow.h" diff --git a/src/Gui/DlgPreferencesImp.h b/src/Gui/Dialogs/DlgPreferencesImp.h similarity index 100% rename from src/Gui/DlgPreferencesImp.h rename to src/Gui/Dialogs/DlgPreferencesImp.h diff --git a/src/Gui/DlgProjectInformation.ui b/src/Gui/Dialogs/DlgProjectInformation.ui similarity index 100% rename from src/Gui/DlgProjectInformation.ui rename to src/Gui/Dialogs/DlgProjectInformation.ui diff --git a/src/Gui/DlgProjectInformationImp.cpp b/src/Gui/Dialogs/DlgProjectInformationImp.cpp similarity index 97% rename from src/Gui/DlgProjectInformationImp.cpp rename to src/Gui/Dialogs/DlgProjectInformationImp.cpp index 7505fb2ed4..7909f1612e 100644 --- a/src/Gui/DlgProjectInformationImp.cpp +++ b/src/Gui/Dialogs/DlgProjectInformationImp.cpp @@ -32,7 +32,7 @@ #include #include -#include "DlgProjectInformationImp.h" +#include "Dialogs/DlgProjectInformationImp.h" #include "ui_DlgProjectInformation.h" #include "MainWindow.h" diff --git a/src/Gui/DlgProjectInformationImp.h b/src/Gui/Dialogs/DlgProjectInformationImp.h similarity index 100% rename from src/Gui/DlgProjectInformationImp.h rename to src/Gui/Dialogs/DlgProjectInformationImp.h diff --git a/src/Gui/DlgProjectUtility.cpp b/src/Gui/Dialogs/DlgProjectUtility.cpp similarity index 93% rename from src/Gui/DlgProjectUtility.cpp rename to src/Gui/Dialogs/DlgProjectUtility.cpp index 75de3e8fe1..eb340dbf1d 100644 --- a/src/Gui/DlgProjectUtility.cpp +++ b/src/Gui/Dialogs/DlgProjectUtility.cpp @@ -29,7 +29,7 @@ #include -#include "DlgProjectUtility.h" +#include "Dialogs/DlgProjectUtility.h" #include "ui_DlgProjectUtility.h" #include "Application.h" #include "Command.h" @@ -47,7 +47,7 @@ DlgProjectUtility::DlgProjectUtility(QWidget* parent, Qt::WindowFlags fl) ui->setupUi(this); connect(ui->extractButton, &QPushButton::clicked, this, &DlgProjectUtility::extractButton); connect(ui->createButton, &QPushButton::clicked, this, &DlgProjectUtility::createButton); - ui->extractSource->setFilter(QString::fromLatin1("%1 (*.FCStd)").arg(tr("Project file"))); + ui->extractSource->setFilter(QStringLiteral("%1 (*.FCStd)").arg(tr("Project file"))); } /** @@ -85,7 +85,7 @@ void DlgProjectUtility::createButton() return; } - dest = QDir(dest).absoluteFilePath(QString::fromUtf8("project.fcstd")); + dest = QDir(dest).absoluteFilePath(QStringLiteral("project.fcstd")); bool openFile = ui->checkLoadProject->isChecked(); tryCreateArchive(source, dest, openFile); diff --git a/src/Gui/DlgProjectUtility.h b/src/Gui/Dialogs/DlgProjectUtility.h similarity index 100% rename from src/Gui/DlgProjectUtility.h rename to src/Gui/Dialogs/DlgProjectUtility.h diff --git a/src/Gui/DlgProjectUtility.ui b/src/Gui/Dialogs/DlgProjectUtility.ui similarity index 100% rename from src/Gui/DlgProjectUtility.ui rename to src/Gui/Dialogs/DlgProjectUtility.ui diff --git a/src/Gui/DlgPropertyLink.cpp b/src/Gui/Dialogs/DlgPropertyLink.cpp similarity index 97% rename from src/Gui/DlgPropertyLink.cpp rename to src/Gui/Dialogs/DlgPropertyLink.cpp index 869d541670..0417c688da 100644 --- a/src/Gui/DlgPropertyLink.cpp +++ b/src/Gui/Dialogs/DlgPropertyLink.cpp @@ -36,7 +36,7 @@ #include #include -#include "DlgPropertyLink.h" +#include "Dialogs/DlgPropertyLink.h" #include "ui_DlgPropertyLink.h" #include "Application.h" #include "Document.h" @@ -173,16 +173,16 @@ DlgPropertyLink::formatObject(App::Document* ownerDoc, App::DocumentObject* obj, if (obj->Label.getStrValue() == obj->getNameInDocument()) { return QLatin1String(objName); } - return QString::fromLatin1("%1 (%2)").arg(QLatin1String(objName), + return QStringLiteral("%1 (%2)").arg(QLatin1String(objName), QString::fromUtf8(obj->Label.getValue())); } auto sobj = obj->getSubObject(sub); if (!sobj || sobj->Label.getStrValue() == sobj->getNameInDocument()) { - return QString::fromLatin1("%1.%2").arg(QLatin1String(objName), QString::fromUtf8(sub)); + return QStringLiteral("%1.%2").arg(QLatin1String(objName), QString::fromUtf8(sub)); } - return QString::fromLatin1("%1.%2 (%3)") + return QStringLiteral("%1.%2 (%3)") .arg(QLatin1String(objName), QString::fromUtf8(sub), QString::fromUtf8(sobj->Label.getValue())); @@ -226,7 +226,7 @@ QString DlgPropertyLink::formatLinks(App::Document* ownerDoc, QList 3 ? " ..." : "")); @@ -239,7 +239,7 @@ QString DlgPropertyLink::formatLinks(App::Document* ownerDoc, QList 3 ? " ..." : "")); } @@ -289,15 +289,15 @@ void DlgPropertyLink::init(const App::DocumentObjectT& prop, bool tryFilter) std::vector docs; singleSelect = false; - if (propLink->isDerivedFrom(App::PropertyXLinkSub::getClassTypeId()) - || propLink->isDerivedFrom(App::PropertyLinkSub::getClassTypeId())) { + if (propLink->isDerivedFrom() + || propLink->isDerivedFrom()) { allowSubObject = true; singleParent = true; } - else if (propLink->isDerivedFrom(App::PropertyLink::getClassTypeId())) { + else if (propLink->isDerivedFrom()) { singleSelect = true; } - else if (propLink->isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())) { + else if (propLink->isDerivedFrom()) { allowSubObject = true; } @@ -310,8 +310,8 @@ void DlgPropertyLink::init(const App::DocumentObjectT& prop, bool tryFilter) } bool isLinkList = false; - if (propLink->isDerivedFrom(App::PropertyXLinkList::getClassTypeId()) - || propLink->isDerivedFrom(App::PropertyLinkList::getClassTypeId())) { + if (propLink->isDerivedFrom() + || propLink->isDerivedFrom()) { isLinkList = true; allowSubObject = false; } diff --git a/src/Gui/DlgPropertyLink.h b/src/Gui/Dialogs/DlgPropertyLink.h similarity index 100% rename from src/Gui/DlgPropertyLink.h rename to src/Gui/Dialogs/DlgPropertyLink.h diff --git a/src/Gui/DlgPropertyLink.ui b/src/Gui/Dialogs/DlgPropertyLink.ui similarity index 100% rename from src/Gui/DlgPropertyLink.ui rename to src/Gui/Dialogs/DlgPropertyLink.ui diff --git a/src/Gui/DlgRevertToBackupConfig.ui b/src/Gui/Dialogs/DlgRevertToBackupConfig.ui similarity index 100% rename from src/Gui/DlgRevertToBackupConfig.ui rename to src/Gui/Dialogs/DlgRevertToBackupConfig.ui diff --git a/src/Gui/DlgRevertToBackupConfigImp.cpp b/src/Gui/Dialogs/DlgRevertToBackupConfigImp.cpp similarity index 88% rename from src/Gui/DlgRevertToBackupConfigImp.cpp rename to src/Gui/Dialogs/DlgRevertToBackupConfigImp.cpp index 2910fbea26..5f9df07c99 100644 --- a/src/Gui/DlgRevertToBackupConfigImp.cpp +++ b/src/Gui/Dialogs/DlgRevertToBackupConfigImp.cpp @@ -26,7 +26,7 @@ # include #endif -#include "DlgRevertToBackupConfigImp.h" +#include "Dialogs/DlgRevertToBackupConfigImp.h" #include "ui_DlgRevertToBackupConfig.h" #include "Application.h" #include "PreferencePackManager.h" @@ -34,7 +34,7 @@ using namespace Gui; using namespace Gui::Dialog; -namespace fs = boost::filesystem; +namespace fs = std::filesystem; /* TRANSLATOR Gui::Dialog::DlgRevertToBackupConfigImp */ @@ -71,12 +71,22 @@ void DlgRevertToBackupConfigImp::changeEvent(QEvent *e) } } +// FIXME: Replace with more accurate C++20 solution once its usable: https://stackoverflow.com/a/68593141 +template +static std::time_t to_time_t(TP tp) +{ + using namespace std::chrono; + auto sctp = time_point_cast(tp - TP::clock::now() + + system_clock::now()); + return system_clock::to_time_t(sctp); +} + void DlgRevertToBackupConfigImp::showEvent(QShowEvent* event) { ui->listWidget->clear(); const auto& backups = Application::Instance->prefPackManager()->configBackups(); for (const auto& backup : backups) { - auto modification_date = QDateTime::fromSecsSinceEpoch(fs::last_write_time(backup)); + auto modification_date = QDateTime::fromSecsSinceEpoch(to_time_t(fs::last_write_time(backup))); auto item = new QListWidgetItem(QLocale().toString(modification_date)); item->setData(Qt::UserRole, QString::fromStdString(backup.string())); ui->listWidget->addItem(item); diff --git a/src/Gui/DlgRevertToBackupConfigImp.h b/src/Gui/Dialogs/DlgRevertToBackupConfigImp.h similarity index 100% rename from src/Gui/DlgRevertToBackupConfigImp.h rename to src/Gui/Dialogs/DlgRevertToBackupConfigImp.h diff --git a/src/Gui/DlgRunExternal.cpp b/src/Gui/Dialogs/DlgRunExternal.cpp similarity index 96% rename from src/Gui/DlgRunExternal.cpp rename to src/Gui/Dialogs/DlgRunExternal.cpp index 0bcdfe6bf5..2d82690a20 100644 --- a/src/Gui/DlgRunExternal.cpp +++ b/src/Gui/Dialogs/DlgRunExternal.cpp @@ -25,7 +25,7 @@ #include #endif -#include "DlgRunExternal.h" +#include "Dialogs/DlgRunExternal.h" #include "ui_DlgRunExternal.h" #include "FileDialog.h" diff --git a/src/Gui/DlgRunExternal.h b/src/Gui/Dialogs/DlgRunExternal.h similarity index 100% rename from src/Gui/DlgRunExternal.h rename to src/Gui/Dialogs/DlgRunExternal.h diff --git a/src/Gui/DlgRunExternal.ui b/src/Gui/Dialogs/DlgRunExternal.ui similarity index 100% rename from src/Gui/DlgRunExternal.ui rename to src/Gui/Dialogs/DlgRunExternal.ui diff --git a/src/Gui/DlgSettingsColorGradient.ui b/src/Gui/Dialogs/DlgSettingsColorGradient.ui similarity index 100% rename from src/Gui/DlgSettingsColorGradient.ui rename to src/Gui/Dialogs/DlgSettingsColorGradient.ui diff --git a/src/Gui/DlgSettingsColorGradientImp.cpp b/src/Gui/Dialogs/DlgSettingsColorGradientImp.cpp similarity index 96% rename from src/Gui/DlgSettingsColorGradientImp.cpp rename to src/Gui/Dialogs/DlgSettingsColorGradientImp.cpp index 5979f363f2..23f3a4856e 100644 --- a/src/Gui/DlgSettingsColorGradientImp.cpp +++ b/src/Gui/Dialogs/DlgSettingsColorGradientImp.cpp @@ -31,7 +31,7 @@ #include #endif -#include "DlgSettingsColorGradientImp.h" +#include "Dialogs/DlgSettingsColorGradientImp.h" #include "ui_DlgSettingsColorGradient.h" #include "SpinBox.h" #include "Tools.h" @@ -69,7 +69,7 @@ DlgSettingsColorGradientImp::DlgSettingsColorGradientImp(const App::ColorGradien // assure that the LineEdit is as wide to contain numbers with 4 digits and 6 decimals QFontMetrics fm(ui->floatLineEditMax->font()); ui->floatLineEditMax->setMinimumWidth( - QtTools::horizontalAdvance(fm, QString::fromLatin1("-8000.000000"))); + QtTools::horizontalAdvance(fm, QStringLiteral("-8000.000000"))); setColorModelNames(cg.getColorModelNames()); setProfile(cg.getProfile()); diff --git a/src/Gui/DlgSettingsColorGradientImp.h b/src/Gui/Dialogs/DlgSettingsColorGradientImp.h similarity index 100% rename from src/Gui/DlgSettingsColorGradientImp.h rename to src/Gui/Dialogs/DlgSettingsColorGradientImp.h diff --git a/src/Gui/DlgSettingsImage.ui b/src/Gui/Dialogs/DlgSettingsImage.ui similarity index 100% rename from src/Gui/DlgSettingsImage.ui rename to src/Gui/Dialogs/DlgSettingsImage.ui diff --git a/src/Gui/DlgSettingsImageImp.cpp b/src/Gui/Dialogs/DlgSettingsImageImp.cpp similarity index 96% rename from src/Gui/DlgSettingsImageImp.cpp rename to src/Gui/Dialogs/DlgSettingsImageImp.cpp index 659c34f9b1..85692b9246 100644 --- a/src/Gui/DlgSettingsImageImp.cpp +++ b/src/Gui/Dialogs/DlgSettingsImageImp.cpp @@ -26,7 +26,7 @@ #include #endif -#include "DlgSettingsImageImp.h" +#include "Dialogs/DlgSettingsImageImp.h" #include "ui_DlgSettingsImage.h" diff --git a/src/Gui/DlgSettingsImageImp.h b/src/Gui/Dialogs/DlgSettingsImageImp.h similarity index 100% rename from src/Gui/DlgSettingsImageImp.h rename to src/Gui/Dialogs/DlgSettingsImageImp.h diff --git a/src/Gui/DlgToolbars.ui b/src/Gui/Dialogs/DlgToolbars.ui similarity index 97% rename from src/Gui/DlgToolbars.ui rename to src/Gui/Dialogs/DlgToolbars.ui index 910985b748..0a4700fbc3 100644 --- a/src/Gui/DlgToolbars.ui +++ b/src/Gui/Dialogs/DlgToolbars.ui @@ -113,7 +113,7 @@ - + :/icons/button_right.svg:/icons/button_right.svg @@ -139,7 +139,7 @@ - + :/icons/button_left.svg:/icons/button_left.svg @@ -171,7 +171,7 @@ - + :/icons/button_up.svg:/icons/button_up.svg @@ -197,7 +197,7 @@ - + :/icons/button_down.svg:/icons/button_down.svg @@ -352,7 +352,7 @@ deleteButton - + diff --git a/src/Gui/DlgToolbarsImp.cpp b/src/Gui/Dialogs/DlgToolbarsImp.cpp similarity index 96% rename from src/Gui/DlgToolbarsImp.cpp rename to src/Gui/Dialogs/DlgToolbarsImp.cpp index b317d4c9e8..33edb6d115 100644 --- a/src/Gui/DlgToolbarsImp.cpp +++ b/src/Gui/Dialogs/DlgToolbarsImp.cpp @@ -30,8 +30,8 @@ #include #endif -#include "DlgToolbarsImp.h" -#include "DlgKeyboardImp.h" +#include "Dialogs/DlgToolbarsImp.h" +#include "Dialogs/DlgKeyboardImp.h" #include "ui_DlgToolbars.h" #include "Application.h" #include "BitmapFactory.h" @@ -84,7 +84,7 @@ DlgCustomToolbars::DlgCustomToolbars(DlgCustomToolbars::Type t, QWidget* parent) workbenches.sort(); int index = 1; ui->workbenchBox->addItem(QApplication::windowIcon(), tr("Global")); - ui->workbenchBox->setItemData(0, QVariant(QString::fromLatin1("Global")), Qt::UserRole); + ui->workbenchBox->setItemData(0, QVariant(QStringLiteral("Global")), Qt::UserRole); for (const auto& workbench : workbenches) { QPixmap px = Application::Instance->workbenchIcon(workbench); QString mt = Application::Instance->workbenchMenuText(workbench); @@ -265,7 +265,7 @@ void DlgCustomToolbars::exportCustomToolbars(const QByteArray& workbench) CommandManager& rMgr = Application::Instance->commandManager(); for (int i = 0; i < ui->toolbarTreeWidget->topLevelItemCount(); i++) { QTreeWidgetItem* toplevel = ui->toolbarTreeWidget->topLevelItem(i); - QString groupName = QString::fromLatin1("Custom_%1").arg(i + 1); + QString groupName = QStringLiteral("Custom_%1").arg(i + 1); QByteArray toolbarName = toplevel->text(0).toUtf8(); ParameterGrp::handle hToolGrp = hGrp->GetGroup(groupName.toLatin1()); hToolGrp->SetASCII("Name", toolbarName.constData()); @@ -439,7 +439,7 @@ void DlgCustomToolbars::onNewButtonClicked() { bool ok; QString text = - QString::fromLatin1("Custom%1").arg(ui->toolbarTreeWidget->topLevelItemCount() + 1); + QStringLiteral("Custom%1").arg(ui->toolbarTreeWidget->topLevelItemCount() + 1); text = QInputDialog::getText(this, tr("New toolbar"), tr("Toolbar name:"), @@ -678,7 +678,7 @@ void DlgCustomToolbarsImp::setActionGroup(QAction* action, const QList QMenu* menu = tb->menu(); if (!menu) { tb->setPopupMode(QToolButton::MenuButtonPopup); - tb->setObjectName(QString::fromLatin1("qt_toolbutton_menubutton")); + tb->setObjectName(QStringLiteral("qt_toolbutton_menubutton")); auto menu = new QMenu(tb); menu->addActions(group); tb->setMenu(menu); diff --git a/src/Gui/DlgToolbarsImp.h b/src/Gui/Dialogs/DlgToolbarsImp.h similarity index 100% rename from src/Gui/DlgToolbarsImp.h rename to src/Gui/Dialogs/DlgToolbarsImp.h diff --git a/src/Gui/DlgTreeWidget.ui b/src/Gui/Dialogs/DlgTreeWidget.ui similarity index 100% rename from src/Gui/DlgTreeWidget.ui rename to src/Gui/Dialogs/DlgTreeWidget.ui diff --git a/src/Gui/DlgUndoRedo.cpp b/src/Gui/Dialogs/DlgUndoRedo.cpp similarity index 96% rename from src/Gui/DlgUndoRedo.cpp rename to src/Gui/Dialogs/DlgUndoRedo.cpp index 64190bcc13..439c0a1532 100644 --- a/src/Gui/DlgUndoRedo.cpp +++ b/src/Gui/Dialogs/DlgUndoRedo.cpp @@ -27,7 +27,7 @@ #include #endif -#include "DlgUndoRedo.h" +#include "Dialogs/DlgUndoRedo.h" #include "Application.h" #include "MainWindow.h" #include "MDIView.h" diff --git a/src/Gui/DlgUndoRedo.h b/src/Gui/Dialogs/DlgUndoRedo.h similarity index 100% rename from src/Gui/DlgUndoRedo.h rename to src/Gui/Dialogs/DlgUndoRedo.h diff --git a/src/Gui/DlgUnitsCalculator.ui b/src/Gui/Dialogs/DlgUnitsCalculator.ui similarity index 100% rename from src/Gui/DlgUnitsCalculator.ui rename to src/Gui/Dialogs/DlgUnitsCalculator.ui diff --git a/src/Gui/DlgUnitsCalculatorImp.cpp b/src/Gui/Dialogs/DlgUnitsCalculatorImp.cpp similarity index 94% rename from src/Gui/DlgUnitsCalculatorImp.cpp rename to src/Gui/Dialogs/DlgUnitsCalculatorImp.cpp index c1a0276c72..f63e080e2e 100644 --- a/src/Gui/DlgUnitsCalculatorImp.cpp +++ b/src/Gui/Dialogs/DlgUnitsCalculatorImp.cpp @@ -28,7 +28,7 @@ #include #endif -#include "DlgUnitsCalculatorImp.h" +#include "Dialogs/DlgUnitsCalculatorImp.h" #include "ui_DlgUnitsCalculator.h" #include @@ -51,7 +51,7 @@ DlgUnitsCalculator::DlgUnitsCalculator(QWidget* parent, Qt::WindowFlags fl) ui->setupUi(this); this->setAttribute(Qt::WA_DeleteOnClose); - ui->comboBoxScheme->addItem(QString::fromLatin1("Preference system"), static_cast(-1)); + ui->comboBoxScheme->addItem(QStringLiteral("Preference system"), static_cast(-1)); int num = static_cast(Base::UnitSystem::NumUnitSystemTypes); for (int i = 0; i < num; i++) { QString item = Base::UnitsApi::getDescription(static_cast(i)); @@ -83,8 +83,8 @@ DlgUnitsCalculator::DlgUnitsCalculator(QWidget* parent, Qt::WindowFlags fl) ui->ValueInput->setParamGrpPath(QByteArray("User parameter:BaseApp/History/UnitsCalculator")); // set a default that also illustrates how the dialog works - ui->ValueInput->setText(QString::fromLatin1("1 cm")); - ui->UnitInput->setText(QString::fromLatin1("in")); + ui->ValueInput->setText(QStringLiteral("1 cm")); + ui->UnitInput->setText(QStringLiteral("in")); units << Base::Unit::Acceleration << Base::Unit::AmountOfSubstance << Base::Unit::Angle << Base::Unit::Area << Base::Unit::Density << Base::Unit::CurrentDensity @@ -137,10 +137,10 @@ void DlgUnitsCalculator::valueChanged(const Base::Quantity& quant) // first check the unit, if it is invalid, getTypeString() outputs an empty string // explicitly check for "ee" like in "eeV" because this would trigger an exception in Base::Unit // since it expects then a scientific notation number like "1e3" - if ((ui->UnitInput->text().mid(0, 2) == QString::fromLatin1("ee")) + if ((ui->UnitInput->text().mid(0, 2) == QStringLiteral("ee")) || Base::Unit(ui->UnitInput->text().toStdString()).getTypeString().empty()) { ui->ValueOutput->setText( - QString::fromLatin1("%1 %2").arg(tr("unknown unit:"), ui->UnitInput->text())); + QStringLiteral("%1 %2").arg(tr("unknown unit:"), ui->UnitInput->text())); ui->pushButton_Copy->setEnabled(false); } else { // the unit is valid @@ -167,7 +167,7 @@ void DlgUnitsCalculator::valueChanged(const Base::Quantity& quant) val = QLocale().toString(value, 'f', Base::UnitsApi::getDecimals()); } // create the output string - QString out = QString::fromLatin1("%1 %2").arg(val, ui->UnitInput->text()); + QString out = QStringLiteral("%1 %2").arg(val, ui->UnitInput->text()); ui->ValueOutput->setText(out); ui->pushButton_Copy->setEnabled(true); } @@ -191,7 +191,7 @@ void DlgUnitsCalculator::copy() void DlgUnitsCalculator::returnPressed() { if (ui->pushButton_Copy->isEnabled()) { - ui->textEdit->append(ui->ValueInput->text() + QString::fromLatin1(" = ") + ui->textEdit->append(ui->ValueInput->text() + QStringLiteral(" = ") + ui->ValueOutput->text()); ui->ValueInput->pushToHistory(); } diff --git a/src/Gui/DlgUnitsCalculatorImp.h b/src/Gui/Dialogs/DlgUnitsCalculatorImp.h similarity index 100% rename from src/Gui/DlgUnitsCalculatorImp.h rename to src/Gui/Dialogs/DlgUnitsCalculatorImp.h diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index 00a800cffd..432214d4de 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -695,7 +695,7 @@ void Document::_resetEdit() // the editing object gets deleted inside the above call to // 'finishEditing()', which will trigger our slotDeletedObject(), which // nullifies _editViewProvider. - if (d->_editViewProvider && d->_editViewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + if (d->_editViewProvider && d->_editViewProvider->isDerivedFrom()) { auto vpd = static_cast(d->_editViewProvider); vpd->getDocument()->signalResetEdit(*vpd); } @@ -823,7 +823,7 @@ std::vector Document::getViewProvidersOfType(const Base::Type& ty std::vector Objects; for (std::map::const_iterator it = d->_ViewProviderMap.begin(); it != d->_ViewProviderMap.end(); ++it ) { - if (it->second->getTypeId().isDerivedFrom(typeId)) + if (it->second->isDerivedFrom(typeId)) Objects.push_back(it->second); } return Objects; @@ -993,7 +993,7 @@ void Document::slotDeletedObject(const App::DocumentObject& Obj) handleChildren3D(viewProvider,true); - if (viewProvider && viewProvider->getTypeId().isDerivedFrom + if (viewProvider && viewProvider->isDerivedFrom (ViewProviderDocumentObject::getClassTypeId())) { // go through the views for (vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) { @@ -1034,7 +1034,7 @@ void Document::slotChangedObject(const App::DocumentObject& Obj, const App::Prop if(d->_editingViewer && d->_editingObject && d->_editViewProviderParent - && (Prop.isDerivedFrom(App::PropertyPlacement::getClassTypeId()) + && (Prop.isDerivedFrom() // Issue ID 0004230 : getName() can return null in which case strstr() crashes || (Prop.getName() && strstr(Prop.getName(),"Scale"))) && d->_editObjs.count(&Obj)) @@ -1063,7 +1063,7 @@ void Document::slotChangedObject(const App::DocumentObject& Obj, const App::Prop handleChildren3D(viewProvider); - if (viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) + if (viewProvider->isDerivedFrom()) signalChangedObject(static_cast(*viewProvider), Prop); } @@ -1079,7 +1079,7 @@ void Document::slotChangedObject(const App::DocumentObject& Obj, const App::Prop void Document::slotRelabelObject(const App::DocumentObject& Obj) { ViewProvider* viewProvider = getViewProvider(&Obj); - if (viewProvider && viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + if (viewProvider && viewProvider->isDerivedFrom()) { signalRelabelObject(*(static_cast(viewProvider))); } } @@ -1087,7 +1087,7 @@ void Document::slotRelabelObject(const App::DocumentObject& Obj) void Document::slotTransactionAppend(const App::DocumentObject& obj, App::Transaction* transaction) { ViewProvider* viewProvider = getViewProvider(&obj); - if (viewProvider && viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + if (viewProvider && viewProvider->isDerivedFrom()) { transaction->addObjectDel(viewProvider); } } @@ -1116,7 +1116,7 @@ void Document::slotTransactionRemove(const App::DocumentObject& obj, App::Transa void Document::slotActivatedObject(const App::DocumentObject& Obj) { ViewProvider* viewProvider = getViewProvider(&Obj); - if (viewProvider && viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + if (viewProvider && viewProvider->isDerivedFrom()) { signalActivatedObject(*(static_cast(viewProvider))); } } @@ -1298,7 +1298,7 @@ static bool checkCanonicalPath(const std::map &docs) auto docName = [](App::Document *doc) -> QString { if (doc->Label.getStrValue() == doc->getName()) return QString::fromLatin1(doc->getName()); - return QString::fromLatin1("%1 (%2)").arg(QString::fromUtf8(doc->Label.getValue()), + return QStringLiteral("%1 (%2)").arg(QString::fromUtf8(doc->Label.getValue()), QString::fromLatin1(doc->getName())); }; int count = 0; @@ -1458,7 +1458,7 @@ bool Document::saveAs() } QString fn = FileDialog::getSaveFileName(getMainWindow(), QObject::tr("Save %1 Document").arg(exe), name, - QString::fromLatin1("%1 %2 (*.FCStd)").arg(exe, QObject::tr("Document"))); + QStringLiteral("%1 %2 (*.FCStd)").arg(exe, QObject::tr("Document"))); if (!fn.isEmpty()) { QFileInfo fi; @@ -1544,7 +1544,7 @@ void Document::saveAll() catch (const Base::Exception& e) { QMessageBox::critical(getMainWindow(), QObject::tr("Failed to save document") + - QString::fromLatin1(": %1").arg(QString::fromUtf8(doc->getName())), + QStringLiteral(": %1").arg(QString::fromUtf8(doc->getName())), QString::fromLatin1(e.what())); break; } @@ -1749,7 +1749,7 @@ void Document::slotFinishRestoreDocument(const App::Document& doc) App::DocumentObject* act = doc.getActiveObject(); if (act) { ViewProvider* viewProvider = getViewProvider(act); - if (viewProvider && viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + if (viewProvider && viewProvider->isDerivedFrom()) { signalActivatedObject(*(static_cast(viewProvider))); } } @@ -2029,7 +2029,7 @@ MDIView *Document::createView(const Base::Type& typeId) view3D->getViewer()->removeViewProvider(getViewProvider(obj)); const char* name = getDocument()->Label.getValue(); - QString title = QString::fromLatin1("%1 : %2[*]") + QString title = QStringLiteral("%1 : %2[*]") .arg(QString::fromUtf8(name)).arg(d->_iWinCount++); view3D->setWindowTitle(title); @@ -2260,7 +2260,7 @@ bool Document::canClose (bool checkModify, bool checkLink) getActiveView(), QObject::tr("Document not saved"), QObject::tr("The document%1 could not be saved. Do you want to cancel closing it?") - .arg(docName?(QString::fromUtf8(" ")+QString::fromUtf8(docName)):QString()), + .arg(docName?(QStringLiteral(" ")+QString::fromUtf8(docName)):QString()), QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard); if (ret == QMessageBox::Discard) @@ -2389,7 +2389,7 @@ MDIView* Document::getActiveView() const // hidden page has view but not in the list. By right, the view will // self delete, but not the case for TechDraw, especially during // document restore. - if(windows.contains(*rit) || (*rit)->isDerivedFrom(View3DInventor::getClassTypeId())) + if(windows.contains(*rit) || (*rit)->isDerivedFrom()) return *rit; } return nullptr; @@ -2434,7 +2434,7 @@ MDIView *Document::setActiveView(const ViewProviderDocumentObject* vp, Base::Typ if (!view || (!typeId.isBad() && !view->isDerivedFrom(typeId))) { view = nullptr; for (auto *v : d->baseViews) { - if (v->isDerivedFrom(MDIView::getClassTypeId()) && + if (v->isDerivedFrom() && (typeId.isBad() || v->isDerivedFrom(typeId))) { view = static_cast(v); break; @@ -2593,7 +2593,7 @@ bool Document::checkTransactionID(bool undo, int iSteps) { str << " " << doc->getName() << "\n"; } int ret = QMessageBox::warning(getMainWindow(), undo ? QObject::tr("Undo") : QObject::tr("Redo"), - QString::fromLatin1("%1,\n%2%3").arg( + QStringLiteral("%1,\n%2%3").arg( QObject::tr("There are grouped transactions in the following documents with " "other preceding transactions"), QString::fromStdString(str.str()), diff --git a/src/Gui/DocumentModel.cpp b/src/Gui/DocumentModel.cpp index c8d58d0006..fc04ef65aa 100644 --- a/src/Gui/DocumentModel.cpp +++ b/src/Gui/DocumentModel.cpp @@ -575,15 +575,10 @@ const Document* DocumentModel::getDocument(const QModelIndex& index) const bool DocumentModel::isPropertyLink(const App::Property& prop) const { - if (prop.isDerivedFrom(App::PropertyLink::getClassTypeId())) - return true; - if (prop.isDerivedFrom(App::PropertyLinkSub::getClassTypeId())) - return true; - if (prop.isDerivedFrom(App::PropertyLinkList::getClassTypeId())) - return true; - if (prop.isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())) - return true; - return false; + return prop.isDerivedFrom() + || prop.isDerivedFrom() + || prop.isDerivedFrom() + || prop.isDerivedFrom(); } std::vector diff --git a/src/Gui/DocumentPy.xml b/src/Gui/DocumentPy.xml index da3a79186c..2823a7acc4 100644 --- a/src/Gui/DocumentPy.xml +++ b/src/Gui/DocumentPy.xml @@ -15,106 +15,106 @@
- show(objName) -> None + show(objName) -> None -Show an object. +Show an object. -objName : str +objName : str Name of the `Gui.ViewProvider` to show. - hide(objName) -> None + hide(objName) -> None -Hide an object. +Hide an object. -objName : str +objName : str Name of the `Gui.ViewProvider` to hide. - setPos(objName, matrix) -> None + setPos(objName, matrix) -> None -Set the position of an object. +Set the position of an object. -objName : str - Name of the `Gui.ViewProvider`. +objName : str + Name of the `Gui.ViewProvider`. -matrix : Base.Matrix +matrix : Base.Matrix Transformation to apply on the object. - setEdit(obj, mod=0, subName) -> bool + setEdit(obj, mod=0, subName) -> bool -Set an object in edit mode. +Set an object in edit mode. -obj : str, App.DocumentObject, Gui.ViewPrivider +obj : str, App.DocumentObject, Gui.ViewPrivider Object to set in edit mode. -mod : int +mod : int Edit mode. -subName : str +subName : str Subelement name. Optional. - getInEdit() -> Gui.ViewProviderDocumentObject or None + getInEdit() -> Gui.ViewProviderDocumentObject or None Returns the current object in edit mode or None if there is no such object. - resetEdit() -> None + resetEdit() -> None End the current editing. - addAnnotation(annoName, fileName, modName) -> None + addAnnotation(annoName, fileName, modName) -> None -Add an Inventor object from a file. +Add an Inventor object from a file. -annoName : str +annoName : str Annotation name. -fileName : str +fileName : str File name. -modName : str +modName : str Display mode name. Optional. - update() -> None + update() -> None Update the view representations of all objects. - getObject(objName) -> object or None + getObject(objName) -> object or None -Return the object with the given name. If no one exists, return None. +Return the object with the given name. If no one exists, return None. -ObjName : str +ObjName : str Object name. - activeObject() -> object or None + activeObject() -> object or None The active object of the document. Deprecated, use ActiveObject. - activeView() -> object or None + activeView() -> object or None The active view of the document. Deprecated, use ActiveView. @@ -131,76 +131,76 @@ type : str - mdiViewsOfType(type) -> list of MDIView + mdiViewsOfType(type) -> list of MDIView -Return a list of mdi views of a given type. +Return a list of mdi views of a given type. -type : str +type : str Type name. - save() -> bool + save() -> bool Attempts to save the document - saveAs() -> bool + saveAs() -> bool Attempts to save the document under a new name - sendMsgToViews(msg) -> None + sendMsgToViews(msg) -> None -Send a message to all views of the document. +Send a message to all views of the document. msg : str - mergeProject(fileName) -> None + mergeProject(fileName) -> None -Merges this document with another project file. +Merges this document with another project file. -fileName : str +fileName : str File name. - toggleTreeItem(obj, mod=0, subName) -> None + toggleTreeItem(obj, mod=0, subName) -> None -Change TreeItem of a document object. +Change TreeItem of a document object. obj : App.DocumentObject -mod : int +mod : int Item mode. 0: Toggle, 1: Collapse, 2: Expand, 3: Expand path. -subName : str +subName : str Subelement name. Optional. - scrollToTreeItem(obj) -> None + scrollToTreeItem(obj) -> None -Scroll the tree view to the item of a view object. +Scroll the tree view to the item of a view object. obj : Gui.ViewProviderDocumentObject - toggleInSceneGraph(obj) -> None + toggleInSceneGraph(obj) -> None -Add or remove view object from scene graph of all views depending -on its canAddToSceneGraph(). +Add or remove view object from scene graph of all views depending +on its canAddToSceneGraph(). obj : Gui.ViewProvider @@ -233,7 +233,7 @@ obj : Gui.ViewProvider Current edit mode. Only meaningful when there is a current object in edit. - + diff --git a/src/Gui/DocumentPyImp.cpp b/src/Gui/DocumentPyImp.cpp index ed89f6c7e2..d982541749 100644 --- a/src/Gui/DocumentPyImp.cpp +++ b/src/Gui/DocumentPyImp.cpp @@ -494,7 +494,7 @@ Py::Object DocumentPy::getInEditInfo() const { return Py::None(); return Py::TupleN(Py::Object(vp->getObject()->getPyObject(),true), - Py::String(subname),Py::String(subelement),Py::Int(mode)); + Py::String(subname),Py::String(subelement),Py::Long(mode)); } void DocumentPy::setInEditInfo(Py::Object arg) @@ -509,12 +509,12 @@ void DocumentPy::setInEditInfo(Py::Object arg) pyobj)->getViewProviderDocumentObjectPtr(),subname); } -Py::Int DocumentPy::getEditMode() const +Py::Long DocumentPy::getEditMode() const { int mode = -1; getDocumentPtr()->getInEdit(nullptr,nullptr,&mode); - return Py::Int(mode); + return Py::Long(mode); } Py::Boolean DocumentPy::getTransacting() const diff --git a/src/Gui/DocumentRecovery.cpp b/src/Gui/DocumentRecovery.cpp index c839a42481..e4ae5a94b0 100644 --- a/src/Gui/DocumentRecovery.cpp +++ b/src/Gui/DocumentRecovery.cpp @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include #include @@ -212,7 +212,7 @@ QString DocumentRecovery::createProjectFile(const QString& documentXml) { QString source = documentXml; QFileInfo fi(source); - QString dest = fi.dir().absoluteFilePath(QString::fromLatin1("fc_recovery_file.fcstd")); + QString dest = fi.dir().absoluteFilePath(QStringLiteral("fc_recovery_file.fcstd")); std::stringstream str; str << doctools << "\n"; @@ -412,16 +412,16 @@ DocumentRecoveryPrivate::Info DocumentRecoveryPrivate::getRecoveryInfo(const QFi if (doc_dir.exists(QLatin1String("fc_recovery_file.xml"))) { XmlConfig cfg = readXmlFile(info.xmlFile); - if (cfg.contains(QString::fromLatin1("Label"))) { - info.label = cfg[QString::fromLatin1("Label")]; + if (cfg.contains(QStringLiteral("Label"))) { + info.label = cfg[QStringLiteral("Label")]; } - if (cfg.contains(QString::fromLatin1("FileName"))) { - info.fileName = cfg[QString::fromLatin1("FileName")]; + if (cfg.contains(QStringLiteral("FileName"))) { + info.fileName = cfg[QStringLiteral("FileName")]; } - if (cfg.contains(QString::fromLatin1("Status"))) { - QString status = cfg[QString::fromLatin1("Status")]; + if (cfg.contains(QStringLiteral("Status"))) { + QString status = cfg[QStringLiteral("Status")]; if (status == QLatin1String("Deprecated")) info.status = DocumentRecoveryPrivate::Overage; else if (status == QLatin1String("Success")) @@ -474,9 +474,9 @@ DocumentRecoveryPrivate::XmlConfig DocumentRecoveryPrivate::readXmlFile(const QS file.close(); QVector filter; - filter << QString::fromLatin1("Label"); - filter << QString::fromLatin1("FileName"); - filter << QString::fromLatin1("Status"); + filter << QStringLiteral("Label"); + filter << QStringLiteral("FileName"); + filter << QStringLiteral("Status"); QDomElement child; if (!root.isNull()) { @@ -590,7 +590,7 @@ void DocumentRecoveryFinder::checkDocumentDirs(QDir& tmp, const QList } else { int countDeletedDocs = 0; - QString recovery_files = QString::fromLatin1("fc_recovery_files"); + QString recovery_files = QStringLiteral("fc_recovery_files"); for (QList::const_iterator it = dirs.cbegin(); it != dirs.cend(); ++it) { QDir doc_dir(it->absoluteFilePath()); doc_dir.setFilter(QDir::NoDotAndDotDot|QDir::AllEntries); @@ -646,7 +646,7 @@ bool DocumentRecoveryFinder::showRecoveryDialogIfNeeded() void DocumentRecoveryHandler::checkForPreviousCrashes(const std::function&, const QString&)> & callableFunc) const { QDir tmp = QString::fromUtf8(App::Application::getUserCachePath().c_str()); - tmp.setNameFilters(QStringList() << QString::fromLatin1("*.lock")); + tmp.setNameFilters(QStringList() << QStringLiteral("*.lock")); tmp.setFilter(QDir::Files); QString exeName = QString::fromStdString(App::Application::getExecutableName()); diff --git a/src/Gui/DownloadItem.cpp b/src/Gui/DownloadItem.cpp index 8831de1868..1ef9e9d0ed 100644 --- a/src/Gui/DownloadItem.cpp +++ b/src/Gui/DownloadItem.cpp @@ -45,7 +45,7 @@ #include "DownloadManager.h" #include "FileDialog.h" #include "MainWindow.h" -#include "ui_DlgAuthorization.h" +#include "Dialogs/ui_DlgAuthorization.h" #include "Tools.h" #include diff --git a/src/Gui/EditableDatumLabel.cpp b/src/Gui/EditableDatumLabel.cpp index bca2b209b2..5fa800935e 100644 --- a/src/Gui/EditableDatumLabel.cpp +++ b/src/Gui/EditableDatumLabel.cpp @@ -27,6 +27,7 @@ # include # include # include +# include #endif // _PreComp_ #include @@ -60,13 +61,17 @@ EditableDatumLabel::EditableDatumLabel(View3DInventorViewer* view, , function(Function::Positioning) { // NOLINTBEGIN - root = new SoAnnotation; + root = new SoSwitch; root->ref(); - root->renderCaching = SoSeparator::OFF; + + annotation = new SoAnnotation; + annotation->ref(); + annotation->renderCaching = SoSeparator::OFF; + root->addChild(annotation); transform = new SoTransform(); transform->ref(); - root->addChild(transform); + annotation->addChild(transform); label = new SoDatumLabel(); label->ref(); @@ -82,16 +87,19 @@ EditableDatumLabel::EditableDatumLabel(View3DInventorViewer* view, if (autoDistance) { setLabelRecommendedDistance(); } - root->addChild(label); + annotation->addChild(label); setPlacement(plc); // NOLINTEND + + static_cast(viewer->getSceneGraph())->addChild(root); // NOLINT } EditableDatumLabel::~EditableDatumLabel() { deactivate(); transform->unref(); + annotation->unref(); root->unref(); label->unref(); } @@ -102,7 +110,7 @@ void EditableDatumLabel::activate() return; } - static_cast(viewer->getSceneGraph())->addChild(root); // NOLINT + root->whichChild = 0; //track camera movements to update spinbox position. auto info = new NodeData{ this }; @@ -129,9 +137,7 @@ void EditableDatumLabel::deactivate() cameraSensor = nullptr; } - if (viewer) { - static_cast(viewer->getSceneGraph())->removeChild(root); // NOLINT - } + root->whichChild = SO_SWITCH_NONE; } void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj, bool visibleToMouse) diff --git a/src/Gui/EditableDatumLabel.h b/src/Gui/EditableDatumLabel.h index 80d6bffe06..ea224ff31a 100644 --- a/src/Gui/EditableDatumLabel.h +++ b/src/Gui/EditableDatumLabel.h @@ -34,6 +34,8 @@ class SoNodeSensor; class SoTransform; +class SoAnnotation; +class SoSwitch; namespace Gui { @@ -97,7 +99,8 @@ private: SbVec3f getTextCenterPoint() const; private: - SoSeparator* root; + SoSwitch* root; + SoAnnotation* annotation; SoTransform* transform; QPointer viewer; QuantitySpinBox* spinBox; diff --git a/src/Gui/EditorView.cpp b/src/Gui/EditorView.cpp index 0f7e94fb67..f0ac94567a 100644 --- a/src/Gui/EditorView.cpp +++ b/src/Gui/EditorView.cpp @@ -370,7 +370,7 @@ bool EditorView::saveAs() this, QObject::tr("Save Macro"), QString(), - QString::fromLatin1("%1 (*.FCMacro);;Python (*.py)").arg(tr("FreeCAD macro"))); + QStringLiteral("%1 (*.FCMacro);;Python (*.py)").arg(tr("FreeCAD macro"))); if (fn.isEmpty()) { return false; } @@ -503,7 +503,7 @@ void EditorView::printPdf() FileDialog::getSaveFileName(this, tr("Export PDF"), QString(), - QString::fromLatin1("%1 (*.pdf)").arg(tr("PDF file"))); + QStringLiteral("%1 (*.pdf)").arg(tr("PDF file"))); if (!filename.isEmpty()) { QPrinter printer(QPrinter::ScreenResolution); // setPdfVersion sets the printied PDF Version to comply with PDF/A-1b, more details under: @@ -511,6 +511,7 @@ void EditorView::printPdf() printer.setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName(filename); + printer.setCreator(QString::fromStdString(App::Application::getNameWithVersion())); d->textEdit->document()->print(&printer); } } @@ -540,7 +541,7 @@ void EditorView::setCurrentFileName(const QString& fileName) shownName = tr("untitled[*]"); } else { - shownName = QString::fromLatin1("%1[*]").arg(name); + shownName = QStringLiteral("%1[*]").arg(name); } shownName += tr(" - Editor"); setWindowTitle(shownName); @@ -893,7 +894,7 @@ void SearchBar::findText(bool skip, bool next, const QString& str) QString styleSheet; if (!found) { - styleSheet = QString::fromLatin1(" QLineEdit {\n" + styleSheet = QStringLiteral(" QLineEdit {\n" " background-color: rgb(221,144,161);\n" " }\n"); } diff --git a/src/Gui/ElideCheckBox.cpp b/src/Gui/ElideCheckBox.cpp new file mode 100644 index 0000000000..8ca88b0d2e --- /dev/null +++ b/src/Gui/ElideCheckBox.cpp @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2025 Alfredo Monclus * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +// This custom widget adds the missing ellipsize functionality in QT5 + +#include "PreCompiled.h" + +#include "ElideCheckBox.h" + +namespace Gui { + +const int CheckboxSpacing = 18; + +ElideCheckBox::ElideCheckBox(QWidget *parent) + : QCheckBox(parent) { +} + +void ElideCheckBox::paintEvent(QPaintEvent *event) { + Q_UNUSED(event); + QStyleOptionButton option; + option.initFrom(this); + option.state = (isChecked() ? QStyle::State_On : QStyle::State_Off) | + (isEnabled() ? QStyle::State_Enabled : QStyle::State_ReadOnly); + + QPainter painter(this); + style()->drawControl(QStyle::CE_CheckBox, &option, &painter, this); + + QRect textRect = option.rect; + textRect.setX(textRect.x() + CheckboxSpacing); + + constexpr int padding = 4; + QFontMetrics fm(font()); + QString elidedText = fm.elidedText(text(), Qt::ElideRight, textRect.width() - padding); + + painter.setPen(palette().color(QPalette::WindowText)); + painter.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, elidedText); +} + +QSize ElideCheckBox::sizeHint() const { + QFontMetrics fm(font()); + int width = fm.horizontalAdvance(this->text()) + CheckboxSpacing; + int height = fm.height(); + return {width, height}; +} + +QSize ElideCheckBox::minimumSizeHint() const { + QFontMetrics fm(font()); + QString minimumText = QStringLiteral("A..."); + int width = fm.horizontalAdvance(minimumText) + CheckboxSpacing; + int height = fm.height(); + return {width, height}; +} + +} // namespace Gui + +#include "moc_ElideCheckBox.cpp" // NOLINT diff --git a/src/Gui/ElideCheckBox.h b/src/Gui/ElideCheckBox.h new file mode 100644 index 0000000000..ce93133b53 --- /dev/null +++ b/src/Gui/ElideCheckBox.h @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2025 Alfredo Monclus * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +// This custom widget adds the missing ellipsize functionality in QT5 + +#ifndef ELIDECHECKBOX_H +#define ELIDECHECKBOX_H + +#ifndef _PreComp_ +#include +#include +#include +#include +#endif + +#include + +namespace Gui { + +class GuiExport ElideCheckBox : public QCheckBox { + Q_OBJECT + +public: + explicit ElideCheckBox(QWidget *parent = nullptr); + ~ElideCheckBox() override = default; + +protected: + void paintEvent(QPaintEvent *event) override; + QSize sizeHint() const override; + QSize minimumSizeHint() const override; +}; + +} // namespace Gui + +#endif // ELIDECHECKBOX_H + diff --git a/src/Gui/ElideLabel.cpp b/src/Gui/ElideLabel.cpp new file mode 100644 index 0000000000..10d7294522 --- /dev/null +++ b/src/Gui/ElideLabel.cpp @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2025 Alfredo Monclus * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +// This custom widget adds the missing ellipsize functionality in QT5 + +#include "PreCompiled.h" + +#include "ElideLabel.h" + +namespace Gui { + +ElideLabel::ElideLabel(QWidget *parent) + : QLabel(parent) { +} + +void ElideLabel::paintEvent(QPaintEvent *event) { + Q_UNUSED(event); + QPainter painter(this); + painter.setPen(palette().color(QPalette::WindowText)); + painter.setFont(font()); + + constexpr int padding = 4; + QFontMetrics fm(painter.fontMetrics()); + + int availableWidth = width() - padding * 2; + if (availableWidth < 0) { + return; + } + + QString elidedText = fm.elidedText(text(), Qt::ElideRight, availableWidth); + + QRect textRect = rect().adjusted(padding, 0, -padding, 0); + painter.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, elidedText); +} + +QSize ElideLabel::sizeHint() const { + QFontMetrics fm(font()); + int width = fm.horizontalAdvance(this->text()); + int height = fm.height(); + return {width, height}; +} + +QSize ElideLabel::minimumSizeHint() const { + QFontMetrics fm(font()); + QString minimumText = QStringLiteral("A..."); + int width = fm.horizontalAdvance(minimumText); + int height = fm.height(); + return {width, height}; +} + +} // namespace Gui + +#include "moc_ElideLabel.cpp" // NOLINT diff --git a/src/Gui/ElideLabel.h b/src/Gui/ElideLabel.h new file mode 100644 index 0000000000..7191d52f57 --- /dev/null +++ b/src/Gui/ElideLabel.h @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2025 Alfredo Monclus * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +// This custom widget adds the missing ellipsize functionality in QT5 + +#ifndef ELIDELABEL_H +#define ELIDELABEL_H + +#ifndef _PreComp_ +#include +#include +#include +#endif + +#include + +namespace Gui { + +class GuiExport ElideLabel : public QLabel { + Q_OBJECT + +public: + explicit ElideLabel(QWidget *parent = nullptr); + ~ElideLabel() override = default; + +protected: + void paintEvent(QPaintEvent *event) override; + QSize sizeHint() const override; + QSize minimumSizeHint() const override; +}; + +} // namespace Gui + +#endif // ELIDELABEL_H diff --git a/src/Gui/ExpressionBinding.cpp b/src/Gui/ExpressionBinding.cpp index d6d8972ef8..b5163cb443 100644 --- a/src/Gui/ExpressionBinding.cpp +++ b/src/Gui/ExpressionBinding.cpp @@ -281,7 +281,7 @@ ExpressionWidget::ExpressionWidget() = default; QPixmap ExpressionWidget::getIcon(const char* name, const QSize& size) const { - QString key = QString::fromLatin1("%1_%2x%3") + QString key = QStringLiteral("%1_%2x%3") .arg(QString::fromLatin1(name)) .arg(size.width()) .arg(size.height()); @@ -308,8 +308,8 @@ void ExpressionWidget::makeLabel(QLineEdit* le) iconLabel->setCursor(Qt::ArrowCursor); QPixmap pixmap = getIcon(":/icons/bound-expression-unset.svg", QSize(iconHeight, iconHeight)); iconLabel->setPixmap(pixmap); - iconLabel->setStyleSheet(QString::fromLatin1("QLabel { border: none; padding: 0px; padding-top: %2px; width: %1px; height: %1px }").arg(iconHeight).arg(frameWidth/2)); + iconLabel->setStyleSheet(QStringLiteral("QLabel { border: none; padding: 0px; padding-top: %2px; width: %1px; height: %1px }").arg(iconHeight).arg(frameWidth/2)); iconLabel->hide(); iconLabel->setExpressionText(QString()); - le->setStyleSheet(QString::fromLatin1("QLineEdit { padding-right: %1px } ").arg(iconHeight+frameWidth)); + le->setStyleSheet(QStringLiteral("QLineEdit { padding-right: %1px } ").arg(iconHeight+frameWidth)); } diff --git a/src/Gui/FileDialog.cpp b/src/Gui/FileDialog.cpp index 978f825dd1..353672461a 100644 --- a/src/Gui/FileDialog.cpp +++ b/src/Gui/FileDialog.cpp @@ -118,7 +118,7 @@ QList FileDialog::fetchSidebarUrls() bool FileDialog::hasSuffix(const QString& ext) const { - QRegularExpression rx(QString::fromLatin1("\\*.(%1)\\W").arg(ext), QRegularExpression::CaseInsensitiveOption); + QRegularExpression rx(QStringLiteral("\\*.(%1)\\W").arg(ext), QRegularExpression::CaseInsensitiveOption); QStringList filters = nameFilters(); for (const auto & str : filters) { if (rx.match(str).hasMatch()) { @@ -142,9 +142,9 @@ void FileDialog::accept() // #0001928: do not add a suffix if a file with suffix is entered // #0002209: make sure that the entered suffix is part of one of the filters if (!ext.isEmpty() && (suffix.isEmpty() || !hasSuffix(suffix))) { - file = QString::fromLatin1("%1.%2").arg(file, ext); + file = QStringLiteral("%1.%2").arg(file, ext); // That's the built-in line edit - auto fileNameEdit = this->findChild(QString::fromLatin1("fileNameEdit")); + auto fileNameEdit = this->findChild(QStringLiteral("fileNameEdit")); if (fileNameEdit) fileNameEdit->setText(file); } @@ -514,10 +514,10 @@ void FileOptionsDialog::accept() if (ext.isEmpty()) setDefaultSuffix(suf); else if (ext.toLower() != suf.toLower()) { - fn = QString::fromLatin1("%1.%2").arg(fn, suf); + fn = QStringLiteral("%1.%2").arg(fn, suf); selectFile(fn); // That's the built-in line edit (fixes Debian bug #811200) - auto fileNameEdit = this->findChild(QString::fromLatin1("fileNameEdit")); + auto fileNameEdit = this->findChild(QStringLiteral("fileNameEdit")); if (fileNameEdit) fileNameEdit->setText(fn); } @@ -617,7 +617,7 @@ QIcon FileIconProvider::icon(const QFileInfo & info) const auto urlToThumbnail = [](const QString& filename) { QString hash = QString::fromLatin1(QCryptographicHash::hash(filename.toUtf8(), QCryptographicHash::Md5).toHex()); QString cache = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); - return QString::fromLatin1("%1/thumbnails/normal/%2.png").arg(cache, hash); + return QStringLiteral("%1/thumbnails/normal/%2.png").arg(cache, hash); }; auto iconFromFile = [](const QString& filename) { @@ -627,7 +627,7 @@ QIcon FileIconProvider::icon(const QFileInfo & info) const return icon; } - return QIcon(QString::fromLatin1(":/icons/freecad-doc.png")); + return QIcon(QStringLiteral(":/icons/freecad-doc.png")); }; if (info.suffix().toLower() == QLatin1String("fcstd")) { @@ -637,7 +637,7 @@ QIcon FileIconProvider::icon(const QFileInfo & info) const return iconFromFile(thumb); } else if (info.suffix().toLower().startsWith(QLatin1String("fcstd"))) { - QIcon icon(QString::fromLatin1(":/icons/freecad-doc.png")); + QIcon icon(QStringLiteral(":/icons/freecad-doc.png")); QIcon darkIcon; int w = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); darkIcon.addPixmap(icon.pixmap(w, w, QIcon::Disabled, QIcon::Off), QIcon::Normal, QIcon::Off); @@ -673,7 +673,7 @@ FileChooser::FileChooser ( QWidget * parent ) completer = new QCompleter ( this ); completer->setMaxVisibleItems( 12 ); fs_model = new QFileSystemModel( completer ); - fs_model->setRootPath(QString::fromUtf8("")); + fs_model->setRootPath(QStringLiteral("")); completer->setModel( fs_model ); lineEdit->setCompleter( completer ); @@ -884,7 +884,7 @@ SelectModule::SelectModule (const QString& type, const SelectModule::Dict& types module = module.left(match.capturedStart()); } - button->setText(QString::fromLatin1("%1 (%2)").arg(filter, module)); + button->setText(QStringLiteral("%1 (%2)").arg(filter, module)); button->setObjectName(it.value()); gridLayout1->addWidget(button, index, 0, 1, 1); group->addButton(button, index); @@ -902,7 +902,7 @@ SelectModule::SelectModule (const QString& type, const SelectModule::Dict& types hboxLayout->addItem(spacerItem1); buttonBox = new QDialogButtonBox(this); - buttonBox->setObjectName(QString::fromUtf8("buttonBox")); + buttonBox->setObjectName(QStringLiteral("buttonBox")); buttonBox->setStandardButtons(QDialogButtonBox::Open | QDialogButtonBox::Cancel); buttonBox->button(QDialogButtonBox::Open)->setEnabled(false); diff --git a/src/Gui/FontScaledSVG.cpp b/src/Gui/FontScaledSVG.cpp new file mode 100644 index 0000000000..89c02e3b21 --- /dev/null +++ b/src/Gui/FontScaledSVG.cpp @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2025 Alfredo Monclus * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +// This custom widget scales an svg according to fonts + +#include "PreCompiled.h" + +#include "FontScaledSVG.h" + +namespace Gui { + +FontScaledSVG::FontScaledSVG(QWidget *parent) + : QWidget(parent), m_svgRenderer(new QSvgRenderer(this)) { + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} + +void FontScaledSVG::setSvg(const QString &svgPath) { + if (m_svgRenderer->load(svgPath)) { + updateScaledSize(); + update(); + } +} + +void FontScaledSVG::paintEvent(QPaintEvent *event) { + Q_UNUSED(event); + QPainter painter(this); + + if (m_svgRenderer->isValid()) { + QRect targetRect(0, 0, width(), height()); + m_svgRenderer->render(&painter, targetRect); + } +} + +void FontScaledSVG::resizeEvent(QResizeEvent *event) { + Q_UNUSED(event); + updateScaledSize(); +} + +void FontScaledSVG::updateScaledSize() { + QSize baseSize = m_svgRenderer->defaultSize(); + + QFontMetrics metrics(font()); + qreal spacing = metrics.lineSpacing(); + constexpr int baseFactor = 18; + qreal scalingFactor = spacing / baseFactor; + + QSize targetSize = baseSize * scalingFactor; + setFixedSize(targetSize); +} + +} // namespace Gui + +#include "moc_FontScaledSVG.cpp" // NOLINT diff --git a/src/Gui/FontScaledSVG.h b/src/Gui/FontScaledSVG.h new file mode 100644 index 0000000000..ffdc3e666b --- /dev/null +++ b/src/Gui/FontScaledSVG.h @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2025 Alfredo Monclus * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +// This custom widget scales an svg according to fonts + +#ifndef FONTSCALEDSVG_H +#define FONTSCALEDSVG_H + +#ifndef _PreComp_ +#include +#include +#include +#include +#endif + +#include + +namespace Gui { + +class GuiExport FontScaledSVG : public QWidget { + Q_OBJECT + +public: + explicit FontScaledSVG(QWidget *parent = nullptr); + void setSvg(const QString &svgPath); + +protected: + void paintEvent(QPaintEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + +private: + QSvgRenderer *m_svgRenderer; + + void updateScaledSize(); +}; + +} // namespace Gui + +#endif // FONTSCALEDSVG_H diff --git a/src/Gui/GraphvizView.cpp b/src/Gui/GraphvizView.cpp index fa51ccdf5b..f7acbc3e99 100644 --- a/src/Gui/GraphvizView.cpp +++ b/src/Gui/GraphvizView.cpp @@ -285,15 +285,15 @@ void GraphvizView::updateSvgItem(const App::Document &doc) args << QLatin1String("-Granksep=2") << QLatin1String("-Goutputorder=edgesfirst") << QLatin1String("-Gsplines=ortho") << QLatin1String("-Tsvg"); flatArgs << QLatin1String("-c2 -l2"); - auto dot = QString::fromLatin1("dot"); - auto unflatten = QString::fromLatin1("unflatten"); + auto dot = QStringLiteral("dot"); + auto unflatten = QStringLiteral("unflatten"); auto path = QString::fromUtf8(hGrp->GetASCII("Graphviz").c_str()); bool pathChanged = false; QDir dir; if (!path.isEmpty()) { dir = QDir(path); - dot = dir.filePath(QString::fromLatin1("dot")); - unflatten = dir.filePath(QString::fromLatin1("unflatten")); + dot = dir.filePath(QStringLiteral("dot")); + unflatten = dir.filePath(QStringLiteral("unflatten")); } dotProc->setEnvironment(QProcess::systemEnvironment()); flatProc->setEnvironment(QProcess::systemEnvironment()); @@ -305,7 +305,7 @@ void GraphvizView::updateSvgItem(const App::Document &doc) if (!dotProc->waitForStarted()) { int ret = QMessageBox::warning(Gui::getMainWindow(), tr("Graphviz not found"), - QString::fromLatin1("%1 " + QStringLiteral("%1 " "%2" "

%3

") .arg(tr("Graphviz couldn't be found on your system."), @@ -324,8 +324,8 @@ void GraphvizView::updateSvgItem(const App::Document &doc) } else { dir = QDir(path); - dot = dir.filePath(QString::fromLatin1("dot")); - unflatten = dir.filePath(QString::fromLatin1("unflatten")); + dot = dir.filePath(QStringLiteral("dot")); + unflatten = dir.filePath(QStringLiteral("unflatten")); pathChanged = true; } } @@ -391,7 +391,7 @@ QByteArray GraphvizView::exportGraph(const QString& format) ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Paths"); QProcess dotProc, flatProc; QStringList args, flatArgs; - args << QString::fromLatin1("-T%1").arg(format); + args << QStringLiteral("-T%1").arg(format); flatArgs << QLatin1String("-c2 -l2"); #ifdef FC_OS_LINUX @@ -401,11 +401,11 @@ QByteArray GraphvizView::exportGraph(const QString& format) #endif #ifdef FC_OS_WIN32 - QString exe = QString::fromLatin1("\"%1/dot\"").arg(path); - QString unflatten = QString::fromLatin1("\"%1/unflatten\"").arg(path); + QString exe = QStringLiteral("\"%1/dot\"").arg(path); + QString unflatten = QStringLiteral("\"%1/unflatten\"").arg(path); #else - QString exe = QString::fromLatin1("%1/dot").arg(path); - QString unflatten = QString::fromLatin1("%1/unflatten").arg(path); + QString exe = QStringLiteral("%1/dot").arg(path); + QString unflatten = QStringLiteral("%1/unflatten").arg(path); #endif dotProc.setEnvironment(QProcess::systemEnvironment()); @@ -442,13 +442,13 @@ bool GraphvizView::onMsg(const char* pMsg, const char**) { if (strcmp("Save",pMsg) == 0 || strcmp("SaveAs",pMsg) == 0) { QList< QPair > formatMap; - formatMap << qMakePair(QString::fromLatin1("%1 (*.gv)").arg(tr("Graphviz format")), QString::fromLatin1("gv")); - formatMap << qMakePair(QString::fromLatin1("%1 (*.png)").arg(tr("PNG format")), QString::fromLatin1("png")); - formatMap << qMakePair(QString::fromLatin1("%1 (*.bmp)").arg(tr("Bitmap format")), QString::fromLatin1("bmp")); - formatMap << qMakePair(QString::fromLatin1("%1 (*.gif)").arg(tr("GIF format")), QString::fromLatin1("gif")); - formatMap << qMakePair(QString::fromLatin1("%1 (*.jpg)").arg(tr("JPG format")), QString::fromLatin1("jpg")); - formatMap << qMakePair(QString::fromLatin1("%1 (*.svg)").arg(tr("SVG format")), QString::fromLatin1("svg")); - formatMap << qMakePair(QString::fromLatin1("%1 (*.pdf)").arg(tr("PDF format")), QString::fromLatin1("pdf")); + formatMap << qMakePair(QStringLiteral("%1 (*.gv)").arg(tr("Graphviz format")), QStringLiteral("gv")); + formatMap << qMakePair(QStringLiteral("%1 (*.png)").arg(tr("PNG format")), QStringLiteral("png")); + formatMap << qMakePair(QStringLiteral("%1 (*.bmp)").arg(tr("Bitmap format")), QStringLiteral("bmp")); + formatMap << qMakePair(QStringLiteral("%1 (*.gif)").arg(tr("GIF format")), QStringLiteral("gif")); + formatMap << qMakePair(QStringLiteral("%1 (*.jpg)").arg(tr("JPG format")), QStringLiteral("jpg")); + formatMap << qMakePair(QStringLiteral("%1 (*.svg)").arg(tr("SVG format")), QStringLiteral("svg")); + formatMap << qMakePair(QStringLiteral("%1 (*.pdf)").arg(tr("PDF format")), QStringLiteral("pdf")); QStringList filter; for (const auto & it : std::as_const(formatMap)) { @@ -523,7 +523,7 @@ void GraphvizView::print(QPrinter* printer) QPainter p(printer); QRect rect = printer->pageLayout().paintRectPixels(printer->resolution()); view->scene()->render(&p, rect); - //QByteArray buffer = exportGraph(QString::fromLatin1("svg")); + //QByteArray buffer = exportGraph(QStringLiteral("svg")); //QSvgRenderer svg(buffer); //svg.render(&p, rect); p.end(); @@ -543,7 +543,7 @@ void GraphvizView::print() void GraphvizView::printPdf() { QStringList filter; - filter << QString::fromLatin1("%1 (*.pdf)").arg(tr("PDF format")); + filter << QStringLiteral("%1 (*.pdf)").arg(tr("PDF format")); QString selectedFilter; QString fn = Gui::FileDialog::getSaveFileName(this, tr("Export graph"), QString(), filter.join(QLatin1String(";;")), &selectedFilter); diff --git a/src/Gui/GuiApplicationNativeEventAware.cpp b/src/Gui/GuiApplicationNativeEventAware.cpp index 2383e93a20..42e8ded33c 100644 --- a/src/Gui/GuiApplicationNativeEventAware.cpp +++ b/src/Gui/GuiApplicationNativeEventAware.cpp @@ -59,7 +59,11 @@ Gui::GUIApplicationNativeEventAware::~GUIApplicationNativeEventAware() = default void Gui::GUIApplicationNativeEventAware::initSpaceball(QMainWindow *window) { #if defined(_USE_3DCONNEXION_SDK) || defined(SPNAV_FOUND) - nativeEvent->initSpaceball(window); + ParameterGrp::handle hViewGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/View"); + if (nativeEvent && hViewGrp->GetBool("LegacySpaceMouseDevices", false)) { + nativeEvent->initSpaceball(window); + } #else Q_UNUSED(window); #endif diff --git a/src/Gui/InputField.cpp b/src/Gui/InputField.cpp index 642b16a58a..0d432566a9 100644 --- a/src/Gui/InputField.cpp +++ b/src/Gui/InputField.cpp @@ -88,11 +88,11 @@ InputField::InputField(QWidget * parent) iconLabel->setCursor(Qt::ArrowCursor); QPixmap pixmap = getValidationIcon(":/icons/button_valid.svg", QSize(sizeHint().height(),sizeHint().height())); iconLabel->setPixmap(pixmap); - iconLabel->setStyleSheet(QString::fromLatin1("QLabel { border: none; padding: 0px; }")); + iconLabel->setStyleSheet(QStringLiteral("QLabel { border: none; padding: 0px; }")); iconLabel->hide(); connect(this, &QLineEdit::textChanged, this, &InputField::updateIconLabel); int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - setStyleSheet(QString::fromLatin1("QLineEdit { padding-right: %1px } ").arg(iconLabel->sizeHint().width() + frameWidth + 1)); + setStyleSheet(QStringLiteral("QLineEdit { padding-right: %1px } ").arg(iconLabel->sizeHint().width() + frameWidth + 1)); QSize msz = minimumSizeHint(); setMinimumSize(qMax(msz.width(), iconLabel->sizeHint().height() + frameWidth * 2 + 2), qMax(msz.height(), iconLabel->sizeHint().height() + frameWidth * 2 + 2)); @@ -143,7 +143,7 @@ bool InputField::apply() QPixmap InputField::getValidationIcon(const char* name, const QSize& size) const { - QString key = QString::fromLatin1("%1_%2x%3") + QString key = QStringLiteral("%1_%2x%3") .arg(QString::fromLatin1(name)) .arg(size.width()) .arg(size.height()); @@ -192,7 +192,7 @@ void InputField::contextMenuEvent(QContextMenuEvent *event) { QMenu *editMenu = createStandardContextMenu(); editMenu->setTitle(tr("Edit")); - auto menu = new QMenu(QString::fromLatin1("InputFieldContextmenu")); + auto menu = new QMenu(QStringLiteral("InputFieldContextmenu")); menu->addMenu(editMenu); menu->addSeparator(); @@ -274,7 +274,7 @@ void InputField::newInput(const QString & text) if(!actUnit.isEmpty() && !res.getUnit().isEmpty() && actUnit != res.getUnit()){ QPixmap pixmap = getValidationIcon(":/icons/button_invalid.svg", QSize(sizeHint().height(),sizeHint().height())); iconLabel->setPixmap(pixmap); - Q_EMIT parseError(QString::fromLatin1("Wrong unit")); + Q_EMIT parseError(QStringLiteral("Wrong unit")); validInput = false; return; } @@ -474,7 +474,7 @@ QString InputField::rawText() const std::string unit; double value = actQuantity.getValue(); actQuantity.getUserString(factor, unit); - return QString::fromLatin1("%1 %2").arg(value / factor).arg(QString::fromStdString(unit)); + return QStringLiteral("%1 %2").arg(value / factor).arg(QString::fromStdString(unit)); } /// expects the string in C locale and internally converts it into the OS-specific locale @@ -595,7 +595,7 @@ void InputField::setHistorySize(int i) void InputField::selectNumber() { - QString expr = QString::fromLatin1("^([%1%2]?[0-9\\%3]*)\\%4?([0-9]+(%5[%1%2]?[0-9]+)?)") + QString expr = QStringLiteral("^([%1%2]?[0-9\\%3]*)\\%4?([0-9]+(%5[%1%2]?[0-9]+)?)") .arg(locale().negativeSign()) .arg(locale().positiveSign()) .arg(locale().groupSeparator()) @@ -676,7 +676,7 @@ void InputField::keyPressEvent(QKeyEvent *event) double dFactor; std::string unitStr; actQuantity.getUserString(dFactor, unitStr); - this->setText(QString::fromUtf8("%L1 %2").arg(val).arg(QString::fromStdString(unitStr))); + this->setText(QStringLiteral("%L1 %2").arg(val).arg(QString::fromStdString(unitStr))); event->accept(); } @@ -702,7 +702,7 @@ void InputField::wheelEvent (QWheelEvent * event) std::string unitStr; actQuantity.getUserString(dFactor, unitStr); - this->setText(QString::fromUtf8("%L1 %2").arg(val).arg(QString::fromStdString(unitStr))); + this->setText(QStringLiteral("%L1 %2").arg(val).arg(QString::fromStdString(unitStr))); selectNumber(); event->accept(); } diff --git a/src/Gui/InputVector.cpp b/src/Gui/InputVector.cpp index 9220a23df2..141583b994 100644 --- a/src/Gui/InputVector.cpp +++ b/src/Gui/InputVector.cpp @@ -158,7 +158,7 @@ void LocationWidget::setDirection(const Base::Vector3d& dir) } // add a new item before the very last item - QString display = QString::fromLatin1("(%1,%2,%3)") + QString display = QStringLiteral("(%1,%2,%3)") .arg(dir.x) .arg(dir.y) .arg(dir.z); diff --git a/src/Gui/InputVector.h b/src/Gui/InputVector.h index 89dc54c3fc..17419500c7 100644 --- a/src/Gui/InputVector.h +++ b/src/Gui/InputVector.h @@ -204,7 +204,7 @@ private: } // add a new item before the very last item - QString display = QString::fromLatin1("(%1,%2,%3)") + QString display = QStringLiteral("(%1,%2,%3)") .arg(dir.x) .arg(dir.y) .arg(dir.z); @@ -322,7 +322,7 @@ public: } // add a new item before the very last item - QString display = QString::fromLatin1("(%1,%2,%3)") + QString display = QStringLiteral("(%1,%2,%3)") .arg(dir.x) .arg(dir.y) .arg(dir.z); @@ -503,7 +503,7 @@ public: } // add a new item before the very last item - QString display = QString::fromLatin1("(%1,%2,%3)") + QString display = QStringLiteral("(%1,%2,%3)") .arg(dir.x) .arg(dir.y) .arg(dir.z); diff --git a/src/Gui/Inventor/SoAxisCrossKit.cpp b/src/Gui/Inventor/SoAxisCrossKit.cpp index e894ff1ae2..ec95db0f03 100644 --- a/src/Gui/Inventor/SoAxisCrossKit.cpp +++ b/src/Gui/Inventor/SoAxisCrossKit.cpp @@ -29,6 +29,8 @@ # include # endif +#include + # include # include # include @@ -50,6 +52,9 @@ # include #endif +#include +#include + #include "SoAxisCrossKit.h" #include "SoDevicePixelRatioElement.h" @@ -218,12 +223,28 @@ SoAxisCrossKit::createAxes() set("xAxis.appearance.drawStyle", "lineWidth 1"); set("yAxis.appearance.drawStyle", "lineWidth 1"); set("zAxis.appearance.drawStyle", "lineWidth 1"); - set("xAxis.appearance.material", "diffuseColor 0.5 0.125 0.125"); - set("xHead.appearance.material", "diffuseColor 0.5 0.125 0.125"); - set("yAxis.appearance.material", "diffuseColor 0.125 0.5 0.125"); - set("yHead.appearance.material", "diffuseColor 0.125 0.5 0.125"); - set("zAxis.appearance.material", "diffuseColor 0.125 0.125 0.5"); - set("zHead.appearance.material", "diffuseColor 0.125 0.125 0.5"); + + unsigned long colorLong; + App::Color color; + std::stringstream parameterstring; + + colorLong = Gui::ViewParams::instance()->getAxisXColor(); + color = App::Color(static_cast(colorLong)); + parameterstring << "diffuseColor " << color.r << " " << color.g << " " << color.b; + set("xAxis.appearance.material", parameterstring.str().c_str()); + set("xHead.appearance.material", parameterstring.str().c_str()); + + colorLong = Gui::ViewParams::instance()->getAxisYColor(); + color = App::Color(static_cast(colorLong)); + parameterstring << "diffuseColor " << color.r << " " << color.g << " " << color.b; + set("yAxis.appearance.material", parameterstring.str().c_str()); + set("yHead.appearance.material", parameterstring.str().c_str()); + + colorLong = Gui::ViewParams::instance()->getAxisZColor(); + color = App::Color(static_cast(colorLong)); + parameterstring << "diffuseColor " << color.r << " " << color.g << " " << color.b; + set("zAxis.appearance.material", parameterstring.str().c_str()); + set("zHead.appearance.material", parameterstring.str().c_str()); // Make unpickable set("xAxis.pickStyle", "style UNPICKABLE"); diff --git a/src/Gui/Language/Translator.cpp b/src/Gui/Language/Translator.cpp index cbe8422492..cdfd257a4c 100644 --- a/src/Gui/Language/Translator.cpp +++ b/src/Gui/Language/Translator.cpp @@ -182,7 +182,7 @@ Translator::Translator() auto entries = hGrp->GetASCII("AdditionalLanguageDomainEntries", ""); // The format of the entries is "Language Name 1"="code1";"Language Name 2"="code2";... // Example: "Romanian"="ro";"Polish"="pl"; - QRegularExpression matchingRE(QString::fromUtf8("\"(.*[^\\s]+.*)\"\\s*=\\s*\"([^\\s]+)\";?")); + QRegularExpression matchingRE(QStringLiteral("\"(.*[^\\s]+.*)\"\\s*=\\s*\"([^\\s]+)\";?")); auto matches = matchingRE.globalMatch(QString::fromStdString(entries)); while (matches.hasNext()) { QRegularExpressionMatch match = matches.next(); @@ -223,7 +223,7 @@ TStringMap Translator::supportedLocales() const for (const auto& domainMap : d->mapLanguageTopLevelDomain) { for (const auto& directoryName : std::as_const(d->paths)) { QDir dir(directoryName); - QString filter = QString::fromLatin1("*_%1.qm").arg(QString::fromStdString(domainMap.second)); + QString filter = QStringLiteral("*_%1.qm").arg(QString::fromStdString(domainMap.second)); QStringList fileNames = dir.entryList(QStringList(filter), QDir::Files, QDir::Name); if (!fileNames.isEmpty()) { d->mapSupportedLocales[domainMap.first] = domainMap.second; @@ -309,7 +309,7 @@ void Translator::addPath(const QString& path) void Translator::installQMFiles(const QDir& dir, const char* locale) { - QString filter = QString::fromLatin1("*_%1.qm").arg(QLatin1String(locale)); + QString filter = QStringLiteral("*_%1.qm").arg(QLatin1String(locale)); QStringList fileNames = dir.entryList(QStringList(filter), QDir::Files, QDir::Name); for (const auto &it : fileNames){ bool ok=false; diff --git a/src/Gui/LinkViewPy.xml b/src/Gui/LinkViewPy.xml index 9341090f85..cf00ba3eac 100644 --- a/src/Gui/LinkViewPy.xml +++ b/src/Gui/LinkViewPy.xml @@ -154,7 +154,7 @@ Return a tuple(path,detail) for the coin3D SoPath and SoDetail of the element Set the element size to create an array of linked object - +
diff --git a/src/Gui/LinkViewPyImp.cpp b/src/Gui/LinkViewPyImp.cpp index c7cccdd198..efc738216f 100644 --- a/src/Gui/LinkViewPyImp.cpp +++ b/src/Gui/LinkViewPyImp.cpp @@ -83,7 +83,7 @@ PyObject* LinkViewPy::setMaterial(PyObject *args) { Py_ssize_t pos = 0; std::map materials; while(PyDict_Next(pyObj, &pos, &key, &value)) { - Py::Int idx(key); + Py::Long idx(key); if(value == Py_None) materials[(int)idx] = nullptr; else if(!PyObject_TypeCheck(value,&App::MaterialPy::Type)) { @@ -135,7 +135,7 @@ PyObject* LinkViewPy::setTransform(PyObject *args) { Py_ssize_t pos = 0; std::map mat; while(PyDict_Next(pyObj, &pos, &key, &value)) { - Py::Int idx(key); + Py::Long idx(key); if(!PyObject_TypeCheck(value,&Base::MatrixPy::Type)) { PyErr_SetString(PyExc_TypeError, "exepcting a type of Matrix"); return nullptr; @@ -384,11 +384,11 @@ PyObject* LinkViewPy::getChildren(PyObject *args) { return Py::new_reference_to(ret); } -Py::Int LinkViewPy::getCount() const { - return Py::Int(getLinkViewPtr()->getSize()); +Py::Long LinkViewPy::getCount() const { + return Py::Long(getLinkViewPtr()->getSize()); } -void LinkViewPy::setCount(Py::Int count) { +void LinkViewPy::setCount(Py::Long count) { try { getLinkViewPtr()->setSize((int)count); } catch (const Base::Exception& e) { diff --git a/src/Gui/MDIView.cpp b/src/Gui/MDIView.cpp index 3b3554664f..5568d3a429 100644 --- a/src/Gui/MDIView.cpp +++ b/src/Gui/MDIView.cpp @@ -39,6 +39,7 @@ #include #include +#include #include "MDIView.h" #include "MDIViewPy.h" @@ -168,7 +169,7 @@ void MDIView::onRelabel(Gui::Document *pDoc) } else { cap = QString::fromUtf8(pDoc->getDocument()->Label.getValue()); - cap = QString::fromLatin1("%1[*]").arg(cap); + cap = QStringLiteral("%1[*]").arg(cap); setWindowTitle(cap); } } @@ -257,13 +258,14 @@ void MDIView::print() void MDIView::printPdf() { QString filename = FileDialog::getSaveFileName(this, tr("Export PDF"), QString(), - QString::fromLatin1("%1 (*.pdf)").arg(tr("PDF file"))); + QStringLiteral("%1 (*.pdf)").arg(tr("PDF file"))); if (!filename.isEmpty()) { QPrinter printer(QPrinter::ScreenResolution); // setPdfVersion sets the printied PDF Version to comply with PDF/A-1b, more details under: https://www.kdab.com/creating-pdfa-documents-qt/ printer.setPdfVersion(QPagedPaintDevice::PdfVersion_A1b); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName(filename); + printer.setCreator(QString::fromStdString(App::Application::getNameWithVersion())); print(&printer); } } diff --git a/src/Gui/Macro.cpp b/src/Gui/Macro.cpp index 32549ca763..7428cccbc3 100644 --- a/src/Gui/Macro.cpp +++ b/src/Gui/Macro.cpp @@ -84,7 +84,7 @@ bool MacroFile::commit() str.setCodec("UTF-8"); #endif QStringList import; - import << QString::fromLatin1("import FreeCAD"); + import << QStringLiteral("import FreeCAD"); QStringList body; for (const auto& it : std::as_const(this->macroInProgress)) { @@ -99,14 +99,14 @@ bool MacroFile::commit() } QString header; - header += QString::fromLatin1("# -*- coding: utf-8 -*-\n\n"); - header += QString::fromLatin1("# Macro Begin: "); + header += QStringLiteral("# -*- coding: utf-8 -*-\n\n"); + header += QStringLiteral("# Macro Begin: "); header += this->macroName; - header += QString::fromLatin1(" +++++++++++++++++++++++++++++++++++++++++++++++++\n"); + header += QStringLiteral(" +++++++++++++++++++++++++++++++++++++++++++++++++\n"); - QString footer = QString::fromLatin1("# Macro End: "); + QString footer = QStringLiteral("# Macro End: "); footer += this->macroName; - footer += QString::fromLatin1(" +++++++++++++++++++++++++++++++++++++++++++++++++\n"); + footer += QStringLiteral(" +++++++++++++++++++++++++++++++++++++++++++++++++\n"); // write the data to the text file str << header; @@ -329,7 +329,7 @@ void MacroManager::addToOutput(LineType type, const char* line) void MacroManager::setModule(const char* sModule) { if (macroFile.isOpen() && sModule && *sModule != '\0') { - macroFile.append(QString::fromLatin1("import %1").arg(QString::fromLatin1(sModule))); + macroFile.append(QStringLiteral("import %1").arg(QString::fromLatin1(sModule))); } } diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 6c1b1a7fa6..a315a2209a 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -114,7 +114,7 @@ #include "SpaceballEvent.h" #include "View3DInventor.h" #include "View3DInventorViewer.h" -#include "DlgObjectSelection.h" +#include "Dialogs/DlgObjectSelection.h" #include FC_LOG_LEVEL_INIT("MainWindow",false,true,true) @@ -366,7 +366,7 @@ MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags f) tab->setTabsClosable(true); // The tabs might be very wide tab->setExpanding(false); - tab->setObjectName(QString::fromLatin1("mdiAreaTabBar")); + tab->setObjectName(QStringLiteral("mdiAreaTabBar")); } d->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); d->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -377,7 +377,7 @@ MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags f) d->mdiArea->setBackground(QBrush(QColor(160,160,160))); setCentralWidget(d->mdiArea); - statusBar()->setObjectName(QString::fromLatin1("statusBar")); + statusBar()->setObjectName(QStringLiteral("statusBar")); connect(statusBar(), &QStatusBar::messageChanged, this, &MainWindow::statusMessageChanged); // labels and progressbar @@ -401,24 +401,24 @@ MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags f) if(notificationAreaEnabled) { NotificationArea* notificationArea = new NotificationArea(statusBar()); - notificationArea->setObjectName(QString::fromLatin1("notificationArea")); + notificationArea->setObjectName(QStringLiteral("notificationArea")); notificationArea->setStyleSheet(QStringLiteral("text-align:left;")); statusBar()->addPermanentWidget(notificationArea); } // clears the action label d->actionTimer = new QTimer( this ); - d->actionTimer->setObjectName(QString::fromLatin1("actionTimer")); + d->actionTimer->setObjectName(QStringLiteral("actionTimer")); connect(d->actionTimer, &QTimer::timeout, d->actionLabel, &QLabel::clear); // clear status type d->statusTimer = new QTimer( this ); - d->statusTimer->setObjectName(QString::fromLatin1("statusTimer")); + d->statusTimer->setObjectName(QStringLiteral("statusTimer")); connect(d->statusTimer, &QTimer::timeout, this, &MainWindow::clearStatus); // update gui timer d->activityTimer = new QTimer(this); - d->activityTimer->setObjectName(QString::fromLatin1("activityTimer")); + d->activityTimer->setObjectName(QStringLiteral("activityTimer")); connect(d->activityTimer, &QTimer::timeout, this, &MainWindow::_updateActions); d->activityTimer->setSingleShot(false); d->activityTimer->start(150); @@ -784,6 +784,7 @@ void MainWindow::closeActiveWindow () int MainWindow::confirmSave(const char *docName, QWidget *parent, bool addCheckbox) { QMessageBox box(parent?parent:this); + box.setObjectName(QStringLiteral("confirmSave")); box.setIcon(QMessageBox::Question); box.setWindowFlags(box.windowFlags() | Qt::WindowStaysOnTopHint); box.setWindowTitle(QObject::tr("Unsaved document")); @@ -798,7 +799,7 @@ int MainWindow::confirmSave(const char *docName, QWidget *parent, bool addCheckb box.setDefaultButton(QMessageBox::Save); box.setEscapeButton(QMessageBox::Cancel); - QCheckBox checkBox(QObject::tr("Apply answer to all")); + QCheckBox checkBox(QObject::tr("Apply to all")); ParameterGrp::handle hGrp; if(addCheckbox) { hGrp = App::GetApplication().GetUserParameter(). @@ -1316,16 +1317,16 @@ void MainWindow::onWindowsMenuAboutToShow() QAction* action = actions.at(index); QString text; QString title = child->windowTitle(); - int lastIndex = title.lastIndexOf(QString::fromLatin1("[*]")); + int lastIndex = title.lastIndexOf(QStringLiteral("[*]")); if (lastIndex > 0) { title = title.left(lastIndex); if (child->isWindowModified()) - title = QString::fromLatin1("%1*").arg(title); + title = QStringLiteral("%1*").arg(title); } if (index < 9) - text = QString::fromLatin1("&%1 %2").arg(index+1).arg(title); + text = QStringLiteral("&%1 %2").arg(index+1).arg(title); else - text = QString::fromLatin1("%1 %2").arg(index+1).arg(title); + text = QStringLiteral("%1 %2").arg(index+1).arg(title); action->setText(text); action->setVisible(true); action->setChecked(child == active); @@ -1590,7 +1591,7 @@ void MainWindow::delayedStartup() void MainWindow::appendRecentFile(const QString& filename) { auto recent = this->findChild - (QString::fromLatin1("recentFiles")); + (QStringLiteral("recentFiles")); if (recent) { recent->appendFile(filename); } @@ -1599,7 +1600,7 @@ void MainWindow::appendRecentFile(const QString& filename) void MainWindow::appendRecentMacro(const QString& filename) { auto recent = this->findChild - (QString::fromLatin1("recentMacros")); + (QStringLiteral("recentMacros")); if (recent) { recent->appendFile(filename); } @@ -1766,6 +1767,8 @@ void MainWindow::loadWindowSettings() statusBar()->setVisible(showStatusBar); + setAttribute(Qt::WA_AlwaysShowToolTips); + ToolBarManager::getInstance()->restoreState(); std::clog << "Toolbars restored" << std::endl; @@ -2152,7 +2155,7 @@ void MainWindow::changeEvent(QEvent *e) void MainWindow::clearStatus() { d->currentStatusType = 100; - statusBar()->setStyleSheet(QString::fromLatin1("#statusBar{}")); + statusBar()->setStyleSheet(QStringLiteral("#statusBar{}")); } void MainWindow::statusMessageChanged() { @@ -2211,7 +2214,7 @@ void MainWindow::showStatus(int type, const QString& message) statusBar()->setStyleSheet(d->status->wrn); break; case MainWindow::Pane: - statusBar()->setStyleSheet(QString::fromLatin1("#statusBar{}")); + statusBar()->setStyleSheet(QStringLiteral("#statusBar{}")); break; default: statusBar()->setStyleSheet(d->status->msg); @@ -2303,23 +2306,18 @@ void MainWindow::setWindowTitle(const QString& string) if (showVersion) { // set main window title with FreeCAD Version - auto config = App::Application::Config(); - QString major = QString::fromUtf8(config["BuildVersionMajor"].c_str()); - QString minor = QString::fromUtf8(config["BuildVersionMinor"].c_str()); - QString point = QString::fromUtf8(config["BuildVersionPoint"].c_str()); - QString suffix = QString::fromUtf8(config["BuildVersionSuffix"].c_str()); - title = QString::fromUtf8("%1 %2.%3.%4%5").arg(appname, major, minor, point, suffix); + title = QString::fromStdString(App::Application::getNameWithVersion()); } else { title = appname; } if (SafeMode::SafeModeEnabled()) { - title = QString::fromUtf8("%1 (%2)").arg(title, tr("Safe Mode")); + title = QStringLiteral("%1 (%2)").arg(title, tr("Safe Mode")); } if (!string.isEmpty()) { - title = QString::fromUtf8("[*] %1 - %2").arg(string, title); + title = QStringLiteral("[*] %1 - %2").arg(string, title); } QMainWindow::setWindowTitle(title); @@ -2330,9 +2328,9 @@ void MainWindow::setWindowTitle(const QString& string) StatusBarObserver::StatusBarObserver() : WindowParameter("OutputWindow") { - msg = QString::fromLatin1("#statusBar{color: #000000}"); // black - wrn = QString::fromLatin1("#statusBar{color: #ffaa00}"); // orange - err = QString::fromLatin1("#statusBar{color: #ff0000}"); // red + msg = QStringLiteral("#statusBar{color: #000000}"); // black + wrn = QStringLiteral("#statusBar{color: #ffaa00}"); // orange + err = QStringLiteral("#statusBar{color: #ff0000}"); // red Base::Console().AttachObserver(this); getWindowParameter()->Attach(this); getWindowParameter()->NotifyAll(); @@ -2347,7 +2345,7 @@ void MainWindow::setWindowTitle(const QString& string) void StatusBarObserver::OnChange(Base::Subject & rCaller, const char* sReason) { ParameterGrp& rclGrp = ((ParameterGrp&)rCaller); - auto format = QString::fromLatin1("#statusBar{color: %1}"); + auto format = QStringLiteral("#statusBar{color: %1}"); if (strcmp(sReason, "colorText") == 0) { unsigned long col = rclGrp.GetUnsigned(sReason); this->msg = format.arg(App::Color::fromPackedRGB(col).name()); diff --git a/src/Gui/ManualAlignment.cpp b/src/Gui/ManualAlignment.cpp index 82a6bb0f94..419acfd717 100644 --- a/src/Gui/ManualAlignment.cpp +++ b/src/Gui/ManualAlignment.cpp @@ -51,7 +51,7 @@ #include #include #include -#include +#include #include #include #include @@ -136,7 +136,7 @@ void AlignmentGroup::setRandomColor() float r = /*(float)rand()/(float)RAND_MAX*/0.0f; float g = (float)rand()/(float)RAND_MAX; float b = (float)rand()/(float)RAND_MAX; - if ((*it)->isDerivedFrom(Gui::ViewProviderGeometryObject::getClassTypeId())) { + if ((*it)->isDerivedFrom()) { SoSearchAction searchAction; searchAction.setType(SoMaterial::getClassTypeId()); searchAction.setInterest(SoSearchAction::FIRST); @@ -239,7 +239,7 @@ Base::BoundBox3d AlignmentGroup::getBoundingBox() const Base::BoundBox3d box; std::vector::const_iterator it; for (it = this->_views.begin(); it != this->_views.end(); ++it) { - if ((*it)->isDerivedFrom(Gui::ViewProviderGeometryObject::getClassTypeId())) { + if ((*it)->isDerivedFrom()) { auto geo = (*it)->getObject(); const App::PropertyComplexGeoData* prop = geo->getPropertyOfGeometry(); if (prop) diff --git a/src/Gui/NaviCube.cpp b/src/Gui/NaviCube.cpp index 354cbabf8f..db95032839 100644 --- a/src/Gui/NaviCube.cpp +++ b/src/Gui/NaviCube.cpp @@ -56,6 +56,7 @@ #include "MainWindow.h" #include "View3DInventorViewer.h" #include "View3DInventor.h" +#include "ViewParams.h" using namespace Eigen; @@ -179,6 +180,10 @@ public: float m_InactiveOpacity = 0.5; SbVec2s m_PosOffset = SbVec2s(0,0); + App::Color m_xColor; + App::Color m_yColor; + App::Color m_zColor; + bool m_Prepared = false; static vector m_commands; bool m_Draggable = false; @@ -212,6 +217,7 @@ int NaviCube::getNaviCubeSize() NaviCube::NaviCube(Gui::View3DInventorViewer* viewer) { m_NaviCubeImplementation = new NaviCubeImplementation(viewer); + updateColors(); } NaviCube::~NaviCube() { @@ -828,13 +834,16 @@ void NaviCubeImplementation::drawNaviCube(bool pickMode, float opacity) a, a, a // 0 }; glVertexPointer(3, GL_FLOAT, 0, pointData); - glColor4f(1, 0, 0, opacity); + + glColor4f(m_xColor.r, m_xColor.g, m_xColor.b, opacity); glDrawArrays(GL_LINES, 0, 2); glDrawArrays(GL_POINTS, 0, 2); - glColor4f(0, 1, 0, opacity); + + glColor4f(m_yColor.r, m_yColor.g, m_yColor.b, opacity); glDrawArrays(GL_LINES, 2, 2); glDrawArrays(GL_POINTS, 2, 2); - glColor4f(0, 0, 1, opacity); + + glColor4f(m_zColor.r, m_zColor.g, m_zColor.b, opacity); glDrawArrays(GL_LINES, 4, 2); glDrawArrays(GL_POINTS, 4, 2); } @@ -1167,6 +1176,18 @@ QString NaviCubeImplementation::str(const char* str) { return QString::fromLatin1(str); } +void NaviCube::updateColors() +{ + unsigned long colorLong; + + colorLong = Gui::ViewParams::instance()->getAxisXColor(); + m_NaviCubeImplementation->m_xColor = App::Color(static_cast(colorLong)); + colorLong = Gui::ViewParams::instance()->getAxisYColor(); + m_NaviCubeImplementation->m_yColor = App::Color(static_cast(colorLong)); + colorLong = Gui::ViewParams::instance()->getAxisZColor(); + m_NaviCubeImplementation->m_zColor = App::Color(static_cast(colorLong)); +} + void NaviCube::setNaviCubeCommands(const std::vector& cmd) { NaviCubeImplementation::m_commands = cmd; @@ -1192,7 +1213,7 @@ void NaviCubeDraggableCmd::activated(int iMsg) bool NaviCubeDraggableCmd::isActive() { Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); - if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + if (view && view->isDerivedFrom()) { bool check = _pcAction->isChecked(); auto view = qobject_cast(getMainWindow()->activeWindow()); bool mode = view->getViewer()->getNaviCube()->isDraggable(); diff --git a/src/Gui/NaviCube.h b/src/Gui/NaviCube.h index 8802e192de..f9412011f6 100644 --- a/src/Gui/NaviCube.h +++ b/src/Gui/NaviCube.h @@ -51,6 +51,7 @@ public: void setCorner(Corner); void setOffset(int x, int y); bool isDraggable(); + void updateColors(); void setDraggable(bool draggable); void setSize(int size); void setChamfer(float size); diff --git a/src/Gui/BlenderNavigationStyle.cpp b/src/Gui/Navigation/BlenderNavigationStyle.cpp similarity index 99% rename from src/Gui/BlenderNavigationStyle.cpp rename to src/Gui/Navigation/BlenderNavigationStyle.cpp index 6988b34caa..3bc606585a 100644 --- a/src/Gui/BlenderNavigationStyle.cpp +++ b/src/Gui/Navigation/BlenderNavigationStyle.cpp @@ -27,7 +27,7 @@ # include #endif -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/CADNavigationStyle.cpp b/src/Gui/Navigation/CADNavigationStyle.cpp similarity index 99% rename from src/Gui/CADNavigationStyle.cpp rename to src/Gui/Navigation/CADNavigationStyle.cpp index b5d9dbb632..301d80907e 100644 --- a/src/Gui/CADNavigationStyle.cpp +++ b/src/Gui/Navigation/CADNavigationStyle.cpp @@ -26,7 +26,7 @@ # include #endif -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/GestureNavigationStyle-state-machine-diagram.docx b/src/Gui/Navigation/GestureNavigationStyle-state-machine-diagram.docx similarity index 100% rename from src/Gui/GestureNavigationStyle-state-machine-diagram.docx rename to src/Gui/Navigation/GestureNavigationStyle-state-machine-diagram.docx diff --git a/src/Gui/GestureNavigationStyle.cpp b/src/Gui/Navigation/GestureNavigationStyle.cpp similarity index 100% rename from src/Gui/GestureNavigationStyle.cpp rename to src/Gui/Navigation/GestureNavigationStyle.cpp diff --git a/src/Gui/GestureNavigationStyle.h b/src/Gui/Navigation/GestureNavigationStyle.h similarity index 99% rename from src/Gui/GestureNavigationStyle.h rename to src/Gui/Navigation/GestureNavigationStyle.h index 3b8886799b..a8fa4e6d0a 100644 --- a/src/Gui/GestureNavigationStyle.h +++ b/src/Gui/Navigation/GestureNavigationStyle.h @@ -23,7 +23,7 @@ #ifndef GESTURENAVIGATIONSTYLE2_H #define GESTURENAVIGATIONSTYLE2_H -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include #include diff --git a/src/Gui/InventorNavigationStyle.cpp b/src/Gui/Navigation/InventorNavigationStyle.cpp similarity index 99% rename from src/Gui/InventorNavigationStyle.cpp rename to src/Gui/Navigation/InventorNavigationStyle.cpp index 9acf9f6255..e8bb21d176 100644 --- a/src/Gui/InventorNavigationStyle.cpp +++ b/src/Gui/Navigation/InventorNavigationStyle.cpp @@ -28,7 +28,7 @@ #endif #include "Inventor/SoMouseWheelEvent.h" -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/MayaGestureNavigationStyle.cpp b/src/Gui/Navigation/MayaGestureNavigationStyle.cpp similarity index 99% rename from src/Gui/MayaGestureNavigationStyle.cpp rename to src/Gui/Navigation/MayaGestureNavigationStyle.cpp index 645f1067b9..9d7e31ebf5 100644 --- a/src/Gui/MayaGestureNavigationStyle.cpp +++ b/src/Gui/Navigation/MayaGestureNavigationStyle.cpp @@ -63,7 +63,7 @@ #include -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "SoTouchEvents.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/NavigationAnimation.cpp b/src/Gui/Navigation/NavigationAnimation.cpp similarity index 100% rename from src/Gui/NavigationAnimation.cpp rename to src/Gui/Navigation/NavigationAnimation.cpp diff --git a/src/Gui/NavigationAnimation.h b/src/Gui/Navigation/NavigationAnimation.h similarity index 98% rename from src/Gui/NavigationAnimation.h rename to src/Gui/Navigation/NavigationAnimation.h index 1308a8e95e..d14e8a366a 100644 --- a/src/Gui/NavigationAnimation.h +++ b/src/Gui/Navigation/NavigationAnimation.h @@ -24,7 +24,7 @@ #ifndef GUI_NAVIGATIONANIMATION_H #define GUI_NAVIGATIONANIMATION_H -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include #include #include diff --git a/src/Gui/NavigationAnimator.cpp b/src/Gui/Navigation/NavigationAnimator.cpp similarity index 100% rename from src/Gui/NavigationAnimator.cpp rename to src/Gui/Navigation/NavigationAnimator.cpp diff --git a/src/Gui/NavigationAnimator.h b/src/Gui/Navigation/NavigationAnimator.h similarity index 98% rename from src/Gui/NavigationAnimator.h rename to src/Gui/Navigation/NavigationAnimator.h index 8b206acd71..0d0f6e953f 100644 --- a/src/Gui/NavigationAnimator.h +++ b/src/Gui/Navigation/NavigationAnimator.h @@ -24,7 +24,7 @@ #ifndef GUI_NAVIGATIONANIMATOR_H #define GUI_NAVIGATIONANIMATOR_H -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include #include diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/Navigation/NavigationStyle.cpp similarity index 99% rename from src/Gui/NavigationStyle.cpp rename to src/Gui/Navigation/NavigationStyle.cpp index 9316c1ac8d..32f9939e3c 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/Navigation/NavigationStyle.cpp @@ -42,14 +42,14 @@ #include #include -#include "NavigationStyle.h" -#include "NavigationStylePy.h" +#include "Navigation/NavigationStyle.h" +#include "Navigation/NavigationStylePy.h" #include "Application.h" #include "Inventor/SoMouseWheelEvent.h" #include "MenuManager.h" #include "MouseSelection.h" -#include "NavigationAnimator.h" -#include "NavigationAnimation.h" +#include "Navigation/NavigationAnimator.h" +#include "Navigation/NavigationAnimation.h" #include "View3DInventorViewer.h" using namespace Gui; diff --git a/src/Gui/NavigationStyle.h b/src/Gui/Navigation/NavigationStyle.h similarity index 100% rename from src/Gui/NavigationStyle.h rename to src/Gui/Navigation/NavigationStyle.h diff --git a/src/Gui/NavigationStylePy.xml b/src/Gui/Navigation/NavigationStylePy.xml similarity index 90% rename from src/Gui/NavigationStylePy.xml rename to src/Gui/Navigation/NavigationStylePy.xml index 7506701f88..314eda00ee 100644 --- a/src/Gui/NavigationStylePy.xml +++ b/src/Gui/Navigation/NavigationStylePy.xml @@ -5,7 +5,7 @@ Name="NavigationStylePy" Twin="NavigationStyle" TwinPointer="NavigationStyle" - Include="Gui/NavigationStyle.h" + Include="Gui/Navigation/NavigationStyle.h" Namespace="Gui" FatherInclude="Base/BaseClassPy.h" FatherNamespace="Base"> diff --git a/src/Gui/NavigationStylePyImp.cpp b/src/Gui/Navigation/NavigationStylePyImp.cpp similarity index 94% rename from src/Gui/NavigationStylePyImp.cpp rename to src/Gui/Navigation/NavigationStylePyImp.cpp index df0f1c573c..c8cb1859ac 100644 --- a/src/Gui/NavigationStylePyImp.cpp +++ b/src/Gui/Navigation/NavigationStylePyImp.cpp @@ -22,8 +22,8 @@ #include "PreCompiled.h" // inclusion of the generated files (generated out of NavigationStylePy.xml) -#include "NavigationStylePy.h" -#include "NavigationStylePy.cpp" +#include "Navigation/NavigationStylePy.h" +#include "Navigation/NavigationStylePy.cpp" using namespace Gui; diff --git a/src/Gui/OpenCascadeNavigationStyle.cpp b/src/Gui/Navigation/OpenCascadeNavigationStyle.cpp similarity index 99% rename from src/Gui/OpenCascadeNavigationStyle.cpp rename to src/Gui/Navigation/OpenCascadeNavigationStyle.cpp index ddb6613069..0100f2c7c0 100644 --- a/src/Gui/OpenCascadeNavigationStyle.cpp +++ b/src/Gui/Navigation/OpenCascadeNavigationStyle.cpp @@ -26,7 +26,7 @@ # include #endif -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/OpenSCADNavigationStyle.cpp b/src/Gui/Navigation/OpenSCADNavigationStyle.cpp similarity index 99% rename from src/Gui/OpenSCADNavigationStyle.cpp rename to src/Gui/Navigation/OpenSCADNavigationStyle.cpp index 263e8f0f85..3603df95a6 100644 --- a/src/Gui/OpenSCADNavigationStyle.cpp +++ b/src/Gui/Navigation/OpenSCADNavigationStyle.cpp @@ -26,7 +26,7 @@ # include #endif -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/RevitNavigationStyle.cpp b/src/Gui/Navigation/RevitNavigationStyle.cpp similarity index 99% rename from src/Gui/RevitNavigationStyle.cpp rename to src/Gui/Navigation/RevitNavigationStyle.cpp index af4e9b114e..7efc1bf436 100644 --- a/src/Gui/RevitNavigationStyle.cpp +++ b/src/Gui/Navigation/RevitNavigationStyle.cpp @@ -26,7 +26,7 @@ # include #endif -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/TinkerCADNavigationStyle.cpp b/src/Gui/Navigation/TinkerCADNavigationStyle.cpp similarity index 99% rename from src/Gui/TinkerCADNavigationStyle.cpp rename to src/Gui/Navigation/TinkerCADNavigationStyle.cpp index e7ca54f6c0..2935e2037f 100644 --- a/src/Gui/TinkerCADNavigationStyle.cpp +++ b/src/Gui/Navigation/TinkerCADNavigationStyle.cpp @@ -26,7 +26,7 @@ # include #endif -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/Navigation/TouchpadNavigationStyle.cpp similarity index 99% rename from src/Gui/TouchpadNavigationStyle.cpp rename to src/Gui/Navigation/TouchpadNavigationStyle.cpp index 6efa6dc9a3..9300b4619e 100644 --- a/src/Gui/TouchpadNavigationStyle.cpp +++ b/src/Gui/Navigation/TouchpadNavigationStyle.cpp @@ -25,7 +25,7 @@ # include #endif -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "View3DInventorViewer.h" diff --git a/src/Gui/NetworkRetriever.cpp b/src/Gui/NetworkRetriever.cpp index 8b71ff0951..989f1856fd 100644 --- a/src/Gui/NetworkRetriever.cpp +++ b/src/Gui/NetworkRetriever.cpp @@ -39,7 +39,7 @@ #include "BitmapFactory.h" #include "FileDialog.h" #include "MainWindow.h" -#include "ui_DlgAuthorization.h" +#include "Dialogs/ui_DlgAuthorization.h" using namespace Gui; @@ -241,15 +241,15 @@ bool NetworkRetriever::startDownload( const QString& startUrl ) if ( !d->proxy.isEmpty() ) { QStringList env = wget->environment(); - env << QString::fromLatin1("http_proxy=%1").arg(d->proxy); - env << QString::fromLatin1("ftp_proxy=%1").arg(d->proxy); + env << QStringLiteral("http_proxy=%1").arg(d->proxy); + env << QStringLiteral("ftp_proxy=%1").arg(d->proxy); wget->setEnvironment(env); } else { QStringList env = wget->environment(); - env.removeAll(QString::fromLatin1("http_proxy=%1").arg(d->proxy)); - env.removeAll(QString::fromLatin1("ftp_proxy=%1").arg(d->proxy)); + env.removeAll(QStringLiteral("http_proxy=%1").arg(d->proxy)); + env.removeAll(QStringLiteral("ftp_proxy=%1").arg(d->proxy)); wget->setEnvironment(env); } @@ -278,43 +278,43 @@ bool NetworkRetriever::startDownload( const QString& startUrl ) { if ( !d->user.isEmpty() ) { - wgetArguments << QString::fromLatin1("--proxy-user=%1").arg( d->user ); + wgetArguments << QStringLiteral("--proxy-user=%1").arg( d->user ); if ( !d->passwd.isEmpty() ) { - wgetArguments << QString::fromLatin1("--proxy-passwd=%1").arg( d->passwd ); + wgetArguments << QStringLiteral("--proxy-passwd=%1").arg( d->passwd ); } } } // output file if ( !d->outputFile.isEmpty() ) - wgetArguments << QString::fromLatin1("--output-document=%1").arg( d->outputFile ); + wgetArguments << QStringLiteral("--output-document=%1").arg( d->outputFile ); // timestamping enabled -> update newer files only if ( d->timeStamp ) - wgetArguments << QString::fromLatin1("-N"); + wgetArguments << QStringLiteral("-N"); // get all needed image files if ( d->img ) - wgetArguments << QString::fromLatin1("-p"); + wgetArguments << QStringLiteral("-p"); // follow relative links only if ( d->folRel ) - wgetArguments<< QString::fromLatin1("-L"); + wgetArguments<< QStringLiteral("-L"); if ( d->recurse ) { - wgetArguments << QString::fromLatin1("-r"); - wgetArguments << QString::fromLatin1("--level=%1").arg( d->level ); + wgetArguments << QStringLiteral("-r"); + wgetArguments << QStringLiteral("--level=%1").arg( d->level ); } if ( d->nop ) - wgetArguments << QString::fromLatin1("-np"); + wgetArguments << QStringLiteral("-np"); // convert absolute links in to relative if ( d->convert ) - wgetArguments << QString::fromLatin1("-k"); + wgetArguments << QStringLiteral("-k"); // number of tries - wgetArguments << QString::fromLatin1("--tries=%1").arg( d->tries ); + wgetArguments << QStringLiteral("--tries=%1").arg( d->tries ); // use HTML file extension if ( d->html ) - wgetArguments << QString::fromLatin1("-E"); + wgetArguments << QStringLiteral("-E"); // start URL wgetArguments << startUrl; @@ -327,10 +327,10 @@ bool NetworkRetriever::startDownload( const QString& startUrl ) QDir::setCurrent(d->dir); } - wget->start(QString::fromLatin1("wget"), wgetArguments); + wget->start(QStringLiteral("wget"), wgetArguments); QDir::setCurrent( cwd ); #else - wget->start(QString::fromLatin1("wget"), wgetArguments); + wget->start(QStringLiteral("wget"), wgetArguments); #endif return wget->state() == QProcess::Running; @@ -374,7 +374,7 @@ void NetworkRetriever::wgetFinished(int exitCode, QProcess::ExitStatus status) bool NetworkRetriever::testWget() { QProcess proc; - proc.setProgram(QString::fromLatin1("wget")); + proc.setProgram(QStringLiteral("wget")); proc.start(); bool ok = proc.state() == QProcess::Running; proc.kill(); @@ -484,7 +484,7 @@ void StdCmdDownloadOnlineHelp::activated(int iMsg) // set output directory QString path = QString::fromStdString(App::Application::getHomePath()); - path += QString::fromLatin1("/doc/"); + path += QStringLiteral("/doc/"); ParameterGrp::handle hURLGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/OnlineHelp"); path = QString::fromUtf8(hURLGrp->GetASCII( "DownloadLocation", path.toLatin1() ).c_str()); diff --git a/src/Gui/NotificationArea.cpp b/src/Gui/NotificationArea.cpp index edade8d749..0925013a70 100644 --- a/src/Gui/NotificationArea.cpp +++ b/src/Gui/NotificationArea.cpp @@ -1134,7 +1134,7 @@ void NotificationArea::showInNotificationArea() // We update the message with the most recent up to maxOpenNotifications QString msgw = - QString::fromLatin1( + QStringLiteral( " \

\ \ @@ -1149,7 +1149,7 @@ void NotificationArea::showInNotificationArea() if (currentlynotifying > pImp->maxOpenNotifications) { msgw += - QString::fromLatin1( + QStringLiteral( " \ \ \ @@ -1187,7 +1187,7 @@ void NotificationArea::showInNotificationArea() convertFromPlainText(item->getMessage(), Qt::WhiteSpaceMode::WhiteSpaceNormal); msgw += - QString::fromLatin1( + QStringLiteral( " \ \ \ @@ -1233,7 +1233,7 @@ void NotificationArea::showInNotificationArea() i++; } - msgw += QString::fromLatin1("

"); + msgw += QStringLiteral("

"); NotificationBox::Options options = NotificationBox::Options::RestrictAreaToReference; diff --git a/src/Gui/OnlineDocumentation.cpp b/src/Gui/OnlineDocumentation.cpp index 9c101ac1f0..e35486ebf3 100644 --- a/src/Gui/OnlineDocumentation.cpp +++ b/src/Gui/OnlineDocumentation.cpp @@ -169,7 +169,7 @@ QByteArray PythonOnlineHelp::loadHelpPage(const QString& filename) const QByteArray PythonOnlineHelp::fileNotFound() const { const int pageNotFound = 404; - QString contentType = QString::fromLatin1( + QString contentType = QStringLiteral( "text/html\r\n" "\r\n" "Error" @@ -189,11 +189,11 @@ QByteArray PythonOnlineHelp::fileNotFound() const "" "\r\n"); - QString header = QString::fromLatin1("content-type: %1\r\n").arg(contentType); + QString header = QStringLiteral("content-type: %1\r\n").arg(contentType); QString http(QLatin1String("HTTP/1.1 %1 %2\r\n%3\r\n")); QString httpResponseHeader = - http.arg(pageNotFound).arg(QString::fromLatin1("File not found"), header); + http.arg(pageNotFound).arg(QStringLiteral("File not found"), header); QByteArray res = httpResponseHeader.toLatin1(); return res; @@ -203,7 +203,7 @@ QByteArray PythonOnlineHelp::loadFailed(const QString& error) const { const int pageNotFound = 404; QString contentType = - QString::fromLatin1( + QStringLiteral( "text/html\r\n" "\r\n" "Error" @@ -222,11 +222,11 @@ QByteArray PythonOnlineHelp::loadFailed(const QString& error) const "\r\n") .arg(error); - QString header = QString::fromLatin1("content-type: %1\r\n").arg(contentType); + QString header = QStringLiteral("content-type: %1\r\n").arg(contentType); QString http(QLatin1String("HTTP/1.1 %1 %2\r\n%3\r\n")); QString httpResponseHeader = - http.arg(pageNotFound).arg(QString::fromLatin1("File not found"), header); + http.arg(pageNotFound).arg(QStringLiteral("File not found"), header); QByteArray res = httpResponseHeader.toLatin1(); return res; diff --git a/src/Gui/Placement.cpp b/src/Gui/Placement.cpp index 307727c363..5e63bb3558 100644 --- a/src/Gui/Placement.cpp +++ b/src/Gui/Placement.cpp @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include @@ -338,7 +338,7 @@ void PlacementHandler::applyPlacement(const App::DocumentObject* obj, const QStr QString PlacementHandler::getIncrementalPlacement(const App::DocumentObject* obj, const QString& data) const { - return QString::fromLatin1( + return QStringLiteral( R"(App.getDocument("%1").%2.%3=%4.multiply(App.getDocument("%1").%2.%3))") .arg(QString::fromLatin1(obj->getDocument()->getName()), QString::fromLatin1(obj->getNameInDocument()), @@ -348,7 +348,7 @@ QString PlacementHandler::getIncrementalPlacement(const App::DocumentObject* obj QString PlacementHandler::getSimplePlacement(const App::DocumentObject* obj, const QString& data) const { - return QString::fromLatin1( + return QStringLiteral( "App.getDocument(\"%1\").%2.%3=%4") .arg(QString::fromLatin1(obj->getDocument()->getName()), QString::fromLatin1(obj->getNameInDocument()), @@ -1036,7 +1036,7 @@ QString Placement::getPlacementFromEulerAngles() const Base::Vector3d pos = getPositionData(); Base::Vector3d ypr = getAnglesData(); Base::Vector3d cnt = getCenterData(); - return QString::fromLatin1( + return QStringLiteral( "App.Placement(App.Vector(%1,%2,%3), App.Rotation(%4,%5,%6), App.Vector(%7,%8,%9))") .arg(pos.x) .arg(pos.y) @@ -1055,7 +1055,7 @@ QString Placement::getPlacementFromAxisWithAngle() const Base::Vector3d cnt = getCenterData(); Base::Vector3d dir = getDirection(); double angle = ui->angle->value().getValue(); - return QString::fromLatin1( + return QStringLiteral( "App.Placement(App.Vector(%1,%2,%3), App.Rotation(App.Vector(%4,%5,%6),%7), App.Vector(%8,%9,%10))") .arg(pos.x) .arg(pos.y) diff --git a/src/Gui/Placement.h b/src/Gui/Placement.h index bf6af51282..89d80d3b80 100644 --- a/src/Gui/Placement.h +++ b/src/Gui/Placement.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/src/Gui/PrefWidgets.cpp b/src/Gui/PrefWidgets.cpp index 445392c041..abd41dda7c 100644 --- a/src/Gui/PrefWidgets.cpp +++ b/src/Gui/PrefWidgets.cpp @@ -169,6 +169,15 @@ void PrefWidget::failedToRestore(const QString& name) const PrefSpinBox::PrefSpinBox ( QWidget * parent ) : QSpinBox(parent), PrefWidget() { + setFocusPolicy(Qt::FocusPolicy::StrongFocus); +} + +void PrefSpinBox::wheelEvent(QWheelEvent *event) +{ + if (hasFocus()) + QSpinBox::wheelEvent(event); + else + event->ignore(); } PrefSpinBox::~PrefSpinBox() = default; @@ -201,6 +210,15 @@ void PrefSpinBox::savePreferences() PrefDoubleSpinBox::PrefDoubleSpinBox ( QWidget * parent ) : QDoubleSpinBox(parent), PrefWidget() { + setFocusPolicy(Qt::FocusPolicy::StrongFocus); +} + +void PrefDoubleSpinBox::wheelEvent(QWheelEvent *event) +{ + if (hasFocus()) + QDoubleSpinBox::wheelEvent(event); + else + event->ignore(); } PrefDoubleSpinBox::~PrefDoubleSpinBox() = default; @@ -332,6 +350,15 @@ void PrefFileChooser::savePreferences() PrefComboBox::PrefComboBox ( QWidget * parent ) : QComboBox(parent), PrefWidget() { + setFocusPolicy(Qt::FocusPolicy::StrongFocus); +} + +void PrefComboBox::wheelEvent(QWheelEvent *event) +{ + if (hasFocus()) + QComboBox::wheelEvent(event); + else + event->ignore(); } PrefComboBox::~PrefComboBox() = default; @@ -566,6 +593,15 @@ void PrefColorButton::savePreferences() PrefUnitSpinBox::PrefUnitSpinBox ( QWidget * parent ) : QuantitySpinBox(parent), PrefWidget() { + setFocusPolicy(Qt::FocusPolicy::StrongFocus); +} + +void PrefUnitSpinBox::wheelEvent(QWheelEvent *event) +{ + if (hasFocus()) + QuantitySpinBox::wheelEvent(event); + else + event->ignore(); } PrefUnitSpinBox::~PrefUnitSpinBox() = default; @@ -662,6 +698,7 @@ PrefQuantitySpinBox::PrefQuantitySpinBox (QWidget * parent) : QuantitySpinBox(parent) , d_ptr(new PrefQuantitySpinBoxPrivate()) { + setFocusPolicy(Qt::FocusPolicy::StrongFocus); } PrefQuantitySpinBox::~PrefQuantitySpinBox() = default; @@ -672,7 +709,7 @@ void PrefQuantitySpinBox::contextMenuEvent(QContextMenuEvent *event) QMenu *editMenu = lineEdit()->createStandardContextMenu(); editMenu->setTitle(tr("Edit")); - std::unique_ptr menu(new QMenu(QString::fromLatin1("PrefQuantitySpinBox"))); + std::unique_ptr menu(new QMenu(QStringLiteral("PrefQuantitySpinBox"))); menu->addMenu(editMenu); menu->addSeparator(); @@ -708,6 +745,14 @@ void PrefQuantitySpinBox::contextMenuEvent(QContextMenuEvent *event) } } +void PrefQuantitySpinBox::wheelEvent(QWheelEvent *event) +{ + if (hasFocus()) + QuantitySpinBox::wheelEvent(event); + else + event->ignore(); +} + void PrefQuantitySpinBox::restorePreferences() { Q_D(PrefQuantitySpinBox); diff --git a/src/Gui/PrefWidgets.h b/src/Gui/PrefWidgets.h index d1f1b5ede3..c805f7d063 100644 --- a/src/Gui/PrefWidgets.h +++ b/src/Gui/PrefWidgets.h @@ -123,6 +123,7 @@ public: ~PrefSpinBox() override; protected: + void wheelEvent(QWheelEvent *event) override; // restore from/save to parameters void restorePreferences() override; void savePreferences() override; @@ -143,6 +144,7 @@ public: ~PrefDoubleSpinBox() override; protected: + void wheelEvent(QWheelEvent *event) override; // restore from/save to parameters void restorePreferences() override; void savePreferences() override; @@ -236,6 +238,7 @@ public: ~PrefComboBox() override; protected: + void wheelEvent(QWheelEvent *event) override; // restore from/save to parameters void restorePreferences() override; void savePreferences() override; @@ -351,6 +354,7 @@ public: ~PrefUnitSpinBox() override; protected: + void wheelEvent(QWheelEvent *event) override; // restore from/save to parameters void restorePreferences() override; void savePreferences() override; @@ -391,6 +395,7 @@ public: protected: void contextMenuEvent(QContextMenuEvent * event) override; + void wheelEvent(QWheelEvent *event) override; // restore from/save to parameters void restorePreferences() override; void savePreferences() override; diff --git a/src/Gui/PreferencePackManager.cpp b/src/Gui/PreferencePackManager.cpp index d443926d8b..56581e9a4d 100644 --- a/src/Gui/PreferencePackManager.cpp +++ b/src/Gui/PreferencePackManager.cpp @@ -29,7 +29,7 @@ # include #endif -#include +#include #include #include @@ -48,15 +48,15 @@ using namespace Gui; using namespace xercesc; -namespace fs = boost::filesystem; +namespace fs = std::filesystem; -static boost::filesystem::path getSavedPrefPacksPath() +static std::filesystem::path getSavedPrefPacksPath() { return fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "SavedPreferencePacks"; } -static boost::filesystem::path getResourcePrefPacksPath() +static std::filesystem::path getResourcePrefPacksPath() { return fs::path(Base::FileInfo::stringToPath(App::Application::getResourceDir())) / "Gui" / "PreferencePacks"; @@ -69,17 +69,17 @@ PreferencePack::PreferencePack(const fs::path& path, const App::Metadata& metada throw std::runtime_error{ "Cannot access " + path.string() }; } - auto qssPaths = QDir::searchPaths(QString::fromUtf8("qss")); - auto cssPaths = QDir::searchPaths(QString::fromUtf8("css")); - auto overlayPaths = QDir::searchPaths(QString::fromUtf8("overlay")); + auto qssPaths = QDir::searchPaths(QStringLiteral("qss")); + auto cssPaths = QDir::searchPaths(QStringLiteral("css")); + auto overlayPaths = QDir::searchPaths(QStringLiteral("overlay")); qssPaths.append(QString::fromStdString(Base::FileInfo::pathToString(_path))); cssPaths.append(QString::fromStdString(Base::FileInfo::pathToString(_path))); overlayPaths.append(QString::fromStdString(Base::FileInfo::pathToString(_path) + "/overlay")); - QDir::setSearchPaths(QString::fromUtf8("qss"), qssPaths); - QDir::setSearchPaths(QString::fromUtf8("css"), cssPaths); - QDir::setSearchPaths(QString::fromUtf8("overlay"), overlayPaths); + QDir::setSearchPaths(QStringLiteral("qss"), qssPaths); + QDir::setSearchPaths(QStringLiteral("css"), cssPaths); + QDir::setSearchPaths(QStringLiteral("overlay"), overlayPaths); } std::string PreferencePack::name() const @@ -228,29 +228,25 @@ void Gui::PreferencePackManager::AddPackToMetadata(const std::string &packName) } void Gui::PreferencePackManager::importConfig(const std::string& packName, - const boost::filesystem::path& path) + const std::filesystem::path& path) { AddPackToMetadata(packName); auto savedPreferencePacksDirectory = getSavedPreferencePacksPath(); auto cfgFilename = savedPreferencePacksDirectory / packName / (packName + ".cfg"); -#if BOOST_VERSION >= 107400 fs::copy_file(path, cfgFilename, fs::copy_options::overwrite_existing); -#else - fs::copy_file(path, cfgFilename, fs::copy_option::overwrite_if_exists); -#endif rescan(); } // TODO(Shvedov): Is this suitable place for this method? It is more generic, // and maybe more suitable place at Application? -std::vector Gui::PreferencePackManager::modPaths() const +std::vector Gui::PreferencePackManager::modPaths() const { auto userModPath = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "Mod"; auto& config = App::Application::Config(); auto additionalModules = config.find("AdditionalModulePaths"); - std::vector result; + std::vector result; if (additionalModules != config.end()) { boost::split(result, @@ -262,12 +258,12 @@ std::vector Gui::PreferencePackManager::modPaths() cons return result; } -boost::filesystem::path Gui::PreferencePackManager::getSavedPreferencePacksPath() const +std::filesystem::path Gui::PreferencePackManager::getSavedPreferencePacksPath() const { return getSavedPrefPacksPath(); } -boost::filesystem::path Gui::PreferencePackManager::getResourcePreferencePacksPath() const +std::filesystem::path Gui::PreferencePackManager::getResourcePreferencePacksPath() const { return getResourcePrefPacksPath(); } @@ -309,7 +305,7 @@ void Gui::PreferencePackManager::FindPreferencePacksInPackage(const fs::path &mo } } -void PreferencePackManager::TryFindPreferencePacksInPackage(const boost::filesystem::path& mod) +void PreferencePackManager::TryFindPreferencePacksInPackage(const std::filesystem::path& mod) { auto packageMetadataFile = mod / "package.xml"; static const auto modDirectory = fs::path(Base::FileInfo::stringToPath(App::Application::getUserAppDataDir())) / "Mod" / "SavedPreferencePacks"; @@ -625,6 +621,16 @@ void Gui::PreferencePackManager::BackupCurrentConfig() const App::GetApplication().GetUserParameter().SaveDocument(Base::FileInfo::pathToString(filename).c_str()); } +// FIXME: Replace with more accurate C++20 solution once its usable: https://stackoverflow.com/a/68593141 +template +static std::time_t to_time_t(TP tp) +{ + using namespace std::chrono; + auto sctp = time_point_cast(tp - TP::clock::now() + + system_clock::now()); + return system_clock::to_time_t(sctp); +} + void Gui::PreferencePackManager::DeleteOldBackups() const { constexpr auto oneWeek = 60.0 * 60.0 * 24.0 * 7.0; @@ -632,7 +638,7 @@ void Gui::PreferencePackManager::DeleteOldBackups() const auto backupDirectory = getSavedPreferencePacksPath() / "Backups"; if (fs::exists(backupDirectory) && fs::is_directory(backupDirectory)) { for (const auto& backup : fs::directory_iterator(backupDirectory)) { - if (std::difftime(now, fs::last_write_time(backup)) > oneWeek) { + if (std::difftime(now, to_time_t(fs::last_write_time(backup))) > oneWeek) { try { fs::remove(backup); } @@ -642,9 +648,10 @@ void Gui::PreferencePackManager::DeleteOldBackups() const } } -std::vector Gui::PreferencePackManager::configBackups() const +// FIXME: Replace with more accurate C++20 solution once its usable: https://stackoverflow.com/a/68593141 +std::vector Gui::PreferencePackManager::configBackups() const { - std::vector results; + std::vector results; auto backupDirectory = getSavedPreferencePacksPath() / "Backups"; if (fs::exists(backupDirectory) && fs::is_directory(backupDirectory)) { for (const auto& backup : fs::directory_iterator(backupDirectory)) { diff --git a/src/Gui/PreferencePackManager.h b/src/Gui/PreferencePackManager.h index bb87917447..5250b3407b 100644 --- a/src/Gui/PreferencePackManager.h +++ b/src/Gui/PreferencePackManager.h @@ -44,7 +44,7 @@ namespace Gui { * \param path A path to a mod directory that contains a preferencePack * \param metadata The metadata from the package.xml file describing this preferencePack */ - PreferencePack(const boost::filesystem::path& path, const App::Metadata& metadata); + PreferencePack(const std::filesystem::path& path, const App::Metadata& metadata); ~PreferencePack() = default; @@ -68,7 +68,7 @@ namespace Gui { void applyConfigChanges() const; - boost::filesystem::path _path; + std::filesystem::path _path; App::Metadata _metadata; }; @@ -168,7 +168,7 @@ namespace Gui { struct TemplateFile { std::string group; // Generally the Add-On/Mod/Package name std::string name; - boost::filesystem::path path; + std::filesystem::path path; }; /** @@ -184,37 +184,37 @@ namespace Gui { /** * Get a list of all available config file backups. Backups are currently stored for one week. */ - std::vector configBackups() const; + std::vector configBackups() const; /** * Import an existing config file as a preference pack with a given name. */ - void importConfig(const std::string &packName, const boost::filesystem::path &path); + void importConfig(const std::string &packName, const std::filesystem::path &path); /** * Get a list of all mod directories. */ - std::vector modPaths() const; + std::vector modPaths() const; /** * Get the path to the saved preference packs. */ - boost::filesystem::path getSavedPreferencePacksPath() const; + std::filesystem::path getSavedPreferencePacksPath() const; /** * Get the path to the preference packs of the resource directory. */ - boost::filesystem::path getResourcePreferencePacksPath() const; + std::filesystem::path getResourcePreferencePacksPath() const; /** * Collect all preference packs of a directory. */ - std::vector getPacksFromDirectory(const boost::filesystem::path& path) const; + std::vector getPacksFromDirectory(const std::filesystem::path& path) const; private: - void FindPreferencePacksInPackage(const boost::filesystem::path& mod); - void TryFindPreferencePacksInPackage(const boost::filesystem::path& mod); + void FindPreferencePacksInPackage(const std::filesystem::path& mod); + void TryFindPreferencePacksInPackage(const std::filesystem::path& mod); void BackupCurrentConfig() const; @@ -222,7 +222,7 @@ namespace Gui { void AddPackToMetadata(const std::string &packName) const; - std::vector _preferencePackPaths; + std::vector _preferencePackPaths; std::vector _templateFiles; std::map _preferencePacks; mutable std::mutex _mutex; diff --git a/src/Gui/PreferencePackTemplates/View.cfg b/src/Gui/PreferencePackTemplates/View.cfg index a7357e70cb..8c2392fb2c 100644 --- a/src/Gui/PreferencePackTemplates/View.cfg +++ b/src/Gui/PreferencePackTemplates/View.cfg @@ -14,6 +14,9 @@ + + + diff --git a/src/Gui/PreferencePacks/FreeCAD Classic/FreeCAD Classic.cfg b/src/Gui/PreferencePacks/FreeCAD Classic/FreeCAD Classic.cfg index f1b0e88734..d70940da22 100644 --- a/src/Gui/PreferencePacks/FreeCAD Classic/FreeCAD Classic.cfg +++ b/src/Gui/PreferencePacks/FreeCAD Classic/FreeCAD Classic.cfg @@ -71,6 +71,12 @@ + + #feff9e + #000000 + #000000 + #000000 + @@ -125,6 +131,7 @@ + diff --git a/src/Gui/PreferencePacks/FreeCAD Light/FreeCAD Light.cfg b/src/Gui/PreferencePacks/FreeCAD Light/FreeCAD Light.cfg index 0f3e06a6ea..8f46f8a66b 100644 --- a/src/Gui/PreferencePacks/FreeCAD Light/FreeCAD Light.cfg +++ b/src/Gui/PreferencePacks/FreeCAD Light/FreeCAD Light.cfg @@ -130,7 +130,7 @@ - + diff --git a/src/Gui/PreferencePages/DlgSettings3DView.ui b/src/Gui/PreferencePages/DlgSettings3DView.ui index bac76fd636..4bbdc75615 100644 --- a/src/Gui/PreferencePages/DlgSettings3DView.ui +++ b/src/Gui/PreferencePages/DlgSettings3DView.ui @@ -103,7 +103,7 @@ in the corner -- in % of height/width of viewport
- Axis letter color + Axis letter and FPS counter color @@ -122,6 +122,117 @@ in the corner -- in % of height/width of viewport
+ + + + + + X-axis color + + + + + + + + + + AxisXColor + + + View + + + + 204 + 51 + 51 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Y-axis color + + + + + + + + + + AxisYColor + + + View + + + + 51 + 204 + 51 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Z-axis color + + + + + + + + + + AxisZColor + + + View + + + + 51 + 51 + 204 + + + + + + diff --git a/src/Gui/PreferencePages/DlgSettings3DViewImp.cpp b/src/Gui/PreferencePages/DlgSettings3DViewImp.cpp index 47775784ba..35112bc81c 100644 --- a/src/Gui/PreferencePages/DlgSettings3DViewImp.cpp +++ b/src/Gui/PreferencePages/DlgSettings3DViewImp.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "DlgSettings3DViewImp.h" #include "ui_DlgSettings3DView.h" @@ -74,6 +75,9 @@ void DlgSettings3DViewImp::saveSettings() ui->sliderIntensity->onSave(); ui->radioPerspective->onSave(); ui->radioOrthographic->onSave(); + ui->xAxisColor->onSave(); + ui->yAxisColor->onSave(); + ui->zAxisColor->onSave(); } void DlgSettings3DViewImp::loadSettings() @@ -92,6 +96,9 @@ void DlgSettings3DViewImp::loadSettings() ui->radioPerspective->onRestore(); ui->radioOrthographic->onRestore(); ui->comboTransparentRender->onRestore(); + ui->xAxisColor->onRestore(); + ui->yAxisColor->onRestore(); + ui->zAxisColor->onRestore(); loadAntiAliasing(); loadRenderCache(); @@ -240,3 +247,4 @@ void DlgSettings3DViewImp::onAliasingChanged(int index) #include "moc_DlgSettings3DViewImp.cpp" + diff --git a/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp b/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp index 0fb60854eb..0c395195e6 100644 --- a/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp +++ b/src/Gui/PreferencePages/DlgSettingsCacheDirectory.cpp @@ -63,12 +63,12 @@ DlgSettingsCacheDirectory::DlgSettingsCacheDirectory(QWidget* parent) QString path = QString::fromStdString(App::Application::getUserCachePath()); ui->cacheLocation->setText(path); - ui->comboBoxLimit->addItem(QString::fromLatin1("100 MB"), 100); - ui->comboBoxLimit->addItem(QString::fromLatin1("300 MB"), 300); - ui->comboBoxLimit->addItem(QString::fromLatin1("500 MB"), 500); - ui->comboBoxLimit->addItem(QString::fromLatin1("1 GB"), 1024); - ui->comboBoxLimit->addItem(QString::fromLatin1("2 GB"), 2048); - ui->comboBoxLimit->addItem(QString::fromLatin1("3 GB"), 3072); + ui->comboBoxLimit->addItem(QStringLiteral("100 MB"), 100); + ui->comboBoxLimit->addItem(QStringLiteral("300 MB"), 300); + ui->comboBoxLimit->addItem(QStringLiteral("500 MB"), 500); + ui->comboBoxLimit->addItem(QStringLiteral("1 GB"), 1024); + ui->comboBoxLimit->addItem(QStringLiteral("2 GB"), 2048); + ui->comboBoxLimit->addItem(QStringLiteral("3 GB"), 3072); connect(ui->pushButtonCheck, &QPushButton::clicked, this, &DlgSettingsCacheDirectory::runCheck); connect(ui->openButton, &QPushButton::clicked, this, &DlgSettingsCacheDirectory::openDirectory); @@ -92,7 +92,7 @@ void DlgSettingsCacheDirectory::loadSettings() // if not found then add a new item with this value if (index < 0) { - ui->comboBoxLimit->addItem(QString::fromLatin1("%1 MB").arg(limit), limit); + ui->comboBoxLimit->addItem(QStringLiteral("%1 MB").arg(limit), limit); index = ui->comboBoxLimit->count() - 1; } ui->comboBoxLimit->setCurrentIndex(index); @@ -208,7 +208,7 @@ bool ApplicationCache::periodicCheckOfSize() const QString application = QString::fromStdString(App::Application::getExecutableName()); QSettings settings(vendor, application); - QString key = QString::fromLatin1("LastCacheCheck"); + QString key = QStringLiteral("LastCacheCheck"); QDate date = settings.value(key).toDate(); QDate now = QDate::currentDate(); @@ -245,7 +245,7 @@ bool ApplicationCache::performAction(qint64 total) QString warn = tr("Warning: Please make sure that this is the only running %1 instance " "and that no documents are opened as this may result into data loss!").arg(QCoreApplication::applicationName()); - msgBox.setText(QString::fromLatin1("%1 %2\n\n\n%3").arg(hint, ask, warn)); + msgBox.setText(QStringLiteral("%1 %2\n\n\n%3").arg(hint, ask, warn)); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Open); msgBox.setDefaultButton(QMessageBox::No); @@ -286,7 +286,7 @@ void ApplicationCache::clearDirectory(const QString& path) { // Add the transient directories and the lock files to the ignore list QDir tmp = QString::fromUtf8(App::Application::getUserCachePath().c_str()); - tmp.setNameFilters(QStringList() << QString::fromLatin1("*.lock")); + tmp.setNameFilters(QStringList() << QStringLiteral("*.lock")); tmp.setFilter(QDir::Files); QList dirs; @@ -347,10 +347,10 @@ qint64 ApplicationCache::toBytes(unsigned int sizeInMB) QString ApplicationCache::toString(qint64 size) { - QStringList units = {QString::fromLatin1("Bytes"), - QString::fromLatin1("KB"), - QString::fromLatin1("MB"), - QString::fromLatin1("GB")}; + QStringList units = {QStringLiteral("Bytes"), + QStringLiteral("KB"), + QStringLiteral("MB"), + QStringLiteral("GB")}; int i; double outputSize = size; for (i=0; iprefSaveTransaction->hide(); ui->prefDiscardTransaction->hide(); - QString tip = QString::fromLatin1("

%1

" + QString tip = QStringLiteral("

%1

" "

%2: %Y%m%d-%H%M%S

" "

%3: C++ strftime" "

").arg(tr("The format of the date to use."), tr("Default"), tr("Format")); diff --git a/src/Gui/PreferencePages/DlgSettingsEditor.cpp b/src/Gui/PreferencePages/DlgSettingsEditor.cpp index 0dda987761..4ccde4fdab 100644 --- a/src/Gui/PreferencePages/DlgSettingsEditor.cpp +++ b/src/Gui/PreferencePages/DlgSettingsEditor.cpp @@ -253,7 +253,7 @@ void DlgSettingsEditor::loadSettings() ui->radioSpaces->onRestore(); setEditorTabWidth(ui->tabSize->value()); - ui->textEdit1->setPlainText(QString::fromLatin1("# Short Python sample\n" + ui->textEdit1->setPlainText(QStringLiteral("# Short Python sample\n" "import sys\n" "\n" "def foo(begin, end):\n" diff --git a/src/Gui/PreferencePages/DlgSettingsGeneral.cpp b/src/Gui/PreferencePages/DlgSettingsGeneral.cpp index 4ae81c7de1..48a0a25855 100644 --- a/src/Gui/PreferencePages/DlgSettingsGeneral.cpp +++ b/src/Gui/PreferencePages/DlgSettingsGeneral.cpp @@ -45,10 +45,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -62,7 +62,7 @@ using namespace Gui; using namespace Gui::Dialog; -namespace fs = boost::filesystem; +namespace fs = std::filesystem; using namespace Base; /* TRANSLATOR Gui::Dialog::DlgSettingsGeneral */ @@ -322,7 +322,7 @@ void DlgSettingsGeneral::loadSettings() int index = 1; TStringMap list = Translator::instance()->supportedLocales(); ui->Languages->clear(); - ui->Languages->addItem(QString::fromLatin1("English"), QByteArray("English")); + ui->Languages->addItem(QStringLiteral("English"), QByteArray("English")); for (auto it = list.begin(); it != list.end(); ++it, index++) { QByteArray lang = it->first.c_str(); QString langname = QString::fromLatin1(lang.constData()); @@ -739,7 +739,7 @@ void DlgSettingsGeneral::onImportConfigClicked() auto path = fs::path(QFileDialog::getOpenFileName(this, tr("Choose a FreeCAD config file to import"), QString(), - QString::fromUtf8("*.cfg")).toStdString()); + QStringLiteral("*.cfg")).toStdString()); if (!path.empty()) { // Create a name from the filename: auto packName = path.filename().stem().string(); diff --git a/src/Gui/PreferencePages/DlgSettingsLightSources.cpp b/src/Gui/PreferencePages/DlgSettingsLightSources.cpp index 563d203b1e..fd1701e92a 100644 --- a/src/Gui/PreferencePages/DlgSettingsLightSources.cpp +++ b/src/Gui/PreferencePages/DlgSettingsLightSources.cpp @@ -233,7 +233,7 @@ void DlgSettingsLightSources::saveDirection() if (lightDragger) { const SbRotation rotation = lightDragger->rotation.getValue(); const SbVec3f dir = getDirectionVector(rotation); - const QString headlightDir = QString::fromLatin1("(%1,%2,%3)").arg(dir[0]).arg(dir[1]).arg(dir[2]); + const QString headlightDir = QStringLiteral("(%1,%2,%3)").arg(dir[0]).arg(dir[1]).arg(dir[2]); ParameterGrp::handle grp = ui->sliderIntensity1->getWindowParameter(); diff --git a/src/Gui/PreferencePages/DlgSettingsNavigation.cpp b/src/Gui/PreferencePages/DlgSettingsNavigation.cpp index 1d71982431..a1df77b0a8 100644 --- a/src/Gui/PreferencePages/DlgSettingsNavigation.cpp +++ b/src/Gui/PreferencePages/DlgSettingsNavigation.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include @@ -285,21 +285,21 @@ void DlgSettingsNavigation::onMouseButtonClicked() ui->comboNavigationStyle->itemData(ui->comboNavigationStyle->currentIndex(), Qt::UserRole); void* instance = Base::Type::createInstanceByName((const char*)data.toByteArray()); std::unique_ptr ns(static_cast(instance)); - uimb.groupBox->setTitle(uimb.groupBox->title() + QString::fromLatin1(" ") + uimb.groupBox->setTitle(uimb.groupBox->title() + QStringLiteral(" ") + ui->comboNavigationStyle->currentText()); QString descr; descr = qApp->translate((const char*)data.toByteArray(),ns->mouseButtons(NavigationStyle::SELECTION)); descr.replace(QLatin1String("\n"), QLatin1String("

")); - uimb.selectionLabel->setText(QString::fromLatin1("%1").arg(descr)); + uimb.selectionLabel->setText(QStringLiteral("%1").arg(descr)); descr = qApp->translate((const char*)data.toByteArray(),ns->mouseButtons(NavigationStyle::PANNING)); descr.replace(QLatin1String("\n"), QLatin1String("

")); - uimb.panningLabel->setText(QString::fromLatin1("%1").arg(descr)); + uimb.panningLabel->setText(QStringLiteral("%1").arg(descr)); descr = qApp->translate((const char*)data.toByteArray(),ns->mouseButtons(NavigationStyle::DRAGGING)); descr.replace(QLatin1String("\n"), QLatin1String("

")); - uimb.rotationLabel->setText(QString::fromLatin1("%1").arg(descr)); + uimb.rotationLabel->setText(QStringLiteral("%1").arg(descr)); descr = qApp->translate((const char*)data.toByteArray(),ns->mouseButtons(NavigationStyle::ZOOMING)); descr.replace(QLatin1String("\n"), QLatin1String("

")); - uimb.zoomingLabel->setText(QString::fromLatin1("%1").arg(descr)); + uimb.zoomingLabel->setText(QStringLiteral("%1").arg(descr)); dlg.exec(); } @@ -416,7 +416,7 @@ CameraDialog::CameraDialog(QWidget* parent) auto currentViewButton = new QPushButton(this); currentViewButton->setText(tr("Current view")); - currentViewButton->setObjectName(QString::fromLatin1("currentView")); + currentViewButton->setObjectName(QStringLiteral("currentView")); layout->addWidget(currentViewButton, 4, 1, 2, 1); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); diff --git a/src/Gui/PreferencePages/DlgSettingsWorkbenchesImp.cpp b/src/Gui/PreferencePages/DlgSettingsWorkbenchesImp.cpp index b91c19a614..99b15a0659 100644 --- a/src/Gui/PreferencePages/DlgSettingsWorkbenchesImp.cpp +++ b/src/Gui/PreferencePages/DlgSettingsWorkbenchesImp.cpp @@ -111,7 +111,7 @@ wbListItem::wbListItem(const QString& wbName, bool enabled, bool startupWb, bool textLabel->setEnabled(enableCheckBox->isChecked()); // 4: shortcut - shortcutLabel = new QLabel(QString::fromLatin1("(W, %1)").arg(index + 1), this); + shortcutLabel = new QLabel(QStringLiteral("(W, %1)").arg(index + 1), this); shortcutLabel->setToolTip(tr("Shortcut to activate this workbench.")); shortcutLabel->setEnabled(enableCheckBox->isChecked()); shortcutLabel->setVisible(index < 9); @@ -188,7 +188,7 @@ void wbListItem::setStartupWb(bool val) void wbListItem::setShortcutLabel(int index) { - shortcutLabel->setText(QString::fromLatin1("(W, %1)").arg(index + 1)); + shortcutLabel->setText(QStringLiteral("(W, %1)").arg(index + 1)); shortcutLabel->setVisible(index < 9); } @@ -593,9 +593,9 @@ void DlgSettingsWorkbenchesImp::setStartWorkbenchComboItems() } { // add special workbench to selection - QPixmap px = Application::Instance->workbenchIcon(QString::fromLatin1("NoneWorkbench")); - QString key = QString::fromLatin1(""); - QString value = QString::fromLatin1("$LastModule"); + QPixmap px = Application::Instance->workbenchIcon(QStringLiteral("NoneWorkbench")); + QString key = QStringLiteral(""); + QString value = QStringLiteral("$LastModule"); if (px.isNull()) { ui->AutoloadModuleCombo->addItem(key, QVariant(value)); } diff --git a/src/Gui/ListWidgetDragBugFix.cpp b/src/Gui/PreferencePages/ListWidgetDragBugFix.cpp similarity index 100% rename from src/Gui/ListWidgetDragBugFix.cpp rename to src/Gui/PreferencePages/ListWidgetDragBugFix.cpp diff --git a/src/Gui/ListWidgetDragBugFix.h b/src/Gui/PreferencePages/ListWidgetDragBugFix.h similarity index 100% rename from src/Gui/ListWidgetDragBugFix.h rename to src/Gui/PreferencePages/ListWidgetDragBugFix.h diff --git a/src/Gui/ProgressBar.cpp b/src/Gui/ProgressBar.cpp index d8e5897756..cffff2082e 100644 --- a/src/Gui/ProgressBar.cpp +++ b/src/Gui/ProgressBar.cpp @@ -295,7 +295,7 @@ void SequencerBar::showRemainingTime() QTime time( 0,0, 0); time = time.addSecs( rest/1000 ); QString remain = Gui::ProgressBar::tr("Remaining: %1").arg(time.toString()); - QString status = QString::fromLatin1("%1\t[%2]").arg(txt, remain); + QString status = QStringLiteral("%1\t[%2]").arg(txt, remain); if (thr != currentThread) { QMetaObject::invokeMethod(getMainWindow(), "showMessage", diff --git a/src/Gui/ProgressDialog.cpp b/src/Gui/ProgressDialog.cpp index 3f596d62ab..90f531fb92 100644 --- a/src/Gui/ProgressDialog.cpp +++ b/src/Gui/ProgressDialog.cpp @@ -217,7 +217,7 @@ void SequencerDialog::showRemainingTime() QTime time( 0,0, 0); time = time.addSecs( rest/1000 ); QString remain = Gui::ProgressDialog::tr("Remaining: %1").arg(time.toString()); - QString status = QString::fromLatin1("%1\t[%2]").arg(txt, remain); + QString status = QStringLiteral("%1\t[%2]").arg(txt, remain); if (thr != currentThread) { QMetaObject::invokeMethod(d->dlg, "setLabelText", diff --git a/src/Gui/PropertyView.cpp b/src/Gui/PropertyView.cpp index 96c66f2b88..9f1094243e 100644 --- a/src/Gui/PropertyView.cpp +++ b/src/Gui/PropertyView.cpp @@ -79,7 +79,7 @@ PropertyView::PropertyView(QWidget *parent) connect(timer, &QTimer::timeout, this, &PropertyView::onTimer); tabs = new QTabWidget (this); - tabs->setObjectName(QString::fromUtf8("propertyTab")); + tabs->setObjectName(QStringLiteral("propertyTab")); tabs->setTabPosition(QTabWidget::South); pLayout->addWidget(tabs, 0, 0); @@ -403,7 +403,7 @@ void PropertyView::onTimer() continue; } - if(vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + if(vp->isDerivedFrom()) { auto cvp = static_cast(vp); if(vpLast && cvp!=vpLast) checkLink = false; diff --git a/src/Gui/PythonConsole.cpp b/src/Gui/PythonConsole.cpp index f6b566c5a4..bed38eb94f 100644 --- a/src/Gui/PythonConsole.cpp +++ b/src/Gui/PythonConsole.cpp @@ -468,7 +468,7 @@ PythonConsole::PythonConsole(QWidget *parent) const char* version = PyUnicode_AsUTF8(PySys_GetObject("version")); const char* platform = PyUnicode_AsUTF8(PySys_GetObject("platform")); - d->info = QString::fromLatin1("Python %1 on %2\n" + d->info = QStringLiteral("Python %1 on %2\n" "Type 'help', 'copyright', 'credits' or 'license' for more information.") .arg(QString::fromLatin1(version), QString::fromLatin1(platform)); d->output = d->info; @@ -609,7 +609,7 @@ void PythonConsole::keyPressEvent(QKeyEvent * e) if (!inputStrg.isEmpty()) { d->history.append( QLatin1String("# ") + inputStrg ); //< put commented string to history ... - inputLineBegin.insertText( QString::fromLatin1("# ") ); //< and comment it on console + inputLineBegin.insertText( QStringLiteral("# ") ); //< and comment it on console setTextCursor( inputLineBegin ); printPrompt(d->interpreter->hasPendingInput() //< print adequate prompt ? PythonConsole::Incomplete @@ -753,10 +753,10 @@ void PythonConsole::printPrompt(PythonConsole::Prompt mode) switch (mode) { case PythonConsole::Incomplete: - cursor.insertText(QString::fromLatin1("... ")); + cursor.insertText(QStringLiteral("... ")); break; case PythonConsole::Complete: - cursor.insertText(QString::fromLatin1(">>> ")); + cursor.insertText(QStringLiteral(">>> ")); break; default: break; @@ -806,7 +806,7 @@ void PythonConsole::runSource(const QString& line) } if (d->interpreter->isOccupied()) { - insertPythonError(QString::fromLatin1("Previous command still running!")); + insertPythonError(QStringLiteral("Previous command still running!")); return; } @@ -1000,7 +1000,7 @@ void PythonConsole::dropEvent (QDropEvent * e) for (int i=0; i> action; - printStatement(QString::fromLatin1("Gui.runCommand(\"%1\")").arg(action)); + printStatement(QStringLiteral("Gui.runCommand(\"%1\")").arg(action)); } e->setDropAction(Qt::CopyAction); @@ -1305,7 +1305,7 @@ void PythonConsole::contextMenuEvent ( QContextMenuEvent * e ) bool mayPasteHere = cursorBeyond( this->textCursor(), this->inputBegin() ); a = menu.addAction(tr("&Copy"), this, &PythonConsole::copy); - a->setShortcut(QKeySequence(QString::fromLatin1("CTRL+C"))); + a->setShortcut(QKeySequence(QStringLiteral("CTRL+C"))); a->setEnabled(textCursor().hasSelection()); a = menu.addAction(tr("&Copy command"), this, &PythonConsole::onCopyCommand); @@ -1325,12 +1325,12 @@ void PythonConsole::contextMenuEvent ( QContextMenuEvent * e ) menu.addSeparator(); a = menu.addAction(tr("&Paste"), this, &PythonConsole::paste); - a->setShortcut(QKeySequence(QString::fromLatin1("CTRL+V"))); + a->setShortcut(QKeySequence(QStringLiteral("CTRL+V"))); const QMimeData *md = QApplication::clipboard()->mimeData(); a->setEnabled( mayPasteHere && md && canInsertFromMimeData(md)); a = menu.addAction(tr("Select All"), this, &PythonConsole::selectAll); - a->setShortcut(QKeySequence(QString::fromLatin1("CTRL+A"))); + a->setShortcut(QKeySequence(QStringLiteral("CTRL+A"))); a->setEnabled(!document()->isEmpty()); a = menu.addAction(tr("Clear console"), this, &PythonConsole::onClearConsole); @@ -1365,7 +1365,7 @@ void PythonConsole::onSaveHistoryAs() QString cMacroPath = QString::fromUtf8(getDefaultParameter()->GetGroup( "Macro" )-> GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()).c_str()); QString fn = FileDialog::getSaveFileName(this, tr("Save History"), cMacroPath, - QString::fromLatin1("%1 (*.FCMacro *.py)").arg(tr("Macro Files"))); + QStringLiteral("%1 (*.FCMacro *.py)").arg(tr("Macro Files"))); if (!fn.isEmpty()) { int dot = fn.indexOf(QLatin1Char('.')); if (dot != -1) { @@ -1385,7 +1385,7 @@ void PythonConsole::onSaveHistoryAs() void PythonConsole::onInsertFileName() { QString fn = Gui::FileDialog::getOpenFileName(Gui::getMainWindow(), tr("Insert file name"), QString(), - QString::fromLatin1("%1 (*.*)").arg(tr("All Files"))); + QStringLiteral("%1 (*.*)").arg(tr("All Files"))); if ( !fn.isEmpty() ) { insertPlainText(fn); } diff --git a/src/Gui/PythonConsolePy.cpp b/src/Gui/PythonConsolePy.cpp index 7d81406ef1..08b1f415a6 100644 --- a/src/Gui/PythonConsolePy.cpp +++ b/src/Gui/PythonConsolePy.cpp @@ -50,7 +50,7 @@ Py::Object PythonStdout::getattr(const char *name) { if (strcmp(name, "softspace") == 0) { int i=0; - return Py::Int(i); + return Py::Long(i); } return getattr_methods(name); } @@ -114,7 +114,7 @@ Py::Object PythonStderr::getattr(const char *name) { if (strcmp(name, "softspace") == 0) { int i=0; - return Py::Int(i); + return Py::Long(i); } return getattr_methods(name); } @@ -175,7 +175,7 @@ Py::Object OutputStdout::getattr(const char *name) { if (strcmp(name, "softspace") == 0) { int i=0; - return Py::Int(i); + return Py::Long(i); } return getattr_methods(name); } @@ -236,7 +236,7 @@ Py::Object OutputStderr::getattr(const char *name) { if (strcmp(name, "softspace") == 0) { int i=0; - return Py::Int(i); + return Py::Long(i); } return getattr_methods(name); } diff --git a/src/Gui/PythonEditor.cpp b/src/Gui/PythonEditor.cpp index 3da59a5ce9..02251ec59f 100644 --- a/src/Gui/PythonEditor.cpp +++ b/src/Gui/PythonEditor.cpp @@ -74,13 +74,13 @@ PythonEditor::PythonEditor(QWidget* parent) // set accelerators auto comment = new QShortcut(this); - comment->setKey(QKeySequence(QString::fromLatin1("ALT+C"))); + comment->setKey(QKeySequence(QStringLiteral("ALT+C"))); auto uncomment = new QShortcut(this); - uncomment->setKey(QKeySequence(QString::fromLatin1("ALT+U"))); + uncomment->setKey(QKeySequence(QStringLiteral("ALT+U"))); auto execInConsole = new QShortcut(this); - execInConsole->setKey(QKeySequence(QString::fromLatin1("ALT+SHIFT+P"))); + execInConsole->setKey(QKeySequence(QStringLiteral("ALT+SHIFT+P"))); connect(comment, &QShortcut::activated, this, &PythonEditor::onComment); connect(uncomment, &QShortcut::activated, this, &PythonEditor::onUncomment); @@ -175,12 +175,12 @@ void PythonEditor::contextMenuEvent ( QContextMenuEvent * e ) if (!isReadOnly()) { menu->addSeparator(); QAction* comment = menu->addAction( tr("Comment"), this, &PythonEditor::onComment); - comment->setShortcut(QKeySequence(QString::fromLatin1("ALT+C"))); + comment->setShortcut(QKeySequence(QStringLiteral("ALT+C"))); QAction* uncomment = menu->addAction( tr("Uncomment"), this, &PythonEditor::onUncomment); - uncomment->setShortcut(QKeySequence(QString::fromLatin1("ALT+U"))); + uncomment->setShortcut(QKeySequence(QStringLiteral("ALT+U"))); QAction* execInConsole = menu->addAction( tr("Execute in console"), this, &PythonEditor::onExecuteInConsole); - execInConsole->setShortcut(QKeySequence(QString::fromLatin1("ALT+Shift+P"))); + execInConsole->setShortcut(QKeySequence(QStringLiteral("ALT+Shift+P"))); } menu->exec(e->globalPos()); @@ -199,8 +199,8 @@ void PythonEditor::keyPressEvent(QKeyEvent* e) ParameterGrp::handle hPrefGrp = getWindowParameter(); int indent = hPrefGrp->GetInt( "IndentSize", 4 ); bool space = hPrefGrp->GetBool( "Spaces", true ); - QString ch = space ? QString::fromLatin1(" ") - : QString::fromLatin1("\t"); + QString ch = space ? QStringLiteral(" ") + : QStringLiteral("\t"); QTextCursor cursor = textCursor(); QString currentLineText = cursor.block().text(); diff --git a/src/Gui/QSint/actionpanel/actionlabel.cpp b/src/Gui/QSint/actionpanel/actionlabel.cpp index 7b1e60d951..e2e893fd47 100644 --- a/src/Gui/QSint/actionpanel/actionlabel.cpp +++ b/src/Gui/QSint/actionpanel/actionlabel.cpp @@ -85,7 +85,7 @@ QSize ActionLabel::sizeHint() const QString s(text()); bool empty = s.isEmpty(); if (empty) - s = QString::fromLatin1("XXXX"); + s = QStringLiteral("XXXX"); QFontMetrics fm = fontMetrics(); QSize sz = fm.size(Qt::TextShowMnemonic, s); w += sz.width(); diff --git a/src/Gui/QSint/actionpanel/actionpanel.cpp b/src/Gui/QSint/actionpanel/actionpanel.cpp index 2c01e08a72..3a7b706379 100644 --- a/src/Gui/QSint/actionpanel/actionpanel.cpp +++ b/src/Gui/QSint/actionpanel/actionpanel.cpp @@ -26,7 +26,7 @@ ActionPanel::ActionPanel(QWidget *parent) : setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); QVBoxLayout *vbl = new QVBoxLayout(); - vbl->setContentsMargins(8, 8, 8, 8); + vbl->setContentsMargins(4, 8, 4, 8); vbl->setSpacing(8); setLayout(vbl); } diff --git a/src/Gui/QSint/actionpanel/freecadscheme.cpp b/src/Gui/QSint/actionpanel/freecadscheme.cpp index 6340493a86..3c22f30de8 100644 --- a/src/Gui/QSint/actionpanel/freecadscheme.cpp +++ b/src/Gui/QSint/actionpanel/freecadscheme.cpp @@ -202,13 +202,11 @@ SystemPanelScheme::SystemPanelScheme() headerAnimation = true; QPalette p = QApplication::palette(); - QPalette p2 = p; - p2.setColor(QPalette::Highlight,p2.color(QPalette::Highlight).lighter()); - headerButtonFold = drawFoldIcon(p, true); - headerButtonFoldOver = drawFoldIcon(p2, true); - headerButtonUnfold = drawFoldIcon(p, false); - headerButtonUnfoldOver = drawFoldIcon(p2, false); + headerButtonFold = drawFoldIcon(p, true, false); + headerButtonFoldOver = drawFoldIcon(p, true, true); + headerButtonUnfold = drawFoldIcon(p, false, false); + headerButtonUnfoldOver = drawFoldIcon(p, false, true); headerButtonSize = QSize(17,17); groupFoldSteps = 20; @@ -219,134 +217,121 @@ SystemPanelScheme::SystemPanelScheme() actionStyle = systemStyle(QApplication::palette()); } -/*! - \code - QPalette p = QApplication::palette(); - QPalette p2 = p; - p2.setColor(QPalette::Highlight,p2.color(QPalette::Highlight).lighter()); - headerButtonFold = drawFoldIcon(p, true); - headerButtonFoldOver = drawFoldIcon(p2, true); - headerButtonUnfold = drawFoldIcon(p, false); - headerButtonUnfoldOver = drawFoldIcon(p2, false); - \endcode - */ -QPixmap SystemPanelScheme::drawFoldIcon(const QPalette& p, bool fold) const +QPixmap SystemPanelScheme::drawFoldIcon(const QPalette& palette, bool fold, bool hover) const { - QImage img(17,17,QImage::Format_ARGB32_Premultiplied); - img.fill(0x00000000); - QPainter painter; - painter.begin(&img); - painter.setBrush(p.window()); - painter.drawEllipse(2,2,13,13); - painter.setPen(p.color(QPalette::Base)); - painter.drawEllipse(2,2,13,13); - painter.setPen(p.color(QPalette::Highlight)); - painter.drawLine(QLine(5,7,8,4)); - painter.drawLine(QLine(6,7,8,5)); - painter.drawLine(QLine(8,4,11,7)); - painter.drawLine(QLine(8,5,10,7)); - painter.drawLine(QLine(5,11,8,8)); - painter.drawLine(QLine(6,11,8,9)); - painter.drawLine(QLine(8,8,11,11)); - painter.drawLine(QLine(9,8,10,11)); - painter.end(); + QSize bSize = headerButtonSize; + QImage img(bSize.width(), bSize.height(), QImage::Format_ARGB32_Premultiplied); + img.fill(Qt::transparent); - if (!fold) { - QTransform mat; - mat.rotate(180.0); - img = img.transformed(mat); + QPainter painter(&img); + + painter.setRenderHint(QPainter::Antialiasing); + + qreal penWidth = bSize.width() / 14.0; + qreal lef_X = 0.25 * bSize.width(); + qreal mid_X = 0.50 * bSize.width(); + qreal rig_X = 0.75 * bSize.width(); + qreal bot_Y = 0.40 * bSize.height(); + qreal top_Y = 0.64 * bSize.height(); + + if (hover) { + penWidth *= 1.8; } + + painter.setBrush(Qt::NoBrush); + painter.setPen(QPen(palette.color(QPalette::HighlightedText), penWidth)); + + QPolygon chevron; + if (fold) { + // Upward + chevron << QPoint(lef_X, top_Y) + << QPoint(mid_X, bot_Y) + << QPoint(rig_X, top_Y); + } else { + // Downward + chevron << QPoint(lef_X, bot_Y) + << QPoint(mid_X, top_Y) + << QPoint(rig_X, bot_Y); + } + + painter.drawPolyline(chevron); + painter.end(); return QPixmap::fromImage(img); } + QString SystemPanelScheme::systemStyle(const QPalette& p) const { - QColor panelBackground1 = p.color(QPalette::Dark); - QColor panelBackground2 = p.color(QPalette::Midlight); + QColor headerBackground = p.color(QPalette::Highlight); + QColor headerLabelText = p.color(QPalette::HighlightedText); + QColor headerLabelTextOver = p.color(QPalette::BrightText); + QColor groupBorder = p.color(QPalette::Mid); + QColor disabledActionText = p.color(QPalette::Disabled, QPalette::Text); + QColor actionSelectedBg = p.color(QPalette::Active, QPalette::Light); + QColor actionSelectedText = p.color(QPalette::Active, QPalette::ButtonText); + QColor actionSelectedBorder = p.color(QPalette::Active, QPalette::Highlight); - QColor headerBackground1 = p.color(QPalette::Highlight); - QColor headerBackground2 = p.color(QPalette::Highlight).lighter(); + QString style = QStringLiteral( + "QSint--ActionGroup QFrame[class='header'] {" + "border: 1px solid transparent;" + "background-color: %1;" + "}" - QColor headerLabelText = p.color(QPalette::HighlightedText); - QColor headerLabelTextOver = p.color(QPalette::BrightText); + "QSint--ActionGroup QToolButton[class='header'] {" + "text-align: left;" + "color: %2;" + "background-color: transparent;" + "border: 1px solid transparent;" + "font-weight: bold;" + "}" - QColor groupBackground = p.window().color(); - QColor groupBorder = p.color(QPalette::Window); + "QSint--ActionGroup QToolButton[class='header']:hover {" + "color: %3;" + "}" - QColor taskLabelText = p.color(QPalette::Text); - QColor taskLabelTextOver = p.color(QPalette::Highlight); + "QSint--ActionGroup QFrame[class='content'] {" + "border: 1px solid %4;" + "}" - QString style = QString::fromLatin1( - "QFrame[class='panel'] {" - "background-color:qlineargradient(x1:1, y1:0.3, x2:1, y2:0, stop:0 %1, stop:1 %2);" - "}" + "QSint--ActionGroup QFrame[class='content'][header='true'] {" + "border-top: none;" + "}" - "QSint--ActionGroup QFrame[class='header'] {" - "border: 1px solid #ffffff;" // todo - "border-top-left-radius: 4px;" - "border-top-right-radius: 4px;" - "background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 %3, stop: 1 %4);" - "}" + "QSint--ActionGroup QToolButton[class='action'] {" + "background-color: transparent;" + "border: 1px solid transparent;" + "text-align: left;" + "}" - "QSint--ActionGroup QToolButton[class='header'] {" - "text-align: left;" - "color: %5;" - "background-color: transparent;" - "border: 1px solid transparent;" - "font-weight: bold;" - "}" + "QSint--ActionGroup QToolButton[class='action']:!enabled {" + "color: %5;" + "}" - "QSint--ActionGroup QToolButton[class='header']:hover {" - "color: %6;" - "}" + "QSint--ActionGroup QToolButton[class='action']:hover {" + "text-decoration: underline;" + "}" - "QSint--ActionGroup QFrame[class='content'] {" - "background-color: %7;" - "border: 1px solid %8;" - "}" + "QSint--ActionGroup QToolButton[class='action']:focus {" + "color: %7;" + "border: 1px dotted %8;" + "}" - "QSint--ActionGroup QFrame[class='content'][header='true'] {" - "border-top: none;" - "}" + "QSint--ActionGroup QToolButton[class='action']:on {" + "background-color: %6;" + "color: %7;" + "}" + ).arg( + headerBackground.name(), + headerLabelText.name(), + headerLabelTextOver.name(), + groupBorder.name(), + disabledActionText.name(), + actionSelectedBg.name(), + actionSelectedText.name(), + actionSelectedBorder.name() + ); - "QSint--ActionGroup QToolButton[class='action'] {" - "background-color: transparent;" - "border: 1px solid transparent;" - "color: %9;" - "text-align: left;" - "}" - - "QSint--ActionGroup QToolButton[class='action']:!enabled {" - "color: #999999;" // todo - "}" - - "QSint--ActionGroup QToolButton[class='action']:hover {" - "color: %10;" - "text-decoration: underline;" - "}" - - "QSint--ActionGroup QToolButton[class='action']:focus {" - "border: 1px dotted black;" - "}" - - "QSint--ActionGroup QToolButton[class='action']:on {" - "background-color: #ddeeff;" // todo - "color: #006600;" // todo - "}" - ) - .arg(panelBackground1.name(), - panelBackground2.name(), - headerBackground1.name(), - headerBackground2.name(), - headerLabelText.name(), - headerLabelTextOver.name(), - groupBackground.name(), - groupBorder.name(), - taskLabelText.name()) - .arg(taskLabelTextOver.name()) - ; - - return style; + return style; } } diff --git a/src/Gui/QSint/actionpanel/freecadscheme.h b/src/Gui/QSint/actionpanel/freecadscheme.h index fedf5afe3a..4cbeca0ba6 100644 --- a/src/Gui/QSint/actionpanel/freecadscheme.h +++ b/src/Gui/QSint/actionpanel/freecadscheme.h @@ -66,7 +66,7 @@ public: } private: - QPixmap drawFoldIcon(const QPalette& p, bool fold) const; + QPixmap drawFoldIcon(const QPalette& p, bool fold, bool hover) const; QString systemStyle(const QPalette& p) const; }; diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp index 1ab6a81e84..38a265e38a 100644 --- a/src/Gui/QuantitySpinBox.cpp +++ b/src/Gui/QuantitySpinBox.cpp @@ -48,7 +48,7 @@ #include "QuantitySpinBox.h" #include "QuantitySpinBox_p.h" #include "Command.h" -#include "DlgExpressionInput.h" +#include "Dialogs/DlgExpressionInput.h" #include "Tools.h" @@ -173,7 +173,7 @@ public: //Prep for expression parser //This regex matches chunks between +,-,$,^ accounting for matching parenthesis. - QRegularExpression chunkRe(QString::fromUtf8("(?<=^|[\\+\\-])((\\((?>[^()]|(?2))*\\))|[^\\+\\-\n])*(?=$|[\\+\\-])")); + QRegularExpression chunkRe(QStringLiteral("(?<=^|[\\+\\-])((\\((?>[^()]|(?2))*\\))|[^\\+\\-\n])*(?=$|[\\+\\-])")); QRegularExpressionMatchIterator expressionChunk = chunkRe.globalMatch(copy); unsigned int lengthOffset = 0; while (expressionChunk.hasNext()) { @@ -198,7 +198,7 @@ public: if (fixUnitsMatch.lastCapturedIndex() == 2 || (fixUnitsMatch.lastCapturedIndex() == 3 && fixUnitsMatch.captured(3).isEmpty())){ QString matchUnits = fixUnitsMatch.captured(1); QString matchNumbers = fixUnitsMatch.captured(2); - copyChunk.replace(matchUnits+matchNumbers, QString::fromUtf8(")")+matchUnits+QString::fromUtf8("1(*")+matchNumbers); + copyChunk.replace(matchUnits+matchNumbers, QStringLiteral(")")+matchUnits+QStringLiteral("1(*")+matchNumbers); } } @@ -208,7 +208,7 @@ public: QRegularExpressionMatch match = unitsRe.match(copyChunk); if (!match.hasMatch() && !copyChunk.isEmpty()) //If no units are found, use default units - copyChunk.prepend(QString::fromUtf8(")")+reverseUnitStr+QString::fromUtf8("1(*")); // Add units to the end of chunk *(1unit) + copyChunk.prepend(QStringLiteral(")")+reverseUnitStr+QStringLiteral("1(*")); // Add units to the end of chunk *(1unit) } std::reverse(copyChunk.begin(), copyChunk.end()); @@ -834,7 +834,7 @@ QSize QuantitySpinBox::sizeHintCalculator(int h) const const QFontMetrics fm(fontMetrics()); int w = 0; - constexpr int maxStrLen = 12; + constexpr int maxStrLen = 9; QString s; QString fixedContent = QLatin1String(" "); @@ -923,7 +923,7 @@ void QuantitySpinBox::clear() void QuantitySpinBox::selectNumber() { - QString expr = QString::fromLatin1("^([%1%2]?[0-9\\%3]*)\\%4?([0-9]+(%5[%1%2]?[0-9]+)?)") + QString expr = QStringLiteral("^([%1%2]?[0-9\\%3]*)\\%4?([0-9]+(%5[%1%2]?[0-9]+)?)") .arg(locale().negativeSign()) .arg(locale().positiveSign()) .arg(locale().groupSeparator()) diff --git a/src/Gui/Quarter/SoQTQuarterAdaptor.cpp b/src/Gui/Quarter/SoQTQuarterAdaptor.cpp index db8a3535c6..72dddc75a3 100644 --- a/src/Gui/Quarter/SoQTQuarterAdaptor.cpp +++ b/src/Gui/Quarter/SoQTQuarterAdaptor.cpp @@ -634,10 +634,11 @@ void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::resetToHomePosition() } -void -SIM::Coin3D::Quarter::SoQTQuarterAdaptor::draw2DString(const char* str, - SbVec2s glsize, - SbVec2f position) +void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::draw2DString( + const char* str, + SbVec2s glsize, + SbVec2f position, + App::Color color = App::Color(1.0F, 1.0F, 0.0F)) // retains yellow as default color { // Store GL state. glPushAttrib(GL_ENABLE_BIT|GL_CURRENT_BIT); @@ -668,7 +669,7 @@ SIM::Coin3D::Quarter::SoQTQuarterAdaptor::draw2DString(const char* str, // glRasterPos2f(position[0], position[1] - 1); // printString(str); - glColor3f(1.0, 1.0, 0.0); + glColor3f(color.r, color.g, color.b); glRasterPos2f(position[0], position[1]); printString(str); diff --git a/src/Gui/Quarter/SoQTQuarterAdaptor.h b/src/Gui/Quarter/SoQTQuarterAdaptor.h index 5bd96da736..8cfe271cb9 100644 --- a/src/Gui/Quarter/SoQTQuarterAdaptor.h +++ b/src/Gui/Quarter/SoQTQuarterAdaptor.h @@ -27,6 +27,8 @@ #include #include +#include + #include "QuarterWidget.h" @@ -150,7 +152,7 @@ private: SoNode * m_storedcamera = nullptr; protected: - static void draw2DString(const char * str, SbVec2s glsize, SbVec2f position); + static void draw2DString(const char * str, SbVec2s glsize, SbVec2f position, App::Color color); static void printString(const char * str); SbVec2f framesPerSecond; // NOLINT }; diff --git a/src/Gui/ReportView.cpp b/src/Gui/ReportView.cpp index d81540f79b..7a61bb5933 100644 --- a/src/Gui/ReportView.cpp +++ b/src/Gui/ReportView.cpp @@ -64,7 +64,7 @@ ReportView::ReportView( QWidget* parent ) tabLayout->setContentsMargins( 0, 0, 0, 0 ); tabWidget = new QTabWidget( this ); - tabWidget->setObjectName(QString::fromUtf8("tabWidget")); + tabWidget->setObjectName(QStringLiteral("tabWidget")); tabWidget->setTabPosition(QTabWidget::South); tabWidget->setTabShape(QTabWidget::Rounded); tabLayout->addWidget( tabWidget, 0, 0 ); @@ -511,7 +511,7 @@ void ReportOutput::SendLog(const std::string& notifiername, const std::string& m if (style == ReportHighlighter::LogText) { if (messageSize > 0 && qMsg.size()>messageSize) { qMsg.truncate(messageSize); - qMsg += QString::fromLatin1("...\n"); + qMsg += QStringLiteral("...\n"); } } @@ -658,7 +658,7 @@ void ReportOutput::contextMenuEvent ( QContextMenuEvent * e ) QAction* copy = menu->addAction(copyStr, this, &ReportOutput::copy); copy->setShortcut(QKeySequence(QKeySequence::Copy)); copy->setEnabled(textCursor().hasSelection()); - QIcon icon = QIcon::fromTheme(QString::fromLatin1("edit-copy")); + QIcon icon = QIcon::fromTheme(QStringLiteral("edit-copy")); if (!icon.isNull()) copy->setIcon(icon); @@ -678,7 +678,7 @@ void ReportOutput::contextMenuEvent ( QContextMenuEvent * e ) void ReportOutput::onSaveAs() { QString fn = QFileDialog::getSaveFileName(this, tr("Save Report Output"), QString(), - QString::fromLatin1("%1 (*.txt *.log)").arg(tr("Plain Text Files"))); + QStringLiteral("%1 (*.txt *.log)").arg(tr("Plain Text Files"))); if (!fn.isEmpty()) { QFileInfo fi(fn); if (fi.completeSuffix().isEmpty()) diff --git a/src/Gui/SceneInspector.cpp b/src/Gui/SceneInspector.cpp index bec6a63f55..b94dc3ed61 100644 --- a/src/Gui/SceneInspector.cpp +++ b/src/Gui/SceneInspector.cpp @@ -30,6 +30,8 @@ # include #endif +#include + #include "SceneInspector.h" #include "ui_SceneInspector.h" #include "Application.h" @@ -37,6 +39,9 @@ #include "View3DInventor.h" #include "View3DInventorViewer.h" #include "ViewProviderDocumentObject.h" +#include "MainWindow.h" + +#include using namespace Gui::Dialog; @@ -53,7 +58,10 @@ enum class Column: std::int8_t { NAME = 1, MEMORY_ADDRESS = 2, DATA = 3, - COUNT = 4, + RENDER_CACHING = 4, + BOUNDING_BOX_CACHING = 5, + BOUNDING_BOX = 6, + COUNT = 7, }; SceneModel::~SceneModel() = default; @@ -84,6 +92,12 @@ QVariant SceneModel::headerData (int section, Qt::Orientation orientation, int r return tr("Address"); case Column::DATA: return tr("Data"); + case Column::RENDER_CACHING: + return tr("Render Cache"); + case Column::BOUNDING_BOX_CACHING: + return tr("Bounds Cache"); + case Column::BOUNDING_BOX: + return tr("Bounds"); default: assert(0 && "Not handled yet"); } @@ -175,6 +189,37 @@ static std::string_view formatSoPickStyleElement(int32_t value) } } +static inline bool isAtFloatValueLimit(float v) +{ + return v == std::numeric_limits::lowest() || v == std::numeric_limits::max(); +} + +static bool isInfinite(const SbVec3f& vec) +{ + float x, y, z; //NOLINT + vec.getValue(x, y, z); + return isAtFloatValueLimit(x) && isAtFloatValueLimit(y) && isAtFloatValueLimit(z); +} + +static std::string formatSbXfBox3f(const SbXfBox3f& box) +{ + SbVec3f minpoint; + SbVec3f maxpoint; + box.getBounds(minpoint, maxpoint); + + if (isInfinite(minpoint) && isInfinite(maxpoint)) { + return {"Infinite"}; + } + + float minx, miny, minz; //NOLINT + minpoint.getValue(minx, miny, minz); + + float maxx, maxy, maxz; //NOLINT + maxpoint.getValue(maxx, maxy, maxz); + + return fmt::format("Min: ({:.3},{:.3},{:.3}), Max: ({:.3},{:.3},{:.3})", minx, miny, minz, maxx, maxy, maxz); +} + void SceneModel::setNode(QModelIndex index, SoNode* node) { this->setData(index.siblingAtColumn(static_cast(Column::INVENTOR_TREE)), @@ -190,6 +235,9 @@ void SceneModel::setNode(QModelIndex index, SoNode* node) this->setData(index.siblingAtColumn(static_cast(Column::MEMORY_ADDRESS)), QVariant(QString::fromStdString(fmt::format("{}", (void*)node)))); + auto view = qobject_cast(getMainWindow()->activeWindow()); + auto vp = view->getViewer()->getSoRenderManager()->getViewportRegion(); + QString data; QTextStream stream(&data); if(static_cast(node->isOfType(SoSwitch::getClassTypeId()))) { @@ -198,8 +246,19 @@ void SceneModel::setNode(QModelIndex index, SoNode* node) stream << fmt::format("Which: {} ({})", formatSoSwitchValue(value), value).c_str(); } else if (static_cast(node->isOfType(SoSeparator::getClassTypeId()))) { auto pcSeparator = static_cast(node); - auto value = pcSeparator->renderCaching.getValue(); - stream << fmt::format("RenderCaching: {} ({})", formatSoSeparatorCacheEnabled(value), value).c_str(); + + auto renderCaching = pcSeparator->renderCaching.getValue(); + this->setData(index.siblingAtColumn(static_cast(Column::RENDER_CACHING)), + QVariant(QString::fromStdString(std::string{formatSoSeparatorCacheEnabled(renderCaching)}))); + + auto boundingBoxCaching = pcSeparator->boundingBoxCaching.getValue(); + this->setData(index.siblingAtColumn(static_cast(Column::BOUNDING_BOX_CACHING)), + QVariant(QString::fromStdString(std::string{formatSoSeparatorCacheEnabled(boundingBoxCaching)}))); + + SoGetBoundingBoxAction getBBox(vp); + getBBox.apply(pcSeparator); + this->setData(index.siblingAtColumn(static_cast(Column::BOUNDING_BOX)), + QVariant(QString::fromStdString(formatSbXfBox3f(getBBox.getXfBoundingBox())))); } else if (static_cast(node->isOfType(SoDrawStyle::getClassTypeId()))) { auto pcDrawStyle = static_cast(node); auto value = pcDrawStyle->style.getValue(); @@ -287,7 +346,10 @@ void DlgInspector::setNode(SoNode* node) header->setSectionResizeMode(static_cast(Column::NAME), QHeaderView::Interactive); header->resizeSection(static_cast(Column::NAME), 200); header->setSectionResizeMode(static_cast(Column::MEMORY_ADDRESS), QHeaderView::Interactive); - header->setSectionResizeMode(static_cast(Column::DATA), QHeaderView::Stretch); + header->resizeSection(static_cast(Column::MEMORY_ADDRESS), 140); + header->setSectionResizeMode(static_cast(Column::DATA), QHeaderView::Interactive); + header->resizeSection(static_cast(Column::DATA), 200); + header->setSectionsMovable(false); } diff --git a/src/Gui/SceneInspector.ui b/src/Gui/SceneInspector.ui index 478137cd5c..6d4a398303 100644 --- a/src/Gui/SceneInspector.ui +++ b/src/Gui/SceneInspector.ui @@ -6,8 +6,8 @@ 0 0 - 805 - 583 + 1200 + 700 diff --git a/src/Gui/Selection.cpp b/src/Gui/Selection/Selection.cpp similarity index 97% rename from src/Gui/Selection.cpp rename to src/Gui/Selection/Selection.cpp index bef006fd72..b8fdab737e 100644 --- a/src/Gui/Selection.cpp +++ b/src/Gui/Selection/Selection.cpp @@ -637,7 +637,7 @@ int SelectionSingleton::setPreselect(const char* pDocName, const char* pObjectNa } else { msg = QCoreApplication::translate("SelectionFilter","Not allowed:"); } - msg.append(QString::fromLatin1(" %1.%2.%3 ") + msg.append(QStringLiteral(" %1.%2.%3 ") .arg(QString::fromLatin1(pDocName), QString::fromLatin1(pObjectName), QString::fromLatin1(pSubName))); diff --git a/src/Gui/Selection.h b/src/Gui/Selection/Selection.h similarity index 91% rename from src/Gui/Selection.h rename to src/Gui/Selection/Selection.h index f5e0154204..336a5948f6 100644 --- a/src/Gui/Selection.h +++ b/src/Gui/Selection/Selection.h @@ -49,9 +49,13 @@ namespace Gui { enum class ResolveMode { + /// No resolve NoResolve, + /// Sub-object with old style element name OldStyleElement, + /// Sub-object with new style element name NewStyleElement, + /// Resolve sub-object and follow link FollowLink }; @@ -185,33 +189,7 @@ public: const SelectionChanges *pOriginalMsg = nullptr; }; -} //namespace Gui - - - -// Export an instance of the base class (to avoid warning C4275, see also -// C++ Language Reference/General Rules and Limitations on MSDN for more details.) -// -// For compiler gcc4.1 we need to define the template class outside namespace 'Gui' -// otherwise we get the compiler error: -// 'explicit instantiation of 'class Base::Subject' -// in namespace 'Gui' (which does not enclose namespace 'Base') -// -// It seems that this construct is not longer needed for gcc4.4 and even leads to -// errors under Mac OS X. Thus, we check for version between 4.1 and 4.4. -// It seems that for Mac OS X this can be completely ignored - -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(FC_OS_MACOSX) -#define GNUC_VERSION (((__GNUC__)<<16)+((__GNUC_MINOR__)<<8)) -#if GNUC_VERSION >= 0x040100 && GNUC_VERSION < 0x040400 -template class GuiExport Base::Subject; -#endif -#undef GNUC_VERSION -#endif - -namespace Gui -{ - class ViewProviderDocumentObject; +class ViewProviderDocumentObject; /** * The SelectionObserver class simplifies the step to write classes that listen @@ -227,9 +205,6 @@ public: * * @param attach: whether to attach this observer on construction * @param resolve: sub-object resolving mode. - * 0 no resolve, - * 1 resolve sub-object with old style element name - * 2 resolve sub-object with new style element name */ explicit SelectionObserver(bool attach = true, ResolveMode resolve = ResolveMode::OldStyleElement); /** Constructor @@ -237,9 +212,6 @@ public: * @param vp: filtering view object. * @param attach: whether to attach this observer on construction * @param resolve: sub-object resolving mode. - * 0 no resolve, - * 1 resolve sub-object with old style element name - * 2 resolve sub-object with new style element name * * Constructs an selection observer that receives only selection event of * objects within the same document as the input view object. @@ -452,9 +424,6 @@ public: * empty vector is returned. If document name is "*", then all document is * considered. * @param resolve: sub-object resolving mode - * 0 no resolve, - * 1 resolve sub-object with old style element name - * 2 resolve sub-object with new style element name * @param single: if set to true, then it will return an empty vector if * there is more than one selections. * @@ -465,15 +434,12 @@ public: * * @param pDocName: document name. If no document name is given the objects * of the active are returned. If nothing for this Document is selected an - * empty vector is returned. If document name is "*", then all document is + * empty vector is returned. If document name is "*", then all documents are * considered. * @param typeId: specify the type of object to be returned. * @param resolve: sub-object resolving mode. - * 0 no resolve, - * 1 resolve sub-object with old style element name - * 2 resolve sub-object with new style element name * @param single: if set to true, then it will return an empty vector if - * there is more than one selections. + * there is more than one selection. * * @return The returned vector reflects the sequence of selection. */ @@ -549,9 +515,6 @@ public: * @param pDocName: optional filtering document, NULL for current active * document * @param resolve: sub-object resolving mode. - * 0 no resolve, - * 1 resolve sub-object with old style element name - * 2 resolve sub-object with new style element name * @param index: optional position in the stack */ std::vector selStackGet(const char* pDocName=nullptr, ResolveMode resolve = ResolveMode::OldStyleElement, int index=0) const; diff --git a/src/Gui/SelectionFilter.cpp b/src/Gui/Selection/SelectionFilter.cpp similarity index 96% rename from src/Gui/SelectionFilter.cpp rename to src/Gui/Selection/SelectionFilter.cpp index 51f0f5c716..991521fb1e 100644 --- a/src/Gui/SelectionFilter.cpp +++ b/src/Gui/Selection/SelectionFilter.cpp @@ -210,7 +210,7 @@ bool SelectionFilter::test(App::DocumentObject*pObj, const char*sSubName) return false; for (const auto& it : Ast->Objects) { - if (pObj->getTypeId().isDerivedFrom(it->ObjectType)) { + if (pObj->isDerivedFrom(it->ObjectType)) { if (!sSubName) return true; if (it->SubName.empty()) diff --git a/src/Gui/SelectionFilter.h b/src/Gui/Selection/SelectionFilter.h similarity index 100% rename from src/Gui/SelectionFilter.h rename to src/Gui/Selection/SelectionFilter.h diff --git a/src/Gui/SelectionFilter.l b/src/Gui/Selection/SelectionFilter.l similarity index 100% rename from src/Gui/SelectionFilter.l rename to src/Gui/Selection/SelectionFilter.l diff --git a/src/Gui/SelectionFilter.tab.c b/src/Gui/Selection/SelectionFilter.tab.c similarity index 100% rename from src/Gui/SelectionFilter.tab.c rename to src/Gui/Selection/SelectionFilter.tab.c diff --git a/src/Gui/SelectionFilter.y b/src/Gui/Selection/SelectionFilter.y similarity index 100% rename from src/Gui/SelectionFilter.y rename to src/Gui/Selection/SelectionFilter.y diff --git a/src/Gui/SelectionFilterPy.cpp b/src/Gui/Selection/SelectionFilterPy.cpp similarity index 100% rename from src/Gui/SelectionFilterPy.cpp rename to src/Gui/Selection/SelectionFilterPy.cpp diff --git a/src/Gui/SelectionFilterPy.h b/src/Gui/Selection/SelectionFilterPy.h similarity index 100% rename from src/Gui/SelectionFilterPy.h rename to src/Gui/Selection/SelectionFilterPy.h diff --git a/src/Gui/SelectionObject.cpp b/src/Gui/Selection/SelectionObject.cpp similarity index 94% rename from src/Gui/SelectionObject.cpp rename to src/Gui/Selection/SelectionObject.cpp index c8450a24cf..f545ff377e 100644 --- a/src/Gui/SelectionObject.cpp +++ b/src/Gui/Selection/SelectionObject.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "SelectionObject.h" #include "Selection.h" @@ -85,7 +85,7 @@ App::DocumentObject * SelectionObject::getObject() bool SelectionObject::isObjectTypeOf(const Base::Type& typeId) const { const App::DocumentObject* obj = getObject(); - return (obj && obj->getTypeId().isDerivedFrom(typeId)); + return (obj && obj->isDerivedFrom(typeId)); } std::string SelectionObject::getAsPropertyLinkSubString()const diff --git a/src/Gui/SelectionObject.h b/src/Gui/Selection/SelectionObject.h similarity index 100% rename from src/Gui/SelectionObject.h rename to src/Gui/Selection/SelectionObject.h diff --git a/src/Gui/SelectionObjectPy.xml b/src/Gui/Selection/SelectionObjectPy.xml similarity index 96% rename from src/Gui/SelectionObjectPy.xml rename to src/Gui/Selection/SelectionObjectPy.xml index e25a724d34..5cd194e455 100644 --- a/src/Gui/SelectionObjectPy.xml +++ b/src/Gui/Selection/SelectionObjectPy.xml @@ -5,7 +5,7 @@ Name="SelectionObjectPy" Twin="SelectionObject" TwinPointer="SelectionObject" - Include="Gui/SelectionObject.h" + Include="Gui/Selection/SelectionObject.h" Namespace="Gui" Delete="true" FatherInclude="Base/BaseClassPy.h" diff --git a/src/Gui/SelectionObjectPyImp.cpp b/src/Gui/Selection/SelectionObjectPyImp.cpp similarity index 95% rename from src/Gui/SelectionObjectPyImp.cpp rename to src/Gui/Selection/SelectionObjectPyImp.cpp index 27b82372ca..686cb68121 100644 --- a/src/Gui/SelectionObjectPyImp.cpp +++ b/src/Gui/Selection/SelectionObjectPyImp.cpp @@ -31,8 +31,8 @@ // inclusion of the generated files (generated out of SelectionObjectPy.xml) -#include "SelectionObjectPy.h" -#include "SelectionObjectPy.cpp" +#include "Selection/SelectionObjectPy.h" +#include "Selection/SelectionObjectPy.cpp" using namespace Gui; diff --git a/src/Gui/SelectionObserverPython.cpp b/src/Gui/Selection/SelectionObserverPython.cpp similarity index 100% rename from src/Gui/SelectionObserverPython.cpp rename to src/Gui/Selection/SelectionObserverPython.cpp diff --git a/src/Gui/SelectionObserverPython.h b/src/Gui/Selection/SelectionObserverPython.h similarity index 100% rename from src/Gui/SelectionObserverPython.h rename to src/Gui/Selection/SelectionObserverPython.h diff --git a/src/Gui/SelectionView.cpp b/src/Gui/Selection/SelectionView.cpp similarity index 91% rename from src/Gui/SelectionView.cpp rename to src/Gui/Selection/SelectionView.cpp index 3e705a2491..469f8d0f72 100644 --- a/src/Gui/SelectionView.cpp +++ b/src/Gui/Selection/SelectionView.cpp @@ -74,12 +74,12 @@ SelectionView::SelectionView(Gui::Document* pcDocument, QWidget* parent) QToolButton* clearButton = new QToolButton(this); clearButton->setFixedSize(18, 21); clearButton->setCursor(Qt::ArrowCursor); - clearButton->setStyleSheet(QString::fromUtf8("QToolButton {margin-bottom:1px}")); + clearButton->setStyleSheet(QStringLiteral("QToolButton {margin-bottom:1px}")); clearButton->setIcon(BitmapFactory().pixmap(":/icons/edit-cleartext.svg")); clearButton->setToolTip(tr("Clears the search field")); clearButton->setAutoRaise(true); countLabel = new QLabel(this); - countLabel->setText(QString::fromUtf8("0")); + countLabel->setText(QStringLiteral("0")); countLabel->setToolTip(tr("The number of selected items")); hLayout->addWidget(searchBox); hLayout->addWidget(clearButton, 0, Qt::AlignRight); @@ -337,7 +337,7 @@ void SelectionView::select(QListWidgetItem* item) // Gui::Selection().clearSelection(); Gui::Command::runCommand(Gui::Command::Gui, "Gui.Selection.clearSelection()"); // Gui::Selection().addSelection(elements[0].toLatin1(),elements[1].toLatin1(),0); - QString cmd = QString::fromLatin1( + QString cmd = QStringLiteral( R"(Gui.Selection.addSelection(App.getDocument("%1").getObject("%2")))") .arg(elements[0], elements[1]); Gui::Command::runCommand(Gui::Command::Gui, cmd.toLatin1()); @@ -359,7 +359,7 @@ void SelectionView::deselect() } // Gui::Selection().rmvSelection(elements[0].toLatin1(),elements[1].toLatin1(),0); - QString cmd = QString::fromLatin1( + QString cmd = QStringLiteral( R"(Gui.Selection.removeSelection(App.getDocument("%1").getObject("%2")))") .arg(elements[0], elements[1]); try { @@ -398,14 +398,14 @@ void SelectionView::toggleSelect(QListWidgetItem* item) } QString cmd; if (Gui::Selection().isSelected(docname, objname, subname)) { - cmd = QString::fromLatin1("Gui.Selection.removeSelection(" + cmd = QStringLiteral("Gui.Selection.removeSelection(" "App.getDocument('%1').getObject('%2'),'%3')") .arg(QString::fromLatin1(docname), QString::fromLatin1(objname), QString::fromLatin1(subname)); } else { - cmd = QString::fromLatin1("Gui.Selection.addSelection(" + cmd = QStringLiteral("Gui.Selection.addSelection(" "App.getDocument('%1').getObject('%2'),'%3',%4,%5,%6)") .arg(QString::fromLatin1(docname), QString::fromLatin1(objname), @@ -448,7 +448,7 @@ void SelectionView::preselect(QListWidgetItem* item) *end = 0; } } - QString cmd = QString::fromLatin1("Gui.Selection.setPreselection(" + QString cmd = QStringLiteral("Gui.Selection.setPreselection(" "App.getDocument('%1').getObject('%2'),'%3',tp=2)") .arg(QString::fromLatin1(docname), QString::fromLatin1(objname), @@ -493,7 +493,7 @@ void SelectionView::touch() if (elements.size() < 2) { return; } - QString cmd = QString::fromLatin1(R"(App.getDocument("%1").getObject("%2").touch())") + QString cmd = QStringLiteral(R"(App.getDocument("%1").getObject("%2").touch())") .arg(elements[0], elements[1]); try { Gui::Command::runCommand(Gui::Command::Doc, cmd.toLatin1()); @@ -515,7 +515,7 @@ void SelectionView::toPython() } try { - QString cmd = QString::fromLatin1(R"(obj = App.getDocument("%1").getObject("%2"))") + QString cmd = QStringLiteral(R"(obj = App.getDocument("%1").getObject("%2"))") .arg(elements[0], elements[1]); Gui::Command::runCommand(Gui::Command::Gui, cmd.toLatin1()); if (elements.length() > 2) { @@ -523,12 +523,12 @@ void SelectionView::toPython() App::DocumentObject* obj = doc->getObject(elements[1].toLatin1()); QString property = getProperty(obj); - cmd = QString::fromLatin1(R"(shp = App.getDocument("%1").getObject("%2").%3)") + cmd = QStringLiteral(R"(shp = App.getDocument("%1").getObject("%2").%3)") .arg(elements[0], elements[1], property); Gui::Command::runCommand(Gui::Command::Gui, cmd.toLatin1()); if (supportPart(obj, elements[2])) { - cmd = QString::fromLatin1(R"(elt = App.getDocument("%1").getObject("%2").%3.%4)") + cmd = QStringLiteral(R"(elt = App.getDocument("%1").getObject("%2").%3.%4)") .arg(elements[0], elements[1], property, elements[2]); Gui::Command::runCommand(Gui::Command::Gui, cmd.toLatin1()); } @@ -555,7 +555,7 @@ void SelectionView::showPart() try { Gui::Command::addModule(Gui::Command::Gui, module.toLatin1()); QString cmd = - QString::fromLatin1(R"(%1.show(App.getDocument("%2").getObject("%3").%4.%5))") + QStringLiteral(R"(%1.show(App.getDocument("%2").getObject("%3").%4.%5))") .arg(module, elements[0], elements[1], property, elements[2]); Gui::Command::runCommand(Gui::Command::Gui, cmd.toLatin1()); } @@ -637,27 +637,27 @@ void SelectionView::onItemContextMenu(const QPoint& point) QAction* selectAction = menu.addAction(tr("Select only"), this, [&] { this->select(nullptr); }); - selectAction->setIcon(QIcon::fromTheme(QString::fromLatin1("view-select"))); + selectAction->setIcon(QIcon::fromTheme(QStringLiteral("view-select"))); selectAction->setToolTip(tr("Selects only this object")); QAction* deselectAction = menu.addAction(tr("Deselect"), this, &SelectionView::deselect); - deselectAction->setIcon(QIcon::fromTheme(QString::fromLatin1("view-unselectable"))); + deselectAction->setIcon(QIcon::fromTheme(QStringLiteral("view-unselectable"))); deselectAction->setToolTip(tr("Deselects this object")); QAction* zoomAction = menu.addAction(tr("Zoom fit"), this, &SelectionView::zoom); - zoomAction->setIcon(QIcon::fromTheme(QString::fromLatin1("zoom-fit-best"))); + zoomAction->setIcon(QIcon::fromTheme(QStringLiteral("zoom-fit-best"))); zoomAction->setToolTip(tr("Selects and fits this object in the 3D window")); QAction* gotoAction = menu.addAction(tr("Go to selection"), this, &SelectionView::treeSelect); gotoAction->setToolTip(tr("Selects and locates this object in the tree view")); QAction* touchAction = menu.addAction(tr("Mark to recompute"), this, &SelectionView::touch); - touchAction->setIcon(QIcon::fromTheme(QString::fromLatin1("view-refresh"))); + touchAction->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); touchAction->setToolTip(tr("Mark this object to be recomputed")); QAction* toPythonAction = menu.addAction(tr("To Python console"), this, &SelectionView::toPython); - toPythonAction->setIcon(QIcon::fromTheme(QString::fromLatin1("applications-python"))); + toPythonAction->setIcon(QIcon::fromTheme(QStringLiteral("applications-python"))); toPythonAction->setToolTip( tr("Reveals this object and its subelements in the Python console.")); @@ -666,7 +666,7 @@ void SelectionView::onItemContextMenu(const QPoint& point) // subshape-specific entries QAction* showPart = menu.addAction(tr("Duplicate subshape"), this, &SelectionView::showPart); - showPart->setIcon(QIcon(QString::fromLatin1(":/icons/ClassBrowser/member.svg"))); + showPart->setIcon(QIcon(QStringLiteral(":/icons/ClassBrowser/member.svg"))); showPart->setToolTip(tr("Creates a standalone copy of this subshape in the document")); } menu.exec(selectionView->mapToGlobal(point)); diff --git a/src/Gui/SelectionView.h b/src/Gui/Selection/SelectionView.h similarity index 100% rename from src/Gui/SelectionView.h rename to src/Gui/Selection/SelectionView.h diff --git a/src/Gui/SoFCSelection.cpp b/src/Gui/Selection/SoFCSelection.cpp similarity index 95% rename from src/Gui/SoFCSelection.cpp rename to src/Gui/Selection/SoFCSelection.cpp index 5317a4b50f..b5dc26de5e 100644 --- a/src/Gui/SoFCSelection.cpp +++ b/src/Gui/Selection/SoFCSelection.cpp @@ -79,7 +79,7 @@ SoFCSelection::SoFCSelection() SO_NODE_ADD_FIELD(colorHighlight, (SbColor(0.8f, 0.1f, 0.1f))); SO_NODE_ADD_FIELD(colorSelection, (SbColor(0.1f, 0.8f, 0.1f))); SO_NODE_ADD_FIELD(style, (EMISSIVE)); - SO_NODE_ADD_FIELD(highlightMode, (AUTO)); + SO_NODE_ADD_FIELD(preselectionMode, (AUTO)); SO_NODE_ADD_FIELD(selectionMode, (SEL_ON)); SO_NODE_ADD_FIELD(selected, (NOTSELECTED)); SO_NODE_ADD_FIELD(documentName, ("")); @@ -92,10 +92,10 @@ SoFCSelection::SoFCSelection() SO_NODE_DEFINE_ENUM_VALUE(Styles, BOX); SO_NODE_SET_SF_ENUM_TYPE(style, Styles); - SO_NODE_DEFINE_ENUM_VALUE(HighlightModes, AUTO); - SO_NODE_DEFINE_ENUM_VALUE(HighlightModes, ON); - SO_NODE_DEFINE_ENUM_VALUE(HighlightModes, OFF); - SO_NODE_SET_SF_ENUM_TYPE (highlightMode, HighlightModes); + SO_NODE_DEFINE_ENUM_VALUE(PreselectionModes, AUTO); + SO_NODE_DEFINE_ENUM_VALUE(PreselectionModes, ON); + SO_NODE_DEFINE_ENUM_VALUE(PreselectionModes, OFF); + SO_NODE_SET_SF_ENUM_TYPE (preselectionMode, PreselectionModes); SO_NODE_DEFINE_ENUM_VALUE(SelectionModes, SEL_ON); SO_NODE_DEFINE_ENUM_VALUE(SelectionModes, SEL_OFF); @@ -216,19 +216,19 @@ void SoFCSelection::doAction(SoAction *action) if(!useNewSelection.getValue()) { - if (action->getTypeId() == SoFCEnableHighlightAction::getClassTypeId()) { - auto preaction = static_cast(action); - if (preaction->highlight) { - this->highlightMode = SoFCSelection::AUTO; + if (action->getTypeId() == SoFCEnablePreselectionAction::getClassTypeId()) { + auto preaction = static_cast(action); + if (preaction->enabled) { + this->preselectionMode = SoFCSelection::AUTO; } else { - this->highlightMode = SoFCSelection::OFF; + this->preselectionMode = SoFCSelection::OFF; } } if (action->getTypeId() == SoFCEnableSelectionAction::getClassTypeId()) { auto selaction = static_cast(action); - if (selaction->selection) { + if (selaction->enabled) { this->selectionMode = SoFCSelection::SEL_ON; } else { @@ -359,7 +359,7 @@ SoFCSelection::handleEvent(SoHandleEventAction * action) } static char buf[513]; - auto mymode = static_cast(this->highlightMode.getValue()); + auto mymode = static_cast(this->preselectionMode.getValue()); const SoEvent * event = action->getEvent(); #ifdef NO_FRONTBUFFER // mouse move events for preselection @@ -777,7 +777,7 @@ SoFCSelection::preRender(SoGLRenderAction *action, GLint &oldDepthFunc) //////////////////////////////////////////////////////////////////////// { // If not performing locate highlighting, just return. - if (highlightMode.getValue() == OFF) + if (preselectionMode.getValue() == OFF) return false; SoState *state = action->getState(); @@ -787,7 +787,7 @@ SoFCSelection::preRender(SoGLRenderAction *action, GLint &oldDepthFunc) // ??? never be called. We are not caching this node correctly yet.... //SoCacheElement::invalidate(state); - SbBool drawHighlighted = (highlightMode.getValue() == ON || isHighlighted(action) || selected.getValue() == SELECTED); + SbBool drawHighlighted = (preselectionMode.getValue() == ON || isHighlighted(action) || selected.getValue() == SELECTED); if (drawHighlighted) { // prevent diffuse & emissive color from leaking out... @@ -930,7 +930,7 @@ SoFCSelection::readInstance ( SoInput * in, unsigned short flags ) bool SoFCSelection::setOverride(SoGLRenderAction * action, SelContextPtr ctx) { - auto mymode = static_cast(this->highlightMode.getValue()); + auto mymode = static_cast(this->preselectionMode.getValue()); bool preselected = ctx && ctx->isHighlighted() && (useNewSelection.getValue()||mymode == AUTO); if (!preselected && mymode!=ON && (!ctx || !ctx->isSelected())) return false; @@ -1040,7 +1040,7 @@ void SoFCSelection::applySettings () bool enablePre = hGrp->GetBool("EnablePreselection", true); bool enableSel = hGrp->GetBool("EnableSelection", true); if (!enablePre) { - this->highlightMode = Gui::SoFCSelection::OFF; + this->preselectionMode = Gui::SoFCSelection::OFF; } else { // Search for a user defined value with the current color as default diff --git a/src/Gui/SoFCSelection.h b/src/Gui/Selection/SoFCSelection.h similarity index 95% rename from src/Gui/SoFCSelection.h rename to src/Gui/Selection/SoFCSelection.h index 2b4b0deb3c..9327aafa49 100644 --- a/src/Gui/SoFCSelection.h +++ b/src/Gui/Selection/SoFCSelection.h @@ -69,7 +69,7 @@ public: /// Load highlight settings from the configuration void applySettings (); - enum HighlightModes { + enum PreselectionModes { AUTO, ON, OFF }; @@ -91,7 +91,7 @@ public: SoSFColor colorSelection; SoSFEnum style; SoSFEnum selected; - SoSFEnum highlightMode; + SoSFEnum preselectionMode; SoSFEnum selectionMode; SoSFString documentName; diff --git a/src/Gui/SoFCSelectionAction.cpp b/src/Gui/Selection/SoFCSelectionAction.cpp similarity index 91% rename from src/Gui/SoFCSelectionAction.cpp rename to src/Gui/Selection/SoFCSelectionAction.cpp index 14777bd78b..6d66687b5e 100644 --- a/src/Gui/SoFCSelectionAction.cpp +++ b/src/Gui/Selection/SoFCSelectionAction.cpp @@ -69,7 +69,7 @@ using namespace Gui; -SO_ACTION_SOURCE(SoFCHighlightAction) +SO_ACTION_SOURCE(SoFCPreselectionAction) /** * The order of the defined SO_ACTION_ADD_METHOD statements is very important. First the base @@ -79,28 +79,28 @@ SO_ACTION_SOURCE(SoFCHighlightAction) * This means that \c SoSwitch must be listed after \c SoGroup and \c SoFCSelection after * \c SoSeparator because both classes inherits the others. */ -void SoFCHighlightAction::initClass() +void SoFCPreselectionAction::initClass() { - SO_ACTION_INIT_CLASS(SoFCHighlightAction,SoAction); + SO_ACTION_INIT_CLASS(SoFCPreselectionAction,SoAction); - SO_ENABLE(SoFCHighlightAction, SoSwitchElement); + SO_ENABLE(SoFCPreselectionAction, SoSwitchElement); SO_ACTION_ADD_METHOD(SoNode,nullAction); - SO_ENABLE(SoFCHighlightAction, SoModelMatrixElement); - SO_ENABLE(SoFCHighlightAction, SoShapeStyleElement); - SO_ENABLE(SoFCHighlightAction, SoComplexityElement); - SO_ENABLE(SoFCHighlightAction, SoComplexityTypeElement); - SO_ENABLE(SoFCHighlightAction, SoCoordinateElement); - SO_ENABLE(SoFCHighlightAction, SoFontNameElement); - SO_ENABLE(SoFCHighlightAction, SoFontSizeElement); - SO_ENABLE(SoFCHighlightAction, SoProfileCoordinateElement); - SO_ENABLE(SoFCHighlightAction, SoProfileElement); - SO_ENABLE(SoFCHighlightAction, SoSwitchElement); - SO_ENABLE(SoFCHighlightAction, SoUnitsElement); - SO_ENABLE(SoFCHighlightAction, SoViewVolumeElement); - SO_ENABLE(SoFCHighlightAction, SoViewingMatrixElement); - SO_ENABLE(SoFCHighlightAction, SoViewportRegionElement); + SO_ENABLE(SoFCPreselectionAction, SoModelMatrixElement); + SO_ENABLE(SoFCPreselectionAction, SoShapeStyleElement); + SO_ENABLE(SoFCPreselectionAction, SoComplexityElement); + SO_ENABLE(SoFCPreselectionAction, SoComplexityTypeElement); + SO_ENABLE(SoFCPreselectionAction, SoCoordinateElement); + SO_ENABLE(SoFCPreselectionAction, SoFontNameElement); + SO_ENABLE(SoFCPreselectionAction, SoFontSizeElement); + SO_ENABLE(SoFCPreselectionAction, SoProfileCoordinateElement); + SO_ENABLE(SoFCPreselectionAction, SoProfileElement); + SO_ENABLE(SoFCPreselectionAction, SoSwitchElement); + SO_ENABLE(SoFCPreselectionAction, SoUnitsElement); + SO_ENABLE(SoFCPreselectionAction, SoViewVolumeElement); + SO_ENABLE(SoFCPreselectionAction, SoViewingMatrixElement); + SO_ENABLE(SoFCPreselectionAction, SoViewportRegionElement); @@ -125,28 +125,28 @@ void SoFCHighlightAction::initClass() SO_ACTION_ADD_METHOD(SoPointSet,callDoAction); } -void SoFCHighlightAction::finish() +void SoFCPreselectionAction::finish() { atexit_cleanup(); } -SoFCHighlightAction::SoFCHighlightAction (const SelectionChanges &SelCh) +SoFCPreselectionAction::SoFCPreselectionAction (const SelectionChanges &SelCh) :SelChange(SelCh) { - SO_ACTION_CONSTRUCTOR(SoFCHighlightAction); + SO_ACTION_CONSTRUCTOR(SoFCPreselectionAction); } -SoFCHighlightAction::~SoFCHighlightAction() = default; +SoFCPreselectionAction::~SoFCPreselectionAction() = default; -void SoFCHighlightAction::beginTraversal(SoNode *node) +void SoFCPreselectionAction::beginTraversal(SoNode *node) { traverse(node); } -void SoFCHighlightAction::callDoAction(SoAction *action,SoNode *node) +void SoFCPreselectionAction::callDoAction(SoAction *action,SoNode *node) { node->doAction(action); } @@ -296,7 +296,7 @@ void SoFCEnableSelectionAction::finish() SoFCEnableSelectionAction::SoFCEnableSelectionAction (const SbBool& sel) - : selection(sel) + : enabled(sel) { SO_ACTION_CONSTRUCTOR(SoFCEnableSelectionAction); } @@ -317,7 +317,7 @@ void SoFCEnableSelectionAction::callDoAction(SoAction *action,SoNode *node) // --------------------------------------------------------------- -SO_ACTION_SOURCE(SoFCEnableHighlightAction) +SO_ACTION_SOURCE(SoFCEnablePreselectionAction) /** * The order of the defined SO_ACTION_ADD_METHOD statements is very important. First the base @@ -327,28 +327,28 @@ SO_ACTION_SOURCE(SoFCEnableHighlightAction) * This means that \c SoSwitch must be listed after \c SoGroup and \c SoFCSelection after * \c SoSeparator because both classes inherits the others. */ -void SoFCEnableHighlightAction::initClass() +void SoFCEnablePreselectionAction::initClass() { - SO_ACTION_INIT_CLASS(SoFCEnableHighlightAction,SoAction); + SO_ACTION_INIT_CLASS(SoFCEnablePreselectionAction,SoAction); - SO_ENABLE(SoFCEnableHighlightAction, SoSwitchElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoSwitchElement); SO_ACTION_ADD_METHOD(SoNode,nullAction); - SO_ENABLE(SoFCEnableHighlightAction, SoModelMatrixElement); - SO_ENABLE(SoFCEnableHighlightAction, SoShapeStyleElement); - SO_ENABLE(SoFCEnableHighlightAction, SoComplexityElement); - SO_ENABLE(SoFCEnableHighlightAction, SoComplexityTypeElement); - SO_ENABLE(SoFCEnableHighlightAction, SoCoordinateElement); - SO_ENABLE(SoFCEnableHighlightAction, SoFontNameElement); - SO_ENABLE(SoFCEnableHighlightAction, SoFontSizeElement); - SO_ENABLE(SoFCEnableHighlightAction, SoProfileCoordinateElement); - SO_ENABLE(SoFCEnableHighlightAction, SoProfileElement); - SO_ENABLE(SoFCEnableHighlightAction, SoSwitchElement); - SO_ENABLE(SoFCEnableHighlightAction, SoUnitsElement); - SO_ENABLE(SoFCEnableHighlightAction, SoViewVolumeElement); - SO_ENABLE(SoFCEnableHighlightAction, SoViewingMatrixElement); - SO_ENABLE(SoFCEnableHighlightAction, SoViewportRegionElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoModelMatrixElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoShapeStyleElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoComplexityElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoComplexityTypeElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoCoordinateElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoFontNameElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoFontSizeElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoProfileCoordinateElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoProfileElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoSwitchElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoUnitsElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoViewVolumeElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoViewingMatrixElement); + SO_ENABLE(SoFCEnablePreselectionAction, SoViewportRegionElement); @@ -369,28 +369,28 @@ void SoFCEnableHighlightAction::initClass() SO_ACTION_ADD_METHOD(SoFCSelection,callDoAction); } -void SoFCEnableHighlightAction::finish() +void SoFCEnablePreselectionAction::finish() { atexit_cleanup(); } -SoFCEnableHighlightAction::SoFCEnableHighlightAction (const SbBool& sel) - : highlight(sel) +SoFCEnablePreselectionAction::SoFCEnablePreselectionAction (const SbBool& sel) + : enabled(sel) { - SO_ACTION_CONSTRUCTOR(SoFCEnableHighlightAction); + SO_ACTION_CONSTRUCTOR(SoFCEnablePreselectionAction); } -SoFCEnableHighlightAction::~SoFCEnableHighlightAction() = default; +SoFCEnablePreselectionAction::~SoFCEnablePreselectionAction() = default; -void SoFCEnableHighlightAction::beginTraversal(SoNode *node) +void SoFCEnablePreselectionAction::beginTraversal(SoNode *node) { traverse(node); } -void SoFCEnableHighlightAction::callDoAction(SoAction *action,SoNode *node) +void SoFCEnablePreselectionAction::callDoAction(SoAction *action,SoNode *node) { node->doAction(action); } diff --git a/src/Gui/SoFCSelectionAction.h b/src/Gui/Selection/SoFCSelectionAction.h similarity index 89% rename from src/Gui/SoFCSelectionAction.h rename to src/Gui/Selection/SoFCSelectionAction.h index 7576ca911a..f1c3191056 100644 --- a/src/Gui/SoFCSelectionAction.h +++ b/src/Gui/Selection/SoFCSelectionAction.h @@ -38,17 +38,17 @@ namespace Gui { class SelectionChanges; /** - * The SoFCHighlightAction class is used to inform an SoFCSelection node - * whether an object gets highlighted. + * The SoFCPreselectionAction class is used to inform an SoFCSelection node + * whether an object gets preselected. * @author Jürgen Riegel */ -class GuiExport SoFCHighlightAction : public SoAction +class GuiExport SoFCPreselectionAction : public SoAction { - SO_ACTION_HEADER(SoFCHighlightAction); + SO_ACTION_HEADER(SoFCPreselectionAction); public: - SoFCHighlightAction (const SelectionChanges &SelCh); - ~SoFCHighlightAction() override; + SoFCPreselectionAction (const SelectionChanges &SelCh); + ~SoFCPreselectionAction() override; static void initClass(); static void finish(); @@ -100,7 +100,7 @@ public: SoFCEnableSelectionAction (const SbBool& sel); ~SoFCEnableSelectionAction() override; - SbBool selection; + SbBool enabled; static void initClass(); static void finish(); @@ -113,19 +113,19 @@ private: }; /** - * The SoFCEnableHighlightAction class is used to inform an SoFCSelection node + * The SoFCEnablePreselectionAction class is used to inform an SoFCSelection node * whether preselection is enabled or disabled. * @author Werner Mayer */ -class GuiExport SoFCEnableHighlightAction : public SoAction +class GuiExport SoFCEnablePreselectionAction : public SoAction { - SO_ACTION_HEADER(SoFCEnableHighlightAction); + SO_ACTION_HEADER(SoFCEnablePreselectionAction); public: - SoFCEnableHighlightAction (const SbBool& sel); - ~SoFCEnableHighlightAction() override; + SoFCEnablePreselectionAction (const SbBool& sel); + ~SoFCEnablePreselectionAction() override; - SbBool highlight; + SbBool enabled; static void initClass(); static void finish(); @@ -164,7 +164,7 @@ private: /** * The SoFCHighlightColorAction class is used to inform an SoFCSelection node - * which preselection color is used. + * which highlight color is used. * @author Werner Mayer */ class GuiExport SoFCHighlightColorAction : public SoAction diff --git a/src/Gui/SoFCSelectionContext.cpp b/src/Gui/Selection/SoFCSelectionContext.cpp similarity index 100% rename from src/Gui/SoFCSelectionContext.cpp rename to src/Gui/Selection/SoFCSelectionContext.cpp diff --git a/src/Gui/SoFCSelectionContext.h b/src/Gui/Selection/SoFCSelectionContext.h similarity index 100% rename from src/Gui/SoFCSelectionContext.h rename to src/Gui/Selection/SoFCSelectionContext.h diff --git a/src/Gui/SoFCUnifiedSelection.cpp b/src/Gui/Selection/SoFCUnifiedSelection.cpp similarity index 87% rename from src/Gui/SoFCUnifiedSelection.cpp rename to src/Gui/Selection/SoFCUnifiedSelection.cpp index 719e384139..79460ba148 100644 --- a/src/Gui/SoFCUnifiedSelection.cpp +++ b/src/Gui/Selection/SoFCUnifiedSelection.cpp @@ -100,7 +100,7 @@ void printPreselectionInfo(const char* documentName, double precision); } -SoFullPath * Gui::SoFCUnifiedSelection::currenthighlight = nullptr; +SoFullPath * Gui::SoFCUnifiedSelection::currentHighlightPath = nullptr; // ************************************************************************* @@ -113,17 +113,17 @@ SoFCUnifiedSelection::SoFCUnifiedSelection() { SO_NODE_CONSTRUCTOR(SoFCUnifiedSelection); - SO_NODE_ADD_FIELD(colorHighlight, (SbColor(1.0f, 0.6f, 0.0f))); - SO_NODE_ADD_FIELD(colorSelection, (SbColor(0.1f, 0.8f, 0.1f))); - SO_NODE_ADD_FIELD(highlightMode, (AUTO)); - SO_NODE_ADD_FIELD(selectionMode, (ON)); - SO_NODE_ADD_FIELD(selectionRole, (true)); - SO_NODE_ADD_FIELD(useNewSelection, (true)); + SO_NODE_ADD_FIELD(colorHighlight, (SbColor(1.0f, 0.6f, 0.0f))); + SO_NODE_ADD_FIELD(colorSelection, (SbColor(0.1f, 0.8f, 0.1f))); + SO_NODE_ADD_FIELD(preselectionMode, (AUTO)); + SO_NODE_ADD_FIELD(selectionMode, (ON)); + SO_NODE_ADD_FIELD(selectionEnabled, (true)); + SO_NODE_ADD_FIELD(useNewSelection, (true)); - SO_NODE_DEFINE_ENUM_VALUE(HighlightModes, AUTO); - SO_NODE_DEFINE_ENUM_VALUE(HighlightModes, ON); - SO_NODE_DEFINE_ENUM_VALUE(HighlightModes, OFF); - SO_NODE_SET_SF_ENUM_TYPE (highlightMode, HighlightModes); + SO_NODE_DEFINE_ENUM_VALUE(PreselectionModes, AUTO); + SO_NODE_DEFINE_ENUM_VALUE(PreselectionModes, ON); + SO_NODE_DEFINE_ENUM_VALUE(PreselectionModes, OFF); + SO_NODE_SET_SF_ENUM_TYPE (preselectionMode, PreselectionModes); // Documentation of SoFullPath: // Since the SoFullPath is derived from SoPath and contains no private data, you can cast SoPath instances to the SoFullPath type. @@ -144,9 +144,9 @@ SoFCUnifiedSelection::~SoFCUnifiedSelection() { // If we're being deleted and we're the current highlight, // NULL out that variable - if (currenthighlight) { - currenthighlight->unref(); - currenthighlight = nullptr; + if (currentHighlightPath) { + currentHighlightPath->unref(); + currentHighlightPath = nullptr; } if (detailPath) { detailPath->unref(); @@ -167,17 +167,16 @@ void SoFCUnifiedSelection::finish() } bool SoFCUnifiedSelection::hasHighlight() { - return currenthighlight != nullptr; + return currentHighlightPath != nullptr; } void SoFCUnifiedSelection::applySettings() { float transparency; ParameterGrp::handle hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("View"); - bool enablePre = hGrp->GetBool("EnablePreselection", true); - bool enableSel = hGrp->GetBool("EnableSelection", true); - if (!enablePre) { - this->highlightMode = SoFCUnifiedSelection::OFF; + bool enablePreselection = hGrp->GetBool("EnablePreselection", true); + if (!enablePreselection) { + this->preselectionMode = SoFCUnifiedSelection::OFF; } else { // Search for a user defined value with the current color as default @@ -188,7 +187,8 @@ void SoFCUnifiedSelection::applySettings() this->colorHighlight.setValue(highlightColor); } - if (!enableSel) { + bool enableSelection = hGrp->GetBool("EnableSelection", true); + if (!enableSelection) { this->selectionMode = SoFCUnifiedSelection::OFF; } else { @@ -312,19 +312,19 @@ SoFCUnifiedSelection::getPickedList(SoHandleEventAction* action, bool singlePick void SoFCUnifiedSelection::doAction(SoAction *action) { - if (action->getTypeId() == SoFCEnableHighlightAction::getClassTypeId()) { - auto preaction = static_cast(action); - if (preaction->highlight) { - this->highlightMode = SoFCUnifiedSelection::AUTO; + if (action->getTypeId() == SoFCEnablePreselectionAction::getClassTypeId()) { + auto enablePreselectionAction = static_cast(action); + if (enablePreselectionAction->enabled) { + this->preselectionMode = SoFCUnifiedSelection::AUTO; } else { - this->highlightMode = SoFCUnifiedSelection::OFF; + this->preselectionMode = SoFCUnifiedSelection::OFF; } } if (action->getTypeId() == SoFCEnableSelectionAction::getClassTypeId()) { - auto selaction = static_cast(action); - if (selaction->selection) { + auto enableSelectionAction = static_cast(action); + if (enableSelectionAction->enabled) { this->selectionMode = SoFCUnifiedSelection::ON; } else { @@ -333,52 +333,52 @@ void SoFCUnifiedSelection::doAction(SoAction *action) } if (action->getTypeId() == SoFCSelectionColorAction::getClassTypeId()) { - auto colaction = static_cast(action); - this->colorSelection = colaction->selectionColor; + auto selectionColorAction = static_cast(action); + this->colorSelection = selectionColorAction->selectionColor; } if (action->getTypeId() == SoFCHighlightColorAction::getClassTypeId()) { - auto colaction = static_cast(action); - this->colorHighlight = colaction->highlightColor; + auto highlightColorAction = static_cast(action); + this->colorHighlight = highlightColorAction->highlightColor; } - if (action->getTypeId() == SoFCHighlightAction::getClassTypeId()) { - auto hilaction = static_cast(action); - // Do not clear currently highlighted object when setting new pre-selection - if (!setPreSelection && hilaction->SelChange.Type == SelectionChanges::RmvPreselect) { - if (currenthighlight) { - SoHighlightElementAction hlAction; - hlAction.apply(currenthighlight); - currenthighlight->unref(); - currenthighlight = nullptr; + if (action->getTypeId() == SoFCPreselectionAction::getClassTypeId()) { + auto preselectAction = static_cast(action); + // Do not clear currently preselected object when setting new pre-selection + if (!setPreSelection && preselectAction->SelChange.Type == SelectionChanges::RmvPreselect) { + if (currentHighlightPath) { + SoHighlightElementAction highlightAction; + highlightAction.apply(currentHighlightPath); + currentHighlightPath->unref(); + currentHighlightPath = nullptr; } } - else if (highlightMode.getValue() != OFF - && hilaction->SelChange.Type == SelectionChanges::SetPreselect) { - if (currenthighlight) { - SoHighlightElementAction hlAction; - hlAction.apply(currenthighlight); - currenthighlight->unref(); - currenthighlight = nullptr; + else if (preselectionMode.getValue() != OFF + && preselectAction->SelChange.Type == SelectionChanges::SetPreselect) { + if (currentHighlightPath) { + SoHighlightElementAction highlightAction; + highlightAction.apply(currentHighlightPath); + currentHighlightPath->unref(); + currentHighlightPath = nullptr; } - App::Document* doc = App::GetApplication().getDocument(hilaction->SelChange.pDocName); - App::DocumentObject* obj = doc->getObject(hilaction->SelChange.pObjectName); + App::Document* doc = App::GetApplication().getDocument(preselectAction->SelChange.pDocName); + App::DocumentObject* obj = doc->getObject(preselectAction->SelChange.pObjectName); ViewProvider*vp = Application::Instance->getViewProvider(obj); - SoDetail* detail = vp->getDetail(hilaction->SelChange.pSubName); + SoDetail* detail = vp->getDetail(preselectAction->SelChange.pSubName); - SoHighlightElementAction hlAction; - hlAction.setHighlighted(true); - hlAction.setColor(this->colorHighlight.getValue()); - hlAction.setElement(detail); - hlAction.apply(vp->getRoot()); + SoHighlightElementAction highlightAction; + highlightAction.setHighlighted(true); + highlightAction.setColor(this->colorHighlight.getValue()); + highlightAction.setElement(detail); + highlightAction.apply(vp->getRoot()); delete detail; SoSearchAction sa; sa.setNode(vp->getRoot()); sa.apply(vp->getRoot()); - currenthighlight = static_cast(sa.getPath()->copy()); - currenthighlight->ref(); + currentHighlightPath = static_cast(sa.getPath()->copy()); + currentHighlightPath->ref(); } if (useNewSelection.getValue()) @@ -386,30 +386,30 @@ void SoFCUnifiedSelection::doAction(SoAction *action) } if (action->getTypeId() == SoFCSelectionAction::getClassTypeId()) { - auto selaction = static_cast(action); + auto selectionAction = static_cast(action); if(selectionMode.getValue() == ON - && (selaction->SelChange.Type == SelectionChanges::AddSelection - || selaction->SelChange.Type == SelectionChanges::RmvSelection)) + && (selectionAction->SelChange.Type == SelectionChanges::AddSelection + || selectionAction->SelChange.Type == SelectionChanges::RmvSelection)) { // selection changes inside the 3d view are handled in handleEvent() - App::Document* doc = App::GetApplication().getDocument(selaction->SelChange.pDocName); - App::DocumentObject* obj = doc->getObject(selaction->SelChange.pObjectName); + App::Document* doc = App::GetApplication().getDocument(selectionAction->SelChange.pDocName); + App::DocumentObject* obj = doc->getObject(selectionAction->SelChange.pObjectName); ViewProvider*vp = Application::Instance->getViewProvider(obj); if (vp && (useNewSelection.getValue()||vp->useNewSelectionModel()) && vp->isSelectable()) { SoDetail *detail = nullptr; detailPath->truncate(0); - auto subName = selaction->SelChange.pSubName; + auto subName = selectionAction->SelChange.pSubName; App::ElementNamePair elementName;; App::GeoFeature::resolveElement(obj, subName, elementName); if (Data::isMappedElement(subName) && !elementName.oldName.empty()) { // If we have a shortened element name subName = elementName.oldName.c_str(); // use it. } - if(!selaction->SelChange.pSubName || !selaction->SelChange.pSubName[0] || + if(!selectionAction->SelChange.pSubName || !selectionAction->SelChange.pSubName[0] || vp->getDetailPath(subName,detailPath,true,detail)) { SoSelectionElementAction::Type type = SoSelectionElementAction::None; - if (selaction->SelChange.Type == SelectionChanges::AddSelection) { + if (selectionAction->SelChange.Type == SelectionChanges::AddSelection) { if (detail) type = SoSelectionElementAction::Append; else @@ -434,13 +434,13 @@ void SoFCUnifiedSelection::doAction(SoAction *action) delete detail; } } - else if (selaction->SelChange.Type == SelectionChanges::ClrSelection) { + else if (selectionAction->SelChange.Type == SelectionChanges::ClrSelection) { SoSelectionElementAction selectionAction(SoSelectionElementAction::None); for(int i=0;igetNumChildren();++i) selectionAction.apply(this->getChild(i)); } else if(selectionMode.getValue() == ON - && selaction->SelChange.Type == SelectionChanges::SetSelection) { + && selectionAction->SelChange.Type == SelectionChanges::SetSelection) { std::vector vps; if (this->pcDocument) vps = this->pcDocument->getViewProvidersOfType(ViewProviderDocumentObject::getClassTypeId()); @@ -459,22 +459,22 @@ void SoFCUnifiedSelection::doAction(SoAction *action) } } } - else if (selaction->SelChange.Type == SelectionChanges::SetPreselectSignal) { + else if (selectionAction->SelChange.Type == SelectionChanges::SetPreselectSignal) { // selection changes inside the 3d view are handled in handleEvent() - App::Document* doc = App::GetApplication().getDocument(selaction->SelChange.pDocName); - App::DocumentObject* obj = doc->getObject(selaction->SelChange.pObjectName); + App::Document* doc = App::GetApplication().getDocument(selectionAction->SelChange.pDocName); + App::DocumentObject* obj = doc->getObject(selectionAction->SelChange.pObjectName); ViewProvider*vp = Application::Instance->getViewProvider(obj); if (vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()) && (useNewSelection.getValue()||vp->useNewSelectionModel()) && vp->isSelectable()) { detailPath->truncate(0); SoDetail *det = nullptr; - if(vp->getDetailPath(selaction->SelChange.pSubName,detailPath,true,det)) { - setHighlight(detailPath,det,static_cast(vp), - selaction->SelChange.pSubName, - selaction->SelChange.x, - selaction->SelChange.y, - selaction->SelChange.z); + if(vp->getDetailPath(selectionAction->SelChange.pSubName,detailPath,true,det)) { + setPreselect(detailPath,det,static_cast(vp), + selectionAction->SelChange.pSubName, + selectionAction->SelChange.x, + selectionAction->SelChange.y, + selectionAction->SelChange.z); } delete det; } @@ -487,15 +487,16 @@ void SoFCUnifiedSelection::doAction(SoAction *action) inherited::doAction( action ); } -bool SoFCUnifiedSelection::setHighlight(const PickedInfo &info) { +bool SoFCUnifiedSelection::setPreselect(const PickedInfo &info) { if(!info.pp) - return setHighlight(nullptr,nullptr,nullptr,nullptr,0.0,0.0,0.0); + return setPreselect(nullptr,nullptr,nullptr,nullptr,0.0,0.0,0.0); + const auto &pt = info.pp->getPoint(); - return setHighlight(static_cast(info.pp->getPath()), + return setPreselect(static_cast(info.pp->getPath()), info.pp->getDetail(), info.vpd, info.element.c_str(), pt[0],pt[1],pt[2]); } -bool SoFCUnifiedSelection::setHighlight(SoFullPath *path, const SoDetail *det, +bool SoFCUnifiedSelection::setPreselect(SoFullPath *path, const SoDetail *det, ViewProviderDocumentObject *vpd, const char *element, float x, float y, float z) { Base::FlagToggler flag(setPreSelection); @@ -513,32 +514,32 @@ bool SoFCUnifiedSelection::setHighlight(SoFullPath *path, const SoDetail *det, int ret = Gui::Selection().setPreselect(docname,objname,element,x,y,z); - if(ret<0 && currenthighlight) + if(ret<0 && currentHighlightPath) return true; if(ret) { - if (currenthighlight) { + if (currentHighlightPath) { SoHighlightElementAction action; action.setHighlighted(false); - action.apply(currenthighlight); - currenthighlight->unref(); - currenthighlight = nullptr; + action.apply(currentHighlightPath); + currentHighlightPath->unref(); + currentHighlightPath = nullptr; } - currenthighlight = static_cast(path->copy()); - currenthighlight->ref(); + currentHighlightPath = static_cast(path->copy()); + currentHighlightPath->ref(); highlighted = true; } } - if(currenthighlight) { + if(currentHighlightPath) { SoHighlightElementAction action; action.setHighlighted(highlighted); action.setColor(this->colorHighlight.getValue()); action.setElement(det); - action.apply(currenthighlight); + action.apply(currentHighlightPath); if(!highlighted) { - currenthighlight->unref(); - currenthighlight = nullptr; + currentHighlightPath->unref(); + currentHighlightPath = nullptr; Selection().rmvPreselect(); } this->touch(); @@ -597,7 +598,7 @@ bool SoFCUnifiedSelection::setSelection(const std::vector &infos, bo auto pPath = static_cast(pp->getPath()); const auto &pt = pp->getPoint(); SoSelectionElementAction::Type type = SoSelectionElementAction::None; - auto mymode = static_cast(this->highlightMode.getValue()); + auto preselectionMode = static_cast(this->preselectionMode.getValue()); static char buf[513]; auto subName = info.element; std::string objectName = objname; @@ -618,7 +619,7 @@ bool SoFCUnifiedSelection::setSelection(const std::vector &infos, bo return false; } - if (ok && mymode == OFF) { + if (ok && preselectionMode == OFF) { snprintf(buf, 512, "Selected: %s.%s.%s (%g, %g, %g)", docname, objname, info.element.c_str(), fabs(pt[0]) > 1e-7 ? pt[0] : 0.0, fabs(pt[1]) > 1e-7 ? pt[1] : 0.0, fabs(pt[2]) > 1e-7 ? pt[2] : 0.0); @@ -701,7 +702,7 @@ bool SoFCUnifiedSelection::setSelection(const std::vector &infos, bo if (ok) type = hasNext ? SoSelectionElementAction::All : SoSelectionElementAction::Append; - if (mymode == OFF) { + if (preselectionMode == OFF) { snprintf(buf, 512, "Selected: %s.%s.%s (%g, %g, %g)", docname, objectName.c_str(), subName.c_str(), fabs(pt[0]) > 1e-7 ? pt[0] : 0.0, fabs(pt[1]) > 1e-7 ? pt[1] : 0.0, fabs(pt[2]) > 1e-7 ? pt[2] : 0.0); @@ -729,38 +730,29 @@ void SoFCUnifiedSelection::handleEvent(SoHandleEventAction * action) { // If off then don't handle this event - if (!selectionRole.getValue()) { + if (!selectionEnabled.getValue()) { inherited::handleEvent(action); return; } - auto mymode = static_cast(this->highlightMode.getValue()); + auto preselectionMode = static_cast(this->preselectionMode.getValue()); const SoEvent * event = action->getEvent(); - // If we don't need to pick for locate highlighting, - // then just behave as separator and return. - // NOTE: we still have to pick for ON even though we don't have - // to re-render, because the app needs to be notified as the mouse - // goes over locate highlight nodes. - //if (highlightMode.getValue() == OFF) { - // inherited::handleEvent( action ); - // return; - //} - // - // If this is a mouseMotion event, then check for locate highlighting + // If this is a mouseMotion event, then check for preselected entities. // - if (event->isOfType(SoLocation2Event::getClassTypeId())) { + bool isMouseMotionEvent = event->isOfType(SoLocation2Event::getClassTypeId()); + if (isMouseMotionEvent) { // NOTE: If preselection is off then we do not check for a picked point because otherwise this search may slow // down extremely the system on really big data sets. In this case we just check for a picked point if the data // set has been selected. - if (mymode == AUTO || mymode == ON) { + if (preselectionMode == AUTO || preselectionMode == ON) { // check to see if the mouse is over our geometry... auto infos = this->getPickedList(action,true); if(!infos.empty()) - setHighlight(infos[0]); + setPreselect(infos[0]); else { - setHighlight(PickedInfo()); + setPreselect(PickedInfo()); if (this->preSelection > 0) { this->preSelection = 0; // touch() makes sure to call GLRenderBelowPath so that the cursor can be updated @@ -1652,9 +1644,9 @@ bool SoFCSelectionRoot::doActionPrivate(Stack &stack, SoAction *action) { } if(action->isOfType(SoHighlightElementAction::getClassTypeId())) { - auto hlAction = static_cast(action); - if(hlAction->isHighlighted()) { - if(hlAction->getElement()) { + auto highlightAction = static_cast(action); + if(highlightAction->isHighlighted()) { + if(highlightAction->getElement()) { auto ctx = getActionContext(action,this,SelContextPtr(),false); if(ctx && ctx->hlAll) { ctx->hlAll = false; @@ -1664,7 +1656,7 @@ bool SoFCSelectionRoot::doActionPrivate(Stack &stack, SoAction *action) { auto ctx = getActionContext(action,this,SelContextPtr()); assert(ctx); ctx->hlAll = true; - ctx->hlColor = hlAction->getColor(); + ctx->hlColor = highlightAction->getColor(); touch(); return false; } diff --git a/src/Gui/SoFCUnifiedSelection.h b/src/Gui/Selection/SoFCUnifiedSelection.h similarity index 91% rename from src/Gui/SoFCUnifiedSelection.h rename to src/Gui/Selection/SoFCUnifiedSelection.h index c426c1907c..ec5c8c55c8 100644 --- a/src/Gui/SoFCUnifiedSelection.h +++ b/src/Gui/Selection/SoFCUnifiedSelection.h @@ -34,7 +34,7 @@ #include #include "SoFCSelectionContext.h" -#include "View3DInventorViewer.h" +#include "../View3DInventorViewer.h" class SoFullPath; @@ -50,7 +50,7 @@ class ViewProviderDocumentObject; /** Unified Selection node * This is the new selection node for the 3D Viewer which will * gradually remove all the low level selection nodes in the view - * provider. The handling of the highlighting and the selection will + * provider. The handling of the preselection and the selection will * be unified here. * \author Jürgen Riegel */ @@ -65,7 +65,7 @@ public: SoFCUnifiedSelection(); void applySettings(); - enum HighlightModes { + enum SelectionModes { AUTO, ON, OFF }; @@ -74,18 +74,15 @@ public: SoSFColor colorHighlight; SoSFColor colorSelection; - SoSFEnum highlightMode; + SoSFEnum preselectionMode; SoSFEnum selectionMode; - SoSFBool selectionRole; + SoSFBool selectionEnabled; SoSFBool useNewSelection; void doAction(SoAction *action) override; - //virtual void GLRender(SoGLRenderAction * action); void handleEvent(SoHandleEventAction * action) override; void GLRenderBelowPath(SoGLRenderAction * action) override; - //virtual void GLRenderInPath(SoGLRenderAction * action); - //static void turnOffCurrentHighlight(SoGLRenderAction * action); static bool hasHighlight(); @@ -93,14 +90,8 @@ public: protected: ~SoFCUnifiedSelection() override; - //virtual void redrawHighlighted(SoAction * act, SbBool flag); - //virtual SbBool readInstance(SoInput * in, unsigned short flags); private: - //static void turnoffcurrent(SoAction * action); - //void setOverride(SoGLRenderAction * action); - //SbBool isHighlighted(SoAction *action); - //SbBool preRender(SoGLRenderAction *act, GLint &oldDepthFunc); static int getPriority(const SoPickedPoint* p); struct PickedInfo { @@ -109,8 +100,8 @@ private: std::string element; }; - bool setHighlight(const PickedInfo &); - bool setHighlight(SoFullPath *path, const SoDetail *det, + bool setPreselect(const PickedInfo &); + bool setPreselect(SoFullPath *path, const SoDetail *det, ViewProviderDocumentObject *vpd, const char *element, float x, float y, float z); bool setSelection(const std::vector &, bool ctrlDown=false); @@ -118,7 +109,7 @@ private: Gui::Document *pcDocument{nullptr}; - static SoFullPath * currenthighlight; + static SoFullPath * currentHighlightPath; SoFullPath * detailPath; SbBool setPreSelection; diff --git a/src/Gui/lex.SelectionFilter.c b/src/Gui/Selection/lex.SelectionFilter.c similarity index 100% rename from src/Gui/lex.SelectionFilter.c rename to src/Gui/Selection/lex.SelectionFilter.c diff --git a/src/Gui/SoFCCSysDragger.cpp b/src/Gui/SoFCCSysDragger.cpp index 3d4ad6b650..39130d3b9e 100644 --- a/src/Gui/SoFCCSysDragger.cpp +++ b/src/Gui/SoFCCSysDragger.cpp @@ -357,7 +357,7 @@ void TDragger::drag() Base::Unit::Length); QString message = - QString::fromLatin1("%1 %2").arg(QObject::tr("Translation:"), QString::fromStdString(quantity.getUserString())); + QStringLiteral("%1 %2").arg(QObject::tr("Translation:"), QString::fromStdString(quantity.getUserString())); getMainWindow()->showMessage(message, 3000); } @@ -642,7 +642,7 @@ void TPlanarDragger::drag() * translationIncrement.getValue(), Base::Unit::Length); - QString message = QString::fromLatin1("%1 %2, %3") + QString message = QStringLiteral("%1 %2, %3") .arg(QObject::tr("Translation XY:"), QString::fromStdString(quantityX.getUserString()), QString::fromStdString(quantityY.getUserString())); @@ -970,7 +970,7 @@ void RDragger::drag() Base::Unit::Angle); QString message = - QString::fromLatin1("%1 %2").arg(QObject::tr("Rotation:"), QString::fromStdString(quantity.getUserString())); + QStringLiteral("%1 %2").arg(QObject::tr("Rotation:"), QString::fromStdString(quantity.getUserString())); getMainWindow()->showMessage(message, 3000); } diff --git a/src/Gui/SoFCColorGradient.cpp b/src/Gui/SoFCColorGradient.cpp index e0f4ee8321..706d067a14 100644 --- a/src/Gui/SoFCColorGradient.cpp +++ b/src/Gui/SoFCColorGradient.cpp @@ -39,7 +39,7 @@ #include #include "SoFCColorGradient.h" #include "SoTextLabel.h" -#include "DlgSettingsColorGradientImp.h" +#include "Dialogs/DlgSettingsColorGradientImp.h" #include "MainWindow.h" #include "MDIView.h" #include "ViewProvider.h" diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index d762615c11..960270f208 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -50,8 +50,8 @@ #include "SoFCDB.h" #include "Camera.h" #include "Flag.h" -#include "GestureNavigationStyle.h" -#include "NavigationStyle.h" +#include "Navigation/GestureNavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "SelectionObject.h" #include "SoDevicePixelRatioElement.h" #include "SoFCColorBar.h" @@ -107,13 +107,13 @@ void Gui::SoFCDB::init() SoFCBoundingBox ::initClass(); SoFCSelection ::initClass(); SoFCUnifiedSelection ::initClass(); - SoFCHighlightAction ::initClass(); + SoFCPreselectionAction ::initClass(); SoFCSelectionAction ::initClass(); SoFCDocumentAction ::initClass(); SoGLWidgetNode ::initClass(); SoGLVBOActivatedElement ::initClass(); SoFCEnableSelectionAction ::initClass(); - SoFCEnableHighlightAction ::initClass(); + SoFCEnablePreselectionAction ::initClass(); SoFCSelectionColorAction ::initClass(); SoFCHighlightColorAction ::initClass(); SoFCDocumentObjectAction ::initClass(); @@ -226,12 +226,12 @@ void Gui::SoFCDB::finish() SoFCBackgroundGradient ::finish(); SoFCBoundingBox ::finish(); SoFCSelection ::finish(); - SoFCHighlightAction ::finish(); + SoFCPreselectionAction ::finish(); SoFCSelectionAction ::finish(); SoFCDocumentAction ::finish(); SoFCDocumentObjectAction ::finish(); SoFCEnableSelectionAction ::finish(); - SoFCEnableHighlightAction ::finish(); + SoFCEnablePreselectionAction ::finish(); SoFCSelectionColorAction ::finish(); SoUpdateVBOAction ::finish(); SoFCHighlightColorAction ::finish(); diff --git a/src/Gui/SpinBox.cpp b/src/Gui/SpinBox.cpp index 2d65a55d17..cd11ec052c 100644 --- a/src/Gui/SpinBox.cpp +++ b/src/Gui/SpinBox.cpp @@ -38,7 +38,7 @@ #include "SpinBox.h" #include "Command.h" -#include "DlgExpressionInput.h" +#include "Dialogs/DlgExpressionInput.h" #include "QuantitySpinBox_p.h" @@ -68,7 +68,7 @@ void ExpressionSpinBox::bind(const App::ObjectIdentifier &_path) void ExpressionSpinBox::showIcon() { int frameWidth = spinbox->style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth); - lineedit->setStyleSheet(QString::fromLatin1("QLineEdit { padding-right: %1px } ").arg(iconLabel->sizeHint().width() + frameWidth + 1)); + lineedit->setStyleSheet(QStringLiteral("QLineEdit { padding-right: %1px } ").arg(iconLabel->sizeHint().width() + frameWidth + 1)); iconLabel->show(); } diff --git a/src/Gui/SplashScreen.cpp b/src/Gui/SplashScreen.cpp index 74f6768048..92bac0563c 100644 --- a/src/Gui/SplashScreen.cpp +++ b/src/Gui/SplashScreen.cpp @@ -260,7 +260,7 @@ QPixmap SplashScreen::splashImage() { // search in the UserAppData dir as very first QPixmap splash_image; - QFileInfo fi(QString::fromLatin1("images:splash_image.png")); + QFileInfo fi(QStringLiteral("images:splash_image.png")); if (fi.isFile() && fi.exists()) { splash_image.load(fi.filePath(), "PNG"); } @@ -316,7 +316,7 @@ QPixmap SplashScreen::splashImage() QString minor = QString::fromStdString(App::Application::Config()["BuildVersionMinor"]); QString point = QString::fromStdString(App::Application::Config()["BuildVersionPoint"]); QString suffix = QString::fromStdString(App::Application::Config()["BuildVersionSuffix"]); - QString version = QString::fromLatin1("%1.%2.%3%4").arg(major, minor, point, suffix); + QString version = QStringLiteral("%1.%2.%3%4").arg(major, minor, point, suffix); QString position, fontFamily; std::map::const_iterator te = diff --git a/src/Gui/SplitView3DInventor.cpp b/src/Gui/SplitView3DInventor.cpp index 09fc08eec1..94e7ec4a72 100644 --- a/src/Gui/SplitView3DInventor.cpp +++ b/src/Gui/SplitView3DInventor.cpp @@ -36,7 +36,7 @@ #include "Application.h" #include "Camera.h" #include "Document.h" -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "SoFCSelectionAction.h" #include "View3DInventorViewer.h" #include "View3DPy.h" diff --git a/src/Gui/StartupProcess.cpp b/src/Gui/StartupProcess.cpp index 0e1a011209..3d7141cbe3 100644 --- a/src/Gui/StartupProcess.cpp +++ b/src/Gui/StartupProcess.cpp @@ -37,7 +37,7 @@ #include "StartupProcess.h" #include "Application.h" #include "AutoSaver.h" -#include "DlgCheckableMessageBox.h" +#include "Dialogs/DlgCheckableMessageBox.h" #include "FileDialog.h" #include "GuiApplication.h" #include "MainWindow.h" @@ -135,7 +135,7 @@ void StartupProcess::setStyleSheetPaths() (App::Application::getUserAppDataDir() + "Gui/Stylesheets/").c_str()) << QString::fromUtf8((App::Application::getResourceDir() + "Gui/Stylesheets/").c_str()) << QLatin1String(":/stylesheets"); - QDir::setSearchPaths(QString::fromLatin1("qss"), qssPaths); + QDir::setSearchPaths(QStringLiteral("qss"), qssPaths); // setup the search paths for Qt overlay style sheets QStringList qssOverlayPaths; qssOverlayPaths << QString::fromUtf8((App::Application::getUserAppDataDir() @@ -152,7 +152,7 @@ void StartupProcess::setImagePaths() imagePaths << QString::fromUtf8((App::Application::getUserAppDataDir() + "Gui/images").c_str()) << QString::fromUtf8((App::Application::getUserAppDataDir() + "pixmaps").c_str()) << QLatin1String(":/icons"); - QDir::setSearchPaths(QString::fromLatin1("images"), imagePaths); + QDir::setSearchPaths(QStringLiteral("images"), imagePaths); } void StartupProcess::registerEventType() @@ -165,7 +165,7 @@ void StartupProcess::setThemePaths() { #if !defined(Q_OS_LINUX) QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() - << QString::fromLatin1(":/icons/FreeCAD-default")); + << QStringLiteral(":/icons/FreeCAD-default")); #endif ParameterGrp::handle hTheme = App::GetApplication().GetParameterGroupByPath( diff --git a/src/Gui/Stylesheets/FreeCAD Dark.qss b/src/Gui/Stylesheets/FreeCAD Dark.qss index 282bd523e3..0326a321b7 100644 --- a/src/Gui/Stylesheets/FreeCAD Dark.qss +++ b/src/Gui/Stylesheets/FreeCAD Dark.qss @@ -416,7 +416,7 @@ QRadioButton::indicator { border-image: none; width: 14px; height: 14px; - image:url(qss:images_classic/Radio-unchecked-white.png); + image:url(qss:images_classic/radio-unchecked-white.png); } QRadioButton::indicator:unchecked { @@ -430,14 +430,14 @@ QRadioButton::indicator:unchecked:disabled { border-image: none; width: 14px; height: 14px; - image:url(qss:images_classic/Radio-unchecked-lightgray.png); + image:url(qss:images_classic/radio-unchecked-lightgray.png); } QRadioButton::indicator:checked { border-image: none; width: 14px; height: 14px; - image:url(qss:images_classic/Radio-checked-white.png); + image:url(qss:images_classic/radio-checked-white.png); } QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:pressed { @@ -448,7 +448,7 @@ QRadioButton::indicator:checked:disabled { border-image: none; width: 14px; height: 14px; - image:url(qss:images_classic/Radio-checked-lightgray.png); + image:url(qss:images_classic/radio-checked-lightgray.png); } /* QMenuBar --------------------------------------------------------------- @@ -462,6 +462,11 @@ QMenuBar { selection-background-color: @ThemeAccentColor1; } +QMenuBar:disabled, +QMenuBar::item:disabled{ + color: #adadad; +} + QMenuBar:focus { border: 1px solid @ThemeAccentColor2; } @@ -512,6 +517,10 @@ QMenu::item { border: 0px transparent #020202; } +QMenu::item:disabled { + color: #adadad; +} + QMenu::item:selected { color: white; background-color: @ThemeAccentColor1; @@ -545,7 +554,7 @@ QMenu::icon:checked { /* appearance of a 'checked' icon */ border-radius: 0px; } QMenu::indicator:non-exclusive:unchecked { - image: url(qss:images_classic/checkbox-Empty-white.png); + image: url(qss:images_classic/checkbox-empty-white.png); } QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:unchecked:focus, QMenu::indicator:non-exclusive:unchecked:pressed { @@ -554,7 +563,7 @@ QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:u } QMenu::indicator:non-exclusive:unchecked:disabled { - image: url(qss:images_classic/checkbox-Empty-lightgray.png); + image: url(qss:images_classic/checkbox-empty-lightgray.png); } QMenu::indicator:non-exclusive:checked { @@ -590,35 +599,35 @@ QMenu::indicator:exclusive:unchecked:hover, QMenu::indicator:exclusive:unchecked border: none; outline: none; background-color: @ThemeAccentColor1; - image: url(qss:images_classic/checkbox-Empty-white.png); + image: url(qss:images_classic/checkbox-empty-white.png); } QMenu::indicator:exclusive:unchecked:disabled { - image: url(qss:images_classic/checkbox-Empty-white.png); + image: url(qss:images_classic/checkbox-empty-white.png); } QMenu::indicator:exclusive:checked { border: none; outline: none; - image: url(qss:images_classic/Radio-checked-white.png); + image: url(qss:images_classic/radio-checked-white.png); } QMenu::indicator:exclusive:checked:hover, QMenu::indicator:exclusive:checked:focus, QMenu::indicator:exclusive:checked:pressed { border: none; outline: none; background-color: @ThemeAccentColor1; - image: url(qss:images_classic/checkbox-Empty-white.png); + image: url(qss:images_classic/checkbox-empty-white.png); } QMenu::indicator:exclusive:checked:disabled { outline: none; - image: url(qss:images_classic/Radio-checked-white.png); + image: url(qss:images_classic/radio-checked-white.png); } QMenu::right-arrow { margin: 5px; padding-left: 12px; - image:url(qss:images_classic/Arrow-right-white.png); + image:url(qss:images_classic/arrow-right-white.png); height: 8px; width: 8px; background-color: transparent; @@ -730,7 +739,7 @@ QScrollBar::handle:vertical:focus { QScrollBar::add-line:horizontal { margin: 6px 6px; - image: url(qss:images_classic/Arrow-right-lightgray.png); + image: url(qss:images_classic/arrow-right-lightgray.png); height: 8px; width: 4px; subcontrol-position: right; @@ -738,7 +747,7 @@ QScrollBar::add-line:horizontal { } QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { - image: url(qss:images_classic/Arrow-right-white.png); + image: url(qss:images_classic/arrow-right-white.png); height: 8px; width: 4px; subcontrol-position: right; @@ -747,7 +756,7 @@ QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { QScrollBar::add-line:vertical { margin: 6px 6px; - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); height: 4px; width: 8px; subcontrol-position: bottom; @@ -755,7 +764,7 @@ QScrollBar::add-line:vertical { } QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { - image: url(qss:images_classic/Arrow-down-white.png); + image: url(qss:images_classic/arrow-down-white.png); height: 4px; width: 8px; subcontrol-position: bottom; @@ -764,7 +773,7 @@ QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { QScrollBar::sub-line:horizontal { margin: 6px 6px; - image: url(qss:images_classic/Arrow-left-lightgray.png); + image: url(qss:images_classic/arrow-left-lightgray.png); height: 8px; width: 4px; subcontrol-position: left; @@ -772,7 +781,7 @@ QScrollBar::sub-line:horizontal { } QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { - image: url(qss:images_classic/Arrow-left-white.png); + image: url(qss:images_classic/arrow-left-white.png); height: 8px; width: 4px; subcontrol-position: left; @@ -781,7 +790,7 @@ QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { QScrollBar::sub-line:vertical { margin: 6px 6px; - image: url(qss:images_classic/Arrow-up-lightgray.png); + image: url(qss:images_classic/arrow-up-lightgray.png); height: 4px; width: 8px; subcontrol-position: top; @@ -789,7 +798,7 @@ QScrollBar::sub-line:vertical { } QScrollBar::sub-line:vertical:hover, QScrollBar::sub-line:vertical:on { - image: url(qss:images_classic/Arrow-up-white.png); + image: url(qss:images_classic/arrow-up-white.png); height: 4px; width: 8px; subcontrol-position: top; @@ -880,7 +889,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar --------------------------------------------------------------------------- */ QToolBar { - background-color: #333333; + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #151515, stop:0.03 #333333,stop:0.97 #303030, stop:1 #151515); /* border: 1px solid #020202; */ /* font-weight: bold; */ } @@ -892,16 +901,22 @@ QToolBar:only-one { } QToolBar:horizontal { - border-bottom: 1px solid #020202; padding-top: 3px; - padding-left: 4px; + padding-left: 3px; + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #151515, stop:0.03 #333333,stop:0.97 #303030, stop:1 #151515); +} + +/* fix background color for toolbars that are the on menubar. */ +QToolBar:only-one { + background-color: transparent; + border:0px; + /* margin-top: -3px; */ } QToolBar:vertical { - border-left: 1px solid #020202; - border-right: 1px solid #020202; - padding-top: 4px; + padding-top: 3px; padding-left: 3px; + background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #151515, stop:0.02 #333333,stop:0.98 #303030, stop:1 #151515); } QToolBar:disabled { @@ -909,34 +924,63 @@ QToolBar:disabled { QToolBar::handle:horizontal { width: 8px; - image: url(qss:images_classic/Hmovetoolbar-lightgray.png); + image: url(qss:images_classic/hmovetoolbar-lightgray.png); } QToolBar::handle:vertical { height: 8px; - image: url(qss:images_classic/Vmovetoolbar-lightgray.png); + image: url(qss:images_classic/vmovetoolbar-lightgray.png); } QToolBar::handle:horizontal:hover { width: 8px; - image: url(qss:images_classic/Hmovetoolbar-white.png); + image: url(qss:images_classic/hmovetoolbar-white.png); } QToolBar::handle:vertical:hover { height: 8px; - image: url(qss:images_classic/Vmovetoolbar-white.png); + image: url(qss:images_classic/vmovetoolbar-white.png); } QToolBar::separator:horizontal { width: 2px; padding: 0px 3px; - image: url(qss:images_classic/Hsepartoolbar-Darkgray.png); + image: url(qss:images_classic/hsepartoolbar-darkgray.png); } QToolBar::separator:vertical { height: 2px; padding: 3px 0px; - image: url(qss:images_classic/Vsepartoolbar-Darkgray.png); + image: url(qss:images_classic/vsepartoolbar-darkgray.png); +} + +/* undo button */ + +QToolBar[objectName="Edit"] > QToolButton::menu-arrow { + background-image: url(qss:images_classic/arrow-down-lightgray.png); + background-position: center center; + background-repeat: none; + subcontrol-origin: padding; + subcontrol-position: bottom right; + height: 6px; +} + +QToolBar[objectName="Edit"] > QToolButton::menu-arrow:hover { + background-image: url(qss:images_classic/arrow-down-white.png); + background-position: center center; + background-repeat: none; + subcontrol-origin: padding; + subcontrol-position: bottom right; + height: 6px; +} + +QToolBar[objectName="Edit"] > QToolButton::menu-arrow:open { + background-image: url(qss:images_classic/arrow-down-white.png); + background-position: center center; + background-repeat: none; + subcontrol-origin: padding; + subcontrol-position: bottom right; + height: 6px; } /*The "show more" button (it can also be stylable with "QToolBarExtension" icon is not working Qproperty works but breaks when you move the toolbar see also */ @@ -971,7 +1015,7 @@ QSpinBox { } QAbstractSpinBox:up-button { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #252525); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:1 #333333); subcontrol-origin: border; subcontrol-position: top right; border-top: 1px solid transparent; @@ -983,20 +1027,24 @@ QAbstractSpinBox:up-button { margin-bottom:-1px; } +QAbstractSpinBox:up-button:disabled { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #444444); +} + QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { - image: url(qss:images_classic/Arrow-up-lightgray.png); + image: url(qss:images_classic/arrow-up-lightgray.png); height: 8px; width: 8px; } QAbstractSpinBox::up-arrow:hover { - image: url(qss:images_classic/Arrow-up-white.png); + image: url(qss:images_classic/arrow-up-white.png); height: 8px; width: 8px; } QAbstractSpinBox:down-button { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #252525, stop:1 #333333); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:1 #333333); subcontrol-origin: border; subcontrol-position: bottom right; border-bottom: 1px solid transparent; @@ -1008,18 +1056,26 @@ QAbstractSpinBox:down-button { margin-top:-1px; } +QAbstractSpinBox:down-button:disabled { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #444444); +} + QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); height: 8px; width: 8px; } QAbstractSpinBox::down-arrow:hover { - image: url(qss:images_classic/Arrow-down-white.png); + image: url(qss:images_classic/arrow-down-white.png); height: 8px; width: 8px; } +QAbstractSpinBox:disabled { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #444444); +} + QAbstractSpinBox:hover { } @@ -1171,7 +1227,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton --------------------------------------------------------------------------- */ QPushButton { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #252525); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:1 #333333); color: white; border: 1px solid #020202; /* border-bottom-color: #1e1e1e; simulates shadow under the button */ @@ -1186,7 +1242,7 @@ QPushButton { } QPushButton:disabled { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #444444); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #333333); color: #adadad; border: 1px solid #020202; } @@ -1212,7 +1268,7 @@ QPushButton:checked:selected { } QPushButton:hover { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:1 #333333); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:1 #404040); color: white; } @@ -1236,6 +1292,10 @@ QDialogButtonBox QPushButton { min-width: 80px; } +QMessageBox[objectName="macroGuideWalkthrough"] QDialogButtonBox QPushButton, +QMessageBox[objectName="confirmSave"] QDialogButtonBox QPushButton { + min-width: 20px; +} /* QToolButton ------------------------------------------------------------ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton @@ -1272,7 +1332,7 @@ QToolButton:checked:disabled { } QToolButton:checked:hover { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:0.7 #444444, stop:1 #444444); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:0.7 #444444, stop:1 #404040); border: 1px solid #020202; } @@ -1281,13 +1341,14 @@ QToolButton:checked:pressed { } QToolButton:checked:selected { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:0.7 #444444, stop:1 #444444); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:0.7 #444444, stop:1 #404040); border: 1px solid @ThemeAccentColor1; } QToolButton:hover { color: white; border: 1px solid #020202; + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:1 #404040); } QToolButton:pressed { @@ -1331,18 +1392,18 @@ QToolButton::menu-indicator { } QToolButton::menu-arrow { - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); width: 18px; height: 18px; /* background-color: transparent; */ } QToolButton::menu-arrow:open { - image: url(qss:images_classic/Arrow-Down-white.png); + image: url(qss:images_classic/arrow-down-white.png); width: 18px; height: 18px; } QToolButton::menu-arrow:hover { - image: url(qss:images_classic/Arrow-Down-white.png); + image: url(qss:images_classic/arrow-down-white.png); width: 18px; height: 18px; } @@ -1375,7 +1436,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox QComboBox { border: 1px solid #020202; border-radius: 2px; - background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #333333, stop:1 #252525); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:1 #333333); selection-background-color: @ThemeAccentColor1; padding-left: 4px; padding-right: 2px; @@ -1392,9 +1453,10 @@ QComboBox { QComboBox:editable { background-color: #252525; } + QComboBox QAbstractItemView { - border: 1px solid #020202; - border-radius: 2px; + border: 2px solid #020202; + /* padding-left: 4px; this fixes the icon padding but adds a 4px padding to all Qcomboboxes.*/ background-color: #252525; selection-background-color: @ThemeAccentColor1; } @@ -1423,7 +1485,7 @@ QComboBox:disabled { } QComboBox:hover { - background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #444444, stop:1 #333333); + background-color: qlineargradient(x1:0, y0:0, x2:0, y1:1, stop:0 #444444, stop:1 #404040); /* border: 1px solid @ThemeAccentColor1; */ } @@ -1473,7 +1535,7 @@ QComboBox::item:selected { QComboBox::drop-down { subcontrol-origin: padding; - /* background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #333333, stop:1 #020202); */ + /* background-color: qlineargradient(x1:0, y0:0, x2:0, y1:1, stop:0 #333333, stop:1 #020202); */ subcontrol-position: top right; width: 20px; border-right: 1px solid transparent; @@ -1485,16 +1547,15 @@ QComboBox::drop-down:hover { } QComboBox::down-arrow { - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); /* height: 10px; */ width: 8px; } QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus { - image: url(qss:images_classic/Arrow-down-white.png); + image: url(qss:images_classic/arrow-down-white.png); } - /*================================================================================================== Tasks panel (custom FreeCAD class) ==================================================================================================*/ @@ -1568,25 +1629,25 @@ padding: 0px; QSint--ActionGroup QFrame[class="header"] QLabel[fold="false"] { width: 30px; height: 30px; - image: url(qss:images_classic/Qsint_header_unfold_lightgray.png); + image: url(qss:images_classic/qsint_header_unfold_lightgray.png); } QSint--ActionGroup QFrame[class="header"] QLabel:hover[fold="false"] { width: 30px; height: 30px; - image: url(qss:images_classic/Qsint_header_unfold_white.png); + image: url(qss:images_classic/qsint_header_unfold_white.png); } QSint--ActionGroup QFrame[class="header"] QLabel[fold="true"] { width: 30px; height: 30px; - image: url(qss:images_classic/Qsint_header_fold_lightgray.png); + image: url(qss:images_classic/qsint_header_fold_lightgray.png); } QSint--ActionGroup QFrame[class="header"] QLabel[fold="true"]:hover { width: 30px; height: 30px; - image: url(qss:images_classic/Qsint_header_fold_white.png); + image: url(qss:images_classic/qsint_header_fold_white.png); } QSint--ActionGroup QFrame[class="content"] { @@ -1640,7 +1701,7 @@ background-color: #252525; QSint--ActionGroup QFrame[class="content"] QToolButton { color: white; text-align: center; - background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #333333, stop:1 #252525); + background-color: qlineargradient(x1:0, y0:0, x2:0, y1:1, stop:0 #333333, stop:1 #252525); border: 1px solid #000000; padding: 1px 1px; /* different than regular QPushButton */ margin: 0px; /* different than regular QPushButton */ @@ -1649,7 +1710,7 @@ QSint--ActionGroup QFrame[class="content"] QToolButton { } QSint--ActionGroup QFrame[class="content"] QToolButton:checked { - background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #333333, stop:1 #444444); + background-color: qlineargradient(x1:0, y0:0, x2:0, y1:1, stop:0 #333333, stop:1 #444444); border: 1px solid @ThemeAccentColor2; } @@ -1935,9 +1996,9 @@ QTabBar[style="text-only"]::tab:left { QTabBar::close-button, QDockWidget QTabBar::close-button { border: 0; - margin: 3px; + margin: 4px; padding: 0px; - image: url(qss:images_classic/Close-lightgray.png); + image: url(qss:images_classic/close-lightgray.png); } QTabBar::close-button:hover, QDockWidget QTabBar::close-button:hover { @@ -1946,7 +2007,7 @@ QTabBar::close-button:hover, QDockWidget QTabBar::close-button:hover { } QTabBar::close-button:pressed, QDockWidget QTabBar::close-button:pressed { - image: url(qss:images_classic/close-DarkRed.png); + image: url(qss:images_classic/close-darkRed.png); } QTabBar::tab, QDockWidget QTabBar::tab { @@ -1961,121 +2022,137 @@ QTabBar::tab:top, QDockWidget QTabBar::tab:top { margin-left: 0px; margin-right: 0px; min-width: 5px; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:0.6 #252525, stop:1 #252525); + background-color: #252525; margin-top: 3px; - border-top: 1px solid #202020; /* selection color */ + border-top: 1px solid #202020; border-bottom: 1px solid #202020; border-left: 1px solid #202020; border-right: 1px solid #202020; - border-top-left-radius: 2px; - border-top-right-radius: 2px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } QTabBar::tab:top:selected, QDockWidget QTabBar::tab:top:selected { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:0.6 #444444, stop:1 #333333); + background-color: #3b3b3b; color: white; - border-top: 1px solid #202020; /* selection color */ - border-bottom: 1px solid #333333; + border-top: 1px solid #202020; + border-bottom: 1px solid #3b3b3b; border-left: 1px solid #202020; border-right: 1px solid #202020; margin-top: 0px; - border-top-left-radius: 2px; - border-top-right-radius: 2px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } QTabBar::tab:top:!selected:hover, QDockWidget QTabBar::tab:top:!selected:hover { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #444444); - margin-top: 0px; + background-color:#333333; + color: white; + border-bottom: 1px solid #202020; + border-top: 1px solid #202020; + border-left: 1px solid #202020; + border-right: 1px solid #202020; } QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { color: #adadad; min-width: 5px; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:0.6 #252525, stop:1 #252525); + background-color: #252525; margin-bottom: 3px; - border-bottom: 1px solid #202020; /* selection color */ + border-bottom: 1px solid #202020; border-top: 1px solid #202020; border-left: 1px solid #202020; border-right: 1px solid #202020; - border-bottom-left-radius: 2px; - border-bottom-right-radius: 2px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; } QTabBar::tab:bottom:selected, QDockWidget QTabBar::tab:bottom:selected { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:0.6 #444444, stop:1 #333333); + background-color: #3b3b3b; color: white; - border-bottom: 1px solid #202020; /* selection color */ - border-top: 1px solid #333333; + border-bottom: 1px solid #202020; + border-top: 1px solid #3b3b3b; border-left: 1px solid #202020; border-right: 1px solid #202020; margin-bottom: 0px; - border-bottom-left-radius: 2px; - border-bottom-right-radius: 2px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; } QTabBar::tab:bottom:!selected:hover, QDockWidget QTabBar::tab:bottom:!selected:hover { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #333333, stop:1 #444444); - margin-bottom: 0px; + background-color:#333333; + color: white; + border-bottom: 1px solid #202020; + border-top: 1px solid #202020; + border-left: 1px solid #202020; + border-right: 1px solid #202020; } QTabBar::tab:left, QDockWidget QTabBar::tab:left { color: #adadad; min-height: 5px; - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #333333, stop:0.6 #252525, stop:1 #252525); + background-color: #252525; margin-right: 3px; - border-bottom: 1px solid #202020; /* selection color */ + border-bottom: 1px solid #202020; border-right: 1px solid #202020; border-left: 1px solid #202020; border-top: 1px solid #202020; - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; } QTabBar::tab:left:selected, QDockWidget QTabBar::tab:left:selected { - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #444444, stop:0.6 #444444, stop:1 #333333); + background-color: #3b3b3b; color: white; - border-bottom: 1px solid #202020; /* selection color */ - border-right: 1px solid #333333; + border-bottom: 1px solid #202020; + border-right: 1px solid #3b3b3b; border-left: 1px solid #202020; border-top: 1px solid #202020; margin-left: 0px; - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; } QTabBar::tab:left:!selected:hover, QDockWidget QTabBar::tab:left:!selected:hover { - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #444444, stop:1 #333333); - margin-left: 0px; + background-color:#333333; + color: white; + border-bottom: 1px solid #202020; + border-top: 1px solid #202020; + border-left: 1px solid #202020; + border-right: 1px solid #202020; } QTabBar::tab:right, QDockWidget QTabBar::tab:right { color: white; min-height: 5px; - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #333333, stop:0.6 #252525, stop:1 #252525); + background-color: #252525; margin-right: 3px; - border-bottom: 1px solid #202020; /* selection color */ + border-bottom: 1px solid #202020; border-left: 1px solid #202020; border-right: 1px solid #202020; border-top: 1px solid #202020; - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; } QTabBar::tab:right:selected, QDockWidget QTabBar::tab:right:selected { - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #444444, stop:0.6 #444444, stop:1 #333333); + background-color: #3b3b3b; color: white; - border-bottom: 1px solid #202020; /* selection color */ - border-left: 1px solid #333333; + border-bottom: 1px solid #202020; + border-left: 1px solid #3b3b3b; border-left: 1px solid #202020; border-top: 1px solid #202020; margin-right: 0px; - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; } QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hover { - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #333333, stop:1 #444444); - margin-right: 0px; + background-color:#333333; + color: white; + border-bottom: 1px solid #202020; + border-top: 1px solid #202020; + border-left: 1px solid #202020; + border-right: 1px solid #202020; } QTabBar QToolButton, QDockWidget QTabBar QToolButton { @@ -2096,19 +2173,19 @@ QTabBar QToolButton:pressed:hover, QDockWidget QTabBar QToolButton:pressed:hover } QTabBar QToolButton::left-arrow:enabled, QDockWidget QTabBar QToolButton::left-arrow:enabled { - image: url(qss:images_classic/Arrow-left-lightgray.png); + image: url(qss:images_classic/arrow-left-lightgray.png); } QTabBar QToolButton::left-arrow:disabled, QDockWidget QTabBar QToolButton::left-arrow:disabled { - image: url(qss:images_classic/Arrow-left-darkgray.png); + image: url(qss:images_classic/arrow-left-darkgray.png); } QTabBar QToolButton::right-arrow:enabled, QDockWidget QTabBar QToolButton::right-arrow:enabled { - image: url(qss:images_classic/Arrow-right-lightgray.png); + image: url(qss:images_classic/arrow-right-lightgray.png); } QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::right-arrow:disabled { - image: url(qss:images_classic/Arrow-right-darkgray.png); + image: url(qss:images_classic/arrow-right-darkgray.png); } /* QDockWiget ------------------------------------------------------------- @@ -2127,7 +2204,7 @@ QDockWidget::title { padding: 3px; spacing: 4px; border: none; - background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #333333, stop:1 #252525); + background-color: qlineargradient(x1:0, y0:0, x2:0, y1:1, stop:0 #333333, stop:1 #252525); text-align: center; font-weight: bold; } @@ -2196,22 +2273,22 @@ QTreeView::branch:!has-children:!has-siblings:adjoins-item { QTreeView::branch:closed:has-children:has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-right-white.png); + image: url(qss:images_classic/arrow-right-white.png); } QTreeView::branch:has-children:!has-siblings:closed { border-image: none; - image: url(qss:images_classic/Arrow-right-white.png); + image: url(qss:images_classic/arrow-right-white.png); } QTreeView::branch:open:has-children:has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-down-white.png); + image: url(qss:images_classic/arrow-down-white.png); } QTreeView::branch:open:has-children:!has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-down-white.png); + image: url(qss:images_classic/arrow-down-white.png); } QTreeView::indicator, @@ -2262,7 +2339,7 @@ QColumnView::indicator:checked:pressed { QListView::indicator:unchecked, QTableView::indicator:unchecked, QColumnView::indicator:unchecked { - image: url(qss:images_classic/checkbox-Empty-white.png); + image: url(qss:images_classic/checkbox-empty-white.png); } */ QTreeView::indicator:unchecked:hover, QTreeView::indicator:unchecked:focus, QTreeView::indicator:unchecked:pressed, @@ -2275,7 +2352,7 @@ QTableView::indicator:unchecked:pressed, QColumnView::indicator:unchecked:hover, QColumnView::indicator:unchecked:focus, QColumnView::indicator:unchecked:pressed { - /* image: url(qss:images_classic/checkbox-Empty-blue.png); */ + /* image: url(qss:images_classic/checkbox-empty-blue.png); */ /* background-color: @ThemeAccentColor1; border: 1px solid #ffffff; */ } @@ -2284,7 +2361,7 @@ QTreeView::indicator:indeterminate, QListView::indicator:indeterminate, QTableView::indicator:indeterminate, QColumnView::indicator:indeterminate { - image: url(qss:images_classic/Indeterminate-mark-white.png); + image: url(qss:images_classic/indeterminate-mark-white.png); } QTreeView::indicator:indeterminate:hover, QTreeView::indicator:indeterminate:focus, QTreeView::indicator:indeterminate:pressed, @@ -2297,7 +2374,7 @@ QTableView::indicator:indeterminate:pressed, QColumnView::indicator:indeterminate:hover, QColumnView::indicator:indeterminate:focus, QColumnView::indicator:indeterminate:pressed { - /* image: url(qss:images_classic/Indeterminate-mark-lightgray.png); + /* image: url(qss:images_classic/indeterminate-mark-lightgray.png); background-color: @ThemeAccentColor1; border: 1px solid #ffffff; */ } @@ -2375,6 +2452,7 @@ QTableView::item { color: white; } + /* QHeaderView ------------------------------------------------------------ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview @@ -2392,7 +2470,7 @@ QTableCornerButton::section { QHeaderView { background-color: transparent; - margin: -1px; /* fix for misalignement*/ + margin: -1px; /* fix for misalignment*/ } QHeaderView:disabled { @@ -2400,11 +2478,15 @@ QHeaderView:disabled { } QHeaderView::section { - background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #333333, stop:1 #252525); + background-color: qlineargradient(x1:0, y0:0, x2:0, y1:1, stop:0 #252525, stop:1 #333333); color: #ffffff; padding: 4px; } +QHeaderView::section:hover { + background-color: qlineargradient(x1:0, y0:0, x2:0, y1:1, stop:0 #444444, stop:1 #404040); +} + QHeaderView::section::horizontal { border-bottom: 2px solid #020202; border-right: 0px solid transparent; @@ -2446,7 +2528,7 @@ QHeaderView::down-arrow { width: 12px; padding-left: 2px; padding-right: 2px; - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); } QHeaderView::up-arrow { @@ -2456,7 +2538,7 @@ QHeaderView::up-arrow { width: 12px; padding-left: 2px; padding-right: 2px; - image: url(qss:images_classic/Arrow-up-lightgray.png); + image: url(qss:images_classic/arrow-up-lightgray.png); } /* QToolBox -------------------------------------------------------------- @@ -2511,7 +2593,7 @@ QToolBox::tab:!selected:disabled { } QToolBox::tab:hover { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #444444, stop:1 #333333); + background-color: qlineargradient(x1:0, y0:0, x2:0, y1:1, stop:0 #444444, stop:1 #404040); } QToolBox > QScrollArea > QWidget > QWidget { @@ -2561,7 +2643,7 @@ https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter ---------------------------------------------------------------------------*/ -QSplitterHandle:hover { /* to fix bug about hovering on splitters https://bugreports.qt.io/browse/QTBUG-13768 */ +QSplitterHandle:hover { /* to fix bug about hovering on splitters https://bugreports.qt.io/browse/qTBUG-13768 */ } @@ -2622,13 +2704,13 @@ QDateEdit::drop-down, QDateTimeEdit::drop-down { } QDateEdit::down-arrow, QDateTimeEdit::down-arrow { - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); height: 8px; width: 8px; } QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:focus, QDateTimeEdit::down-arrow:on, QDateTimeEdit::down-arrow:hover, QDateTimeEdit::down-arrow:focus { - image: url(qss:images_classic/Arrow-down-white.png); + image: url(qss:images_classic/arrow-down-white.png); } QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { @@ -2752,23 +2834,23 @@ Settings menu #groupsTreeView: QTreeView::branch#groupsTreeView:closed:has-children:has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-right-white.png); + image: url(qss:images_classic/arrow-right-white.png); } QTreeView::branch#groupsTreeView:open:has-children:has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-down-white.png); + image: url(qss:images_classic/arrow-down-white.png); } QTreeView::branch#groupsTreeView:open:has-children:!has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-down-white.png); + image: url(qss:images_classic/arrow-down-white.png); } QTreeView::branch#groupsTreeView:has-children:!has-siblings:closed { border-image: none; - image: url(qss:images_classic/Arrow-right-white.png); + image: url(qss:images_classic/arrow-right-white.png); } QTreeView::branch#groupsTreeView:has-siblings:!adjoins-item { @@ -2816,3 +2898,4 @@ QTreeView::item:!selected:hover#groupsTreeView { background-color: @ThemeAccentColor1; margin-left:-8px; } */ + diff --git a/src/Gui/Stylesheets/FreeCAD Light.qss b/src/Gui/Stylesheets/FreeCAD Light.qss index 943222caf0..9cafa1cb2a 100644 --- a/src/Gui/Stylesheets/FreeCAD Light.qss +++ b/src/Gui/Stylesheets/FreeCAD Light.qss @@ -104,6 +104,7 @@ Main window ==================================================================================================*/ QMainWindow, QDialog, + QDockWidget { background-color: #f0f0f0; /* main background color */ } @@ -416,7 +417,7 @@ QRadioButton::indicator { border-image: none; width: 14px; height: 14px; - image:url(qss:images_classic/Radio-unchecked-black.png); + image:url(qss:images_classic/radio-unchecked-black.png); } QRadioButton::indicator:unchecked { @@ -430,14 +431,14 @@ QRadioButton::indicator:unchecked:disabled { border-image: none; width: 14px; height: 14px; - image:url(qss:images_classic/Radio-unchecked-lightgray.png); + image:url(qss:images_classic/radio-unchecked-lightgray.png); } QRadioButton::indicator:checked { border-image: none; width: 14px; height: 14px; - image:url(qss:images_classic/Radio-checked-black.png); + image:url(qss:images_classic/radio-checked-black.png); } QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:pressed { @@ -448,7 +449,7 @@ QRadioButton::indicator:checked:disabled { border-image: none; width: 14px; height: 14px; - image:url(qss:images_classic/Radio-checked-lightgray.png); + image:url(qss:images_classic/radio-checked-lightgray.png); } /* QMenuBar --------------------------------------------------------------- @@ -457,11 +458,16 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar --------------------------------------------------------------------------- */ QMenuBar { - background-color: #f0f0f0; + background-color: #ffffff; color: black; selection-background-color: @ThemeAccentColor1; } +QMenuBar:disabled, +QMenuBar::item:disabled{ + color: #646464; +} + QMenuBar:focus { border: 1px solid @ThemeAccentColor2; } @@ -495,6 +501,10 @@ QMenu { selection-background-color: @ThemeAccentColor1; } +QMenu::item:disabled { + color: #646464; +} + QMenu::separator { height: 2px; background-color: #ededed; @@ -545,7 +555,7 @@ QMenu::icon:checked { /* appearance of a 'checked' icon */ border-radius: 0px; } QMenu::indicator:non-exclusive:unchecked { - image: url(qss:images_classic/checkbox-Empty-black.png); + image: url(qss:images_classic/checkbox-empty-black.png); } QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:unchecked:focus, QMenu::indicator:non-exclusive:unchecked:pressed { @@ -554,7 +564,7 @@ QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:u } QMenu::indicator:non-exclusive:unchecked:disabled { - image: url(qss:images_classic/checkbox-Empty-lightgray.png); + image: url(qss:images_classic/checkbox-empty-lightgray.png); } QMenu::indicator:non-exclusive:checked { @@ -590,35 +600,35 @@ QMenu::indicator:exclusive:unchecked:hover, QMenu::indicator:exclusive:unchecked border: none; outline: none; background-color: @ThemeAccentColor1; - image: url(qss:images_classic/checkbox-Empty-black.png); + image: url(qss:images_classic/checkbox-empty-black.png); } QMenu::indicator:exclusive:unchecked:disabled { - image: url(qss:images_classic/checkbox-Empty-black.png); + image: url(qss:images_classic/checkbox-empty-black.png); } QMenu::indicator:exclusive:checked { border: none; outline: none; - image: url(qss:images_classic/Radio-checked-black.png); + image: url(qss:images_classic/radio-checked-black.png); } QMenu::indicator:exclusive:checked:hover, QMenu::indicator:exclusive:checked:focus, QMenu::indicator:exclusive:checked:pressed { border: none; outline: none; background-color: @ThemeAccentColor1; - image: url(qss:images_classic/checkbox-Empty-black.png); + image: url(qss:images_classic/checkbox-empty-black.png); } QMenu::indicator:exclusive:checked:disabled { outline: none; - image: url(qss:images_classic/Radio-checked-black.png); + image: url(qss:images_classic/radio-checked-black.png); } QMenu::right-arrow { margin: 5px; padding-left: 12px; - image:url(qss:images_classic/Arrow-right-black.png); + image:url(qss:images_classic/arrow-right-black.png); height: 8px; width: 8px; background-color: transparent; @@ -730,7 +740,7 @@ QScrollBar::handle:vertical:focus { QScrollBar::add-line:horizontal { margin: 6px 6px; - image: url(qss:images_classic/Arrow-right-lightgray.png); + image: url(qss:images_classic/arrow-right-lightgray.png); height: 8px; width: 4px; subcontrol-position: right; @@ -738,7 +748,7 @@ QScrollBar::add-line:horizontal { } QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { - image: url(qss:images_classic/Arrow-right-black.png); + image: url(qss:images_classic/arrow-right-black.png); height: 8px; width: 4px; subcontrol-position: right; @@ -747,7 +757,7 @@ QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { QScrollBar::add-line:vertical { margin: 6px 6px; - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); height: 4px; width: 8px; subcontrol-position: bottom; @@ -755,7 +765,7 @@ QScrollBar::add-line:vertical { } QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { - image: url(qss:images_classic/Arrow-down-black.png); + image: url(qss:images_classic/arrow-down-black.png); height: 4px; width: 8px; subcontrol-position: bottom; @@ -764,7 +774,7 @@ QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { QScrollBar::sub-line:horizontal { margin: 6px 6px; - image: url(qss:images_classic/Arrow-left-lightgray.png); + image: url(qss:images_classic/arrow-left-lightgray.png); height: 8px; width: 4px; subcontrol-position: left; @@ -772,7 +782,7 @@ QScrollBar::sub-line:horizontal { } QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { - image: url(qss:images_classic/Arrow-left-black.png); + image: url(qss:images_classic/arrow-left-black.png); height: 8px; width: 4px; subcontrol-position: left; @@ -781,7 +791,7 @@ QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { QScrollBar::sub-line:vertical { margin: 6px 6px; - image: url(qss:images_classic/Arrow-up-lightgray.png); + image: url(qss:images_classic/arrow-up-lightgray.png); height: 4px; width: 8px; subcontrol-position: top; @@ -789,7 +799,7 @@ QScrollBar::sub-line:vertical { } QScrollBar::sub-line:vertical:hover, QScrollBar::sub-line:vertical:on { - image: url(qss:images_classic/Arrow-up-black.png); + image: url(qss:images_classic/arrow-up-black.png); height: 4px; width: 8px; subcontrol-position: top; @@ -880,8 +890,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar --------------------------------------------------------------------------- */ QToolBar { - background-color: #f0f0f0; - /* border: 1px solid #ababab; */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #cecece, stop:0.03 #f4f4f4,stop:0.97 #f0f0f0, stop:1 #cecece); /* font-weight: bold; */ } @@ -892,16 +901,22 @@ QToolBar:only-one { } QToolBar:horizontal { - border-bottom: 1px solid #ababab; padding-top: 3px; - padding-left: 4px; + padding-left: 3px; + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #cecece, stop:0.03 #f4f4f4,stop:0.97 #f0f0f0, stop:1 #cecece); +} + +/* fix background color for toolbars that are the on menubar. */ +QToolBar:only-one { + background-color: transparent; + border:0px; + /* margin-top: -3px; */ } QToolBar:vertical { - border-left: 1px solid #ababab; - border-right: 1px solid #ababab; - padding-top: 4px; + padding-top: 3px; padding-left: 3px; + background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #cecece, stop:0.03 #f4f4f4,stop:0.97 #f0f0f0, stop:1 #cecece); } QToolBar:disabled { @@ -909,34 +924,63 @@ QToolBar:disabled { QToolBar::handle:horizontal { width: 8px; - image: url(qss:images_classic/Hmovetoolbar-lightgray.png); + image: url(qss:images_classic/hmovetoolbar-lightgray.png); } QToolBar::handle:vertical { height: 8px; - image: url(qss:images_classic/Vmovetoolbar-lightgray.png); + image: url(qss:images_classic/vmovetoolbar-lightgray.png); } QToolBar::handle:horizontal:hover { width: 8px; - image: url(qss:images_classic/Hmovetoolbar-darkgray.png); + image: url(qss:images_classic/hmovetoolbar-darkgray.png); } QToolBar::handle:vertical:hover { height: 8px; - image: url(qss:images_classic/Vmovetoolbar-darkgray.png); + image: url(qss:images_classic/vmovetoolbar-darkgray.png); } QToolBar::separator:horizontal { width: 2px; padding: 0px 3px; - image: url(qss:images_classic/Hsepartoolbar-lightgray.png); + image: url(qss:images_classic/hsepartoolbar-lightgray.png); } QToolBar::separator:vertical { height: 2px; padding: 3px 0px; - image: url(qss:images_classic/Vsepartoolbar-lightgray.png); + image: url(qss:images_classic/vsepartoolbar-lightgray.png); +} + +/* undo button */ + +QToolBar[objectName="Edit"] > QToolButton::menu-arrow { + background-image: url(qss:images_classic/arrow-down-lightgray.png); + background-position: center center; + background-repeat: none; + subcontrol-origin: padding; + subcontrol-position: bottom right; + height: 6px; +} + +QToolBar[objectName="Edit"] > QToolButton::menu-arrow:hover { + background-image: url(qss:images_classic/arrow-down-black.png); + background-position: center center; + background-repeat: none; + subcontrol-origin: padding; + subcontrol-position: bottom right; + height: 6px; +} + +QToolBar[objectName="Edit"] > QToolButton::menu-arrow:open { + background-image: url(qss:images_classic/arrow-down-black.png); + background-position: center center; + background-repeat: none; + subcontrol-origin: padding; + subcontrol-position: bottom right; + height: 6px; } /*The "show more" button (it can also be stylable with "QToolBarExtension" icon is not working Qproperty works but breaks when you move the toolbar see also */ @@ -969,7 +1013,7 @@ QSpinBox { } QAbstractSpinBox:up-button { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f0f0f0, stop:1 #fdfdfd); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fdfdfd, stop:1 #f0f0f0); subcontrol-origin: border; subcontrol-position: top right; border-top: 1px solid transparent; @@ -981,14 +1025,18 @@ QAbstractSpinBox:up-button { margin-bottom:-1px; } +QAbstractSpinBox:up-button:disabled { +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #e2e2e2, stop:1 #ededed); +} + QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { - image: url(qss:images_classic/Arrow-up-lightgray.png); + image: url(qss:images_classic/arrow-up-lightgray.png); height: 8px; width: 8px; } QAbstractSpinBox::up-arrow:hover { - image: url(qss:images_classic/Arrow-up-black.png); + image: url(qss:images_classic/arrow-up-black.png); height: 8px; width: 8px; } @@ -1006,18 +1054,26 @@ QAbstractSpinBox:down-button { margin-top:-1px; } +QAbstractSpinBox:down-button:disabled { +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #e2e2e2, stop:1 #ededed); +} + QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); height: 8px; width: 8px; } QAbstractSpinBox::down-arrow:hover { - image: url(qss:images_classic/Arrow-down-black.png); + image: url(qss:images_classic/arrow-down-black.png); height: 8px; width: 8px; } +QAbstractSpinBox:disabled { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #e2e2e2, stop:1 #ededed); +} + QAbstractSpinBox:hover { } @@ -1168,7 +1224,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton --------------------------------------------------------------------------- */ QPushButton { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f0f0f0, stop:1 #fdfdfd); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fdfdfd, stop:1 #f0f0f0); color: black; border: 1px solid #ababab; /* border-bottom-color: #1e1e1e; simulates shadow under the button */ @@ -1183,7 +1239,7 @@ QPushButton { } QPushButton:disabled { -background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #e2e2e2, stop:1 #fdfdfd); +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #e2e2e2, stop:1 #ededed); color: #646464; border: 1px solid #ababab; } @@ -1209,7 +1265,7 @@ QPushButton:checked:selected { } QPushButton:hover { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fefefe, stop:1 #f8f8f8); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #fefefe); color: black; } @@ -1233,6 +1289,11 @@ QDialogButtonBox QPushButton { min-width: 80px; } +QMessageBox[objectName="macroGuideWalkthrough"] QDialogButtonBox QPushButton, +QMessageBox[objectName="confirmSave"] QDialogButtonBox QPushButton { + min-width: 20px; +} + /* QToolButton ------------------------------------------------------------ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton @@ -1284,6 +1345,7 @@ QToolButton:checked:selected { QToolButton:hover { color: black; + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #fefefe); border: 1px solid #ababab; } @@ -1328,18 +1390,18 @@ QToolButton::menu-indicator { } QToolButton::menu-arrow { - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); width: 18px; height: 18px; /* background-color: transparent; */ } QToolButton::menu-arrow:open { - image: url(qss:images_classic/Arrow-Down-black.png); + image: url(qss:images_classic/arrow-down-black.png); width: 18px; height: 18px; } QToolButton::menu-arrow:hover { - image: url(qss:images_classic/Arrow-Down-black.png); + image: url(qss:images_classic/arrow-down-black.png); width: 18px; height: 18px; } @@ -1372,7 +1434,7 @@ https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox QComboBox { border: 1px solid #ababab; border-radius: 2px; - background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #f0f0f0, stop:1 #fdfdfd); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fdfdfd, stop:1 #f0f0f0); selection-background-color: @ThemeAccentColor1; padding-left: 4px; padding-right: 2px; @@ -1389,9 +1451,10 @@ QComboBox { QComboBox:editable { background-color: #fdfdfd; } + QComboBox QAbstractItemView { - border: 1px solid #ababab; - border-radius: 2px; + border: 2px solid #ababab; + /* padding-left: 4px; this fixes the icon padding but adds a 4px padding to all Qcomboboxes.*/ background-color: #fdfdfd; selection-background-color: @ThemeAccentColor1; } @@ -1482,13 +1545,13 @@ QComboBox::drop-down:hover { } QComboBox::down-arrow { - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); /* height: 10px; */ width: 8px; } QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus { - image: url(qss:images_classic/Arrow-down-black.png); + image: url(qss:images_classic/arrow-down-black.png); } @@ -1565,25 +1628,25 @@ padding: 0px; QSint--ActionGroup QFrame[class="header"] QLabel[fold="false"] { width: 30px; height: 30px; - image: url(qss:images_classic/Qsint_header_unfold_lightgray.png); + image: url(qss:images_classic/qsint_header_unfold_lightgray.png); } QSint--ActionGroup QFrame[class="header"] QLabel:hover[fold="false"] { width: 30px; height: 30px; - image: url(qss:images_classic/Qsint_header_unfold_black.png); + image: url(qss:images_classic/qsint_header_unfold_black.png); } QSint--ActionGroup QFrame[class="header"] QLabel[fold="true"] { width: 30px; height: 30px; - image: url(qss:images_classic/Qsint_header_fold_lightgray.png); + image: url(qss:images_classic/qsint_header_fold_lightgray.png); } QSint--ActionGroup QFrame[class="header"] QLabel[fold="true"]:hover { width: 30px; height: 30px; - image: url(qss:images_classic/Qsint_header_fold_black.png); + image: url(qss:images_classic/qsint_header_fold_black.png); } QSint--ActionGroup QFrame[class="content"] { @@ -1637,7 +1700,7 @@ background-color: #f0f0f0; QSint--ActionGroup QFrame[class="content"] QToolButton { color: black; text-align: center; - background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #f0f0f0, stop:1 #fdfdfd); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fdfdfd, stop:1 #f0f0f0); border: 1px solid #adadad; padding: 1px 1px; /* different than regular QPushButton */ margin: 0px; /* different than regular QPushButton */ @@ -1646,7 +1709,7 @@ QSint--ActionGroup QFrame[class="content"] QToolButton { } QSint--ActionGroup QFrame[class="content"] QToolButton:checked { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fefefe, stop:1 #f8f8f8); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #fefefe); border: 1px solid @ThemeAccentColor2; } @@ -1677,7 +1740,7 @@ QSint--ActionGroup QToolButton#filterButton QListWidget { QSint--ActionGroup QFrame[class="content"] QToolButton:hover{ - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fefefe, stop:1 #f8f8f8); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #fefefe); } QSint--ActionGroup QFrame[class="content"] QToolButton:focus { border: 1px solid @ThemeAccentColor2; @@ -1932,9 +1995,9 @@ QTabBar[style="text-only"]::tab:left { QTabBar::close-button, QDockWidget QTabBar::close-button { border: 0; - margin: 3px; + margin: 4px; padding: 0px; - image: url(qss:images_classic/Close-lightgray.png); + image: url(qss:images_classic/close-lightgray.png); } QTabBar::close-button:hover, QDockWidget QTabBar::close-button:hover { @@ -1958,122 +2021,133 @@ QTabBar::tab:top, QDockWidget QTabBar::tab:top { margin-left: 0px; margin-right: 0px; min-width: 5px; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #dddddd, stop:0.6 #e2e2e2, stop:1 #cccccc); + background-color: #e2e2e2; margin-top: 3px; - border-top: 1px solid #ababab; /* selection color */ + border-top: 1px solid #ababab; border-bottom: 1px solid #ababab; border-left: 1px solid #ababab; border-right: 1px solid #ababab; - border-top-left-radius: 2px; - border-top-right-radius: 2px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } QTabBar::tab:top:selected, QDockWidget QTabBar::tab:top:selected { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f0f0f0, stop:0.6 #fdfdfd stop:1 #f0f0f0); + background-color: #f8f8f8; color: black; - border-top: 1px solid #ababab; /* selection color */ - border-bottom: 1px solid #f0f0f0; + border-top: 1px solid #ababab; + border-bottom: 1px solid #f8f8f8; border-left: 1px solid #ababab; border-right: 1px solid #ababab; margin-top: 0px; - border-top-left-radius: 2px; - border-top-right-radius: 2px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } QTabBar::tab:top:!selected:hover, QDockWidget QTabBar::tab:top:!selected:hover { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f0f0f0, stop:1 #d8d8d8); - margin-top: 0px; + background-color: #f8f8f8; } QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { color: #646464; min-width: 5px; - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #dddddd, stop:0.6 #e2e2e2, stop:1 #cccccc); + background-color: #e2e2e2; margin-bottom: 3px; - border-bottom: 1px solid #ababab; /* selection color */ + border-bottom: 1px solid #ababab; border-top: 1px solid #ababab; border-left: 1px solid #ababab; border-right: 1px solid #ababab; - border-bottom-left-radius: 2px; - border-bottom-right-radius: 2px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; } QTabBar::tab:bottom:selected, QDockWidget QTabBar::tab:bottom:selected { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #f0f0f0, stop:0.6 #fdfdfd stop:1 #f0f0f0); + background-color: #f8f8f8; color: black; - border-bottom: 1px solid #ababab; /* selection color */ - border-top: 1px solid #f0f0f0; + border-bottom: 1px solid #ababab; + border-top: 1px solid #f8f8f8; border-left: 1px solid #ababab; border-right: 1px solid #ababab; margin-bottom: 0px; - border-bottom-left-radius: 2px; - border-bottom-right-radius: 2px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; } QTabBar::tab:bottom:!selected:hover, QDockWidget QTabBar::tab:bottom:!selected:hover { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #d8d8d8, stop:1 #f0f0f0); - margin-bottom: 0px; + background-color: #f8f8f8; + color: black; + border-bottom: 1px solid #ababab; + border-top: 1px solid #ababab; + border-left: 1px solid #ababab; + border-right: 1px solid #ababab; } QTabBar::tab:left, QDockWidget QTabBar::tab:left { color: #646464; min-height: 5px; - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #dddddd, stop:0.6 #e2e2e2, stop:1 #cccccc); + background-color: #e2e2e2; margin-left: 3px; - border-bottom: 1px solid #ababab; /* selection color */ + border-bottom: 1px solid #ababab; border-right: 1px solid #ababab; border-left: 1px solid #ababab; border-top: 1px solid #ababab; - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; } QTabBar::tab:left:selected, QDockWidget QTabBar::tab:left:selected { - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #f0f0f0, stop:0.6 #fdfdfd stop:1 #f0f0f0); + background-color: #f8f8f8; color: black; - border-bottom: 1px solid #ababab; /* selection color */ + border-bottom: 1px solid #ababab; border-right: 1px solid #f0f0f0; border-left: 1px solid #ababab; border-top: 1px solid #ababab; margin-left: 0px; - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; } QTabBar::tab:left:!selected:hover, QDockWidget QTabBar::tab:left:!selected:hover { - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #d8d8d8, stop:1 #f0f0f0); - margin-left: 0px; + background-color: #f8f8f8; + color: black; + border-bottom: 1px solid #ababab; + border-top: 1px solid #ababab; + border-left: 1px solid #ababab; + border-right: 1px solid #ababab; } QTabBar::tab:right, QDockWidget QTabBar::tab:right { color: black; min-height: 5px; - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #dddddd, stop:0.6 #e2e2e2, stop:1 #cccccc); + background-color: #e2e2e2; margin-right: 3px; - border-bottom: 1px solid #ababab; /* selection color */ + border-bottom: 1px solid #ababab; border-left: 1px solid #ababab; border-right: 1px solid #ababab; border-top: 1px solid #ababab; - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; } QTabBar::tab:right:selected, QDockWidget QTabBar::tab:right:selected { - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #f0f0f0, stop:0.6 #fdfdfd stop:1 #f0f0f0); + background-color: #f8f8f8; color: black; - border-bottom: 1px solid #ababab; /* selection color */ + border-bottom: 1px solid #ababab; border-left: 1px solid #f0f0f0; border-left: 1px solid #ababab; border-top: 1px solid #ababab; margin-right: 0px; - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; } QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hover { - background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #f0f0f0, stop:1 #d8d8d8); - margin-right: 0px; -} + background-color: #f8f8f8; + color: black; + border-bottom: 1px solid #ababab; + border-top: 1px solid #ababab; + border-left: 1px solid #ababab; + border-right: 1px solid #ababab; + } QTabBar QToolButton, QDockWidget QTabBar QToolButton { /* Fixes #136 */ @@ -2093,19 +2167,19 @@ QTabBar QToolButton:pressed:hover, QDockWidget QTabBar QToolButton:pressed:hover } QTabBar QToolButton::left-arrow:enabled, QDockWidget QTabBar QToolButton::left-arrow:enabled { - image: url(qss:images_classic/Arrow-left-darkgray.png); + image: url(qss:images_classic/arrow-left-darkgray.png); } QTabBar QToolButton::left-arrow:disabled, QDockWidget QTabBar QToolButton::left-arrow:disabled { - image: url(qss:images_classic/Arrow-left-lightgray.png); + image: url(qss:images_classic/arrow-left-lightgray.png); } QTabBar QToolButton::right-arrow:enabled, QDockWidget QTabBar QToolButton::right-arrow:enabled { - image: url(qss:images_classic/Arrow-right-darkgray.png); + image: url(qss:images_classic/arrow-right-darkgray.png); } QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::right-arrow:disabled { - image: url(qss:images_classic/Arrow-right-lightgray.png); + image: url(qss:images_classic/arrow-right-lightgray.png); } /* QDockWiget ------------------------------------------------------------- @@ -2193,22 +2267,22 @@ QTreeView::branch:!has-children:!has-siblings:adjoins-item { QTreeView::branch:closed:has-children:has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-right-black.png); + image: url(qss:images_classic/arrow-right-black.png); } QTreeView::branch:has-children:!has-siblings:closed { border-image: none; - image: url(qss:images_classic/Arrow-right-black.png); + image: url(qss:images_classic/arrow-right-black.png); } QTreeView::branch:open:has-children:has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-down-black.png); + image: url(qss:images_classic/arrow-down-black.png); } QTreeView::branch:open:has-children:!has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-down-black.png) ; + image: url(qss:images_classic/arrow-down-black.png) ; } QTreeView::indicator, @@ -2259,7 +2333,7 @@ QColumnView::indicator:checked:pressed { QListView::indicator:unchecked, QTableView::indicator:unchecked, QColumnView::indicator:unchecked { - image: url(qss:images_classic/checkbox-Empty-black.png); + image: url(qss:images_classic/checkbox-empty-black.png); } */ QTreeView::indicator:unchecked:hover, QTreeView::indicator:unchecked:focus, QTreeView::indicator:unchecked:pressed, @@ -2272,7 +2346,7 @@ QTableView::indicator:unchecked:pressed, QColumnView::indicator:unchecked:hover, QColumnView::indicator:unchecked:focus, QColumnView::indicator:unchecked:pressed { - /* image: url(qss:images_classic/checkbox-Empty-blue.png); */ + /* image: url(qss:images_classic/checkbox-empty-blue.png); */ /* background-color: @ThemeAccentColor1; border: 1px solid #1c1c1c; */ } @@ -2389,7 +2463,8 @@ QTableCornerButton::section { QHeaderView { background-color: transparent; /* text-align: bottom; */ - margin: -1px; /* fix for misalignement*/ + margin: -1px; /* fix for misalignment*/ + selection-background-color: @ThemeAccentColor1; } QHeaderView:disabled { @@ -2398,18 +2473,33 @@ QHeaderView:disabled { } QHeaderView::section { - background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #f0f0f0, stop:1 #fdfdfd); + background-color: qlineargradient(x1:0, y1:0.3, x2:0, y2:1, stop:0 #fdfdfd, stop:1 #f0f0f0); color: black; - padding: 4px; + /* padding: 1px; */ +} + +QHeaderView::section:hover { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #fefefe); +} + +QHeaderView::section:checked, QHeaderView::section:selected { + background-color: @ThemeAccentColor1; /*Does not work currently. */ } QHeaderView::section::horizontal { + selection-background-color: @ThemeAccentColor1; border-bottom: 2px solid #ababab; border-right: 0px solid transparent; border-top: 2px solid #ababab; border-left: 1px solid #ababab; } +QHeaderView::section::horizontal:selected { + background-color: @ThemeAccentColor1; + selection-background-color: @ThemeAccentColor1; +} + + QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { /* border-left: 0px solid #ababab; */ } @@ -2444,7 +2534,7 @@ QHeaderView::down-arrow { width: 12px; padding-left: 2px; padding-right: 2px; - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); } QHeaderView::up-arrow { @@ -2454,7 +2544,7 @@ QHeaderView::up-arrow { width: 12px; padding-left: 2px; padding-right: 2px; - image: url(qss:images_classic/Arrow-up-lightgray.png); + image: url(qss:images_classic/arrow-up-lightgray.png); } /* QToolBox -------------------------------------------------------------- @@ -2491,7 +2581,7 @@ QToolBox::tab:disabled { } QToolBox::tab:selected { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fefefe, stop:1 #f8f8f8); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #fefefe); } QToolBox::tab:selected:disabled { @@ -2509,7 +2599,7 @@ QToolBox::tab:!selected:disabled { } QToolBox::tab:hover { - background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fefefe, stop:1 #f8f8f8); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ffffff, stop:1 #fefefe); } QToolBox > QScrollArea > QWidget > QWidget { @@ -2559,7 +2649,7 @@ https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter ---------------------------------------------------------------------------*/ -QSplitterHandle:hover { /* to fix bug about hovering on splitters https://bugreports.qt.io/browse/QTBUG-13768 */ +QSplitterHandle:hover { /* to fix bug about hovering on splitters https://bugreports.qt.io/browse/qTBUG-13768 */ } @@ -2620,13 +2710,13 @@ QDateEdit::drop-down, QDateTimeEdit::drop-down { } QDateEdit::down-arrow, QDateTimeEdit::down-arrow { - image: url(qss:images_classic/Arrow-down-lightgray.png); + image: url(qss:images_classic/arrow-down-lightgray.png); height: 8px; width: 8px; } QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:focus, QDateTimeEdit::down-arrow:on, QDateTimeEdit::down-arrow:hover, QDateTimeEdit::down-arrow:focus { - image: url(qss:images_classic/Arrow-down-black.png); + image: url(qss:images_classic/arrow-down-black.png); } QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { @@ -2750,22 +2840,22 @@ Settings menu #groupsTreeView: QTreeView::branch#groupsTreeView:closed:has-children:has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-right-black.png); + image: url(qss:images_classic/arrow-right-black.png); } QTreeView::branch#groupsTreeView:open:has-children:has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-down-black.png); + image: url(qss:images_classic/arrow-down-black.png); } QTreeView::branch#groupsTreeView:open:has-children:!has-siblings { border-image: none; - image: url(qss:images_classic/Arrow-down-black.png); + image: url(qss:images_classic/arrow-down-black.png); } QTreeView::branch#groupsTreeView:has-children:!has-siblings:closed { border-image: none; - image: url(qss:images_classic/Arrow-right-black.png); + image: url(qss:images_classic/arrow-right-black.png); } QTreeView::branch#groupsTreeView:has-siblings:!adjoins-item { diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-black.png b/src/Gui/Stylesheets/images_classic/arrow-double-leftright-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-black.png rename to src/Gui/Stylesheets/images_classic/arrow-double-leftright-black.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-blue.png b/src/Gui/Stylesheets/images_classic/arrow-double-leftright-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-blue.png rename to src/Gui/Stylesheets/images_classic/arrow-double-leftright-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-darkgray.png b/src/Gui/Stylesheets/images_classic/arrow-double-leftright-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-darkgray.png rename to src/Gui/Stylesheets/images_classic/arrow-double-leftright-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-lightgray.png b/src/Gui/Stylesheets/images_classic/arrow-double-leftright-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-lightgray.png rename to src/Gui/Stylesheets/images_classic/arrow-double-leftright-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-white.png b/src/Gui/Stylesheets/images_classic/arrow-double-leftright-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-LeftRight-white.png rename to src/Gui/Stylesheets/images_classic/arrow-double-leftright-white.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-black.png b/src/Gui/Stylesheets/images_classic/arrow-double-updown-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-black.png rename to src/Gui/Stylesheets/images_classic/arrow-double-updown-black.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-blue.png b/src/Gui/Stylesheets/images_classic/arrow-double-updown-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-blue.png rename to src/Gui/Stylesheets/images_classic/arrow-double-updown-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-darkgray.png b/src/Gui/Stylesheets/images_classic/arrow-double-updown-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-darkgray.png rename to src/Gui/Stylesheets/images_classic/arrow-double-updown-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-lightgray.png b/src/Gui/Stylesheets/images_classic/arrow-double-updown-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-lightgray.png rename to src/Gui/Stylesheets/images_classic/arrow-double-updown-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-white.png b/src/Gui/Stylesheets/images_classic/arrow-double-updown-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-double-UpDown-white.png rename to src/Gui/Stylesheets/images_classic/arrow-double-updown-white.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-down-black.png b/src/Gui/Stylesheets/images_classic/arrow-down-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-down-black.png rename to src/Gui/Stylesheets/images_classic/arrow-down-black.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-down-blue.png b/src/Gui/Stylesheets/images_classic/arrow-down-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-down-blue.png rename to src/Gui/Stylesheets/images_classic/arrow-down-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-down-darkgray.png b/src/Gui/Stylesheets/images_classic/arrow-down-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-down-darkgray.png rename to src/Gui/Stylesheets/images_classic/arrow-down-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-down-lightgray.png b/src/Gui/Stylesheets/images_classic/arrow-down-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-down-lightgray.png rename to src/Gui/Stylesheets/images_classic/arrow-down-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-down-white.png b/src/Gui/Stylesheets/images_classic/arrow-down-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-down-white.png rename to src/Gui/Stylesheets/images_classic/arrow-down-white.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-left-black.png b/src/Gui/Stylesheets/images_classic/arrow-left-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-left-black.png rename to src/Gui/Stylesheets/images_classic/arrow-left-black.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-left-blue.png b/src/Gui/Stylesheets/images_classic/arrow-left-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-left-blue.png rename to src/Gui/Stylesheets/images_classic/arrow-left-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-left-darkgray.png b/src/Gui/Stylesheets/images_classic/arrow-left-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-left-darkgray.png rename to src/Gui/Stylesheets/images_classic/arrow-left-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-left-lightgray.png b/src/Gui/Stylesheets/images_classic/arrow-left-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-left-lightgray.png rename to src/Gui/Stylesheets/images_classic/arrow-left-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-left-white.png b/src/Gui/Stylesheets/images_classic/arrow-left-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-left-white.png rename to src/Gui/Stylesheets/images_classic/arrow-left-white.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-leftDown-black.png b/src/Gui/Stylesheets/images_classic/arrow-leftdown-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-leftDown-black.png rename to src/Gui/Stylesheets/images_classic/arrow-leftdown-black.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-leftDown-blue.png b/src/Gui/Stylesheets/images_classic/arrow-leftdown-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-leftDown-blue.png rename to src/Gui/Stylesheets/images_classic/arrow-leftdown-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-leftDown-darkgray.png b/src/Gui/Stylesheets/images_classic/arrow-leftdown-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-leftDown-darkgray.png rename to src/Gui/Stylesheets/images_classic/arrow-leftdown-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-leftDown-lightgray.png b/src/Gui/Stylesheets/images_classic/arrow-leftdown-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-leftDown-lightgray.png rename to src/Gui/Stylesheets/images_classic/arrow-leftdown-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-leftDown-white.png b/src/Gui/Stylesheets/images_classic/arrow-leftdown-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-leftDown-white.png rename to src/Gui/Stylesheets/images_classic/arrow-leftdown-white.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-right-black.png b/src/Gui/Stylesheets/images_classic/arrow-right-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-right-black.png rename to src/Gui/Stylesheets/images_classic/arrow-right-black.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-right-blue.png b/src/Gui/Stylesheets/images_classic/arrow-right-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-right-blue.png rename to src/Gui/Stylesheets/images_classic/arrow-right-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-right-darkgray.png b/src/Gui/Stylesheets/images_classic/arrow-right-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-right-darkgray.png rename to src/Gui/Stylesheets/images_classic/arrow-right-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-right-lightgray.png b/src/Gui/Stylesheets/images_classic/arrow-right-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-right-lightgray.png rename to src/Gui/Stylesheets/images_classic/arrow-right-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-right-white.png b/src/Gui/Stylesheets/images_classic/arrow-right-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-right-white.png rename to src/Gui/Stylesheets/images_classic/arrow-right-white.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-rightDown-black.png b/src/Gui/Stylesheets/images_classic/arrow-rightdown-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-rightDown-black.png rename to src/Gui/Stylesheets/images_classic/arrow-rightdown-black.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-rightDown-blue.png b/src/Gui/Stylesheets/images_classic/arrow-rightdown-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-rightDown-blue.png rename to src/Gui/Stylesheets/images_classic/arrow-rightdown-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-rightDown-darkgray.png b/src/Gui/Stylesheets/images_classic/arrow-rightdown-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-rightDown-darkgray.png rename to src/Gui/Stylesheets/images_classic/arrow-rightdown-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-rightDown-lightgray.png b/src/Gui/Stylesheets/images_classic/arrow-rightdown-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-rightDown-lightgray.png rename to src/Gui/Stylesheets/images_classic/arrow-rightdown-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-rightDown-white.png b/src/Gui/Stylesheets/images_classic/arrow-rightdown-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-rightDown-white.png rename to src/Gui/Stylesheets/images_classic/arrow-rightdown-white.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-up-black.png b/src/Gui/Stylesheets/images_classic/arrow-up-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-up-black.png rename to src/Gui/Stylesheets/images_classic/arrow-up-black.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-up-blue.png b/src/Gui/Stylesheets/images_classic/arrow-up-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-up-blue.png rename to src/Gui/Stylesheets/images_classic/arrow-up-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-up-darkgray.png b/src/Gui/Stylesheets/images_classic/arrow-up-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-up-darkgray.png rename to src/Gui/Stylesheets/images_classic/arrow-up-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-up-lightgray.png b/src/Gui/Stylesheets/images_classic/arrow-up-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-up-lightgray.png rename to src/Gui/Stylesheets/images_classic/arrow-up-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Arrow-up-white.png b/src/Gui/Stylesheets/images_classic/arrow-up-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Arrow-up-white.png rename to src/Gui/Stylesheets/images_classic/arrow-up-white.png diff --git a/src/Gui/Stylesheets/images_classic/checkbox-Empty-black.png b/src/Gui/Stylesheets/images_classic/checkbox-empty-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/checkbox-Empty-black.png rename to src/Gui/Stylesheets/images_classic/checkbox-empty-black.png diff --git a/src/Gui/Stylesheets/images_classic/checkbox-Empty-blue.png b/src/Gui/Stylesheets/images_classic/checkbox-empty-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/checkbox-Empty-blue.png rename to src/Gui/Stylesheets/images_classic/checkbox-empty-blue.png diff --git a/src/Gui/Stylesheets/images_classic/checkbox-Empty-darkgray.png b/src/Gui/Stylesheets/images_classic/checkbox-empty-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/checkbox-Empty-darkgray.png rename to src/Gui/Stylesheets/images_classic/checkbox-empty-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/checkbox-Empty-lightgray.png b/src/Gui/Stylesheets/images_classic/checkbox-empty-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/checkbox-Empty-lightgray.png rename to src/Gui/Stylesheets/images_classic/checkbox-empty-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/checkbox-Empty-white.png b/src/Gui/Stylesheets/images_classic/checkbox-empty-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/checkbox-Empty-white.png rename to src/Gui/Stylesheets/images_classic/checkbox-empty-white.png diff --git a/src/Gui/Stylesheets/images_classic/Close-DarkRed.png b/src/Gui/Stylesheets/images_classic/close-darkred.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Close-DarkRed.png rename to src/Gui/Stylesheets/images_classic/close-darkred.png diff --git a/src/Gui/Stylesheets/images_classic/Close-lightgray.png b/src/Gui/Stylesheets/images_classic/close-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Close-lightgray.png rename to src/Gui/Stylesheets/images_classic/close-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Hmovetoolbar-black.png b/src/Gui/Stylesheets/images_classic/hmovetoolbar-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hmovetoolbar-black.png rename to src/Gui/Stylesheets/images_classic/hmovetoolbar-black.png diff --git a/src/Gui/Stylesheets/images_classic/Hmovetoolbar-blue.png b/src/Gui/Stylesheets/images_classic/hmovetoolbar-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hmovetoolbar-blue.png rename to src/Gui/Stylesheets/images_classic/hmovetoolbar-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Hmovetoolbar-darkgray.png b/src/Gui/Stylesheets/images_classic/hmovetoolbar-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hmovetoolbar-darkgray.png rename to src/Gui/Stylesheets/images_classic/hmovetoolbar-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Hmovetoolbar-lightgray.png b/src/Gui/Stylesheets/images_classic/hmovetoolbar-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hmovetoolbar-lightgray.png rename to src/Gui/Stylesheets/images_classic/hmovetoolbar-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Hmovetoolbar-white.png b/src/Gui/Stylesheets/images_classic/hmovetoolbar-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hmovetoolbar-white.png rename to src/Gui/Stylesheets/images_classic/hmovetoolbar-white.png diff --git a/src/Gui/Stylesheets/images_classic/Hsepartoolbar-black.png b/src/Gui/Stylesheets/images_classic/hsepartoolbar-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hsepartoolbar-black.png rename to src/Gui/Stylesheets/images_classic/hsepartoolbar-black.png diff --git a/src/Gui/Stylesheets/images_classic/Hsepartoolbar-blue.png b/src/Gui/Stylesheets/images_classic/hsepartoolbar-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hsepartoolbar-blue.png rename to src/Gui/Stylesheets/images_classic/hsepartoolbar-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Hsepartoolbar-darkgray.png b/src/Gui/Stylesheets/images_classic/hsepartoolbar-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hsepartoolbar-darkgray.png rename to src/Gui/Stylesheets/images_classic/hsepartoolbar-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Hsepartoolbar-lightgray.png b/src/Gui/Stylesheets/images_classic/hsepartoolbar-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hsepartoolbar-lightgray.png rename to src/Gui/Stylesheets/images_classic/hsepartoolbar-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Hsepartoolbar-white.png b/src/Gui/Stylesheets/images_classic/hsepartoolbar-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Hsepartoolbar-white.png rename to src/Gui/Stylesheets/images_classic/hsepartoolbar-white.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_fold_black.png b/src/Gui/Stylesheets/images_classic/qsint_header_fold_black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_fold_black.png rename to src/Gui/Stylesheets/images_classic/qsint_header_fold_black.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_Fold_Blue-Blue.png b/src/Gui/Stylesheets/images_classic/qsint_header_fold_blue-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_Fold_Blue-Blue.png rename to src/Gui/Stylesheets/images_classic/qsint_header_fold_blue-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_Fold_Blue-dark.png b/src/Gui/Stylesheets/images_classic/qsint_header_fold_blue-dark.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_Fold_Blue-dark.png rename to src/Gui/Stylesheets/images_classic/qsint_header_fold_blue-dark.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_Fold_Blue-light.png b/src/Gui/Stylesheets/images_classic/qsint_header_fold_blue-light.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_Fold_Blue-light.png rename to src/Gui/Stylesheets/images_classic/qsint_header_fold_blue-light.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_fold_darkgray.png b/src/Gui/Stylesheets/images_classic/qsint_header_fold_darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_fold_darkgray.png rename to src/Gui/Stylesheets/images_classic/qsint_header_fold_darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_fold_lightgray.png b/src/Gui/Stylesheets/images_classic/qsint_header_fold_lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_fold_lightgray.png rename to src/Gui/Stylesheets/images_classic/qsint_header_fold_lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_fold_white.png b/src/Gui/Stylesheets/images_classic/qsint_header_fold_white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_fold_white.png rename to src/Gui/Stylesheets/images_classic/qsint_header_fold_white.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_FoldOver_Blue-Blue.png b/src/Gui/Stylesheets/images_classic/qsint_header_foldover_blue-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_FoldOver_Blue-Blue.png rename to src/Gui/Stylesheets/images_classic/qsint_header_foldover_blue-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_FoldOver_Blue-dark.png b/src/Gui/Stylesheets/images_classic/qsint_header_foldover_blue-dark.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_FoldOver_Blue-dark.png rename to src/Gui/Stylesheets/images_classic/qsint_header_foldover_blue-dark.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_FoldOver_Blue-light.png b/src/Gui/Stylesheets/images_classic/qsint_header_foldover_blue-light.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_FoldOver_Blue-light.png rename to src/Gui/Stylesheets/images_classic/qsint_header_foldover_blue-light.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_unfold_black.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfold_black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_unfold_black.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfold_black.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_Unfold_Blue-Blue.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfold_blue-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_Unfold_Blue-Blue.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfold_blue-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_Unfold_Blue-dark.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfold_blue-dark.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_Unfold_Blue-dark.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfold_blue-dark.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_Unfold_Blue-light.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfold_blue-light.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_Unfold_Blue-light.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfold_blue-light.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_unfold_darkgray.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfold_darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_unfold_darkgray.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfold_darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_unfold_lightgray.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfold_lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_unfold_lightgray.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfold_lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_unfold_white.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfold_white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_unfold_white.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfold_white.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_UnFoldOver_Blue-Blue.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfoldover_blue-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_UnFoldOver_Blue-Blue.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfoldover_blue-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_UnfoldOver_Blue-dark.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfoldover_blue-dark.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_UnfoldOver_Blue-dark.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfoldover_blue-dark.png diff --git a/src/Gui/Stylesheets/images_classic/Qsint_header_UnfoldOver_Blue-light.png b/src/Gui/Stylesheets/images_classic/qsint_header_unfoldover_blue-light.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Qsint_header_UnfoldOver_Blue-light.png rename to src/Gui/Stylesheets/images_classic/qsint_header_unfoldover_blue-light.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-checked-black.png b/src/Gui/Stylesheets/images_classic/radio-checked-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-checked-black.png rename to src/Gui/Stylesheets/images_classic/radio-checked-black.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-checked-blue.png b/src/Gui/Stylesheets/images_classic/radio-checked-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-checked-blue.png rename to src/Gui/Stylesheets/images_classic/radio-checked-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-checked-darkgray.png b/src/Gui/Stylesheets/images_classic/radio-checked-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-checked-darkgray.png rename to src/Gui/Stylesheets/images_classic/radio-checked-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-checked-lightgray.png b/src/Gui/Stylesheets/images_classic/radio-checked-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-checked-lightgray.png rename to src/Gui/Stylesheets/images_classic/radio-checked-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-checked-white.png b/src/Gui/Stylesheets/images_classic/radio-checked-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-checked-white.png rename to src/Gui/Stylesheets/images_classic/radio-checked-white.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-unchecked-black.png b/src/Gui/Stylesheets/images_classic/radio-unchecked-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-unchecked-black.png rename to src/Gui/Stylesheets/images_classic/radio-unchecked-black.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-unchecked-blue.png b/src/Gui/Stylesheets/images_classic/radio-unchecked-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-unchecked-blue.png rename to src/Gui/Stylesheets/images_classic/radio-unchecked-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-unchecked-darkgray.png b/src/Gui/Stylesheets/images_classic/radio-unchecked-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-unchecked-darkgray.png rename to src/Gui/Stylesheets/images_classic/radio-unchecked-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-unchecked-lightgray.png b/src/Gui/Stylesheets/images_classic/radio-unchecked-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-unchecked-lightgray.png rename to src/Gui/Stylesheets/images_classic/radio-unchecked-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Radio-unchecked-white.png b/src/Gui/Stylesheets/images_classic/radio-unchecked-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Radio-unchecked-white.png rename to src/Gui/Stylesheets/images_classic/radio-unchecked-white.png diff --git a/src/Gui/Stylesheets/images_classic/Vmovetoolbar-black.png b/src/Gui/Stylesheets/images_classic/vmovetoolbar-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vmovetoolbar-black.png rename to src/Gui/Stylesheets/images_classic/vmovetoolbar-black.png diff --git a/src/Gui/Stylesheets/images_classic/Vmovetoolbar-blue.png b/src/Gui/Stylesheets/images_classic/vmovetoolbar-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vmovetoolbar-blue.png rename to src/Gui/Stylesheets/images_classic/vmovetoolbar-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Vmovetoolbar-darkgray.png b/src/Gui/Stylesheets/images_classic/vmovetoolbar-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vmovetoolbar-darkgray.png rename to src/Gui/Stylesheets/images_classic/vmovetoolbar-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Vmovetoolbar-lightgray.png b/src/Gui/Stylesheets/images_classic/vmovetoolbar-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vmovetoolbar-lightgray.png rename to src/Gui/Stylesheets/images_classic/vmovetoolbar-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Vmovetoolbar-white.png b/src/Gui/Stylesheets/images_classic/vmovetoolbar-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vmovetoolbar-white.png rename to src/Gui/Stylesheets/images_classic/vmovetoolbar-white.png diff --git a/src/Gui/Stylesheets/images_classic/Vsepartoolbar-black.png b/src/Gui/Stylesheets/images_classic/vsepartoolbar-black.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vsepartoolbar-black.png rename to src/Gui/Stylesheets/images_classic/vsepartoolbar-black.png diff --git a/src/Gui/Stylesheets/images_classic/Vsepartoolbar-blue.png b/src/Gui/Stylesheets/images_classic/vsepartoolbar-blue.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vsepartoolbar-blue.png rename to src/Gui/Stylesheets/images_classic/vsepartoolbar-blue.png diff --git a/src/Gui/Stylesheets/images_classic/Vsepartoolbar-darkgray.png b/src/Gui/Stylesheets/images_classic/vsepartoolbar-darkgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vsepartoolbar-darkgray.png rename to src/Gui/Stylesheets/images_classic/vsepartoolbar-darkgray.png diff --git a/src/Gui/Stylesheets/images_classic/Vsepartoolbar-lightgray.png b/src/Gui/Stylesheets/images_classic/vsepartoolbar-lightgray.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vsepartoolbar-lightgray.png rename to src/Gui/Stylesheets/images_classic/vsepartoolbar-lightgray.png diff --git a/src/Gui/Stylesheets/images_classic/Vsepartoolbar-white.png b/src/Gui/Stylesheets/images_classic/vsepartoolbar-white.png similarity index 100% rename from src/Gui/Stylesheets/images_classic/Vsepartoolbar-white.png rename to src/Gui/Stylesheets/images_classic/vsepartoolbar-white.png diff --git a/src/Gui/TaskDlgRelocation.cpp b/src/Gui/TaskDlgRelocation.cpp index 01d90432c7..c6008264a4 100644 --- a/src/Gui/TaskDlgRelocation.cpp +++ b/src/Gui/TaskDlgRelocation.cpp @@ -22,8 +22,8 @@ #include "PreCompiled.h" -#include "ui_DlgLocationAngle.h" -#include "ui_DlgLocationPos.h" +#include "Dialogs/ui_DlgLocationAngle.h" +#include "Dialogs/ui_DlgLocationPos.h" #include "TaskDlgRelocation.h" #include "BitmapFactory.h" diff --git a/src/Gui/TaskView/TaskAppearance.h b/src/Gui/TaskView/TaskAppearance.h index 30b0256924..e6658ec0b3 100644 --- a/src/Gui/TaskView/TaskAppearance.h +++ b/src/Gui/TaskView/TaskAppearance.h @@ -24,7 +24,7 @@ #ifndef GUI_TASKVIEW_TASKAPPERANCE_H #define GUI_TASKVIEW_TASKAPPERANCE_H -#include +#include #include "TaskView.h" diff --git a/src/Gui/TaskView/TaskSelectLinkProperty.cpp b/src/Gui/TaskView/TaskSelectLinkProperty.cpp index e4176d7deb..51c3b630e2 100644 --- a/src/Gui/TaskView/TaskSelectLinkProperty.cpp +++ b/src/Gui/TaskView/TaskSelectLinkProperty.cpp @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include #include "ui_TaskSelectLinkProperty.h" #include "TaskSelectLinkProperty.h" diff --git a/src/Gui/TaskView/TaskSelectLinkProperty.h b/src/Gui/TaskView/TaskSelectLinkProperty.h index 099179d229..b729370337 100644 --- a/src/Gui/TaskView/TaskSelectLinkProperty.h +++ b/src/Gui/TaskView/TaskSelectLinkProperty.h @@ -25,7 +25,7 @@ #define GUI_TASKVIEW_TaskSelectLinkProperty_H #include "TaskView.h" -#include +#include #include diff --git a/src/Gui/TaskView/TaskView.h b/src/Gui/TaskView/TaskView.h index c15d3ab0a4..f613c4d0d1 100644 --- a/src/Gui/TaskView/TaskView.h +++ b/src/Gui/TaskView/TaskView.h @@ -28,7 +28,7 @@ #include #include -#include +#include #include "TaskWatcher.h" diff --git a/src/Gui/TaskView/TaskWatcher.h b/src/Gui/TaskView/TaskWatcher.h index 9778fe8db5..a9c9d7707b 100644 --- a/src/Gui/TaskView/TaskWatcher.h +++ b/src/Gui/TaskView/TaskWatcher.h @@ -27,7 +27,7 @@ #include #include -#include +#include namespace Gui { diff --git a/src/Gui/TextDocumentEditorView.cpp b/src/Gui/TextDocumentEditorView.cpp index ef859f6a76..c9b40768e4 100644 --- a/src/Gui/TextDocumentEditorView.cpp +++ b/src/Gui/TextDocumentEditorView.cpp @@ -115,7 +115,7 @@ void TextDocumentEditorView::textChanged() void TextDocumentEditorView::labelChanged() { - setWindowTitle(QString::fromUtf8(textDocument->Label.getValue()) + QString::fromLatin1("[*]")); + setWindowTitle(QString::fromUtf8(textDocument->Label.getValue()) + QStringLiteral("[*]")); } void TextDocumentEditorView::refresh() diff --git a/src/Gui/TextEdit.cpp b/src/Gui/TextEdit.cpp index 5e19327e10..68ae0efd99 100644 --- a/src/Gui/TextEdit.cpp +++ b/src/Gui/TextEdit.cpp @@ -60,7 +60,7 @@ TextEdit::TextEdit(QWidget* parent) //Note: Set the correct context to this shortcut as we may use several instances of this //class at a time auto shortcut = new QShortcut(this); - shortcut->setKey(QKeySequence(QString::fromLatin1("CTRL+Space"))); + shortcut->setKey(QKeySequence(QStringLiteral("CTRL+Space"))); shortcut->setContext(Qt::WidgetShortcut); connect(shortcut, &QShortcut::activated, this, &TextEdit::complete); @@ -502,7 +502,7 @@ void PythonTextEditor::keyPressEvent (QKeyEvent * e) bool space = hPrefGrp->GetBool("Spaces", true); int indent = hPrefGrp->GetInt( "IndentSize", 4 ); QString ch = space ? QString(indent, QLatin1Char(' ')) - : QString::fromLatin1("\t"); + : QStringLiteral("\t"); QTextCursor cursor = textCursor(); if (!cursor.hasSelection()) { diff --git a/src/Gui/TextureMapping.cpp b/src/Gui/TextureMapping.cpp index 4a928801ba..72a5e565dd 100644 --- a/src/Gui/TextureMapping.cpp +++ b/src/Gui/TextureMapping.cpp @@ -65,7 +65,7 @@ TextureMapping::TextureMapping(QWidget* parent, Qt::WindowFlags fl) QStringList formats; QList qtformats = QImageReader::supportedImageFormats(); for (const auto & it : qtformats) { - formats << QString::fromLatin1("*.%1").arg(QLatin1String(it)); + formats << QStringLiteral("*.%1").arg(QLatin1String(it)); } ui->fileChooser->setFilter(tr("Image files (%1)").arg(formats.join(QLatin1String(" ")))); @@ -143,7 +143,7 @@ void TextureMapping::onFileChooserFileNameSelected(const QString& s) Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (doc) { Gui::MDIView* mdi = doc->getActiveView(); - if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) { + if (mdi && mdi->isDerivedFrom()) { Gui::View3DInventorViewer* view = static_cast(mdi)->getViewer(); this->grp = static_cast(view->getSceneGraph()); this->grp->ref(); diff --git a/src/Gui/Thumbnail.cpp b/src/Gui/Thumbnail.cpp index c822e26c09..fed843fc83 100644 --- a/src/Gui/Thumbnail.cpp +++ b/src/Gui/Thumbnail.cpp @@ -113,7 +113,7 @@ void Thumbnail::SaveDocFile (Base::Writer &writer) const if (!px.isNull()) { // according to specification add some meta-information to the image qint64 mt = QDateTime::currentDateTimeUtc().toSecsSinceEpoch(); - QString mtime = QString::fromLatin1("%1").arg(mt); + QString mtime = QStringLiteral("%1").arg(mt); img.setText(QLatin1String("Software"), qApp->applicationName()); img.setText(QLatin1String("Thumb::Mimetype"), QLatin1String("application/x-extension-fcstd")); img.setText(QLatin1String("Thumb::MTime"), mtime); diff --git a/src/Gui/ToolHandler.cpp b/src/Gui/ToolHandler.cpp index bb20296449..606e2527be 100644 --- a/src/Gui/ToolHandler.cpp +++ b/src/Gui/ToolHandler.cpp @@ -48,7 +48,7 @@ using namespace Gui; QString ToolHandler::getCrosshairCursorSVGName() const { - return QString::fromLatin1("None"); + return QStringLiteral("None"); } bool ToolHandler::activate() @@ -230,7 +230,7 @@ void ToolHandler::updateCursor() { auto cursorstring = getCrosshairCursorSVGName(); - if (cursorstring != QString::fromLatin1("None")) { + if (cursorstring != QStringLiteral("None")) { setCrosshairCursor(cursorstring); } } @@ -281,7 +281,7 @@ void ToolHandler::setWidgetCursor(QCursor cursor) Gui::View3DInventorViewer* ToolHandler::getViewer() { Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); - if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + if (view && view->isDerivedFrom()) { return static_cast(view)->getViewer(); } return nullptr; diff --git a/src/Gui/ToolHandler.h b/src/Gui/ToolHandler.h index 100fa5bd5f..11803c7561 100644 --- a/src/Gui/ToolHandler.h +++ b/src/Gui/ToolHandler.h @@ -29,7 +29,7 @@ #include #include -#include "Selection.h" +#include "Selection/Selection.h" namespace Gui diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index fa31e9a49b..03473cc240 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -439,7 +439,7 @@ TreeWidgetItemDelegate::TreeWidgetItemDelegate(QObject* parent) : QStyledItemDelegate(parent) { artificial = new QTreeView(qobject_cast(parent)); - artificial->setObjectName(QString::fromLatin1("DocumentTreeItems")); + artificial->setObjectName(QStringLiteral("DocumentTreeItems")); artificial->setFixedSize(0, 0); // ensure that it does not render } @@ -1075,7 +1075,7 @@ void TreeWidget::contextMenuEvent(QContextMenuEvent* e) contextMenu.addAction(this->toggleVisibilityInTreeAction); if (!acrossDocuments) { // is only sensible for selections within one document - if (objitem->object()->getObject()->isDerivedFrom(App::DocumentObjectGroup::getClassTypeId())) + if (objitem->object()->getObject()->isDerivedFrom()) contextMenu.addAction(this->createGroupAction); // if there are dependent objects in the selection, add context menu to add them to selection if (CheckForDependents()) @@ -1201,7 +1201,7 @@ void TreeWidget::onCreateGroup() if (this->contextItem->type() == DocumentType) { auto docitem = static_cast(this->contextItem); App::Document* doc = docitem->document()->getDocument(); - QString cmd = QString::fromLatin1("App.getDocument(\"%1\").addObject" + QString cmd = QStringLiteral("App.getDocument(\"%1\").addObject" "(\"App::DocumentObjectGroup\",\"Group\").Label=\"%2\"") .arg(QString::fromLatin1(doc->getName()), name); Gui::Command::runCommand(Gui::Command::App, cmd.toUtf8()); @@ -1211,7 +1211,7 @@ void TreeWidget::onCreateGroup() (this->contextItem); App::DocumentObject* obj = objitem->object()->getObject(); App::Document* doc = obj->getDocument(); - QString cmd = QString::fromLatin1("App.getDocument(\"%1\").getObject(\"%2\")" + QString cmd = QStringLiteral("App.getDocument(\"%1\").getObject(\"%2\")" ".newObject(\"App::DocumentObjectGroup\",\"Group\").Label=\"%3\"") .arg(QString::fromLatin1(doc->getName()), QString::fromLatin1(obj->getNameInDocument()), @@ -2885,7 +2885,7 @@ void TreeWidget::slotRenameDocument(const Gui::Document& Doc) void TreeWidget::slotChangedViewObject(const Gui::ViewProvider& vp, const App::Property& prop) { if (!App::GetApplication().isRestoring() - && vp.isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) + && vp.isDerivedFrom()) { const auto& vpd = static_cast(vp); if (&prop == &vpd.ShowInTree) { diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h index b643e65686..6c3c37ad99 100644 --- a/src/Gui/Tree.h +++ b/src/Gui/Tree.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include class QLineEdit; diff --git a/src/Gui/VectorListEditor.cpp b/src/Gui/VectorListEditor.cpp index cb181b6893..9450145b7f 100644 --- a/src/Gui/VectorListEditor.cpp +++ b/src/Gui/VectorListEditor.cpp @@ -26,6 +26,7 @@ #include "ui_VectorListEditor.h" #include "QuantitySpinBox.h" +#include #include #include @@ -115,7 +116,7 @@ QVariant VectorTableModel::data(const QModelIndex &index, int role) const d = vectors[r].z; if (role == Qt::DisplayRole) { - QString str = QString::fromLatin1("%1").arg(d, 0, 'f', decimals); + QString str = QStringLiteral("%1").arg(d, 0, 'f', decimals); return str; } @@ -142,11 +143,14 @@ void Gui::VectorTableModel::copyToClipboard() const { QString clipboardText; QTextStream stream(&clipboardText); + int precision = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units") + ->GetInt("PropertyVectorListCopyPrecision", 16); for (const auto& vector : vectors) { - stream << QString::number(vector.x, 'f', decimals) << '\t' - << QString::number(vector.y, 'f', decimals) << '\t' - << QString::number(vector.z, 'f', decimals) << '\n'; + stream << QString::number(vector.x, 'f', precision) << '\t' + << QString::number(vector.y, 'f', precision) << '\t' + << QString::number(vector.z, 'f', precision) << '\n'; } QApplication::clipboard()->setText(clipboardText); diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index 603872b9d9..87e9615046 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -50,6 +50,8 @@ # include #endif + +#include #include #include #include @@ -65,7 +67,7 @@ #include "FileDialog.h" #include "MainWindow.h" #include "NaviCube.h" -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "SoFCDB.h" #include "SoFCSelectionAction.h" #include "SoFCVectorizeSVGAction.h" @@ -248,7 +250,7 @@ void View3DInventor::print() void View3DInventor::printPdf() { QString filename = FileDialog::getSaveFileName(this, tr("Export PDF"), QString(), - QString::fromLatin1("%1 (*.pdf)").arg(tr("PDF file"))); + QStringLiteral("%1 (*.pdf)").arg(tr("PDF file"))); if (!filename.isEmpty()) { Gui::WaitCursor wc; QPrinter printer(QPrinter::ScreenResolution); @@ -257,6 +259,7 @@ void View3DInventor::printPdf() printer.setOutputFormat(QPrinter::PdfFormat); printer.setPageOrientation(QPageLayout::Landscape); printer.setOutputFileName(filename); + printer.setCreator(QString::fromStdString(App::Application::getNameWithVersion())); print(&printer); } } @@ -808,7 +811,7 @@ RayPickInfo View3DInventor::getObjInfoRay(Base::Vector3d* startvec, Base::Vector ret.point = Base::convertTo(Point->getPoint()); ViewProvider* vp = getViewer()->getViewProviderByPath(Point->getPath()); - if (vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + if (vp && vp->isDerivedFrom()) { if (!vp->isSelectable()) { return ret; } diff --git a/src/Gui/View3DInventorSelection.h b/src/Gui/View3DInventorSelection.h index 523258d5da..39f8c38f1d 100644 --- a/src/Gui/View3DInventorSelection.h +++ b/src/Gui/View3DInventorSelection.h @@ -25,7 +25,7 @@ #include #include -#include +#include class SoGroup; class SoNode; diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index ff57cede1b..cd21a948d5 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -107,7 +107,7 @@ #include "MainWindow.h" #include "Multisample.h" #include "NaviCube.h" -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "Selection.h" #include "SoDevicePixelRatioElement.h" #include "SoFCDB.h" @@ -126,8 +126,8 @@ #include "ViewProvider.h" #include "ViewProviderDocumentObject.h" #include "ViewProviderLink.h" -#include "NavigationAnimator.h" -#include "NavigationAnimation.h" +#include "Navigation/NavigationAnimator.h" +#include "Navigation/NavigationAnimation.h" #include "Utilities.h" #include @@ -486,8 +486,6 @@ void View3DInventorViewer::init() // increase refcount before passing it to setScenegraph(), to avoid // premature destruction pcViewProviderRoot->ref(); - // is not really working with Coin3D. - //redrawOverlayOnSelectionChange(pcSelection); setSceneGraph(pcViewProviderRoot); // Event callback node pEventCallback = new SoEventCallback(); @@ -569,7 +567,11 @@ void View3DInventorViewer::init() //filter a few qt events viewerEventFilter = new ViewerEventFilter; installEventFilter(viewerEventFilter); - getEventFilter()->registerInputDevice(new SpaceNavigatorDevice); + ParameterGrp::handle hViewGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/View"); + if (hViewGrp->GetBool("LegacySpaceMouseDevices", false)) { + getEventFilter()->registerInputDevice(new SpaceNavigatorDevice); + } getEventFilter()->registerInputDevice(new GesturesDevice(this)); try{ @@ -588,6 +590,8 @@ void View3DInventorViewer::init() naviCube = new NaviCube(this); naviCubeEnabled = true; + + updateColors(); } View3DInventorViewer::~View3DInventorViewer() @@ -788,11 +792,11 @@ void View3DInventorViewer::onSelectionChanged(const SelectionChanges & reason) { //Hint: do not create a tmp. instance of SelectionChanges SelectionChanges selChanges(SelectionChanges::RmvPreselect); - SoFCHighlightAction cAct(selChanges); - cAct.apply(pcViewProviderRoot); + SoFCPreselectionAction preselectionAction(selChanges); + preselectionAction.apply(pcViewProviderRoot); } else { - SoFCSelectionAction cAct(Reason); - cAct.apply(pcViewProviderRoot); + SoFCSelectionAction selectionAction(Reason); + selectionAction.apply(pcViewProviderRoot); } } /// @endcond @@ -804,7 +808,7 @@ bool View3DInventorViewer::searchNode(SoNode* node) const searchAction.setInterest(SoSearchAction::FIRST); searchAction.apply(this->getSceneGraph()); SoPath* selectionPath = searchAction.getPath(); - return selectionPath ? true : false; + return selectionPath != nullptr; } bool View3DInventorViewer::hasViewProvider(ViewProvider* pcProvider) const @@ -1136,7 +1140,12 @@ void View3DInventorViewer::setOverrideMode(const std::string& mode) overrideMode = mode; - auto views = getDocument()->getViewProvidersOfType(Gui::ViewProvider::getClassTypeId()); + auto document = getDocument(); + if (!document) { + return; + } + + auto views = document->getViewProvidersOfType(Gui::ViewProvider::getClassTypeId()); if (mode == "No Shading") { this->shading = false; std::string flatLines = "Flat Lines"; @@ -1792,14 +1801,12 @@ const std::vector& View3DInventorViewer::getPolygon(SelectionRole* role void View3DInventorViewer::setSelectionEnabled(bool enable) { - SoNode* root = getSceneGraph(); - static_cast(root)->selectionRole.setValue(enable); // NOLINT + this->selectionRoot->selectionEnabled.setValue(enable); // NOLINT } bool View3DInventorViewer::isSelectionEnabled() const { - SoNode* root = getSceneGraph(); - return static_cast(root)->selectionRole.getValue(); // NOLINT + return this->selectionRoot->selectionEnabled.getValue(); // NOLINT } SbVec2f View3DInventorViewer::screenCoordsOfPath(SoPath* path) const @@ -2444,12 +2451,42 @@ void View3DInventorViewer::renderScene() stream.precision(1); stream.setf(std::ios::fixed | std::ios::showpoint); stream << framesPerSecond[0] << " ms / " << framesPerSecond[1] << " fps"; - draw2DString(stream.str().c_str(), SbVec2s(10, 10), SbVec2f(0.1F, 0.1F)); // NOLINT + ParameterGrp::handle hGrpOverlayL = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/MainWindow/DockWindows/OverlayLeft"); + std::string overlayLeftWidgets = hGrpOverlayL->GetASCII("Widgets", ""); + ParameterGrp::handle hGrpView = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/View"); + unsigned long axisLetterColor = + hGrpView->GetUnsigned("AxisLetterColor", 4294902015); // default FPS color (yellow) + draw2DString(stream.str().c_str(), + SbVec2s(10, 10), + SbVec2f((overlayLeftWidgets.empty() ? 0.1f : 1.1f), 0.1f), + App::Color(static_cast(axisLetterColor))); // NOLINT } if (naviCubeEnabled) { naviCube->drawNaviCube(); } + + // Workaround for inconsistent QT behavior related to handling custom OpenGL widgets that + // leave non opaque alpha values in final output. + // On wayland that can cause window to become transparent or blurry trail effect in the + // parts that contain partially transparent objects. + // + // At the end of rendering clear alpha value, so that it doesn't matter how rest of the + // compositing stack at QT and desktop level would interpret transparent pixels. + // + // Related issues: + // https://bugreports.qt.io/browse/QTBUG-110014 + // https://bugreports.qt.io/browse/QTBUG-132197 + // https://bugreports.qt.io/browse/QTBUG-119214 + // https://github.com/FreeCAD/FreeCAD/issues/8341 + // https://github.com/FreeCAD/FreeCAD/issues/6177 + glPushAttrib(GL_COLOR_BUFFER_BIT); + glColorMask(false, false, false, true); + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + glPopAttrib(); } void View3DInventorViewer::setSeekMode(bool on) @@ -3706,6 +3743,25 @@ void View3DInventorViewer::setAxisLetterColor(const SbColor& color) recolor(ZPM_PIXEL_MASK, ZPM_pixel_data, ZPM_WIDTH, ZPM_HEIGHT, ZPM_BYTES_PER_PIXEL); } +void View3DInventorViewer::updateColors() +{ + unsigned long colorLong; + + colorLong = Gui::ViewParams::instance()->getAxisXColor(); + m_xColor = App::Color(static_cast(colorLong)); + colorLong = Gui::ViewParams::instance()->getAxisYColor(); + m_yColor = App::Color(static_cast(colorLong)); + colorLong = Gui::ViewParams::instance()->getAxisZColor(); + m_zColor = App::Color(static_cast(colorLong)); + + naviCube->updateColors(); + + if(hasAxisCross()) { + setAxisCross(false); // Force redraw + setAxisCross(true); + } +} + void View3DInventorViewer::drawAxisCross() { // NOLINTBEGIN @@ -3813,10 +3869,10 @@ void View3DInventorViewer::drawAxisCross() glPushMatrix(); if (i == XAXIS) { // X axis. - if (stereoMode() != Quarter::SoQTQuarterAdaptor::MONO) - glColor3f(0.500F, 0.5F, 0.5F); + if (stereoMode() != Quarter::SoQTQuarterAdaptor::MONO) // What is this + glColor3f(0.500F, 0.5F, 0.5F); // Why different colors?? else - glColor3f(0.500F, 0.125F, 0.125F); + glColor3f(m_xColor.r, m_xColor.g, m_xColor.b); } else if (i == YAXIS) { // Y axis. glRotatef(90, 0, 0, 1); @@ -3824,7 +3880,7 @@ void View3DInventorViewer::drawAxisCross() if (stereoMode() != Quarter::SoQTQuarterAdaptor::MONO) glColor3f(0.400F, 0.4F, 0.4F); else - glColor3f(0.125F, 0.500F, 0.125F); + glColor3f(m_yColor.r, m_yColor.g, m_yColor.b); } else { // Z axis. glRotatef(-90, 0, 1, 0); @@ -3832,7 +3888,7 @@ void View3DInventorViewer::drawAxisCross() if (stereoMode() != Quarter::SoQTQuarterAdaptor::MONO) glColor3f(0.300F, 0.3F, 0.3F); else - glColor3f(0.125F, 0.125F, 0.500F); + glColor3f(m_zColor.r, m_zColor.g, m_zColor.b); } drawArrow(); diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 1a520e616c..e7c1e867fc 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -40,7 +40,7 @@ #include #include "Namespace.h" -#include "Selection.h" +#include "Selection/Selection.h" #include "CornerCrossLetters.h" #include "View3DInventorSelection.h" @@ -434,6 +434,9 @@ public: bool isEnabledVBO() const; void setRenderCache(int); + //! Update colors of axis in corner to match preferences + void updateColors(); + void getDimensions(float& fHeight, float& fWidth) const; float getMaxDimension() const; SbVec3f getCenterPointOnFocalPlane() const; @@ -531,6 +534,10 @@ private: bool vboEnabled; bool naviCubeEnabled; + App::Color m_xColor; + App::Color m_yColor; + App::Color m_zColor; + bool editing; QCursor editCursor, zoomCursor, panCursor, spinCursor; bool redirected; diff --git a/src/Gui/View3DPy.cpp b/src/Gui/View3DPy.cpp index 138e457fc3..eb8b946289 100644 --- a/src/Gui/View3DPy.cpp +++ b/src/Gui/View3DPy.cpp @@ -56,7 +56,7 @@ #include "Camera.h" #include "Document.h" #include "Inventor/SoMouseWheelEvent.h" -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "PythonWrapper.h" #include "SoFCDB.h" #include "SoFCOffscreenRenderer.h" @@ -1282,8 +1282,8 @@ Py::Object View3DInventorPy::getCursorPos() auto viewer = getView3DInventorPtr()->getViewer(); SbVec2s vec = viewer->fromQPoint(pos); Py::Tuple tuple(2); - tuple.setItem(0, Py::Int(vec[0])); - tuple.setItem(1, Py::Int(vec[1])); + tuple.setItem(0, Py::Long(vec[0])); + tuple.setItem(1, Py::Long(vec[1])); return tuple; } catch (const Py::Exception&) { @@ -1300,13 +1300,13 @@ Py::Object View3DInventorPy::getObjectInfo(const Py::Tuple& args) try { //Note: For gcc (4.2) we need the 'const' keyword to avoid the compiler error: - //conversion from 'Py::seqref' to non-scalar type 'Py::Int' requested + //conversion from 'Py::seqref' to non-scalar type 'Py::Long' requested //We should report this problem to the PyCXX project as in the documentation an //example without the 'const' keyword is used. - //Or we can also write Py::Int x(tuple[0]); + //Or we can also write Py::Long x(tuple[0]); const Py::Tuple tuple(object); - Py::Int x(tuple[0]); - Py::Int y(tuple[1]); + Py::Long x(tuple[0]); + Py::Long y(tuple[1]); // As this method could be called during a SoHandleEventAction scene // graph traversal we must not use a second SoHandleEventAction as @@ -1327,7 +1327,7 @@ Py::Object View3DInventorPy::getObjectInfo(const Py::Tuple& args) dict.setItem("z", Py::Float(pt[2])); ViewProvider *vp = getView3DInventorPtr()->getViewer()->getViewProviderByPath(Point->getPath()); - if (vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + if (vp && vp->isDerivedFrom()) { if (!vp->isSelectable()) return ret; auto vpd = static_cast(vp); @@ -1406,13 +1406,13 @@ Py::Object View3DInventorPy::getObjectsInfo(const Py::Tuple& args) try { //Note: For gcc (4.2) we need the 'const' keyword to avoid the compiler error: - //conversion from 'Py::seqref' to non-scalar type 'Py::Int' requested + //conversion from 'Py::seqref' to non-scalar type 'Py::Long' requested //We should report this problem to the PyCXX project as in the documentation an //example without the 'const' keyword is used. - //Or we can also write Py::Int x(tuple[0]); + //Or we can also write Py::Long x(tuple[0]); const Py::Tuple tuple(object); - Py::Int x(tuple[0]); - Py::Int y(tuple[1]); + Py::Long x(tuple[0]); + Py::Long y(tuple[1]); // As this method could be called during a SoHandleEventAction scene // graph traversal we must not use a second SoHandleEventAction as @@ -1437,7 +1437,7 @@ Py::Object View3DInventorPy::getObjectsInfo(const Py::Tuple& args) dict.setItem("z", Py::Float(pt[2])); ViewProvider *vp = getView3DInventorPtr()->getViewer()->getViewProviderByPath(point->getPath()); - if(vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + if(vp && vp->isDerivedFrom()) { if(!vp->isSelectable()) continue; auto vpd = static_cast(vp); @@ -1562,8 +1562,8 @@ Py::Object View3DInventorPy::getSize() try { SbVec2s size = getView3DInventorPtr()->getViewer()->getSoRenderManager()->getSize(); Py::Tuple tuple(2); - tuple.setItem(0, Py::Int(size[0])); - tuple.setItem(1, Py::Int(size[1])); + tuple.setItem(0, Py::Long(size[0])); + tuple.setItem(1, Py::Long(size[1])); return tuple; } catch (const Py::Exception&) { @@ -1577,8 +1577,8 @@ Py::Object View3DInventorPy::getPointOnFocalPlane(const Py::Tuple& args) if (!PyArg_ParseTuple(args.ptr(), "hh", &x, &y)) { PyErr_Clear(); Py::Tuple t(args[0]); - x = (int)Py::Int(t[0]); - y = (int)Py::Int(t[1]); + x = (int)Py::Long(t[0]); + y = (int)Py::Long(t[1]); } try { SbVec3f pt = getView3DInventorPtr()->getViewer()->getPointOnFocalPlane(SbVec2s(x,y)); @@ -1612,8 +1612,8 @@ Py::Object View3DInventorPy::getPointOnViewport(const Py::Tuple& args) try { SbVec2s pt = getView3DInventorPtr()->getViewer()->getPointOnViewport(SbVec3f(vx,vy,vz)); Py::Tuple tuple(2); - tuple.setItem(0, Py::Int(pt[0])); - tuple.setItem(1, Py::Int(pt[1])); + tuple.setItem(0, Py::Long(pt[0])); + tuple.setItem(1, Py::Long(pt[1])); return tuple; } @@ -1631,8 +1631,8 @@ Py::Object View3DInventorPy::projectPointToLine(const Py::Tuple& args) if (!PyArg_ParseTuple(args.ptr(), "hh", &x, &y)) { PyErr_Clear(); Py::Tuple t(args[0]); - x = (int)Py::Int(t[0]); - y = (int)Py::Int(t[1]); + x = (int)Py::Long(t[0]); + y = (int)Py::Long(t[1]); } try { SbVec3f pt1, pt2; @@ -1691,8 +1691,8 @@ void View3DInventorPy::eventCallback(void * ud, SoEventCallback * n) dict.setItem("Time", Py::String(std::string(e->getTime().formatDate("%Y-%m-%d %H:%M:%S").getString()))); SbVec2s p = n->getEvent()->getPosition(); Py::Tuple pos(2); - pos.setItem(0, Py::Int(p[0])); - pos.setItem(1, Py::Int(p[1])); + pos.setItem(0, Py::Long(p[0])); + pos.setItem(1, Py::Long(p[1])); // Position dict.setItem("Position", pos); // Shift, Ctrl, Alt down @@ -2565,7 +2565,7 @@ Py::Object View3DInventorPy::setCornerCrossSize(const Py::Tuple& args) Py::Object View3DInventorPy::getCornerCrossSize() { int size = getView3DInventorPtr()->getViewer()->getFeedbackSize(); - return Py::Int(size); + return Py::Long(size); } Py::Object View3DInventorPy::cast_to_base() diff --git a/src/Gui/View3DSettings.cpp b/src/Gui/View3DSettings.cpp index b3aa7fe6d7..80ae157cbd 100644 --- a/src/Gui/View3DSettings.cpp +++ b/src/Gui/View3DSettings.cpp @@ -33,7 +33,7 @@ #include #include "NaviCube.h" -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "SoFCSelectionAction.h" #include "View3DSettings.h" #include "View3DInventorViewer.h" @@ -86,6 +86,9 @@ void View3DSettings::applySettings() OnChange(*hGrp,"UseBackgroundColorMid"); OnChange(*hGrp,"ShowFPS"); OnChange(*hGrp,"ShowNaviCube"); + OnChange(*hGrp,"AxisXColor"); + OnChange(*hGrp,"AxisYColor"); + OnChange(*hGrp,"AxisZColor"); OnChange(*hGrp,"UseVBO"); OnChange(*hGrp,"RenderCache"); OnChange(*hGrp,"Orthographic"); @@ -182,7 +185,7 @@ void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M } else if (strcmp(Reason,"EnablePreselection") == 0) { const ParameterGrp& rclGrp = ((ParameterGrp&)rCaller); - SoFCEnableHighlightAction cAct(rclGrp.GetBool("EnablePreselection", true)); + SoFCEnablePreselectionAction cAct(rclGrp.GetBool("EnablePreselection", true)); for (auto _viewer : _viewers) { cAct.apply(_viewer->getSceneGraph()); } @@ -341,6 +344,11 @@ void View3DSettings::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M _viewer->setEnabledNaviCube(rGrp.GetBool("ShowNaviCube", true)); } } + else if (strcmp(Reason,"AxisXColor") == 0 || strcmp(Reason,"AxisYColor") == 0 || strcmp(Reason,"AxisZColor") == 0) { + for (auto _viewer : _viewers) { + _viewer->updateColors(); + } + } else if (strcmp(Reason,"UseVBO") == 0) { if (!ignoreVBO) { for (auto _viewer : _viewers) { diff --git a/src/Gui/View3DViewerPy.cpp b/src/Gui/View3DViewerPy.cpp index 318a1e77b6..5bd05b3c15 100644 --- a/src/Gui/View3DViewerPy.cpp +++ b/src/Gui/View3DViewerPy.cpp @@ -32,7 +32,7 @@ #include #include "PythonWrapper.h" -#include "NavigationStyle.h" +#include "Navigation/NavigationStyle.h" #include "View3DViewerPy.h" #include "View3DInventorViewer.h" @@ -277,8 +277,8 @@ Py::Object View3DInventorViewerPy::seekToPoint(const Py::Tuple& args) _viewer->seekToPoint(hitpoint); } else { - Py::Int x(tuple[0]); - Py::Int y(tuple[1]); + Py::Long x(tuple[0]); + Py::Long y(tuple[1]); SbVec2s hitpoint ((long)x,(long)y); _viewer->seekToPoint(hitpoint); @@ -344,8 +344,8 @@ Py::Object View3DInventorViewerPy::getPointOnFocalPlane(const Py::Tuple& args) if (!PyArg_ParseTuple(args.ptr(), "hh", &x, &y)) { PyErr_Clear(); Py::Tuple t(args[0]); - x = (int)Py::Int(t[0]); - y = (int)Py::Int(t[1]); + x = (int)Py::Long(t[0]); + y = (int)Py::Long(t[1]); } try { SbVec3f pt = _viewer->getPointOnFocalPlane(SbVec2s(x,y)); diff --git a/src/Gui/ViewProvider.cpp b/src/Gui/ViewProvider.cpp index 6609d809af..33abc679ae 100644 --- a/src/Gui/ViewProvider.cpp +++ b/src/Gui/ViewProvider.cpp @@ -96,10 +96,10 @@ ViewProvider::ViewProvider() setStatus(UpdateData, true); - // SoFCSeparater and SoFCSelectionRoot can both track render cache setting. + // SoFCSeparator and SoFCSelectionRoot can both track render cache setting. // We change to SoFCSelectionRoot so that we can dynamically change full // selection mode (full highlight vs. boundbox). Note that comparing to - // SoFCSeparater, there are some small overhead with SoFCSelectionRoot for + // SoFCSeparator, there are some small overhead with SoFCSelectionRoot for // selection context tracking. // // pcRoot = new SoFCSeparator(true); @@ -906,6 +906,7 @@ std::vector< App::DocumentObject* > ViewProvider::claimChildren3D() const } return vec; } + bool ViewProvider::getElementPicked(const SoPickedPoint *pp, std::string &subname) const { if(!isSelectable()) return false; diff --git a/src/Gui/ViewProvider.h b/src/Gui/ViewProvider.h index c49c5a12eb..dc3ef78959 100644 --- a/src/Gui/ViewProvider.h +++ b/src/Gui/ViewProvider.h @@ -178,7 +178,7 @@ public: * @param append: If true, pPath will be first appended with the root node and * the mode switch node of this view provider. * - * @return the coint detail of the subelement + * @return the coin detail of the subelement * * If this view provider links to other view provider, then the * implementation of getDetailPath() shall also append all intermediate diff --git a/src/Gui/ViewProviderBuilder.cpp b/src/Gui/ViewProviderBuilder.cpp index 478dace621..c6bb1097e3 100644 --- a/src/Gui/ViewProviderBuilder.cpp +++ b/src/Gui/ViewProviderBuilder.cpp @@ -63,7 +63,7 @@ Gui::SoFCSelection* ViewProviderBuilder::createSelection() bool enablePre = hGrp->GetBool("EnablePreselection", true); bool enableSel = hGrp->GetBool("EnableSelection", true); if (!enablePre) { - sel->highlightMode = Gui::SoFCSelection::OFF; + sel->preselectionMode = Gui::SoFCSelection::OFF; } else { // Search for a user defined value with the current color as default diff --git a/src/Gui/ViewProviderDocumentObject.cpp b/src/Gui/ViewProviderDocumentObject.cpp index 3aed6cf9b1..7de7919277 100644 --- a/src/Gui/ViewProviderDocumentObject.cpp +++ b/src/Gui/ViewProviderDocumentObject.cpp @@ -499,12 +499,10 @@ void ViewProviderDocumentObject::setActiveMode() bool ViewProviderDocumentObject::canDelete(App::DocumentObject* obj) const { - Q_UNUSED(obj) - if (getObject()->hasExtension(App::GroupExtension::getExtensionClassTypeId())) - return true; - if (getObject()->isDerivedFrom(App::Origin::getClassTypeId())) - return true; - return false; + Q_UNUSED(obj); + auto* o = getObject(); + return o->hasExtension(App::GroupExtension::getExtensionClassTypeId()) + || o->isDerivedFrom(); } PyObject* ViewProviderDocumentObject::getPyObject() diff --git a/src/Gui/ViewProviderDragger.cpp b/src/Gui/ViewProviderDragger.cpp index 50647c8f9f..70caa50b6b 100644 --- a/src/Gui/ViewProviderDragger.cpp +++ b/src/Gui/ViewProviderDragger.cpp @@ -66,7 +66,7 @@ ViewProviderDragger::~ViewProviderDragger() = default; void ViewProviderDragger::updateData(const App::Property* prop) { - if (prop->isDerivedFrom(App::PropertyPlacement::getClassTypeId()) + if (prop->isDerivedFrom() && strcmp(prop->getName(), "Placement") == 0) { // Note: If R is the rotation, c the rotation center and t the translation // vector then Inventor applies the following transformation: R*(x-c)+c+t diff --git a/src/Gui/ViewProviderExtension.cpp b/src/Gui/ViewProviderExtension.cpp index c7ac21bfc3..b2787019a3 100644 --- a/src/Gui/ViewProviderExtension.cpp +++ b/src/Gui/ViewProviderExtension.cpp @@ -46,13 +46,13 @@ ViewProviderExtension::~ViewProviderExtension() = default; const ViewProviderDocumentObject* ViewProviderExtension::getExtendedViewProvider() const{ - assert(getExtendedContainer()->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())); + assert(getExtendedContainer()->isDerivedFrom()); return static_cast(getExtendedContainer()); } ViewProviderDocumentObject* ViewProviderExtension::getExtendedViewProvider() { - assert(getExtendedContainer()->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())); + assert(getExtendedContainer()->isDerivedFrom()); return static_cast(getExtendedContainer()); } diff --git a/src/Gui/ViewProviderExtension.h b/src/Gui/ViewProviderExtension.h index 931b4dd534..728acfec11 100644 --- a/src/Gui/ViewProviderExtension.h +++ b/src/Gui/ViewProviderExtension.h @@ -48,8 +48,7 @@ class ViewProviderDocumentObject; */ class GuiExport ViewProviderExtension : public App::Extension { - - //The cass does not have properties itself, but it is important to provide the property access + //The class does not have properties itself, but it is important to provide the property access //functions. EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(Gui::ViewProviderExtension); @@ -124,7 +123,6 @@ public: private: bool m_ignoreOverlayIcon = false; - //Gui::ViewProviderDocumentObject* m_viewBase = nullptr; }; } //Gui diff --git a/src/Gui/ViewProviderFeaturePython.cpp b/src/Gui/ViewProviderFeaturePython.cpp index 8996bfe23c..7b24735582 100644 --- a/src/Gui/ViewProviderFeaturePython.cpp +++ b/src/Gui/ViewProviderFeaturePython.cpp @@ -356,7 +356,7 @@ ViewProviderFeaturePythonImp::setEdit(int ModNum) try { if (has__object__) { Py::Tuple args(1); - args.setItem(0, Py::Int(ModNum)); + args.setItem(0, Py::Long(ModNum)); Py::Object ret(Base::pyCall(py_setEdit.ptr(),args.ptr())); if (ret.isNone()) return NotImplemented; @@ -367,7 +367,7 @@ ViewProviderFeaturePythonImp::setEdit(int ModNum) else { Py::Tuple args(2); args.setItem(0, Py::Object(object->getPyObject(), true)); - args.setItem(1, Py::Int(ModNum)); + args.setItem(1, Py::Long(ModNum)); Py::Object ret(Base::pyCall(py_setEdit.ptr(),args.ptr())); if (ret.isNone()) return NotImplemented; @@ -397,7 +397,7 @@ ViewProviderFeaturePythonImp::unsetEdit(int ModNum) try { if (has__object__) { Py::Tuple args(1); - args.setItem(0, Py::Int(ModNum)); + args.setItem(0, Py::Long(ModNum)); Py::Object ret(Base::pyCall(py_unsetEdit.ptr(),args.ptr())); if (ret.isNone()) return NotImplemented; @@ -408,7 +408,7 @@ ViewProviderFeaturePythonImp::unsetEdit(int ModNum) else { Py::Tuple args(2); args.setItem(0, Py::Object(object->getPyObject(), true)); - args.setItem(1, Py::Int(ModNum)); + args.setItem(1, Py::Long(ModNum)); Py::Object ret(Base::pyCall(py_unsetEdit.ptr(),args.ptr())); if (ret.isNone()) return NotImplemented; @@ -439,7 +439,7 @@ ViewProviderFeaturePythonImp::setEditViewer(View3DInventorViewer *viewer, int Mo Py::Tuple args(3); args.setItem(0, Py::Object(object->getPyObject(),true)); args.setItem(1, Py::Object(viewer->getPyObject(),true)); - args.setItem(2, Py::Int(ModNum)); + args.setItem(2, Py::Long(ModNum)); Py::Object ret(Base::pyCall(py_setEditViewer.ptr(),args.ptr())); return ret.isTrue()?Accepted:Rejected; } @@ -681,7 +681,7 @@ void ViewProviderFeaturePythonImp::finishRestoring() Py::Object vp = Proxy.getValue(); if (vp.isNone()) { object->show(); - Proxy.setValue(Py::Int(1)); + Proxy.setValue(Py::Long(1)); } else { _FC_PY_CALL_CHECK(finishRestoring,return); Base::pyCall(py_finishRestoring.ptr()); diff --git a/src/Gui/ViewProviderGeometryObject.cpp b/src/Gui/ViewProviderGeometryObject.cpp index 826cff4139..e585a4ed60 100644 --- a/src/Gui/ViewProviderGeometryObject.cpp +++ b/src/Gui/ViewProviderGeometryObject.cpp @@ -175,13 +175,13 @@ void ViewProviderGeometryObject::attach(App::DocumentObject* pcObj) void ViewProviderGeometryObject::updateData(const App::Property* prop) { - if (prop->isDerivedFrom(App::PropertyComplexGeoData::getClassTypeId())) { + if (prop->isDerivedFrom()) { Base::BoundBox3d box = static_cast(prop)->getBoundingBox(); pcBoundingBox->minBounds.setValue(box.MinX, box.MinY, box.MinZ); pcBoundingBox->maxBounds.setValue(box.MaxX, box.MaxY, box.MaxZ); } - else if (prop->isDerivedFrom(App::PropertyPlacement::getClassTypeId())) { + else if (prop->isDerivedFrom()) { auto geometry = getObject(); if (geometry && prop == &geometry->Placement) { const App::PropertyComplexGeoData* data = geometry->getPropertyOfGeometry(); @@ -347,13 +347,13 @@ void ViewProviderGeometryObject::setSelectable(bool selectable) if (selectable) { if (selNode) { selNode->selectionMode = SoFCSelection::SEL_ON; - selNode->highlightMode = SoFCSelection::AUTO; + selNode->preselectionMode = SoFCSelection::AUTO; } } else { if (selNode) { selNode->selectionMode = SoFCSelection::SEL_OFF; - selNode->highlightMode = SoFCSelection::OFF; + selNode->preselectionMode = SoFCSelection::OFF; selNode->selected = SoFCSelection::NOTSELECTED; } } diff --git a/src/Gui/ViewProviderGroupExtension.cpp b/src/Gui/ViewProviderGroupExtension.cpp index bbeb686cb2..e42bdacd4e 100644 --- a/src/Gui/ViewProviderGroupExtension.cpp +++ b/src/Gui/ViewProviderGroupExtension.cpp @@ -103,7 +103,7 @@ void ViewProviderGroupExtension::extensionDropObject(App::DocumentObject* obj) { // build Python command for execution QString cmd; - cmd = QString::fromLatin1("App.getDocument(\"%1\").getObject(\"%2\").addObject(" + cmd = QStringLiteral("App.getDocument(\"%1\").getObject(\"%2\").addObject(" "App.getDocument(\"%1\").getObject(\"%3\"))") .arg(QString::fromLatin1(doc->getName()), QString::fromLatin1(grp->getNameInDocument()), diff --git a/src/Gui/ViewProviderInventorObject.cpp b/src/Gui/ViewProviderInventorObject.cpp index 19e55469bf..38cb578659 100644 --- a/src/Gui/ViewProviderInventorObject.cpp +++ b/src/Gui/ViewProviderInventorObject.cpp @@ -124,7 +124,7 @@ void ViewProviderInventorObject::updateData(const App::Property* prop) } } } - else if (prop->isDerivedFrom(App::PropertyPlacement::getClassTypeId()) && + else if (prop->isDerivedFrom() && strcmp(prop->getName(), "Placement") == 0) { // Note: If R is the rotation, c the rotation center and t the translation // vector then Inventor applies the following transformation: R*(x-c)+c+t diff --git a/src/Gui/ViewProviderLink.cpp b/src/Gui/ViewProviderLink.cpp index 9ee4e070cc..63857efd54 100644 --- a/src/Gui/ViewProviderLink.cpp +++ b/src/Gui/ViewProviderLink.cpp @@ -74,7 +74,7 @@ #include "ActionFunction.h" #include "Command.h" -#include "DlgObjectSelection.h" +#include "Dialogs/DlgObjectSelection.h" FC_LOG_LEVEL_INIT("App::Link", true, true) @@ -140,7 +140,7 @@ public: Document *pDoc = Application::Instance->getDocument(obj->getDocument()); if(pDoc) { ViewProvider *vp = pDoc->getViewProvider(obj); - if(vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) + if(vp && vp->isDerivedFrom()) return static_cast(vp); } } @@ -283,7 +283,7 @@ public: continue; int count = pcSwitches[i]->getNumChildren(); if((index<0 && i==LinkView::SnapshotChild) || !count) - pcSwitches[i]->whichChild = -1; + pcSwitches[i]->whichChild = SO_SWITCH_NONE; else if(count>pcLinked->getDefaultMode()) pcSwitches[i]->whichChild = pcLinked->getDefaultMode(); else @@ -313,12 +313,8 @@ public: } } - // VC2013 has trouble with template argument dependent lookup in + // MSVC has trouble with template argument dependent lookup in // namespace. Have to put the below functions in global namespace. - // - // However, gcc seems to behave the opposite, hence the conditional - // compilation here. - // #if defined(_MSC_VER) friend void Gui::intrusive_ptr_add_ref(LinkInfo *px); friend void Gui::intrusive_ptr_release(LinkInfo *px); @@ -334,7 +330,7 @@ public: for(int idx : indices) { if(!pcSwitches[idx]) continue; - if(pcSwitches[idx]->whichChild.getValue()==-1) + if(pcSwitches[idx]->whichChild.getValue()==SO_SWITCH_NONE) return false; } return true; @@ -348,7 +344,7 @@ public: if(!pcSwitches[idx]) continue; if(!visible) - pcSwitches[idx]->whichChild = -1; + pcSwitches[idx]->whichChild = SO_SWITCH_NONE; else if(pcSwitches[idx]->getNumChildren()>pcLinked->getDefaultMode()) pcSwitches[idx]->whichChild = pcLinked->getDefaultMode(); } @@ -389,7 +385,7 @@ public: pcLinkedSwitch.reset(); coinRemoveAllChildren(pcSnapshot); - pcModeSwitch->whichChild = -1; + pcModeSwitch->whichChild = SO_SWITCH_NONE; coinRemoveAllChildren(pcModeSwitch); SoSwitch *pcUpdateSwitch = pcModeSwitch; @@ -1142,7 +1138,7 @@ void LinkView::setChildren(const std::vector &children, auto &info = *nodeArray[i]; info.isGroup = false; info.groupIndex = -1; - info.pcSwitch->whichChild = (vis.size()<=i||vis[i])?0:-1; + info.pcSwitch->whichChild = (vis.size()<=i||vis[i])?0:SO_SWITCH_NONE; info.link(obj); if(obj->hasExtension(App::GroupExtension::getExtensionClassTypeId(),false)) { info.isGroup = true; @@ -1193,7 +1189,7 @@ void LinkView::setTransform(int index, const Base::Matrix4D &mat) { void LinkView::setElementVisible(int idx, bool visible) { if(idx>=0 && idx<(int)nodeArray.size()) - nodeArray[idx]->pcSwitch->whichChild = visible?0:-1; + nodeArray[idx]->pcSwitch->whichChild = visible?0:SO_SWITCH_NONE; } bool LinkView::isElementVisible(int idx) const { @@ -1685,7 +1681,7 @@ void ViewProviderLink::attach(App::DocumentObject *pcObj) { setDisplayMaskMode("Link"); inherited::attach(pcObj); checkIcon(); - if(pcObj->isDerivedFrom(App::LinkElement::getClassTypeId())) + if(pcObj->isDerivedFrom()) hide(); linkView->setOwner(this); diff --git a/src/Gui/ViewProviderLink.h b/src/Gui/ViewProviderLink.h index 79ead6d8cf..c61fb19420 100644 --- a/src/Gui/ViewProviderLink.h +++ b/src/Gui/ViewProviderLink.h @@ -25,7 +25,7 @@ #include -#include "SoFCUnifiedSelection.h" +#include "Selection/SoFCUnifiedSelection.h" #include "ViewProviderDocumentObject.h" #include "ViewProviderExtension.h" #include "ViewProviderFeaturePython.h" @@ -41,7 +41,7 @@ class LinkInfo; using LinkInfoPtr = boost::intrusive_ptr; #if defined(_MSC_VER) -// forward declaration to please VC 2013 +// forward declaration to please MSVC void intrusive_ptr_add_ref(Gui::LinkInfo *px); void intrusive_ptr_release(Gui::LinkInfo *px); #endif diff --git a/src/Gui/ViewProviderPy.xml b/src/Gui/ViewProviderPy.xml index 8ce41e4deb..5a8c92359f 100644 --- a/src/Gui/ViewProviderPy.xml +++ b/src/Gui/ViewProviderPy.xml @@ -15,274 +15,274 @@ - addProperty(type, name, group, doc, attr=0, ro=False, hd=False) -> ViewProvider + addProperty(type, name, group, doc, attr=0, ro=False, hd=False) -> ViewProvider -Add a generic property. +Add a generic property. -type : str +type : str Property type. -name : str +name : str Property name. Optional. -group : str +group : str Property group. Optional. -attr : int +attr : int Property attributes. -ro : bool +ro : bool Read only property. -hd : bool +hd : bool Hidden property. - removeProperty(name) -> bool + removeProperty(name) -> bool Remove a generic property. -Only user-defined properties can be removed, not built-in ones. +Only user-defined properties can be removed, not built-in ones. -name : str +name : str Property name. - supportedProperties() -> list + supportedProperties() -> list A list of supported property types. - show() -> None + show() -> None Show the object. - show() -> None + show() -> None Hide the object. - isVisible() -> bool + isVisible() -> bool Check if the object is visible. - canDragObject(obj=None) -> bool + canDragObject(obj=None) -> bool Check whether the child object can be removed by dragging. -If 'obj' is not given, check without filter by any particular object. +If 'obj' is not given, check without filter by any particular object. -obj : App.DocumentObject +obj : App.DocumentObject Object to be dragged. - dragObject(obj) -> None + dragObject(obj) -> None -Remove a child object by dropping. +Remove a child object by dropping. -obj : App.DocumentObject +obj : App.DocumentObject Object to be dragged. - canDropObject(obj=None, owner=None, subname, elem=None) -> bool + canDropObject(obj=None, owner=None, subname, elem=None) -> bool Check whether the child object can be added by dropping. -If 'obj' is not given, check without filter by any particular object. +If 'obj' is not given, check without filter by any particular object. -obj : App.DocumentObject +obj : App.DocumentObject Object to be dropped. -owner : App.DocumentObject +owner : App.DocumentObject Parent object of the dropping object. -subname : str +subname : str Subname reference to the dropping object. Optional. -elem : sequence of str +elem : sequence of str Non-objects subelements selected when the object is being dropped. - dropObject(obj, owner=None, subname, elem=None) -> str + dropObject(obj, owner=None, subname, elem=None) -> str -Add a child object by dropping. +Add a child object by dropping. -obj : App.DocumentObject +obj : App.DocumentObject Object to be dropped. -owner : App.DocumentObject +owner : App.DocumentObject Parent object of the dropping object. -subname : str +subname : str Subname reference to the dropping object. Optional. -elem : sequence of str +elem : sequence of str Non-objects subelements selected when the object is being dropped. - canDragAndDropObject(obj) -> bool + canDragAndDropObject(obj) -> bool Check whether the child object can be removed from -other parent and added here by drag and drop. +other parent and added here by drag and drop. -obj : App.DocumentObject +obj : App.DocumentObject Object to be dragged and dropped. - replaceObject(oldObj, newObj) -> int + replaceObject(oldObj, newObj) -> int Replace a child object. -Returns 1 if succeeded, 0 if not found, -1 if not supported. +Returns 1 if succeeded, 0 if not found, -1 if not supported. -oldObj : App.DocumentObject +oldObj : App.DocumentObject Old object. -newObj : App.DocumentObject +newObj : App.DocumentObject New object. - doubleClicked() -> bool + doubleClicked() -> bool Trigger double clicking the corresponding tree item of this view object. - addDisplayMode(obj, mode) -> None + addDisplayMode(obj, mode) -> None -Add a new display mode to the view provider. +Add a new display mode to the view provider. -obj : coin.SoNode +obj : coin.SoNode Display mode. -mode : str +mode : str Name of the display mode. - listDisplayModes() -> list + listDisplayModes() -> list Show a list of all display modes. - toString() -> str + toString() -> str Return a string representation of the Inventor node. - setTransformation(trans) -> None + setTransformation(trans) -> None -Set a transformation on the Inventor node. +Set a transformation on the Inventor node. trans : Base.Placement, Base.Matrix - claimChildren() -> list + claimChildren() -> list Returns list of objects that are to be grouped in tree under this object. - claimChildrenRecursive() -> list + claimChildrenRecursive() -> list Returns list of objects that are to be grouped in tree under this object recursively. - partialRender(sub=None, clear=False) -> int + partialRender(sub=None, clear=False) -> int -Render only part of the object. +Render only part of the object. -sub: None, str, sequence of str +sub: None, str, sequence of str Refer to the subelement. If it is None then reset the partial rendering. -clear: bool +clear: bool True to add, or False to remove the subelement(s) for rendering. - getElementColors(elementName) -> dict + getElementColors(elementName) -> dict Get a dictionary of the form {elementName : (r,g,b,a)}. -If no element name is given a dictionary with all the elements is returned. +If no element name is given a dictionary with all the elements is returned. -elementName : str +elementName : str Name of the element. Optional. - setElementColors(colors) -> None + setElementColors(colors) -> None -Set element colors. +Set element colors. -colors: dict +colors: dict Color dictionary of the form {elementName:(r,g,b,a)}. - getElementPicked(pickPoint) -> str + getElementPicked(pickPoint) -> str -Return the picked subelement. +Return the picked subelement. pickPoint : coin.SoPickedPoint - getDetailPath(subelement, path, append=True) -> coin.SoDetail or None + getDetailPath(subelement, path, append=True) -> coin.SoDetail or None -Return Coin detail and path of an subelement. +Return Coin detail and path of an subelement. -subname: str +subname: str Dot separated string reference to the sub element. -pPath: coin.SoPath +pPath: coin.SoPath Output coin path leading to the returned element detail. -append: bool +append: bool If True, path will be first appended with the root node and the mode switch node of this view provider. - signalChangeIcon() -> None + signalChangeIcon() -> None Trigger icon changed signal. - getBoundingBox(subName, transform=True, view) -> Base.BoundBox + getBoundingBox(subName, transform=True, view) -> Base.BoundBox -Obtain the bounding box of this view object. +Obtain the bounding box of this view object. -subName : str +subName : str Name referring a sub-object. Optional. -transform: bool +transform: bool Whether to apply the transformation matrix of this view provider. -view: View3DInventorPy +view: View3DInventorPy Default to active view. Optional. @@ -314,7 +314,7 @@ view: View3DInventorPy Get/Set the default display mode in turns of coin node index. - + diff --git a/src/Gui/ViewProviderPyImp.cpp b/src/Gui/ViewProviderPyImp.cpp index dabd1bb97b..30178bf008 100644 --- a/src/Gui/ViewProviderPyImp.cpp +++ b/src/Gui/ViewProviderPyImp.cpp @@ -304,7 +304,7 @@ PyObject* ViewProviderPy::replaceObject(PyObject *args) int ret = getViewProviderPtr()->replaceObject( static_cast(oldObj)->getDocumentObjectPtr(), static_cast(newObj)->getDocumentObjectPtr()); - return Py::new_reference_to(Py::Int(ret)); + return Py::new_reference_to(Py::Long(ret)); } PY_CATCH; } @@ -456,7 +456,7 @@ PyObject* ViewProviderPy::partialRender(PyObject* args) } } - Py::Int ret(getViewProviderPtr()->partialRender(values, Base::asBoolean(clear))); + Py::Long ret(getViewProviderPtr()->partialRender(values, Base::asBoolean(clear))); return Py::new_reference_to(ret); } @@ -677,12 +677,12 @@ Py::Object ViewProviderPy::getIcon() const return wrap.fromQIcon(new QIcon(icon)); } -Py::Int ViewProviderPy::getDefaultMode() const +Py::Long ViewProviderPy::getDefaultMode() const { - return Py::Int((long)getViewProviderPtr()->getDefaultMode()); + return Py::Long((long)getViewProviderPtr()->getDefaultMode()); } -void ViewProviderPy::setDefaultMode(Py::Int arg) +void ViewProviderPy::setDefaultMode(Py::Long arg) { return getViewProviderPtr()->setDefaultMode(arg); } diff --git a/src/Gui/ViewProviderVRMLObject.cpp b/src/Gui/ViewProviderVRMLObject.cpp index f99e8d98ed..0f106c69f1 100644 --- a/src/Gui/ViewProviderVRMLObject.cpp +++ b/src/Gui/ViewProviderVRMLObject.cpp @@ -59,7 +59,7 @@ PROPERTY_SOURCE(Gui::ViewProviderVRMLObject, Gui::ViewProviderDocumentObject) ViewProviderVRMLObject::ViewProviderVRMLObject() { pcVRML = new SoFCSelection(); - pcVRML->highlightMode = Gui::SoFCSelection::OFF; + pcVRML->preselectionMode = Gui::SoFCSelection::OFF; pcVRML->selectionMode = Gui::SoFCSelection::SEL_OFF; //pcVRML->style = Gui::SoFCSelection::BOX; pcVRML->ref(); @@ -249,7 +249,7 @@ void ViewProviderVRMLObject::updateData(const App::Property* prop) SoInput::removeDirectory(subpath.constData()); } } - else if (prop->isDerivedFrom(App::PropertyPlacement::getClassTypeId()) && + else if (prop->isDerivedFrom() && strcmp(prop->getName(), "Placement") == 0) { // Note: If R is the rotation, c the rotation center and t the translation // vector then Inventor applies the following transformation: R*(x-c)+c+t diff --git a/src/Gui/ViewProviderVarSet.h b/src/Gui/ViewProviderVarSet.h index 715a05a438..6afa7b975e 100644 --- a/src/Gui/ViewProviderVarSet.h +++ b/src/Gui/ViewProviderVarSet.h @@ -24,7 +24,7 @@ #define GUI_ViewProviderVarSet_H #include "ViewProviderDocumentObject.h" -#include "DlgAddPropertyVarSet.h" +#include "Dialogs/DlgAddPropertyVarSet.h" namespace Gui { diff --git a/src/Gui/WidgetFactory.cpp b/src/Gui/WidgetFactory.cpp index 8b9821e067..82ee5d2f27 100644 --- a/src/Gui/WidgetFactory.cpp +++ b/src/Gui/WidgetFactory.cpp @@ -493,7 +493,7 @@ bool PyResource::connect(const char* sender, const char* signal, PyObject* cb) QList list = myDlg->findChildren(); QList::const_iterator it = list.cbegin(); QObject *obj; - QString sigStr = QString::fromLatin1("2%1").arg(QString::fromLatin1(signal)); + QString sigStr = QStringLiteral("2%1").arg(QString::fromLatin1(signal)); while ( it != list.cend() ) { obj = *it; @@ -584,7 +584,7 @@ Py::Object PyResource::value(const Py::Tuple& args) item = Py::Long(static_cast(v.toUInt())); break; case QMetaType::Int: - item = Py::Int(v.toInt()); + item = Py::Long(v.toInt()); break; default: item = Py::String(""); diff --git a/src/Gui/WidgetFactory.h b/src/Gui/WidgetFactory.h index 3a6e5fe76d..71418c48d5 100644 --- a/src/Gui/WidgetFactory.h +++ b/src/Gui/WidgetFactory.h @@ -27,8 +27,8 @@ #include #include -#include "DlgCustomizeImp.h" -#include "DlgPreferencesImp.h" +#include "Dialogs/DlgCustomizeImp.h" +#include "Dialogs/DlgPreferencesImp.h" #include "PropertyPage.h" #include diff --git a/src/Gui/Widgets.cpp b/src/Gui/Widgets.cpp index 990fe61310..3d326ee782 100644 --- a/src/Gui/Widgets.cpp +++ b/src/Gui/Widgets.cpp @@ -50,11 +50,11 @@ #include "Application.h" #include "BitmapFactory.h" #include "Command.h" -#include "DlgExpressionInput.h" +#include "Dialogs/DlgExpressionInput.h" #include "PrefWidgets.h" #include "QuantitySpinBox_p.h" #include "Tools.h" -#include "ui_DlgTreeWidget.h" +#include "Dialogs/ui_DlgTreeWidget.h" using namespace Gui; using namespace App; @@ -94,7 +94,7 @@ void CommandIconView::startDrag (Qt::DropActions supportedActions) } auto mimeData = new QMimeData; - mimeData->setData(QString::fromLatin1("text/x-action-items"), itemData); + mimeData->setData(QStringLiteral("text/x-action-items"), itemData); auto drag = new QDrag(this); drag->setMimeData(mimeData); @@ -428,7 +428,7 @@ void AccelLineEdit::keyPressEvent (QKeyEvent * e) txtLine.clear(); break; default: - txtLine += QString::fromLatin1(","); + txtLine += QStringLiteral(","); break; } } @@ -524,7 +524,7 @@ void ModifierLineEdit::keyPressEvent (QKeyEvent * e) ClearLineEdit::ClearLineEdit (QWidget * parent) : QLineEdit(parent) { - clearAction = this->addAction(QIcon(QString::fromLatin1(":/icons/edit-cleartext.svg")), + clearAction = this->addAction(QIcon(QStringLiteral(":/icons/edit-cleartext.svg")), QLineEdit::TrailingPosition); connect(clearAction, &QAction::triggered, this, &ClearLineEdit::clear); connect(this, &QLineEdit::textChanged, this, &ClearLineEdit::updateClearButton); @@ -943,7 +943,7 @@ void StatefulLabel::registerState(const QString& state, const QColor& color, { QString css; if (color.isValid()) - css = QString::fromUtf8("Gui--StatefulLabel{ color : rgba(%1,%2,%3,%4) ;}").arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha()); + css = QStringLiteral("Gui--StatefulLabel{ color : rgba(%1,%2,%3,%4) ;}").arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha()); _availableStates[state] = { css, preferenceName }; } @@ -952,10 +952,10 @@ void StatefulLabel::registerState(const QString& state, const QColor& fg, const { QString colorEntries; if (fg.isValid()) - colorEntries.append(QString::fromUtf8("color : rgba(%1,%2,%3,%4);").arg(fg.red()).arg(fg.green()).arg(fg.blue()).arg(fg.alpha())); + colorEntries.append(QStringLiteral("color : rgba(%1,%2,%3,%4);").arg(fg.red()).arg(fg.green()).arg(fg.blue()).arg(fg.alpha())); if (bg.isValid()) - colorEntries.append(QString::fromUtf8("background-color : rgba(%1,%2,%3,%4);").arg(bg.red()).arg(bg.green()).arg(bg.blue()).arg(bg.alpha())); - QString css = QString::fromUtf8("Gui--StatefulLabel{ %1 }").arg(colorEntries); + colorEntries.append(QStringLiteral("background-color : rgba(%1,%2,%3,%4);").arg(bg.red()).arg(bg.green()).arg(bg.blue()).arg(bg.alpha())); + QString css = QStringLiteral("Gui--StatefulLabel{ %1 }").arg(colorEntries); _availableStates[state] = { css, preferenceName }; } @@ -1010,7 +1010,7 @@ void StatefulLabel::setState(QString state) // Convert the stored Uint into usable color data: unsigned int col = unsignedEntry.second; QColor qcolor(App::Color::fromPackedRGB(col)); - this->setStyleSheet(QString::fromUtf8("Gui--StatefulLabel{ color : rgba(%1,%2,%3,%4) ;}").arg(qcolor.red()).arg(qcolor.green()).arg(qcolor.blue()).arg(qcolor.alpha())); + this->setStyleSheet(QStringLiteral("Gui--StatefulLabel{ color : rgba(%1,%2,%3,%4) ;}").arg(qcolor.red()).arg(qcolor.green()).arg(qcolor.blue()).arg(qcolor.alpha())); _styleCache[state] = this->styleSheet(); return; } @@ -1020,7 +1020,7 @@ void StatefulLabel::setState(QString state) auto availableStringPrefs = _parameterGroup->GetASCIIMap(); for (const auto& stringEntry : availableStringPrefs) { if (stringEntry.first == entry->second.preferenceString) { - QString css = QString::fromUtf8("Gui--StatefulLabel{ %1 }").arg(QString::fromStdString(stringEntry.second)); + QString css = QStringLiteral("Gui--StatefulLabel{ %1 }").arg(QString::fromStdString(stringEntry.second)); this->setStyleSheet(css); _styleCache[state] = this->styleSheet(); return; @@ -1409,7 +1409,7 @@ public: if (edit) { QString inputText = edit->toPlainText(); if (!inputText.isEmpty()) // let pass empty input, regardless of the type, so user can void the value - lines = inputText.split(QString::fromLatin1("\n")); + lines = inputText.split(QStringLiteral("\n")); } if (!lines.isEmpty()) { if (type == 1) { // floats @@ -1483,7 +1483,7 @@ void LabelEditor::setText(const QString& s) { this->plainText = s; - QString text = QString::fromLatin1("[%1]").arg(this->plainText); + QString text = QStringLiteral("[%1]").arg(this->plainText); lineEdit->setText(text); } @@ -1506,7 +1506,7 @@ void LabelEditor::changeText() connect(buttonBox, &QDialogButtonBox::rejected, dlg, &PropertyListDialog::reject); connect(dlg, &PropertyListDialog::accepted, this, [&] { QString inputText = edit->toPlainText(); - QString text = QString::fromLatin1("[%1]").arg(inputText); + QString text = QStringLiteral("[%1]").arg(inputText); lineEdit->setText(text); }); @@ -1578,7 +1578,7 @@ void ExpLineEdit::bind(const ObjectIdentifier& _path) { ExpressionBinding::bind(_path); int frameWidth = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth); - setStyleSheet(QString::fromLatin1("QLineEdit { padding-right: %1px } ").arg(iconLabel->sizeHint().width() + frameWidth + 1)); + setStyleSheet(QStringLiteral("QLineEdit { padding-right: %1px } ").arg(iconLabel->sizeHint().width() + frameWidth + 1)); iconLabel->show(); } @@ -1603,7 +1603,7 @@ void ExpLineEdit::onChange() { if (getExpression()) { std::unique_ptr result(getExpression()->eval()); - if(result->isDerivedFrom(App::StringExpression::getClassTypeId())) + if(result->isDerivedFrom()) setText(QString::fromUtf8(static_cast( result.get())->getText().c_str())); else diff --git a/src/Gui/Window.h b/src/Gui/Window.h index 179c7a88d8..a57fe5e4c3 100644 --- a/src/Gui/Window.h +++ b/src/Gui/Window.h @@ -25,6 +25,7 @@ #define GUI_WINDOW_H #include +#include namespace Gui { diff --git a/src/Gui/WorkbenchSelector.cpp b/src/Gui/WorkbenchSelector.cpp index a96a530702..72e02d42fd 100644 --- a/src/Gui/WorkbenchSelector.cpp +++ b/src/Gui/WorkbenchSelector.cpp @@ -38,7 +38,7 @@ #include "Action.h" #include "BitmapFactory.h" #include "Command.h" -#include "DlgPreferencesImp.h" +#include "Dialogs/DlgPreferencesImp.h" #include "MainWindow.h" #include "WorkbenchSelector.h" #include "ToolBarAreaWidget.h" @@ -108,7 +108,7 @@ WorkbenchTabWidget::WorkbenchTabWidget(WorkbenchGroup* aGroup, QWidget* parent) setToolTip(aGroup->toolTip()); setStatusTip(aGroup->action()->statusTip()); setWhatsThis(aGroup->action()->whatsThis()); - setObjectName(QString::fromLatin1("WbTabBar")); + setObjectName(QStringLiteral("WbTabBar")); tabBar = new WbTabBar(this); moreButton = new QToolButton(this); @@ -125,7 +125,7 @@ WorkbenchTabWidget::WorkbenchTabWidget(WorkbenchGroup* aGroup, QWidget* parent) moreButton->setToolButtonStyle(Qt::ToolButtonIconOnly); moreButton->setPopupMode(QToolButton::InstantPopup); moreButton->setMenu(new QMenu(moreButton)); - moreButton->setObjectName(QString::fromLatin1("WbTabBarMore")); + moreButton->setObjectName(QStringLiteral("WbTabBarMore")); if (parent->inherits("QToolBar")) { // when toolbar is created it is not yet placed in its designated area @@ -404,7 +404,7 @@ void WorkbenchTabWidget::buildPrefMenu() // Add disabled workbenches, sorted alphabetically. for (auto action : wbActionGroup->getDisabledWbActions()) { - if (action->text() == QString::fromLatin1("")) { + if (action->text() == QStringLiteral("")) { continue; } @@ -416,7 +416,7 @@ void WorkbenchTabWidget::buildPrefMenu() QAction* preferencesAction = menu->addAction(tr("Preferences")); connect(preferencesAction, &QAction::triggered, this, []() { Gui::Dialog::DlgPreferencesImp cDlg(getMainWindow()); - cDlg.activateGroupPage(QString::fromUtf8("Workbenches"), 0); + cDlg.activateGroupPage(QStringLiteral("Workbenches"), 0); cDlg.exec(); }); } diff --git a/src/Gui/propertyeditor/PropertyEditor.cpp b/src/Gui/propertyeditor/PropertyEditor.cpp index 561c7f9916..6dfa5db131 100644 --- a/src/Gui/propertyeditor/PropertyEditor.cpp +++ b/src/Gui/propertyeditor/PropertyEditor.cpp @@ -39,7 +39,7 @@ #include #include "PropertyEditor.h" -#include "DlgAddProperty.h" +#include "Dialogs/DlgAddProperty.h" #include "MainWindow.h" #include "PropertyItemDelegate.h" #include "PropertyModel.h" @@ -643,7 +643,7 @@ void PropertyEditor::buildUp(PropertyModel::PropertyList&& props, bool _checkDoc continue; } // Include document to get proper handling in PropertyView::slotDeleteDocument() - if (checkDocument && container->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + if (checkDocument && container->isDerivedFrom()) { propOwners.insert(static_cast(container)->getDocument()); } propOwners.insert(container); @@ -779,7 +779,7 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent*) if (props.size() == 1) { auto item = static_cast(contextIndex.internalPointer()); auto prop = *props.begin(); - if (item->isBound() && !prop->isDerivedFrom(App::PropertyExpressionEngine::getClassTypeId()) + if (item->isBound() && !prop->isDerivedFrom() && !prop->isReadOnly() && !prop->testStatus(App::Property::Immutable) && !(prop->getType() & App::Prop_ReadOnly)) { contextIndex = propertyModel->buddy(contextIndex); @@ -794,7 +794,7 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent*) menu.addSeparator(); // the subMenu is allocated on the heap but managed by menu. - auto subMenu = new QMenu(QString::fromLatin1("Status"), &menu); + auto subMenu = new QMenu(QStringLiteral("Status"), &menu); QAction* action; QString text; @@ -811,7 +811,7 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent*) do { \ _ACTION_SETUP(_name); \ if (propType & App::Prop_##_name) { \ - action->setText(text + QString::fromLatin1(" *")); \ + action->setText(text + QStringLiteral(" *")); \ action->setChecked(true); \ } \ } while (0) diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index e506926b5b..8d95ef7d84 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -53,12 +53,12 @@ #include #include #include -#include +#include #include #include #include #include -#include +#include #include #include #include @@ -386,7 +386,7 @@ QVariant PropertyItem::decoration(const QVariant& value) const QString PropertyItem::asNone(const Py::Object& pyobj) const { Q_UNUSED(pyobj) - return QString::fromUtf8(""); + return QStringLiteral(""); } QString PropertyItem::asString(const Py::Object& pyobj) const @@ -611,17 +611,17 @@ void PropertyItem::setPropertyValue(const std::string& value) continue; } - if (parent->isDerivedFrom(App::Document::getClassTypeId())) { + if (parent->isDerivedFrom()) { auto doc = static_cast(parent); ss << "FreeCAD.getDocument('" << doc->getName() << "')."; } - else if (parent->isDerivedFrom(App::DocumentObject::getClassTypeId())) { + else if (parent->isDerivedFrom()) { auto obj = static_cast(parent); App::Document* doc = obj->getDocument(); ss << "FreeCAD.getDocument('" << doc->getName() << "').getObject('" << obj->getNameInDocument() << "')."; } - else if (parent->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) { + else if (parent->isDerivedFrom()) { App::DocumentObject* obj = static_cast(parent)->getObject(); App::Document* doc = obj->getDocument(); @@ -685,7 +685,7 @@ QVariant PropertyItem::dataProperty(int role) const } if (role == Qt::ToolTipRole) { QString type = - QString::fromLatin1("Type: %1\nName: %2") + QStringLiteral("Type: %1\nName: %2") .arg(QString::fromLatin1(propertyItems[0]->getTypeId().getName()), objectName()); QString doc = PropertyItem::toolTip(propertyItems[0]).toString(); @@ -999,7 +999,7 @@ QVariant PropertyIntegerItem::toString(const QVariant& v) const if (hasExpression()) { string += - QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + QStringLiteral(" ( %1 )").arg(QString::fromStdString(getExpressionString())); } return {string}; @@ -1081,7 +1081,7 @@ QVariant PropertyIntegerConstraintItem::toString(const QVariant& v) const if (hasExpression()) { string += - QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + QStringLiteral(" ( %1 )").arg(QString::fromStdString(getExpressionString())); } return {string}; @@ -1100,7 +1100,7 @@ QVariant PropertyFloatItem::toString(const QVariant& prop) const QString data = QLocale().toString(value, 'f', decimals()); if (hasExpression()) { - data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + data += QStringLiteral(" ( %1 )").arg(QString::fromStdString(getExpressionString())); } return {data}; @@ -1426,7 +1426,7 @@ public: if (data.canConvert()) { const Base::Vector3d& value = data.value(); - QString str = QString::fromLatin1("(%1, %2, %3)") + QString str = QStringLiteral("(%1, %2, %3)") .arg(value.x, 0, 'f', decimals) .arg(value.y, 0, 'f', decimals) .arg(value.z, 0, 'f', decimals); @@ -1468,12 +1468,12 @@ QVariant PropertyVectorItem::toString(const QVariant& prop) const { QLocale loc; const Base::Vector3d& value = prop.value(); - QString data = QString::fromLatin1("[%1 %2 %3]") + QString data = QStringLiteral("[%1 %2 %3]") .arg(loc.toString(value.x, 'f', lowPrec), loc.toString(value.y, 'f', lowPrec), loc.toString(value.z, 'f', lowPrec)); if (hasExpression()) { - data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + data += QStringLiteral(" ( %1 )").arg(QString::fromStdString(getExpressionString())); } return {data}; } @@ -1492,7 +1492,7 @@ void PropertyVectorItem::setValue(const QVariant& value) return; } const Base::Vector3d& val = value.value(); - QString data = QString::fromLatin1("(%1, %2, %3)") + QString data = QStringLiteral("(%1, %2, %3)") .arg(val.x, 0, 'g', highPrec) .arg(val.y, 0, 'g', highPrec) .arg(val.z, 0, 'g', highPrec); @@ -1519,7 +1519,7 @@ void PropertyVectorItem::setEditorData(QWidget* editor, const QVariant& data) co QLocale loc; auto le = qobject_cast(editor); const Base::Vector3d& value = data.value(); - QString text = QString::fromLatin1("[%1 %2 %3]") + QString text = QStringLiteral("[%1 %2 %3]") .arg(loc.toString(value.x, 'f', lowPrec), loc.toString(value.y, 'f', lowPrec), loc.toString(value.z, 'f', lowPrec)); @@ -1657,10 +1657,10 @@ void VectorListWidget::showValue(const QVariant& d) QString data; const QList& value = d.value>(); if (value.isEmpty()) { - data = QString::fromLatin1("[]"); + data = QStringLiteral("[]"); } else { - data = QString::fromLatin1("[%1 %2 %3], ...") + data = QStringLiteral("[%1 %2 %3], ...") .arg(loc.toString(value[0].x, 'f', lowPrec), loc.toString(value[0].y, 'f', lowPrec), loc.toString(value[0].z, 'f', lowPrec)); @@ -1679,17 +1679,17 @@ QVariant PropertyVectorListItem::toString(const QVariant& prop) const QString data; const QList& value = prop.value>(); if (value.isEmpty()) { - data = QString::fromLatin1("[]"); + data = QStringLiteral("[]"); } else { - data = QString::fromLatin1("[%1 %2 %3], ...") + data = QStringLiteral("[%1 %2 %3], ...") .arg(loc.toString(value[0].x, 'f', lowPrec), loc.toString(value[0].y, 'f', lowPrec), loc.toString(value[0].z, 'f', lowPrec)); } if (hasExpression()) { - data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); + data += QStringLiteral(" ( %1 )").arg(QString::fromStdString(getExpressionString())); } return {data}; } @@ -1715,7 +1715,7 @@ void PropertyVectorListItem::setValue(const QVariant& value) QTextStream str(&data); str << "["; for (const auto& it : val) { - str << QString::fromLatin1("(%1, %2, %3), ") + str << QStringLiteral("(%1, %2, %3), ") .arg(it.x, 0, 'g', highPrec) .arg(it.y, 0, 'g', highPrec) .arg(it.z, 0, 'g', highPrec); @@ -1971,7 +1971,7 @@ QVariant PropertyMatrixItem::toString(const QVariant& prop) const QLocale loc; const Base::Matrix4D& value = prop.value(); // NOLINTBEGIN - QString text = QString::fromLatin1("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") + QString text = QStringLiteral("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") .arg(loc.toString(value[0][0], 'f', lowPrec), //(unsigned short usNdx) loc.toString(value[0][1], 'f', lowPrec), loc.toString(value[0][2], 'f', lowPrec), @@ -2016,7 +2016,7 @@ void PropertyMatrixItem::setValue(const QVariant& value) const Base::Matrix4D& val = value.value(); // NOLINTBEGIN QString data = - QString::fromLatin1( + QStringLiteral( "FreeCAD.Matrix(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16)") .arg(val[0][0], 0, 'g', highPrec) .arg(val[0][1], 0, 'g', highPrec) @@ -2053,7 +2053,7 @@ void PropertyMatrixItem::setEditorData(QWidget* editor, const QVariant& data) co auto le = qobject_cast(editor); const Base::Matrix4D& value = data.value(); // NOLINTBEGIN - QString text = QString::fromLatin1("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") + QString text = QStringLiteral("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") .arg(loc.toString(value[0][0], 'f', lowPrec), //(unsigned short usNdx) loc.toString(value[0][1], 'f', lowPrec), loc.toString(value[0][2], 'f', lowPrec), @@ -2515,7 +2515,7 @@ QVariant PropertyRotationItem::toolTip(const App::Property* prop) const QLocale loc; QString data = - QString::fromUtf8("Axis: (%1 %2 %3)\n" + QStringLiteral("Axis: (%1 %2 %3)\n" "Angle: %4") .arg(loc.toString(dir.x, 'f', decimals()), loc.toString(dir.y, 'f', decimals()), @@ -2534,7 +2534,7 @@ QVariant PropertyRotationItem::toString(const QVariant& prop) const QLocale loc; QString data = - QString::fromUtf8("[(%1 %2 %3); %4]") + QStringLiteral("[(%1 %2 %3); %4]") .arg(loc.toString(dir.x, 'f', lowPrec), loc.toString(dir.y, 'f', lowPrec), loc.toString(dir.z, 'f', lowPrec), @@ -2819,7 +2819,7 @@ QVariant PropertyPlacementItem::toolTip(const App::Property* prop) const QLocale loc; QString data = - QString::fromUtf8("Axis: (%1 %2 %3)\n" + QStringLiteral("Axis: (%1 %2 %3)\n" "Angle: %4\n" "Position: (%5 %6 %7)") .arg(loc.toString(dir.x, 'f', decimals()), @@ -2844,7 +2844,7 @@ QVariant PropertyPlacementItem::toString(const QVariant& prop) const QLocale loc; QString data = - QString::fromUtf8("[(%1 %2 %3); %4; (%5 %6 %7)]") + QStringLiteral("[(%1 %2 %3); %4; (%5 %6 %7)]") .arg(loc.toString(dir.x, 'f', lowPrec), loc.toString(dir.y, 'f', lowPrec), loc.toString(dir.z, 'f', lowPrec), @@ -2993,7 +2993,7 @@ void PropertyEnumItem::setValue(const QVariant& value) ss << "["; for (const auto& it : values) { QString text(it); - text.replace(QString::fromUtf8("'"), QString::fromUtf8("\\'")); + text.replace(QStringLiteral("'"), QStringLiteral("\\'")); std::string str = Base::Tools::escapedUnicodeFromUtf8(text.toUtf8()); str = Base::InterpreterSingleton::strToPython(str); @@ -3231,7 +3231,7 @@ QVariant PropertyStringListItem::toString(const QVariant& prop) const list.append(QLatin1String("...")); } - QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); + QString text = QStringLiteral("[%1]").arg(list.join(QLatin1String(","))); return {text}; } @@ -3307,7 +3307,7 @@ QVariant PropertyFloatListItem::toString(const QVariant& prop) const list = list.mid(0, size); list.append(QLatin1String("...")); } - QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); + QString text = QStringLiteral("[%1]").arg(list.join(QLatin1String(","))); return {text}; } @@ -3385,7 +3385,7 @@ QVariant PropertyIntegerListItem::toString(const QVariant& prop) const list = list.mid(0, size); list.append(QLatin1String("...")); } - QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); + QString text = QStringLiteral("[%1]").arg(list.join(QLatin1String(","))); return {text}; } @@ -3445,7 +3445,7 @@ QVariant PropertyColorItem::toString(const QVariant& prop) const { auto value = prop.value(); QString color = - QString::fromLatin1("[%1, %2, %3]").arg(value.red()).arg(value.green()).arg(value.blue()); + QStringLiteral("[%1, %2, %3]").arg(value.red()).arg(value.green()).arg(value.blue()); return {color}; } @@ -3464,7 +3464,7 @@ void PropertyColorItem::setValue(const QVariant& value) } auto col = value.value(); QString data = - QString::fromLatin1("(%1,%2,%3)").arg(col.red()).arg(col.green()).arg(col.blue()); + QStringLiteral("(%1,%2,%3)").arg(col.red()).arg(col.green()).arg(col.blue()); setPropertyValue(data); } @@ -3715,7 +3715,7 @@ QVariant PropertyMaterialItem::toString(const QVariant& prop) const auto val = prop.value(); QColor value = val.diffuseColor; QString color = - QString::fromLatin1("[%1, %2, %3]").arg(value.red()).arg(value.green()).arg(value.blue()); + QStringLiteral("[%1, %2, %3]").arg(value.red()).arg(value.green()).arg(value.blue()); return {color}; } @@ -3729,7 +3729,7 @@ QVariant PropertyMaterialItem::toolTip(const App::Property* prop) const auto sc = value.specularColor.asValue(); auto ec = value.emissiveColor.asValue(); - QString data = QString::fromUtf8("Diffuse color: [%1, %2, %3]\n" + QString data = QStringLiteral("Diffuse color: [%1, %2, %3]\n" "Ambient color: [%4, %5, %6]\n" "Specular color: [%7, %8, %9]\n" "Emissive color: [%10, %11, %12]\n" @@ -3788,7 +3788,7 @@ void PropertyMaterialItem::setValue(const QVariant& value) float s = mat.shininess; float t = mat.transparency; - QString data = QString::fromLatin1("App.Material(" + QString data = QStringLiteral("App.Material(" "DiffuseColor=(%1,%2,%3)," "AmbientColor=(%4,%5,%6)," "SpecularColor=(%7,%8,%9)," @@ -4197,7 +4197,7 @@ QVariant PropertyMaterialListItem::toString(const QVariant& prop) const auto mat = list[0].value(); QColor value = mat.diffuseColor; QString color = - QString::fromLatin1("[%1, %2, %3]").arg(value.red()).arg(value.green()).arg(value.blue()); + QStringLiteral("[%1, %2, %3]").arg(value.red()).arg(value.green()).arg(value.blue()); return {color}; } @@ -4217,7 +4217,7 @@ QVariant PropertyMaterialListItem::toolTip(const App::Property* prop) const auto sc = value.specularColor.asValue(); auto ec = value.emissiveColor.asValue(); - QString data = QString::fromUtf8("Diffuse color: [%1, %2, %3]\n" + QString data = QStringLiteral("Diffuse color: [%1, %2, %3]\n" "Ambient color: [%4, %5, %6]\n" "Specular color: [%7, %8, %9]\n" "Emissive color: [%10, %11, %12]\n" @@ -4295,7 +4295,7 @@ void PropertyMaterialListItem::setValue(const QVariant& value) float s = mat.shininess; float t = mat.transparency; - QString item = QString::fromLatin1("App.Material(" + QString item = QStringLiteral("App.Material(" "DiffuseColor=(%1,%2,%3)," "AmbientColor=(%4,%5,%6)," "SpecularColor=(%7,%8,%9)," @@ -4612,7 +4612,7 @@ void LinkLabel::updatePropertyLink() auto& sobj = links.front(); link = QVariant::fromValue(sobj); QString linkcolor = QApplication::palette().color(QPalette::Link).name(); - text = QString::fromLatin1("" "

" diff --git a/src/Gui/resource.cpp b/src/Gui/resource.cpp index 41d6c35e3d..cdf3485ccd 100644 --- a/src/Gui/resource.cpp +++ b/src/Gui/resource.cpp @@ -29,7 +29,7 @@ // INCLUDE YOUR PREFERENCE PAGES HERE // -#include "DlgPreferencesImp.h" +#include "Dialogs/DlgPreferencesImp.h" #include "PreferencePages/DlgSettings3DViewImp.h" #include "PreferencePages/DlgSettingsCacheDirectory.h" #include "PreferencePages/DlgSettingsDocumentImp.h" @@ -47,13 +47,13 @@ #include "PreferencePages/DlgSettingsWorkbenchesImp.h" #include "PreferencePages/DlgSettingsAdvanced.h" -#include "DlgToolbarsImp.h" -#include "DlgActionsImp.h" -#include "DlgKeyboardImp.h" +#include "Dialogs/DlgToolbarsImp.h" +#include "Dialogs/DlgActionsImp.h" +#include "Dialogs/DlgKeyboardImp.h" #if defined(_USE_3DCONNEXION_SDK) || defined(SPNAV_FOUND) -#include "DlgCustomizeSpaceball.h" -#include "DlgCustomizeSpNavSettings.h" +#include "Dialogs/DlgCustomizeSpaceball.h" +#include "Dialogs/DlgCustomizeSpNavSettings.h" #endif #include "InputField.h" diff --git a/src/Main/MainCmd.cpp b/src/Main/MainCmd.cpp index ae23df7e20..8dba8a5ef2 100644 --- a/src/Main/MainCmd.cpp +++ b/src/Main/MainCmd.cpp @@ -51,7 +51,7 @@ using App::Application; using Base::Console; const char sBanner[] = - "(C) 2001-2024 FreeCAD contributors\n" + "(C) 2001-2025 FreeCAD contributors\n" "FreeCAD is free and open-source software licensed under the terms of LGPL2+ license.\n\n"; int main(int argc, char** argv) diff --git a/src/Main/MainGui.cpp b/src/Main/MainGui.cpp index be25becbef..bcb07ffd19 100644 --- a/src/Main/MainGui.cpp +++ b/src/Main/MainGui.cpp @@ -61,7 +61,7 @@ void PrintInitHelp(); const char sBanner[] = - "(C) 2001-2024 FreeCAD contributors\n" + "(C) 2001-2025 FreeCAD contributors\n" "FreeCAD is free and open-source software licensed under the terms of LGPL2+ license.\n\n"; #if defined(_MSC_VER) @@ -95,6 +95,35 @@ private: FILE* file; }; +static void DisplayInfo(const QString& msg, bool preformatted = true) +{ + if (App::Application::Config()["Console"] == "1") { + std::cout << msg.toStdString(); + return; + } + + QString appName = QString::fromStdString(App::Application::Config()["ExeName"]); + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Information); + msgBox.setWindowTitle(appName); + msgBox.setDetailedText(msg); + msgBox.setText(preformatted ? QStringLiteral("

%1
").arg(msg) : msg); + msgBox.exec(); +} + +static void DisplayCritical(const QString& msg, bool preformatted = true) +{ + if (App::Application::Config()["Console"] == "1") { + std::cerr << msg.toStdString(); + return; + } + + QString appName = QString::fromStdString(App::Application::Config()["ExeName"]); + QString title = QObject::tr("Initialization of %1 failed").arg(appName); + QString text = preformatted ? QStringLiteral("
%1
").arg(msg) : msg; + QMessageBox::critical(nullptr, title, text); +} + int main(int argc, char** argv) { #if defined(FC_OS_LINUX) || defined(FC_OS_BSD) @@ -217,24 +246,14 @@ int main(int argc, char** argv) } catch (const Base::UnknownProgramOption& e) { QApplication app(argc, argv); - QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromLatin1(e.what()); - QString s = QLatin1String("
") + msg + QLatin1String("
"); - QMessageBox::critical(nullptr, appName, s); + DisplayCritical(msg); exit(1); } catch (const Base::ProgramInformation& e) { QApplication app(argc, argv); - QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromUtf8(e.what()); - QString s = QLatin1String("
") + msg + QLatin1String("
"); - - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Information); - msgBox.setWindowTitle(appName); - msgBox.setDetailedText(msg); - msgBox.setText(s); - msgBox.exec(); + DisplayInfo(msg); exit(0); } catch (const Base::Exception& e) { @@ -261,9 +280,7 @@ int main(int argc, char** argv) "\nPlease contact the application's support team for more information.\n\n"); } - QMessageBox::critical(nullptr, - QObject::tr("Initialization of %1 failed").arg(appName), - msg); + DisplayCritical(msg, false); exit(100); } catch (...) { @@ -274,9 +291,7 @@ int main(int argc, char** argv) QObject::tr("Unknown runtime error occurred while initializing %1.\n\n" "Please contact the application's support team for more information.\n\n") .arg(appName); - QMessageBox::critical(nullptr, - QObject::tr("Initialization of %1 failed").arg(appName), - msg); + DisplayCritical(msg, false); exit(101); } diff --git a/src/Mod/AddonManager/Addon.py b/src/Mod/AddonManager/Addon.py index 7266dba998..d028429689 100644 --- a/src/Mod/AddonManager/Addon.py +++ b/src/Mod/AddonManager/Addon.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Defines the Addon class to encapsulate information about FreeCAD Addons """ +"""Defines the Addon class to encapsulate information about FreeCAD Addons""" import os import re diff --git a/src/Mod/AddonManager/AddonManagerOptions.py b/src/Mod/AddonManager/AddonManagerOptions.py index 4b1d7e2300..783f1a733a 100644 --- a/src/Mod/AddonManager/AddonManagerOptions.py +++ b/src/Mod/AddonManager/AddonManagerOptions.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Contains a the Addon Manager's preferences dialog management class """ +"""Contains a the Addon Manager's preferences dialog management class""" import os diff --git a/src/Mod/AddonManager/AddonManagerTest/app/test_dependency_installer.py b/src/Mod/AddonManager/AddonManagerTest/app/test_dependency_installer.py index e0ba09cad1..c70e08491c 100644 --- a/src/Mod/AddonManager/AddonManagerTest/app/test_dependency_installer.py +++ b/src/Mod/AddonManager/AddonManagerTest/app/test_dependency_installer.py @@ -136,12 +136,6 @@ class TestDependencyInstaller(unittest.TestCase): self.assertTrue(ff_required.called) self.assertTrue(ff_optional.called) - def test_verify_pip_no_python(self): - self.test_object._get_python = lambda: None - should_continue = self.test_object._verify_pip() - self.assertFalse(should_continue) - self.assertEqual(len(self.signals_caught), 0) - def test_verify_pip_no_pip(self): sm = SubprocessMock() sm.succeed = False diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_change_branch.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_change_branch.py new file mode 100644 index 0000000000..b70689d0c4 --- /dev/null +++ b/src/Mod/AddonManager/AddonManagerTest/gui/test_change_branch.py @@ -0,0 +1,234 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# *************************************************************************** +# * * +# * Copyright (c) 2025 The FreeCAD Project Association AISBL * +# * * +# * This file is part of FreeCAD. * +# * * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * +# * * +# *************************************************************************** + +"""Test the Change Branch GUI code""" + +# pylint: disable=wrong-import-position, deprecated-module, too-many-return-statements + +import sys +import unittest +from unittest.mock import patch, Mock, MagicMock + +# So that when run standalone, the Addon Manager classes imported below are available +sys.path.append("../..") + +from AddonManagerTest.gui.gui_mocks import DialogWatcher, AsynchronousMonitor + +from change_branch import ChangeBranchDialog + +from addonmanager_freecad_interface import translate +from addonmanager_git import GitFailed + +try: + from PySide import QtCore, QtWidgets +except ImportError: + try: + from PySide6 import QtCore, QtWidgets + except ImportError: + from PySide2 import QtCore, QtWidgets + + +class MockFilter(QtCore.QSortFilterProxyModel): + """Replaces a filter with a non-filter that simply always returns whatever it's given""" + + def mapToSource(self, something): + return something + + +class MockChangeBranchDialogModel(QtCore.QAbstractTableModel): + """Replace a data-connected model with a static one for testing""" + + branches = [ + {"ref_name": "ref1", "upstream": "us1"}, + {"ref_name": "ref2", "upstream": "us2"}, + {"ref_name": "ref3", "upstream": "us3"}, + ] + current_branch = "ref1" + DataSortRole = QtCore.Qt.UserRole + RefAccessRole = QtCore.Qt.UserRole + 1 + + def __init__(self, _: str, parent=None) -> None: + super().__init__(parent) + + def rowCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int: + """Number of rows: should always return 3""" + if parent.isValid(): + return 0 + return len(self.branches) + + def columnCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int: + """Number of columns (identical to non-mocked version)""" + if parent.isValid(): + return 0 + return 3 # Local name, remote name, date + + def data(self, index: QtCore.QModelIndex, role: int = QtCore.Qt.DisplayRole): + """Mock returns static untranslated strings for DisplayRole, no tooltips at all, and + otherwise matches the non-mock version""" + if not index.isValid(): + return None + row = index.row() + column = index.column() + if role == QtCore.Qt.DisplayRole: + if column == 2: + return "date" + if column == 0: + return "ref_name" + if column == 1: + return "upstream" + return None + if role == MockChangeBranchDialogModel.DataSortRole: + return None + if role == MockChangeBranchDialogModel.RefAccessRole: + return self.branches[row] + return None + + def headerData( + self, + section: int, + orientation: QtCore.Qt.Orientation, + role: int = QtCore.Qt.DisplayRole, + ): + """Mock returns untranslated strings for DisplayRole, and no tooltips at all""" + if orientation == QtCore.Qt.Vertical: + return None + if role != QtCore.Qt.DisplayRole: + return None + if section == 0: + return "Local" + if section == 1: + return "Remote tracking" + if section == 2: + return "Last Updated" + return None + + def currentBranch(self) -> str: + """Mock returns a static string stored in the class: that string could be modified to + return something else by tests that require it.""" + return self.current_branch + + +class TestChangeBranchGui(unittest.TestCase): + """Tests for the ChangeBranch GUI code""" + + MODULE = "test_change_branch" # file name without extension + + def setUp(self): + pass + + def tearDown(self): + pass + + @patch("change_branch.ChangeBranchDialogModel", new=MockChangeBranchDialogModel) + @patch("change_branch.initialize_git", new=Mock(return_value=None)) + def test_no_git(self): + """If git is not present, a dialog saying so is presented""" + # Arrange + gui = ChangeBranchDialog("/some/path") + ref = {"ref_name": "foo/bar", "upstream": "us1"} + dialog_watcher = DialogWatcher( + translate("AddonsInstaller", "Cannot find git"), + QtWidgets.QDialogButtonBox.Ok, + ) + + # Act + gui.change_branch("/foo/bar/baz", ref) + + # Assert + self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") + + @patch("change_branch.ChangeBranchDialogModel", new=MockChangeBranchDialogModel) + @patch("change_branch.initialize_git") + def test_git_failed(self, init_git: MagicMock): + """If git fails when attempting to change branches, a dialog saying so is presented""" + # Arrange + git_manager = MagicMock() + git_manager.checkout = MagicMock() + git_manager.checkout.side_effect = GitFailed() + init_git.return_value = git_manager + gui = ChangeBranchDialog("/some/path") + ref = {"ref_name": "foo/bar", "upstream": "us1"} + dialog_watcher = DialogWatcher( + translate("AddonsInstaller", "git operation failed"), + QtWidgets.QDialogButtonBox.Ok, + ) + + # Act + gui.change_branch("/foo/bar/baz", ref) + + # Assert + self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") + + @patch("change_branch.ChangeBranchDialogModel", new=MockChangeBranchDialogModel) + @patch("change_branch.initialize_git", new=MagicMock) + def test_branch_change_succeeded(self): + """If nothing gets thrown, then the process is assumed to have worked, and the appropriate + signal is emitted.""" + + # Arrange + gui = ChangeBranchDialog("/some/path") + ref = {"ref_name": "foo/bar", "upstream": "us1"} + monitor = AsynchronousMonitor(gui.branch_changed) + + # Act + gui.change_branch("/foo/bar/baz", ref) + + # Assert + monitor.wait_for_at_most(10) # Should be effectively instantaneous + self.assertTrue(monitor.good()) + + @patch("change_branch.ChangeBranchDialogFilter", new=MockFilter) + @patch("change_branch.ChangeBranchDialogModel", new=MockChangeBranchDialogModel) + @patch("change_branch.initialize_git", new=MagicMock) + def test_warning_is_shown_when_dialog_is_accepted(self): + """If the dialog is accepted (e.g. a branch change is requested) then a warning dialog is + displayed, and gives the opportunity to cancel. If cancelled, no signal is emitted.""" + # Arrange + gui = ChangeBranchDialog("/some/path") + gui.ui.exec = MagicMock() + gui.ui.exec.return_value = QtWidgets.QDialog.Accepted + gui.ui.tableView.selectedIndexes = MagicMock() + gui.ui.tableView.selectedIndexes.return_value = [MagicMock()] + gui.ui.tableView.selectedIndexes.return_value[0].isValid = MagicMock() + gui.ui.tableView.selectedIndexes.return_value[0].isValid.return_value = True + dialog_watcher = DialogWatcher( + translate("AddonsInstaller", "DANGER: Developer feature"), + QtWidgets.QDialogButtonBox.Cancel, + ) + monitor = AsynchronousMonitor(gui.branch_changed) + + # Act + gui.exec() + + # Assert + self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box") + self.assertFalse(monitor.good()) # The watcher cancelled the op, so no signal is emitted + + +if __name__ == "__main__": + app = QtWidgets.QApplication(sys.argv) + QtCore.QTimer.singleShot(0, unittest.main) + if hasattr(app, "exec"): + app.exec() # PySide6 + else: + app.exec_() # PySide2 diff --git a/src/Mod/AddonManager/AddonStats.py b/src/Mod/AddonManager/AddonStats.py index 60c329dcc8..4cf7b319ac 100644 --- a/src/Mod/AddonManager/AddonStats.py +++ b/src/Mod/AddonManager/AddonStats.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Classes and structures related to Addon sidecar information """ +"""Classes and structures related to Addon sidecar information""" from __future__ import annotations from dataclasses import dataclass diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_addon_buttons.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_addon_buttons.py index 8c65c5998c..e5ffc3fdc1 100644 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_addon_buttons.py +++ b/src/Mod/AddonManager/Widgets/addonmanager_widget_addon_buttons.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Defines a QWidget-derived class for displaying the single-addon buttons. """ +"""Defines a QWidget-derived class for displaying the single-addon buttons.""" from enum import Enum, auto diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_filter_selector.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_filter_selector.py index a8fb528dc4..308335e3c9 100644 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_filter_selector.py +++ b/src/Mod/AddonManager/Widgets/addonmanager_widget_filter_selector.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Defines a QWidget-derived class for displaying the view selection buttons. """ +"""Defines a QWidget-derived class for displaying the view selection buttons.""" from enum import IntEnum diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_global_buttons.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_global_buttons.py index cce7336890..67833201bd 100644 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_global_buttons.py +++ b/src/Mod/AddonManager/Widgets/addonmanager_widget_global_buttons.py @@ -21,9 +21,9 @@ # * * # *************************************************************************** -""" Defines a QWidget-derived class for displaying a set of buttons that affect the Addon +"""Defines a QWidget-derived class for displaying a set of buttons that affect the Addon Manager as a whole (rather than a specific Addon). Typically inserted at the bottom of the Addon -Manager main window. """ +Manager main window.""" try: import FreeCAD diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_progress_bar.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_progress_bar.py index 2e069a5baf..1e9c0a1f20 100644 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_progress_bar.py +++ b/src/Mod/AddonManager/Widgets/addonmanager_widget_progress_bar.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Defines a QWidget-derived class for displaying the cache load status. """ +"""Defines a QWidget-derived class for displaying the cache load status.""" try: import FreeCAD diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_search.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_search.py index 7da8b1c271..339f31fcdf 100644 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_search.py +++ b/src/Mod/AddonManager/Widgets/addonmanager_widget_search.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Defines a QWidget-derived class for displaying the view selection buttons. """ +"""Defines a QWidget-derived class for displaying the view selection buttons.""" try: import FreeCAD diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_view_control_bar.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_view_control_bar.py index 9343b030e1..3d44a18954 100644 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_view_control_bar.py +++ b/src/Mod/AddonManager/Widgets/addonmanager_widget_view_control_bar.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Defines a class derived from QWidget for displaying the bar at the top of the addons list. """ +"""Defines a class derived from QWidget for displaying the bar at the top of the addons list.""" from enum import IntEnum, auto diff --git a/src/Mod/AddonManager/Widgets/addonmanager_widget_view_selector.py b/src/Mod/AddonManager/Widgets/addonmanager_widget_view_selector.py index 3049d23194..7a65a0f655 100644 --- a/src/Mod/AddonManager/Widgets/addonmanager_widget_view_selector.py +++ b/src/Mod/AddonManager/Widgets/addonmanager_widget_view_selector.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Defines a QWidget-derived class for displaying the view selection buttons. """ +"""Defines a QWidget-derived class for displaying the view selection buttons.""" from enum import IntEnum diff --git a/src/Mod/AddonManager/addonmanager_connection_checker.py b/src/Mod/AddonManager/addonmanager_connection_checker.py index ac3c08aa14..1b721ce761 100644 --- a/src/Mod/AddonManager/addonmanager_connection_checker.py +++ b/src/Mod/AddonManager/addonmanager_connection_checker.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" System for checking the network connection status asynchronously. """ +"""System for checking the network connection status asynchronously.""" import FreeCAD diff --git a/src/Mod/AddonManager/addonmanager_dependency_installer.py b/src/Mod/AddonManager/addonmanager_dependency_installer.py index 466809e2de..edead4ff53 100644 --- a/src/Mod/AddonManager/addonmanager_dependency_installer.py +++ b/src/Mod/AddonManager/addonmanager_dependency_installer.py @@ -27,8 +27,6 @@ import os import subprocess from typing import List -from freecad.utils import get_python_exe - import addonmanager_freecad_interface as fci from addonmanager_pyside_interface import QObject, Signal, is_interruption_requested @@ -46,7 +44,7 @@ class DependencyInstaller(QObject): no_python_exe = Signal() no_pip = Signal(str) # Attempted command failure = Signal(str, str) # Short message, detailed message - finished = Signal() + finished = Signal(bool) # True if everything completed normally, otherwise false def __init__( self, @@ -65,17 +63,25 @@ class DependencyInstaller(QObject): self.python_requires = python_requires self.python_optional = python_optional self.location = location + self.required_succeeded = False + self.finished_successfully = False def run(self): """Normally not called directly, but rather connected to the worker thread's started signal.""" - if self._verify_pip(): + try: if self.python_requires or self.python_optional: - if not is_interruption_requested(): - self._install_python_packages() - if not is_interruption_requested(): - self._install_addons() - self.finished.emit() + if self._verify_pip(): + if not is_interruption_requested(): + self._install_python_packages() + else: + self.required_succeeded = True + if not is_interruption_requested(): + self._install_addons() + self.finished_successfully = self.required_succeeded + except RuntimeError: + pass + self.finished.emit(self.finished_successfully) def _install_python_packages(self): """Install required and optional Python dependencies using pip.""" @@ -87,20 +93,20 @@ class DependencyInstaller(QObject): if not os.path.exists(vendor_path): os.makedirs(vendor_path) - self._install_required(vendor_path) + self.required_succeeded = self._install_required(vendor_path) self._install_optional(vendor_path) def _verify_pip(self) -> bool: """Ensure that pip is working -- returns True if it is, or False if not. Also emits the no_pip signal if pip cannot execute.""" - python_exe = self._get_python() - if not python_exe: - return False try: proc = self._run_pip(["--version"]) fci.Console.PrintMessage(proc.stdout + "\n") + if proc.returncode != 0: + return False except subprocess.CalledProcessError: - self.no_pip.emit(f"{python_exe} -m pip --version") + call = utils.create_pip_call([]) + self.no_pip.emit(" ".join(call)) return False return True @@ -115,7 +121,6 @@ class DependencyInstaller(QObject): proc = self._run_pip( [ "install", - "--disable-pip-version-check", "--target", vendor_path, pymod, @@ -144,7 +149,6 @@ class DependencyInstaller(QObject): proc = self._run_pip( [ "install", - "--disable-pip-version-check", "--target", vendor_path, pymod, @@ -160,22 +164,13 @@ class DependencyInstaller(QObject): ) def _run_pip(self, args): - python_exe = self._get_python() - final_args = [python_exe, "-m", "pip"] - final_args.extend(args) + final_args = utils.create_pip_call(args) return self._subprocess_wrapper(final_args) @staticmethod def _subprocess_wrapper(args) -> subprocess.CompletedProcess: """Wrap subprocess call so test code can mock it.""" - return utils.run_interruptable_subprocess(args) - - def _get_python(self) -> str: - """Wrap Python access so test code can mock it.""" - python_exe = get_python_exe() - if not python_exe: - self.no_python_exe.emit() - return python_exe + return utils.run_interruptable_subprocess(args, timeout_secs=120) def _install_addons(self): for addon in self.addons: diff --git a/src/Mod/AddonManager/addonmanager_devmode.py b/src/Mod/AddonManager/addonmanager_devmode.py index 860b9ab934..4888ae6076 100644 --- a/src/Mod/AddonManager/addonmanager_devmode.py +++ b/src/Mod/AddonManager/addonmanager_devmode.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Classes to manage "Developer Mode" """ +"""Classes to manage "Developer Mode" """ import os import datetime diff --git a/src/Mod/AddonManager/addonmanager_devmode_add_content.py b/src/Mod/AddonManager/addonmanager_devmode_add_content.py index c5994ccbab..f990f643ec 100644 --- a/src/Mod/AddonManager/addonmanager_devmode_add_content.py +++ b/src/Mod/AddonManager/addonmanager_devmode_add_content.py @@ -21,8 +21,8 @@ # * * # *************************************************************************** -""" Contains a class for adding a single content item, as well as auxiliary classes for -its dependent dialog boxes. """ +"""Contains a class for adding a single content item, as well as auxiliary classes for +its dependent dialog boxes.""" import os from typing import Optional, Tuple, List diff --git a/src/Mod/AddonManager/addonmanager_devmode_license_selector.py b/src/Mod/AddonManager/addonmanager_devmode_license_selector.py index 72db565694..2e6441d9f8 100644 --- a/src/Mod/AddonManager/addonmanager_devmode_license_selector.py +++ b/src/Mod/AddonManager/addonmanager_devmode_license_selector.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Contains a class to manage selection of a license for an Addon. """ +"""Contains a class to manage selection of a license for an Addon.""" import os from datetime import date diff --git a/src/Mod/AddonManager/addonmanager_devmode_licenses_table.py b/src/Mod/AddonManager/addonmanager_devmode_licenses_table.py index 1d52568471..26e29c434c 100644 --- a/src/Mod/AddonManager/addonmanager_devmode_licenses_table.py +++ b/src/Mod/AddonManager/addonmanager_devmode_licenses_table.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Contains a wrapper class for a table listing authors and maintainers """ +"""Contains a wrapper class for a table listing authors and maintainers""" import os diff --git a/src/Mod/AddonManager/addonmanager_devmode_metadata_checker.py b/src/Mod/AddonManager/addonmanager_devmode_metadata_checker.py index d1ec922836..efae4ab928 100644 --- a/src/Mod/AddonManager/addonmanager_devmode_metadata_checker.py +++ b/src/Mod/AddonManager/addonmanager_devmode_metadata_checker.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Metadata validation functions """ +"""Metadata validation functions""" from typing import List diff --git a/src/Mod/AddonManager/addonmanager_devmode_people_table.py b/src/Mod/AddonManager/addonmanager_devmode_people_table.py index e6caca269a..048100bff4 100644 --- a/src/Mod/AddonManager/addonmanager_devmode_people_table.py +++ b/src/Mod/AddonManager/addonmanager_devmode_people_table.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Contains a wrapper class for a table listing authors and maintainers """ +"""Contains a wrapper class for a table listing authors and maintainers""" import os diff --git a/src/Mod/AddonManager/addonmanager_devmode_person_editor.py b/src/Mod/AddonManager/addonmanager_devmode_person_editor.py index 4c1fbda24c..12f5d2a31a 100644 --- a/src/Mod/AddonManager/addonmanager_devmode_person_editor.py +++ b/src/Mod/AddonManager/addonmanager_devmode_person_editor.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Contains a class to handle editing a person (from a Metadata standpoint). """ +"""Contains a class to handle editing a person (from a Metadata standpoint).""" import os from typing import Tuple # Needed until Py 3.9, when tuple supports this directly diff --git a/src/Mod/AddonManager/addonmanager_devmode_predictor.py b/src/Mod/AddonManager/addonmanager_devmode_predictor.py index 278ada4e87..012e0eb6c5 100644 --- a/src/Mod/AddonManager/addonmanager_devmode_predictor.py +++ b/src/Mod/AddonManager/addonmanager_devmode_predictor.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Class to guess metadata based on folder contents. Note that one of the functions +"""Class to guess metadata based on folder contents. Note that one of the functions of this file is to guess the license being applied to the new software package based in its contents. It is up to the user to make the final determination about whether the selected license is the correct one, and inclusion here shouldn't be construed as diff --git a/src/Mod/AddonManager/addonmanager_devmode_validators.py b/src/Mod/AddonManager/addonmanager_devmode_validators.py index 000f2aaefc..c4c7e71fda 100644 --- a/src/Mod/AddonManager/addonmanager_devmode_validators.py +++ b/src/Mod/AddonManager/addonmanager_devmode_validators.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Validators used for various line edits """ +"""Validators used for various line edits""" import keyword diff --git a/src/Mod/AddonManager/addonmanager_firstrun.py b/src/Mod/AddonManager/addonmanager_firstrun.py index 2fc9f8a3b1..2b8cbeb378 100644 --- a/src/Mod/AddonManager/addonmanager_firstrun.py +++ b/src/Mod/AddonManager/addonmanager_firstrun.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Class to display a first-run dialog for the Addon Manager """ +"""Class to display a first-run dialog for the Addon Manager""" import os diff --git a/src/Mod/AddonManager/addonmanager_freecad_interface.py b/src/Mod/AddonManager/addonmanager_freecad_interface.py index ac66a100ca..5a087a4efe 100644 --- a/src/Mod/AddonManager/addonmanager_freecad_interface.py +++ b/src/Mod/AddonManager/addonmanager_freecad_interface.py @@ -46,9 +46,13 @@ try: getUserMacroDir = FreeCAD.getUserMacroDir getUserCachePath = FreeCAD.getUserCachePath translate = FreeCAD.Qt.translate + loadUi = None if FreeCAD.GuiUp: import FreeCADGui + + if hasattr(FreeCADGui, "PySideUic"): + loadUi = FreeCADGui.PySideUic.loadUi else: FreeCADGui = None @@ -63,7 +67,7 @@ except ImportError: return string def Version(): - return 0, 22, 0, "dev" + return 1, 1, 0, "dev" class ConsoleReplacement: """If FreeCAD's Console is not available, create a replacement by redirecting FreeCAD diff --git a/src/Mod/AddonManager/addonmanager_installer.py b/src/Mod/AddonManager/addonmanager_installer.py index d3f2f7de1b..059f0fc0c1 100644 --- a/src/Mod/AddonManager/addonmanager_installer.py +++ b/src/Mod/AddonManager/addonmanager_installer.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Contains the classes to manage Addon installation: intended as a stable API, safe for external +"""Contains the classes to manage Addon installation: intended as a stable API, safe for external code to call and to rely upon existing. See classes AddonInstaller and MacroInstaller for details. """ import json diff --git a/src/Mod/AddonManager/addonmanager_installer_gui.py b/src/Mod/AddonManager/addonmanager_installer_gui.py index 7eec964e52..c2139f4f05 100644 --- a/src/Mod/AddonManager/addonmanager_installer_gui.py +++ b/src/Mod/AddonManager/addonmanager_installer_gui.py @@ -77,14 +77,26 @@ class AddonInstallerGUI(QtCore.QObject): self.installer.failure.connect(self._installation_failed) def __del__(self): - if self.worker_thread and hasattr(self.worker_thread, "quit"): - self.worker_thread.quit() - self.worker_thread.wait(500) - if self.worker_thread.isRunning(): + self._stop_thread(self.worker_thread) + self._stop_thread(self.dependency_worker_thread) + + @staticmethod + def _stop_thread(thread: QtCore.QThread): + if thread and hasattr(thread, "quit"): + if thread.isRunning(): + FreeCAD.Console.PrintMessage( + "INTERNAL ERROR: a QThread is still running when it should have finished" + ) + + thread.requestInterruption() + thread.wait(100) + thread.quit() + thread.wait(500) + if thread.isRunning(): FreeCAD.Console.PrintError( "INTERNAL ERROR: Thread did not quit() cleanly, using terminate()\n" ) - self.worker_thread.terminate() + thread.terminate() def run(self): """Instructs this class to begin displaying the necessary dialogs to guide a user through @@ -300,13 +312,11 @@ class AddonInstallerGUI(QtCore.QObject): self.dependency_installer.no_python_exe.connect(self._report_no_python_exe) self.dependency_installer.no_pip.connect(self._report_no_pip) self.dependency_installer.failure.connect(self._report_dependency_failure) - self.dependency_installer.finished.connect(self._cleanup_dependency_worker) - self.dependency_installer.finished.connect(self._report_dependency_success) + self.dependency_installer.finished.connect(self._dependencies_finished) self.dependency_worker_thread = QtCore.QThread(self) self.dependency_installer.moveToThread(self.dependency_worker_thread) self.dependency_worker_thread.started.connect(self.dependency_installer.run) - self.dependency_installer.finished.connect(self.dependency_worker_thread.quit) self.dependency_installation_dialog = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, @@ -319,16 +329,6 @@ class AddonInstallerGUI(QtCore.QObject): self.dependency_installation_dialog.show() self.dependency_worker_thread.start() - def _cleanup_dependency_worker(self) -> None: - return - self.dependency_worker_thread.quit() - self.dependency_worker_thread.wait(500) - if self.dependency_worker_thread.isRunning(): - FreeCAD.Console.PrintError( - "INTERNAL ERROR: Thread did not quit() cleanly, using terminate()\n" - ) - self.dependency_worker_thread.terminate() - def _report_no_python_exe(self) -> None: """Callback for the dependency installer failing to locate a Python executable.""" if self.dependency_installation_dialog is not None: @@ -409,6 +409,11 @@ class AddonInstallerGUI(QtCore.QObject): self.dependency_installation_dialog.hide() self.install() + def _dependencies_finished(self, success: bool): + if success: + self._report_dependency_success() + self.dependency_worker_thread.quit() + def _dependency_dialog_ignore_clicked(self) -> None: """Callback for when dependencies are ignored.""" self.install() diff --git a/src/Mod/AddonManager/addonmanager_licenses.py b/src/Mod/AddonManager/addonmanager_licenses.py index 5781c093a2..46af254959 100644 --- a/src/Mod/AddonManager/addonmanager_licenses.py +++ b/src/Mod/AddonManager/addonmanager_licenses.py @@ -21,9 +21,9 @@ # * * # *************************************************************************** -""" Utilities for working with licenses. Based on SPDX info downloaded from +"""Utilities for working with licenses. Based on SPDX info downloaded from https://github.com/spdx/license-list-data and stored as part of the FreeCAD repo, loaded into a Qt -resource. """ +resource.""" import json diff --git a/src/Mod/AddonManager/addonmanager_macro.py b/src/Mod/AddonManager/addonmanager_macro.py index 2af34c7b2c..9858076f9c 100644 --- a/src/Mod/AddonManager/addonmanager_macro.py +++ b/src/Mod/AddonManager/addonmanager_macro.py @@ -22,7 +22,7 @@ # * * # *************************************************************************** -""" Unified handler for FreeCAD macros that can be obtained from different sources. """ +"""Unified handler for FreeCAD macros that can be obtained from different sources.""" import os import re diff --git a/src/Mod/AddonManager/addonmanager_package_details_controller.py b/src/Mod/AddonManager/addonmanager_package_details_controller.py index 9d84e8055d..ccd97a2e7f 100644 --- a/src/Mod/AddonManager/addonmanager_package_details_controller.py +++ b/src/Mod/AddonManager/addonmanager_package_details_controller.py @@ -248,18 +248,6 @@ class PackageDetailsController(QtCore.QObject): def branch_changed(self, old_branch: str, name: str) -> None: """Displays a dialog confirming the branch changed, and tries to access the metadata file from that branch.""" - QtWidgets.QMessageBox.information( - self.ui, - translate("AddonsInstaller", "Success"), - translate( - "AddonsInstaller", - "Branch change succeeded.\n" - "Moved\n" - "from: {}\n" - "to: {}\n" - "Please restart to use the new version.", - ).format(old_branch, name), - ) # See if this branch has a package.xml file: basedir = fci.getUserAppDataDir() path_to_metadata = os.path.join(basedir, "Mod", self.addon.name, "package.xml") @@ -275,6 +263,18 @@ class PackageDetailsController(QtCore.QObject): self.addon.set_status(Addon.Status.PENDING_RESTART) self.ui.set_new_branch(name) self.update_status.emit(self.addon) + QtWidgets.QMessageBox.information( + self.ui, + translate("AddonsInstaller", "Success"), + translate( + "AddonsInstaller", + "Branch change succeeded.\n" + "Moved\n" + "from: {}\n" + "to: {}\n" + "Please restart to use the new version.", + ).format(old_branch, name), + ) def display_repo_status(self, addon): self.update_status.emit(self.addon) diff --git a/src/Mod/AddonManager/addonmanager_python_deps_gui.py b/src/Mod/AddonManager/addonmanager_python_deps_gui.py index 4419b1635c..8123ef9930 100644 --- a/src/Mod/AddonManager/addonmanager_python_deps_gui.py +++ b/src/Mod/AddonManager/addonmanager_python_deps_gui.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: LGPL-2.1-or-later # *************************************************************************** # * * -# * Copyright (c) 2022-2024 FreeCAD Project Association AISBL * +# * Copyright (c) 2022-2025 FreeCAD Project Association AISBL * # * * # * This file is part of FreeCAD. * # * * @@ -21,9 +21,9 @@ # * * # *************************************************************************** -""" Provides classes and support functions for managing the automatically-installed +"""Provides classes and support functions for managing the automatically-installed Python library dependencies. No support is provided for uninstalling those dependencies -because pip's uninstall function does not support the target directory argument. """ +because pip's uninstall function does not support the target directory argument.""" import json import os @@ -33,20 +33,37 @@ import subprocess import sys from functools import partial from typing import Dict, Iterable, List, Tuple, TypedDict +from addonmanager_utilities import create_pip_call import addonmanager_freecad_interface as fci try: from PySide import QtCore, QtGui, QtWidgets - from PySide.QtUiTools import QUiLoader except ImportError: try: from PySide6 import QtCore, QtGui, QtWidgets - from PySide6.QtUiTools import QUiLoader except ImportError: from PySide2 import QtCore, QtGui, QtWidgets + +# Make sure this can run inside and outside FreeCAD, and don't require that (when run inside FreeCAD) the user has the +# python QtUiTools installed, because FreeCAD wraps it for us. +try: + import FreeCADGui + + loadUi = FreeCADGui.PySideUic.loadUi +except ImportError: + try: + from PySide6.QtUiTools import QUiLoader + except ImportError: from PySide2.QtUiTools import QUiLoader + def loadUi(ui_file: str) -> QtWidgets.QWidget: + q_ui_file = QtCore.QFile(ui_file) + q_ui_file.open(QtCore.QFile.OpenModeFlag.ReadOnly) + loader = QUiLoader() + return loader.load(ui_file) + + try: from freecad.utils import get_python_exe except ImportError: @@ -107,26 +124,21 @@ def call_pip(args: List[str]) -> List[str]: """Tries to locate the appropriate Python executable and run pip with version checking disabled. Fails if Python can't be found or if pip is not installed.""" - python_exe = get_python_exe() - pip_failed = False - if python_exe: - call_args = [python_exe, "-m", "pip", "--disable-pip-version-check"] - call_args.extend(args) - proc = None - try: - proc = utils.run_interruptable_subprocess(call_args) - except subprocess.CalledProcessError: - pip_failed = True + try: + call_args = create_pip_call(args) + except RuntimeError as exception: + raise PipFailed() from exception - if not pip_failed: - data = proc.stdout - return data.split("\n") - elif proc: - raise PipFailed(proc.stderr) - else: - raise PipFailed("pip timed out") - else: - raise PipFailed("Could not locate Python executable on this system") + try: + proc = utils.run_interruptable_subprocess(call_args) + except subprocess.CalledProcessError as exception: + raise PipFailed("pip timed out") from exception + + if proc.returncode != 0: + raise PipFailed(proc.stderr) + + data = proc.stdout + return data.split("\n") def parse_pip_list_output(all_packages, outdated_packages) -> Dict[str, Dict[str, str]]: @@ -210,12 +222,9 @@ class PythonPackageManager: optional: bool def __init__(self, addons): - ui_file = QtCore.QFile( + self.dlg = loadUi( os.path.join(os.path.dirname(__file__), "PythonDependencyUpdateDialog.ui") ) - ui_file.open(QtCore.QFile.OpenModeFlag.ReadOnly) - loader = QUiLoader() - self.dlg = loader.load(ui_file) self.addons = addons self.vendor_path = utils.get_pip_target_directory() diff --git a/src/Mod/AddonManager/addonmanager_readme_controller.py b/src/Mod/AddonManager/addonmanager_readme_controller.py index 7507db4afd..d7b1624a9f 100644 --- a/src/Mod/AddonManager/addonmanager_readme_controller.py +++ b/src/Mod/AddonManager/addonmanager_readme_controller.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" A Qt Widget for displaying Addon README information """ +"""A Qt Widget for displaying Addon README information""" import FreeCAD from Addon import Addon diff --git a/src/Mod/AddonManager/addonmanager_uninstaller.py b/src/Mod/AddonManager/addonmanager_uninstaller.py index bf709f9172..448031e890 100644 --- a/src/Mod/AddonManager/addonmanager_uninstaller.py +++ b/src/Mod/AddonManager/addonmanager_uninstaller.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Contains the classes to manage Addon removal: intended as a stable API, safe for +"""Contains the classes to manage Addon removal: intended as a stable API, safe for external code to call and to rely upon existing. See classes AddonUninstaller and MacroUninstaller for details.""" import json diff --git a/src/Mod/AddonManager/addonmanager_utilities.py b/src/Mod/AddonManager/addonmanager_utilities.py index b0e66ca00b..1e7b0296b8 100644 --- a/src/Mod/AddonManager/addonmanager_utilities.py +++ b/src/Mod/AddonManager/addonmanager_utilities.py @@ -22,21 +22,20 @@ # * * # *************************************************************************** -""" Utilities to work across different platforms, providers and python versions """ +"""Utilities to work across different platforms, providers and python versions""" + +# pylint: disable=deprecated-module, ungrouped-imports from datetime import datetime -from typing import Optional, Any -import ctypes +from typing import Optional, Any, List import os import platform -import re import shutil import stat import subprocess import time import re import ctypes -from typing import Optional, Any from urllib.parse import urlparse @@ -50,20 +49,67 @@ except ImportError: import addonmanager_freecad_interface as fci +try: + from freecad.utils import get_python_exe +except ImportError: + + def get_python_exe(): + """Use shutil.which to find python executable""" + return shutil.which("python") + + if fci.FreeCADGui: # If the GUI is up, we can use the NetworkManager to handle our downloads. If there is no event # loop running this is not possible, so fall back to requests (if available), or the native # Python urllib.request (if requests is not available). import NetworkManager # Requires an event loop, so is only available with the GUI + + requests = None + ssl = None + urllib = None else: + NetworkManager = None try: import requests + + ssl = None + urllib = None except ImportError: requests = None import urllib.request import ssl +if fci.FreeCADGui: + loadUi = fci.loadUi +else: + has_loader = False + try: + from PySide6.QtUiTools import QUiLoader + + has_loader = True + except ImportError: + try: + from PySide2.QtUiTools import QUiLoader + + has_loader = True + except ImportError: + + def loadUi(ui_file: str): + """If there are no available versions of QtUiTools, then raise an error if this + method is used.""" + raise RuntimeError("Cannot use QUiLoader without PySide or FreeCAD") + + if has_loader: + + def loadUi(ui_file: str) -> QtWidgets.QWidget: + """Load a Qt UI from an on-disk file.""" + q_ui_file = QtCore.QFile(ui_file) + q_ui_file.open(QtCore.QFile.OpenModeFlag.ReadOnly) + loader = QUiLoader() + return loader.load(ui_file) + + # @package AddonManager_utilities # \ingroup ADDONMANAGER # \brief Utilities to work across different platforms, providers and python versions @@ -103,10 +149,13 @@ def symlink(source, link_name): def rmdir(path: str) -> bool: + """Remove a directory or symlink, even if it is read-only.""" try: if os.path.islink(path): os.unlink(path) # Remove symlink else: + # NOTE: the onerror argument was deprecated in Python 3.12, replaced by onexc -- replace + # when earlier versions are no longer supported. shutil.rmtree(path, onerror=remove_readonly) except (WindowsError, PermissionError, OSError): return False @@ -181,7 +230,7 @@ def get_zip_url(repo): def recognized_git_location(repo) -> bool: - """Returns whether this repo is based at a known git repo location: works with github, gitlab, + """Returns whether this repo is based at a known git repo location: works with GitHub, gitlab, framagit, and salsa.debian.org""" parsed_url = urlparse(repo.url) @@ -198,19 +247,20 @@ def construct_git_url(repo, filename): """Returns a direct download link to a file in an online Git repo""" parsed_url = urlparse(repo.url) + repo_url = repo.url[:-4] if repo.url.endswith(".git") else repo.url if parsed_url.netloc == "github.com": - return f"{repo.url}/raw/{repo.branch}/{filename}" + return f"{repo_url}/raw/{repo.branch}/{filename}" if parsed_url.netloc in ["gitlab.com", "framagit.org", "salsa.debian.org"]: - return f"{repo.url}/-/raw/{repo.branch}/{filename}" + return f"{repo_url}/-/raw/{repo.branch}/{filename}" if parsed_url.netloc in ["codeberg.org"]: - return f"{repo.url}/raw/branch/{repo.branch}/{filename}" + return f"{repo_url}/raw/branch/{repo.branch}/{filename}" fci.Console.PrintLog( "Debug: addonmanager_utilities.construct_git_url: Unknown git host:" + parsed_url.netloc + f" for file {filename}\n" ) # Assume it's some kind of local GitLab instance... - return f"{repo.url}/-/raw/{repo.branch}/{filename}" + return f"{repo_url}/-/raw/{repo.branch}/{filename}" def get_readme_url(repo): @@ -362,7 +412,7 @@ def is_float(element: Any) -> bool: def get_pip_target_directory(): - # Get the default location to install new pip packages + """Get the default location to install new pip packages""" major, minor, _ = platform.python_version_tuple() vendor_path = os.path.join( fci.DataPaths().mod_dir, "..", "AdditionalPythonPackages", f"py{major}{minor}" @@ -384,7 +434,12 @@ def blocking_get(url: str, method=None) -> bytes: succeeded, or an empty string if it failed, or returned no data. The method argument is provided mainly for testing purposes.""" p = b"" - if fci.FreeCADGui and method is None or method == "networkmanager": + if ( + fci.FreeCADGui + and method is None + or method == "networkmanager" + and NetworkManager is not None + ): NetworkManager.InitializeNetworkManager() p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url, 10000) # 10 second timeout if p: @@ -429,13 +484,13 @@ def run_interruptable_subprocess(args, timeout_secs: int = 10) -> subprocess.Com # one second timeout allows interrupting the run once per second stdout, stderr = p.communicate(timeout=1) return_code = p.returncode - except subprocess.TimeoutExpired: + except subprocess.TimeoutExpired as timeout_exception: if ( hasattr(QtCore, "QThread") and QtCore.QThread.currentThread().isInterruptionRequested() ): p.kill() - raise ProcessInterrupted() + raise ProcessInterrupted() from timeout_exception if time.time() - start_time >= timeout_secs: # The real timeout p.kill() stdout, stderr = p.communicate() @@ -448,9 +503,10 @@ def run_interruptable_subprocess(args, timeout_secs: int = 10) -> subprocess.Com def process_date_string_to_python_datetime(date_string: str) -> datetime: - """For modern macros the expected date format is ISO 8601, YYYY-MM-DD. For older macros this standard was not always - used, and various orderings and separators were used. This function tries to match the majority of those older - macros. Commonly-used separators are periods, slashes, and dashes.""" + """For modern macros the expected date format is ISO 8601, YYYY-MM-DD. For older macros this + standard was not always used, and various orderings and separators were used. This function + tries to match the majority of those older macros. Commonly-used separators are periods, + slashes, and dashes.""" def raise_error(bad_string: str, root_cause: Exception = None): raise ValueError( @@ -466,19 +522,19 @@ def process_date_string_to_python_datetime(date_string: str) -> datetime: # The earliest possible year an addon can be created or edited is 2001: if split_result[0] > 2000: return datetime(split_result[0], split_result[1], split_result[2]) - elif split_result[2] > 2000: - # Generally speaking it's not possible to distinguish between DD-MM and MM-DD, so try the first, and - # only if that fails try the second + if split_result[2] > 2000: + # Generally speaking it's not possible to distinguish between DD-MM and MM-DD, so try + # the first, and only if that fails try the second if split_result[1] <= 12: return datetime(split_result[2], split_result[1], split_result[0]) return datetime(split_result[2], split_result[0], split_result[1]) - else: - raise ValueError(f"Invalid year in date string '{date_string}'") + raise ValueError(f"Invalid year in date string '{date_string}'") except ValueError as exception: raise_error(date_string, exception) def get_main_am_window(): + """Find the Addon Manager's main window in the Qt widget hierarchy.""" windows = QtWidgets.QApplication.topLevelWidgets() for widget in windows: if widget.objectName() == "AddonManager_Main_Window": @@ -494,3 +550,20 @@ def get_main_am_window(): return widget.centralWidget() # Why is this code even getting called? return None + + +def create_pip_call(args: List[str]) -> List[str]: + """Choose the correct mechanism for calling pip on each platform. It currently supports + either `python -m pip` (most environments) or `freecad.pip` (Snap packages). Returns a list + of arguments suitable for passing directly to subprocess.Popen and related functions.""" + snap_package = os.getenv("SNAP_REVISION") + if snap_package: + call_args = ["freecad.pip", "--disable-pip-version-check"] + call_args.extend(args) + else: + python_exe = get_python_exe() + if not python_exe: + raise RuntimeError("Could not locate Python executable on this system") + call_args = [python_exe, "-m", "pip", "--disable-pip-version-check"] + call_args.extend(args) + return call_args diff --git a/src/Mod/AddonManager/addonmanager_workers_installation.py b/src/Mod/AddonManager/addonmanager_workers_installation.py index ff3e063ece..635b2650ab 100644 --- a/src/Mod/AddonManager/addonmanager_workers_installation.py +++ b/src/Mod/AddonManager/addonmanager_workers_installation.py @@ -22,7 +22,7 @@ # * * # *************************************************************************** -""" Worker thread classes for Addon Manager installation and removal """ +"""Worker thread classes for Addon Manager installation and removal""" # pylint: disable=c-extension-no-member,too-few-public-methods,too-many-instance-attributes diff --git a/src/Mod/AddonManager/addonmanager_workers_startup.py b/src/Mod/AddonManager/addonmanager_workers_startup.py index c84b226c6a..3b0bf82b10 100644 --- a/src/Mod/AddonManager/addonmanager_workers_startup.py +++ b/src/Mod/AddonManager/addonmanager_workers_startup.py @@ -22,7 +22,7 @@ # * * # *************************************************************************** -""" Worker thread classes for Addon Manager startup """ +"""Worker thread classes for Addon Manager startup""" import hashlib import json import os diff --git a/src/Mod/AddonManager/addonmanager_workers_utility.py b/src/Mod/AddonManager/addonmanager_workers_utility.py index 48b8d360bd..5c8aa1b538 100644 --- a/src/Mod/AddonManager/addonmanager_workers_utility.py +++ b/src/Mod/AddonManager/addonmanager_workers_utility.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Misc. worker thread classes for the FreeCAD Addon Manager. """ +"""Misc. worker thread classes for the FreeCAD Addon Manager.""" from typing import Optional diff --git a/src/Mod/AddonManager/change_branch.py b/src/Mod/AddonManager/change_branch.py index 3fb73358de..1880ab95be 100644 --- a/src/Mod/AddonManager/change_branch.py +++ b/src/Mod/AddonManager/change_branch.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: LGPL-2.1-or-later # *************************************************************************** # * * -# * Copyright (c) 2022-2023 FreeCAD Project Association * +# * Copyright (c) 2022-2025 The FreeCAD Project Association AISBL * # * * # * This file is part of FreeCAD. * # * * @@ -21,27 +21,38 @@ # * * # *************************************************************************** +"""The Change Branch dialog and utility classes and methods""" + import os +from typing import Dict -import FreeCAD -import FreeCADGui -from addonmanager_git import initialize_git +import addonmanager_freecad_interface as fci +import addonmanager_utilities as utils -from PySide import QtWidgets, QtCore +from addonmanager_git import initialize_git, GitFailed -translate = FreeCAD.Qt.translate +try: + from PySide import QtWidgets, QtCore +except ImportError: + try: + from PySide6 import QtWidgets, QtCore + except ImportError: + from PySide2 import QtWidgets, QtCore # pylint: disable=deprecated-module + +translate = fci.translate class ChangeBranchDialog(QtWidgets.QWidget): + """A dialog that displays available git branches and allows the user to select one to change + to. Includes code that does that change, as well as some modal dialogs to warn them of the + possible consequences and display various error messages.""" branch_changed = QtCore.Signal(str, str) def __init__(self, path: str, parent=None): super().__init__(parent) - self.ui = FreeCADGui.PySideUic.loadUi( - os.path.join(os.path.dirname(__file__), "change_branch.ui") - ) + self.ui = utils.loadUi(os.path.join(os.path.dirname(__file__), "change_branch.ui")) self.item_filter = ChangeBranchDialogFilter() self.ui.tableView.setModel(self.item_filter) @@ -54,6 +65,9 @@ class ChangeBranchDialog(QtWidgets.QWidget): # Figure out what row gets selected: git_manager = initialize_git() + if git_manager is None: + return + row = 0 self.current_ref = git_manager.current_branch(path) selection_model = self.ui.tableView.selectionModel() @@ -71,6 +85,9 @@ class ChangeBranchDialog(QtWidgets.QWidget): header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents) def exec(self): + """Run the Change Branch dialog and its various sub-dialogs. May result in the branch + being changed. Code that cares if that happens should connect to the branch_changed + signal.""" if self.ui.exec() == QtWidgets.QDialog.Accepted: selection = self.ui.tableView.selectedIndexes() @@ -111,17 +128,58 @@ class ChangeBranchDialog(QtWidgets.QWidget): if result == QtWidgets.QMessageBox.Cancel: return - gm = initialize_git() - remote_name = ref["ref_name"] - _, _, local_name = ref["ref_name"].rpartition("/") + self.change_branch(self.item_model.path, ref) + + def change_branch(self, path: str, ref: Dict[str, str]) -> None: + """Change the git clone in `path` to git ref `ref`. Emits the branch_changed signal + on success.""" + remote_name = ref["ref_name"] + _, _, local_name = ref["ref_name"].rpartition("/") + gm = initialize_git() + if gm is None: + self._show_no_git_dialog() + return + + try: if ref["upstream"]: - gm.checkout(self.item_model.path, remote_name) + gm.checkout(path, remote_name) else: - gm.checkout(self.item_model.path, remote_name, args=["-b", local_name]) + gm.checkout(path, remote_name, args=["-b", local_name]) self.branch_changed.emit(self.current_ref, local_name) + except GitFailed: + self._show_git_failed_dialog() + + def _show_no_git_dialog(self): + QtWidgets.QMessageBox.critical( + self, + translate("AddonsInstaller", "Cannot find git"), + translate( + "AddonsInstaller", + "Could not find git executable: cannot change branch", + ), + QtWidgets.QMessageBox.Ok, + QtWidgets.QMessageBox.Ok, + ) + + def _show_git_failed_dialog(self): + QtWidgets.QMessageBox.critical( + self, + translate("AddonsInstaller", "git operation failed"), + translate( + "AddonsInstaller", + "Git returned an error code when attempting to change branch. There may be " + "more details in the Report View.", + ), + QtWidgets.QMessageBox.Ok, + QtWidgets.QMessageBox.Ok, + ) class ChangeBranchDialogModel(QtCore.QAbstractTableModel): + """The data for the dialog comes from git: this model handles the git interactions and + returns branch information as its rows. Use user data in the RefAccessRole to get information + about the git refs. RefAccessRole data is a dictionary defined by the GitManager class as the + results of a `get_branches_with_info()` call.""" branches = [] DataSortRole = QtCore.Qt.UserRole @@ -138,54 +196,61 @@ class ChangeBranchDialogModel(QtCore.QAbstractTableModel): self._remove_tracking_duplicates() def rowCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int: + """Returns the number of rows in the model, e.g. the number of branches.""" if parent.isValid(): return 0 return len(self.branches) def columnCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int: + """Returns the number of columns in the model, e.g. the number of entries in the git ref + structure (currently 3, 'ref_name', 'upstream', and 'date').""" if parent.isValid(): return 0 return 3 # Local name, remote name, date def data(self, index: QtCore.QModelIndex, role: int = QtCore.Qt.DisplayRole): + """The data access method for this model. Supports four roles: ToolTipRole, DisplayRole, + DataSortRole, and RefAccessRole.""" if not index.isValid(): return None row = index.row() column = index.column() if role == QtCore.Qt.ToolTipRole: - tooltip = self.branches[row]["author"] + ": " + self.branches[row]["subject"] - return tooltip - elif role == QtCore.Qt.DisplayRole: - dd = self.branches[row] - if column == 2: - if dd["date"] is not None: - q_date = QtCore.QDateTime.fromString( - dd["date"], QtCore.Qt.DateFormat.RFC2822Date - ) - return QtCore.QLocale().toString(q_date, QtCore.QLocale.ShortFormat) - return None - elif column == 0: - return dd["ref_name"] - elif column == 1: - return dd["upstream"] - else: - return None - elif role == ChangeBranchDialogModel.DataSortRole: - if column == 2: - if self.branches[row]["date"] is not None: - q_date = QtCore.QDateTime.fromString( - self.branches[row]["date"], QtCore.Qt.DateFormat.RFC2822Date - ) - return q_date - return None - elif column == 0: - return self.branches[row]["ref_name"] - elif column == 1: - return self.branches[row]["upstream"] - else: - return None - elif role == ChangeBranchDialogModel.RefAccessRole: + return self.branches[row]["author"] + ": " + self.branches[row]["subject"] + if role == QtCore.Qt.DisplayRole: + return self._data_display_role(column, row) + if role == ChangeBranchDialogModel.DataSortRole: + return self._data_sort_role(column, row) + if role == ChangeBranchDialogModel.RefAccessRole: return self.branches[row] + return None + + def _data_display_role(self, column, row): + dd = self.branches[row] + if column == 2: + if dd["date"] is not None: + q_date = QtCore.QDateTime.fromString(dd["date"], QtCore.Qt.DateFormat.RFC2822Date) + return QtCore.QLocale().toString(q_date, QtCore.QLocale.ShortFormat) + return None + if column == 0: + return dd["ref_name"] + if column == 1: + return dd["upstream"] + return None + + def _data_sort_role(self, column, row): + if column == 2: + if self.branches[row]["date"] is not None: + q_date = QtCore.QDateTime.fromString( + self.branches[row]["date"], QtCore.Qt.DateFormat.RFC2822Date + ) + return q_date + return None + if column == 0: + return self.branches[row]["ref_name"] + if column == 1: + return self.branches[row]["upstream"] + return None def headerData( self, @@ -193,6 +258,7 @@ class ChangeBranchDialogModel(QtCore.QAbstractTableModel): orientation: QtCore.Qt.Orientation, role: int = QtCore.Qt.DisplayRole, ): + """Returns the header information for the data in this model.""" if orientation == QtCore.Qt.Vertical: return None if role != QtCore.Qt.DisplayRole: @@ -209,14 +275,13 @@ class ChangeBranchDialogModel(QtCore.QAbstractTableModel): "Remote tracking", "Table header for git remote tracking branch name", ) - elif section == 2: + if section == 2: return translate( "AddonsInstaller", "Last Updated", "Table header for git update date", ) - else: - return None + return None def _remove_tracking_duplicates(self): remote_tracking_branches = [] @@ -234,12 +299,12 @@ class ChangeBranchDialogModel(QtCore.QAbstractTableModel): class ChangeBranchDialogFilter(QtCore.QSortFilterProxyModel): + """Uses the DataSortRole in the model to provide a comparison method to sort the data.""" + def lessThan(self, left: QtCore.QModelIndex, right: QtCore.QModelIndex): - leftData = self.sourceModel().data(left, ChangeBranchDialogModel.DataSortRole) - rightData = self.sourceModel().data(right, ChangeBranchDialogModel.DataSortRole) - if leftData is None or rightData is None: - if rightData is not None: - return True - else: - return False - return leftData < rightData + """Compare two git refs according to the DataSortRole in the model.""" + left_data = self.sourceModel().data(left, ChangeBranchDialogModel.DataSortRole) + right_data = self.sourceModel().data(right, ChangeBranchDialogModel.DataSortRole) + if left_data is None or right_data is None: + return right_data is not None + return left_data < right_data diff --git a/src/Mod/AddonManager/composite_view.py b/src/Mod/AddonManager/composite_view.py index d9c429d5df..c20a724225 100644 --- a/src/Mod/AddonManager/composite_view.py +++ b/src/Mod/AddonManager/composite_view.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Provides a class for showing the list view and detail view at the same time. """ +"""Provides a class for showing the list view and detail view at the same time.""" import base64 diff --git a/src/Mod/AddonManager/install_to_toolbar.py b/src/Mod/AddonManager/install_to_toolbar.py index c40af1bf39..9f3ba038b8 100644 --- a/src/Mod/AddonManager/install_to_toolbar.py +++ b/src/Mod/AddonManager/install_to_toolbar.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" A collection of functions to handle installing a macro icon to the toolbar. """ +"""A collection of functions to handle installing a macro icon to the toolbar.""" import os diff --git a/src/Mod/AddonManager/package_list.py b/src/Mod/AddonManager/package_list.py index 921337af50..b4590b776f 100644 --- a/src/Mod/AddonManager/package_list.py +++ b/src/Mod/AddonManager/package_list.py @@ -21,7 +21,7 @@ # * * # *************************************************************************** -""" Defines the PackageList QWidget for displaying a list of Addons. """ +"""Defines the PackageList QWidget for displaying a list of Addons.""" import datetime import threading diff --git a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp index e3b78445b2..b9a59e29a0 100644 --- a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp +++ b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp @@ -160,10 +160,7 @@ bool ViewProviderAssembly::doubleClicked() bool ViewProviderAssembly::canDragObject(App::DocumentObject* obj) const { // The user should not be able to drag the joint group out of the assembly - if (!obj || obj->getTypeId() == Assembly::JointGroup::getClassTypeId()) { - return false; - } - return true; + return obj && !obj->is(); } bool ViewProviderAssembly::canDragObjectToTarget(App::DocumentObject* obj, @@ -1028,9 +1025,8 @@ bool ViewProviderAssembly::onDelete(const std::vector& subNames) { // Delete the assembly groups when assembly is deleted for (auto obj : getObject()->getOutList()) { - if (obj->getTypeId() == Assembly::JointGroup::getClassTypeId() - || obj->getTypeId() == Assembly::ViewGroup::getClassTypeId() - || obj->getTypeId() == Assembly::BomGroup::getClassTypeId()) { + if (obj->is() || obj->is() + || obj->is()) { // Delete the group content first. Gui::Command::doCommand(Gui::Command::Doc, diff --git a/src/Mod/Assembly/Gui/ViewProviderAssembly.h b/src/Mod/Assembly/Gui/ViewProviderAssembly.h index 4db69e76be..fc7defe8e2 100644 --- a/src/Mod/Assembly/Gui/ViewProviderAssembly.h +++ b/src/Mod/Assembly/Gui/ViewProviderAssembly.h @@ -28,7 +28,7 @@ #include -#include +#include #include class SoSwitch; diff --git a/src/Mod/BIM/ArchBuildingPart.py b/src/Mod/BIM/ArchBuildingPart.py index 421f7355c6..14f340e1fa 100644 --- a/src/Mod/BIM/ArchBuildingPart.py +++ b/src/Mod/BIM/ArchBuildingPart.py @@ -427,11 +427,12 @@ class ViewProviderBuildingPart: def __init__(self,vobj): - vobj.addExtension("Gui::ViewProviderGroupExtensionPython") - #vobj.addExtension("Gui::ViewProviderGeoFeatureGroupExtensionPython") - vobj.Proxy = self - self.setProperties(vobj) - vobj.ShapeColor = ArchCommands.getDefaultColor("Helpers") + if vobj: + vobj.addExtension("Gui::ViewProviderGroupExtensionPython") + vobj.Proxy = self + self.setProperties(vobj) + vobj.ShapeColor = ArchCommands.getDefaultColor("Helpers") + self.Object = vobj.Object def setProperties(self,vobj): @@ -533,6 +534,9 @@ class ViewProviderBuildingPart: return ":/icons/Arch_Building_Tree.svg" elif self.Object.IfcType == "Annotation": return ":/icons/BIM_ArchView.svg" + elif hasattr(self.Object,"IfcClass"): + from nativeifc import ifc_viewproviders + return ifc_viewproviders.get_icon(self) return ":/icons/Arch_BuildingPart_Tree.svg" def attach(self,vobj): @@ -662,7 +666,10 @@ class ViewProviderBuildingPart: self.lco.point.setValues([[-fs,0,0],[fs,0,0],[0,-fs,0],[0,fs,0],[0,0,-fs],[0,0,fs]]) elif prop in ["OverrideUnit","ShowUnit","ShowLevel","ShowLabel"]: if hasattr(vobj,"OverrideUnit") and hasattr(vobj,"ShowUnit") and hasattr(vobj,"ShowLevel") and hasattr(vobj,"ShowLabel") and hasattr(self,"txt"): - z = vobj.Object.Placement.Base.z + vobj.Object.LevelOffset.Value + offset = getattr(vobj.Object, "LevelOffset", 0) + if hasattr(offset, "Value"): + offset = offset.Value + z = vobj.Object.Placement.Base.z + offset q = FreeCAD.Units.Quantity(z,FreeCAD.Units.Length) txt = "" if vobj.ShowLabel: @@ -730,7 +737,7 @@ class ViewProviderBuildingPart: self.clip.plane.setValue(plane) sg.insertChild(self.clip,0) else: - if self.clip: + if getattr(self,"clip",None): sg.removeChild(self.clip) self.clip = None for o in Draft.get_group_contents(vobj.Object.Group, diff --git a/src/Mod/BIM/ArchPanel.py b/src/Mod/BIM/ArchPanel.py index 1953753467..d2b7f60f42 100644 --- a/src/Mod/BIM/ArchPanel.py +++ b/src/Mod/BIM/ArchPanel.py @@ -115,8 +115,6 @@ class _Panel(ArchComponent.Component): if self.clone(obj): return - if not self.ensureBase(obj): - return layers = [] length = 0 diff --git a/src/Mod/BIM/ArchPipe.py b/src/Mod/BIM/ArchPipe.py index 5a5ceb0e94..0d3f67d9a7 100644 --- a/src/Mod/BIM/ArchPipe.py +++ b/src/Mod/BIM/ArchPipe.py @@ -303,8 +303,6 @@ class _ArchPipeConnector(ArchComponent.Component): if self.clone(obj): return - if not self.ensureBase(obj): - return tol = 1 # tolerance for alignment. This is only visual, we can keep it low... ptol = 0.001 # tolerance for coincident points diff --git a/src/Mod/BIM/ArchSchedule.py b/src/Mod/BIM/ArchSchedule.py index b1c5ee671a..6cf4e8384d 100644 --- a/src/Mod/BIM/ArchSchedule.py +++ b/src/Mod/BIM/ArchSchedule.py @@ -271,7 +271,10 @@ class _ArchSchedule: if objs[0].isDerivedFrom("App::DocumentObjectGroup"): objs = objs[0].Group objs = Draft.get_group_contents(objs) - objs = Arch.pruneIncluded(objs,strict=True,silent=True) + objs = self.expandArrays(objs) + # Remove included objects (e.g. walls that are part of another wall, + # base geometry, etc) + objs = Arch.pruneIncluded(objs, strict=True, silent=True) # Remove all schedules and spreadsheets: objs = [o for o in objs if Draft.get_type(o) not in ["Schedule", "Spreadsheet::Sheet"]] @@ -580,6 +583,51 @@ class _ArchSchedule: if state: self.Type = state + def getIfcClass(self, obj): + """gets the IFC class of this object""" + + if hasattr(obj, "IfcType"): + return obj.IfcType + elif hasattr(obj, "IfcRole"): + return obj.IfcRole + elif hasattr(obj, "IfcClass"): + return obj.IfcClass + else: + return None + + def getArray(self, obj): + "returns a count number if this object needs to be duplicated" + + import Draft + + elementCount = 0 + + # The given object can belong to multiple arrays + # o is a potential parent array of the given object + for o in obj.InList: + if Draft.getType(o) == "Array": + elementCount += o.Count + + return elementCount + + def expandArrays(self, objs): + """Expands array elements in the given list of objects""" + + expandedobjs = [] + + for obj in objs: + ifcClass = self.getIfcClass(obj) + # This filters out the array object itself, which has no IFC class, + # but leaves the array elements, which do have an IFC class. + if ifcClass: + expandedobjs.append(obj) + # If the object is in an array, add it and the rest of its elements + # to the list. + array = self.getArray(obj) + for i in range(1, array): # The first element (0) was already added + expandedobjs.append(obj) + + return expandedobjs class _ViewProviderArchSchedule: diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index 14b3319312..c839b3e9ca 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -547,6 +547,8 @@ class _Wall(ArchComponent.Component): for e in self.connectEdges: l += e.Length l = l / 2 + if self.layersNum: + l = l / self.layersNum if obj.Length.Value != l: obj.Length = l self.oldLength = None # delete the stored value to prevent triggering base change below @@ -986,6 +988,9 @@ class _Wall(ArchComponent.Component): if self.basewires: if (len(self.basewires) == 1) and layers: self.basewires = [self.basewires[0] for l in layers] + self.layersNum = len(layers) + else: + self.layersNum = 0 layeroffset = 0 baseface = None self.connectEdges = [] diff --git a/src/Mod/BIM/Resources/ui/dialogClassification.ui b/src/Mod/BIM/Resources/ui/dialogClassification.ui index 58c858321a..511042cf16 100644 --- a/src/Mod/BIM/Resources/ui/dialogClassification.ui +++ b/src/Mod/BIM/Resources/ui/dialogClassification.ui @@ -1,7 +1,7 @@ Dialog - + 0 diff --git a/src/Mod/BIM/Resources/ui/dialogProjectManager.ui b/src/Mod/BIM/Resources/ui/dialogProjectManager.ui index bc6111c044..ccbb337bc7 100644 --- a/src/Mod/BIM/Resources/ui/dialogProjectManager.ui +++ b/src/Mod/BIM/Resources/ui/dialogProjectManager.ui @@ -6,8 +6,8 @@ 0 0 - 402 - 470 + 443 + 840 @@ -17,7 +17,7 @@ - This screen allows you to configure a new BIM project in FreeCAD. + This screen allows you to create and configure a new BIM project in FreeCAD. true @@ -25,43 +25,42 @@ - + - - Use preset... - - - - - - - - + + + + 0 + 0 + + - Saves the current document as a template, including all the current BIM settings - - - Save template... - - - - - + Fill this dialog with preset values + + + Use preset... + + - + + + + 0 + 0 + + - Loads the contents of a FCStd file into the active document, applying all the BIM settings stored in it if any + The settings below can be saved as a preset. Presets are stored as .txt files in your FreeCAD user folder - Load template... + Save preset - - - + + ../../../../../../../.designer/backup../../../../../../../.designer/backup @@ -76,58 +75,108 @@ 0 - 0 - 369 - 1214 + -1041 + 428 + 1740 - + + + Create a new BIM project + - Create new document + Create a new BIM project true - false + true - - - + + + - Project name + A new BIM project will be created, either as a new FreeCAD document or as a Native IFC project + + + true - - - - Unnamed - - + + + + + + This will create a new FreeCAD docment that allows you to build a BIM model, but with no specific IFC structure yet. This is the most flexible option when you start working ona BIM project. You can convert this project to IFC anytime later. + + + Create a new document witout IFC support yet + + + false + + + + + + + This will create an IFC project. All the BIM objects you will add to that IFC project will immediately become IFC objects. This is less flexible, but allows you to stick more strictly to the IFC standard. + + + Create a Native IFC project in the current dopcument + + + true + + + + + + + The new IFC project will be created as a new FreeCAD document. In that mode, the IFC project is the FreeCAD document, anything you create in that document becomes part of the IFC project. This is extremely restrictive as no non-IFC object can be added to the document. + + + Create a locked Native IFC project as a new document + + + + + + + + + + + Project name + + + + + + + A name for this BIM or IFC project + + + Unnamed + + + + - - - - If this is checked, a human figure will be added, which helps greatly to give a sense of scale when viewing the model - - - Add a human figure - - - true - - - + + Create a new site + - Create Site + Create site false @@ -150,17 +199,20 @@ + + The East longitude of this site + E 4 + + -180.000000000000000 + - 180.0 - - - -180.0 + 180.000000000000000 @@ -180,6 +232,9 @@ + + A name for this site + Default Site @@ -194,6 +249,9 @@ + + The difference between the up direction of this site and the true North direction + ° @@ -211,13 +269,20 @@ + + The elevation of this site + - + + + The physical (postal) address of this site + + @@ -235,17 +300,20 @@ + + The North latitude of this site + N 4 - - 90.0 - - -90.0 + -90.000000000000000 + + + 90.000000000000000 @@ -256,8 +324,11 @@ + + Create a new building + - Create Building + Create building true @@ -332,6 +403,9 @@ 16777215 + + The main use of this building + QComboBox::AdjustToMinimumContentsLength @@ -352,6 +426,9 @@ + + Number of vertical axes + 0 @@ -366,6 +443,9 @@ + + Number of horizontal axes + 0 @@ -373,8 +453,11 @@ + + An estimate building width. Keep 0 if you don't want to specify this now + - 0 + 0 @@ -383,6 +466,9 @@ + + The line width of axes + 2 @@ -390,8 +476,11 @@ + + Distance between vertical axes + - 0 + 0 @@ -400,8 +489,11 @@ + + An estimate building length. Keep 0 if you don't want to specify this now + - 0 + 0 @@ -410,6 +502,9 @@ + + Distance between horizontal axes + 0 @@ -427,6 +522,9 @@ + + The color of axes + 33 @@ -448,16 +546,54 @@
+ + + + Add a human figure to the document + + + Add a human figure + + + true + + + + + + A human figure will be added to the document, which helps giving a sense of scale + + + true + + + + + + Levels + + + + BIM projects are typically organized into levels, that represents the different storeys of a building. Although it is not mandatory to work with levels in FreeCAD, you can set up default levels here + + + true + + + + + The number of levels to create + 1 @@ -475,6 +611,9 @@ + + The vertical distance between each level + 0 @@ -492,29 +631,21 @@ - - - - Bind levels to vertical axes - - - - - - - Define a working plane for each level - - - - Default groups to be added to each level + Default groups to be added to each level. Defautl groups such as walls, windows,... are useful to organize the different building elements inside a level + + + true + + A list of grouls to add under each level + true @@ -530,25 +661,29 @@ + + Add a new group + Add - - + ../../../../../../../.designer/backup../../../../../../../.designer/backup + + Delete a selected group + Del - - + ../../../../../../../.designer/backup../../../../../../../.designer/backup @@ -561,30 +696,8 @@ - - - - The above settings can be saved as a preset. Presets are stored as .txt files in your FreeCAD user folder - - - true - - - - - - - Save preset - - - - - - - - @@ -600,25 +713,29 @@ + + Accept the values fo this form + OK - - + ../../../../../../../.designer/backup../../../../../../../.designer/backup + + Cancel + Cancel - - + ../../../../../../../.designer/backup../../../../../../../.designer/backup @@ -638,43 +755,6 @@
Gui/Widgets.h
- - presets - buttonSaveTemplate - buttonLoadTemplate - scrollArea - groupNewDocument - projectName - addHumanFigure - groupSite - siteName - siteAddress - siteLatitude - siteLongitude - siteDeviation - siteElevation - groupBuilding - buildingName - buildingUse - buildingLength - buildingWidth - countVAxes - distVAxes - countHAxes - distHAxes - lineWidth - lineColor - countLevels - levelHeight - levelsAxis - levelsWP - groupsList - buttonAdd - buttonDel - buttonSave - buttonOK - buttonCancel - diff --git a/src/Mod/BIM/Resources/ui/preferences-sh3d-import.ui b/src/Mod/BIM/Resources/ui/preferences-sh3d-import.ui index d916e0bde7..14a6d5efa5 100644 --- a/src/Mod/BIM/Resources/ui/preferences-sh3d-import.ui +++ b/src/Mod/BIM/Resources/ui/preferences-sh3d-import.ui @@ -37,6 +37,9 @@ Mod/Arch + + true +
@@ -96,6 +99,9 @@ Mod/Arch + + true + @@ -112,6 +118,9 @@ Mod/Arch + + true + @@ -261,9 +270,9 @@ - 255 - 255 - 255 + 246 + 246 + 246 @@ -306,6 +315,9 @@ Mod/Arch + + true + @@ -388,6 +400,25 @@ + + + + Create Facebinders, Baseboards for walls, floors and ceilings for Rooms + + + Decorate surfaces + + + sh3dDecorateSurfaces + + + Mod/Arch + + + true + + + diff --git a/src/Mod/BIM/bimcommands/BimClassification.py b/src/Mod/BIM/bimcommands/BimClassification.py index 490d298888..6038f3ba9b 100644 --- a/src/Mod/BIM/bimcommands/BimClassification.py +++ b/src/Mod/BIM/bimcommands/BimClassification.py @@ -29,6 +29,7 @@ import os QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP translate = FreeCAD.Qt.translate +PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") class BIM_Classification: @@ -63,11 +64,15 @@ class BIM_Classification: # load the form and set the tree model up self.form = FreeCADGui.PySideUic.loadUi(":/ui/dialogClassification.ui") self.form.setWindowIcon(QtGui.QIcon(":/icons/BIM_Classification.svg")) + self.form.groupMode.setItemIcon(0, QtGui.QIcon(":/icons/Arch_SectionPlane_Tree.svg")) # Alphabetical + self.form.groupMode.setItemIcon(1, QtGui.QIcon(":/icons/IFC.svg")) # Type + self.form.groupMode.setItemIcon(2, QtGui.QIcon(":/icons/Arch_Material.svg")) # Material + self.form.groupMode.setItemIcon(3, QtGui.QIcon(":/icons/Document.svg")) # Model structure # restore saved values - p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") - w = p.GetInt("BimClassificationDialogWidth", 629) - h = p.GetInt("BimClassificationDialogHeight", 516) + self.form.onlyVisible.setChecked(PARAMS.GetInt("BimClassificationVisibleState", 0)) + w = PARAMS.GetInt("BimClassificationDialogWidth", 629) + h = PARAMS.GetInt("BimClassificationDialogHeight", 516) self.form.resize(w, h) # add modified search box from bimmaterial @@ -151,6 +156,7 @@ class BIM_Classification: self.form.treeClass.itemDoubleClicked.connect(self.apply) self.form.search.up.connect(self.onUpArrow) self.form.search.down.connect(self.onDownArrow) + self.form.onlyVisible.stateChanged.connect(self.onVisible) # center the dialog over FreeCAD window mw = FreeCADGui.getMainWindow() @@ -650,6 +656,10 @@ class BIM_Classification: if self.form.treeClass.itemBelow(i): self.form.treeClass.setCurrentItem(self.form.treeClass.itemBelow(i)) + def onVisible(self, index): + PARAMS.SetInt("BimClassificationVisibleState", index) + self.updateObjects() + def getIcon(self,obj): """returns a QIcon for an object""" diff --git a/src/Mod/BIM/bimcommands/BimIfcQuantities.py b/src/Mod/BIM/bimcommands/BimIfcQuantities.py index d36850be03..f1ea3d0b19 100644 --- a/src/Mod/BIM/bimcommands/BimIfcQuantities.py +++ b/src/Mod/BIM/bimcommands/BimIfcQuantities.py @@ -318,7 +318,7 @@ class BIM_IfcQuantities: return txt def get_row(self, name): - """Returns the row number correspinding to the given object name""" + """Returns the row number corresponding to the given object name""" for i in range(self.qmodel.rowCount()): if self.qmodel.item(i).toolTip().split(" ")[0] == name: diff --git a/src/Mod/BIM/bimcommands/BimProjectManager.py b/src/Mod/BIM/bimcommands/BimProjectManager.py index 24fc94c299..3c33f44b7a 100644 --- a/src/Mod/BIM/bimcommands/BimProjectManager.py +++ b/src/Mod/BIM/bimcommands/BimProjectManager.py @@ -25,6 +25,7 @@ import os import sys +import math import FreeCAD import FreeCADGui @@ -33,22 +34,27 @@ translate = FreeCAD.Qt.translate class BIM_ProjectManager: + def GetResources(self): + return { "Pixmap": "BIM_ProjectManager", - "MenuText": QT_TRANSLATE_NOOP("BIM_ProjectManager", "Manage project..."), + "MenuText": QT_TRANSLATE_NOOP("BIM_ProjectManager", "Setup project..."), "ToolTip": QT_TRANSLATE_NOOP( - "BIM_ProjectManager", "Setup your BIM project" + "BIM_ProjectManager", "Create or manage a BIM project" ), } def Activated(self): - import FreeCADGui - # load dialog + import FreeCADGui + import ArchBuildingPart from PySide import QtCore, QtGui self.form = FreeCADGui.PySideUic.loadUi(":/ui/dialogProjectManager.ui") + self.project = None + self.site = None + self.building = None # center the dialog over FreeCAD window mw = FreeCADGui.getMainWindow() @@ -59,75 +65,130 @@ class BIM_ProjectManager: ) # set things up - import ArchBuildingPart - self.form.buildingUse.addItems(ArchBuildingPart.BuildingTypes) self.form.setWindowIcon(QtGui.QIcon(":/icons/BIM_ProjectManager.svg")) - QtCore.QObject.connect( - self.form.buttonAdd, QtCore.SIGNAL("clicked()"), self.addGroup - ) - QtCore.QObject.connect( - self.form.buttonDel, QtCore.SIGNAL("clicked()"), self.delGroup - ) - QtCore.QObject.connect( - self.form.buttonSave, QtCore.SIGNAL("clicked()"), self.savePreset - ) - QtCore.QObject.connect( - self.form.presets, - QtCore.SIGNAL("currentIndexChanged(QString)"), - self.getPreset, - ) - QtCore.QObject.connect( - self.form.buttonOK, QtCore.SIGNAL("clicked()"), self.accept - ) - QtCore.QObject.connect( - self.form.buttonCancel, QtCore.SIGNAL("clicked()"), self.reject - ) - QtCore.QObject.connect( - self.form.buttonSaveTemplate, QtCore.SIGNAL("clicked()"), self.saveTemplate - ) - QtCore.QObject.connect( - self.form.buttonLoadTemplate, QtCore.SIGNAL("clicked()"), self.loadTemplate - ) + self.form.buttonAdd.clicked.connect(self.addGroup) + self.form.buttonDel.clicked.connect(self.delGroup) + self.form.buttonSave.clicked.connect(self.savePreset) + self.form.presets.currentIndexChanged.connect(self.getPreset) + self.form.buttonOK.clicked.connect(self.accept) + self.form.buttonCancel.clicked.connect(self.reject) self.fillPresets() + # Detect existing objects + sel = FreeCADGui.Selection.getSelection() + doc = FreeCAD.ActiveDocument + if doc: + if len(sel) == 1: + if hasattr(sel[0], "Proxy") and hasattr(sel[0].Proxy, "ifcfile"): + # case 1: a project is selected + self.project = sel[0] + self.form.groupNewProject.setEnabled(False) + if hasattr(doc, "Proxy"): + # case 2: the actuve document is a project + if hasattr(doc.Proxy, "ifcfile"): + self.project = doc + self.form.groupNewProject.setEnabled(False) + if self.project: + from nativeifc import ifc_tools + sites = ifc_tools.get_children(self.project, ifctype="IfcSite") + sites = list(filter(None, [ifc_tools.get_object(s) for s in sites])) + self.form.projectName.setText(self.project.Label) + else: + sites = [o for o in doc.Objects if getattr(o, "IfcType", "") == "Site"] + if sites: + self.site = sites[0] + self.form.siteName.setText(self.site.Label) + if hasattr(self.site,"Address"): + self.form.siteAddress.setText(self.site.Address) + elif hasattr(self.site,"SiteAddress"): + self.form.siteAddress.setText(self.site.SiteAddress) + if hasattr(self.site,"Longitude"): + self.form.siteLongitude.setValue(self.site.Longitude) + elif hasattr(self.site,"RefLongitude"): + self.form.siteLongitude.setValue(self.site.RefLongitude) + if hasattr(self.site,"Latitude"): + self.form.siteLatitude.setValue(self.site.Latitude) + elif hasattr(self.site,"RefLatitude"): + self.form.siteLatitude.setValue(self.site.RefLatitude) + if hasattr(self.site,"Elevation"): + self.form.siteElevation.setText(self.site.Elevation.UserString) + elif hasattr(self.site,"RefElevation"): + self.form.siteElevation.setText(self.site.RefElevation.UserString) + if hasattr(self.site, "Declination"): + self.form.siteElevation.setText(str(self.site.Declination)) + buildings = [] + if self.site and self.project: + from nativeifc import ifc_tools + buildings = ifc_tools.get_children(self.site, ifctype="IfcBuilding") + buildings = list(filter(None, [ifc_tools.get_object(b) for b in buildings])) + if not buildings: + buildings = [o for o in doc.Objects if getattr(o, "IfcType", "") == "Building"] + if buildings: + self.building = buildings[0] + self.form.buildingName.setText(self.building.Label) + levels = ifc_tools.get_children(self.building, ifctype="IfcBuildingStorey") + if levels: + self.form.countLevels.setValue(len(levels)) + # show dialog self.form.show() def reject(self): + self.form.hide() return True def accept(self): + import Arch import Draft import FreeCADGui import Part - if self.form.groupNewDocument.isChecked() or (FreeCAD.ActiveDocument is None): - doc = FreeCAD.newDocument() - if self.form.projectName.text(): - doc.Label = self.form.projectName.text() - FreeCAD.ActiveDocument = doc - if not FreeCAD.ActiveDocument: - FreeCAD.Console.PrintError( - translate("BIM", "No active document, aborting.") + "\n" - ) - site = None + vaxes = [] + haxes = [] outline = None - if self.form.groupSite.isChecked(): - site = Arch.makeSite() - site.Label = self.form.siteName.text() - site.Address = self.form.siteAddress.text() - site.Longitude = self.form.siteLongitude.value() - site.Latitude = self.form.siteLatitude.value() - if hasattr(site, "NorthDeviation"): - site.NorthDeviation = self.form.siteDeviation.value() - elif hasattr(site, "Declination"): - site.Declination = self.form.siteDeviation.value() - site.Elevation = FreeCAD.Units.Quantity( - self.form.siteElevation.text() - ).Value + outtext = None + human = None + grp = None + + if self.form.groupNewProject.isChecked(): + self.project = None + self.site = None + self.building = None + + # reading form values + buildingWidth = FreeCAD.Units.Quantity(self.form.buildingWidth.text()).Value + buildingLength = FreeCAD.Units.Quantity(self.form.buildingLength.text()).Value + distVAxes = FreeCAD.Units.Quantity(self.form.distVAxes.text()).Value + distHAxes = FreeCAD.Units.Quantity(self.form.distHAxes.text()).Value + levelHeight = FreeCAD.Units.Quantity(self.form.levelHeight.text()).Value + color = self.form.lineColor.property("color").getRgbF()[:3] + + # Document creation + doc = FreeCAD.ActiveDocument + if self.form.groupNewProject.isChecked(): + if self.form.radioNative1.isChecked() or \ + self.form.radioNative3.isChecked() or \ + (self.form.radioNative2.isChecked() and doc is None): + doc = FreeCAD.newDocument() + if self.form.projectName.text(): + doc.Label = self.form.projectName.text() + if doc: + FreeCAD.setActiveDocument(doc.Name) + + # Project creation + if self.form.groupNewProject.isChecked(): + from nativeifc import ifc_tools + if self.form.radioNative2.isChecked(): + self.project = ifc_tools.create_document_object(doc, silent=True) + if self.form.projectName.text(): + self.project.Label = self.form.projectName.text() + elif self.form.radioNative3.isChecked(): + self.project = ifc_tools.convert_document(doc, silent=True) + + # human human = None if self.form.addHumanFigure.isChecked(): humanshape = Part.Shape() @@ -135,47 +196,127 @@ class BIM_ProjectManager: human = FreeCAD.ActiveDocument.addObject("Part::Feature", "Human") human.Shape = humanshape human.Placement.move(FreeCAD.Vector(500, 500, 0)) + + # Site creation or edition + outline = None + if self.form.groupSite.isChecked(): + if not self.site: + self.site = Arch.makeSite() + if self.project: + from nativeifc import ifc_tools + self.site = ifc_tools.aggregate(self.site, self.project) + self.site.Label = self.form.siteName.text() + if hasattr(self.site,"Address"): + self.site.Address = self.form.siteAddress.text() + elif hasattr(self.site,"SiteAddress"): + self.site.SiteAddress = self.form.siteAddress.text() + if hasattr(self.site,"Longitude"): + self.site.Longitude = self.form.siteLongitude.value() + elif hasattr(self.site,"RefLongitude"): + self.site.RefLongitude = self.form.siteLongitude.value() + if hasattr(self.site,"Latitude"): + self.site.Latitude = self.form.siteLatitude.value() + elif hasattr(self.site,"RefLatitude"): + self.site.RefLatitude = self.form.siteLatitude.value() + if hasattr(self.site, "NorthDeviation"): + self.site.NorthDeviation = self.form.siteDeviation.value() + elif hasattr(self.site, "Declination"): + self.site.Declination = self.form.siteDeviation.value() + elev = FreeCAD.Units.Quantity(self.form.siteElevation.text()).Value + if hasattr(self.site, "Elevation"): + self.site.Elevation = elev + elif hasattr(self.site, "RefElevation"): + self.site.RefElevation = elev + + # Building creation or edition if self.form.groupBuilding.isChecked(): - building = Arch.makeBuilding() - if site: - site.Group = [building] - building.Label = self.form.buildingName.text() - building.BuildingType = self.form.buildingUse.currentText() - buildingWidth = FreeCAD.Units.Quantity(self.form.buildingWidth.text()).Value - buildingLength = FreeCAD.Units.Quantity( - self.form.buildingLength.text() - ).Value - distVAxes = FreeCAD.Units.Quantity(self.form.distVAxes.text()).Value - distHAxes = FreeCAD.Units.Quantity(self.form.distHAxes.text()).Value - levelHeight = FreeCAD.Units.Quantity(self.form.levelHeight.text()).Value - color = self.form.lineColor.property("color").getRgbF()[:3] - grp = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup") - grp.Label = translate("BIM", "Building Layout") - building.addObject(grp) + if not self.building: + self.building = Arch.makeBuilding() + if self.project: + from nativeifc import ifc_tools + if self.site: + self.building = ifc_tools.aggregate(self.building, self.site) + else: + self.building = ifc_tools.aggregate(self.building, self.project) + elif self.site: + self.site.Group = [self.building] + self.building.Label = self.form.buildingName.text() + if hasattr(self.building, "BuildingType"): + self.building.BuildingType = self.form.buildingUse.currentText() + + # Detecting existing contents + if self.building: + grp = [o for o in self.building.Group if o.Name.startswith("BuildingLayout")] + if grp: + grp = grp[0] + if grp: + axes = [o for o in grp.Group if o.Name.startswith("Axis")] + if axes: + for ax in axes: + if round(math.degrees(ax.Placement.Rotation.Angle),0) in [0, 180, 360]: + vaxes.append(ax) + elif round(math.degrees(ax.Placement.Rotation.Angle),0) in [90, 270]: + haxes.append(ax) + outline = [o for o in grp.Group if o.Name.startswith("Rectangle")] + if outline: + outline = outline[0] + human = [o for o in grp.Group if o.Name.startswith("Human")] + if human: + human = human[0] + else: + if self.form.addHumanFigure.isChecked() or self.form.countVAxes.value() \ + or self.form.countHAxes.value() or (buildingWidth and buildingLength): + grp = doc.addObject("App::DocumentObjectGroup", "BuildingLayout") + grp.Label = translate("BIM", "Building Layout") + if self.building: + if hasattr(self.building, "addObject"): + self.building.addObject(grp) + + # Human figure + if self.form.addHumanFigure.isChecked(): + if not human: + # TODO embed this + humanpath = os.path.join( + os.path.dirname(__file__), "geometry", "human figure.brep" + ) + if os.path.exists(humanpath): + humanshape = Part.Shape() + humanshape.importBrep(humanpath) + human = FreeCAD.ActiveDocument.addObject("Part::Feature", "Human") + human.Shape = humanshape + human.Placement.move(FreeCAD.Vector(500, 500, 0)) + if human: + grp.addObject(human) + # TODO: nativeifc + + # Outline if buildingWidth and buildingLength: - outline = Draft.makeRectangle(buildingLength, buildingWidth, face=False) - outline.Label = translate("BIM", "Building Outline") - outline.ViewObject.DrawStyle = "Dashed" + if not outline: + outline = Draft.makeRectangle(buildingLength, buildingWidth, face=False) + outline.Label = translate("BIM", "Building Outline") + outline.ViewObject.DrawStyle = "Dashed" + grp.addObject(outline) outline.ViewObject.LineColor = color outline.ViewObject.LineWidth = self.form.lineWidth.value() * 2 - grp.addObject(outline) - if self.form.buildingName.text(): - buildingname = self.form.buildingName.text() - if sys.version_info.major == 2: - buildingname = unicode(buildingname) - outtext = Draft.makeText( - [buildingname], - point=FreeCAD.Vector( - Draft.getParam("textheight", 0.20) * 0.3, - -Draft.getParam("textheight", 0.20) * 1.43, - 0, - ), - ) - outtext.Label = translate("BIM", "Building Label") - outtext.ViewObject.TextColor = color - grp.addObject(outtext) - if human: - grp.addObject(human) + outline.Length = buildingLength + outline.Height = buildingWidth + + # Label + if self.form.buildingName.text(): + buildingname = self.form.buildingName.text() + outtext = Draft.make_text( + [buildingname], + FreeCAD.Vector( + Draft.getParam("textheight", 0.20) * 0.3, + -Draft.getParam("textheight", 0.20) * 1.43, + 0, + ), + ) + outtext.Label = translate("BIM", "Building Label") + outtext.ViewObject.TextColor = color + grp.addObject(outtext) + + # Axes axisV = None if self.form.countVAxes.value() and distVAxes: axisV = Arch.makeAxis( @@ -187,18 +328,6 @@ class BIM_ProjectManager: axisV.ViewObject.FontSize = Draft.getParam("textheight", 0.20) axisV.ViewObject.BubbleSize = Draft.getParam("textheight", 0.20) * 1.43 axisV.ViewObject.LineColor = color - if outline: - axisV.setExpression("Length", outline.Name + ".Height * 1.1") - axisV.setExpression( - "Placement.Base.y", - outline.Name - + ".Placement.Base.y - " - + axisV.Name - + ".Length * 0.05", - ) - axisV.setExpression( - "Placement.Base.x", outline.Name + ".Placement.Base.x" - ) axisH = None if self.form.countHAxes.value() and distHAxes: axisH = Arch.makeAxis( @@ -212,18 +341,6 @@ class BIM_ProjectManager: axisH.ViewObject.BubbleSize = Draft.getParam("textheight", 0.20) * 1.43 axisH.Placement.Rotation = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 90) axisH.ViewObject.LineColor = color - if outline: - axisH.setExpression("Length", outline.Name + ".Length * 1.1") - axisH.setExpression( - "Placement.Base.x", - outline.Name - + ".Placement.Base.x + " - + axisH.Name - + ".Length * 0.945", - ) - axisH.setExpression( - "Placement.Base.y", outline.Name + ".Placement.Base.y" - ) if axisV and axisH: axisG = Arch.makeAxisSystem([axisH, axisV]) axisG.Label = translate("BIM", "Axes") @@ -245,67 +362,41 @@ class BIM_ProjectManager: alabels.append(lev.Label) lev.Height = levelHeight lev.Placement.move(FreeCAD.Vector(0, 0, h)) - building.addObject(lev) - if self.form.levelsWP.isChecked(): - prx = Draft.makeWorkingPlaneProxy(FreeCAD.Placement()) - prx.Placement.move(FreeCAD.Vector(0, 0, h)) - lev.addObject(prx) + if self.project and self.building: + from nativeifc import ifc_tools + lev = ifc_tools.aggregate(lev, self.building) + elif self.building: + self.building.addObject(lev) h += levelHeight for group in groups: levGroup = FreeCAD.ActiveDocument.addObject( "App::DocumentObjectGroup" ) levGroup.Label = group - lev.addObject(levGroup) - if self.form.levelsAxis.isChecked(): - axisL = Arch.makeAxis( - num=self.form.countLevels.value(), - size=levelHeight, - name="laxis", - ) - axisL.Label = translate("BIM", "Level Axes") - axisL.ViewObject.BubblePosition = "None" - axisL.ViewObject.LineWidth = self.form.lineWidth.value() - axisL.ViewObject.FontSize = Draft.getParam("textheight", 0.20) - axisL.Placement.Rotation = FreeCAD.Rotation( - FreeCAD.Vector( - 0.577350269189626, -0.5773502691896257, 0.5773502691896257 - ), - 120, - ) - axisL.ViewObject.LineColor = color - axisL.ViewObject.LabelOffset.Rotation = FreeCAD.Rotation( - FreeCAD.Vector(1, 0, 0), 90 - ) - axisL.Labels = alabels - axisL.ViewObject.ShowLabel = True - if outline: - axisL.setExpression("Length", outline.Name + ".Length * 1.1") - axisL.setExpression( - "Placement.Base.x", - outline.Name - + ".Placement.Base.x + " - + axisL.Name - + ".Length * 0.945", - ) - axisL.setExpression( - "Placement.Base.y", outline.Name + ".Placement.Base.y" - ) - grp.addObject(axisL) - axisL.ViewObject.LabelOffset.Base = FreeCAD.Vector( - -axisL.Length.Value + Draft.getParam("textheight", 0.20) * 0.43, - 0, - Draft.getParam("textheight", 0.20) * 0.43, - ) - self.form.hide() + if self.project: + from nativeifc import ifc_tools + ifc_tools.aggregate(levGroup, lev) + else: + lev.addObject(levGroup) FreeCAD.ActiveDocument.recompute() + # fit zoom if outline: FreeCADGui.Selection.clearSelection() FreeCADGui.Selection.addSelection(outline) FreeCADGui.SendMsgToActiveView("ViewSelection") FreeCADGui.Selection.clearSelection() + # aggregate layout group + if self.building and grp: + if hasattr(self.building, "IfcClass"): + from nativeifc import ifc_tools + ifc_tools.aggregate(grp, self.building) + self.form.hide() + FreeCAD.ActiveDocument.recompute() if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.show() + if self.form.radioNative3.isChecked(): + from nativeifc import ifc_status + ifc_status.set_button(True,True) return True def addGroup(self): @@ -403,6 +494,7 @@ class BIM_ProjectManager: import Arch from PySide import QtGui + preset = self.form.presets.itemText(preset) pfile = os.path.join(FreeCAD.getUserAppDataDir(), "BIM", preset + ".txt") if os.path.exists(pfile): f = open(pfile, "r") diff --git a/src/Mod/BIM/bimcommands/BimTDView.py b/src/Mod/BIM/bimcommands/BimTDView.py index c3d1230d01..a80c0819d4 100644 --- a/src/Mod/BIM/bimcommands/BimTDView.py +++ b/src/Mod/BIM/bimcommands/BimTDView.py @@ -77,7 +77,7 @@ class BIM_TDView: FreeCAD.ActiveDocument.openTransaction("Create view") for section in sections: view = FreeCAD.ActiveDocument.addObject( - "TechDraw::DrawViewArch", "ArchView" + "TechDraw::DrawViewArch", "BIM view" ) view.Label = section.Label view.Source = section diff --git a/src/Mod/BIM/bimcommands/BimViews.py b/src/Mod/BIM/bimcommands/BimViews.py index 4b3fc36828..1c03676a87 100644 --- a/src/Mod/BIM/bimcommands/BimViews.py +++ b/src/Mod/BIM/bimcommands/BimViews.py @@ -292,7 +292,7 @@ class BIM_Views: top.addChild(i) vm.viewtree.addTopLevelItem(top) - # set TreeVinew Item selected if obj is selected + # set TreeView Item selected if obj is selected bold = QtGui.QFont() bold.setBold(True) objSelected = FreeCADGui.Selection.getSelection() @@ -615,7 +615,7 @@ def show(item, column=None): for storey in storeys: if storey != obj: storey.ViewObject.Visibility = False - elif obj.IfcType == "IfcBuilding": + elif hasattr(obj, "IfcType") and obj.IfcType == "IfcBuilding": # show all storeys storeys = [o for o in obj.OutList if Draft.getType(o) == "IfcBuildingStorey"] for storey in storeys: diff --git a/src/Mod/BIM/importers/exportIFC.py b/src/Mod/BIM/importers/exportIFC.py index fa65264b90..12e2a10933 100644 --- a/src/Mod/BIM/importers/exportIFC.py +++ b/src/Mod/BIM/importers/exportIFC.py @@ -2423,7 +2423,8 @@ def getUID(obj,preferences): obj.IfcData = d if hasattr(obj, "GlobalId"): obj.GlobalId = uid - uids.append(uid) + if "uids" in globals(): + uids.append(uid) return uid @@ -2499,6 +2500,11 @@ def create_annotation(anno, ifcfile, context, history, preferences): """Creates an annotation object""" global curvestyles, ifcbin + reps = [] + repid = "Annotation" + reptype = "Annotation2D" + description = getattr(anno, "Description", None) + # uses global ifcbin, curvestyles objectType = None ovc = None zvc = None @@ -2506,7 +2512,6 @@ def create_annotation(anno, ifcfile, context, history, preferences): reps = [] repid = "Annotation" reptype = "Annotation2D" - description = getattr(anno, "Description", None) if anno.isDerivedFrom("Part::Feature"): if Draft.getType(anno) == "Hatch": objectType = "HATCH" @@ -2525,15 +2530,8 @@ def create_annotation(anno, ifcfile, context, history, preferences): axes.append(axis) if axes: if len(axes) > 1: - xvc = ifcbin.createIfcDirection((1.0,0.0,0.0)) - zvc = ifcbin.createIfcDirection((0.0,0.0,1.0)) - ovc = ifcbin.createIfcCartesianPoint((0.0,0.0,0.0)) - gpl = ifcbin.createIfcAxis2Placement3D(ovc,zvc,xvc) - plac = ifcbin.createIfcLocalPlacement(gpl) - grid = ifcfile.createIfcGrid(uid,history,name,description,None,plac,None,axes,None,None) - return grid - else: - return axes[0] + print("DEBUG: exportIFC.create_annotation: Cannot create more thna one axis",anno.Label) + return axes[0] else: print("Unable to handle object",anno.Label) return None diff --git a/src/Mod/BIM/importers/importDAE.py b/src/Mod/BIM/importers/importDAE.py index d3749559da..9a3797dae4 100644 --- a/src/Mod/BIM/importers/importDAE.py +++ b/src/Mod/BIM/importers/importDAE.py @@ -166,7 +166,7 @@ def read(filename): # Print the errors that occurred during reading. if col.errors: - FreeCAD.Console.PrintWarning(translate("BIM", "File was read but some errors occured:") + "\n") + FreeCAD.Console.PrintWarning(translate("BIM", "File was read but some errors occurred:") + "\n") for e in col.errors: FreeCAD.Console.PrintWarning(str(e) + "\n") diff --git a/src/Mod/BIM/importers/importSH3DHelper.py b/src/Mod/BIM/importers/importSH3DHelper.py index 52f10c12b9..c32084c01b 100644 --- a/src/Mod/BIM/importers/importSH3DHelper.py +++ b/src/Mod/BIM/importers/importSH3DHelper.py @@ -19,6 +19,8 @@ # * * # *************************************************************************** """Helper functions that are used by SH3D importer.""" +import itertools +import numpy as np import math import os import re @@ -28,14 +30,15 @@ import xml.etree.ElementTree as ET import zipfile import Arch +import BOPTools.SplitFeatures +import BOPTools.BOPFeatures import Draft import DraftGeomUtils import DraftVecUtils import Mesh import MeshPart -import numpy import Part -from draftobjects.facebinder import Facebinder + from draftutils.messages import _err, _log, _msg, _wrn from draftutils.params import get_param_arch @@ -44,7 +47,6 @@ import FreeCAD as App if App.GuiUp: import FreeCADGui as Gui from draftutils.translate import translate - from draftviewproviders.view_facebinder import ViewProviderFacebinder else: # \cond def translate(_, text): @@ -86,7 +88,7 @@ Z_NORM = App.Vector(0, 0, 1) # "Sliding 4-pane", "Awning"] # unzip -p all-windows.sh3d Home.xml | \ # grep 'catalogId=' | \ -# sed -e 's/.*catalogId=//;s/ name=.*/: ("Open 2-pane","Window"),/' | sort -u +# sed -e 's/.*catalogId=//;s/ name=.*/: ("Fixed","Window"),/' | sort -u # unzip -p all-doors.sh3d Home.xml | \ # grep 'catalogId=' | \ # sed -e 's/.*catalogId=//;s/ name=.*/: ("Simple door","Door")/' | sort -u @@ -115,39 +117,51 @@ DOOR_MODELS = { 'Scopia#glass_door': ("Glass door","Door"), 'Scopia#puerta': ("Simple door","Door"), - 'eTeks#doubleFrenchWindow126x200': ("Open 2-pane","Window"), - 'eTeks#doubleHungWindow80x122': ("Open 2-pane","Window"), - 'eTeks#doubleOutwardOpeningWindow': ("Open 2-pane","Window"), - 'eTeks#doubleWindow126x123': ("Open 2-pane","Window"), - 'eTeks#doubleWindow126x163': ("Open 2-pane","Window"), - 'eTeks#fixedTriangleWindow85x85': ("Open 2-pane","Window"), - 'eTeks#fixedWindow85x123': ("Open 2-pane","Window"), - 'eTeks#frenchWindow85x200': ("Open 2-pane","Window"), - 'eTeks#halfRoundWindow': ("Open 2-pane","Window"), - 'eTeks#roundWindow': ("Open 2-pane","Window"), - 'eTeks#sliderWindow126x200': ("Open 2-pane","Window"), - 'eTeks#window85x123': ("Open 2-pane","Window"), - 'eTeks#window85x163': ("Open 2-pane","Window"), - 'Kator Legaz#window-01': ("Open 2-pane","Window"), - 'Kator Legaz#window-08-02': ("Open 2-pane","Window"), - 'Kator Legaz#window-08': ("Open 2-pane","Window"), - 'Scopia#turn-window': ("Open 2-pane","Window"), - 'Scopia#window_2x1_medium_with_large_pane': ("Open 2-pane","Window"), - 'Scopia#window_2x1_with_sliders': ("Open 2-pane","Window"), - 'Scopia#window_2x3_arched': ("Open 2-pane","Window"), - 'Scopia#window_2x3': ("Open 2-pane","Window"), - 'Scopia#window_2x3_regular': ("Open 2-pane","Window"), - 'Scopia#window_2x4_arched': ("Open 2-pane","Window"), - 'Scopia#window_2x4': ("Open 2-pane","Window"), - 'Scopia#window_2x6': ("Open 2-pane","Window"), - 'Scopia#window_3x1': ("Open 2-pane","Window"), - 'Scopia#window_4x1': ("Open 2-pane","Window"), - 'Scopia#window_4x3_arched': ("Open 2-pane","Window"), - 'Scopia#window_4x3': ("Open 2-pane","Window"), - 'Scopia#window_4x5': ("Open 2-pane","Window"), + 'eTeks#doubleFrenchWindow126x200': ("Fixed","Window"), + 'eTeks#doubleHungWindow80x122': ("Fixed","Window"), + 'eTeks#doubleOutwardOpeningWindow': ("Fixed","Window"), + 'eTeks#doubleWindow126x123': ("Fixed","Window"), + 'eTeks#doubleWindow126x163': ("Fixed","Window"), + 'eTeks#fixedTriangleWindow85x85': ("Fixed","Window"), + 'eTeks#fixedWindow85x123': ("Fixed","Window"), + 'eTeks#frenchWindow85x200': ("Fixed","Window"), + 'eTeks#halfRoundWindow': ("Fixed","Window"), + 'eTeks#roundWindow': ("Fixed","Window"), + 'eTeks#sliderWindow126x200': ("Fixed","Window"), + 'eTeks#window85x123': ("Fixed","Window"), + 'eTeks#window85x163': ("Fixed","Window"), + 'Kator Legaz#window-01': ("Fixed","Window"), + 'Kator Legaz#window-08-02': ("Fixed","Window"), + 'Kator Legaz#window-08': ("Fixed","Window"), + 'Scopia#turn-window': ("Fixed","Window"), + 'Scopia#window_2x1_medium_with_large_pane': ("Fixed","Window"), + 'Scopia#window_2x1_with_sliders': ("Fixed","Window"), + 'Scopia#window_2x3_arched': ("Fixed","Window"), + 'Scopia#window_2x3': ("Fixed","Window"), + 'Scopia#window_2x3_regular': ("Fixed","Window"), + 'Scopia#window_2x4_arched': ("Fixed","Window"), + 'Scopia#window_2x4': ("Fixed","Window"), + 'Scopia#window_2x6': ("Fixed","Window"), + 'Scopia#window_3x1': ("Fixed","Window"), + 'Scopia#window_4x1': ("Fixed","Window"), + 'Scopia#window_4x3_arched': ("Fixed","Window"), + 'Scopia#window_4x3': ("Fixed","Window"), + 'Scopia#window_4x5': ("Fixed","Window"), } + +ET_XPATH_LEVEL = 'level' +ET_XPATH_ROOM = 'room' +ET_XPATH_WALL = 'wall' +ET_XPATH_DOOR_OR_WINDOWS = './/doorOrWindow' +ET_XPATH_PIECE_OF_FURNITURE = './/pieceOfFurniture' +ET_XPATH_LIGHT = 'light' +ET_XPATH_OBSERVER_CAMERA = 'observerCamera' +ET_XPATH_CAMERA = 'camera' +ET_XPATH_DUMMY_SLAB = 'DummySlab' +ET_XPATH_DUMMY_DECORATE = 'DummyDecorate' + class SH3DImporter: """The main class to import an SH3D file. @@ -179,8 +193,8 @@ class SH3DImporter: self.building = None self.default_floor = None self.floors = {} - self.walls = [] - self.space_upper_faces = [] + self.walls = {} + self.spaces = {} def import_sh3d_from_string(self, home:str): """Import the SH3D Home from a String. @@ -234,17 +248,15 @@ class SH3DImporter: # Get all the FreeCAD object in the active doc, in order to allow # for merge of existing object if self.preferences["MERGE"]: - for object in doc.Objects: - if hasattr(object, 'id'): - self.fc_objects[object.id] = object + list(map(lambda o2: self.add_fc_objects(o2), list(filter(lambda o1: hasattr(o1, 'id'), doc.Objects)))) # Let's create the project and site for this import self._setup_project(home) # Import the element if any. If none are defined # create a default one. - if home.find(path='level') != None: - self._import_elements(home, 'level') + if home.find(ET_XPATH_LEVEL) != None: + self._import_elements(home, ET_XPATH_LEVEL) else: # Has the default floor already been created from a # previous import? @@ -252,54 +264,47 @@ class SH3DImporter: self.default_floor = self.fc_objects.get('Level') if 'Level' in self.fc_objects else self._create_default_floor() # Importing elements ... - self._import_elements(home, 'room') + self._import_elements(home, ET_XPATH_ROOM) # Importing elements ... - self._import_elements(home, 'wall') + self._import_elements(home, ET_XPATH_WALL) + self._refresh() + # Walls&Rooms have been imported. Created the floor slabs + self._create_slabs() self._refresh() if self.preferences["CREATE_GROUND_MESH"]: self._create_ground_mesh(home) + self._refresh() - self._refresh() if App.GuiUp and self.preferences["FIT_VIEW"]: Gui.SendMsgToActiveView("ViewFit") # Importing elements ... if self.preferences["IMPORT_DOORS_AND_WINDOWS"]: - self._import_elements(home, 'doorOrWindow') - for furniture_group in home.findall('furnitureGroup'): - self._import_elements(furniture_group, 'doorOrWindow', False) + self._import_elements(home, ET_XPATH_DOOR_OR_WINDOWS) self._refresh() - group = App.ActiveDocument.Facebinders - for element in group.Group: - faces = [] - new_sel_subshapes = [] - for (sel_object, sel_subshapes) in element.Faces: - for sel_subshape in sel_subshapes: - sel_subshape = sel_subshape[1:] if sel_subshape.startswith('?') else sel_subshape - new_sel_subshapes.append(sel_subshape) - faces.append((sel_object, new_sel_subshapes)) - element.Faces = faces + + # Door&Windows have been imported. Now we can decorate... + if self.preferences["DECORATE_SURFACES"]: + self._decorate_surfaces() self._refresh() # Importing && elements ... if self.preferences["IMPORT_FURNITURES"]: - self._import_elements(home, 'pieceOfFurniture') - for furniture_group in home.findall('furnitureGroup'): - self._import_elements(furniture_group, 'pieceOfFurniture', False) + self._import_elements(home, ET_XPATH_PIECE_OF_FURNITURE) self._refresh() # Importing elements ... if self.preferences["IMPORT_LIGHTS"]: - self._import_elements(home, 'light') + self._import_elements(home, ET_XPATH_LIGHT) self._refresh() # Importing elements ... if self.preferences["IMPORT_CAMERAS"]: - self._import_elements(home, 'observerCamera') - self._import_elements(home, 'camera') + self._import_elements(home, ET_XPATH_OBSERVER_CAMERA) + self._import_elements(home, ET_XPATH_CAMERA) self._refresh() if self.preferences["CREATE_RENDER_PROJECT"] and self.site: @@ -338,29 +343,32 @@ class SH3DImporter: 'CREATE_GROUND_MESH': get_param_arch("sh3dCreateGroundMesh"), 'DEFAULT_GROUND_COLOR': color_fc2sh(get_param_arch("sh3dDefaultGroundColor")), 'DEFAULT_SKY_COLOR': color_fc2sh(get_param_arch("sh3dDefaultSkyColor")), + 'DECORATE_SURFACES': get_param_arch("sh3dDecorateSurfaces"), } def _setup_handlers(self): self.handlers = { - 'level': LevelHandler(self), - 'room': RoomHandler(self), - 'wall': WallHandler(self), + ET_XPATH_LEVEL: LevelHandler(self), + ET_XPATH_ROOM: RoomHandler(self), + ET_XPATH_WALL: WallHandler(self), + ET_XPATH_DUMMY_SLAB : None, } if self.preferences["IMPORT_DOORS_AND_WINDOWS"]: - self.handlers['doorOrWindow'] = DoorOrWindowHandler(self) - self.handlers['furnitureGroup'] = None + self.handlers[ET_XPATH_DOOR_OR_WINDOWS] = DoorOrWindowHandler(self) + + if self.preferences["DECORATE_SURFACES"]: + self.handlers[ET_XPATH_DUMMY_DECORATE] = None, if self.preferences["IMPORT_FURNITURES"]: - self.handlers['pieceOfFurniture'] = FurnitureHandler(self) - self.handlers['furnitureGroup'] = None + self.handlers[ET_XPATH_PIECE_OF_FURNITURE] = FurnitureHandler(self) if self.preferences["IMPORT_LIGHTS"]: - self.handlers['light'] = LightHandler(self) + self.handlers[ET_XPATH_LIGHT] = LightHandler(self) if self.preferences["IMPORT_CAMERAS"]: camera_handler = CameraHandler(self) - self.handlers['observerCamera'] = camera_handler - self.handlers['camera'] = camera_handler + self.handlers[ET_XPATH_OBSERVER_CAMERA] = camera_handler + self.handlers[ET_XPATH_CAMERA] = camera_handler def _refresh(self): App.ActiveDocument.recompute() @@ -392,10 +400,14 @@ class SH3DImporter: value = str(value.get(name, "")) elif type_ == "App::PropertyFloat": value = float(value.get(name, 0)) + elif type_ == "App::PropertyQuantity": + value = float(value.get(name, 0)) elif type_ == "App::PropertyInteger": value = int(value.get(name, 0)) + elif type_ == "App::PropertyPercent": + value = int(value.get(name, 0)) elif type_ == "App::PropertyBool": - value = bool(value.get(name, True)) + value = value.get(name, "true") == "true" if self.preferences["DEBUG"]: _log(f"Setting @{obj}.{name} = {value}") setattr(obj, name, value) @@ -414,6 +426,17 @@ class SH3DImporter: if name not in obj.PropertiesList: obj.addProperty(property_type, name, group, description) + def add_fc_objects(self, obj): + """Register `obj`. + + This object can then be referenced later on by + other objects (i.e. light, etc.) + + Args: + obj (AppDocumentObject): the object to register + """ + self.fc_objects[obj.id] = obj + def get_fc_object(self, id, sh_type): """Returns the FC doc element corresponding to the imported id and sh_type @@ -455,6 +478,14 @@ class SH3DImporter: return self.default_floor return self.floors.get(level_id, None) + def add_space(self, floor, space): + if floor.id not in self.spaces: + self.spaces[floor.id] = [] + self.spaces[floor.id].append(space) + + def get_spaces(self, floor): + return self.spaces.get(floor.id, []) + def get_space(self, floor, p): """Returns the Space this point belongs to. @@ -468,26 +499,35 @@ class SH3DImporter: Space: the space the object belongs to or None """ closest_space = None - for (space_floor, space, space_face) in self.space_upper_faces: - if not space_face: #?!? - continue - space_face_z = space_face.CenterOfMass.z - projection = App.Vector(p.x, p.y, space_face_z) + for space in self.spaces.get(floor.id, []): + space_face = space.Base.Shape + space_z = space_face.CenterOfMass.z + projection = App.Vector(p.x, p.y, space_z) # Checks that: # - the point's projection is inside the face # - the point is above the face # - the point's parent and the face's are on the same level # NOTE: If two rooms overlap on the same level, the result is # undefined... - if space_face.isInside(projection, 1, True) and space_face_z < p.z and space_floor.id == floor.id: + if space_face.isInside(projection, 1, True) and space_z < p.z: closest_space = space return closest_space - def add_wall(self, wall): - self.walls.append(wall) + def add_wall(self, floor, wall): + if floor.id not in self.walls: + self.walls[floor.id] = [] + self.walls[floor.id].append(wall) - def get_walls(self): - return self.walls + def get_walls(self, floor): + """Returns the wall belonging to the specified level + + Args: + floor (Arch.Level): the level for which to return the list of wall + + Returns: + list: the list of Arch.Wall + """ + return self.walls.get(floor.id, []) def _create_groups(self): """Create FreeCAD Group for the different imported elements @@ -507,10 +547,6 @@ class SH3DImporter: elm (str): the element """ - if 'Project' in self.fc_objects: - self.project = self.fc_objects.get('Project') - elif self.preferences["CREATE_IFC_PROJECT"]: - self.project = self._create_project() if 'Site' in self.fc_objects: self.site = self.fc_objects.get('Site') else: @@ -522,11 +558,15 @@ class SH3DImporter: else: self.building = self._create_building(elm) - if self.preferences["CREATE_IFC_PROJECT"]: - self.project.addObject(self.site) - self.site.addObject(self.building) + if 'Project' in self.fc_objects: + self.project = self.fc_objects.get('Project') + elif self.preferences["CREATE_IFC_PROJECT"]: + self.project = self._create_project() + if self.project: + self.project.addObject(self.site) + def _create_project(self): """Create a default Arch::Project object """ @@ -589,7 +629,7 @@ class SH3DImporter: self.site.addObject(ground) - def _import_elements(self, parent, tag, update_progress=True): + def _import_elements(self, parent, xpath): """Generic function to import a specific element. This function will lookup the handler registered for the elements @@ -599,31 +639,40 @@ class SH3DImporter: Args: parent (Element): the parent of the elements to be imported. Usually the element. - tag (str): the tag of the elements to be imported. + xpath (str): the xpath of the elements to be imported. update_progress (bool, optional): whether to update the progress. Set to false when importing a group of elements. Defaults to True. """ - tags = list(self.handlers.keys()) - elements = parent.findall(tag) - if update_progress and self.progress_bar: + xpaths = list(self.handlers.keys()) + elements = parent.findall(xpath) + tag_name = xpath[3:] if xpath.startswith('.') else xpath + + total_steps, current_step, total_elements = self._get_progress_info(xpath, elements) + if self.progress_bar: self.progress_bar.stop() - self.progress_bar.start(f"Step {tags.index(tag)+1}/{len(tags)}: importing {len(elements)} '{tag}' elements. Please wait ...", len(elements)) - _msg(f"Importing {len(elements)} '{tag}' elements ...") + self.progress_bar.start(f"Step {current_step}/{total_steps}: importing {total_elements} '{tag_name}' elements. Please wait ...", total_elements) + _msg(f"Importing {total_elements} '{tag_name}' elements ...") def _process(tuple): (i, elm) = tuple - _msg(f"Importing {tag}#{i} ({self.current_object_count + 1}/{self.total_object_count}) ...") + _msg(f"Importing {tag_name}#{i} ({self.current_object_count + 1}/{self.total_object_count}) ...") try: - self.handlers[tag].process(parent, i, elm) + self.handlers[xpath].process(parent, i, elm) except Exception as e: - _err(f"Failed to import <{tag}>#{i} ({elm.get('id', elm.get('name'))}):") + _err(f"Failed to import <{tag_name}>#{i} ({elm.get('id', elm.get('name'))}):") _err(str(e)) _err(traceback.format_exc()) - if update_progress and self.progress_bar: + if self.progress_bar: self.progress_bar.next() self.current_object_count = self.current_object_count + 1 list(map(_process, enumerate(elements))) + def _get_progress_info(self, xpath, elements): + xpaths = list(self.handlers.keys()) + total_steps = len(xpaths) + current_step = xpaths.index(xpath)+1 + return total_steps, current_step, len(elements) + def _set_site_properties(self, elm): # All information in environment?, backgroundImage?, print?, compass # are added to the site object. Some are furthermore added to the ground @@ -691,6 +740,52 @@ class SH3DImporter: else: _msg(f"No tag found in <{elm.tag}>") + def _create_slabs(self): + floors = self.floors.values() + total_steps, current_step, total_elements = self._get_progress_info(ET_XPATH_DUMMY_SLAB, floors) + if self.progress_bar: + self.progress_bar.stop() + self.progress_bar.start(f"Step {current_step}/{total_steps}: Creating {total_elements} 'slab' elements. Please wait ...", total_elements) + _msg(f"Creating {total_elements} 'slab' elements ...") + handler = self.handlers[ET_XPATH_LEVEL] + def _create_slab(tuple): + (i, floor) = tuple + _msg(f"Creating slab#{i} for floor '{floor.Label}' ...") + try: + handler.create_slabs(floor) + except Exception as e: + _err(f"Failed to create slab#{i} for floor '{floor.Label}':") + _err(str(e)) + _err(traceback.format_exc()) + if self.progress_bar: + self.progress_bar.next() + list(map(_create_slab, enumerate(floors))) + + def _decorate_surfaces(self): + + all_spaces = self.spaces.values() + all_spaces = list(itertools.chain(*all_spaces)) + all_walls = self.walls.values() + all_walls = list(itertools.chain(*all_walls)) + + total_elements = len(all_spaces)+len(all_walls) + + if self.progress_bar: + self.progress_bar.stop() + self.progress_bar.start(f"Decorating {total_elements} elements. Please wait ...", total_elements) + _msg(f"Decorating {total_elements} elements ...") + + handler = self.handlers[ET_XPATH_ROOM] + for i, space in enumerate(all_spaces): + handler.post_process(space) + if self.progress_bar: self.progress_bar.next() + + handler = self.handlers[ET_XPATH_WALL] + for i, wall in enumerate(all_walls): + handler.post_process(wall) + if self.progress_bar: self.progress_bar.next() + if self.progress_bar: self.progress_bar.stop() + class BaseHandler: """The base class for all importers.""" @@ -741,6 +836,9 @@ class BaseHandler: """ return self.importer.get_floor(level_id) + def get_spaces(self, floor): + return self.importer.get_spaces(floor) + def get_space(self, floor, p): """Returns the Space this point belongs to. @@ -755,47 +853,30 @@ class BaseHandler: """ return self.importer.get_space(floor, p) - def _get_upper_face(self, faces): - """Returns the upper face of a given list of faces + def get_walls(self, floor): + return self.importer.get_walls(floor) - More specifically returns the face with the highest z. - It is used to figure out which space a furniture belongs to. + def _ps(self, section, print_z: bool = False): + # Pretty print a Section in a condensed way + if hasattr(section, 'Shape'): + v = section.Shape.Vertexes + else: + # a Part.Face + v = section.Vertexes + return f"[{self._pv(v[0].Point, print_z)}, {self._pv(v[1].Point, print_z)}, {self._pv(v[2].Point, print_z)}, {self._pv(v[3].Point, print_z)}]" - Args: - faces (list): The list of faces + def _pe(self, edge, print_z: bool = False): + # Print an Edge in a condensed way + v = edge.Vertexes + return f"[{self._pv(v[0].Point, print_z)}, {self._pv(v[1].Point, print_z)}]" - Returns: - Face: the upper face - """ - upper_face = None - com_max_z = -float('inf') - for face in faces: - com = face.CenterOfMass - if com.z > com_max_z: - upper_face = face - com_max_z = com.z - return upper_face - - def _get_lower_face(self, faces): - """Returns the lower face of a given list of faces - - More specifically returns the face with the lowest z. - It is used to figure out which space a furniture belongs to. - - Args: - faces (list): The list of faces - - Returns: - Face: the lower face - """ - lower_face = None - com_min_z = float('inf') - for face in faces: - com = face.CenterOfMass - if com.z < com_min_z: - lower_face = face - com_min_z = com.z - return lower_face + def _pv(self, v, print_z: bool = False, ndigits: None = None): + # Print an Vector in a condensed way + if hasattr(v,'X'): + return f"({round(getattr(v, 'X'), ndigits)},{round(getattr(v, 'Y'), ndigits)}{',' + str(round(getattr(v, 'Z'), ndigits)) if print_z else ''})" + elif hasattr(v,'x'): + return f"({round(getattr(v, 'x'), ndigits)},{round(getattr(v, 'y'), ndigits)}{',' + str(round(getattr(v, 'z'), ndigits)) if print_z else ''})" + raise ValueError(f"Expected a Point or Vector, got {type(v)}") class LevelHandler(BaseHandler): @@ -822,9 +903,8 @@ class LevelHandler(BaseHandler): floor.Placement.Base.z = dim_sh2fc(float(elm.get('elevation'))) floor.Height = dim_sh2fc(float(elm.get('height'))) self._set_properties(floor, elm) - - floor.ViewObject.Visibility = elm.get('visible', 'true') == 'true' - self._add_groups(floor) + floor.Visibility = elm.get('visible', 'true') == 'true' + self._create_groups(floor) self.importer.add_floor(floor) def create_default_floor(self): @@ -833,8 +913,8 @@ class LevelHandler(BaseHandler): floor.Placement.Base.z = 0 floor.Height = 2500 - self._set_properties(floor, dict({'shType': 'level', 'id':'Level', 'floorThickness':dim_fc2sh(250), 'elevationIndex': 0, 'viewable': True})) - self._add_groups(floor) + self._set_properties(floor, dict({'shType': 'level', 'id':'Level', 'floorThickness':25, 'elevationIndex': 0, 'viewable': True})) + self._create_groups(floor) self.importer.add_floor(floor) return floor @@ -842,20 +922,126 @@ class LevelHandler(BaseHandler): def _set_properties(self, obj, elm): self.setp(obj, "App::PropertyString", "shType", "The element type", 'level') self.setp(obj, "App::PropertyString", "id", "The floor's id", elm) - self.setp(obj, "App::PropertyFloat", "floorThickness", "The floor's slab thickness", dim_sh2fc(float(elm.get('floorThickness')))) + self.setp(obj, "App::PropertyQuantity", "floorThickness", "The floor's slab thickness", dim_sh2fc(float(elm.get('floorThickness')))) self.setp(obj, "App::PropertyInteger", "elevationIndex", "The floor number", elm) self.setp(obj, "App::PropertyBool", "viewable", "Whether the floor is viewable", elm) + def _create_groups(self, floor): + # This is a special group that does not appear in the TreeView. + group = floor.newObject("App::DocumentObjectGroup") + group.Label = f"References-{floor.Label}" + self.setp(floor, "App::PropertyString", "ReferenceFacesGroupName", "The DocumentObjectGroup name for all Reference Faces on this floor", group.Name) + group.Visibility = False + group.ViewObject.ShowInTree = False - def _add_groups(self, floor): - group = floor.newObject("App::DocumentObjectGroup", "Facebinders") - self.setp(floor, "App::PropertyString", "FacebinderGroupName", "The DocumentObjectGroup name for all Facebinders on this floor", group.Name) + if self.importer.preferences["DECORATE_SURFACES"]: + group = floor.newObject("App::DocumentObjectGroup") + group.Label = f"Decoration-{floor.Label}-Walls" + self.setp(floor, "App::PropertyString", "DecorationWallsGroupName", "The DocumentObjectGroup name for all wall decorations on this floor", group.Name) + group = floor.newObject("App::DocumentObjectGroup") + group.Label = f"Decoration-{floor.Label}-Ceilings" + self.setp(floor, "App::PropertyString", "DecorationCeilingsGroupName", "The DocumentObjectGroup name for all ceilings decoration on this floor", group.Name) + group = floor.newObject("App::DocumentObjectGroup") + group.Label = f"Decoration-{floor.Label}-Floors" + self.setp(floor, "App::PropertyString", "DecorationFloorsGroupName", "The DocumentObjectGroup name for all floors decoration on this floor", group.Name) + group = floor.newObject("App::DocumentObjectGroup") + group.Label = f"Decoration-{floor.Label}-Baseboards" + self.setp(floor, "App::PropertyString", "DecorationBaseboardsGroupName", "The DocumentObjectGroup name for all baseboards on this floor", group.Name) if self.importer.preferences["IMPORT_FURNITURES"]: - group = floor.newObject("App::DocumentObjectGroup", "Furnitures") + group = floor.newObject("App::DocumentObjectGroup", f"Furnitures-{floor.Label}") self.setp(floor, "App::PropertyString", "FurnitureGroupName", "The DocumentObjectGroup name for all furnitures in this floor", group.Name) - group = floor.newObject("App::DocumentObjectGroup", "Baseboards") - self.setp(floor, "App::PropertyString", "BaseboardGroupName", "The DocumentObjectGroup name for all baseboards on this floor", group.Name) + + def create_slabs(self, floor): + """Creates a Arch.Slab for the given floor. + + Creating a slab consists in projecting all the structures of that + floor into a plane, then create a extrusion for each one and then + fuse thogether (in order to simplify the slab geometry). + + Args: + floor (Arch.Floor): the Arch Floor for which to create the Slab + """ + # Take the walls and only the spaces whose floor is actually visible. + objects_to_project = list(filter(lambda s: s.floorVisible, self.get_spaces(floor))) + objects_to_project.extend(self.get_walls(floor)) + objects_to_fuse = self._get_object_to_fuse(floor, objects_to_project) + if len(objects_to_fuse) > 0: + if len(objects_to_fuse) > 1: + bf = BOPTools.BOPFeatures.BOPFeatures(App.ActiveDocument) + slab_base = bf.make_multi_fuse([ o.Name for o in objects_to_fuse]) + slab_base.Label = f"{floor.Label}-footprint" + else: + slab_base = objects_to_fuse[0] + slab_base.Label = f"{floor.Label}-footprint" + + slab = Arch.makeStructure(slab_base) + slab.Label = f"{floor.Label}-slab" + slab.setExpression('Height', f"{slab_base.Name}.Shape.BoundBox.ZLength") + slab.Normal = -Z_NORM + floor.addObject(slab) + else: + _wrn(f"No object found for floor {floor.Label}. No slab created.") + + def _get_object_to_fuse(self, floor, objects_to_project): + group = floor.newObject("App::DocumentObjectGroup", f"SlabObjects-{floor.Label}") + group.Visibility = False + group.ViewObject.ShowInTree = False + + objects_to_fuse = [] + for object in objects_to_project: + # Project the floor's objects onto the XY plane + sv = Draft.make_shape2dview(object, Z_NORM) + sv.Label = f"SV-{floor.Label}-{object.Label}" + sv.Placement.Base.z = floor.Placement.Base.z + sv.Visibility = False + sv.recompute() + group.addObject(sv) + + wire = Part.Wire(sv.Shape.Edges) + if not wire.isClosed(): + # Sometimes the wire is not closed because the edges are + # not sorted and do not form a "chain". Therefore, sort them, + # recreate the wire while also rounding the precision of the + # Vertices in order to avoid not closing because the points + # are not close enough + wire = Part.Wire(Part.__sortEdges__(self._round(sv.Shape.Edges))) + if not wire.isClosed(): + _wrn(f"Projected Face for {object.Label} does not produce a closed wire. Not adding to slab construction ...") + continue + + face = Part.Face(wire) + extrude = face.extrude(-Z_NORM*floor.floorThickness.Value) + part = Part.show(extrude, "Footprint") + part.Label = f"Extrude-{floor.Label}-{object.Label}-footprint" + part.recompute() + part.Visibility = False + part.ViewObject.ShowInTree = False + objects_to_fuse.append(part) + return objects_to_fuse + + def _round(self, edges, decimals=2): + """ + Rounds the coordinates of all vertices in a list of edges to the specified number of decimals. + + :param edges: A list of Part.Edge objects. + :param decimals: Number of decimal places to round to (default: 2). + :return: A list of edges with rounded vertices. + """ + new_edges = [] + + for edge in edges: + vertices = edge.Vertexes + if len(vertices) != 2: # Line or similar + raise ValueError("Unsupported edge type: Only straight edges are handled.") + new_vertices = [ + App.Vector(round(v.X, decimals), round(v.Y, decimals), round(v.Z, decimals)) + for v in vertices + ] + # Create a new edge with the rounded vertices + new_edge = Part.Edge(Part.LineSegment(new_vertices[0], new_vertices[1])) + new_edges.append(new_edge) + return new_edges class RoomHandler(BaseHandler): @@ -878,57 +1064,43 @@ class RoomHandler(BaseHandler): floor = self.get_floor(level_id) assert floor != None, f"Missing floor '{level_id}' for '{elm.get('id')}' ..." - # A Room is composed of a space with the slab as the base object - - points = [] - for point in elm.findall('point'): - x = float(point.get('x')) - y = float(point.get('y')) - z = dim_fc2sh(floor.Placement.Base.z) - points.append(coord_sh2fc(App.Vector(x, y, z))) - - slab = None + space = face = None if self.importer.preferences["MERGE"]: - slab = self.get_fc_object(elm.get("id"), 'room') - - if not slab: - line = Draft.make_wire(points, placement=App.Placement(), closed=True, face=True, support=None) - slab = Arch.makeStructure(line, height=floor.floorThickness) - - slab.Label = elm.get('name', 'Room') + '-slab' - slab.IfcType = "Slab" - slab.Normal = -Z_NORM - - color = elm.get('floorColor', self.importer.preferences["DEFAULT_FLOOR_COLOR"]) - set_color_and_transparency(slab, color) - self._set_properties(slab, elm) - - slab.recompute(True) - - # No 1-to-1 correspondance between SH3D and FC element. - # Creating a fake SH3D elemement in order to take advantage of the - # different lookup facilities. NOTE the suffix '-space' for both - # the sh_type and id... - space = None - if self.importer.preferences["MERGE"]: - space = self.get_fc_object(elm.get("id")+"-space", 'room-space') + space = self.get_fc_object(elm.get("id"), 'room') + # A Room is composed of a space with a Face as the base object if not space: - space = Arch.makeSpace(slab) + floor_z = dim_fc2sh(floor.Placement.Base.z) + points = [ coord_sh2fc(App.Vector(float(p.get('x')), float(p.get('y')), floor_z)) for p in elm.findall('point') ] + # remove consecutive identical points + points = [points[i] for i in range(len(points)) if i == 0 or points[i] != points[i - 1]] + + # Create a reference face that can be used later on to create + # the floor & ceiling decoration... + reference_face = Draft.make_wire(points, closed=True, face=True, support=None) + reference_face.Label = elm.get('name', 'Room') + '-reference' + reference_face.Visibility = False + reference_face.recompute() + floor.getObject(floor.ReferenceFacesGroupName).addObject(reference_face) + + # NOTE: for room to properly display and calculate the area, the + # Base object can not be a face but must have a height... + footprint = App.ActiveDocument.addObject("Part::Feature", "Footprint") + footprint.Shape = reference_face.Shape.extrude(Z_NORM) + footprint.Label = elm.get('name', 'Room') + '-footprint' + + space = Arch.makeSpace(footprint) space.IfcType = "Space" space.Label = elm.get('name', 'Room') - self._set_space_properties(space, elm) + self._set_properties(space, elm) - self.importer.fc_objects[slab.id] = slab - self.importer.fc_objects[space.id] = space + space.setExpression('ElevationWithFlooring', f"{footprint.Name}.Shape.BoundBox.ZMin") + self.setp(space, "App::PropertyLink", "ReferenceFace", "The Reference Part.Face", reference_face) + self.setp(space, "App::PropertyString", "ReferenceFloorName", "The name of the Arch.Floor this room belongs to", floor.Name) - upper_face = self._get_upper_face(slab.Shape.Faces) - if not upper_face: - _wrn(f"Couldn't find the upper face of slab {slab.Label} on level {floor.Label}!") - else: - self.importer.space_upper_faces.append((floor, space, upper_face)) + self.importer.add_space(floor, space) - slab.Visibility = True + space.Visibility = True if space.floorVisible else False floor.addObject(space) @@ -947,15 +1119,41 @@ class RoomHandler(BaseHandler): self.setp(obj, "App::PropertyFloat", "areaYOffset", "The room's area annotation y offset", elm) self.setp(obj, "App::PropertyBool", "floorVisible", "Whether the floor of the room is displayed", elm) self.setp(obj, "App::PropertyString", "floorColor", "The room's floor color", floor_color) - self.setp(obj, "App::PropertyFloat", "floorShininess", "The room's floor shininess", elm) + self.setp(obj, "App::PropertyPercent", "floorShininess", "The room's floor shininess", percent_sh2fc(elm.get('floorShininess', 0))) self.setp(obj, "App::PropertyBool", "ceilingVisible", "Whether the ceiling of the room is displayed", elm) self.setp(obj, "App::PropertyString", "ceilingColor", "The room's ceiling color", ceiling_color) - self.setp(obj, "App::PropertyFloat", "ceilingShininess", "The room's ceiling shininess", elm) + self.setp(obj, "App::PropertyPercent", "ceilingShininess", "The room's ceiling shininess", percent_sh2fc(elm.get('ceilingShininess', 0))) self.setp(obj, "App::PropertyBool", "ceilingFlat", "", elm) - def _set_space_properties(self, obj, elm): - self.setp(obj, "App::PropertyString", "shType", "The element type", 'room-space') - self.setp(obj, "App::PropertyString", "id", "The slab's id", elm.get('id', str(uuid.uuid4()))+"-space") + def post_process(self, obj): + if self.importer.preferences["DECORATE_SURFACES"]: + floor = App.ActiveDocument.getObject(obj.ReferenceFloorName) + self._add_facebinder(floor, obj, "floor") + self._add_facebinder(floor, obj, "ceiling") + + def _add_facebinder(self, floor, space, side): + facebinder_id = f"{floor.id}-{space.id}-{side}-facebinder" + facebinder = None + if self.importer.preferences["MERGE"]: + facebinder = self.get_fc_object(facebinder_id, 'facebinder') + + if not facebinder: + # NOTE: always use Face1 as this is a 2D object + facebinder = Draft.make_facebinder(( space.ReferenceFace, ("Face1", ) )) + facebinder.Extrusion = 1 + facebinder.Label = space.Label + f" {side} finish" + + facebinder.Placement.Base.z = 1 if (side == "floor") else floor.Height.Value-1 + facebinder.Visibility = getattr(space, f"{side}Visible") + set_color_and_transparency(facebinder, getattr(space, f"{side}Color")) + set_shininess(facebinder, getattr(space, f"{side}Shininess", 0)) + + self.setp(facebinder, "App::PropertyString", "shType", "The element type", 'facebinder') + self.setp(facebinder, "App::PropertyString", "id", "The element's id", facebinder_id) + self.setp(facebinder, "App::PropertyString", "ReferenceRoomName", "The Reference Arch.Space", space.Name) + + group_name = getattr(floor, "DecorationFloorsGroupName") if (side == "floor") else getattr(floor, "DecorationCeilingsGroupName") + floor.getObject(group_name).addObject(facebinder) class WallHandler(BaseHandler): @@ -991,24 +1189,20 @@ class WallHandler(BaseHandler): wall.IfcType = "Wall" wall.Label = f"wall{i}" + wall.Base.Label = f"wall{i}-wallshape" self._set_properties(wall, elm) + self._set_baseboard_properties(wall, elm) + self.setp(wall, "App::PropertyString", "ReferenceFloorName", "The Name of the Arch.Floor this walls belongs to", floor.Name) + wall.recompute(True) - self._create_facebinders(floor, wall, elm) - - if self.importer.preferences["IMPORT_FURNITURES"]: - for baseboard in elm.findall('baseboard'): - space = self._import_baseboard(floor, wall, baseboard) - if space: - space.Boundaries = space.Boundaries + [wall] - floor.addObject(wall) if base_object: floor.addObject(base_object) base_object.Visibility = False base_object.Label = base_object.Label + "-" + wall.Label - self.importer.add_wall(wall) + self.importer.add_wall(floor, wall) def _get_sibling_wall(self, parent, wall, sibling_attribute_name): sibling_wall_id = wall.get(sibling_attribute_name, None) @@ -1021,11 +1215,32 @@ class WallHandler(BaseHandler): return sibling_wall def _set_properties(self, obj, elm): + + top_color = elm.get('topColor', self.importer.preferences["DEFAULT_FLOOR_COLOR"]) + left_side_color = elm.get('leftSideColor', self.importer.preferences["DEFAULT_FLOOR_COLOR"]) + right_side_color = elm.get('rightSideColor', self.importer.preferences["DEFAULT_FLOOR_COLOR"]) + self.setp(obj, "App::PropertyString", "shType", "The element type", 'wall') self.setp(obj, "App::PropertyString", "id", "The wall's id", elm) self.setp(obj, "App::PropertyString", "wallAtStart", "The Id of the contiguous wall at the start of this wall", elm) self.setp(obj, "App::PropertyString", "wallAtEnd", "The Id of the contiguous wall at the end of this wall", elm) self.setp(obj, "App::PropertyString", "pattern", "The pattern of this wall in plan view", elm) + self.setp(obj, "App::PropertyString", "topColor", "The wall inner color", top_color) + self.setp(obj, "App::PropertyString", "leftSideColor", "The wall inner color", left_side_color) + self.setp(obj, "App::PropertyPercent","leftSideShininess", "The room's ceiling shininess", percent_sh2fc(elm.get('leftSideShininess', 0))) + self.setp(obj, "App::PropertyString", "rightSideColor", "The wall inner color", right_side_color) + self.setp(obj, "App::PropertyPercent","rightSideShininess", "The room's ceiling shininess", percent_sh2fc(elm.get('rightSideShininess', 0))) + + def _set_baseboard_properties(self, obj, elm): + # Baseboard are a little bit special: + # Since their placement and other characteristics are dependant of + # the wall elements to be created (such as Door&Windows), their + # creation is delayed until the + for baseboard in elm.findall('baseboard'): + side = baseboard.get('attribute') + self.setp(obj, "App::PropertyQuantity", f"{side}Thickness", f"The thickness of the {side} baseboard", dim_sh2fc(float(baseboard.get("thickness")))) + self.setp(obj, "App::PropertyQuantity", f"{side}Height", f"The height of the {side} baseboard", dim_sh2fc(float(baseboard.get("height")))) + self.setp(obj, "App::PropertyString", f"{side}Color", f"The color of the {side} baseboard", baseboard.get("color")) def _create_wall(self, floor, prev, next, elm): """Create an Arch::Structure from an SH3D Element. @@ -1070,7 +1285,7 @@ class WallHandler(BaseHandler): # object based on ruled surface instead. # See https://github.com/FreeCAD/FreeCAD/issues/18658 and related OCCT # ticket - if (sweep.Shape.isNull() or not sweep.Shape.isValid()): + if sweep.Shape.isNull() or not sweep.Shape.isValid(): if is_wall_straight: _log(f"Sweep's shape is invalid, using ruled surface instead ...") App.ActiveDocument.removeObject(sweep.Label) @@ -1082,13 +1297,13 @@ class WallHandler(BaseHandler): else: wall = Arch.makeWall(sweep) - # Keep track of base object. Used for baseboard import + # Keep track of base objects. Used to decorate walls self.importer.set_property(wall, "App::PropertyLinkList", "BaseObjects", "The different base objects whose sweep failed. Kept for compatibility reasons", [section_start, section_end, spine]) # TODO: Width is incorrect when joining walls - wall.setExpression('Length', f'{spine.Label}.Length') - wall.setExpression('Width', f'({section_start.Label}.Length + {section_end.Label}.Length) / 2') - wall.setExpression('Height', f'({section_start.Label}.Height + {section_end.Label}.Height) / 2') + wall.setExpression('Length', f'{spine.Name}.Length') + wall.setExpression('Width', f'({section_start.Name}.Length + {section_end.Name}.Length) / 2') + wall.setExpression('Height', f'({section_start.Name}.Height + {section_end.Name}.Height) / 2') return wall, base_object @@ -1104,7 +1319,7 @@ class WallHandler(BaseHandler): Part::Sweep: the Part::Sweep """ App.ActiveDocument.recompute([section_start, section_end, spine]) - sweep = App.ActiveDocument.addObject('Part::Sweep') + sweep = App.ActiveDocument.addObject('Part::Sweep', "WallShape") sweep.Sections = [section_start, section_end] sweep.Spine = spine sweep.Solid = True @@ -1137,7 +1352,7 @@ class WallHandler(BaseHandler): compound.Links = [ruled_surface, section_start, section_end, spine] compound.recompute() - compound_solid = App.ActiveDocument.addObject("Part::Feature") + compound_solid = App.ActiveDocument.addObject("Part::Feature", "WallShape") compound_solid.Shape = Part.Solid(Part.Shell(compound.Shape.Faces)) return compound_solid, compound @@ -1170,11 +1385,6 @@ class WallHandler(BaseHandler): height_start = dim_sh2fc(elm.get('height', dim_fc2sh(floor.Height))) height_end = dim_sh2fc(elm.get('heightAtEnd', dim_fc2sh(height_start))) - # NOTE: the wall height is adjusted with the floor thickness - # BUG: It should be adjusted for all floor except the last one. - height_start = height_start + floor.floorThickness - height_end = height_end + floor.floorThickness - start = coord_sh2fc(App.Vector(x_start, y_start, z)) end = coord_sh2fc(App.Vector(x_end, y_end, z)) @@ -1197,6 +1407,7 @@ class WallHandler(BaseHandler): section_end = self._get_section(wall_details, False, next_wall_details) spine = Draft.makeLine(start, end) + spine.Label = f"Spine" App.ActiveDocument.recompute([section_start, section_end, spine]) if self.importer.preferences["DEBUG"]: _log(f"_create_straight_segment(): wall {self._pv(start)}->{self._pv(end)} => section_start={self._ps(section_start)}, section_end={self._ps(section_end)}") @@ -1237,7 +1448,12 @@ class WallHandler(BaseHandler): # The Length property is used in the Wall to calculate volume, etc... # Since make Circle does not calculate this Length I calculate it here... self.importer.set_property(spine, "App::PropertyFloat", "Length", "The length of the Arc", length, group="Draft") + # The Start and End property are used in the Wall to determine Facebinders + # characteristics... + self.importer.set_property(spine, "App::PropertyVector", "Start", "The start point of the Arc", start, group="Draft") + self.importer.set_property(spine, "App::PropertyVector", "End", "The end point of the Arc", end, group="Draft") + spine.Label = f"Spine" App.ActiveDocument.recompute([section_start, section_end, spine]) if self.importer.preferences["DEBUG"]: _log(f"_create_curved_segment(): wall {self._pv(start)}->{self._pv(end)} => section_start={self._ps(section_start)}, section_end={self._ps(section_end)}") @@ -1301,6 +1517,7 @@ class WallHandler(BaseHandler): section.recompute() _color_section(section) + section.Label = "Section-start" if at_start else "Section-end" return section def _get_intersection_edge(self, lside, rside, sibling_lside, sibling_rside): @@ -1359,7 +1576,7 @@ class WallHandler(BaseHandler): # We take the center that preserve the arc_extent orientation (in FC # coordinate). The orientation is calculated from start to end center = circles[0].Center - if numpy.sign(arc_extent) != numpy.sign(DraftVecUtils.angle(start-center, end-center, Z_NORM)): + if np.sign(arc_extent) != np.sign(DraftVecUtils.angle(start-center, end-center, Z_NORM)): invert_angle = True center = circles[1].Center @@ -1410,85 +1627,87 @@ class WallHandler(BaseHandler): """ return (b - a).cross(c - a).normalize() - def _ps(self, section, print_z: bool = False): - # Pretty print a Section in a condensed way - if hasattr(section, 'Shape'): - v = section.Shape.Vertexes - else: - # a Part.Face - v = section.Vertexes - return f"[{self._pv(v[0].Point, print_z)}, {self._pv(v[1].Point, print_z)}, {self._pv(v[2].Point, print_z)}, {self._pv(v[3].Point, print_z)}]" + def post_process(self, obj): + if self.importer.preferences["DECORATE_SURFACES"]: + floor = App.ActiveDocument.getObject(obj.ReferenceFloorName) - def _pe(self, edge, print_z: bool = False): - # Print an Edge in a condensed way - v = edge.Vertexes - return f"[{self._pv(v[0].Point, print_z)}, {self._pv(v[1].Point, print_z)}]" + (left_face_name, left_face, right_face_name, right_face) = self._get_faces(obj) - def _pv(self, v, print_z: bool = False, ndigits: None = None): - # Print an Vector in a condensed way - if hasattr(v,'X'): - return f"({round(getattr(v, 'X'), ndigits)},{round(getattr(v, 'Y'), ndigits)}{',' + str(round(getattr(v, 'Z'), ndigits)) if print_z else ''})" - elif hasattr(v,'x'): - return f"({round(getattr(v, 'x'), ndigits)},{round(getattr(v, 'y'), ndigits)}{',' + str(round(getattr(v, 'z'), ndigits)) if print_z else ''})" - raise ValueError(f"Expected a Point or Vector, got {type(v)}") + self._create_facebinders(floor, obj, left_face_name, right_face_name) - def _create_facebinders(self, floor, wall, elm): + self._create_baseboards(floor, obj, left_face, right_face) + + def _create_facebinders(self, floor, wall, left_face_name, right_face_name): """Set the wall's colors taken from `elm`. Creates 2 FaceBinders (left and right) and sets the corresponding color and the shininess of the wall. Args: + floor (Arch::Level): the level the wall belongs to. Used to group + the resulting Facebinders wall (Arch::Wall): the wall to paint elm (Element): the xml element for the wall to be imported + left_face_name (str): the name of the left face suitable for selecting + right_face_name (str): the name of the right face suitable for selecting """ # The top color is the color of the "mass" of the wall - top_color = elm.get('topColor', self.importer.preferences["DEFAULT_FLOOR_COLOR"]) + top_color = wall.topColor set_color_and_transparency(wall, top_color) + self._create_facebinder(floor, wall,left_face_name, "left") + self._create_facebinder(floor, wall, right_face_name, "right") - left_facebinder = Draft.make_facebinder(( wall, ("Face2", ) )) - left_facebinder.Extrusion = 1 - left_facebinder.Label = wall.Label + "-fb-left" - left_side_color = elm.get('leftSideColor', top_color) - set_color_and_transparency(left_facebinder, left_side_color) - left_side_shininess = elm.get('leftSideShininess', 0) - set_shininess(left_facebinder, left_side_shininess) - floor.getObject(floor.FacebinderGroupName).addObject(left_facebinder) + def _create_facebinder(self, floor, wall, face_name, side): + if face_name: + facebinder_id = f"{wall.id}-{side}-facebinder" + facebinder = None + if self.importer.preferences["MERGE"]: + facebinder = self.get_fc_object(facebinder_id, 'facebinder') - right_facebinder = Draft.make_facebinder(( wall, ("Face4", ) )) - right_facebinder.Extrusion = 1 - right_facebinder.Label = wall.Label + "-fb-right" - right_side_color = elm.get('rightSideColor', top_color) - set_color_and_transparency(right_facebinder, right_side_color) - right_side_shininess = elm.get('rightSideShininess', 0) - set_shininess(right_facebinder, right_side_shininess) - floor.getObject(floor.FacebinderGroupName).addObject(right_facebinder) + if not facebinder: + facebinder = Draft.make_facebinder(( wall, (face_name, ) )) + facebinder.Extrusion = 1 + facebinder.Label = wall.Label + f" {side} side finish" - def _import_baseboard(self, floor, wall, elm): + color = getattr(wall, f"{side}SideColor") + set_color_and_transparency(facebinder, color) + shininess = getattr(wall, f"{side}SideShininess", 0) + set_shininess(facebinder, shininess) + self.setp(facebinder, "App::PropertyString", "shType", "The element type", 'facebinder') + self.setp(facebinder, "App::PropertyString", "id", "The element's id", facebinder_id) + self.setp(facebinder, "App::PropertyString", "ReferenceWallName", "The element's wall Name", wall.Name) + + floor.getObject(floor.DecorationWallsGroupName).addObject(facebinder) + else: + _wrn(f"Failed to determine {side} face for wall {wall.Label}!") + + def _create_baseboards(self, floor, wall, left_face, right_face): """Creates and returns a Part::Extrusion from the imported_baseboard object Args: floor (Slab): the Slab the wall belongs to wall (Wall): the Arch wall - elm (Element): the wall being imported + elm (Element): the wall being imported (with child baseboards) + left_face (Part.Face): the left hand side of the wall + right_face (Part.Face): the right hand side of the wall Returns: Part::Extrusion: the newly created object """ - wall_width = float(wall.Width) + for side in ["leftSideBaseboard", "rightSideBaseboard"]: + if hasattr(wall, f"{side}Height"): + face = left_face if side == "leftSideBaseboard" else right_face + self._create_baseboard(floor, wall, side, face) - baseboard_width = dim_sh2fc(elm.get('thickness')) - baseboard_height = dim_sh2fc(elm.get('height')) + def _create_baseboard(self, floor, wall, side, face): - # This is brittle in case the wall is merged and the there are already - # some doors, windows, etc... - side = elm.get('attribute') - faces = wall.Base.Shape.Faces - face = faces[1] if side == 'leftSideBaseboard' else faces[3] + baseboard_width = getattr(wall, f"{side}Thickness").Value + baseboard_height = getattr(wall, f"{side}Height").Value # Once I have the face, I get the lowest edge. lowest_z = float('inf') bottom_edge = None + for edge in face.Edges: if edge and edge.CenterOfMass and edge.CenterOfMass.z < lowest_z: lowest_z = edge.CenterOfMass.z @@ -1512,16 +1731,16 @@ class WallHandler(BaseHandler): for edge in [edge0, edge1, edge2, edge3]: edge.Vertexes[0].Point.z = edge.Vertexes[1].Point.z = ref_z - baseboard_id = f"{wall.id}-{side}" + baseboard_id = f"{wall.id} {side}" baseboard = None if self.importer.preferences["MERGE"]: baseboard = self.get_fc_object(baseboard_id, 'baseboard') if not baseboard: - base = App.ActiveDocument.addObject("Part::Feature", "baseboard-base") + base = App.ActiveDocument.addObject("Part::Feature", f"{wall.Label} {side} base") base.Shape = Part.makeFace([ Part.Wire([edge0, edge1, edge2, edge3]) ]) base.Visibility = False - baseboard = App.ActiveDocument.addObject('Part::Extrusion', f"{wall.Label}-{side}") + baseboard = App.ActiveDocument.addObject('Part::Extrusion', f"{wall.Label} {side}") baseboard.Base = base baseboard.DirMode = "Custom" @@ -1535,23 +1754,79 @@ class WallHandler(BaseHandler): baseboard.TaperAngle = 0 baseboard.TaperAngleRev = 0 - set_color_and_transparency(baseboard, elm.get('color')) + set_color_and_transparency(baseboard, getattr(wall, f"{side}Color")) self.setp(baseboard, "App::PropertyString", "shType", "The element type", 'baseboard') self.setp(baseboard, "App::PropertyString", "id", "The element's id", baseboard_id) - self.setp(baseboard, "App::PropertyLink", "parent", "The element parent", wall) + self.setp(baseboard, "App::PropertyString", "ReferenceWallName", "The element's wall Name", wall.Name) baseboard.recompute(True) + floor.getObject(floor.DecorationBaseboardsGroupName).addObject(baseboard) - space = self.get_space(floor, baseboard.Shape.BoundBox.Center) - if space: - space.Group = space.Group + [baseboard] - else: - _log(f"No space found to enclose {baseboard.Label}. Adding to generic group.") - floor.getObject(floor.BaseboardGroupName).addObject(baseboard) + def _get_faces(self, wall): + """Returns the name of the left and right face for `wall` - # Returns the Space for the wall to be added to the space.Boundaries - return space + The face names are suitable for selection later on when creating + the Facebinders and baseboards. Note, that this must be executed + once the wall has been completely constructed. If a window or + door is added afterward, this will have an impact on what is + considered the left and right side of the wall + + Args: + wall (Arch.Wall): the wall for which we have to determine + the left and right side. + + Returns: + tuple: a tuple of string containing the name of the left and + right side of the wall + """ + # In order to handle curved walls, take the oriented line (from + # start to end) that pass through the center of gravity of the wall + # Hopefully the COG of the face will always be on the correct side + # of the COG of the wall + wall_start = wall.BaseObjects[2].Start + wall_end = wall.BaseObjects[2].End + wall_cog_start = wall.Shape.CenterOfGravity + wall_cog_end = wall_cog_start + wall_end - wall_start + + left_face_name = right_face_name = None + left_face = right_face = None + for (i, face) in enumerate(wall.Shape.Faces): + face_cog = face.CenterOfGravity + + # The face COG is not on the same z as the wall COG + # just skipping. + if not math.isclose(face_cog.z, wall_cog_start.z, abs_tol=1): + continue + + side = self._get_face_side(wall_cog_start, wall_cog_end, face_cog) + # NOTE: face names start at 1... + if side > 0: + left_face_name = f"Face{i+1}" + left_face = face + elif side < 0: + right_face_name = f"Face{i+1}" + right_face = face + if left_face_name and right_face_name: + # Optimization. Is it always true? + break + return (left_face_name, left_face, right_face_name, right_face) + + def _get_face_side(self, start:App.Vector, end:App.Vector, cog:App.Vector): + # Compute vectors + ab = end - start # Vector from start to end + ac = cog - start # Vector from start to CenterOfGravity + + ab.z = 0 + ac.z = 0 + + # Compute the cross product (z-component is enough for 2D test) + cross_z = ab.x * ac.y - ab.y * ac.x + + # Determine the position of point cog + if math.isclose(cross_z, 0, abs_tol=1): + return 0 + return cross_z class BaseFurnitureHandler(BaseHandler): @@ -1594,7 +1869,7 @@ class BaseFurnitureHandler(BaseHandler): self.setp(obj, "App::PropertyBool", "deformable", "Whether the object is deformable", elm) self.setp(obj, "App::PropertyBool", "texturable", "Whether the object is texturable", elm) self.setp(obj, "App::PropertyString", "staircaseCutOutShape", "", elm) - self.setp(obj, "App::PropertyFloat", "shininess", "The object's shininess", elm) + self.setp(obj, "App::PropertyPercent", "shininess", "The object's shininess", percent_sh2fc(elm.get('shininess', 0))) self.setp(obj, "App::PropertyFloat", "valueAddedTaxPercentage", "The object's VAT percentage", elm) self.setp(obj, "App::PropertyString", "currency", "The object's price currency", str(elm.get('currency', 'EUR'))) @@ -1687,7 +1962,7 @@ class DoorOrWindowHandler(BaseFurnitureHandler): center = coord_sh2fc(App.Vector(x_center, y_center, z_center)) center.z += floor.Placement.Base.z - # First create a solid representing the window countour and find the + # First create a solid representing the window contour and find the # walls containing that window width = dim_sh2fc(elm.get('width')) depth = dim_sh2fc(elm.get('depth')) @@ -1696,18 +1971,27 @@ class DoorOrWindowHandler(BaseFurnitureHandler): corner = center.add(App.Vector(-width/2, -depth/2, -height/2)) + # Then create a box that represent the BoundingBox of the windows + # to find out which wall contains the window. solid = Part.makeBox(width, depth, height) solid.rotate(solid.CenterOfMass, Z_NORM, math.degrees(ang_sh2fc(angle))) solid.translate(corner) # Get all the walls hosting that door/window... wall_width = -DEFAULT_WALL_WIDTH - walls = self._get_containing_walls(solid) + walls = self._get_containing_walls(floor, solid) if len(walls) == 0: _err(f"Missing wall for {elm.get('id')}. Defaulting to width {DEFAULT_WALL_WIDTH} ...") else: - wall_width = walls[0].Width - + # NOTE: + # The main host (the one defining the width of the door/window) is + # the one that contains the CenterOfMass of the windows, or maybe + # the one that has the same normal? + wall_width = float(walls[0].Width) + com = solid.CenterOfMass + for wall in walls: + if wall.Shape.isInside(com, 1, False): + wall_width = float(wall.Width) center2corner = App.Vector(-width/2, -wall_width/2, 0) rotation = App.Rotation(Z_NORM, math.degrees(ang_sh2fc(angle))) @@ -1730,13 +2014,14 @@ class DoorOrWindowHandler(BaseFurnitureHandler): (windowtype, ifc_type) = ('Simple door', 'Door') # See the https://wiki.freecad.org/Arch_Window for details about these values - h1 = 50 - h2 = 50 - h3 = 50 - o1 = 40 - w1 = float(wall_width)-o1 # make sure the door takes the whole wall (facebinder+baseboard) - w2 = 40 - o2 = (w1-w2) / 2 + # Only using Opening / Fixed / Simple Door + h1 = min(50,height*.025) # 2.5% of frame + h2 = h1 + h3 = 0 + w1 = wall_width + w2 = min(20.0,wall_width*.2) # 20% of width + o1 = 0 + o2 = (wall_width-w2)/2 window = Arch.makeWindowPreset(windowtype, width, height, h1, h2, h3, w1, w2, o1, o2, pl) window.IfcType = ifc_type @@ -1752,10 +2037,11 @@ class DoorOrWindowHandler(BaseFurnitureHandler): window.Hosts = walls return window - def _get_containing_walls(self, solid): + def _get_containing_walls(self, floor, solid): """Returns the wall(s) intersecting with the door/window. Args: + floor (Arch.Level): the level the solid must belongs to solid (Part.Solid): the solid to test against each wall's bounding box @@ -1763,7 +2049,7 @@ class DoorOrWindowHandler(BaseFurnitureHandler): list(Arch::Wall): the wall(s) containing the given solid """ host_walls = [] - for wall in self.importer.get_walls(): + for wall in self.importer.get_walls(floor): if solid.common(wall.Shape).Volume > 0: host_walls.append(wall) return host_walls @@ -1821,7 +2107,7 @@ class FurnitureHandler(BaseFurnitureHandler): # We add the object to the list of known object that can then # be referenced elsewhere in the SH3D model (i.e. lights). - self.importer.fc_objects[feature.id] = feature + self.importer.add_fc_objects(feature) def _create_equipment(self, floor, elm): width = dim_sh2fc(float(elm.get('width'))) @@ -1852,7 +2138,7 @@ class FurnitureHandler(BaseFurnitureHandler): App.Vector(rij[3], rij[4], rij[5]), App.Vector(rij[6], rij[7], rij[8]) ) - _msg(f"model_rotation is not yet implemented ...") + _msg(f"{elm.get('id')}: modelRotation is not yet implemented ...") transform.scale(width/bb.XLength, height/bb.YLength, depth/bb.ZLength) # NOTE: the model is facing up, thus y and z are inverted transform.rotateX(math.pi/2) @@ -2093,8 +2379,17 @@ def _color_section(section): def set_shininess(obj, shininess): + # TODO: it seems a shininess of 0 means the wall looses its + # color. We'll leave it at the default setting until a later time + return if not App.GuiUp or not shininess: return - if hasattr(obj.ViewObject, "Shininess"): - # Shininess goes from 0 -> 0.25 in SH3d and 0 -> 100 in FC - obj.ViewObject.Shininess = int((100*shininess)/0.25) + if hasattr(obj.ViewObject, "ShapeAppearance"): + mat = obj.ViewObject.ShapeAppearance[0] + mat.Shininess = float(shininess)/100 + obj.ViewObject.ShapeAppearance = mat + + +def percent_sh2fc(percent): + # percent goes from 0 -> 1 in SH3d and 0 -> 100 in FC + return int(float(percent)*100) diff --git a/src/Mod/BIM/importers/importWebGL.py b/src/Mod/BIM/importers/importWebGL.py index b1ce15cd45..d84b241fce 100644 --- a/src/Mod/BIM/importers/importWebGL.py +++ b/src/Mod/BIM/importers/importWebGL.py @@ -70,6 +70,7 @@ import numpy as np disableCompression = False # Compress object data before sending to JS base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!#$%&()*+-:;/=>?@[]^_,.{|}~`" # safe str chars for js in all cases baseFloat = ",.-0123456789" +threejs_version = "0.172.0" def getHTMLTemplate(): @@ -110,23 +111,31 @@ def getHTMLTemplate(): select { width: 170px; } +