diff --git a/3rdparty/README.md b/3rdparty/README.md index 91e93aa228..6ece08adc2 100644 --- a/3rdparty/README.md +++ b/3rdparty/README.md @@ -1,238 +1,242 @@ = CMake external projects to build krita's dependencies on Linux, Windows or OSX = If you need to build Krita's dependencies for the following reasons: * you develop on Windows and aren't using Emerge * you develop on OSX and aren't using Homebrew * you want to build a generic, distro-agnostic version of Krita for Linux * you develop on Linux, but some dependencies aren't available for your distribution and you know what you're doing, you can use the following guide to build the dependencies that Krita needs. If you develop on Linux and your distribution has the dependencies available, YOU DO NOT NEED THIS GUIDE AND YOU SHOULD STOP READING NOW Otherwise you risk major confusion. == Prerequisites == Note: on all operating systems the entire procedure is done in a terminal window. 1. git: https://git-scm.com/downloads. Make sure git is in your path 2. cmake 3.3.2: https://cmake.org/download/. Make sure cmake is in your path. 3. Make sure you have a compiler: * Linux: gcc, minimum version 4.8 * OSX: clang, you need to install xcode for this * Windows: (http://tdm-gcc.tdragon.net/, version 5.1). MSVC cannot build G'Mic correctly. Remember to install the OpenMP plugin in tdm-gcc. Make sure mingw's bin folder is in your path. 4. If you compile Qt on Windows, you will also need Python: https://www.python.org. Make sure to have python.exe in your path. == Setup your environment == == Prepare your directory layout == 1. Make a toplevel build directory, say $HOME/dev or c:\dev. We'll refer to this directory as BUILDROOT. You can use a variable for this, on WINDOWS %BUILDROOT%, on OSX and Linux $BUILDROOT. You will have to replace BUILDROOT with $BUILDROOT or %BUILDROOT whenever you copy and paste a command, depending on your operating system. 2. Checkout krita in BUILDROOT cd BUILDROOT git clone git://anongit.kde.org/krita.git 3. Create the build directory mkdir BUILDROOT/b 4. Create the downloads directory mkdir BUILDROOT/d 5. Create the install directory mkdir BUILDROOT/i == Prepare the externals build == 1. enter the BUILDROOT/b directory 2. run cmake: * Linux: export PATH=$BUILDROOT/i/bin export PYTHONHOME=$BUILDROOT/i (only if you want to build your own python) cmake ../krita/3rdparty \ -DINSTALL_ROOT=$BUILDROOT/i \ -DEXTERNALS_DOWNLOAD_DIR=$BUILDROOT/d \ -DCMAKE_INSTALL_PREFIX=BUILDROOT/i * OSX: export PATH=$BUILDROOT/i/bin export PYTHONHOME=$BUILDROOT/i (only if you want to build your own python) cmake ../krita/3rdparty/ \ -DCMAKE_INSTALL_PREFIX=$BUILDROOT/i \ -DEXTERNALS_DOWNLOAD_DIR=$BUILDROOT/d \ -DINSTALL_ROOT=$BUILDROOT/i * Windows 32 bits: TODO * Windows 64 bits: Note that the cmake command needs to point to your BUILDROOT like /dev/d, not c:\dev\d. set PATH=%BUILDROOT%\i\bin\;%BUILDROOT%\i\lib;%PATH% set PYTHONHOME=%BUILDROOT%/i (only if you want to build your own python) set PATH=BUILDROOT\i\bin\;BUILDROOT\i\lib;%PATH% cmake ..\krita\3rdparty -DEXTERNALS_DOWNLOAD_DIR=/dev/d -DINSTALL_ROOT=/dev/i -G "MinGW Makefiles" 3. build the packages: With a judicious application of DEPENDS statements, it's possible to build it all in one go, but in my experience that fails always, so it's better to build the dependencies independently. If you want to use the included version of Python (can be used on Windows to build Qt instead of installing Python separately): cmake --build . --config RelWithDebInfo --target ext_python On Windows: cmake --build . --config RelWithDebInfo --target ext_patch cmake --build . --config RelWithDebInfo --target ext_png2ico cmake --build . --config RelWithDebInfo --target ext_gettext On all operating systems: cmake --build . --config RelWithDebInfo --target ext_qt cmake --build . --config RelWithDebInfo --target ext_zlib cmake --build . --config RelWithDebInfo --target ext_boost Note about boost: check if the headers are installed into i/include/boost, but not into i/include/boost-1.61/boost cmake --build . --config RelWithDebInfo --target ext_eigen3 cmake --build . --config RelWithDebInfo --target ext_exiv2 cmake --build . --config RelWithDebInfo --target ext_fftw3 On Windows: set FFTW_LIB_DIR=%BUILDROOT%\i\lib dlltool.exe -k --output-lib %FFTW_LIB_DIR%\libfftw3-3.a --input-def %FFTW_LIB_DIR%\libfftw3-3.def dlltool.exe -k --output-lib %FFTW_LIB_DIR%\libfftw3f-3.a --input-def %FFTW_LIB_DIR%\libfftw3f-3.def dlltool.exe -k --output-lib %FFTW_LIB_DIR%\libfftw3l-3.a --input-def %FFTW_LIB_DIR%\libfftw3l-3.def On all operating systems cmake --build . --config RelWithDebInfo --target ext_ilmbase cmake --build . --config RelWithDebInfo --target ext_jpeg cmake --build . --config RelWithDebInfo --target ext_lcms2 cmake --build . --config RelWithDebInfo --target ext_ocio cmake --build . --config RelWithDebInfo --target ext_openexr Note for OSX: On OSX, you need to first build openexr; that will fail; then you need to set the rpath for the two utilities correctly, then try to build openexr again. install_name_tool -add_rpath $BUILD_ROOT/i/lib $BUILD_ROOT/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./b44ExpLogTable install_name_tool -add_rpath $BUILD_ROOT/i/lib $BUILD_ROOT/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./dwaLookups On All operating systems: cmake --build . --config RelWithDebInfo --target ext_png cmake --build . --config RelWithDebInfo --target ext_tiff cmake --build . --config RelWithDebInfo --target ext_gsl cmake --build . --config RelWithDebInfo --target ext_vc cmake --build . --config RelWithDebInfo --target ext_libraw On Windows cmake --build . --config RelWithDebInfo --target ext_freetype cmake --build . --config RelWithDebInfo --target ext_poppler On Linux cmake --build . --config RelWithDebInfo --target ext_kcrash Everywhere else: cmake --build . --config RelWithDebInfo --target ext_kwindowsystem +On Windows, if you want to include DrMingw for dumping backtrace on crash: + + cmake --build . --config RelWithDebInfo --target ext_drmingw + Note: poppler should be buildable on Linux as well with a home-built freetype and fontconfig, but I don't know how to make fontconfig find freetype, and on Linux, fontconfig is needed for poppler. Poppler is needed for PDF import. Note 2: libcurl still isn't available. Note 3: if you want to build a release, you need to get the binary gettext archives from files.kde.org/krita/build/dependencies: http://files.kde.org/krita/build/dependencies/gettext0.19.8.1-iconv1.14-shared-32.zip http://files.kde.org/krita/build/dependencies/gettext0.19.8.1-iconv1.14-shared-64.zip Take care, these zips contain a libstdc++-6.dll that you don't want in your path when building. == Build Krita == 1. Make a krita build directory: mkdir BUILDROOT/build 2. Enter the BUILDROOT/build 3. Run On Windows Depending on what you want to use, run this command for MSBuild: cmake ..\krita -G "MinGW Makefiles" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -DPACKAGERS_BUILD=ON -Wno-dev -DDEFINE_NO_DEPRECATED=1 Or this to use jom (faster compiling, uses all cores, ships with QtCreator/pre-built Qt binaries): cmake ..\krita -G "MinGW Makefiles" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -DPACKAGERS_BUILD=ON -Wno-dev -DDEFINE_NO_DEPRECATED=1 On Linux cmake ../krita -DCMAKE_INSTALL_PREFIX=BUILDROOT/i -DDEFINE_NO_DEPRECATED=1 -DPACKAGERS_BUILD=ON -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfobg On OSX cmake ../krita -DCMAKE_INSTALL_PREFIX=/Users/boud/dev/i -DDEFINE_NO_DEPRECATED=1 -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DPACKAGERS_BUILD=ON -DBUNDLE_INSTALL_DIR=$HOME/dev/i/bin -DCMAKE_BUILD_TYPE=RelWithDebInfo 4. Run On Linux and OSX make make install On Windows Either use MSBuild to build (-- /m tells msbuild to use all your cores): cmake --build . --config RelWithDebInfo --target INSTALL -- /m Or use jom which should be in a path similar to C:\Qt\Qt5.6.0\Tools\QtCreator\bin\jom.exe. So, from the same folder, instead of running cmake run: "C:\Qt\Qt5.6.0\Tools\QtCreator\bin\jom.exe" install 6. Run krita: On Linux BUILDROOT/i/bin/krita On Windows BUILDROOT\i\bin\krita.exe On OSX BUILDROOT/i/bin/krita.app/Contents/MacOS/krita == Packaging a Windows Build == If you want to create a stripped down version of Krita to distribute, after building everything just copy the makepkg.bat file from the "windows" folder inside krita root source folder to BUILDROOT and run it. That will copy the necessary files into the specified folder and leave behind developer related files, so the resulting folder will be a smaller install folder. == Common Issues == - On Windows, if you get a 'mspdb140.dll' missing alert window, it means you did not run the bat file. Make sure to include the quotes in the command: "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" - On Windows, if you get an error about Qt5Core.dll missing/not found or nmake exit with an error that mention QT_PLUGIN_PATH, you have to copy a couple of dlls in the Qt build directory, look for the N.B. in the Qt instructions at the start of the Readme. - If you receive an error while compiling about "missing QtCore5.cmake", or something similar, check to make sure qmake is in your PATH. Restart your command line after any changes are made. diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fd1b3c1d4..3a26d22aa2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,730 +1,654 @@ project(krita) message(STATUS "Using CMake version: ${CMAKE_VERSION}") cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) set(MIN_QT_VERSION 5.6.0) option(OVERRIDE_QT_VERSION "Use this to make it possible to build with Qt < 5.6.0. There will be bugs." OFF) if (OVERRIDE_QT_VERSION) set(MIN_QT_VERSION 5.4.0) endif() set(MIN_FRAMEWORKS_VERSION 5.7.0) if (POLICY CMP0002) cmake_policy(SET CMP0002 OLD) endif() if (POLICY CMP0017) cmake_policy(SET CMP0017 NEW) endif () if (POLICY CMP0022) cmake_policy(SET CMP0022 OLD) endif () if (POLICY CMP0026) cmake_policy(SET CMP0026 OLD) endif() if (POLICY CMP0042) cmake_policy(SET CMP0042 NEW) endif() if (POLICY CMP0046) cmake_policy(SET CMP0046 OLD) endif () if (POLICY CMP0059) cmake_policy(SET CMP0059 OLD) endif() if (POLICY CMP0063) cmake_policy(SET CMP0063 OLD) endif() if (POLICY CMP0054) cmake_policy(SET CMP0054 OLD) endif() if (POLICY CMP0064) cmake_policy(SET CMP0064 OLD) endif() if (APPLE) set(APPLE_SUPPRESS_X11_WARNING TRUE) set(KDE_SKIP_RPATH_SETTINGS TRUE) set(CMAKE_MACOSX_RPATH 1) set(BUILD_WITH_INSTALL_RPATH 1) add_definitions(-mmacosx-version-min=10.9 -Wno-deprecated-register) endif() ###################### ####################### ## Constants defines ## ####################### ###################### # define common versions of Krita applications, used to generate kritaversion.h # update these version for every release: set(KRITA_VERSION_STRING "3.0.92") set(KRITA_STABLE_VERSION_MAJOR 3) # 3 for 3.x, 4 for 4.x, etc. set(KRITA_STABLE_VERSION_MINOR 0) # 0 for 3.0, 1 for 3.1, etc. set(KRITA_VERSION_RELEASE 91) # 89 for Alpha, increase for next test releases, set 0 for first Stable, etc. #set(KRITA_ALPHA 1) # uncomment only for Alpha set(KRITA_BETA 1) # uncomment only for Beta #set(KRITA_RC 1) # uncomment only for RC set(KRITA_YEAR 2016) # update every year if(NOT DEFINED KRITA_ALPHA AND NOT DEFINED KRITA_BETA AND NOT DEFINED KRITA_RC) set(KRITA_STABLE 1) # do not edit endif() message(STATUS "Krita version: ${KRITA_VERSION_STRING}") # Define the generic version of the Krita libraries here # This makes it easy to advance it when the next Krita release comes. # 14 was the last GENERIC_KRITA_LIB_VERSION_MAJOR of the previous Krita series # (2.x) so we're starting with 15 in 3.x series. if(KRITA_STABLE_VERSION_MAJOR EQUAL 3) math(EXPR GENERIC_KRITA_LIB_VERSION_MAJOR "${KRITA_STABLE_VERSION_MINOR} + 15") else() # let's make sure we won't forget to update the "15" message(FATAL_ERROR "Reminder: please update offset == 15 used to compute GENERIC_KRITA_LIB_VERSION_MAJOR to something bigger") endif() set(GENERIC_KRITA_LIB_VERSION "${GENERIC_KRITA_LIB_VERSION_MAJOR}.0.0") set(GENERIC_KRITA_LIB_SOVERSION "${GENERIC_KRITA_LIB_VERSION_MAJOR}") LIST (APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") LIST (APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/kde_macro") # fetch git revision for the current build set(KRITA_GIT_SHA1_STRING "") set(KRITA_GIT_BRANCH_STRING "") include(GetGitRevisionDescription) get_git_head_revision(GIT_REFSPEC GIT_SHA1) get_git_branch(GIT_BRANCH) if(GIT_SHA1 AND GIT_BRANCH) string(SUBSTRING ${GIT_SHA1} 0 7 GIT_SHA1) set(KRITA_GIT_SHA1_STRING ${GIT_SHA1}) set(KRITA_GIT_BRANCH_STRING ${GIT_BRANCH}) endif() if(NOT DEFINED RELEASE_BUILD) # estimate mode by CMAKE_BUILD_TYPE content if not set on cmdline string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_TOLOWER) set(RELEASE_BUILD_TYPES "release" "relwithdebinfo" "minsizerel") list(FIND RELEASE_BUILD_TYPES "${CMAKE_BUILD_TYPE_TOLOWER}" INDEX) if (INDEX EQUAL -1) set(RELEASE_BUILD FALSE) else() set(RELEASE_BUILD TRUE) endif() endif() message(STATUS "Release build: ${RELEASE_BUILD}") +# create test make targets +enable_testing() +# collect list of broken tests, empty here to start fresh with each cmake run +set(KRITA_BROKEN_TESTS "" CACHE INTERNAL "KRITA_BROKEN_TESTS") + ############ ############# ## Options ## ############# ############ include(FeatureSummary) option(PACKAGERS_BUILD "Build support of multiple CPU architectures in one binary. Should be used by packagers only or Krita developers. Only switch off when you're an artist optimizing a build for your very own machine." ON) add_feature_info("Packagers' Build" PACKAGERS_BUILD "Support several CPU arch in one binary. Recommended for packages. Switch this off to make a build for only your machine.") if (WIN32) option(USE_DRMINGW "Support the Dr. Mingw crash handler (only on windows)" ON) add_feature_info("Dr. Mingw" USE_DRMINGW "Enable the Dr. Mingw crash handler") + + if (MINGW) + option(USE_MINGW_HARDENING_LINKER "Enable DEP (NX), ASLR and high-entropy ASLR linker flags (mingw-w64)" ON) + add_feature_info("Linker Security Flags" USE_MINGW_HARDENING_LINKER "Enable DEP (NX), ASLR and high-entropy ASLR linker flags") + if (USE_MINGW_HARDENING_LINKER) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--dynamicbase -Wl,--nxcompat -Wl,--disable-auto-image-base") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--dynamicbase -Wl,--nxcompat -Wl,--disable-auto-image-base") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--dynamicbase -Wl,--nxcompat -Wl,--disable-auto-image-base") + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + # Enable high-entropy ASLR for 64-bit + # The image base has to be >4GB for HEASLR to be enabled. + # The values used here are kind of arbitrary. + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--high-entropy-va -Wl,--image-base,0x140000000") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--high-entropy-va -Wl,--image-base,0x180000000") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--high-entropy-va -Wl,--image-base,0x180000000") + endif ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + else (USE_MINGW_HARDENING_LINKER) + message(WARNING "Linker Security Flags not enabled!") + endif (USE_MINGW_HARDENING_LINKER) + endif (MINGW) endif () option(HIDE_SAFE_ASSERTS "Don't show message box for \"safe\" asserts, just ignore them automatically and dump a message to the terminal." ON) configure_file(config-hide-safe-asserts.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-hide-safe-asserts.h) add_feature_info("Safe Asserts" HIDE_SAFE_ASSERTS "Don't show message box for \"safe\" asserts, just ignore them automatically and dump a message to the terminal.") option(FOUNDATION_BUILD "A Foundation build is a binary release build that can package some extra things like color themes. Linux distributions that build and install Krita into a default system location should not define this option to true." OFF) add_feature_info("Foundation Build" FOUNDATION_BUILD "A Foundation build is a binary release build that can package some extra things like color themes. Linux distributions that build and install Krita into a default system location should not define this option to true.") - ####################### -######################## -## Productset setting ## -######################## -####################### - -# For predefined productsets see the definitions in KritaProducts.cmake and -# in the files in the folder cmake/productsets. +option(KRITA_ENABLE_BROKEN_TESTS "Enable tests that are marked as broken" OFF) +add_feature_info("Enable Broken Tests" KRITA_ENABLE_BROKEN_TESTS "Runs broken test when \"make test\" is invoked (use -DKRITA_ENABLE_BROKEN_TESTS=ON to enable).") -# Finding out the products & features to build is done in 5 steps: -# 1. have the user define the products/features wanted, by giving a productset -# 2. estimate all additional required products/features -# 3. estimate which of the products/features can be build by external deps -# 4. find which products/features have been temporarily disabled due to problems -# 5. estimate which of the products/features can be build by internal deps -# get the special macros -include(CalligraProductSetMacros) include(MacroJPEG) -include(GenerateTestExportHeader) - - -# get the definitions of products, features and product sets -include(KritaProducts.cmake) - -set(PRODUCTSET_DEFAULT "ALL") -# temporary migration support -if (CREATIVEONLY) - set(WARN_ABOUT_CREATIVEONLY TRUE) - set(PRODUCTSET_DEFAULT "CREATIVE") -endif () - -if(NOT PRODUCTSET) - set(PRODUCTSET ${PRODUCTSET_DEFAULT} CACHE STRING "Set of products/features to build" FORCE) -endif() - -if (RELEASE_BUILD) - set(CALLIGRA_SHOULD_BUILD_STAGING FALSE) -else () - set(CALLIGRA_SHOULD_BUILD_STAGING TRUE) -endif () - -# finally choose products/features to build -calligra_set_productset(${PRODUCTSET}) ######################## ######################### ## Look for KDE and Qt ## ######################### ######################## find_package(ECM 1.7.0 REQUIRED NOMODULE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include(ECMOptionalAddSubdirectory) include(ECMAddAppIcon) include(ECMSetupVersion) include(ECMMarkNonGuiExecutable) include(ECMGenerateHeaders) include(GenerateExportHeader) include(ECMMarkAsTest) include(ECMInstallIcons) include(CMakePackageConfigHelpers) include(WriteBasicConfigVersionFile) include(CheckFunctionExists) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings) # do not reorder to be alphabetical: this is the order in which the frameworks # depend on each other. find_package(KF5 ${MIN_FRAMEWORKS_VERSION} REQUIRED COMPONENTS Archive Config WidgetsAddons Completion CoreAddons GuiAddons I18n ItemModels ItemViews WindowSystem ) # KConfig deprecated authorizeKAction. In order to be warning free, # compile with the updated function when the dependency is new enough. # Remove this (and the uses of the define) when the minimum KF5 # version is >= 5.24.0. if (${KF5Config_VERSION} VERSION_LESS "5.24.0" ) message("Old KConfig (< 5.24.0) found.") add_definitions(-DKCONFIG_BEFORE_5_24) endif() find_package(Qt5 ${MIN_QT_VERSION} REQUIRED COMPONENTS Core Gui Widgets Xml Network PrintSupport Svg Test Concurrent ) include (MacroAddFileDependencies) include (MacroBoolTo01) include (MacroEnsureOutOfSourceBuild) macro_ensure_out_of_source_build("Compiling Krita inside the source directory is not possible. Please refer to the build instruction https://community.kde.org/Krita#Build_Instructions") # Note: OPTIONAL_COMPONENTS does not seem to be reliable # (as of ECM 5.15.0, CMake 3.2) if (NOT WIN32 AND NOT APPLE) find_package(Qt5 ${MIN_QT_VERSION} REQUIRED X11Extras) find_package(Qt5DBus ${MIN_QT_VERSION} QUIET) set(HAVE_DBUS ${Qt5DBus_FOUND}) set_package_properties(Qt5DBus PROPERTIES DESCRIPTION "Qt DBUS integration" URL "http://www.qt.io/" TYPE OPTIONAL PURPOSE "Optionally used to provide a dbus api on Linux") find_package(KF5KIO ${MIN_FRAMEWORKS_VERSION} QUIET) macro_bool_to_01(KF5KIO_FOUND HAVE_KIO) set_package_properties(KF5KIO PROPERTIES DESCRIPTION "KDE's KIO Framework" URL "http://api.kde.org/frameworks-api/frameworks5-apidocs/kio/html/index.html" TYPE OPTIONAL PURPOSE "Optionally used for recent document handling") find_package(KF5Crash ${MIN_FRAMEWORKS_VERSION} QUIET) macro_bool_to_01(KF5Crash_FOUND HAVE_KCRASH) set_package_properties(KF5Crash PROPERTIES DESCRIPTION "KDE's Crash Handler" URL "http://api.kde.org/frameworks-api/frameworks5-apidocs/kcrash/html/index.html" TYPE OPTIONAL PURPOSE "Optionally used to provide crash reporting on Linux") find_package(X11 REQUIRED COMPONENTS Xinput) set(HAVE_X11 TRUE) add_definitions(-DHAVE_X11) find_package(XCB COMPONENTS XCB ATOM) set(HAVE_XCB ${XCB_FOUND}) else() set(HAVE_DBUS FALSE) set(HAVE_X11 FALSE) set(HAVE_XCB FALSE) endif() add_definitions( -DQT_USE_QSTRINGBUILDER -DQT_STRICT_ITERATORS -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DQT_USE_FAST_OPERATOR_PLUS -DQT_USE_FAST_CONCATENATION -DQT_NO_URL_CAST_FROM_STRING -DQT_DISABLE_DEPRECATED_BEFORE=0 ) add_definitions(-DTRANSLATION_DOMAIN=\"krita\") # # The reason for this mode is that the Debug mode disable inlining # if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS_KRITADEVS "-O3 -g" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals") endif() if(UNIX) set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};m") endif() if(WIN32) if(MSVC) # C4522: 'class' : multiple assignment operators specified set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4522") endif() endif() # enable exceptions globally kde_enable_exceptions() # only with this definition will all the FOO_TEST_EXPORT macro do something # TODO: check if this can be moved to only those places which make use of it, # to reduce global compiler definitions that would trigger a recompile of # everything on a change (like adding/removing tests to/from the build) if(BUILD_TESTING) add_definitions(-DCOMPILING_TESTS) endif() set(KRITA_DEFAULT_TEST_DATA_DIR ${CMAKE_SOURCE_DIR}/sdk/tests/data/) macro(macro_add_unittest_definitions) add_definitions(-DFILES_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data/") add_definitions(-DFILES_OUTPUT_DIR="${CMAKE_CURRENT_BINARY_DIR}") add_definitions(-DFILES_DEFAULT_DATA_DIR="${KRITA_DEFAULT_TEST_DATA_DIR}") endmacro() # overcome some platform incompatibilities if(WIN32) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/winquirks) add_definitions(-D_USE_MATH_DEFINES) add_definitions(-DNOMINMAX) set(WIN32_PLATFORM_NET_LIBS ws2_32.lib netapi32.lib) endif() # set custom krita plugin installdir set(KRITA_PLUGIN_INSTALL_DIR ${LIB_INSTALL_DIR}/kritaplugins) ########################### ############################ ## Required dependencies ## ############################ ########################### find_package(PNG REQUIRED) if (APPLE) # this is not added correctly on OSX -- see http://forum.kde.org/viewtopic.php?f=139&t=101867&p=221242#p221242 include_directories(SYSTEM ${PNG_INCLUDE_DIR}) endif() add_definitions(-DBOOST_ALL_NO_LIB) find_package(Boost REQUIRED COMPONENTS system) # for pigment and stage include_directories(${Boost_INCLUDE_DIRS}) ## ## Test for GNU Scientific Library ## find_package(GSL) set_package_properties(GSL PROPERTIES URL "http://www.gnu.org/software/gsl" TYPE RECOMMENDED PURPOSE "Required by Krita's Transform tool.") macro_bool_to_01(GSL_FOUND HAVE_GSL) configure_file(config-gsl.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-gsl.h ) ########################### ############################ ## Optional dependencies ## ############################ ########################### ## ## Check for OpenEXR ## find_package(ZLIB) set_package_properties(ZLIB PROPERTIES DESCRIPTION "Compression library" URL "http://www.zlib.net/" TYPE OPTIONAL PURPOSE "Optionally used by the G'Mic and the PSD plugins") macro_bool_to_01(ZLIB_FOUND HAVE_ZLIB) find_package(OpenEXR) set_package_properties(OpenEXR PROPERTIES DESCRIPTION "High dynamic-range (HDR) image file format" URL "http://www.openexr.com" TYPE OPTIONAL PURPOSE "Required by the Krita OpenEXR filter") macro_bool_to_01(OPENEXR_FOUND HAVE_OPENEXR) set(LINK_OPENEXR_LIB) if(OPENEXR_FOUND) include_directories(SYSTEM ${OPENEXR_INCLUDE_DIR}) set(LINK_OPENEXR_LIB ${OPENEXR_LIBRARIES}) add_definitions(${OPENEXR_DEFINITIONS}) endif() find_package(TIFF) set_package_properties(TIFF PROPERTIES DESCRIPTION "TIFF Library and Utilities" URL "http://www.remotesensing.org/libtiff" TYPE OPTIONAL PURPOSE "Required by the Krita TIFF filter") find_package(JPEG) set_package_properties(JPEG PROPERTIES DESCRIPTION "Free library for JPEG image compression. Note: libjpeg8 is NOT supported." URL "http://www.libjpeg-turbo.org" TYPE OPTIONAL PURPOSE "Required by the Krita JPEG filter") set(LIBRAW_MIN_VERSION "0.16") find_package(LibRaw ${LIBRAW_MIN_VERSION}) set_package_properties(LibRaw PROPERTIES DESCRIPTION "Library to decode RAW images" URL "http://www.libraw.org" TYPE OPTIONAL PURPOSE "Required to build the raw import plugin") find_package(FFTW3) set_package_properties(FFTW3 PROPERTIES DESCRIPTION "A fast, free C FFT library" URL "http://www.fftw.org/" TYPE OPTIONAL PURPOSE "Required by the Krita for fast convolution operators and some G'Mic features") macro_bool_to_01(FFTW3_FOUND HAVE_FFTW3) find_package(OCIO) set_package_properties(OCIO PROPERTIES DESCRIPTION "The OpenColorIO Library" URL "http://www.opencolorio.org" TYPE OPTIONAL PURPOSE "Required by the Krita LUT docker") macro_bool_to_01(OCIO_FOUND HAVE_OCIO) ## ## Look for OpenGL ## # TODO: see if there is a better check for QtGui being built with opengl support (and thus the QOpenGL* classes) if(Qt5Gui_OPENGL_IMPLEMENTATION) message(STATUS "Found QtGui OpenGL support") else() message(FATAL_ERROR "Did NOT find QtGui OpenGL support. Check your Qt configuration. You cannot build Krita without Qt OpenGL support.") endif() ## ## Test for eigen3 ## find_package(Eigen3 REQUIRED "3.0") set_package_properties(Eigen3 PROPERTIES DESCRIPTION "C++ template library for linear algebra" URL "http://eigen.tuxfamily.org" TYPE REQUIRED) ## ## Test for exiv2 ## set(EXIV2_MIN_VERSION "0.16") find_package(Exiv2 REQUIRED) set_package_properties(Exiv2 PROPERTIES DESCRIPTION "Image metadata library and tools" URL "http://www.exiv2.org" PURPOSE "Required by Krita") ## ## Test for lcms ## find_package(LCMS2 REQUIRED "2.4") set_package_properties(LCMS2 PROPERTIES DESCRIPTION "LittleCMS Color management engine" URL "http://www.littlecms.com" TYPE REQUIRED PURPOSE "Will be used for color management and is necessary for Krita") if(LCMS2_FOUND) if(NOT ${LCMS2_VERSION} VERSION_LESS 2040 ) set(HAVE_LCMS24 TRUE) endif() set(HAVE_REQUIRED_LCMS_VERSION TRUE) set(HAVE_LCMS2 TRUE) endif() ## ## Test for Vc ## set(OLD_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules ) set(HAVE_VC FALSE) if( NOT MSVC) find_package(Vc 1.1.0) set_package_properties(Vc PROPERTIES DESCRIPTION "Portable, zero-overhead SIMD library for C++" URL "https://github.com/VcDevel/Vc" TYPE OPTIONAL PURPOSE "Required by the Krita for vectorization") macro_bool_to_01(Vc_FOUND HAVE_VC) macro_bool_to_01(PACKAGERS_BUILD DO_PACKAGERS_BUILD) endif() configure_file(config-vc.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-vc.h ) if(HAVE_VC) message(STATUS "Vc found!") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/vc") include (VcMacros) if(Vc_COMPILER_IS_CLANG) set(ADDITIONAL_VC_FLAGS "-Wabi -ffp-contract=fast -fPIC") elseif (NOT MSVC) set(ADDITIONAL_VC_FLAGS "-Wabi -fabi-version=0 -ffp-contract=fast -fPIC") endif() #Handle Vc master if(Vc_COMPILER_IS_GCC OR Vc_COMPILER_IS_CLANG) AddCompilerFlag("-std=c++11" _ok) if(NOT _ok) AddCompilerFlag("-std=c++0x" _ok) endif() endif() macro(ko_compile_for_all_implementations_no_scalar _objs _src) if(PACKAGERS_BUILD) vc_compile_for_all_implementations(${_objs} ${_src} FLAGS ${ADDITIONAL_VC_FLAGS} ONLY SSE2 SSSE3 SSE4_1 AVX AVX2+FMA+BMI2) else() set(${_objs} ${_src}) endif() endmacro() macro(ko_compile_for_all_implementations _objs _src) if(PACKAGERS_BUILD) vc_compile_for_all_implementations(${_objs} ${_src} FLAGS ${ADDITIONAL_VC_FLAGS} ONLY Scalar SSE2 SSSE3 SSE4_1 AVX AVX2+FMA+BMI2) else() set(${_objs} ${_src}) endif() endmacro() if (NOT PACKAGERS_BUILD) # Optimize everything for the current architecture set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Vc_DEFINITIONS}") endif () endif() set(CMAKE_MODULE_PATH ${OLD_CMAKE_MODULE_PATH} ) -## -## Test for Xinput -## -if(NOT WIN32 AND NOT APPLE) - set(REQUIRED_Xinput_FOUND ${X11_Xinput_FOUND}) -else() - set(REQUIRED_Xinput_FOUND TRUE) -endif() - add_definitions(${QT_DEFINITIONS} ${QT_QTDBUS_DEFINITIONS}) if(WIN32) set(LIB_INSTALL_DIR ${LIB_INSTALL_DIR} RUNTIME DESTINATION ${BIN_INSTALL_DIR} LIBRARY ${INSTALL_TARGETS_DEFAULT_ARGS} ARCHIVE ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif() ## ## Test endianess ## include (TestBigEndian) test_big_endian(CMAKE_WORDS_BIGENDIAN) ## ## Test for qt-poppler ## find_package(Poppler) set_package_properties(Poppler PROPERTIES DESCRIPTION "A PDF rendering library" URL "http://poppler.freedesktop.org" TYPE OPTIONAL PURPOSE "Required by the Krita PDF filter.") ## ## Test for pthreads (for G'Mic) ## find_package(Threads) set_package_properties(Threads PROPERTIES DESCRIPTION "PThreads - A low-level threading library" TYPE OPTIONAL PURPOSE "Optionally used by the G'Mic plugin") ## ## Test for OpenMP (for G'Mic) ## find_package(OpenMP) set_package_properties(OpenMP PROPERTIES DESCRIPTION "A low-level parallel execution library" URL "http://openmp.org/wp/" TYPE OPTIONAL PURPOSE "Optionally used by the G'Mic plugin") ## ## Test for Curl (for G'Mic) ## find_package(CURL) set_package_properties(CURL PROPERTIES DESCRIPTION "A tool to fetch remote data" URL "http://curl.haxx.se/" TYPE OPTIONAL PURPOSE "Optionally used by the G'Mic plugin") ############################ ############################# ## Add Krita helper macros ## ############################# ############################ include(MacroKritaAddBenchmark) #################### ##################### ## Define includes ## ##################### #################### # for config.h and includes (if any?) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/interfaces ) -include_directories( - ${CMAKE_SOURCE_DIR}/libs/version - ${CMAKE_BINARY_DIR}/libs/version -) - - ################################################### -#################################################### -## Detect which products/features can be compiled ## -#################################################### -################################################### - -calligra_drop_product_on_bad_condition( APP_KRITA - EIGEN3_FOUND "Eigen devel not found" - EXIV2_FOUND "libexiv2 devel not found" - HAVE_REQUIRED_LCMS_VERSION "lcms devel not found" - Boost_SYSTEM_FOUND "boost-system devel not found" - REQUIRED_Xinput_FOUND "Xinput devel not found " -) - -############################################# -#### Backward compatibility BUILD_x=off #### -############################################# - -# workaround: disable directly all products which might be activated by internal -# dependencies, but belong to scope of old flag -calligra_drop_products_on_old_flag(krita APP_KRITA) - -############################################# -#### Temporarily broken products #### -############################################# - -# If a product does not build due to some temporary brokeness disable it here, -# by calling calligra_disable_product with the product id and the reason, -# e.g.: -# calligra_disable_product(APP_KEXI "isn't buildable at the moment") - -############################################# -#### Calculate buildable products #### -############################################# - -calligra_drop_unbuildable_products() - - ################### -#################### -## Subdirectories ## -#################### -################### - -if(SHOULD_BUILD_APP_KRITA) - add_subdirectory(krita) -endif() - -# non-app directories are moved here because they can depend on SHOULD_BUILD_{appname} variables set above add_subdirectory(libs) add_subdirectory(plugins) - -add_subdirectory( benchmarks ) - -feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) - -calligra_product_deps_report("product_deps") -calligra_log_should_build() +add_subdirectory(benchmarks) +add_subdirectory(krita) configure_file(KoConfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/KoConfig.h ) configure_file(config_convolution.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_convolution.h) configure_file(config-ocio.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ocio.h ) check_function_exists(powf HAVE_POWF) configure_file(config-powf.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-powf.h) +message("\nBroken tests:") +foreach(tst ${KRITA_BROKEN_TESTS}) + message(" * ${tst}") +endforeach() +feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/KritaProducts.cmake b/KritaProducts.cmake deleted file mode 100644 index a23f97ce25..0000000000 --- a/KritaProducts.cmake +++ /dev/null @@ -1,250 +0,0 @@ -### DEFINITION OF PRODUCTS, FEATURES AND PRODUCTSETS -#################################################### - -# When building Krita a lot of different things are created and installed. To -# describe them and their internal dependencies the concepts of "product", -# "feature" and "product set" are used. - -# A "product" is the smallest functional unit which can be created in the build -# and which is useful on its own when installed. Examples are e.g. libraries, -# plugins or executables. Products have external and internal required -# dependencies at build-time. Internal dependencies are noted in terms of other -# products or features (see below) and could be e.g. other libraries to link -# against or build tools needed to generate source files. -# A product gets defined by setting an identifier, a descriptive fullname and -# the needed internal build-time requirements. Any other product or feature -# listed as requirement must have been defined before. - -# A "feature" is not a standalone product, but adds abilities to one or multiple -# given products. One examples is e.g. scriptability. Features have external and -# internal required dependencies at build-time. Internal dependencies are noted -# in terms of other products or features and could be e.g. other libraries to -# link against or build tools needed to generate source files. -# A feature gets defined by setting an identifier, a descriptive fullname and -# the needed internal build-time requirements. Any other product or feature -# listed as requirement must have been defined before. - -# A "productset" is a selection of products and features which should be build -# together. The products and features can be either essential or optional to the -# set. If essential (REQUIRES), the whole productset will not be build if a -# product or feature is missing another internal or external dependency. If -# optional (OPTIONAL), the rest of the set will still be build in that case. -# The products and features to include in a set can be listed directly or -# indirectly: they can be named explicitely, but also by including other -# productsets in a set, whose products and features will then be part of the -# first set as well. -# Products, features and productsets can be listed as dependencies in multiple -# product sets. As with dependencies for products or features, they must have -# been defined before. - -# Products, features and product sets are in the same namespace, so a given -# identifier can be only used either for a product or for a feature or for a -# product set. - -# The ids of products and features (but not sets) are used to generate cmake -# variables SHOULD_BUILD_${ID}, which then are used to control what is build and -# how. - - -############################################# -#### Product definitions #### -############################################# - -# For defining new products see end of this file, "How to add another product?" - -# IDEA: also add headers/sdk for all the libs ("_DEVEL"?) -# IDEA: note external deps for products, so they are only checked if needed -# There can be required or optional external deps, required will also result -# in automatic disabling of product building -# TODO: some products have multiple optional requirements, but need at least one. -# See APP_CONVERTER, FILEMANAGER_* - -# building tools - -# Calligra-independent utility libs -calligra_define_product(LIB_KOVECTORIMAGE "libkovectorimage") - -# calligra libs -calligra_define_product(LIB_CALLIGRA "Calligra core libs" REQUIRES ) - -# features - -# plugins -calligra_define_product(PLUGIN_TEXTSHAPE "Text shape plugin" REQUIRES LIB_CALLIGRA) - -# parts - -# apps -calligra_define_product(APP_KRITA "Krita app (for Desktop)" REQUIRES LIB_CALLIGRA) - -# extras - -# more plugins -calligra_define_product(PLUGIN_COLORENGINES "Colorengine plugins" REQUIRES LIB_CALLIGRA) -calligra_define_product(PLUGIN_ARTISTICTEXTSHAPE "Artistic shape plugin" REQUIRES LIB_CALLIGRA) -calligra_define_product(PLUGIN_DOCKERS "Default dockers plugin" REQUIRES LIB_CALLIGRA) -calligra_define_product(PLUGIN_DEFAULTTOOLS "Default Flake tools plugin" REQUIRES LIB_CALLIGRA) -calligra_define_product(PLUGIN_PATHSHAPES "Path shape plugins" REQUIRES LIB_CALLIGRA) -calligra_define_product(PLUGIN_VECTORSHAPE "Vectorgraphic shape plugin" REQUIRES LIB_CALLIGRA LIB_KOVECTORIMAGE) - -# staging plugins - -############################################# -#### Product set definitions #### -############################################# - -# For defining new productsets see end of this file, -# "How to add another productset?" - -calligra_define_productset(KRITA "Full Krita" - REQUIRES - APP_KRITA - OPTIONAL - # plugins - PLUGIN_ARTISTICTEXTSHAPE - PLUGIN_COLORENGINES - PLUGIN_DEFAULTTOOLS - PLUGIN_DOCKERS - PLUGIN_PATHSHAPES - PLUGIN_TEXTSHAPE - PLUGIN_VECTORSHAPE -) - -# How to add another product? -# =========================== -# -# 1. Define the product by a call of calligra_define_product, -# e.g. -# -# calligra_define_product(MYPRODUCT "title of product") -# -# For the product id use a proper prefix (LIB_, PLUGIN_, FILTER_, APP_, PART_, -# ...), whatever is appropriate. -# -# 2. Extend that call with a REQUIRES argument section, if the product has -# hard internal build-time dependencies on other products or features. -# Products/features that are listed as dependencies have to be defined before -# (see also the API doc in cmake/modules/CalligraProductSetMacros.cmake) -# E.g. -# -# calligra_define_product(MYPRODUCT "title of product" REQUIRES P1 P2) -# -# 3. Add a rule when to not build the product, in the section "Detect which -# products/features can be compiled" of the toplevel CMakeLists.txt. Each -# product should have their own boolean expression when to set the build flag -# to FALSE, e.g. -# -# if (PLATFORMX OR NOT EXTERNAL_DEP_X_FOUND) -# set(SHOULD_BUILD_MYPRODUCT FALSE) -# endif () -# -# 4. Wrap everything belonging to the product with the build flag of the product. -# Ideally this is done around subdirectory inclusions, results in easier code. -# e.g. -# -# if (SHOULD_BUILD_MYPRODUCT) -# add_subdirectory(myproduct) -# endif () -# -# 5. Tag the product as STAGING, if it is not yet ready for release, but already -# integrated in the master branch, e.g. -# -# calligra_define_product(MYPRODUCT "title of product" STAGING REQUIRES P1) -# -# 6. Add the product to all products, features and product sets which have this -# product as REQUIRED or OPTIONAL dependency. -# -# -# How to add another feature? -# =========================== -# -# 1. Define the feature by a call of calligra_define_feature, -# e.g. -# -# calligra_define_feature(MYFEATURE "title of feature") -# -# For the feature id use a proper prefix (FEATURE_, ...), whatever is -# appropriate. -# -# 2. Extend that call with a REQUIRES argument section, if the feature has -# hard internal build-time dependencies on other products or features. -# Products or features that are listed as dependencies have to be defined -# before -# (see also the API doc in cmake/modules/CalligraProductSetMacros.cmake) -# E.g. -# -# calligra_define_feature(MYFEATURE "title of feature" REQUIRES P1 F1) -# -# 3. Add a rule when to not build the feature, in the section "Detect which -# products/features can be compiled" of the toplevel CMakeLists.txt. Each -# feature should have their own boolean expression when to set the build flag -# to FALSE, e.g. -# -# if (PLATFORMX OR NOT EXTERNAL_DEP_X_FOUND) -# set(SHOULD_BUILD_MYFEATURE FALSE) -# endif () -# -# 4. Wrap everything belonging to the feature with the build flag of the feature. -# Ideally this is done around subdirectory inclusions, results in easier code. -# e.g. -# -# if (SHOULD_BUILD_MYFEATURE) -# add_subdirectory(myproduct) -# endif () -# -# 5. Tag the feature as STAGING, if it is not yet ready for release, but already -# integrated in the master branch, e.g. -# -# calligra_define_product(MYFEATURE "title of feature" STAGING REQUIRES P1 F1) -# -# 6. Add the feature to all products, features and product sets which have this -# product as REQUIRED or OPTIONAL dependency. -# -# -# How to add another productset? -# ============================== -# -# There are two possible places to put a productset definition. The first is to -# add it to this file, which should be done for more generic sets that are -# useful for many people. The second is a file of its own, in the directory -# "cmake/productsets", which should be done for more special ones or for those -# which should not be added to the repository. -# The file must be named with the name of the productset in lowercase and have -# the extension ".cmake". -# -# 1. Define the productset by a call of calligra_define_productset, -# e.g. -# -# calligra_define_productset(MYPRODUCTSET "title of productset") -# -# 2. Extend that call with REQUIRES or OPTIONAL argument sections, if the productset -# has hard or soft internal dependencies on other products, features or -# productsets. -# Products, features or productsets that are listed as dependencies have to -# be defined before -# (see also the API doc in cmake/modules/CalligraProductSetMacros.cmake) -# E.g. -# -# calligra_define_productset(MYPRODUCT "title of product" -# REQUIRES P1 P2 F1 PS1 -# OPTIONAL P3 F2 PS2) -# -# 3. Add the productset to all product sets which have this product set as -# REQUIRED or OPTIONAL dependency. -# -# Example for a file-based productset definition: -# You want a productset "MYWORDS". For that you add a file named -# "mywords.cmake" into the directory "cmake/productsets", with the content: -# --- 8< --- -# calligra_define_productset(MYWORDS "My Words" -# REQUIRES -# APP_WORDS -# PLUGIN_DEFAULTTOOLS -# PLUGIN_DOCKERS -# PLUGIN_PATHSHAPES -# PLUGIN_VARIABLES -# PLUGIN_TEXTSHAPE -# PLUGIN_PLUGINSHAPE -# PLUGIN_FORMULASHAPE -# ) -# --- 8< --- diff --git a/cmake/modules/CalligraProductSetMacros.cmake b/cmake/modules/CalligraProductSetMacros.cmake deleted file mode 100644 index 0925a26519..0000000000 --- a/cmake/modules/CalligraProductSetMacros.cmake +++ /dev/null @@ -1,503 +0,0 @@ -# Copyright (c) 2013-2014 Friedrich W. H. Kossebau -# -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - -# Global variables -# CALLIGRA_SHOULD_BUILD_PRODUCTS - list of requested products by the user -# CALLIGRA_NEEDED_PRODUCTS - list of internal needed products -# CALLIGRA_WANTED_PRODUCTS - list of internal wanted products -# CALLIGRA_STAGING_PRODUCTS - list of products only in staging mode -# temporary during qt5 port, remove after: -# CALLIGRA_UNPORTED_PRODUCTS - list of products not yet ported -# SHOULD_BUILD_${product_id} - boolean if product should be build - - -macro(calligra_disable_product _product_id _reason) - if (NOT DEFINED SHOULD_BUILD_${_product_id}) - message(FATAL_ERROR "Unknown product: ${_product_id}") - endif (NOT DEFINED SHOULD_BUILD_${_product_id}) - - set(SHOULD_BUILD_${_product_id} FALSE) - if (DEFINED BUILD_${_product_id}_DISABLE_REASON) - set(BUILD_${_product_id}_DISABLE_REASON "${BUILD_${_product_id}_DISABLE_REASON} / ") - endif (DEFINED BUILD_${_product_id}_DISABLE_REASON) - set(BUILD_${_product_id}_DISABLE_REASON "${BUILD_${_product_id}_DISABLE_REASON}${_reason}") -endmacro() - -# Usage: -# calligra_drop_product_on_bad_condition( -# NAME_OF_BOOL_VAR1 REASON_TEXT_FOR_DROPPING_ON_FALSE1 -# NAME_OF_BOOL_VAR2 REASON_TEXT_FOR_DROPPING_ON_FALSE2 -# ... -# ) -macro(calligra_drop_product_on_bad_condition _product_id) - if (NOT DEFINED SHOULD_BUILD_${_product_id}) - message(FATAL_ERROR "Unknown product: ${_product_id}") - endif (NOT DEFINED SHOULD_BUILD_${_product_id}) - - set(_current_flag) - foreach(_arg ${ARGN}) - if(DEFINED _current_flag) - if(NOT ${_current_flag}) - calligra_disable_product(${_product_id} ${_arg}) - endif() - set(_current_flag) - else() - set(_current_flag ${_arg}) - endif() - endforeach(_arg) - if(DEFINED _current_flag) - message(FATAL_ERROR "Bad number of arguments for calligra_drop_product_on_bad_condition(${_product_id} ...)") - endif() -endmacro() - -macro(calligra_set_shouldbuild_dependentproduct _product_id _dep_product_id) - # if not already enabled, enable - if (NOT SHOULD_BUILD_${_dep_product_id}) - list(APPEND CALLIGRA_NEEDED_PRODUCTS ${_dep_product_id}) - set(SHOULD_BUILD_${_dep_product_id} TRUE) - if (DEFINED CALLIGRA_PRODUCT_${_dep_product_id}_needed_dependencies OR - DEFINED CALLIGRA_PRODUCT_${_dep_product_id}_wanted_dependencies) - calligra_set_shouldbuild_productdependencies(${_dep_product_id} - "${CALLIGRA_PRODUCT_${_dep_product_id}_needed_dependencies}" - "${CALLIGRA_PRODUCT_${_dep_product_id}_wanted_dependencies}") - endif (DEFINED CALLIGRA_PRODUCT_${_dep_product_id}_needed_dependencies OR - DEFINED CALLIGRA_PRODUCT_${_dep_product_id}_wanted_dependencies) - endif (NOT SHOULD_BUILD_${_dep_product_id}) -endmacro() - - -macro(calligra_set_shouldbuild_productdependencies _product_id _productset_id_needed_dependencies _productset_id_wanted_dependencies) - # activate all needed products and note the dependency - foreach(_dep_product_id ${_productset_id_needed_dependencies}) - list(APPEND CALLIGRA_PRODUCT_${_dep_product_id}_dependents ${_product_id}) - calligra_set_shouldbuild_dependentproduct(${_product_id} ${_dep_product_id}) - endforeach(_dep_product_id) - - # activate all wanted products - foreach(_dep_product_id ${_productset_id_wanted_dependencies}) - calligra_set_shouldbuild_dependentproduct(${_product_id} ${_dep_product_id}) - endforeach(_dep_product_id) -endmacro() - - -macro(calligra_drop_unbuildable_products) - # temporary during qt5 port, remove after - if(NOT BUILD_UNPORTED) - foreach(_product_id ${CALLIGRA_UNPORTED_PRODUCTS}) - calligra_disable_product(${_product_id} "Not yet ported to Qt5/KF5") - endforeach(_product_id) - endif(NOT BUILD_UNPORTED) - - # first drop all staging products if not enabled - if(NOT CALLIGRA_SHOULD_BUILD_STAGING) - foreach(_product_id ${CALLIGRA_STAGING_PRODUCTS}) - calligra_disable_product(${_product_id} "Not ready for release") - endforeach(_product_id) - endif(NOT CALLIGRA_SHOULD_BUILD_STAGING) - - # can assume calligra_all_products has products in down-up order - # 1. check all wanted products and see if they will be built, - # if not then drop their required products - # TODO! - # 2. check all products if they can be built, if not disable build of depending - foreach(_product_id ${CALLIGRA_ALL_PRODUCTS}) - if(NOT SHOULD_BUILD_${_product_id}) - if(DEFINED CALLIGRA_PRODUCT_${_product_id}_dependents) - foreach(_dependent_product_id ${CALLIGRA_PRODUCT_${_product_id}_dependents}) - calligra_disable_product(${_dependent_product_id} "Required internal dependency missing: ${_product_id}") - endforeach(_dependent_product_id ${CALLIGRA_PRODUCT_${_dep_product_id}_dependents}) - endif(DEFINED CALLIGRA_PRODUCT_${_product_id}_dependents) - endif(NOT SHOULD_BUILD_${_product_id}) - endforeach(_product_id) -endmacro() - -# backward compatibility: BUILD_app as option or passed as cmake parameter can overwrite product set -# and disable a product if set to FALSE (TRUE was ignored) -macro(calligra_drop_products_on_old_flag _build_id) - string(TOLOWER "${_build_id}" lowercase_build_id) - if (DEFINED BUILD_${lowercase_build_id} AND NOT BUILD_${lowercase_build_id}) - foreach(_product_id ${ARGN}) - if (NOT DEFINED SHOULD_BUILD_${_product_id}) - message(FATAL_ERROR "Unknown product: ${_product_id}") - endif (NOT DEFINED SHOULD_BUILD_${_product_id}) - calligra_disable_product(${_product_id} "Disabled by cmake parameter") - endforeach(_product_id) - endif (DEFINED BUILD_${lowercase_build_id} AND NOT BUILD_${lowercase_build_id}) -endmacro() - -macro(calligra_set_productset _productset_string) - set(CALLIGRA_SHOULD_BUILD_PRODUCTS "") - # turn into list, _productset_string is not yet one - set(_productset_ids ${_productset_string}) - separate_arguments(_productset_ids) - set(_productset_list "") - # _product_id could be a product, feature or product set (predefined or from file) - foreach(_product_id ${_productset_ids}) - # be gracefull and compare the productset id case insensitive - string(TOUPPER "${_product_id}" _uppercase_product_id) - - if(_uppercase_product_id STREQUAL "ALL") - list( APPEND CALLIGRA_SHOULD_BUILD_PRODUCTS ${CALLIGRA_ALL_PRODUCTS}) - elseif(DEFINED SHOULD_BUILD_${_uppercase_product_id}) - list( APPEND CALLIGRA_SHOULD_BUILD_PRODUCTS ${_uppercase_product_id}) - else() - # also expects a productset definition filename in all lowercase - string(TOLOWER "${_product_id}" _lowercase_productset_id) - set(_productset_filename "${CMAKE_SOURCE_DIR}/cmake/productsets/${_lowercase_productset_id}.cmake") - - if (NOT EXISTS "${_productset_filename}") - message(FATAL_ERROR "Unknown product, feature or product set: ${_product_id}") - endif (NOT EXISTS "${_productset_filename}") - - # include the productset definition - include(${_productset_filename}) - if(NOT CALLIGRA_PRODUCTSET_${_uppercase_product_id}) - message(FATAL_ERROR "Product set file \"${_productset_filename}\" did not define a productset named \"${_uppercase_product_id}\".") - endif() - - list( APPEND CALLIGRA_SHOULD_BUILD_PRODUCTS ${_uppercase_product_id}) - endif() - list( APPEND _productset_list ${_uppercase_product_id}) - endforeach(_product_id) - - string(REPLACE ";" " " _productset_list "${_productset_list}") - set(CALLIGRA_NEEDED_PRODUCTS "") - - message(STATUS "-------------------------------------------------------------------" ) - message(STATUS "Configured with product set \"${_productset_list}\"") - message(STATUS "-------------------------------------------------------------------" ) - - # backward compatibility: BUILD_app as option or passed as cmake parameter can overwrite product set - # and disable a product if set to FALSE (TRUE was ignored) - foreach(_product_id ${CALLIGRA_ALL_PRODUCTS}) - string(TOLOWER "${_product_id}" lowercase_product_id) - if (DEFINED BUILD_${lowercase_product_id}) - if(NOT BUILD_${lowercase_product_id}) - list(FIND CALLIGRA_SHOULD_BUILD_PRODUCTS ${_product_id} _index) - # remove from product set, if part - if(NOT _index EQUAL -1) - list(REMOVE_AT CALLIGRA_SHOULD_BUILD_PRODUCTS ${_index}) - endif(NOT _index EQUAL -1) - endif(NOT BUILD_${lowercase_product_id}) - endif (DEFINED BUILD_${lowercase_product_id}) - endforeach(_product_id ${CALLIGRA_ALL_PRODUCTS}) - - # mark all products of the set as SHOULD_BUILD - foreach(_product_id ${CALLIGRA_SHOULD_BUILD_PRODUCTS}) - # check that this product is actually existing - if (NOT DEFINED SHOULD_BUILD_${_product_id}) - message(FATAL_ERROR "Unknown product: ${_product_id}") - endif (NOT DEFINED SHOULD_BUILD_${_product_id}) - - # mark product as should build, also all dependencies - set(SHOULD_BUILD_${_product_id} TRUE) - if (DEFINED CALLIGRA_PRODUCT_${_product_id}_needed_dependencies OR - DEFINED CALLIGRA_PRODUCT_${_product_id}_wanted_dependencies) - calligra_set_shouldbuild_productdependencies(${_product_id} - "${CALLIGRA_PRODUCT_${_product_id}_needed_dependencies}" - "${CALLIGRA_PRODUCT_${_product_id}_wanted_dependencies}") - endif (DEFINED CALLIGRA_PRODUCT_${_product_id}_needed_dependencies OR - DEFINED CALLIGRA_PRODUCT_${_product_id}_wanted_dependencies) - endforeach(_product_id) -endmacro() - - -# Usage: -# calligra_define_product( -# [NAME] -# [STAGING] -# [REQUIRES ...] -# ) -macro(calligra_define_product _product_id) - # default product name to id, empty deps - set(_product_name "${_product_id}") - set(_needed_dep_product_ids) - - if(DEFINED SHOULD_BUILD_${_product_id}) - message(FATAL_ERROR "Product \"${_product_id}\" already defined, as \"${CALLIGRA_PRODUCT_${_product_id}_name}\".") - endif(DEFINED SHOULD_BUILD_${_product_id}) - - # parse arguments: two states, "name" or "requires" - set(_current_arg_type "name") - foreach(_arg ${ARGN}) - if(${_arg} STREQUAL "NAME") - set(_current_arg_type "name") - elseif(${_arg} STREQUAL "REQUIRES") - set(_current_arg_type "requires") - else(${_arg} STREQUAL "NAME") - if(${_current_arg_type} STREQUAL "name") - if(${_arg} STREQUAL "STAGING") - list(APPEND CALLIGRA_STAGING_PRODUCTS ${_product_id}) - elseif(${_arg} STREQUAL "UNPORTED") - # temporary during qt5 port, remove after - list(APPEND CALLIGRA_UNPORTED_PRODUCTS ${_product_id}) - else(${_arg} STREQUAL "STAGING") - set(_product_name "${_arg}") - endif(${_arg} STREQUAL "STAGING") - elseif(${_current_arg_type} STREQUAL "requires") - # check that the dependency is actually existing - if(NOT DEFINED SHOULD_BUILD_${_arg}) - message(FATAL_ERROR "Unknown product/feature listed as dependency for \"${_product_id}\": \"${_arg}\"") - elseif(CALLIGRA_PRODUCTSET_${_arg}) - message(FATAL_ERROR "Productset cannot be a dependency for \"${_product_id}\": \"${_arg}\"") - endif() - list(APPEND _needed_dep_product_ids "${_arg}") - endif(${_current_arg_type} STREQUAL "name") - endif(${_arg} STREQUAL "NAME") - endforeach(_arg) - - # set product vars - set(SHOULD_BUILD_${_product_id} FALSE) - set(CALLIGRA_PRODUCT_${_product_id}_name "${_product_name}") - set(CALLIGRA_PRODUCT_${_product_id}_needed_dependencies ${_needed_dep_product_ids}) - list(APPEND CALLIGRA_ALL_PRODUCTS ${_product_id}) -endmacro(calligra_define_product) - - -# Usage: -# calligra_define_feature( -# [NAME] -# [STAGING] -# [REQUIRES ...] -# ) -macro(calligra_define_feature _product_id) - # default product name to id, empty deps - set(_product_name "${_product_id}") - set(_needed_dep_product_ids) - - if(DEFINED SHOULD_BUILD_${_product_id}) - message(FATAL_ERROR "Feature \"${_product_id}\" already defined, as \"${CALLIGRA_PRODUCT_${_product_id}_name}\".") - endif(DEFINED SHOULD_BUILD_${_product_id}) - - # parse arguments: two states, "name" or "requires" - set(_current_arg_type "name") - foreach(_arg ${ARGN}) - if(${_arg} STREQUAL "NAME") - set(_current_arg_type "name") - elseif(${_arg} STREQUAL "REQUIRES") - set(_current_arg_type "requires") - else(${_arg} STREQUAL "NAME") - if(${_current_arg_type} STREQUAL "name") - if(${_arg} STREQUAL "STAGING") - list(APPEND CALLIGRA_STAGING_PRODUCTS ${_product_id}) - elseif(${_arg} STREQUAL "UNPORTED") - # temporary during qt5 port, remove after - list(APPEND CALLIGRA_UNPORTED_PRODUCTS ${_product_id}) - else(${_arg} STREQUAL "STAGING") - set(_product_name "${_arg}") - endif(${_arg} STREQUAL "STAGING") - elseif(${_current_arg_type} STREQUAL "requires") - # check that the dependency is actually existing - if(NOT DEFINED SHOULD_BUILD_${_arg}) - message(FATAL_ERROR "Unknown product/feature listed as dependency for \"${_product_id}\": \"${_arg}\"") - elseif(CALLIGRA_PRODUCTSET_${_arg}) - message(FATAL_ERROR "Productset cannot be a dependency for \"${_product_id}\": \"${_arg}\"") - endif() - list(APPEND _needed_dep_product_ids "${_arg}") - endif(${_current_arg_type} STREQUAL "name") - endif(${_arg} STREQUAL "NAME") - endforeach(_arg) - - # set product vars - set(SHOULD_BUILD_${_product_id} FALSE) - set(CALLIGRA_PRODUCT_${_product_id}_name "${_product_name}") - set(CALLIGRA_PRODUCT_${_product_id}_needed_dependencies ${_needed_dep_product_ids}) - list(APPEND CALLIGRA_ALL_PRODUCTS ${_product_id}) -endmacro(calligra_define_feature) - - -# Usage: -# calligra_define_productset( -# [NAME] -# [REQUIRES ... ...] -# [OPTIONAL ... ...] -# ) -macro(calligra_define_productset _product_id) - # default product name to id, empty deps - set(_product_name "${_product_id}") - set(_needed_dep_product_ids) - set(_wanted_dep_product_ids) - - if(DEFINED SHOULD_BUILD_${_product_id}) - message(FATAL_ERROR "Productset \"${_product_id}\" already defined, as \"${CALLIGRA_PRODUCT_${_product_id}_name}\".") - endif(DEFINED SHOULD_BUILD_${_product_id}) - - # parse arguments: three states, "name", "requires" or "optional" - set(_current_arg_type "name") - foreach(_arg ${ARGN}) - if(${_arg} STREQUAL "NAME") - set(_current_arg_type "name") - elseif(${_arg} STREQUAL "REQUIRES") - set(_current_arg_type "requires") - elseif(${_arg} STREQUAL "OPTIONAL") - set(_current_arg_type "optional") - else(${_arg} STREQUAL "NAME") - if(${_current_arg_type} STREQUAL "name") - set(_product_name "${_arg}") - elseif(${_current_arg_type} STREQUAL "requires") - # check that the dependency is actually existing - if(NOT DEFINED SHOULD_BUILD_${_arg}) - message(FATAL_ERROR "Unknown product(set)/feature listed as dependency for \"${_product_id}\": \"${_arg}\"") - endif(NOT DEFINED SHOULD_BUILD_${_arg}) - list(APPEND _needed_dep_product_ids "${_arg}") - elseif(${_current_arg_type} STREQUAL "optional") - # check that the dependency is actually existing - if(NOT DEFINED SHOULD_BUILD_${_arg}) - message(FATAL_ERROR "Unknown product(set)/feature listed as dependency for \"${_product_id}\": \"${_arg}\"") - endif(NOT DEFINED SHOULD_BUILD_${_arg}) - list(APPEND _wanted_dep_product_ids "${_arg}") - endif(${_current_arg_type} STREQUAL "name") - endif(${_arg} STREQUAL "NAME") - endforeach(_arg) - - # set product(set) vars - set(SHOULD_BUILD_${_product_id} FALSE) - set(CALLIGRA_PRODUCT_${_product_id}_name "${_product_name}") - set(CALLIGRA_PRODUCTSET_${_product_id} TRUE) - set(CALLIGRA_PRODUCT_${_product_id}_needed_dependencies ${_needed_dep_product_ids}) - set(CALLIGRA_PRODUCT_${_product_id}_wanted_dependencies ${_wanted_dep_product_ids}) - list(APPEND CALLIGRA_ALL_PRODUCTS ${_product_id}) -endmacro(calligra_define_productset) - - -macro(calligra_log_should_build) - # find what products will be built and which not - set(_built_product_ids "") - set(_not_built_product_ids "") - set(_built_dependency_product_ids "") - set(_not_built_dependency_product_ids "") - - foreach(_product_id ${CALLIGRA_ALL_PRODUCTS}) - list(FIND CALLIGRA_SHOULD_BUILD_PRODUCTS ${_product_id} _index) - if(NOT _index EQUAL -1) - if(SHOULD_BUILD_${_product_id}) - list(APPEND _built_product_ids ${_product_id}) - else(SHOULD_BUILD_${_product_id}) - list(APPEND _not_built_product_ids ${_product_id}) - endif(SHOULD_BUILD_${_product_id}) - else(NOT _index EQUAL -1) - if(SHOULD_BUILD_${_product_id}) - list(APPEND _built_dependency_product_ids ${_product_id}) - else(SHOULD_BUILD_${_product_id}) - list(FIND CALLIGRA_NEEDED_PRODUCTS ${_product_id} _index2) - if(NOT _index2 EQUAL -1) - list(APPEND _not_built_dependency_product_ids ${_product_id}) - endif(NOT _index2 EQUAL -1) - endif(SHOULD_BUILD_${_product_id}) - endif(NOT _index EQUAL -1) - endforeach(_product_id) - - if(NOT _built_dependency_product_ids STREQUAL "") - message(STATUS "------ The following required product(set)s/features will be built -------") - foreach(_product_id ${_built_dependency_product_ids}) - if (DEFINED CALLIGRA_PRODUCT_${_product_id}_dependents) - set(dependents " [[needed by: ${CALLIGRA_PRODUCT_${_product_id}_dependents}]]") - else (DEFINED CALLIGRA_PRODUCT_${_product_id}_dependents) - set(dependents "") - endif (DEFINED CALLIGRA_PRODUCT_${_product_id}_dependents) - - message(STATUS "${_product_id}: ${CALLIGRA_PRODUCT_${_product_id}_name}${dependents}" ) - endforeach(_product_id) - message(STATUS "") - endif(NOT _built_dependency_product_ids STREQUAL "") - if(NOT _not_built_dependency_product_ids STREQUAL "") - message(STATUS "---- The following required product(set)s/features can NOT be built ------") - foreach(_product_id ${_not_built_dependency_product_ids}) - if (DEFINED CALLIGRA_PRODUCT_${_product_id}_dependents) - set(dependents " [[needed by: ${CALLIGRA_PRODUCT_${_product_id}_dependents}]]") - else (DEFINED CALLIGRA_PRODUCT_${_product_id}_dependents) - set(dependents "") - endif (DEFINED CALLIGRA_PRODUCT_${_product_id}_dependents) - - message(STATUS "${_product_id}: ${CALLIGRA_PRODUCT_${_product_id}_name}${dependents} | ${BUILD_${_product_id}_DISABLE_REASON}" ) - endforeach(_product_id) - message(STATUS "") - endif(NOT _not_built_dependency_product_ids STREQUAL "") - message(STATUS "------ The following product(set)s/features will be built ---------") - foreach(_product_id ${_built_product_ids}) - message(STATUS "${_product_id}: ${CALLIGRA_PRODUCT_${_product_id}_name}" ) - endforeach(_product_id) - if(NOT _not_built_product_ids STREQUAL "") - message(STATUS "\n------ The following product(set)s/features can NOT be built ------") - foreach(_product_id ${_not_built_product_ids}) - message(STATUS "${_product_id}: ${CALLIGRA_PRODUCT_${_product_id}_name} | ${BUILD_${_product_id}_DISABLE_REASON}" ) - endforeach(_product_id) - endif(NOT _not_built_product_ids STREQUAL "") - message(STATUS "-------------------------------------------------------------------" ) -endmacro(calligra_log_should_build) - - -macro(calligra_product_deps_report_stylebybuild _output _product_id) - if(SHOULD_BUILD_${_product_id}) - set(${_output} "filled") - else() - set(${_output} "solid") - endif() -endmacro(calligra_product_deps_report_stylebybuild) - -# Usage: -# calligra_product_deps_report() -macro(calligra_product_deps_report _filename) - set(_dot "${_dot}# This is a graphviz file. It shows the internal product dependencies of Calligra.\n") - set(_dot "${_dot}# dot -Tsvg ${_filename}.dot > ${_filename}.svg\n") - set(_dot "${_dot}# dot -Tpng ${_filename}.dot > ${_filename}.png\n") - set(_dot "${_dot}digraph calligra {\n") - set(_dot "${_dot}node [colorscheme=set312]\;\n") # pastel19, set312 or accent8 - set(_dot "${_dot}rankdir=LR\;\n") - - foreach(_product_id ${CALLIGRA_ALL_PRODUCTS}) - set(_color 11) - set(_shape "box") - set(_style "") - - if(CALLIGRA_PRODUCTSET_${_product_id}) - set(_color 1) - set(_shape "folder") - elseif(_product_id MATCHES "^LIB_") - set(_color 2) - set(_shape "box") - elseif(_product_id MATCHES "^FILTER_") - set(_color 3) - set(_shape "component") - elseif(_product_id MATCHES "^PLUGIN_") - set(_color 4) - set(_shape "component") - elseif(_product_id MATCHES "^PART_") - set(_color 5) - set(_shape "component") - elseif(_product_id MATCHES "^APP_") - set(_color 6) - set(_shape "box") - set(_style "rounded,") - elseif(_product_id MATCHES "^BUILDUTIL_") - set(_color 7) - set(_shape "diamond") - set(_style "rounded,") - elseif(_product_id MATCHES "^FEATURE_") - set(_color 8) - elseif(_product_id MATCHES "^OKULAR_") - set(_color 9) - set(_shape "component") - elseif(_product_id MATCHES "^FILEMANAGER_") - set(_color 10) - set(_shape "box") - endif() - - calligra_product_deps_report_stylebybuild(_stylebybuild ${_product_id}) - - set(_dot "${_dot}\"${_product_id}\" [fillcolor=${_color}, shape=${_shape}, style=\"${_style}${_stylebybuild}\"];\n") - - foreach(_dependent_product_id ${CALLIGRA_PRODUCT_${_product_id}_needed_dependencies}) - set(_edges "${_edges}\"${_product_id}\" -> \"${_dependent_product_id}\"\;\n") - endforeach(_dependent_product_id) - foreach(_dependent_product_id ${CALLIGRA_PRODUCT_${_product_id}_wanted_dependencies}) - set(_edges "${_edges}\"${_product_id}\" -> \"${_dependent_product_id}\" [style=dashed]\;\n") - endforeach(_dependent_product_id) - endforeach(_product_id) - - set(_dot "${_dot}${_edges}") - set(_dot "${_dot}}\n") - file(WRITE ${CMAKE_BINARY_DIR}/${_filename}.dot ${_dot}) -endmacro(calligra_product_deps_report) diff --git a/cmake/modules/GenerateTestExportHeader.cmake b/cmake/modules/GenerateTestExportHeader.cmake deleted file mode 100644 index a412d6fd12..0000000000 --- a/cmake/modules/GenerateTestExportHeader.cmake +++ /dev/null @@ -1,255 +0,0 @@ -#.rst: -# GenerateTestExportHeader -# -------------------- -# -# This module provides the function GENERATE_TEST_EXPORT_HEADER(). -# It is almost identical to generate_export_header() but produces -# additional test export symbols using exporttestheader.cmake.in -# -# The standard format is ${BASE_NAME}_TEST_EXPORT -# If you use a custom export symbol like EXPORTMYLIB -# the test symbol will be of the format EXPORTMYLIB_TEST -# - -#============================================================================= -# Copyright 2011 Stephen Kelly -# Copyright 2015 Michael Abrahams -# -# All rights reserved. - -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. - -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#============================================================================= - -include(CMakeParseArguments) -include(CheckCXXCompilerFlag) - -# TODO: Install this macro separately? -macro(_check_cxx_compiler_attribute _ATTRIBUTE _RESULT) - check_cxx_source_compiles("${_ATTRIBUTE} int somefunc() { return 0; } - int main() { return somefunc();}" ${_RESULT} - ) -endmacro() - -macro(_test_compiler_hidden_visibility) - - if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.2") - set(GCC_TOO_OLD TRUE) - elseif(CMAKE_COMPILER_IS_GNUC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2") - set(GCC_TOO_OLD TRUE) - elseif(CMAKE_CXX_COMPILER_ID MATCHES Intel AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0") - set(_INTEL_TOO_OLD TRUE) - endif() - - # Exclude XL here because it misinterprets -fvisibility=hidden even though - # the check_cxx_compiler_flag passes - if(NOT GCC_TOO_OLD - AND NOT _INTEL_TOO_OLD - AND NOT WIN32 - AND NOT CYGWIN - AND NOT CMAKE_CXX_COMPILER_ID MATCHES XL - AND NOT CMAKE_CXX_COMPILER_ID MATCHES PGI - AND NOT CMAKE_CXX_COMPILER_ID MATCHES Watcom) - check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY) - check_cxx_compiler_flag(-fvisibility-inlines-hidden - COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) - option(USE_COMPILER_HIDDEN_VISIBILITY - "Use HIDDEN visibility support if available." ON) - mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) - endif() -endmacro() - -macro(_test_compiler_has_deprecated) - if(CMAKE_CXX_COMPILER_ID MATCHES Borland - OR CMAKE_CXX_COMPILER_ID MATCHES HP - OR GCC_TOO_OLD - OR CMAKE_CXX_COMPILER_ID MATCHES PGI - OR CMAKE_CXX_COMPILER_ID MATCHES Watcom) - set(COMPILER_HAS_DEPRECATED "" CACHE INTERNAL - "Compiler support for a deprecated attribute") - else() - _check_cxx_compiler_attribute("__attribute__((__deprecated__))" - COMPILER_HAS_DEPRECATED_ATTR) - if(COMPILER_HAS_DEPRECATED_ATTR) - set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}" - CACHE INTERNAL "Compiler support for a deprecated attribute") - else() - _check_cxx_compiler_attribute("__declspec(deprecated)" - COMPILER_HAS_DEPRECATED) - endif() - endif() -endmacro() - -get_filename_component(_GENERATE_TEST_EXPORT_HEADER_MODULE_DIR - "${CMAKE_CURRENT_LIST_FILE}" PATH) - -macro(_DO_SET_MACRO_VALUES TARGET_LIBRARY) - set(DEFINE_DEPRECATED) - set(DEFINE_EXPORT) - set(DEFINE_IMPORT) - set(DEFINE_NO_EXPORT) - - if (COMPILER_HAS_DEPRECATED_ATTR) - set(DEFINE_DEPRECATED "__attribute__ ((__deprecated__))") - elseif(COMPILER_HAS_DEPRECATED) - set(DEFINE_DEPRECATED "__declspec(deprecated)") - endif() - - get_property(type TARGET ${TARGET_LIBRARY} PROPERTY TYPE) - - if(NOT ${type} STREQUAL "STATIC_LIBRARY") - if(WIN32) - set(DEFINE_EXPORT "__declspec(dllexport)") - set(DEFINE_IMPORT "__declspec(dllimport)") - elseif(COMPILER_HAS_HIDDEN_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY) - set(DEFINE_EXPORT "__attribute__((visibility(\"default\")))") - set(DEFINE_IMPORT "__attribute__((visibility(\"default\")))") - set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))") - endif() - endif() -endmacro() - -macro(_DO_GENERATE_TEST_EXPORT_HEADER TARGET_LIBRARY) - # Option overrides - set(options DEFINE_NO_DEPRECATED) - set(oneValueArgs PREFIX_NAME BASE_NAME EXPORT_MACRO_NAME EXPORT_FILE_NAME - DEPRECATED_MACRO_NAME NO_EXPORT_MACRO_NAME STATIC_DEFINE - NO_DEPRECATED_MACRO_NAME) - set(multiValueArgs) - - cmake_parse_arguments(_GEH "${options}" "${oneValueArgs}" "${multiValueArgs}" - ${ARGN}) - - set(BASE_NAME "${TARGET_LIBRARY}") - - if(_GEH_BASE_NAME) - set(BASE_NAME ${_GEH_BASE_NAME}) - endif() - - string(TOUPPER ${BASE_NAME} BASE_NAME_UPPER) - string(TOLOWER ${BASE_NAME} BASE_NAME_LOWER) - - # Default options - set(EXPORT_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_EXPORT") - set(EXPORT_TEST_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_TEST_EXPORT") - set(NO_EXPORT_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_NO_EXPORT") - set(EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME_LOWER}_export.h") - set(DEPRECATED_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_DEPRECATED") - set(STATIC_DEFINE "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_STATIC_DEFINE") - set(NO_DEPRECATED_MACRO_NAME - "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_NO_DEPRECATED") - - if(_GEH_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Unknown keywords given to GENERATE_TEST_EXPORT_HEADER(): \"${_GEH_UNPARSED_ARGUMENTS}\"") - endif() - - if(_GEH_EXPORT_MACRO_NAME) - set(EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_EXPORT_MACRO_NAME}) - set(EXPORT_TEST_MACRO_NAME "${_GEH_PREFIX_NAME}${_GEH_EXPORT_MACRO_NAME}_TEST") - endif() - string(MAKE_C_IDENTIFIER ${EXPORT_MACRO_NAME} EXPORT_MACRO_NAME) - string(MAKE_C_IDENTIFIER ${EXPORT_MACRO_NAME} EXPORT_TEST_MACRO_NAME) - if(_GEH_EXPORT_FILE_NAME) - if(IS_ABSOLUTE ${_GEH_EXPORT_FILE_NAME}) - set(EXPORT_FILE_NAME ${_GEH_EXPORT_FILE_NAME}) - else() - set(EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${_GEH_EXPORT_FILE_NAME}") - endif() - endif() - if(_GEH_DEPRECATED_MACRO_NAME) - set(DEPRECATED_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_DEPRECATED_MACRO_NAME}) - endif() - string(MAKE_C_IDENTIFIER ${DEPRECATED_MACRO_NAME} DEPRECATED_MACRO_NAME) - if(_GEH_NO_EXPORT_MACRO_NAME) - set(NO_EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_NO_EXPORT_MACRO_NAME}) - endif() - string(MAKE_C_IDENTIFIER ${NO_EXPORT_MACRO_NAME} NO_EXPORT_MACRO_NAME) - if(_GEH_STATIC_DEFINE) - set(STATIC_DEFINE ${_GEH_PREFIX_NAME}${_GEH_STATIC_DEFINE}) - endif() - string(MAKE_C_IDENTIFIER ${STATIC_DEFINE} STATIC_DEFINE) - - if(_GEH_DEFINE_NO_DEPRECATED) - set(DEFINE_NO_DEPRECATED TRUE) - endif() - - if(_GEH_NO_DEPRECATED_MACRO_NAME) - set(NO_DEPRECATED_MACRO_NAME - ${_GEH_PREFIX_NAME}${_GEH_NO_DEPRECATED_MACRO_NAME}) - endif() - string(MAKE_C_IDENTIFIER ${NO_DEPRECATED_MACRO_NAME} NO_DEPRECATED_MACRO_NAME) - - set(INCLUDE_GUARD_NAME "${EXPORT_MACRO_NAME}_H") - - get_target_property(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY} DEFINE_SYMBOL) - - if(NOT EXPORT_IMPORT_CONDITION) - set(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY}_EXPORTS) - endif() - string(MAKE_C_IDENTIFIER ${EXPORT_IMPORT_CONDITION} EXPORT_IMPORT_CONDITION) - - configure_file("${_GENERATE_TEST_EXPORT_HEADER_MODULE_DIR}/exporttestheader.cmake.in" - "${EXPORT_FILE_NAME}" @ONLY) -endmacro() - -function(GENERATE_TEST_EXPORT_HEADER TARGET_LIBRARY) - get_property(type TARGET ${TARGET_LIBRARY} PROPERTY TYPE) - if(NOT ${type} STREQUAL "STATIC_LIBRARY" - AND NOT ${type} STREQUAL "SHARED_LIBRARY" - AND NOT ${type} STREQUAL "OBJECT_LIBRARY" - AND NOT ${type} STREQUAL "MODULE_LIBRARY") - message(WARNING "This macro can only be used with libraries") - return() - endif() - _test_compiler_hidden_visibility() - _test_compiler_has_deprecated() - _do_set_macro_values(${TARGET_LIBRARY}) - _do_generate_test_export_header(${TARGET_LIBRARY} ${ARGN}) -endfunction() - -function(add_compiler_export_flags) - if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12) - message(DEPRECATION "The add_compiler_export_flags function is obsolete. Use the CXX_VISIBILITY_PRESET and VISIBILITY_INLINES_HIDDEN target properties instead.") - endif() - - _test_compiler_hidden_visibility() - _test_compiler_has_deprecated() - - if(NOT (USE_COMPILER_HIDDEN_VISIBILITY AND COMPILER_HAS_HIDDEN_VISIBILITY)) - # Just return if there are no flags to add. - return() - endif() - - set (EXTRA_FLAGS "-fvisibility=hidden") - - if(COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) - set (EXTRA_FLAGS "${EXTRA_FLAGS} -fvisibility-inlines-hidden") - endif() - - # Either return the extra flags needed in the supplied argument, or to the - # CMAKE_CXX_FLAGS if no argument is supplied. - if(ARGC GREATER 0) - set(${ARGV0} "${EXTRA_FLAGS}" PARENT_SCOPE) - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_FLAGS}" PARENT_SCOPE) - endif() -endfunction() diff --git a/cmake/modules/KritaAddBrokenUnitTest.cmake b/cmake/modules/KritaAddBrokenUnitTest.cmake index e22fc1454a..c3c89a81b3 100644 --- a/cmake/modules/KritaAddBrokenUnitTest.cmake +++ b/cmake/modules/KritaAddBrokenUnitTest.cmake @@ -1,47 +1,53 @@ include(CMakeParseArguments) include(ECMMarkAsTest) include(ECMMarkNonGuiExecutable) # modified version of ECMAddTests.cmake in cmake-extra-modules function(KRITA_ADD_BROKEN_UNIT_TEST) set(options GUI) # TARGET_NAME_VAR and TEST_NAME_VAR are undocumented args used by # ecm_add_tests set(oneValueArgs TEST_NAME NAME_PREFIX TARGET_NAME_VAR TEST_NAME_VAR) set(multiValueArgs LINK_LIBRARIES) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(_sources ${ARG_UNPARSED_ARGUMENTS}) list(LENGTH _sources _sourceCount) if(ARG_TEST_NAME) set(_targetname ${ARG_TEST_NAME}) elseif(${_sourceCount} EQUAL "1") #use the source file name without extension as the testname get_filename_component(_targetname ${_sources} NAME_WE) else() #more than one source file passed, but no test name given -> error message(FATAL_ERROR "ecm_add_test() called with multiple source files but without setting \"TEST_NAME\"") endif() set(_testname ${ARG_NAME_PREFIX}${_targetname}) - MESSAGE(" * Unittest " ${_testname} " is broken!") + + # add test to the global list of disabled tests + set(KRITA_BROKEN_TESTS ${KRITA_BROKEN_TESTS} ${_testname} CACHE INTERNAL "KRITA_BROKEN_TESTS") set(gui_args) if(ARG_GUI) set(gui_args WIN32 MACOSX_BUNDLE) endif() add_executable(${_targetname} ${gui_args} ${_sources}) if(NOT ARG_GUI) ecm_mark_nongui_executable(${_targetname}) endif() - # do not add it as test, so make test skips it! - # add_test(NAME ${_testname} COMMAND ${_targetname}) + + # do not add it as test, so make test skips it unless asked for it + if(KRITA_ENABLE_BROKEN_TESTS) + add_test(NAME ${_testname} COMMAND ${_targetname}) + endif() + target_link_libraries(${_targetname} ${ARG_LINK_LIBRARIES}) ecm_mark_as_test(${_targetname}) if (ARG_TARGET_NAME_VAR) set(${ARG_TARGET_NAME_VAR} "${_targetname}" PARENT_SCOPE) endif() if (ARG_TEST_NAME_VAR) set(${ARG_TEST_NAME_VAR} "${_testname}" PARENT_SCOPE) endif() endfunction() diff --git a/krita/data/templates/comics/BD-EuroTemplate.desktop b/krita/data/templates/comics/BD-EuroTemplate.desktop index af051139e3..96b751cede 100644 --- a/krita/data/templates/comics/BD-EuroTemplate.desktop +++ b/krita/data/templates/comics/BD-EuroTemplate.desktop @@ -1,63 +1,69 @@ [Desktop Entry] Type=Link URL=.source/BD-EuroTemplate.kra Icon=template_comics_empty Name=European BD template Name[bs]=Evropski BD predložak Name[ca]=Plantilla europea BD Name[ca@valencia]=Plantilla europea BD Name[da]=Europæisk BD-skabelon Name[de]=Europäische „Bande Dessinée (BD)“-Vorlage Name[el]=Ευρωπαϊκό BD πρότυπο Name[en_GB]=European BD template Name[es]=plantilla de cómic europeo Name[et]=Euroopa BD mall Name[eu]=Europako BD-txantiloia Name[fi]=Eurooppalainen BD-pohja Name[fr]=Modèle européen de bandes dessinées Name[gl]=Formato europeo (2×4 viñetas) Name[hu]=Európai BD sablon Name[it]=Modello MD europeo Name[kk]=Еуропалық BD үлгісі Name[lt]=Europos DB šablonas +Name[nb]=Europeisk BD-mal Name[nds]=Europääsch BD-Vörlaag Name[nl]=Europees BD-sjabloon Name[pl]=Europejski szablon BD +Name[pt]=Modelo de BD Europeia Name[pt_BR]=Modelo Europeu BD Name[ru]=Шаблон в европейском стиле (BD) Name[sk]=Európska BD šablóna Name[sl]=Evropska predloga BD Name[sv]=Europeisk BD-mall Name[tr]=Avrupa BD Şablonu Name[uk]=Європейський шаблон BD Name[wa]=Modele di binde d' imådje a l' uropeyinne +Name[x-test]=xxEuropean BD templatexx Name[zh_TW]=歐式 BD 樣本 Comment=template for European BD-style comics Comment[bs]=predložak za evropske BD stripove Comment[ca]=plantilla per a còmics d'estil BD europeu Comment[ca@valencia]=plantilla per a còmics d'estil BD europeu Comment[da]=Skabelon til tegneserier i europæisk BD-stil Comment[de]=Vorlage für Comics im europäischen „Bande Dessinée“-Stil Comment[el]=πρότυπο για Ευρωπαϊκά BD-style κόμικς Comment[en_GB]=template for European BD-style comics Comment[es]=plantilla para cómics de estilo europeo Comment[et]=Euroopa BD-stiilis koomiksi mall Comment[eu]=Europako BD estiloko komikietarako txantiloia Comment[fi]=Eurooppalaisen BD-tyylin sarjakuvan pohja Comment[fr]=Modèle européen de bandes dessinées Comment[gl]=Páxina de banda deseñada de formato europeo, con 2×4 viñetas regulares. Comment[hu]=sablon az európai BD-stílusú képregényekhez Comment[it]=modello per fumetti in stile BD europeo Comment[kk]=Еуропалық BD-стильдегі комикс үлгісі +Comment[nb]=mal for europeiske tegneserier i BD-stil Comment[nds]=BD-Vörlaag för europääsche Comics Comment[nl]=sjabloon voor Europese strips in BD-stijl Comment[pl]=szablon dla Europejskiego stylu komików BD +Comment[pt]=modelo de banda desenhada do estilo Europeu Comment[pt_BR]=Modelo de quadrinhos no estilo Europeu BD Comment[ru]=Шаблон комиксов в европейском стиле (BD) Comment[sk]=šablóna pre európske BD komixy Comment[sl]=predloga za stripe v evropskem slogu BD Comment[sv]=seriemall med europeisk BD-stil Comment[uk]=шаблон для європейських коміксів у стилі BD Comment[wa]=Modele po les bindes d' imådje al môde uropeyinne +Comment[x-test]=xxtemplate for European BD-style comicsxx Comment[zh_TW]=歐式 BD-樣式漫畫的樣本 X-Krita-Version=28 diff --git a/krita/integration/LICENSE b/krita/integration/LICENSE new file mode 100644 index 0000000000..2e6a0b73d4 --- /dev/null +++ b/krita/integration/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/krita/integration/README.md b/krita/integration/README.md new file mode 100644 index 0000000000..e46f7fb4e3 --- /dev/null +++ b/krita/integration/README.md @@ -0,0 +1,9 @@ +# Krita-QuickLook +QuickLook Generator plugin for .kra and .ora files. + +This generator takes the preview.png image and uses it as the thumbnail image and the mergedimage.png file as the preview image. On files created with older versions of Krita that do not have the mergedimage.png file, QuickLook will simply fall back to using the thumbnail image instead. + +# Installing +Place the generator in the `/Library/QuickLook` folder. + +If you package Krita 3.0, you can include the generator file in the directory `krita.app/Contents/Library/QuickLook`. Be sure to reset QuickLook with `qlmanage -r` and `qlmanage -r cache`. If the changes don't happen right away, `killall Finder` and ensure that the app you put the generator in is the default app for opening .kra files. diff --git a/krita/integration/kritaquicklook.xcodeproj/project.pbxproj b/krita/integration/kritaquicklook.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..ff141194b9 --- /dev/null +++ b/krita/integration/kritaquicklook.xcodeproj/project.pbxproj @@ -0,0 +1,301 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + E13E64F11C08579B0062F932 /* GenerateThumbnailForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = E13E64F01C08579B0062F932 /* GenerateThumbnailForURL.m */; }; + E13E64F31C08579B0062F932 /* GeneratePreviewForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = E13E64F21C08579B0062F932 /* GeneratePreviewForURL.m */; }; + E13E64F51C08579B0062F932 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = E13E64F41C08579B0062F932 /* main.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + E13E64EB1C08579B0062F932 /* Krita.qlgenerator */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Krita.qlgenerator; sourceTree = BUILT_PRODUCTS_DIR; }; + E13E64EF1C08579B0062F932 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E13E64F01C08579B0062F932 /* GenerateThumbnailForURL.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GenerateThumbnailForURL.m; sourceTree = ""; }; + E13E64F21C08579B0062F932 /* GeneratePreviewForURL.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GeneratePreviewForURL.m; sourceTree = ""; }; + E13E64F41C08579B0062F932 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E13E64E71C08579B0062F932 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + E13E64E11C08579B0062F932 = { + isa = PBXGroup; + children = ( + E13E64ED1C08579B0062F932 /* kritaquicklook */, + E13E64EC1C08579B0062F932 /* Products */, + ); + sourceTree = ""; + }; + E13E64EC1C08579B0062F932 /* Products */ = { + isa = PBXGroup; + children = ( + E13E64EB1C08579B0062F932 /* Krita.qlgenerator */, + ); + name = Products; + sourceTree = ""; + }; + E13E64ED1C08579B0062F932 /* kritaquicklook */ = { + isa = PBXGroup; + children = ( + E13E64F01C08579B0062F932 /* GenerateThumbnailForURL.m */, + E13E64F21C08579B0062F932 /* GeneratePreviewForURL.m */, + E13E64F41C08579B0062F932 /* main.c */, + E13E64EE1C08579B0062F932 /* Supporting Files */, + ); + path = kritaquicklook; + sourceTree = ""; + }; + E13E64EE1C08579B0062F932 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + E13E64EF1C08579B0062F932 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + E13E64E81C08579B0062F932 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + E13E64EA1C08579B0062F932 /* kritaquicklook */ = { + isa = PBXNativeTarget; + buildConfigurationList = E13E64F81C08579B0062F932 /* Build configuration list for PBXNativeTarget "kritaquicklook" */; + buildPhases = ( + E13E64E61C08579B0062F932 /* Sources */, + E13E64E71C08579B0062F932 /* Frameworks */, + E13E64E81C08579B0062F932 /* Headers */, + E13E64E91C08579B0062F932 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = kritaquicklook; + productName = Krita; + productReference = E13E64EB1C08579B0062F932 /* Krita.qlgenerator */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E13E64E21C08579B0062F932 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0620; + ORGANIZATIONNAME = "Krita Foundation"; + TargetAttributes = { + E13E64EA1C08579B0062F932 = { + CreatedOnToolsVersion = 6.2; + }; + }; + }; + buildConfigurationList = E13E64E51C08579B0062F932 /* Build configuration list for PBXProject "kritaquicklook" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = E13E64E11C08579B0062F932; + productRefGroup = E13E64EC1C08579B0062F932 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E13E64EA1C08579B0062F932 /* kritaquicklook */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + E13E64E91C08579B0062F932 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + E13E64E61C08579B0062F932 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E13E64F11C08579B0062F932 /* GenerateThumbnailForURL.m in Sources */, + E13E64F31C08579B0062F932 /* GeneratePreviewForURL.m in Sources */, + E13E64F51C08579B0062F932 /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + E13E64F61C08579B0062F932 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + E13E64F71C08579B0062F932 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + E13E64F91C08579B0062F932 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_ENABLE_OBJC_ARC = NO; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + /Users/alvina/kf5/QuickLook/ZipFramework, + "/Users/alvina/kf5/QuickLook/ZipFramework-src", + ); + INFOPLIST_FILE = kritaquicklook/Info.plist; + INSTALL_PATH = /Library/QuickLook; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /Users/alvina/kf5/QuickLook/ZipArchive, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = ""; + "USER_HEADER_SEARCH_PATHS[arch=*]" = "/Users/alvina/kf5/QuickLook/ZipFramework-src/**"; + WRAPPER_EXTENSION = qlgenerator; + }; + name = Debug; + }; + E13E64FA1C08579B0062F932 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_ENABLE_OBJC_ARC = NO; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + /Users/alvina/kf5/QuickLook/ZipFramework, + "/Users/alvina/kf5/QuickLook/ZipFramework-src", + ); + INFOPLIST_FILE = kritaquicklook/Info.plist; + INSTALL_PATH = /Library/QuickLook; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /Users/alvina/kf5/QuickLook/ZipArchive, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = ""; + "USER_HEADER_SEARCH_PATHS[arch=*]" = "/Users/alvina/kf5/QuickLook/ZipFramework-src/**"; + WRAPPER_EXTENSION = qlgenerator; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + E13E64E51C08579B0062F932 /* Build configuration list for PBXProject "kritaquicklook" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E13E64F61C08579B0062F932 /* Debug */, + E13E64F71C08579B0062F932 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E13E64F81C08579B0062F932 /* Build configuration list for PBXNativeTarget "kritaquicklook" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E13E64F91C08579B0062F932 /* Debug */, + E13E64FA1C08579B0062F932 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = E13E64E21C08579B0062F932 /* Project object */; +} diff --git a/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..5c7d033f10 --- /dev/null +++ b/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/xcshareddata/Krita.xccheckout b/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/xcshareddata/Krita.xccheckout new file mode 100644 index 0000000000..7671f592ed --- /dev/null +++ b/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/xcshareddata/Krita.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + E3E24D36-805E-4EB4-AB6F-CCF8DE1EC9DF + IDESourceControlProjectName + Krita + IDESourceControlProjectOriginsDictionary + + A5B8AD5391A8194BF497FF65F2909CBC9A9EB430 + https://github.com/Algorithmus/Krita-QuickLook + + IDESourceControlProjectPath + Krita.xcodeproj + IDESourceControlProjectRelativeInstallPathDictionary + + A5B8AD5391A8194BF497FF65F2909CBC9A9EB430 + ../.. + + IDESourceControlProjectURL + https://github.com/Algorithmus/Krita-QuickLook + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + A5B8AD5391A8194BF497FF65F2909CBC9A9EB430 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + A5B8AD5391A8194BF497FF65F2909CBC9A9EB430 + IDESourceControlWCCName + Krita + + + + diff --git a/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/xcshareddata/kritaquicklook.xccheckout b/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/xcshareddata/kritaquicklook.xccheckout new file mode 100644 index 0000000000..6bd583d3b2 --- /dev/null +++ b/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/xcshareddata/kritaquicklook.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 28DD4631-F598-46F8-A5D9-6D5A4C867DCB + IDESourceControlProjectName + kritaquicklook + IDESourceControlProjectOriginsDictionary + + A5B8AD5391A8194BF497FF65F2909CBC9A9EB430 + https://github.com/algorithmus/krita-quicklook.git + + IDESourceControlProjectPath + kritaquicklook.xcodeproj + IDESourceControlProjectRelativeInstallPathDictionary + + A5B8AD5391A8194BF497FF65F2909CBC9A9EB430 + ../.. + + IDESourceControlProjectURL + https://github.com/algorithmus/krita-quicklook.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + A5B8AD5391A8194BF497FF65F2909CBC9A9EB430 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + A5B8AD5391A8194BF497FF65F2909CBC9A9EB430 + IDESourceControlWCCName + krita-quicklook + + + + diff --git a/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/xcuserdata/alvina.xcuserdatad/UserInterfaceState.xcuserstate b/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/xcuserdata/alvina.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000..547f3f97a6 Binary files /dev/null and b/krita/integration/kritaquicklook.xcodeproj/project.xcworkspace/xcuserdata/alvina.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/krita/integration/kritaquicklook.xcodeproj/xcuserdata/alvina.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/krita/integration/kritaquicklook.xcodeproj/xcuserdata/alvina.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000000..c5b338eae9 --- /dev/null +++ b/krita/integration/kritaquicklook.xcodeproj/xcuserdata/alvina.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/krita/integration/kritaquicklook.xcodeproj/xcuserdata/alvina.xcuserdatad/xcschemes/kritaquicklook.xcscheme b/krita/integration/kritaquicklook.xcodeproj/xcuserdata/alvina.xcuserdatad/xcschemes/kritaquicklook.xcscheme new file mode 100644 index 0000000000..3fecd44f03 --- /dev/null +++ b/krita/integration/kritaquicklook.xcodeproj/xcuserdata/alvina.xcuserdatad/xcschemes/kritaquicklook.xcscheme @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/krita/integration/kritaquicklook.xcodeproj/xcuserdata/alvina.xcuserdatad/xcschemes/xcschememanagement.plist b/krita/integration/kritaquicklook.xcodeproj/xcuserdata/alvina.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000000..780c7c48d2 --- /dev/null +++ b/krita/integration/kritaquicklook.xcodeproj/xcuserdata/alvina.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,27 @@ + + + + + SchemeUserState + + Krita.xcscheme + + orderHint + 0 + + kritaquicklook.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + E13E64EA1C08579B0062F932 + + primary + + + + + diff --git a/krita/integration/quicklook/GeneratePreviewForURL.m b/krita/integration/kritaquicklook/GeneratePreviewForURL.m similarity index 100% rename from krita/integration/quicklook/GeneratePreviewForURL.m rename to krita/integration/kritaquicklook/GeneratePreviewForURL.m diff --git a/krita/integration/quicklook/GenerateThumbnailForURL.m b/krita/integration/kritaquicklook/GenerateThumbnailForURL.m similarity index 100% rename from krita/integration/quicklook/GenerateThumbnailForURL.m rename to krita/integration/kritaquicklook/GenerateThumbnailForURL.m diff --git a/krita/integration/quicklook/Info.plist b/krita/integration/kritaquicklook/Info.plist similarity index 100% rename from krita/integration/quicklook/Info.plist rename to krita/integration/kritaquicklook/Info.plist diff --git a/krita/integration/kritaquicklook/LICENSE b/krita/integration/kritaquicklook/LICENSE new file mode 100644 index 0000000000..2e6a0b73d4 --- /dev/null +++ b/krita/integration/kritaquicklook/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/krita/integration/kritaquicklook/README.md b/krita/integration/kritaquicklook/README.md new file mode 100644 index 0000000000..e46f7fb4e3 --- /dev/null +++ b/krita/integration/kritaquicklook/README.md @@ -0,0 +1,9 @@ +# Krita-QuickLook +QuickLook Generator plugin for .kra and .ora files. + +This generator takes the preview.png image and uses it as the thumbnail image and the mergedimage.png file as the preview image. On files created with older versions of Krita that do not have the mergedimage.png file, QuickLook will simply fall back to using the thumbnail image instead. + +# Installing +Place the generator in the `/Library/QuickLook` folder. + +If you package Krita 3.0, you can include the generator file in the directory `krita.app/Contents/Library/QuickLook`. Be sure to reset QuickLook with `qlmanage -r` and `qlmanage -r cache`. If the changes don't happen right away, `killall Finder` and ensure that the app you put the generator in is the default app for opening .kra files. diff --git a/krita/integration/quicklook/main.c b/krita/integration/kritaquicklook/main.c similarity index 100% rename from krita/integration/quicklook/main.c rename to krita/integration/kritaquicklook/main.c diff --git a/krita/integration/quicklook/CMakeLists.txt b/krita/integration/quicklook/CMakeLists.txt deleted file mode 100644 index 5944d09b2e..0000000000 --- a/krita/integration/quicklook/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -project(quicklook) - -set(kritaquicklook_SRCS - GeneratePreviewForURL.m - GenerateThumbnailForURL.m - main.c -) - -set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-bundle -headerpad_max_install_names") -add_library(kritaquicklook MODULE ${kritaquicklook_SRCS}) - -find_library(FOUNDATION_LIBRARY Foundation) -find_library(COREGRAPHICS_LIBRARY CoreGraphics) -find_library(QUICKLOOK_LIBRARY QuickLook) -find_library(COCOA_LIBRARY Cocoa) - -target_link_libraries(kritaquicklook - ${FOUNDATION_LIBRARY} - ${COREGRAPHICS_LIBRARY} - ${QUICKLOOK_LIBRARY} - ${COCOA_LIBRARY} -) - -set_target_properties(kritaquicklook PROPERTIES - FRAMEWORK TRUE - MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist" - SUFFIX .qlgenerator -) - -install(TARGETS kritaquicklook DESTINATION ${PLUGIN_INSTALL_DIR}) - diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 8e8b1fbfe1..542bcc8f7c 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,20 +1,17 @@ add_subdirectory( version ) add_subdirectory( global ) add_subdirectory( koplugin ) add_subdirectory( widgetutils ) add_subdirectory( widgets ) add_subdirectory( store ) add_subdirectory( odf ) add_subdirectory( flake ) add_subdirectory( basicflakes ) add_subdirectory( pigment ) add_subdirectory( kundo2 ) add_subdirectory( brush ) add_subdirectory( psd ) add_subdirectory( color ) add_subdirectory( image ) add_subdirectory( ui ) - -if (SHOULD_BUILD_LIB_KOVECTORIMAGE) - add_subdirectory( vectorimage ) -endif () +add_subdirectory( vectorimage ) diff --git a/libs/brush/CMakeLists.txt b/libs/brush/CMakeLists.txt index 704906c8b9..88e61fe607 100644 --- a/libs/brush/CMakeLists.txt +++ b/libs/brush/CMakeLists.txt @@ -1,51 +1,49 @@ add_subdirectory( tests ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ) set(kritalibbrush_LIB_SRCS kis_predefined_brush_factory.cpp kis_auto_brush.cpp kis_boundary.cc kis_brush.cpp kis_scaling_size_brush.cpp kis_brush_registry.cpp kis_brush_server.cpp kis_gbr_brush.cpp kis_abr_brush.cpp kis_abr_brush_collection.cpp kis_imagepipe_brush.cpp kis_pipebrush_parasite.cpp kis_png_brush.cpp kis_svg_brush.cpp kis_qimage_pyramid.cpp kis_text_brush.cpp kis_auto_brush_factory.cpp kis_text_brush_factory.cpp ) add_library(kritalibbrush SHARED ${kritalibbrush_LIB_SRCS} ) generate_export_header(kritalibbrush BASE_NAME kritabrush EXPORT_MACRO_NAME BRUSH_EXPORT) if (WIN32) target_link_libraries(kritalibbrush kritaimage Qt5::Svg ${WIN32_PLATFORM_NET_LIBS}) else () target_link_libraries(kritalibbrush kritaimage Qt5::Svg) endif () if(HAVE_VC) include_directories(SYSTEM ${Vc_INCLUDE_DIR}) target_link_libraries(kritalibbrush ${Vc_LIBRARIES}) # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Vc_DEFINITIONS}") endif() -target_link_libraries(kritalibbrush LINK_INTERFACE_LIBRARIES kritaimage Qt5::Svg) - set_target_properties(kritalibbrush PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritalibbrush ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/color/CMakeLists.txt b/libs/color/CMakeLists.txt index 818b2190de..88f55f769d 100644 --- a/libs/color/CMakeLists.txt +++ b/libs/color/CMakeLists.txt @@ -1,25 +1,23 @@ if (UNIX AND NOT APPLE AND HAVE_DBUS) add_subdirectory(colord) set(kritacolor_LIB_SRCS kis_color_manager.h linux/kis_color_manager.cpp) set(kritacolor_EXTRA_LIBRARIES kritacolord) set_target_properties(kritacolord PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) elseif (MSVC) set(kritacolor_LIB_SRCS kis_color_manager.h dummy/kis_color_manager.cpp ${CMAKE_CURRENT_BINARY_DIR}/kritacolor_export.h) else () set(kritacolor_LIB_SRCS kis_color_manager.h dummy/kis_color_manager.cpp) endif () add_library(kritacolor SHARED ${kritacolor_LIB_SRCS} ) generate_export_header(kritacolor BASE_NAME kritacolor) target_link_libraries(kritacolor kritaglobal ${QT_QTCORE_LIBRARY} KF5::I18n ${kritacolor_EXTRA_LIBRARIES}) -target_link_libraries(kritacolor LINK_INTERFACE_LIBRARIES kritaglobal ${QT_QTCORE_LIBRARY}) - set_target_properties(kritacolor PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritacolor ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/flake/CMakeLists.txt b/libs/flake/CMakeLists.txt index aef106e243..e9a3bbde8a 100644 --- a/libs/flake/CMakeLists.txt +++ b/libs/flake/CMakeLists.txt @@ -1,226 +1,225 @@ project(kritaflake) include_directories( ${CMAKE_SOURCE_DIR}/libs/flake/commands ${CMAKE_SOURCE_DIR}/libs/flake/tools ${CMAKE_SOURCE_DIR}/libs/flake/svg ${CMAKE_BINARY_DIR}/libs/flake ) add_subdirectory(styles) add_subdirectory(tests) set(kritaflake_SRCS KoGradientHelper.cpp KoFlake.cpp KoCanvasBase.cpp KoResourceManager_p.cpp KoDerivedResourceConverter.cpp KoResourceUpdateMediator.cpp KoCanvasResourceManager.cpp KoDocumentResourceManager.cpp KoCanvasObserverBase.cpp KoCanvasSupervisor.cpp KoDockFactoryBase.cpp KoDockRegistry.cpp KoDataCenterBase.cpp KoInsets.cpp KoPathShape.cpp KoPathPoint.cpp KoPathSegment.cpp KoSelection.cpp KoShape.cpp KoShapeAnchor.cpp KoShapeBasedDocumentBase.cpp KoShapeApplicationData.cpp KoShapeContainer.cpp KoShapeContainerModel.cpp KoShapeContainerDefaultModel.cpp KoShapeGroup.cpp KoShapeManagerPaintingStrategy.cpp KoShapeManager.cpp KoShapePaintingContext.cpp KoFrameShape.cpp KoUnavailShape.cpp KoMarkerData.cpp KoMarker.cpp KoMarkerCollection.cpp KoMarkerSharedLoadingData.cpp KoToolBase.cpp KoCanvasController.cpp KoCanvasControllerWidget.cpp KoCanvasControllerWidgetViewport_p.cpp KoShapeRegistry.cpp KoDeferredShapeFactoryBase.cpp KoToolFactoryBase.cpp KoPathShapeFactory.cpp KoShapeFactoryBase.cpp KoShapeUserData.cpp KoParameterShape.cpp KoPointerEvent.cpp KoShapeController.cpp KoToolSelection.cpp KoShapeLayer.cpp KoPostscriptPaintDevice.cpp KoInputDevice.cpp KoToolManager_p.cpp KoToolManager.cpp KoToolRegistry.cpp KoToolProxy.cpp KoShapeSavingContext.cpp KoShapeLoadingContext.cpp KoLoadingShapeUpdater.cpp KoPathShapeLoader.cpp KoShapeStrokeModel.cpp KoShapeStroke.cpp KoShapeBackground.cpp KoColorBackground.cpp KoGradientBackground.cpp KoOdfGradientBackground.cpp KoHatchBackground.cpp KoPatternBackground.cpp KoShapeConfigWidgetBase.cpp KoDrag.cpp KoDragOdfSaveHelper.cpp KoShapeOdfSaveHelper.cpp KoShapePaste.cpp KoConnectionPoint.cpp KoConnectionShape.cpp KoConnectionShapeLoadingUpdater.cpp KoConnectionShapeFactory.cpp KoConnectionShapeConfigWidget.cpp KoSnapGuide.cpp KoSnapProxy.cpp KoSnapStrategy.cpp KoSnapData.cpp KoShapeShadow.cpp KoSharedLoadingData.cpp KoSharedSavingData.cpp KoViewConverter.cpp KoInputDeviceHandler.cpp KoInputDeviceHandlerEvent.cpp KoInputDeviceHandlerRegistry.cpp KoImageData.cpp KoImageData_p.cpp KoImageCollection.cpp KoOdfWorkaround.cpp KoFilterEffect.cpp KoFilterEffectStack.cpp KoFilterEffectFactoryBase.cpp KoFilterEffectRegistry.cpp KoFilterEffectConfigWidgetBase.cpp KoFilterEffectRenderContext.cpp KoFilterEffectLoadingContext.cpp KoTextShapeDataBase.cpp KoTosContainer.cpp KoTosContainerModel.cpp KoClipPath.cpp KoCurveFit.cpp commands/KoShapeGroupCommand.cpp commands/KoShapeAlignCommand.cpp commands/KoShapeBackgroundCommand.cpp commands/KoShapeCreateCommand.cpp commands/KoShapeDeleteCommand.cpp commands/KoShapeDistributeCommand.cpp commands/KoShapeLockCommand.cpp commands/KoShapeMoveCommand.cpp commands/KoShapeShearCommand.cpp commands/KoShapeSizeCommand.cpp commands/KoShapeStrokeCommand.cpp commands/KoShapeUngroupCommand.cpp commands/KoShapeReorderCommand.cpp commands/KoShapeKeepAspectRatioCommand.cpp commands/KoPathBaseCommand.cpp commands/KoPathPointMoveCommand.cpp commands/KoPathControlPointMoveCommand.cpp commands/KoPathPointTypeCommand.cpp commands/KoPathPointRemoveCommand.cpp commands/KoPathPointInsertCommand.cpp commands/KoPathSegmentBreakCommand.cpp commands/KoPathBreakAtPointCommand.cpp commands/KoPathSegmentTypeCommand.cpp commands/KoPathCombineCommand.cpp commands/KoSubpathRemoveCommand.cpp commands/KoSubpathJoinCommand.cpp commands/KoParameterHandleMoveCommand.cpp commands/KoParameterToPathCommand.cpp commands/KoShapeTransformCommand.cpp commands/KoPathFillRuleCommand.cpp commands/KoConnectionShapeTypeCommand.cpp commands/KoShapeShadowCommand.cpp commands/KoPathReverseCommand.cpp commands/KoShapeRenameCommand.cpp commands/KoShapeRunAroundCommand.cpp commands/KoPathPointMergeCommand.cpp commands/KoShapeTransparencyCommand.cpp commands/KoShapeClipCommand.cpp commands/KoShapeUnclipCommand.cpp commands/KoPathShapeMarkerCommand.cpp commands/KoShapeConnectionChangeCommand.cpp tools/KoCreateShapeStrategy.cpp tools/KoPathToolFactory.cpp tools/KoPathTool.cpp tools/KoPathToolSelection.cpp tools/KoPathToolHandle.cpp tools/PathToolOptionWidget.cpp tools/KoPathPointRubberSelectStrategy.cpp tools/KoPathPointMoveStrategy.cpp tools/KoPathConnectionPointStrategy.cpp tools/KoPathControlPointMoveStrategy.cpp tools/KoParameterChangeStrategy.cpp tools/KoZoomTool.cpp tools/KoZoomToolFactory.cpp tools/KoZoomToolWidget.cpp tools/KoZoomStrategy.cpp tools/KoPanTool.cpp tools/KoPanToolFactory.cpp tools/KoInteractionTool.cpp tools/KoInteractionStrategy.cpp tools/KoCreateShapesTool.cpp tools/KoCreateShapesToolFactory.cpp tools/KoShapeRubberSelectStrategy.cpp tools/KoPathSegmentChangeStrategy.cpp svg/KoShapePainter.cpp svg/SvgUtil.cpp svg/SvgGraphicContext.cpp svg/SvgSavingContext.cpp svg/SvgWriter.cpp svg/SvgStyleWriter.cpp svg/SvgShape.cpp svg/SvgParser.cpp svg/SvgStyleParser.cpp svg/SvgGradientHelper.cpp svg/SvgPatternHelper.cpp svg/SvgFilterHelper.cpp svg/SvgCssHelper.cpp svg/SvgClipPathHelper.cpp svg/SvgLoadingContext.cpp svg/SvgShapeFactory.cpp FlakeDebug.cpp ) ki18n_wrap_ui(kritaflake_SRCS tools/PathToolOptionWidgetBase.ui KoConnectionShapeConfigWidget.ui tools/KoZoomToolWidget.ui ) add_library(kritaflake SHARED ${kritaflake_SRCS}) generate_export_header(kritaflake BASE_NAME kritaflake) target_include_directories(kritaflake PUBLIC $ $ $ ) target_link_libraries(kritaflake kritapigment kritawidgetutils kritaodf kritaundo2 KF5::WidgetsAddons Qt5::Svg) -target_link_libraries(kritaflake LINK_INTERFACE_LIBRARIES kritapigment kritawidgetutils kritaodf kritaundo2 KF5::WidgetsAddons ) set_target_properties(kritaflake PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaflake ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/image/brushengine/kis_paintop_preset.cpp b/libs/image/brushengine/kis_paintop_preset.cpp index 45f8e40db7..5e42e14d55 100644 --- a/libs/image/brushengine/kis_paintop_preset.cpp +++ b/libs/image/brushengine/kis_paintop_preset.cpp @@ -1,405 +1,405 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * Copyright (C) Sven Langkamp , (C) 2009 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include "kis_paintop_registry.h" #include "kis_painter.h" #include #include "kis_paint_device.h" #include "kis_image.h" #include "kis_paintop_settings_update_proxy.h" #include #include struct Q_DECL_HIDDEN KisPaintOpPreset::Private { Private() : settings(0), dirtyPreset(false) { } KisPaintOpSettingsSP settings; bool dirtyPreset; QScopedPointer updateProxy; }; KisPaintOpPreset::KisPaintOpPreset() : KoResource(QString()) , m_d(new Private) { } KisPaintOpPreset::KisPaintOpPreset(const QString & fileName) : KoResource(fileName) , m_d(new Private) { } KisPaintOpPreset::~KisPaintOpPreset() { delete m_d; } KisPaintOpPresetSP KisPaintOpPreset::clone() const { KisPaintOpPresetSP preset = new KisPaintOpPreset(); if (settings()) { preset->setSettings(settings()); // the settings are cloned inside! } preset->setPresetDirty(isPresetDirty()); // only valid if we could clone the settings preset->setValid(settings()); preset->setPaintOp(paintOp()); preset->setName(name()); preset->setImage(image()); preset->settings()->setPreset(KisPaintOpPresetWSP(preset)); Q_ASSERT(preset->valid()); return preset; } void KisPaintOpPreset::setPresetDirty(bool value) { m_d->dirtyPreset = value; } bool KisPaintOpPreset::isPresetDirty() const { return m_d->dirtyPreset; } void KisPaintOpPreset::setPaintOp(const KoID & paintOp) { Q_ASSERT(m_d->settings); m_d->settings->setProperty("paintop", paintOp.id()); } KoID KisPaintOpPreset::paintOp() const { Q_ASSERT(m_d->settings); return KoID(m_d->settings->getString("paintop"), name()); } void KisPaintOpPreset::setOptionsWidget(KisPaintOpConfigWidget* widget) { if (m_d->settings) { m_d->settings->setOptionsWidget(widget); if (widget) { widget->setConfigurationSafe(m_d->settings); } } } void KisPaintOpPreset::setSettings(KisPaintOpSettingsSP settings) { Q_ASSERT(settings); - Q_ASSERT(!settings->getString("paintop", "").isEmpty()); + Q_ASSERT(!settings->getString("paintop", QString()).isEmpty()); DirtyStateSaver dirtyStateSaver(this); KisPaintOpConfigWidget *oldOptionsWidget = 0; if (m_d->settings) { oldOptionsWidget = m_d->settings->optionsWidget(); m_d->settings->setOptionsWidget(0); m_d->settings->setPreset(0); m_d->settings = 0; } if (settings) { m_d->settings = settings->clone(); m_d->settings->setPreset(KisPaintOpPresetWSP(this)); if (oldOptionsWidget) { m_d->settings->setOptionsWidget(oldOptionsWidget); oldOptionsWidget->setConfigurationSafe(m_d->settings); } } setValid(m_d->settings); if (m_d->updateProxy) { m_d->updateProxy->notifyUniformPropertiesChanged(); m_d->updateProxy->notifySettingsChanged(); } } KisPaintOpSettingsSP KisPaintOpPreset::settings() const { Q_ASSERT(m_d->settings); - Q_ASSERT(!m_d->settings->getString("paintop", "").isEmpty()); + Q_ASSERT(!m_d->settings->getString("paintop", QString()).isEmpty()); return m_d->settings; } bool KisPaintOpPreset::load() { dbgImage << "Load preset " << filename(); setValid(false); if (filename().isEmpty()) { return false; } QIODevice *dev = 0; QByteArray ba; if (filename().startsWith("bundle://")) { QString bn = filename().mid(9); int pos = bn.lastIndexOf(":"); QString fn = bn.right(bn.size() - pos - 1); bn = bn.left(pos); QScopedPointer resourceStore(KoStore::createStore(bn, KoStore::Read, "application/x-krita-resourcebundle", KoStore::Zip)); if (!resourceStore || resourceStore->bad()) { warnKrita << "Could not open store on bundle" << bn; return false; } if (resourceStore->isOpen()) resourceStore->close(); if (!resourceStore->open(fn)) { warnKrita << "Could not open preset" << fn << "in bundle" << bn; return false; } ba = resourceStore->device()->readAll(); dev = new QBuffer(&ba); resourceStore->close(); } else { dev = new QFile(filename()); if (dev->size() == 0) { delete dev; return false; } if (!dev->open(QIODevice::ReadOnly)) { warnKrita << "Can't open file " << filename(); delete dev; return false; } } bool res = loadFromDevice(dev); delete dev; setValid(res); setPresetDirty(false); return res; } bool KisPaintOpPreset::loadFromDevice(QIODevice *dev) { QImageReader reader(dev, "PNG"); QString version = reader.text("version"); QString preset = reader.text("preset"); dbgImage << version; if (version != "2.2") { return false; } QImage img; if (!reader.read(&img)) { dbgImage << "Fail to decode PNG"; return false; } //Workaround for broken presets //Presets was saved with nested cdata section preset.replace(""); preset.replace("]]>", ""); QDomDocument doc; if (!doc.setContent(preset)) { return false; } fromXML(doc.documentElement()); if (!m_d->settings) { return false; } setValid(true); setImage(img); return true; } bool KisPaintOpPreset::save() { if (filename().isEmpty()) return false; - QString paintopid = m_d->settings->getString("paintop", ""); + QString paintopid = m_d->settings->getString("paintop", QString()); if (paintopid.isEmpty()) return false; QFile f(filename()); f.open(QFile::WriteOnly); return saveToDevice(&f); } void KisPaintOpPreset::toXML(QDomDocument& doc, QDomElement& elt) const { - QString paintopid = m_d->settings->getString("paintop", ""); + QString paintopid = m_d->settings->getString("paintop", QString()); elt.setAttribute("paintopid", paintopid); elt.setAttribute("name", name()); // sanitize the settings bool hasTexture = m_d->settings->getBool("Texture/Pattern/Enabled"); if (!hasTexture) { Q_FOREACH (const QString & key, m_d->settings->getProperties().keys()) { if (key.startsWith("Texture") && key != "Texture/Pattern/Enabled") { m_d->settings->removeProperty(key); } } } m_d->settings->toXML(doc, elt); } void KisPaintOpPreset::fromXML(const QDomElement& presetElt) { setName(presetElt.attribute("name")); QString paintopid = presetElt.attribute("paintopid"); if (paintopid.isEmpty()) { dbgImage << "No paintopid attribute"; setValid(false); return; } if (KisPaintOpRegistry::instance()->get(paintopid) == 0) { dbgImage << "No paintop " << paintopid; setValid(false); return; } - KoID id(paintopid, ""); + KoID id(paintopid, QString()); KisPaintOpSettingsSP settings = KisPaintOpRegistry::instance()->settings(id); if (!settings) { setValid(false); warnKrita << "Could not load settings for preset" << paintopid; return; } settings->fromXML(presetElt); // sanitize the settings bool hasTexture = settings->getBool("Texture/Pattern/Enabled"); if (!hasTexture) { Q_FOREACH (const QString & key, settings->getProperties().keys()) { if (key.startsWith("Texture") && key != "Texture/Pattern/Enabled") { settings->removeProperty(key); } } } setSettings(settings); } bool KisPaintOpPreset::saveToDevice(QIODevice *dev) const { QImageWriter writer(dev, "PNG"); QDomDocument doc; QDomElement root = doc.createElement("Preset"); toXML(doc, root); doc.appendChild(root); writer.setText("version", "2.2"); writer.setText("preset", doc.toString()); QImage img; if (image().isNull()) { img = QImage(1, 1, QImage::Format_RGB32); } else { img = image(); } m_d->dirtyPreset = false; KoResource::saveToDevice(dev); return writer.write(img); } KisPaintopSettingsUpdateProxy* KisPaintOpPreset::updateProxy() const { if (!m_d->updateProxy) { m_d->updateProxy.reset(new KisPaintopSettingsUpdateProxy()); } return m_d->updateProxy.data(); } KisPaintopSettingsUpdateProxy* KisPaintOpPreset::updateProxyNoCreate() const { return m_d->updateProxy.data(); } QList KisPaintOpPreset::uniformProperties() { return m_d->settings->uniformProperties(m_d->settings); } KisPaintOpPreset::UpdatedPostponer::UpdatedPostponer(KisPaintOpPreset *preset) : m_updateProxy(preset->updateProxyNoCreate()) { if (m_updateProxy) { m_updateProxy->postponeSettingsChanges(); } } KisPaintOpPreset::UpdatedPostponer::~UpdatedPostponer() { if (m_updateProxy) { m_updateProxy->unpostponeSettingsChanges(); } } diff --git a/libs/image/tests/kis_properties_configuration_test.cpp b/libs/image/tests/kis_properties_configuration_test.cpp index d6bf267045..6c870a8fb0 100644 --- a/libs/image/tests/kis_properties_configuration_test.cpp +++ b/libs/image/tests/kis_properties_configuration_test.cpp @@ -1,96 +1,96 @@ /* * Copyright (c) 2007 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_properties_configuration_test.h" #include #include "kis_properties_configuration.h" KisPropertiesConfigurationTest::KisPropertiesConfigurationTest() : v1(10), v2("hello"), v3(1242.0), v4(true) { QList pts; pts.push_back(QPointF(0.2, 0.3)); pts.push_back(QPointF(0.5, 0.7)); v5.setPoints(pts); } void KisPropertiesConfigurationTest::testSerialization() { KisPropertiesConfigurationSP config = createConfig(); QString xml = config->toXML(); KisPropertiesConfigurationSP decodedConfig = new KisPropertiesConfiguration(); decodedConfig->fromXML(xml); testConfig(decodedConfig); } void KisPropertiesConfigurationTest::testSetGet() { KisPropertiesConfigurationSP config = createConfig(); testConfig(config); } void KisPropertiesConfigurationTest::testDefaultValues() { KisPropertiesConfigurationSP config = new KisPropertiesConfiguration(); QVERIFY(config->getInt("bouh", v1) == v1); QVERIFY(config->getString("bouh", v2) == v2); QVERIFY(config->getDouble("bouh", v3) == v3); QVERIFY(config->getBool("bouh", v4) == v4); QVERIFY(config->getCubicCurve("bouh", v5) == v5); } KisPropertiesConfigurationSP KisPropertiesConfigurationTest::createConfig() { KisPropertiesConfigurationSP config = new KisPropertiesConfiguration(); config->setProperty("v1", v1); config->setProperty("v2", v2); config->setProperty("v3", v3); config->setProperty("v4", v4); config->setProperty("v5", qVariantFromValue(v5)); return config; } void KisPropertiesConfigurationTest::testConfig(KisPropertiesConfigurationSP config) { QVERIFY(config->getInt("v1", 0) == v1); - QVERIFY(config->getString("v2", "") == v2); + QVERIFY(config->getString("v2", QString()) == v2); QVERIFY(config->getDouble("v3", 0.0) == v3); QVERIFY(config->getBool("v4", !v4) == v4); QVERIFY(config->getCubicCurve("v5") == v5); } void KisPropertiesConfigurationTest::testNotSavedValues() { KisPropertiesConfigurationSP config = createConfig(); config->setPropertyNotSaved("v3"); testConfig(config); QString s = config->toXML(); config = new KisPropertiesConfiguration(); config->fromXML(s); QVERIFY(config->getInt("v1", 0) == v1); - QVERIFY(config->getString("v2", "") == v2); + QVERIFY(config->getString("v2", QString()) == v2); QVERIFY(config->hasProperty("v3") == false); QVERIFY(config->getBool("v4", !v4) == v4); QVERIFY(config->getCubicCurve("v5") == v5); } QTEST_MAIN(KisPropertiesConfigurationTest) diff --git a/libs/odf/CMakeLists.txt b/libs/odf/CMakeLists.txt index 7df7b66af8..1ba16f491c 100644 --- a/libs/odf/CMakeLists.txt +++ b/libs/odf/CMakeLists.txt @@ -1,47 +1,46 @@ add_subdirectory( tests ) set(kritaodf_LIB_SRCS KoOdf.cpp KoOdfManifestEntry.cpp KoDocumentInfo.cpp KoGenStyle.cpp KoGenStyles.cpp KoFontFace.cpp KoOdfLoadingContext.cpp KoOasisSettings.cpp KoOdfStylesReader.cpp KoOdfNumberStyles.cpp KoOdfPaste.cpp KoOdfReadStore.cpp KoOdfWriteStore.cpp KoStyleStack.cpp KoOdfGraphicStyles.cpp KoGenChange.cpp KoGenChanges.cpp KoDocumentBase.cpp KoEmbeddedDocumentSaver.cpp KoBorder.cpp KoShadowStyle.cpp KoPageLayout.cpp KoPageFormat.cpp KoColumns.cpp KoUnit.cpp KoOdfNotesConfiguration.cpp KoOdfBibliographyConfiguration.cpp KoOdfNumberDefinition.cpp KoOdfLineNumberingConfiguration.cpp KoElementReference.cpp OdfDebug.cpp ) add_library(kritaodf SHARED ${kritaodf_LIB_SRCS}) generate_export_header(kritaodf BASE_NAME kritaodf) target_link_libraries(kritaodf kritaversion kritaplugin kritastore KF5::CoreAddons KF5::ConfigCore KF5::I18n Qt5::PrintSupport Qt5::Gui Qt5::Xml) -target_link_libraries(kritaodf LINK_INTERFACE_LIBRARIES kritastore KF5::CoreAddons KF5::I18n Qt5::PrintSupport Qt5::Gui Qt5::Xml) set_target_properties(kritaodf PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaodf ${INSTALL_TARGETS_DEFAULT_ARGS} ) diff --git a/libs/pigment/resources/KoColorSet.cpp b/libs/pigment/resources/KoColorSet.cpp index 8034fd529c..1363974b9d 100644 --- a/libs/pigment/resources/KoColorSet.cpp +++ b/libs/pigment/resources/KoColorSet.cpp @@ -1,733 +1,740 @@ /* This file is part of the KDE project Copyright (c) 2005 Boudewijn Rempt This library 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. This library 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 this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include // qFromLittleEndian #include #include #include #include #include #include #include #include #include #include +#include #include #include #include "KoColor.h" #include "KoColorSpaceRegistry.h" #include "KoColorModelStandardIds.h" struct KoColorSet::Private { QByteArray data; QString name; QString comment; qint32 columns; QVector colors; }; KoColorSet::PaletteType detectFormat(const QString &fileName, const QByteArray &ba) { QFileInfo fi(fileName); // .pal if (ba.startsWith("RIFF") && ba.indexOf("PAL data", 8)) { return KoColorSet::RIFF_PAL; } // .gpl else if (ba.startsWith("GIMP Palette")) { return KoColorSet::GPL; } // .pal else if (ba.startsWith("JASC-PAL")) { return KoColorSet::PSP_PAL; } else if (fi.suffix().toLower() == "aco") { return KoColorSet::ACO; } else if (fi.suffix().toLower() == "act") { return KoColorSet::ACT; } else if (fi.suffix().toLower() == "xml") { return KoColorSet::XML; } return KoColorSet::UNKNOWN; } KoColorSet::KoColorSet(const QString& filename) : KoResource(filename) , d(new Private()) { // Implemented in KoResource class d->columns = 0; // Set the default value that the GIMP uses... } KoColorSet::KoColorSet() : KoResource(QString()) , d(new Private()) { d->columns = 0; // Set the default value that the GIMP uses... } /// Create an copied palette KoColorSet::KoColorSet(const KoColorSet& rhs) : QObject(0) , KoResource(QString()) , d(new Private()) { setFilename(rhs.filename()); d->name = rhs.d->name; d->comment = rhs.d->comment; d->columns = rhs.d->columns; d->colors = rhs.d->colors; setValid(true); } KoColorSet::~KoColorSet() { } bool KoColorSet::load() { QFile file(filename()); if (file.size() == 0) return false; if (!file.open(QIODevice::ReadOnly)) { warnPigment << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool KoColorSet::loadFromDevice(QIODevice *dev) { if (!dev->isOpen()) dev->open(QIODevice::ReadOnly); d->data = dev->readAll(); Q_ASSERT(d->data.size() != 0); return init(); } bool KoColorSet::save() { QFile file(filename()); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } saveToDevice(&file); file.close(); return true; } qint32 KoColorSet::nColors() { return d->colors.count(); } qint32 KoColorSet::getIndexClosestColor(KoColor color, bool useGivenColorSpace) { qint32 closestIndex = 0; quint8 highestPercentage = 0; quint8 testPercentage = 0; KoColor compare = color; for (qint32 i=0; icolors.at(i).color; if (useGivenColorSpace==true && compare.colorSpace()!=entry.colorSpace()) { entry.convertTo(compare.colorSpace()); } else if(compare.colorSpace()!=entry.colorSpace()) { compare.convertTo(entry.colorSpace()); } testPercentage = (255 - compare.colorSpace()->difference(compare.data(), entry.data())); if (testPercentage>highestPercentage) { closestIndex = i; highestPercentage = testPercentage; } } return closestIndex; } QString KoColorSet::closestColorName(KoColor color, bool useGivenColorSpace) { int i = getIndexClosestColor(color, useGivenColorSpace); QString name = d->colors.at(i).name; return name; } bool KoColorSet::saveToDevice(QIODevice *dev) const { QTextStream stream(dev); stream << "GIMP Palette\nName: " << name() << "\nColumns: " << d->columns << "\n#\n"; for (int i = 0; i < d->colors.size(); i++) { const KoColorSetEntry& entry = d->colors.at(i); QColor c = entry.color.toQColor(); stream << c.red() << " " << c.green() << " " << c.blue() << "\t"; if (entry.name.isEmpty()) stream << "Untitled\n"; else stream << entry.name << "\n"; } KoResource::saveToDevice(dev); return true; } bool KoColorSet::init() { d->colors.clear(); // just in case this is a reload (eg by KoEditColorSetDialog), if (filename().isNull()) { warnPigment << "Cannot load palette" << name() << "there is no filename set"; return false; } if (d->data.isNull()) { QFile file(filename()); if (file.size() == 0) { warnPigment << "Cannot load palette" << name() << "there is no data available"; return false; } file.open(QIODevice::ReadOnly); d->data = file.readAll(); file.close(); } bool res = false; PaletteType paletteType = detectFormat(filename(), d->data); switch(paletteType) { case GPL: res = loadGpl(); break; case ACT: res = loadAct(); break; case RIFF_PAL: res = loadRiff(); break; case PSP_PAL: res = loadPsp(); break; case ACO: res = loadAco(); break; case XML: res = loadXml(); break; default: res = false; } setValid(res); if (d->columns == 0) { d->columns = 10; } QImage img(d->columns * 4, (d->colors.size() / d->columns) * 4, QImage::Format_ARGB32); QPainter gc(&img); gc.fillRect(img.rect(), Qt::darkGray); int counter = 0; for(int i = 0; i < d->columns; ++i) { for (int j = 0; j < (d->colors.size() / d->columns); ++j) { if (counter < d->colors.size()) { QColor c = d->colors.at(counter).color.toQColor(); gc.fillRect(i * 4, j * 4, 4, 4, c); counter++; } else { break; } } } setImage(img); // save some memory d->data.clear(); return res; } void KoColorSet::add(const KoColorSetEntry & c) { d->colors.push_back(c); } void KoColorSet::remove(const KoColorSetEntry & c) { for (auto it = d->colors.begin(); it != d->colors.end(); /*noop*/) { if ((*it) == c) { it = d->colors.erase(it); return; } ++it; } } void KoColorSet::removeAt(quint32 index) { d->colors.remove(index); } void KoColorSet::clear() { d->colors.clear(); } KoColorSetEntry KoColorSet::getColor(quint32 index) { return d->colors[index]; } void KoColorSet::setColumnCount(int columns) { d->columns = columns; } int KoColorSet::columnCount() { return d->columns; } QString KoColorSet::defaultFileExtension() const { return QString(".gpl"); } bool KoColorSet::loadGpl() { QString s = QString::fromUtf8(d->data.data(), d->data.count()); if (s.isEmpty() || s.isNull() || s.length() < 50) { warnPigment << "Illegal Gimp palette file: " << filename(); return false; } quint32 index = 0; QStringList lines = s.split('\n', QString::SkipEmptyParts); if (lines.size() < 3) { return false; } QString columns; qint32 r, g, b; KoColorSetEntry e; // Read name if (!lines[0].startsWith("GIMP") || !lines[1].startsWith("Name: ")) { warnPigment << "Illegal Gimp palette file: " << filename(); return false; } setName(i18n(lines[1].mid(strlen("Name: ")).trimmed().toLatin1())); index = 2; // Read columns if (lines[index].startsWith("Columns: ")) { columns = lines[index].mid(strlen("Columns: ")).trimmed(); d->columns = columns.toInt(); index = 3; } for (qint32 i = index; i < lines.size(); i++) { if (lines[i].startsWith('#')) { d->comment += lines[i].mid(1).trimmed() + ' '; } else if (!lines[i].isEmpty()) { QStringList a = lines[i].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() < 3) { break; } r = a[0].toInt(); a.pop_front(); g = a[0].toInt(); a.pop_front(); b = a[0].toInt(); a.pop_front(); r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); QString name = a.join(" "); e.name = name.isEmpty() ? i18n("Untitled") : name; add(e); } } return true; } bool KoColorSet::loadAct() { QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; for (int i = 0; i < d->data.size(); i += 3) { quint8 r = d->data[i]; quint8 g = d->data[i+1]; quint8 b = d->data[i+2]; e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); add(e); } return true; } struct RiffHeader { quint32 riff; quint32 size; quint32 signature; quint32 data; quint32 datasize; quint16 version; quint16 colorcount; }; bool KoColorSet::loadRiff() { // http://worms2d.info/Palette_file QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; RiffHeader header; memcpy(&header, d->data.constData(), sizeof(RiffHeader)); header.colorcount = qFromBigEndian(header.colorcount); for (int i = sizeof(RiffHeader); (i < (int)(sizeof(RiffHeader) + header.colorcount) && i < d->data.size()); i += 4) { quint8 r = d->data[i]; quint8 g = d->data[i+1]; quint8 b = d->data[i+2]; e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); add(e); } return true; } bool KoColorSet::loadPsp() { QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; qint32 r, g, b; QString s = QString::fromUtf8(d->data.data(), d->data.count()); QStringList l = s.split('\n', QString::SkipEmptyParts); if (l.size() < 4) return false; if (l[0] != "JASC-PAL") return false; if (l[1] != "0100") return false; int entries = l[2].toInt(); for (int i = 0; i < entries; ++i) { QStringList a = l[i + 3].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() != 3) { continue; } r = a[0].toInt(); a.pop_front(); g = a[0].toInt(); a.pop_front(); b = a[0].toInt(); a.pop_front(); r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); QString name = a.join(" "); e.name = name.isEmpty() ? i18n("Untitled") : name; add(e); } return true; } void scribusParseColor(KoColorSet *set, QXmlStreamReader *xml) { KoColorSetEntry currentColor; //It's a color, retrieve it QXmlStreamAttributes colorProperties = xml->attributes(); QStringRef colorValue; // RGB or CMYK? if (colorProperties.hasAttribute("RGB")) { dbgPigment << "Color " << colorProperties.value("NAME") << ", RGB " << colorProperties.value("RGB"); QStringRef colorName = colorProperties.value("NAME"); currentColor.name = colorName.isEmpty() || colorName.isNull() ? i18n("Untitled") : colorName.toString(); currentColor.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); colorValue = colorProperties.value("RGB"); if (colorValue.length() != 7 && colorValue.at(0) != '#') { // Color is a hexadecimal number xml->raiseError("Invalid rgb8 color (malformed): " + colorValue); return; } else { bool rgbOk; quint32 rgb = colorValue.mid(1).toUInt(&rgbOk, 16); if (!rgbOk) { xml->raiseError("Invalid rgb8 color (unable to convert): " + colorValue); return; } quint8 r = rgb >> 16 & 0xff; quint8 g = rgb >> 8 & 0xff; quint8 b = rgb & 0xff; dbgPigment << "Color parsed: "<< r << g << b; currentColor.color.data()[0] = r; currentColor.color.data()[1] = g; currentColor.color.data()[2] = b; currentColor.color.setOpacity(OPACITY_OPAQUE_U8); set->add(currentColor); while(xml->readNextStartElement()) { //ignore - these are all unknown or the /> element tag xml->skipCurrentElement(); } return; } } else if (colorProperties.hasAttribute("CMYK")) { dbgPigment << "Color " << colorProperties.value("NAME") << ", CMYK " << colorProperties.value("CMYK"); QStringRef colorName = colorProperties.value("NAME"); currentColor.name = colorName.isEmpty() || colorName.isNull() ? i18n("Untitled") : colorName.toString(); - currentColor.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer8BitsColorDepthID.id(), "")); + currentColor.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer8BitsColorDepthID.id(), QString())); colorValue = colorProperties.value("CMYK"); if (colorValue.length() != 9 && colorValue.at(0) != '#') { // Color is a hexadecimal number xml->raiseError("Invalid cmyk color (malformed): " + colorValue); return; } else { bool cmykOk; quint32 cmyk = colorValue.mid(1).toUInt(&cmykOk, 16); // cmyk uses the full 32 bits if (!cmykOk) { xml->raiseError("Invalid cmyk color (unable to convert): " + colorValue); return; } quint8 c = cmyk >> 24 & 0xff; quint8 m = cmyk >> 16 & 0xff; quint8 y = cmyk >> 8 & 0xff; quint8 k = cmyk & 0xff; dbgPigment << "Color parsed: "<< c << m << y << k; currentColor.color.data()[0] = c; currentColor.color.data()[1] = m; currentColor.color.data()[2] = y; currentColor.color.data()[3] = k; currentColor.color.setOpacity(OPACITY_OPAQUE_U8); set->add(currentColor); while(xml->readNextStartElement()) { //ignore - these are all unknown or the /> element tag xml->skipCurrentElement(); } return; } } else { xml->raiseError("Unknown color space for color " + currentColor.name); } } bool loadScribusXmlPalette(KoColorSet *set, QXmlStreamReader *xml) { //1. Get name QXmlStreamAttributes paletteProperties = xml->attributes(); QStringRef paletteName = paletteProperties.value("Name"); dbgPigment << "Processed name of palette:" << paletteName; set->setName(paletteName.toString()); //2. Inside the SCRIBUSCOLORS, there are lots of colors. Retrieve them while(xml->readNextStartElement()) { QStringRef currentElement = xml->name(); if(QStringRef::compare(currentElement, "COLOR", Qt::CaseInsensitive) == 0) { scribusParseColor(set, xml); } else { xml->skipCurrentElement(); } } if(xml->hasError()) { return false; } return true; } bool KoColorSet::loadXml() { bool res = false; QXmlStreamReader *xml = new QXmlStreamReader(d->data); if (xml->readNextStartElement()) { QStringRef paletteId = xml->name(); if (QStringRef::compare(paletteId, "SCRIBUSCOLORS", Qt::CaseInsensitive) == 0) { // Scribus dbgPigment << "XML palette: " << filename() << ", Scribus format"; res = loadScribusXmlPalette(this, xml); } else { // Unknown XML format xml->raiseError("Unknown XML palette format. Expected SCRIBUSCOLORS, found " + paletteId); } } // If there is any error (it should be returned through the stream) if (xml->hasError() || !res) { warnPigment << "Illegal XML palette:" << filename(); warnPigment << "Error (line"<< xml->lineNumber() << ", column" << xml->columnNumber() << "):" << xml->errorString(); return false; } else { dbgPigment << "XML palette parsed successfully:" << filename(); return true; } } quint16 readShort(QIODevice *io) { quint16 val; quint64 read = io->read((char*)&val, 2); if (read != 2) return false; return qFromBigEndian(val); } bool KoColorSet::loadAco() { QFileInfo info(filename()); setName(info.baseName()); QBuffer buf(&d->data); buf.open(QBuffer::ReadOnly); quint16 version = readShort(&buf); quint16 numColors = readShort(&buf); KoColorSetEntry e; + if (version == 1 && buf.size() > 4+numColors*10) { + buf.seek(4+numColors*10); + version = readShort(&buf); + numColors = readShort(&buf); + } + const quint16 quint16_MAX = 65535; for (int i = 0; i < numColors && !buf.atEnd(); ++i) { quint16 colorSpace = readShort(&buf); quint16 ch1 = readShort(&buf); quint16 ch2 = readShort(&buf); quint16 ch3 = readShort(&buf); quint16 ch4 = readShort(&buf); bool skip = false; if (colorSpace == 0) { // RGB e.color = KoColor(KoColorSpaceRegistry::instance()->rgb16()); reinterpret_cast(e.color.data())[0] = ch3; reinterpret_cast(e.color.data())[1] = ch2; reinterpret_cast(e.color.data())[2] = ch1; e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 1) { // HSB e.color = KoColor(KoColorSpaceRegistry::instance()->rgb16()); QColor c; c.setHsvF(ch1 / 65536.0, ch2 / 65536.0, ch3 / 65536.0); e.color.fromQColor(c); e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 2) { // CMYK - e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer16BitsColorDepthID.id(), "")); + e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer16BitsColorDepthID.id(), QString())); reinterpret_cast(e.color.data())[0] = quint16_MAX - ch1; reinterpret_cast(e.color.data())[1] = quint16_MAX - ch2; reinterpret_cast(e.color.data())[2] = quint16_MAX - ch3; reinterpret_cast(e.color.data())[3] = quint16_MAX - ch4; e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 7) { // LAB e.color = KoColor(KoColorSpaceRegistry::instance()->lab16()); reinterpret_cast(e.color.data())[0] = ch3; reinterpret_cast(e.color.data())[1] = ch2; reinterpret_cast(e.color.data())[2] = ch1; e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 8) { // GRAY - e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer16BitsColorDepthID.id(), "")); + e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer16BitsColorDepthID.id(), QString())); reinterpret_cast(e.color.data())[0] = ch1 * (quint16_MAX / 10000); e.color.setOpacity(OPACITY_OPAQUE_U8); } else { warnPigment << "Unsupported colorspace in palette" << filename() << "(" << colorSpace << ")"; skip = true; } if (version == 2) { - quint16 v2 = readShort(&buf); - if (v2 != 2) { - warnPigment << "Version 2 block is not version 2" << filename() << "(" << v2 << ")"; - return false; - } - quint16 size = readShort(&buf); - QByteArray ba = buf.read(size); - if (ba.size() != size) { - warnPigment << "Version 2 name block is the wrong size" << filename(); - return false; + quint16 v2 = readShort(&buf); //this isn't a version, it's a marker and needs to be skipped. + quint16 size = readShort(&buf) -1; //then comes the length + if (size>0) { + QByteArray ba = buf.read(size*2); + if (ba.size() == size*2) { + QTextCodec *Utf16Codec = QTextCodec::codecForName("UTF-16BE"); + e.name = Utf16Codec->toUnicode(ba); + } else { + warnPigment << "Version 2 name block is the wrong size" << filename(); + } } - e.name = QString::fromUtf8(ba.constData(), ba.size()); + v2 = readShort(&buf); //end marker also needs to be skipped. } if (!skip) { add(e); } } return true; } diff --git a/libs/psd/CMakeLists.txt b/libs/psd/CMakeLists.txt index f343f14e80..9fcdb6eb4e 100644 --- a/libs/psd/CMakeLists.txt +++ b/libs/psd/CMakeLists.txt @@ -1,37 +1,36 @@ include_directories( ${CMAKE_BINARY_DIR}/libs/psd #For kispsd_include.h ${Boost_INCLUDE_DIRS} ) set(kritapsd_LIB_SRCS psd_utils.cpp psd.cpp compression.cpp psd_pattern.cpp asl/kis_asl_reader.cpp asl/kis_asl_reader_utils.cpp asl/kis_asl_xml_parser.cpp asl/kis_asl_object_catcher.cpp asl/kis_asl_callback_object_catcher.cpp asl/kis_asl_xml_writer.cpp asl/kis_asl_writer_utils.cpp asl/kis_asl_patterns_writer.cpp asl/kis_asl_writer.cpp ) add_library(kritapsd SHARED ${kritapsd_LIB_SRCS} ) generate_export_header(kritapsd BASE_NAME kritapsd) if (WIN32) target_link_libraries(kritapsd kritapigment kritaglobal KF5::I18n ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${WIN32_PLATFORM_NET_LIBS}) else (WIN32) target_link_libraries(kritapsd kritapigment kritaglobal KF5::I18n ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) endif (WIN32) -target_link_libraries(kritapsd LINK_INTERFACE_LIBRARIES kritaglobal ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) set_target_properties(kritapsd PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritapsd ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt index 16369b2491..7e1cdcaa24 100644 --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -1,562 +1,545 @@ -# Disable -Wswitch because of the extra definitions we here: -# kis_input_manager.cpp: In member function ‘virtual bool KisInputManager::eventFilter(QObject*, QEvent*)’: -# warning: case value ‘1001’ not in enumerated type ‘QEvent::Type’ [-Wswitch] -# warning: case value ‘1002’ not in enumerated type ‘QEvent::Type’ [-Wswitch] -if (CMAKE_COMPILER_IS_GNUCXX) - add_definitions(${KDE4_ENABLE_EXCEPTIONS} -Wno-switch) -endif () - include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile ${EXIV2_INCLUDE_DIR} ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ${OCIO_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ) add_subdirectory( tests ) if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) endif () set(kritaui_LIB_SRCS canvas/kis_canvas_widget_base.cpp canvas/kis_canvas2.cpp canvas/kis_canvas_updates_compressor.cpp canvas/kis_canvas_controller.cpp canvas/kis_paintop_transformation_connector.cpp canvas/kis_display_color_converter.cpp canvas/kis_display_filter.cpp canvas/kis_exposure_gamma_correction_interface.cpp canvas/kis_tool_proxy.cpp canvas/kis_canvas_decoration.cc canvas/kis_coordinates_converter.cpp canvas/kis_grid_manager.cpp canvas/kis_grid_decoration.cpp canvas/kis_grid_config.cpp canvas/kis_prescaled_projection.cpp canvas/kis_qpainter_canvas.cpp canvas/kis_projection_backend.cpp canvas/kis_update_info.cpp canvas/kis_image_patch.cpp canvas/kis_image_pyramid.cpp canvas/kis_infinity_manager.cpp canvas/kis_change_guides_command.cpp canvas/kis_guides_decoration.cpp canvas/kis_guides_manager.cpp canvas/kis_guides_config.cpp canvas/kis_snap_config.cpp canvas/kis_snap_line_strategy.cpp dialogs/kis_about_application.cpp dialogs/kis_dlg_adj_layer_props.cc dialogs/kis_dlg_adjustment_layer.cc dialogs/kis_dlg_filter.cpp dialogs/kis_dlg_generator_layer.cpp dialogs/kis_dlg_file_layer.cpp dialogs/kis_dlg_filter.cpp dialogs/kis_dlg_stroke_selection_properties.cpp dialogs/kis_dlg_image_properties.cc dialogs/kis_dlg_layer_properties.cc dialogs/kis_dlg_preferences.cc dialogs/slider_and_spin_box_sync.cpp dialogs/kis_dlg_blacklist_cleanup.cpp dialogs/kis_dlg_layer_style.cpp dialogs/kis_dlg_png_import.cpp dialogs/kis_dlg_import_image_sequence.cpp dialogs/kis_delayed_save_dialog.cpp dialogs/kis_dlg_internal_color_selector.cpp flake/kis_node_dummies_graph.cpp flake/kis_dummies_facade_base.cpp flake/kis_dummies_facade.cpp flake/kis_node_shapes_graph.cpp flake/kis_node_shape.cpp flake/kis_shape_controller.cpp flake/kis_shape_layer.cc flake/kis_shape_layer_canvas.cpp flake/kis_shape_selection.cpp flake/kis_shape_selection_canvas.cpp flake/kis_shape_selection_model.cpp flake/kis_take_all_shapes_command.cpp brushhud/kis_uniform_paintop_property_widget.cpp brushhud/kis_brush_hud.cpp brushhud/kis_round_hud_button.cpp brushhud/kis_dlg_brush_hud_config.cpp brushhud/kis_brush_hud_properties_list.cpp brushhud/kis_brush_hud_properties_config.cpp kis_aspect_ratio_locker.cpp kis_autogradient.cc kis_bookmarked_configurations_editor.cc kis_bookmarked_configurations_model.cc kis_bookmarked_filter_configurations_model.cc kis_base_option.cpp kis_canvas_resource_provider.cpp kis_derived_resources.cpp kis_categories_mapper.cpp kis_categorized_list_model.cpp kis_categorized_item_delegate.cpp kis_clipboard.cc kis_config.cc kis_config_notifier.cpp kis_control_frame.cpp kis_composite_ops_model.cc kis_paint_ops_model.cpp kis_cursor.cc kis_cursor_cache.cpp kis_custom_pattern.cc kis_file_layer.cpp kis_safe_document_loader.cpp kis_splash_screen.cpp kis_filter_manager.cc kis_filters_model.cc kis_histogram_view.cc kis_image_manager.cc kis_image_view_converter.cpp kis_import_catcher.cc kis_layer_manager.cc kis_mask_manager.cc kis_mimedata.cpp kis_node_commands_adapter.cpp kis_node_manager.cpp kis_node_juggler_compressed.cpp kis_node_selection_adapter.cpp kis_node_insertion_adapter.cpp kis_node_model.cpp kis_node_filter_proxy_model.cpp kis_model_index_converter_base.cpp kis_model_index_converter.cpp kis_model_index_converter_show_all.cpp kis_painting_assistant.cc kis_painting_assistants_decoration.cpp kis_painting_assistants_manager.cpp kis_paintop_box.cc kis_paintop_option.cpp kis_paintop_options_model.cpp kis_paintop_settings_widget.cpp kis_popup_palette.cpp kis_png_converter.cpp kis_preference_set_registry.cpp kis_script_manager.cpp kis_resource_server_provider.cpp kis_selection_decoration.cc kis_selection_manager.cc kis_statusbar.cc kis_zoom_manager.cc kis_favorite_resource_manager.cpp kis_workspace_resource.cpp kis_action.cpp kis_action_manager.cpp kis_view_plugin.cpp kis_canvas_controls_manager.cpp kis_tooltip_manager.cpp kis_multinode_property.cpp kis_async_action_feedback.cpp kis_stopgradient_editor.cpp kisexiv2/kis_exif_io.cpp kisexiv2/kis_exiv2.cpp kisexiv2/kis_iptc_io.cpp kisexiv2/kis_xmp_io.cpp kra/kis_kra_utils.cpp kra/kis_kra_load_visitor.cpp kra/kis_kra_loader.cpp kra/kis_kra_save_visitor.cpp kra/kis_kra_saver.cpp kra/kis_kra_savexml_visitor.cpp kra/kis_colorize_dom_utils.cpp opengl/kis_opengl.cpp opengl/kis_opengl_canvas2.cpp opengl/kis_opengl_canvas_debugger.cpp opengl/kis_opengl_image_textures.cpp opengl/kis_texture_tile.cpp opengl/kis_opengl_shader_loader.cpp kis_fps_decoration.cpp ora/kis_open_raster_stack_load_visitor.cpp ora/kis_open_raster_stack_save_visitor.cpp ora/ora_load_context.cc ora/ora_save_context.cc recorder/kis_node_query_path_editor.cc recorder/kis_recorded_action_creator.cc recorder/kis_recorded_action_creator_factory.cc recorder/kis_recorded_action_creator_factory_registry.cc recorder/kis_recorded_action_editor_factory.cc recorder/kis_recorded_action_editor_factory_registry.cc recorder/kis_recorded_filter_action_editor.cc recorder/kis_recorded_filter_action_creator.cpp recorder/kis_recorded_paint_action_editor.cc tool/kis_selection_tool_helper.cpp tool/kis_selection_tool_config_widget_helper.cpp tool/kis_rectangle_constraint_widget.cpp tool/kis_shape_tool_helper.cpp tool/kis_tool.cc tool/kis_delegated_tool_policies.cpp tool/kis_tool_freehand.cc tool/kis_speed_smoother.cpp tool/kis_painting_information_builder.cpp tool/kis_stabilized_events_sampler.cpp tool/kis_tool_freehand_helper.cpp tool/kis_tool_multihand_helper.cpp tool/kis_figure_painting_tool_helper.cpp tool/kis_recording_adapter.cpp tool/kis_tool_paint.cc tool/kis_tool_shape.cc tool/kis_tool_ellipse_base.cpp tool/kis_tool_rectangle_base.cpp tool/kis_tool_polyline_base.cpp tool/kis_tool_utils.cpp tool/kis_resources_snapshot.cpp tool/kis_smoothing_options.cpp tool/strokes/freehand_stroke.cpp tool/strokes/kis_painter_based_stroke_strategy.cpp tool/strokes/kis_filter_stroke_strategy.cpp tool/strokes/kis_color_picker_stroke_strategy.cpp widgets/kis_cmb_composite.cc widgets/kis_cmb_contour.cpp widgets/kis_cmb_gradient.cpp widgets/kis_paintop_list_widget.cpp widgets/kis_cmb_idlist.cc widgets/kis_color_space_selector.cc widgets/kis_advanced_color_space_selector.cc widgets/kis_cie_tongue_widget.cpp widgets/kis_tone_curve_widget.cpp widgets/kis_curve_widget.cpp widgets/kis_custom_image_widget.cc widgets/kis_image_from_clipboard_widget.cpp widgets/kis_double_widget.cc widgets/kis_filter_selector_widget.cc widgets/kis_gradient_chooser.cc widgets/kis_gradient_slider_widget.cc widgets/kis_gradient_slider.cpp widgets/kis_iconwidget.cc widgets/kis_mask_widgets.cpp widgets/kis_meta_data_merge_strategy_chooser_widget.cc widgets/kis_multi_bool_filter_widget.cc widgets/kis_multi_double_filter_widget.cc widgets/kis_multi_integer_filter_widget.cc widgets/kis_multipliers_double_slider_spinbox.cpp widgets/kis_paintop_presets_popup.cpp widgets/kis_tool_options_popup.cpp widgets/kis_paintop_presets_chooser_popup.cpp widgets/kis_pattern_chooser.cc widgets/kis_popup_button.cc widgets/kis_preset_chooser.cpp widgets/kis_progress_widget.cpp widgets/kis_selection_options.cc widgets/kis_scratch_pad.cpp widgets/kis_scratch_pad_event_filter.cpp widgets/kis_preset_selector_strip.cpp widgets/kis_slider_spin_box.cpp widgets/kis_size_group.cpp widgets/kis_size_group_p.cpp widgets/kis_wdg_generator.cpp widgets/kis_workspace_chooser.cpp widgets/squeezedcombobox.cpp widgets/kis_categorized_list_view.cpp widgets/kis_widget_chooser.cpp widgets/kis_tool_button.cpp widgets/kis_floating_message.cpp widgets/kis_lod_availability_widget.cpp widgets/kis_color_label_selector_widget.cpp widgets/kis_color_filter_combo.cpp widgets/kis_elided_label.cpp widgets/kis_stopgradient_slider_widget.cpp widgets/kis_spinbox_color_selector.cpp widgets/kis_screen_color_picker.cpp widgets/kis_visual_color_selector.cpp widgets/KoDualColorButton.cpp widgets/kis_color_input.cpp widgets/kis_color_button.cpp input/kis_input_manager.cpp input/kis_input_manager_p.cpp input/kis_extended_modifiers_mapper.cpp input/kis_abstract_input_action.cpp input/kis_tool_invocation_action.cpp input/kis_pan_action.cpp input/kis_alternate_invocation_action.cpp input/kis_rotate_canvas_action.cpp input/kis_zoom_action.cpp input/kis_change_frame_action.cpp input/kis_gamma_exposure_action.cpp input/kis_show_palette_action.cpp input/kis_change_primary_setting_action.cpp input/kis_abstract_shortcut.cpp input/kis_single_action_shortcut.cpp input/kis_stroke_shortcut.cpp input/kis_shortcut_matcher.cpp input/kis_select_layer_action.cpp operations/kis_operation.cpp operations/kis_operation_configuration.cpp operations/kis_operation_registry.cpp operations/kis_operation_ui_factory.cpp operations/kis_operation_ui_widget.cpp operations/kis_filter_selection_operation.cpp actions/kis_selection_action_factories.cpp input/kis_touch_shortcut.cpp kis_document_undo_store.cpp kis_transaction_based_command.cpp kis_gui_context_command.cpp kis_gui_context_command_p.cpp input/kis_tablet_debugger.cpp input/kis_input_profile_manager.cpp input/kis_input_profile.cpp input/kis_shortcut_configuration.cpp input/config/kis_input_configuration_page.cpp input/config/kis_edit_profiles_dialog.cpp input/config/kis_input_profile_model.cpp input/config/kis_input_configuration_page_item.cpp input/config/kis_action_shortcuts_model.cpp input/config/kis_input_type_delegate.cpp input/config/kis_input_mode_delegate.cpp input/config/kis_input_button.cpp input/config/kis_input_editor_delegate.cpp input/config/kis_mouse_input_editor.cpp input/config/kis_wheel_input_editor.cpp input/config/kis_key_input_editor.cpp processing/fill_processing_visitor.cpp kis_asl_layer_style_serializer.cpp kis_psd_layer_style_resource.cpp canvas/kis_mirror_axis.cpp kis_abstract_perspective_grid.cpp KisApplication.cpp KisAutoSaveRecoveryDialog.cpp KisDetailsPane.cpp KisDocument.cpp KisNodeDelegate.cpp kis_node_view_visibility_delegate.cpp KisNodeToolTip.cpp KisNodeView.cpp kis_node_view_color_scheme.cpp KisFilterChain.cpp KisFilterChainLink.cpp KisFilterChainLinkList.cpp KisImportExportFilter.cpp KisFilterEdge.cpp KisFilterEntry.cpp KisFilterGraph.cpp KisImportExportManager.cpp KisFilterVertex.cpp KisMainWindow.cpp KisOpenPane.cpp KisPart.cpp KisPrintJob.cpp KisTemplate.cpp KisTemplateCreateDia.cpp KisTemplateGroup.cpp KisTemplates.cpp KisTemplatesPane.cpp KisTemplateTree.cpp KisUndoStackAction.cpp KisView.cpp thememanager.cpp kis_mainwindow_observer.cpp KisViewManager.cpp kis_mirror_manager.cpp qtlockedfile/qtlockedfile.cpp qtsingleapplication/qtlocalpeer.cpp qtsingleapplication/qtsingleapplication.cpp KisResourceBundle.cpp KisResourceBundleManifest.cpp kis_md5_generator.cpp KisApplicationArguments.cpp KisNetworkAccessManager.cpp KisMultiFeedRSSModel.cpp KisRemoteFileFetcher.cpp KisPaletteModel.cpp kis_palette_delegate.cpp kis_palette_view.cpp KisColorsetChooser.cpp KisSaveGroupVisitor.cpp ) if(WIN32) if (NOT Qt5Gui_PRIVATE_INCLUDE_DIRS) message(FATAL_ERROR "Qt5Gui Private header are missing!") endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support_win.cpp input/wintab/kis_screen_size_choice_dialog.cpp qtlockedfile/qtlockedfile_win.cpp ) - include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) + include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} kis_animation_frame_cache.cpp kis_animation_cache_populator.cpp canvas/kis_animation_player.cpp kis_animation_exporter.cpp kis_animation_importer.cpp ) if(UNIX) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support.cpp qtlockedfile/qtlockedfile_unix.cpp ) if(NOT APPLE) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/kis_tablet_support_x11.cpp input/wintab/qxcbconnection_xi2.cpp input/wintab/qxcbconnection.cpp input/wintab/kis_xi2_event_filter.cpp ) endif() endif() -if(WIN32) - #ki18n_wrap_ui( - # input/wintab/kis_screen_size_choice_dialog.ui - #) -endif() - - ki18n_wrap_ui(kritaui_LIB_SRCS forms/wdgdlgpngimport.ui forms/wdgfullscreensettings.ui forms/wdgautogradient.ui forms/wdggeneralsettings.ui forms/wdgperformancesettings.ui forms/wdggenerators.ui forms/wdgbookmarkedconfigurationseditor.ui forms/wdgapplyprofile.ui forms/wdgcustompattern.ui forms/wdglayerproperties.ui forms/wdgcolorsettings.ui forms/wdgtabletsettings.ui forms/wdgcolorspaceselector.ui forms/wdgcolorspaceselectoradvanced.ui forms/wdgdisplaysettings.ui forms/kis_previewwidgetbase.ui forms/kis_matrix_widget.ui forms/wdgselectionoptions.ui forms/wdggeometryoptions.ui forms/wdgnewimage.ui forms/wdgimageproperties.ui forms/wdgmaskfromselection.ui forms/wdgmasksource.ui forms/wdgfilterdialog.ui forms/wdgmetadatamergestrategychooser.ui forms/wdgpaintoppresets.ui forms/wdgpaintopsettings.ui forms/wdgdlggeneratorlayer.ui forms/wdgdlgfilelayer.ui forms/wdgfilterselector.ui forms/wdgfilternodecreation.ui forms/wdgpaintactioneditor.ui forms/wdgmultipliersdoublesliderspinbox.ui forms/wdgnodequerypatheditor.ui forms/wdgpresetselectorstrip.ui forms/wdgdlgblacklistcleanup.ui forms/wdgrectangleconstraints.ui forms/wdgimportimagesequence.ui forms/wdgstrokeselectionproperties.ui forms/KisDetailsPaneBase.ui forms/KisOpenPaneBase.ui forms/wdgstopgradienteditor.ui brushhud/kis_dlg_brush_hud_config.ui forms/wdgdlginternalcolorselector.ui dialogs/kis_delayed_save_dialog.ui input/config/kis_input_configuration_page.ui input/config/kis_edit_profiles_dialog.ui input/config/kis_input_configuration_page_item.ui input/config/kis_mouse_input_editor.ui input/config/kis_wheel_input_editor.ui input/config/kis_key_input_editor.ui layerstyles/wdgBevelAndEmboss.ui layerstyles/wdgblendingoptions.ui layerstyles/WdgColorOverlay.ui layerstyles/wdgContour.ui layerstyles/wdgdropshadow.ui layerstyles/WdgGradientOverlay.ui layerstyles/wdgInnerGlow.ui layerstyles/wdglayerstyles.ui layerstyles/WdgPatternOverlay.ui layerstyles/WdgSatin.ui layerstyles/WdgStroke.ui layerstyles/wdgstylesselector.ui layerstyles/wdgTexture.ui wdgsplash.ui input/wintab/kis_screen_size_choice_dialog.ui ) QT5_WRAP_CPP(kritaui_HEADERS_MOC KisNodePropertyAction_p.h) add_library(kritaui SHARED ${kritaui_HEADERS_MOC} ${kritaui_LIB_SRCS} ) generate_export_header(kritaui BASE_NAME kritaui) target_link_libraries(kritaui KF5::CoreAddons KF5::Completion KF5::I18n KF5::ItemViews Qt5::Network kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES} ) if (HAVE_KIO) target_link_libraries(kritaui KF5::KIOCore) endif() if (NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${X11_X11_LIB} ${X11_Xinput_LIB} ${XCB_LIBRARIES}) endif() if(APPLE) target_link_libraries(kritaui ${FOUNDATION_LIBRARY}) endif () target_link_libraries(kritaui ${OPENEXR_LIBRARIES}) # Add VSync disable workaround if(NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${CMAKE_DL_LIBS} Qt5::X11Extras) endif() if(X11_FOUND) target_link_libraries(kritaui Qt5::X11Extras ${X11_LIBRARIES}) endif() -target_link_libraries(kritaui LINK_INTERFACE_LIBRARIES kritaimage kritalibbrush kritapigment kritawidgets KF5::Completion KF5::I18n ${GL_INTERFACE_LIBRARIES}) - target_include_directories(kritaui PUBLIC $ $ $ $ $ $ $ ) set_target_properties(kritaui PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS}) if (APPLE) install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita) endif () diff --git a/libs/ui/KisImportExportManager.cpp b/libs/ui/KisImportExportManager.cpp index 05927857b2..c466363b00 100644 --- a/libs/ui/KisImportExportManager.cpp +++ b/libs/ui/KisImportExportManager.cpp @@ -1,337 +1,341 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis 2000, 2001 Werner Trobin Copyright (C) 2004 Nicolas Goutte Copyright (C) 2009 Thomas Zander This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisImportExportManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoProgressUpdater.h" #include "KoJsonTrader.h" #include #include #include "KisImportExportFilter.h" #include "KisDocument.h" #include #include // static cache for import and export mimetypes QStringList KisImportExportManager::m_importMimeTypes; QStringList KisImportExportManager::m_exportMimeTypes; class Q_DECL_HIDDEN KisImportExportManager::Private { public: bool batch; QByteArray importMimeType; QWeakPointer progressUpdater; Private(KoProgressUpdater *progressUpdater_ = 0) : progressUpdater(progressUpdater_) { } }; KisImportExportManager::KisImportExportManager(KisDocument* document) : m_document(document) , m_graph("") , d(new Private(0)) { d->batch = false; } KisImportExportManager::KisImportExportManager(const QString& location) : m_document(0) , m_importFileName(location) , m_graph("") , d(new Private) { d->batch = false; } KisImportExportManager::KisImportExportManager(const QByteArray& mimeType) : m_document(0) , m_graph("") , d(new Private) { d->batch = false; d->importMimeType = mimeType; } KisImportExportManager::~KisImportExportManager() { delete d; } QString KisImportExportManager::importDocument(const QString& location, const QString& documentMimeType, KisImportExportFilter::ConversionStatus& status) { // Find the mime type for the file to be imported. QString typeName = documentMimeType; if (typeName.isEmpty()) { typeName = KisMimeDatabase::mimeTypeForFile(location); } m_graph.setSourceMimeType(typeName.toLatin1()); // .latin1() is okay here (Werner) if (!m_graph.isValid()) { errFile << "Couldn't create a valid graph for this source mimetype: " << typeName; status = KisImportExportFilter::BadConversionGraph; return QString(); } KisFilterChainSP chain(0); // Are we owned by a KisDocument? if (m_document) { QByteArray mimeType = m_document->nativeFormatMimeType(); QStringList extraMimes = m_document->extraNativeMimeTypes(); int i = 0; int n = extraMimes.count(); chain = m_graph.chain(this, mimeType); while (i < n) { QByteArray extraMime = extraMimes[i].toUtf8(); // TODO check if its the same target mime then continue KisFilterChainSP newChain(0); newChain = m_graph.chain(this, extraMime); if (!chain || (newChain && newChain->weight() < chain->weight())) chain = newChain; ++i; } } else if (!d->importMimeType.isEmpty()) { chain = m_graph.chain(this, d->importMimeType); } else { errFile << "You aren't supposed to use import() from a filter!" << endl; status = KisImportExportFilter::UsageError; return QString(); } if (!chain) { errFile << "Couldn't create a valid filter chain!" << endl; importErrorHelper(typeName); status = KisImportExportFilter::BadConversionGraph; return QString(); } // Okay, let's invoke the filters one after the other m_direction = Import; // vital information! m_importFileName = location; m_exportFileName.clear(); status = chain->invokeChain(); m_importFileName.clear(); // Reset the import URL if (status == KisImportExportFilter::OK) return chain->chainOutput(); return QString(); } KisImportExportFilter::ConversionStatus KisImportExportManager::exportDocument(const QString& location, QByteArray& mimeType, KisPropertiesConfigurationSP exportConfiguration) { bool userCancelled = false; // The import url should already be set correctly (null if we have a KisDocument // file manager and to the correct URL if we have an embedded manager) m_direction = Export; // vital information! m_exportFileName = location; m_exportConfiguration = exportConfiguration; KisFilterChainSP chain; if (m_document) { // We have to pick the right native mimetype as source. QStringList nativeMimeTypes; nativeMimeTypes.append(m_document->nativeFormatMimeType()); nativeMimeTypes += m_document->extraNativeMimeTypes(); QStringList::ConstIterator it = nativeMimeTypes.constBegin(); const QStringList::ConstIterator end = nativeMimeTypes.constEnd(); for (; !chain && it != end; ++it) { m_graph.setSourceMimeType((*it).toLatin1()); if (m_graph.isValid()) chain = m_graph.chain(this, mimeType); } } else { QString t = KisMimeDatabase::mimeTypeForFile(m_importFileName); m_graph.setSourceMimeType(t.toLatin1()); } if (!m_graph.isValid()) { errFile << "Couldn't create a valid graph for this source mimetype."; QApplication::restoreOverrideCursor(); if (!d->batch && !userCancelled) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not export file: the export filter is missing.")); } return KisImportExportFilter::BadConversionGraph; } if (!chain) { // already set when coming from the m_document case chain = m_graph.chain(this, mimeType); } if (!chain) { errFile << "Couldn't create a valid filter chain to " << mimeType << " !" << endl; if (!d->batch) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not export file: the export filter is missing.")); } QApplication::restoreOverrideCursor(); return KisImportExportFilter::BadConversionGraph; } return chain->invokeChain(); } // The static method to figure out to which parts of the // graph this mimetype has a connection to. QStringList KisImportExportManager::mimeFilter(Direction direction) { // Find the right mimetype by the extension QSet mimeTypes; // mimeTypes << KisDocument::nativeFormatMimeType() << "application/x-krita-paintoppreset" << "image/openraster"; if (direction == KisImportExportManager::Import) { if (m_importMimeTypes.isEmpty()) { KoJsonTrader trader; QListlist = trader.query("Krita/FileFilter", ""); Q_FOREACH(QPluginLoader *loader, list) { QJsonObject json = loader->metaData().value("MetaData").toObject(); Q_FOREACH(const QString &mimetype, json.value("X-KDE-Import").toString().split(",")) { - mimeTypes << mimetype; + if (!mimetype.isEmpty()) { + mimeTypes << mimetype; + } } } qDeleteAll(list); m_importMimeTypes = mimeTypes.toList(); } return m_importMimeTypes; } else if (direction == KisImportExportManager::Export) { if (m_exportMimeTypes.isEmpty()) { KoJsonTrader trader; QListlist = trader.query("Krita/FileFilter", ""); Q_FOREACH(QPluginLoader *loader, list) { QJsonObject json = loader->metaData().value("MetaData").toObject(); Q_FOREACH(const QString &mimetype, json.value("X-KDE-Export").toString().split(",")) { - mimeTypes << mimetype; + if (!mimetype.isEmpty()) { + mimeTypes << mimetype; + } } } qDeleteAll(list); m_exportMimeTypes = mimeTypes.toList(); } return m_exportMimeTypes; } return QStringList(); } KisImportExportFilter *KisImportExportManager::filterForMimeType(const QString &mimetype, KisImportExportManager::Direction direction) { int weight = -1; KisImportExportFilter *filter = 0; KoJsonTrader trader; QListlist = trader.query("Krita/FileFilter", ""); Q_FOREACH(QPluginLoader *loader, list) { QJsonObject json = loader->metaData().value("MetaData").toObject(); QString directionKey = direction == Export ? "X-KDE-Export" : "X-KDE-Import"; if (json.value(directionKey).toString().split(",").contains(mimetype)) { KLibFactory *factory = qobject_cast(loader->instance()); if (!factory) { warnUI << loader->errorString(); continue; } QObject* obj = factory->create(0); if (!obj || !obj->inherits("KisImportExportFilter")) { delete obj; continue; } KisImportExportFilter *f = static_cast(obj); if (!f) { delete obj; continue; } int w = json.value("X-KDE-Weight").toInt(); if (w > weight) { delete filter; filter = f; f->setObjectName(loader->fileName()); weight = w; } } } qDeleteAll(list); return filter; } void KisImportExportManager::importErrorHelper(const QString& mimeType, const bool suppressDialog) { // ###### FIXME: use KLibLoader::lastErrorMessage() here if (!suppressDialog) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not import file of type\n%1. The import filter is missing.", mimeType)); } } void KisImportExportManager::setBatchMode(const bool batch) { d->batch = batch; } bool KisImportExportManager::getBatchMode(void) const { return d->batch; } void KisImportExportManager::setProgresUpdater(KoProgressUpdater *updater) { d->progressUpdater = updater; } KoProgressUpdater* KisImportExportManager::progressUpdater() const { if (d->progressUpdater.isNull()) { // somebody, probably its parent, deleted our progress updater for us return 0; } return d->progressUpdater.data(); } #include diff --git a/libs/ui/tool/kis_tool_freehand_helper.cpp b/libs/ui/tool/kis_tool_freehand_helper.cpp index 52e088dcb3..41b8b70e89 100644 --- a/libs/ui/tool/kis_tool_freehand_helper.cpp +++ b/libs/ui/tool/kis_tool_freehand_helper.cpp @@ -1,854 +1,855 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_freehand_helper.h" #include #include #include #include #include #include #include "kis_painting_information_builder.h" #include "kis_recording_adapter.h" #include "kis_image.h" #include "kis_painter.h" #include #include #include "kis_update_time_monitor.h" #include "kis_stabilized_events_sampler.h" #include "kis_config.h" #include //#define DEBUG_BEZIER_CURVES struct KisToolFreehandHelper::Private { KisPaintingInformationBuilder *infoBuilder; KisRecordingAdapter *recordingAdapter; KisStrokesFacade *strokesFacade; KUndo2MagicString transactionText; bool haveTangent; QPointF previousTangent; bool hasPaintAtLeastOnce; QTime strokeTime; QTimer strokeTimeoutTimer; QVector painterInfos; KisResourcesSnapshotSP resources; KisStrokeId strokeId; KisPaintInformation previousPaintInformation; KisPaintInformation olderPaintInformation; KisSmoothingOptionsSP smoothingOptions; QTimer airbrushingTimer; QList history; QList distanceHistory; KisPaintOpUtils::PositionHistory lastOutlinePos; // Stabilizer data QQueue stabilizerDeque; QTimer stabilizerPollTimer; KisStabilizedEventsSampler stabilizedSampler; int canvasRotation; bool canvasMirroredH; KisPaintInformation getStabilizedPaintInfo(const QQueue &queue, const KisPaintInformation &lastPaintInfo); qreal effectiveSmoothnessDistance() const; }; KisToolFreehandHelper::KisToolFreehandHelper(KisPaintingInformationBuilder *infoBuilder, const KUndo2MagicString &transactionText, KisRecordingAdapter *recordingAdapter) : m_d(new Private()) { m_d->infoBuilder = infoBuilder; m_d->recordingAdapter = recordingAdapter; m_d->transactionText = transactionText; m_d->smoothingOptions = KisSmoothingOptionsSP(new KisSmoothingOptions()); m_d->canvasRotation = 0; m_d->strokeTimeoutTimer.setSingleShot(true); connect(&m_d->strokeTimeoutTimer, SIGNAL(timeout()), SLOT(finishStroke())); connect(&m_d->airbrushingTimer, SIGNAL(timeout()), SLOT(doAirbrushing())); connect(&m_d->stabilizerPollTimer, SIGNAL(timeout()), SLOT(stabilizerPollAndPaint())); } KisToolFreehandHelper::~KisToolFreehandHelper() { delete m_d; } void KisToolFreehandHelper::setSmoothness(KisSmoothingOptionsSP smoothingOptions) { m_d->smoothingOptions = smoothingOptions; } KisSmoothingOptionsSP KisToolFreehandHelper::smoothingOptions() const { return m_d->smoothingOptions; } QPainterPath KisToolFreehandHelper::paintOpOutline(const QPointF &savedCursorPos, const KoPointerEvent *event, const KisPaintOpSettingsSP globalSettings, KisPaintOpSettings::OutlineMode mode) const { KisPaintOpSettingsSP settings = globalSettings; KisPaintInformation info = m_d->infoBuilder->hover(savedCursorPos, event); info.setCanvasRotation(m_d->canvasRotation); info.setCanvasHorizontalMirrorState( m_d->canvasMirroredH ); KisDistanceInformation distanceInfo(m_d->lastOutlinePos.pushThroughHistory(savedCursorPos), 0); if (!m_d->painterInfos.isEmpty()) { settings = m_d->resources->currentPaintOpPreset()->settings(); info = m_d->previousPaintInformation; /** * When LoD mode is active it may happen that the helper has * already started a stroke, but it painted noting, because * all the work is being calculated by the scaled-down LodN * stroke. So at first we try to fetch the data from the lodN * stroke ("buddy") and then check if there is at least * something has been painted with this distance information * object. */ KisDistanceInformation *buddyDistance = m_d->painterInfos.first()->buddyDragDistance(); if (buddyDistance) { /** * Tiny hack alert: here we fetch the distance information * directly from the LodN stroke. Ideally, we should * upscale its data, but here we just override it with our * local copy of the coordinates. */ distanceInfo = *buddyDistance; distanceInfo.overrideLastValues(m_d->lastOutlinePos.pushThroughHistory(savedCursorPos), 0); } else if (m_d->painterInfos.first()->dragDistance->isStarted()) { distanceInfo = *m_d->painterInfos.first()->dragDistance; } } KisPaintInformation::DistanceInformationRegistrar registrar = info.registerDistanceInformation(&distanceInfo); QPainterPath outline = settings->brushOutline(info, mode); if (m_d->resources && m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::STABILIZER && m_d->smoothingOptions->useDelayDistance()) { const qreal R = m_d->smoothingOptions->delayDistance() / m_d->resources->effectiveZoom(); outline.addEllipse(info.pos(), R, R); } return outline; } void KisToolFreehandHelper::initPaint(KoPointerEvent *event, KoCanvasResourceManager *resourceManager, KisImageWSP image, KisNodeSP currentNode, KisStrokesFacade *strokesFacade, KisPostExecutionUndoAdapter *undoAdapter, KisNodeSP overrideNode, KisDefaultBoundsBaseSP bounds) { KisPaintInformation pi = m_d->infoBuilder->startStroke(event, elapsedStrokeTime(), resourceManager); initPaintImpl(pi, resourceManager, image, currentNode, strokesFacade, undoAdapter, overrideNode, bounds); } bool KisToolFreehandHelper::isRunning() const { return m_d->strokeId; } void KisToolFreehandHelper::initPaintImpl(const KisPaintInformation &previousPaintInformation, KoCanvasResourceManager *resourceManager, KisImageWSP image, KisNodeSP currentNode, KisStrokesFacade *strokesFacade, KisPostExecutionUndoAdapter *undoAdapter, KisNodeSP overrideNode, KisDefaultBoundsBaseSP bounds) { Q_UNUSED(overrideNode); m_d->strokesFacade = strokesFacade; m_d->haveTangent = false; m_d->previousTangent = QPointF(); m_d->hasPaintAtLeastOnce = false; m_d->strokeTime.start(); m_d->previousPaintInformation = previousPaintInformation; createPainters(m_d->painterInfos, m_d->previousPaintInformation.pos(), m_d->previousPaintInformation.currentTime()); m_d->resources = new KisResourcesSnapshot(image, currentNode, undoAdapter, resourceManager, bounds); if(overrideNode) { m_d->resources->setCurrentNode(overrideNode); } if(m_d->recordingAdapter) { m_d->recordingAdapter->startStroke(image, m_d->resources); } KisStrokeStrategy *stroke = new FreehandStrokeStrategy(m_d->resources->needsIndirectPainting(), m_d->resources->indirectPaintingCompositeOp(), m_d->resources, m_d->painterInfos, m_d->transactionText); m_d->strokeId = m_d->strokesFacade->startStroke(stroke); m_d->history.clear(); m_d->distanceHistory.clear(); if(m_d->resources->needsAirbrushing()) { m_d->airbrushingTimer.setInterval(m_d->resources->airbrushingRate()); m_d->airbrushingTimer.start(); } if (m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::STABILIZER) { stabilizerStart(m_d->previousPaintInformation); } } void KisToolFreehandHelper::paintBezierSegment(KisPaintInformation pi1, KisPaintInformation pi2, QPointF tangent1, QPointF tangent2) { if (tangent1.isNull() || tangent2.isNull()) return; const qreal maxSanePoint = 1e6; QPointF controlTarget1; QPointF controlTarget2; // Shows the direction in which control points go QPointF controlDirection1 = pi1.pos() + tangent1; QPointF controlDirection2 = pi2.pos() - tangent2; // Lines in the direction of the control points QLineF line1(pi1.pos(), controlDirection1); QLineF line2(pi2.pos(), controlDirection2); // Lines to check whether the control points lay on the opposite // side of the line QLineF line3(controlDirection1, controlDirection2); QLineF line4(pi1.pos(), pi2.pos()); QPointF intersection; if (line3.intersect(line4, &intersection) == QLineF::BoundedIntersection) { qreal controlLength = line4.length() / 2; line1.setLength(controlLength); line2.setLength(controlLength); controlTarget1 = line1.p2(); controlTarget2 = line2.p2(); } else { QLineF::IntersectType type = line1.intersect(line2, &intersection); if (type == QLineF::NoIntersection || intersection.manhattanLength() > maxSanePoint) { intersection = 0.5 * (pi1.pos() + pi2.pos()); // dbgKrita << "WARINING: there is no intersection point " // << "in the basic smoothing algoriths"; } controlTarget1 = intersection; controlTarget2 = intersection; } // shows how near to the controlTarget the value raises qreal coeff = 0.8; qreal velocity1 = QLineF(QPointF(), tangent1).length(); qreal velocity2 = QLineF(QPointF(), tangent2).length(); if (velocity1 == 0.0 || velocity2 == 0.0) { velocity1 = 1e-6; velocity2 = 1e-6; warnKrita << "WARNING: Basic Smoothing: Velocity is Zero! Please report a bug:" << ppVar(velocity1) << ppVar(velocity2); } qreal similarity = qMin(velocity1/velocity2, velocity2/velocity1); // the controls should not differ more than 50% similarity = qMax(similarity, qreal(0.5)); // when the controls are symmetric, their size should be smaller // to avoid corner-like curves coeff *= 1 - qMax(qreal(0.0), similarity - qreal(0.8)); Q_ASSERT(coeff > 0); QPointF control1; QPointF control2; if (velocity1 > velocity2) { control1 = pi1.pos() * (1.0 - coeff) + coeff * controlTarget1; coeff *= similarity; control2 = pi2.pos() * (1.0 - coeff) + coeff * controlTarget2; } else { control2 = pi2.pos() * (1.0 - coeff) + coeff * controlTarget2; coeff *= similarity; control1 = pi1.pos() * (1.0 - coeff) + coeff * controlTarget1; } paintBezierCurve(pi1, control1, control2, pi2); } qreal KisToolFreehandHelper::Private::effectiveSmoothnessDistance() const { const qreal effectiveSmoothnessDistance = !smoothingOptions->useScalableDistance() ? smoothingOptions->smoothnessDistance() : smoothingOptions->smoothnessDistance() / resources->effectiveZoom(); return effectiveSmoothnessDistance; } void KisToolFreehandHelper::paint(KoPointerEvent *event) { KisPaintInformation info = m_d->infoBuilder->continueStroke(event, elapsedStrokeTime()); info.setCanvasRotation( m_d->canvasRotation ); info.setCanvasHorizontalMirrorState( m_d->canvasMirroredH ); KisUpdateTimeMonitor::instance()->reportMouseMove(info.pos()); /** * Smooth the coordinates out using the history and the * distance. This is a heavily modified version of an algo used in * Gimp and described in https://bugs.kde.org/show_bug.cgi?id=281267 and * http://www24.atwiki.jp/sigetch_2007/pages/17.html. The main * differences are: * * 1) It uses 'distance' instead of 'velocity', since time * measurements are too unstable in realworld environment * * 2) There is no 'Quality' parameter, since the number of samples * is calculated automatically * * 3) 'Tail Aggressiveness' is used for controling the end of the * stroke * * 4) The formila is a little bit different: 'Distance' parameter * stands for $3 \Sigma$ */ if (m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::WEIGHTED_SMOOTHING && m_d->smoothingOptions->smoothnessDistance() > 0.0) { { // initialize current distance QPointF prevPos; if (!m_d->history.isEmpty()) { const KisPaintInformation &prevPi = m_d->history.last(); prevPos = prevPi.pos(); } else { prevPos = m_d->previousPaintInformation.pos(); } qreal currentDistance = QVector2D(info.pos() - prevPos).length(); m_d->distanceHistory.append(currentDistance); } m_d->history.append(info); qreal x = 0.0; qreal y = 0.0; if (m_d->history.size() > 3) { const qreal sigma = m_d->effectiveSmoothnessDistance() / 3.0; // '3.0' for (3 * sigma) range qreal gaussianWeight = 1 / (sqrt(2 * M_PI) * sigma); qreal gaussianWeight2 = sigma * sigma; qreal distanceSum = 0.0; qreal scaleSum = 0.0; qreal pressure = 0.0; qreal baseRate = 0.0; Q_ASSERT(m_d->history.size() == m_d->distanceHistory.size()); for (int i = m_d->history.size() - 1; i >= 0; i--) { qreal rate = 0.0; const KisPaintInformation nextInfo = m_d->history.at(i); double distance = m_d->distanceHistory.at(i); Q_ASSERT(distance >= 0.0); qreal pressureGrad = 0.0; if (i < m_d->history.size() - 1) { pressureGrad = nextInfo.pressure() - m_d->history.at(i + 1).pressure(); const qreal tailAgressiveness = 40.0 * m_d->smoothingOptions->tailAggressiveness(); if (pressureGrad > 0.0 ) { pressureGrad *= tailAgressiveness * (1.0 - nextInfo.pressure()); distance += pressureGrad * 3.0 * sigma; // (3 * sigma) --- holds > 90% of the region } } if (gaussianWeight2 != 0.0) { distanceSum += distance; rate = gaussianWeight * exp(-distanceSum * distanceSum / (2 * gaussianWeight2)); } if (m_d->history.size() - i == 1) { baseRate = rate; } else if (baseRate / rate > 100) { break; } scaleSum += rate; x += rate * nextInfo.pos().x(); y += rate * nextInfo.pos().y(); if (m_d->smoothingOptions->smoothPressure()) { pressure += rate * nextInfo.pressure(); } } if (scaleSum != 0.0) { x /= scaleSum; y /= scaleSum; if (m_d->smoothingOptions->smoothPressure()) { pressure /= scaleSum; } } if ((x != 0.0 && y != 0.0) || (x == info.pos().x() && y == info.pos().y())) { info.setPos(QPointF(x, y)); if (m_d->smoothingOptions->smoothPressure()) { info.setPressure(pressure); } m_d->history.last() = info; } } } if (m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::SIMPLE_SMOOTHING || m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::WEIGHTED_SMOOTHING) { // Now paint between the coordinates, using the bezier curve interpolation if (!m_d->haveTangent) { m_d->haveTangent = true; m_d->previousTangent = (info.pos() - m_d->previousPaintInformation.pos()) / qMax(qreal(1.0), info.currentTime() - m_d->previousPaintInformation.currentTime()); } else { QPointF newTangent = (info.pos() - m_d->olderPaintInformation.pos()) / qMax(qreal(1.0), info.currentTime() - m_d->olderPaintInformation.currentTime()); paintBezierSegment(m_d->olderPaintInformation, m_d->previousPaintInformation, m_d->previousTangent, newTangent); m_d->previousTangent = newTangent; } m_d->olderPaintInformation = m_d->previousPaintInformation; m_d->strokeTimeoutTimer.start(100); } else if (m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::NO_SMOOTHING){ paintLine(m_d->previousPaintInformation, info); } if (m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::STABILIZER) { m_d->stabilizedSampler.addEvent(info); } else { m_d->previousPaintInformation = info; } if(m_d->airbrushingTimer.isActive()) { m_d->airbrushingTimer.start(); } } void KisToolFreehandHelper::endPaint() { if (!m_d->hasPaintAtLeastOnce) { paintAt(m_d->previousPaintInformation); } else if (m_d->smoothingOptions->smoothingType() != KisSmoothingOptions::NO_SMOOTHING) { finishStroke(); } m_d->strokeTimeoutTimer.stop(); if(m_d->airbrushingTimer.isActive()) { m_d->airbrushingTimer.stop(); } if (m_d->smoothingOptions->smoothingType() == KisSmoothingOptions::STABILIZER) { stabilizerEnd(); } /** * There might be some timer events still pending, so * we should cancel them. Use this flag for the purpose. * Please note that we are not in MT here, so no mutex * is needed */ m_d->painterInfos.clear(); m_d->strokesFacade->endStroke(m_d->strokeId); m_d->strokeId.clear(); if(m_d->recordingAdapter) { m_d->recordingAdapter->endStroke(); } } void KisToolFreehandHelper::cancelPaint() { if (!m_d->strokeId) return; m_d->strokeTimeoutTimer.stop(); if (m_d->airbrushingTimer.isActive()) { m_d->airbrushingTimer.stop(); } if (m_d->stabilizerPollTimer.isActive()) { m_d->stabilizerPollTimer.stop(); } // see a comment in endPaint() m_d->painterInfos.clear(); m_d->strokesFacade->cancelStroke(m_d->strokeId); m_d->strokeId.clear(); if(m_d->recordingAdapter) { //FIXME: not implemented //m_d->recordingAdapter->cancelStroke(); } } int KisToolFreehandHelper::elapsedStrokeTime() const { return m_d->strokeTime.elapsed(); } void KisToolFreehandHelper::stabilizerStart(KisPaintInformation firstPaintInfo) { // FIXME: Ugly hack, this is no a "distance" in any way int sampleSize = qRound(m_d->effectiveSmoothnessDistance()); sampleSize = qMax(3, sampleSize); // Fill the deque with the current value repeated until filling the sample m_d->stabilizerDeque.clear(); for (int i = sampleSize; i > 0; i--) { m_d->stabilizerDeque.enqueue(firstPaintInfo); } // Poll and draw regularly KisConfig cfg; m_d->stabilizerPollTimer.setInterval(cfg.stabilizerSampleSize()); m_d->stabilizerPollTimer.start(); m_d->stabilizedSampler.clear(); + m_d->stabilizedSampler.addEvent(firstPaintInfo); } KisPaintInformation KisToolFreehandHelper::Private::getStabilizedPaintInfo(const QQueue &queue, const KisPaintInformation &lastPaintInfo) { KisPaintInformation result(lastPaintInfo); if (queue.size() > 1) { QQueue::const_iterator it = queue.constBegin(); QQueue::const_iterator end = queue.constEnd(); /** * The first point is going to be overridden by lastPaintInfo, skip it. */ it++; int i = 2; if (smoothingOptions->stabilizeSensors()) { while (it != end) { qreal k = qreal(i - 1) / i; // coeff for uniform averaging result = KisPaintInformation::mix(k, *it, result); it++; i++; } } else{ while (it != end) { qreal k = qreal(i - 1) / i; // coeff for uniform averaging result = KisPaintInformation::mixOnlyPosition(k, *it, result); it++; i++; } } } return result; } void KisToolFreehandHelper::stabilizerPollAndPaint() { KisStabilizedEventsSampler::iterator it; KisStabilizedEventsSampler::iterator end; std::tie(it, end) = m_d->stabilizedSampler.range(); for (; it != end; ++it) { KisPaintInformation sampledInfo = *it; bool canPaint = true; if (m_d->smoothingOptions->useDelayDistance()) { const qreal R = m_d->smoothingOptions->delayDistance() / m_d->resources->effectiveZoom(); QPointF diff = sampledInfo.pos() - m_d->previousPaintInformation.pos(); qreal dx = sqrt(pow2(diff.x()) + pow2(diff.y())); canPaint = dx > R; } if (canPaint) { KisPaintInformation newInfo = m_d->getStabilizedPaintInfo(m_d->stabilizerDeque, sampledInfo); paintLine(m_d->previousPaintInformation, newInfo); m_d->previousPaintInformation = newInfo; // Push the new entry through the queue m_d->stabilizerDeque.dequeue(); m_d->stabilizerDeque.enqueue(sampledInfo); emit requestExplicitUpdateOutline(); } else if (m_d->stabilizerDeque.head().pos() != m_d->previousPaintInformation.pos()) { QQueue::iterator it = m_d->stabilizerDeque.begin(); QQueue::iterator end = m_d->stabilizerDeque.end(); while (it != end) { *it = m_d->previousPaintInformation; ++it; } } } m_d->stabilizedSampler.clear(); } void KisToolFreehandHelper::stabilizerEnd() { // Stop the timer m_d->stabilizerPollTimer.stop(); // Finish the line if (m_d->smoothingOptions->finishStabilizedCurve()) { // In each iteration we add the latest paint info and delete the oldest // After `sampleSize` iterations the deque will be filled with the latest // value and we will have reached the end point. m_d->stabilizedSampler.addFinishingEvent(m_d->stabilizerDeque.size()); stabilizerPollAndPaint(); } } const KisPaintOp* KisToolFreehandHelper::currentPaintOp() const { return !m_d->painterInfos.isEmpty() ? m_d->painterInfos.first()->painter->paintOp() : 0; } void KisToolFreehandHelper::finishStroke() { if (m_d->haveTangent) { m_d->haveTangent = false; QPointF newTangent = (m_d->previousPaintInformation.pos() - m_d->olderPaintInformation.pos()) / (m_d->previousPaintInformation.currentTime() - m_d->olderPaintInformation.currentTime()); paintBezierSegment(m_d->olderPaintInformation, m_d->previousPaintInformation, m_d->previousTangent, newTangent); } } void KisToolFreehandHelper::doAirbrushing() { if(!m_d->painterInfos.isEmpty()) { paintAt(m_d->previousPaintInformation); } } void KisToolFreehandHelper::paintAt(int painterInfoId, const KisPaintInformation &pi) { m_d->hasPaintAtLeastOnce = true; m_d->strokesFacade->addJob(m_d->strokeId, new FreehandStrokeStrategy::Data(m_d->resources->currentNode(), painterInfoId, pi)); if(m_d->recordingAdapter) { m_d->recordingAdapter->addPoint(pi); } } void KisToolFreehandHelper::paintLine(int painterInfoId, const KisPaintInformation &pi1, const KisPaintInformation &pi2) { m_d->hasPaintAtLeastOnce = true; m_d->strokesFacade->addJob(m_d->strokeId, new FreehandStrokeStrategy::Data(m_d->resources->currentNode(), painterInfoId, pi1, pi2)); if(m_d->recordingAdapter) { m_d->recordingAdapter->addLine(pi1, pi2); } } void KisToolFreehandHelper::paintBezierCurve(int painterInfoId, const KisPaintInformation &pi1, const QPointF &control1, const QPointF &control2, const KisPaintInformation &pi2) { #ifdef DEBUG_BEZIER_CURVES KisPaintInformation tpi1; KisPaintInformation tpi2; tpi1 = pi1; tpi2 = pi2; tpi1.setPressure(0.3); tpi2.setPressure(0.3); paintLine(tpi1, tpi2); tpi1.setPressure(0.6); tpi2.setPressure(0.3); tpi1.setPos(pi1.pos()); tpi2.setPos(control1); paintLine(tpi1, tpi2); tpi1.setPos(pi2.pos()); tpi2.setPos(control2); paintLine(tpi1, tpi2); #endif m_d->hasPaintAtLeastOnce = true; m_d->strokesFacade->addJob(m_d->strokeId, new FreehandStrokeStrategy::Data(m_d->resources->currentNode(), painterInfoId, pi1, control1, control2, pi2)); if(m_d->recordingAdapter) { m_d->recordingAdapter->addCurve(pi1, control1, control2, pi2); } } void KisToolFreehandHelper::createPainters(QVector &painterInfos, const QPointF &lastPosition, int lastTime) { painterInfos << new PainterInfo(lastPosition, lastTime); } void KisToolFreehandHelper::paintAt(const KisPaintInformation &pi) { paintAt(0, pi); } void KisToolFreehandHelper::paintLine(const KisPaintInformation &pi1, const KisPaintInformation &pi2) { paintLine(0, pi1, pi2); } void KisToolFreehandHelper::paintBezierCurve(const KisPaintInformation &pi1, const QPointF &control1, const QPointF &control2, const KisPaintInformation &pi2) { paintBezierCurve(0, pi1, control1, control2, pi2); } int KisToolFreehandHelper::canvasRotation() { return m_d->canvasRotation; } void KisToolFreehandHelper::setCanvasRotation(int rotation) { m_d->canvasRotation = rotation; } bool KisToolFreehandHelper::canvasMirroredH() { return m_d->canvasMirroredH; } void KisToolFreehandHelper::setCanvasHorizontalMirrorState(bool mirrored) { m_d->canvasMirroredH = mirrored; } diff --git a/libs/widgets/CMakeLists.txt b/libs/widgets/CMakeLists.txt index 6d53be629a..0e90f601bf 100644 --- a/libs/widgets/CMakeLists.txt +++ b/libs/widgets/CMakeLists.txt @@ -1,112 +1,110 @@ add_subdirectory( tests ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(kritawidgets_LIB_SRCS KoGradientEditWidget.cpp KoVBox.cpp KoDialog.cpp KoGlobal.cpp KoZoomWidget.cpp KoTagToolButton.cpp KoTagChooserWidget.cpp KoTagFilterWidget.cpp KoResourceTaggingManager.cpp KoResourceItemChooserContextMenu.cpp KoAspectButton.cpp KoPagePreviewWidget.cpp KoPositionSelector.cpp KoSliderCombo.cpp KoColorPopupButton.cpp KoConfigAuthorPage.cpp KoUnitDoubleSpinBox.cpp KoZoomAction.cpp KoZoomController.cpp KoZoomInput.cpp KoZoomHandler.cpp KoZoomMode.cpp KoDpi.cpp KoGlobal.cpp KoColorPatch.cpp KoColorPopupAction.cpp KoColorSetWidget.cpp KoColorSlider.cpp KoEditColorSetDialog.cpp KoTriangleColorSelector.cpp KoResourcePopupAction.cpp KoFillConfigWidget.cpp KoIconToolTip.cpp KoResourceItemChooser.cpp KoResourceItemChooserSync.cpp KoResourceSelector.cpp KoResourceModel.cpp KoResourceItemDelegate.cpp KoResourceItemView.cpp KoResourceTagStore.cpp KoRuler.cpp #KoRulerController.cpp KoItemToolTip.cpp KoCheckerBoardPainter.cpp KoResourceServerAdapter.cpp KoResourceServerProvider.cpp KoLineStyleSelector.cpp KoLineStyleItemDelegate.cpp KoLineStyleModel.cpp KoDockWidgetTitleBar.cpp KoDockWidgetTitleBarButton.cpp KoResourceFiltering.cpp KoResourceModelBase.cpp KoToolBoxButton.cpp KoToolBox.cpp KoToolBoxDocker.cpp KoToolBoxFactory.cpp KoToolDocker.cpp KoPageLayoutWidget.cpp KoPageLayoutDialog.cpp KoShadowConfigWidget.cpp KoStrokeConfigWidget.cpp KoMarkerSelector.cpp KoMarkerModel.cpp KoMarkerItemDelegate.cpp KoDocumentInfoDlg.cpp KoGlobal.cpp KoTableView.cpp WidgetsDebug.cpp kis_file_name_requester.cpp kis_double_parse_spin_box.cpp kis_double_parse_unit_spin_box.cpp kis_int_parse_spin_box.cpp ) ki18n_wrap_ui( kritawidgets_LIB_SRCS KoConfigAuthorPage.ui koDocumentInfoAboutWidget.ui koDocumentInfoAuthorWidget.ui KoEditColorSet.ui wdg_file_name_requester.ui KoPageLayoutWidget.ui KoShadowConfigWidget.ui ) add_library(kritawidgets SHARED ${kritawidgets_LIB_SRCS}) generate_export_header(kritawidgets BASE_NAME kritawidgets) target_link_libraries(kritawidgets kritaodf kritaflake kritapigment kritawidgetutils Qt5::PrintSupport KF5::CoreAddons KF5::ConfigGui KF5::GuiAddons KF5::WidgetsAddons KF5::ConfigCore KF5::Completion) if(X11_FOUND) target_link_libraries(kritawidgets Qt5::X11Extras ${X11_LIBRARIES}) endif() -target_link_libraries(kritawidgets LINK_INTERFACE_LIBRARIES kritaodf kritaflake kritapigment kritawidgetutils Qt5::PrintSupport KF5::CoreAddons KF5::ConfigGui KF5::GuiAddons KF5::WidgetsAddons KF5::ConfigCore KF5::Completion) - set_target_properties(kritawidgets PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritawidgets ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/widgets/kis_double_parse_spin_box.cpp b/libs/widgets/kis_double_parse_spin_box.cpp index 1b0cc46439..801d9cca2f 100644 --- a/libs/widgets/kis_double_parse_spin_box.cpp +++ b/libs/widgets/kis_double_parse_spin_box.cpp @@ -1,245 +1,235 @@ /* * Copyright (c) 2016 Laurent Valentin Jospin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_double_parse_spin_box.h" #include "kis_num_parser.h" #include #include #include #include #include #include // for qIsNaN KisDoubleParseSpinBox::KisDoubleParseSpinBox(QWidget *parent) : QDoubleSpinBox(parent), - boolLastValid(true) + boolLastValid(true), + lastExprParsed(QStringLiteral("0.0")) { - - lastExprParsed = new QString("0.0"); - connect(this, SIGNAL(noMoreParsingError()), this, SLOT(clearErrorStyle())); //hack to let the clearError be called, even if the value changed method is the one from QDoubleSpinBox. connect(this, SIGNAL(valueChanged(double)), this, SLOT(clearError())); connect(this, SIGNAL(errorWhileParsing(QString)), this, SLOT(setErrorStyle())); oldValue = value(); warningIcon = new QLabel(this); if (QFile(":/./16_light_warning.svg").exists()) { warningIcon->setPixmap(QIcon(":/./16_light_warning.svg").pixmap(16, 16)); } else { warningIcon->setText("!"); } warningIcon->setStyleSheet("background:transparent;"); warningIcon->move(1, 1); warningIcon->setVisible(false); isOldPaletteSaved = false; areOldMarginsSaved = false; } KisDoubleParseSpinBox::~KisDoubleParseSpinBox() { - - //needed to avoid a segfault during destruction. - delete lastExprParsed; - } double KisDoubleParseSpinBox::valueFromText(const QString & text) const { - - *lastExprParsed = text; + lastExprParsed = text; bool ok; double ret; if ( (suffix().isEmpty() || !text.endsWith(suffix())) && (prefix().isEmpty() || !text.startsWith(prefix())) ) { ret = KisNumericParser::parseSimpleMathExpr(text, &ok); } else { QString expr = text; if (text.endsWith(suffix())) { expr.remove(text.size()-suffix().size(), suffix().size()); } if(text.startsWith(prefix())){ expr.remove(0, prefix().size()); } - *lastExprParsed = expr; - + lastExprParsed = expr; ret = KisNumericParser::parseSimpleMathExpr(expr, &ok); - } if(qIsNaN(ret) || qIsInf(ret)){ ok = false; } if (!ok) { if (boolLastValid) { oldValue = value(); } boolLastValid = false; ret = oldValue; //in case of error set to minimum. } else { if (!boolLastValid) { oldValue = ret; } boolLastValid = true; } return ret; } QString KisDoubleParseSpinBox::textFromValue(double val) const { if (!boolLastValid) { - emit errorWhileParsing(*lastExprParsed); - return *lastExprParsed; + emit errorWhileParsing(lastExprParsed); + return lastExprParsed; } - emit noMoreParsingError(); double v = KisNumericParser::parseSimpleMathExpr(cleanText()); v = QString("%1").arg(v, 0, 'f', decimals()).toDouble(); if (hasFocus() && (v == value() || (v >= maximum() && value() == maximum()) || (v <= minimum() && value() == minimum())) ) { //solve a very annoying bug where the formula can collapse while editing. With this trick the formula is not lost until focus is lost. return cleanText(); } return QDoubleSpinBox::textFromValue(val); } QValidator::State KisDoubleParseSpinBox::validate ( QString & input, int & pos ) const { Q_UNUSED(input); Q_UNUSED(pos); return QValidator::Acceptable; } void KisDoubleParseSpinBox::stepBy(int steps) { boolLastValid = true; //reset to valid state so we can use the up and down buttons. emit noMoreParsingError(); QDoubleSpinBox::stepBy(steps); } void KisDoubleParseSpinBox::setValue(double value) { if(value == oldValue && hasFocus()){ //avoid to reset the button when it set the value of something that will recall this slot. return; } if (!hasFocus()) { clearError(); } QDoubleSpinBox::setValue(value); } void KisDoubleParseSpinBox::setErrorStyle() { if (!boolLastValid) { //setStyleSheet(_oldStyleSheet + "Background: red; color: white; padding-left: 18px;"); if (!isOldPaletteSaved) { oldPalette = palette(); } isOldPaletteSaved = true; QPalette nP = oldPalette; nP.setColor(QPalette::Background, Qt::red); nP.setColor(QPalette::Base, Qt::red); nP.setColor(QPalette::Text, Qt::white); setPalette(nP); if (!areOldMarginsSaved) { oldMargins = lineEdit()->textMargins(); } areOldMarginsSaved = true; if (width() - height() >= 3*height()) { //if we have twice as much place as needed by the warning icon then display it. QMargins newMargins = oldMargins; newMargins.setLeft( newMargins.left() + height() - 4 ); lineEdit()->setTextMargins(newMargins); int h = warningIcon->height(); int hp = height()-2; if (h != hp) { warningIcon->resize(hp, hp); if (QFile(":/./16_light_warning.svg").exists()) { warningIcon->setPixmap(QIcon(":/./16_light_warning.svg").pixmap(hp-7, hp-7)); } } warningIcon->move(oldMargins.left()+4, 1); warningIcon->setVisible(true); } } } void KisDoubleParseSpinBox::clearErrorStyle() { if (boolLastValid) { warningIcon->setVisible(false); //setStyleSheet(QString()); setPalette(oldPalette); isOldPaletteSaved = false; lineEdit()->setTextMargins(oldMargins); areOldMarginsSaved = false; } } void KisDoubleParseSpinBox::clearError() { boolLastValid = true; emit noMoreParsingError(); oldValue = value(); clearErrorStyle(); } diff --git a/libs/widgets/kis_double_parse_spin_box.h b/libs/widgets/kis_double_parse_spin_box.h index 4c2b920773..29085af972 100644 --- a/libs/widgets/kis_double_parse_spin_box.h +++ b/libs/widgets/kis_double_parse_spin_box.h @@ -1,82 +1,82 @@ /* * Copyright (c) 2016 Laurent Valentin Jospin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISDOUBLEPARSESPINBOX_H #define KISDOUBLEPARSESPINBOX_H #include #include "kritawidgets_export.h" class QLabel; /*! * \brief The KisDoubleParseSpinBox class is a cleverer doubleSpinBox, able to parse arithmetic expressions. * * Use this spinbox instead of the basic one from Qt if you want it to be able to parse arithmetic expressions. */ class KRITAWIDGETS_EXPORT KisDoubleParseSpinBox : public QDoubleSpinBox { Q_OBJECT public: KisDoubleParseSpinBox(QWidget* parent = 0); ~KisDoubleParseSpinBox(); virtual double valueFromText(const QString & text) const; virtual QString textFromValue(double val) const; virtual QValidator::State validate ( QString & input, int & pos ) const; virtual void stepBy(int steps); void setValue(double value); //polymorphism won't work directly, we use a signal/slot hack to do so but if signals are disabled this function will still be useful. bool isLastValid() const{ return boolLastValid; } Q_SIGNALS: //! \brief signal emmitted when the last parsed expression create an error. void errorWhileParsing(QString expr) const; //! \brief signal emmitted when the last parsed expression is valid. void noMoreParsingError() const; public Q_SLOTS: //! \brief useful to let the widget change it's stylesheet when an error occured in the last expression. void setErrorStyle(); //! \brief useful to let the widget reset it's stylesheet when there's no more error. void clearErrorStyle(); //! \brief say the widget to return to an error free state. void clearError(); protected: - mutable QString* lastExprParsed; mutable bool boolLastValid; mutable double oldValue; + mutable QString lastExprParsed; QLabel* warningIcon; QPalette oldPalette; bool isOldPaletteSaved; QMargins oldMargins; bool areOldMarginsSaved; }; #endif // KISDOUBLEPARSESPINBOX_H diff --git a/libs/widgetutils/kis_action_registry.cpp b/libs/widgetutils/kis_action_registry.cpp index bca451e45b..ce7340ec0e 100644 --- a/libs/widgetutils/kis_action_registry.cpp +++ b/libs/widgetutils/kis_action_registry.cpp @@ -1,481 +1,482 @@ /* * Copyright (c) 2015 Michael Abrahams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include "kis_debug.h" #include "KoResourcePaths.h" #include "kis_icon_utils.h" #include "kactioncollection.h" #include "kactioncategory.h" #include "kis_action_registry.h" #include "kshortcutschemeshelper_p.h" namespace { /** * We associate several pieces of information with each shortcut. The first * piece of information is a QDomElement, containing the raw data from the * .action XML file. The second and third are QKeySequences, the first of * which is the default shortcut, the last of which is any custom shortcut. * The last two are the KActionCollection and KActionCategory used to * organize the shortcut editor. */ struct ActionInfoItem { QDomElement xmlData; QList defaultShortcuts; QList customShortcuts; QString collectionName; QString categoryName; }; // Convenience macros to extract text of a child node. QString getChildContent(QDomElement xml, QString node) { return xml.firstChildElement(node).text(); }; ActionInfoItem emptyActionInfo; // Used as default return value // Use Krita debug logging categories instead of KDE's default qDebug() for // harmless empty strings and translations QString quietlyTranslate(const QString &s) { if (s.isEmpty()) { return s; } QString translatedString = i18nc("action", s.toUtf8()); if (translatedString == s) { translatedString = i18n(s.toUtf8()); } if (translatedString.isEmpty()) { dbgAction << "No translation found for" << s; return s; } return translatedString; }; QList preferredShortcuts(ActionInfoItem action) { if (action.customShortcuts.isEmpty()) { return action.defaultShortcuts; } else { return action.customShortcuts; } }; }; class Q_DECL_HIDDEN KisActionRegistry::Private { public: Private(KisActionRegistry *_q) : q(_q) {}; // This is the main place containing ActionInfoItems. QMap actionInfoList; void loadActionFiles(); void loadCustomShortcuts(QString filename = QStringLiteral("kritashortcutsrc")); ActionInfoItem &actionInfo(const QString &name) { if (!actionInfoList.contains(name)) { dbgAction << "Tried to look up info for unknown action" << name; } return actionInfoList[name]; }; KisActionRegistry *q; QMap actionCollections; }; Q_GLOBAL_STATIC(KisActionRegistry, s_instance); KisActionRegistry *KisActionRegistry::instance() { return s_instance; }; KisActionRegistry::KisActionRegistry() : d(new KisActionRegistry::Private(this)) { + d->loadActionFiles(); KConfigGroup cg = KSharedConfig::openConfig()->group("Shortcut Schemes"); QString schemeName = cg.readEntry("Current Scheme", "Default"); loadShortcutScheme(schemeName); loadCustomShortcuts(); } QList KisActionRegistry::getCustomShortcut(const QString &name) { return d->actionInfo(name).customShortcuts; }; QList KisActionRegistry::getPreferredShortcut(const QString &name) { return preferredShortcuts(d->actionInfo(name)); }; QString KisActionRegistry::getCategory(const QString &name) { return d->actionInfo(name).categoryName; }; QStringList KisActionRegistry::allActions() { return d->actionInfoList.keys(); }; KActionCollection * KisActionRegistry::getDefaultCollection() { return d->actionCollections.value("Krita"); }; void KisActionRegistry::addAction(const QString &name, QAction *a) { auto info = d->actionInfo(name); KActionCollection *collection = d->actionCollections.value(info.collectionName); if (!collection) { dbgAction << "No collection found for action" << name; return; } if (collection->action(name)) { dbgAction << "duplicate action" << name << "in collection" << collection->componentName(); } else { } collection->addCategorizedAction(name, a, info.categoryName); }; void KisActionRegistry::notifySettingsUpdated() { d->loadCustomShortcuts(); }; void KisActionRegistry::loadCustomShortcuts(const QString &path) { if (path.isEmpty()) { d->loadCustomShortcuts(); } else { d->loadCustomShortcuts(path); } }; void KisActionRegistry::loadShortcutScheme(const QString &schemeName) { // Load scheme file if (schemeName != QStringLiteral("Default")) { QString schemeFileName = KShortcutSchemesHelper::schemeFileLocations().value(schemeName); if (schemeFileName.isEmpty()) { return; } KConfig schemeConfig(schemeFileName, KConfig::SimpleConfig); applyShortcutScheme(&schemeConfig); } else { // Apply default scheme, updating KisActionRegistry data applyShortcutScheme(); } } QAction * KisActionRegistry::makeQAction(const QString &name, QObject *parent) { QAction * a = new QAction(parent); if (!d->actionInfoList.contains(name)) { dbgAction << "Warning: requested data for unknown action" << name; return a; } propertizeAction(name, a); return a; }; void KisActionRegistry::setupDialog(KisShortcutsDialog *dlg) { for (auto i = d->actionCollections.constBegin(); i != d->actionCollections.constEnd(); i++ ) { dlg->addCollection(i.value(), i.key()); } } void KisActionRegistry::settingsPageSaved() { // For now, custom shortcuts are dealt with by writing to file and reloading. loadCustomShortcuts(); // Announce UI should reload current shortcuts. emit shortcutsUpdated(); } void KisActionRegistry::applyShortcutScheme(const KConfigBase *config) { // First, update the things in KisActionRegistry if (config == 0) { // Use default shortcut scheme. Simplest just to reload everything. d->actionInfoList.clear(); d->loadActionFiles(); loadCustomShortcuts(); } else { const auto schemeEntries = config->group(QStringLiteral("Shortcuts")).entryMap(); // Load info item for each shortcut, reset custom shortcuts auto it = schemeEntries.constBegin(); while (it != schemeEntries.end()) { ActionInfoItem &info = d->actionInfo(it.key()); if (!it.value().isEmpty()) info.defaultShortcuts = QKeySequence::listFromString(it.value()); it++; } } } void KisActionRegistry::updateShortcut(const QString &name, QAction *action) { const ActionInfoItem &info = d->actionInfo(name); action->setShortcuts(preferredShortcuts(info)); action->setProperty("defaultShortcuts", qVariantFromValue(info.defaultShortcuts)); } bool KisActionRegistry::propertizeAction(const QString &name, QAction * a) { const ActionInfoItem info = d->actionInfo(name); QDomElement actionXml = info.xmlData; if (actionXml.text().isEmpty()) { dbgAction << "No XML data found for action" << name; return false; } // i18n requires converting format from QString. auto getChildContent_i18n = [=](QString node){return quietlyTranslate(getChildContent(actionXml, node));}; // Note: the fields in the .action documents marked for translation are determined by extractrc. QString icon = getChildContent(actionXml, "icon"); QString text = getChildContent_i18n("text"); QString whatsthis = getChildContent_i18n("whatsThis"); QString toolTip = getChildContent_i18n("toolTip"); QString statusTip = getChildContent_i18n("statusTip"); QString iconText = getChildContent_i18n("iconText"); bool isCheckable = getChildContent(actionXml, "isCheckable") == QString("true"); a->setObjectName(name); // This is helpful, should be added more places in Krita a->setIcon(KisIconUtils::loadIcon(icon.toLatin1())); a->setText(text); a->setObjectName(name); a->setWhatsThis(whatsthis); a->setToolTip(toolTip); a->setStatusTip(statusTip); a->setIconText(iconText); a->setCheckable(isCheckable); updateShortcut(name, a); // TODO: check for colliding shortcuts in .action files either here or in loading code #if 0 QMap existingShortcuts; Q_FOREACH (QAction* action, actionCollection->actions()) { if(action->shortcut() == QKeySequence(0)) { continue; } if (existingShortcuts.contains(action->shortcut())) { dbgAction << QString("Actions %1 and %2 have the same shortcut: %3") \ .arg(action->text()) \ .arg(existingShortcuts[action->shortcut()]->text()) \ .arg(action->shortcut()); } else { existingShortcuts[action->shortcut()] = action; } } #endif return true; } QString KisActionRegistry::getActionProperty(const QString &name, const QString &property) { ActionInfoItem info = d->actionInfo(name); QDomElement actionXml = info.xmlData; if (actionXml.text().isEmpty()) { dbgAction << "No XML data found for action" << name; return QString(); } return getChildContent(actionXml, property); } void KisActionRegistry::writeCustomShortcuts(KConfigBase *config) const { KConfigGroup cg; if (config == 0) { cg = KConfigGroup(KSharedConfig::openConfig("kritashortcutsrc"), QStringLiteral("Shortcuts")); } else { cg = KConfigGroup(config, QStringLiteral("Shortcuts")); } for (auto it = d->actionInfoList.constBegin(); it != d->actionInfoList.constEnd(); ++it) { QString actionName = it.key(); QString s = QKeySequence::listToString(it.value().customShortcuts); if (s.isEmpty()) { cg.deleteEntry(actionName, KConfigGroup::Persistent); } else { cg.writeEntry(actionName, s, KConfigGroup::Persistent); } } cg.sync(); } void KisActionRegistry::Private::loadActionFiles() { QStringList actionDefinitions = KoResourcePaths::findAllResources("kis_actions", "*.action", KoResourcePaths::Recursive); // Extract actions all XML .action files. Q_FOREACH (const QString &actionDefinition, actionDefinitions) { QDomDocument doc; QFile f(actionDefinition); f.open(QFile::ReadOnly); doc.setContent(f.readAll()); QDomElement base = doc.documentElement(); // "ActionCollection" outer group QString collectionName = base.attribute("name"); QString version = base.attribute("version"); if (version != "2") { errAction << ".action XML file" << actionDefinition << "has incorrect version; skipping."; continue; } KActionCollection *actionCollection; if (!actionCollections.contains(collectionName)) { actionCollection = new KActionCollection(q, collectionName); actionCollections.insert(collectionName, actionCollection); dbgAction << "Adding a new action collection " << collectionName; } else { actionCollection = actionCollections.value(collectionName); } // Loop over nodes. Each of these corresponds to a // KActionCategory, producing a group of actions in the shortcut dialog. QDomElement actions = base.firstChild().toElement(); while (!actions.isNull()) { // field QDomElement categoryTextNode = actions.firstChild().toElement(); QString categoryName = quietlyTranslate(categoryTextNode.text()); // KActionCategory *category = actionCollection->getCategory(categoryName); // dbgAction << "Using category" << categoryName; // tags QDomElement actionXml = categoryTextNode.nextSiblingElement(); // Loop over individual actions while (!actionXml.isNull()) { if (actionXml.tagName() == "Action") { // Read name from format QString name = actionXml.attribute("name"); // Bad things if (name.isEmpty()) { errAction << "Unnamed action in definitions file " << actionDefinition; } else if (actionInfoList.contains(name)) { // errAction << "NOT COOL: Duplicated action name from xml data: " << name; } else { ActionInfoItem info; info.xmlData = actionXml; // Use empty list to signify no shortcut QString shortcutText = getChildContent(actionXml, "shortcut"); if (!shortcutText.isEmpty()) info.defaultShortcuts << QKeySequence(shortcutText); info.categoryName = categoryName; info.collectionName = collectionName; // dbgAction << "default shortcut for" << name << " - " << info.defaultShortcut; actionInfoList.insert(name,info); } } actionXml = actionXml.nextSiblingElement(); } actions = actions.nextSiblingElement(); } } }; void KisActionRegistry::Private::loadCustomShortcuts(QString filename) { const KConfigGroup localShortcuts(KSharedConfig::openConfig(filename), QStringLiteral("Shortcuts")); if (!localShortcuts.exists()) { return; } // Distinguish between two "null" states for custom shortcuts. for (auto i = actionInfoList.begin(); i != actionInfoList.end(); ++i) { if (localShortcuts.hasKey(i.key())) { QString entry = localShortcuts.readEntry(i.key(), QString()); if (entry == QStringLiteral("none")) { // A shortcut list with a single entry "" means the user has disabled the shortcut. // This occurs after stealing the shortcut without assigning a new one. i.value().customShortcuts = QList(); } else { i.value().customShortcuts = QKeySequence::listFromString(entry); } } else { // An empty shortcut list means no custom shortcut has been set. i.value().customShortcuts = QList(); } } }; diff --git a/libs/widgetutils/xmlgui/kshortcutschemeshelper.cpp b/libs/widgetutils/xmlgui/kshortcutschemeshelper.cpp index 9f76bd507d..f3cebac449 100644 --- a/libs/widgetutils/xmlgui/kshortcutschemeshelper.cpp +++ b/libs/widgetutils/xmlgui/kshortcutschemeshelper.cpp @@ -1,66 +1,61 @@ /* This file is part of the KDE libraries Copyright (C) 2008 Alexander Dymo This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kshortcutschemeshelper_p.h" #include #include #include #include #include #include #include #include #include #include "kactioncollection.h" #include "kxmlguiclient.h" #include "KoResourcePaths.h" #include "kis_action_registry.h" -QString KShortcutSchemesHelper::currentShortcutSchemeName() -{ - return KSharedConfig::openConfig()->group("Shortcut Schemes").readEntry("Current Scheme", "Default"); -} - QString KShortcutSchemesHelper::shortcutSchemeFileName(const QString &schemeName) { // Create a directory if one cannot be found. return KoResourcePaths::locateLocal("kis_shortcuts", schemeName, true); } QHash KShortcutSchemesHelper::schemeFileLocations() { QStringList schemes; schemes << QString("Default"); // Forbid "Default.shortcuts" QHash schemeFileLocations; const QStringList shortcutFiles = KoResourcePaths::findAllResources("kis_shortcuts", "*.shortcuts"); Q_FOREACH (const QString &file, shortcutFiles) { QFileInfo fileInfo(file); QString schemeName = fileInfo.completeBaseName(); if (!schemes.contains(schemeName)) { schemes << schemeName; schemeFileLocations.insert(schemeName, fileInfo.canonicalFilePath()); } } return schemeFileLocations; } diff --git a/libs/widgetutils/xmlgui/kshortcutschemeshelper_p.h b/libs/widgetutils/xmlgui/kshortcutschemeshelper_p.h index 9c706d26ba..6316fa37e6 100644 --- a/libs/widgetutils/xmlgui/kshortcutschemeshelper_p.h +++ b/libs/widgetutils/xmlgui/kshortcutschemeshelper_p.h @@ -1,53 +1,48 @@ /* This file is part of the KDE libraries Copyright (C) 2008 Alexander Dymo This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KSHORTCUTSCHEMESHELPER_P_H #define KSHORTCUTSCHEMESHELPER_P_H #include #include class KActionCollection; class KXMLGUIClient; class KConfigBase; class KShortcutSchemesHelper { public: - /** - * @return the current shortcut scheme name for the application. - */ - static QString currentShortcutSchemeName(); - /** * @return the name of the (writable) file to save the shortcut scheme to. */ static QString shortcutSchemeFileName(const QString &schemeName); static bool saveShortcutScheme(); /** * @return a list of files to save the shortcut scheme to. Does not include "Default" * @see shortcutSchemeFileName, exportActionCollection */ static QHash schemeFileLocations(); }; #endif diff --git a/plugins/flake/CMakeLists.txt b/plugins/flake/CMakeLists.txt index 0aa9280d31..ac791d0a98 100644 --- a/plugins/flake/CMakeLists.txt +++ b/plugins/flake/CMakeLists.txt @@ -1,15 +1,4 @@ -if (SHOULD_BUILD_PLUGIN_ARTISTICTEXTSHAPE) - add_subdirectory( artistictextshape ) -endif () - -if (SHOULD_BUILD_PLUGIN_PATHSHAPES) - add_subdirectory( pathshapes ) -endif () - -if (SHOULD_BUILD_PLUGIN_TEXTSHAPE) - add_subdirectory( textshape ) -endif() - -if (SHOULD_BUILD_PLUGIN_VECTORSHAPE) - add_subdirectory( vectorshape ) -endif () +add_subdirectory( artistictextshape ) +add_subdirectory( pathshapes ) +add_subdirectory( textshape ) +add_subdirectory( vectorshape ) diff --git a/plugins/impex/ora/CMakeLists.txt b/plugins/impex/ora/CMakeLists.txt index 360d6e3052..a12abb7822 100644 --- a/plugins/impex/ora/CMakeLists.txt +++ b/plugins/impex/ora/CMakeLists.txt @@ -1,32 +1,28 @@ set(libkritaconverter_LIB_SRCS ora_converter.cc ) set(kritaoraimport_SOURCES ora_import.cc ${libkritaconverter_LIB_SRCS} ) add_library(kritaoraimport MODULE ${kritaoraimport_SOURCES}) target_link_libraries(kritaoraimport kritaui ) install(TARGETS kritaoraimport DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) set(kritaoraexport_SOURCES ora_export.cc ${libkritaconverter_LIB_SRCS} ) add_library(kritaoraexport MODULE ${kritaoraexport_SOURCES}) target_link_libraries(kritaoraexport kritaui ) install(TARGETS kritaoraexport DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) install( PROGRAMS krita_ora.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) -if(SHOULD_BUILD_FILEMANAGER_THUMBNAIL) - install( FILES krita_ora_thumbnail.desktop DESTINATION ${SERVICES_INSTALL_DIR}) -endif() - diff --git a/plugins/impex/tiff/kis_dlg_options_tiff.cpp b/plugins/impex/tiff/kis_dlg_options_tiff.cpp index 4dbe04e97a..84df9b8c99 100644 --- a/plugins/impex/tiff/kis_dlg_options_tiff.cpp +++ b/plugins/impex/tiff/kis_dlg_options_tiff.cpp @@ -1,172 +1,167 @@ /* * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_dlg_options_tiff.h" #include #include #include #include #include #include #include #include #include #include #include #include KisTIFFOptionsWidget::KisTIFFOptionsWidget(QWidget *parent) : KisConfigWidget(parent) { setupUi(this); activated(0); connect(kComboBoxCompressionType, SIGNAL(activated(int)), this, SLOT(activated(int))); connect(flatten, SIGNAL(toggled(bool)), this, SLOT(flattenToggled(bool))); QApplication::restoreOverrideCursor(); setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); } -KisTIFFOptionsWidget::~KisTIFFOptionsWidget() -{ - delete optionswdg; -} - void KisTIFFOptionsWidget::setConfiguration(const KisPropertiesConfigurationSP cfg) { kComboBoxCompressionType->setCurrentIndex(cfg->getInt("compressiontype", 0)); activated(kComboBoxCompressionType->currentIndex()); kComboBoxPredictor->setCurrentIndex(cfg->getInt("predictor", 0)); alpha->setChecked(cfg->getBool("alpha", true)); flatten->setChecked(cfg->getBool("flatten", true)); flattenToggled(flatten->isChecked()); qualityLevel->setValue(cfg->getInt("quality", 80)); compressionLevelDeflate->setValue(cfg->getInt("deflate", 6)); kComboBoxFaxMode->setCurrentIndex(cfg->getInt("faxmode", 0)); compressionLevelPixarLog->setValue(cfg->getInt("pixarlog", 6)); chkSaveProfile->setChecked(cfg->getBool("saveProfile", true)); if (cfg->getInt("type", -1) == KoChannelInfo::FLOAT16 || cfg->getInt("type", -1) == KoChannelInfo::FLOAT32) { kComboBoxPredictor->removeItem(1); } else { kComboBoxPredictor->removeItem(2); } if (cfg->getBool("isCMYK")) { alpha->setChecked(false); alpha->setEnabled(false); } } KisPropertiesConfigurationSP KisTIFFOptionsWidget::configuration() const { KisTIFFOptions opts = options(); KisPropertiesConfigurationSP cfg(new KisPropertiesConfiguration()); cfg->setProperty("compressiontype", kComboBoxCompressionType->currentIndex()); cfg->setProperty("predictor", opts.predictor - 1); cfg->setProperty("alpha", opts.alpha); cfg->setProperty("flatten", opts.flatten); cfg->setProperty("quality", opts.jpegQuality); cfg->setProperty("deflate", opts.deflateCompress); cfg->setProperty("faxmode", opts.faxMode - 1); cfg->setProperty("pixarlog", opts.pixarLogCompress); cfg->setProperty("saveProfile", opts.saveProfile); return cfg; } void KisTIFFOptionsWidget::activated(int index) { switch (index) { case 1: codecsOptionsStack->setCurrentIndex(1); break; case 2: codecsOptionsStack->setCurrentIndex(2); break; case 6: codecsOptionsStack->setCurrentIndex(3); break; case 8: codecsOptionsStack->setCurrentIndex(4); break; default: codecsOptionsStack->setCurrentIndex(0); } } void KisTIFFOptionsWidget::flattenToggled(bool t) { alpha->setEnabled(t); if (!t) { alpha->setChecked(true); } } KisTIFFOptions KisTIFFOptionsWidget::options() const { KisTIFFOptions options; switch (kComboBoxCompressionType->currentIndex()) { case 0: options.compressionType = COMPRESSION_NONE; break; case 1: options.compressionType = COMPRESSION_JPEG; break; case 2: options.compressionType = COMPRESSION_DEFLATE; break; case 3: options.compressionType = COMPRESSION_LZW; break; case 4: options.compressionType = COMPRESSION_JP2000; break; case 5: options.compressionType = COMPRESSION_CCITTRLE; break; case 6: options.compressionType = COMPRESSION_CCITTFAX3; break; case 7: options.compressionType = COMPRESSION_CCITTFAX4; break; case 8: options.compressionType = COMPRESSION_PIXARLOG; break; default: options.compressionType = COMPRESSION_NONE; } options.predictor = kComboBoxPredictor->currentIndex() + 1; options.alpha = alpha->isChecked(); options.flatten = flatten->isChecked(); options.jpegQuality = qualityLevel->value(); options.deflateCompress = compressionLevelDeflate->value(); options.faxMode = kComboBoxFaxMode->currentIndex() + 1; options.pixarLogCompress = compressionLevelPixarLog->value(); options.saveProfile = chkSaveProfile->isChecked(); return options; } diff --git a/plugins/impex/tiff/kis_dlg_options_tiff.h b/plugins/impex/tiff/kis_dlg_options_tiff.h index b7fb930b3a..62a78db5f1 100644 --- a/plugins/impex/tiff/kis_dlg_options_tiff.h +++ b/plugins/impex/tiff/kis_dlg_options_tiff.h @@ -1,51 +1,47 @@ /* * Copyright (c) 2005-2006 Cyrille Berger * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KIS_DLG_OPTIONS_TIFF_H #define KIS_DLG_OPTIONS_TIFF_H #include #include #include "ui_kis_wdg_options_tiff.h" class Ui_KisWdgOptionsTIFF; /** @author Cyrille Berger */ class KisTIFFOptionsWidget : public KisConfigWidget, public Ui::KisWdgOptionsTIFF { Q_OBJECT public: KisTIFFOptionsWidget(QWidget *parent = 0); - ~KisTIFFOptionsWidget(); - void setConfiguration(const KisPropertiesConfigurationSP cfg); - KisPropertiesConfigurationSP configuration() const; + void setConfiguration(const KisPropertiesConfigurationSP cfg) override; + KisPropertiesConfigurationSP configuration() const override; public Q_SLOTS: void activated(int index); void flattenToggled(bool); KisTIFFOptions options() const; -public: - QWidget* wdg; - Ui_KisWdgOptionsTIFF* optionswdg; }; #endif diff --git a/plugins/impex/video/video_export_options_dialog.cpp b/plugins/impex/video/video_export_options_dialog.cpp index 05f367259f..8894d52cb9 100644 --- a/plugins/impex/video/video_export_options_dialog.cpp +++ b/plugins/impex/video/video_export_options_dialog.cpp @@ -1,243 +1,243 @@ /* * Copyright (c) 2016 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "video_export_options_dialog.h" #include "ui_video_export_options_dialog.h" #include #include #include struct VideoExportOptionsDialog::Private { Private() { presets << KoID("ultrafast", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "ultrafast")); presets << KoID("superfast", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "superfast")); presets << KoID("veryfast", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "veryfast")); presets << KoID("faster", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "faster")); presets << KoID("fast", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "fast")); presets << KoID("medium", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "medium")); presets << KoID("slow", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "slow")); presets << KoID("slower", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "slower")); presets << KoID("veryslow", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "veryslow")); presets << KoID("placebo", i18nc("h264 preset name, check simplescreenrecorder for standard translations", "placebo")); profiles << KoID("baseline", i18nc("h264 profile name, check simplescreenrecorder for standard translations", "baseline")); profiles << KoID("main", i18nc("h264 profile name, check simplescreenrecorder for standard translations", "main")); profiles << KoID("high", i18nc("h264 profile name, check simplescreenrecorder for standard translations", "high")); profiles << KoID("high10", i18nc("h264 profile name, check simplescreenrecorder for standard translations", "high10")); profiles << KoID("high422", i18nc("h264 profile name, check simplescreenrecorder for standard translations", "high422")); profiles << KoID("high444", i18nc("h264 profile name, check simplescreenrecorder for standard translations", "high444")); tunes << KoID("film", i18nc("h264 tune option name, check simplescreenrecorder for standard translations", "film")); tunes << KoID("animation", i18nc("h264 tune option name, check simplescreenrecorder for standard translations", "animation")); tunes << KoID("grain", i18nc("h264 tune option name, check simplescreenrecorder for standard translations", "grain")); tunes << KoID("stillimage", i18nc("h264 tune option name, check simplescreenrecorder for standard translations", "stillimage")); tunes << KoID("psnr", i18nc("h264 tune option name, check simplescreenrecorder for standard translations", "psnr")); tunes << KoID("ssim", i18nc("h264 tune option name, check simplescreenrecorder for standard translations", "ssim")); tunes << KoID("fastdecode", i18nc("h264 tune option name, check simplescreenrecorder for standard translations", "fastdecode")); tunes << KoID("zerolatency", i18nc("h264 tune option name, check simplescreenrecorder for standard translations", "zerolatency")); } QVector presets; int defaultPreset; int defaultBitrate; int defaultConstantRateFactor; QVector profiles; int defaultProfile; QVector tunes; int defaultTune; QString defaultCustomLine; QString currentCustomLine; void updateDefaultCustomLine() { defaultCustomLine = currentCustomLine; } }; VideoExportOptionsDialog::VideoExportOptionsDialog(QWidget *parent) : KisConfigWidget(parent), ui(new Ui::VideoExportOptionsDialog), m_d(new Private) { ui->setupUi(this); ui->intConstantRateFactor->setRange(0, 51); ui->intConstantRateFactor->setValue(m_d->defaultConstantRateFactor); Q_FOREACH (const KoID &preset, m_d->presets) { ui->cmbPreset->insertItem(ui->cmbPreset->count(), preset.name()); } ui->cmbPreset->setCurrentIndex(m_d->defaultPreset); Q_FOREACH (const KoID &profile, m_d->profiles) { ui->cmbProfile->insertItem(ui->cmbProfile->count(), profile.name()); } ui->cmbProfile->setCurrentIndex(m_d->defaultProfile); Q_FOREACH (const KoID &tune, m_d->tunes) { ui->cmbTune->insertItem(ui->cmbTune->count(), tune.name()); } ui->cmbTune->setCurrentIndex(m_d->defaultTune); ui->intBitrate->setRange(10, 50000); ui->intBitrate->setValue(5000); ui->intBitrate->setSuffix(i18nc("kilo-bits-per-second, video bitrate suffix", "kbps")); connect(ui->cmbCodec, SIGNAL(currentIndexChanged(int)), ui->stackedWidget, SLOT(setCurrentIndex(int))); ui->cmbCodec->setCurrentIndex(0); ui->cmbCodec->setEnabled(false); // TODO: temporarily hidden! Some combinations of 'tune' and // 'profile' options make ffmpeg generate empty file. // We should not let the user shoot into his own foot! ui->cmbTune->setVisible(false); ui->lblTune->setVisible(false); ui->chkCustomLine->setChecked(!m_d->defaultCustomLine.isEmpty()); slotCustomLineToggled(!m_d->defaultCustomLine.isEmpty()); connect(ui->chkCustomLine, SIGNAL(toggled(bool)), SLOT(slotCustomLineToggled(bool))); connect(ui->txtCustomLine, SIGNAL(editingFinished()), SLOT(slotSaveCustomLine())); connect(ui->btnResetCustomLine, SIGNAL(clicked()), SLOT(slotResetCustomLine())); } VideoExportOptionsDialog::~VideoExportOptionsDialog() { delete ui; } KisPropertiesConfigurationSP VideoExportOptionsDialog::configuration() const { KisPropertiesConfigurationSP cfg(new KisPropertiesConfiguration()); cfg->setProperty("h264PresetIndex", ui->cmbPreset->currentIndex()); cfg->setProperty("h264ConstantRateFactor", ui->intConstantRateFactor->value()); cfg->setProperty("h264ProfileIndex", ui->cmbProfile->currentIndex()); cfg->setProperty("h264TuneIndex", ui->cmbTune->currentIndex()); cfg->setProperty("TheoraBitrate", ui->intBitrate->value()); cfg->setProperty("CustomLineValue", ui->txtCustomLine->text()); cfg->setProperty("customUserOptions", customUserOptions().join(' ')); return cfg; } void VideoExportOptionsDialog::slotCustomLineToggled(bool value) { m_d->updateDefaultCustomLine(); QString customLine = m_d->defaultCustomLine; if (customLine.isEmpty() && value) { customLine = generateCustomLine().join(" "); } else if (!value) { - customLine = ""; + customLine = QString(); } ui->txtCustomLine->setText(customLine); ui->stackedWidget->setEnabled(!value); ui->txtCustomLine->setEnabled(value); ui->btnResetCustomLine->setEnabled(value); } void VideoExportOptionsDialog::slotResetCustomLine() { ui->txtCustomLine->setText(generateCustomLine().join(" ")); slotSaveCustomLine(); } void VideoExportOptionsDialog::slotSaveCustomLine() { m_d->currentCustomLine = ui->txtCustomLine->text(); } void VideoExportOptionsDialog::setCodec(CodecIndex index) { ui->cmbCodec->setCurrentIndex(int(index)); } QStringList VideoExportOptionsDialog::customUserOptions() const { return ui->chkCustomLine->isChecked() ? ui->txtCustomLine->text().split(" ", QString::SkipEmptyParts) : generateCustomLine(); } void VideoExportOptionsDialog::setConfiguration(const KisPropertiesConfigurationSP cfg) { m_d->defaultPreset = cfg->getInt("h264PresetIndex", 5); ui->cmbPreset->setCurrentIndex(m_d->defaultPreset); m_d->defaultConstantRateFactor = cfg->getInt("h264ConstantRateFactor", 23); ui->intConstantRateFactor->setValue(m_d->defaultConstantRateFactor); m_d->defaultProfile = cfg->getInt("h264ProfileIndex", 4); ui->cmbProfile->setCurrentIndex(m_d->defaultProfile); m_d->defaultTune = cfg->getInt("h264TuneIndex", 1); ui->cmbTune->setCurrentIndex(m_d->defaultTune); m_d->defaultBitrate = cfg->getInt("TheoraBitrate", 5000); ui->intBitrate->setValue(m_d->defaultBitrate); - m_d->defaultCustomLine = cfg->getString("CustomLineValue", ""); + m_d->defaultCustomLine = cfg->getString("CustomLineValue", QString()); ui->txtCustomLine->setText(m_d->defaultCustomLine); if (cfg->hasProperty("CodecIndex")) { setCodec((VideoExportOptionsDialog::CodecIndex)cfg->getInt("CodecIndex")); } if (cfg->getString("mimetype") == "video/ogg") { ui->cmbCodec->setEnabled(false); } } QStringList VideoExportOptionsDialog::generateCustomLine() const { QStringList options; if (ui->cmbCodec->currentIndex() == int(CODEC_H264)) { options << "-crf" << QString::number(ui->intConstantRateFactor->value()); const int presetIndex = ui->cmbPreset->currentIndex(); //qDebug() << "presetIndex" << presetIndex << m_d->presets; options << "-preset" << m_d->presets[presetIndex].id(); const int profileIndex = ui->cmbProfile->currentIndex(); options << "-profile" << m_d->profiles[profileIndex].id(); if (m_d->profiles[profileIndex].id() == "high422") { options << "-pix_fmt" << "yuv422p"; } else if (m_d->profiles[profileIndex].id() == "high444") { options << "-pix_fmt" << "yuv444p"; } else { options << "-pix_fmt" << "yuv420p"; } // Disabled! see the comment in c-tor! //const int tuneIndex = ui->cmbTune->currentIndex(); //options << "-tune" << m_d->tunes[tuneIndex].id(); } else if (ui->cmbCodec->currentIndex() == int(CODEC_THEORA)) { options << "-b" << QString::number(ui->intBitrate->value()) + "k"; } return options; } diff --git a/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp b/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp index dd774ea014..2d378181f5 100644 --- a/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp +++ b/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp @@ -1,340 +1,340 @@ /* * Copyright (c) 2010 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_brush_based_paintop_settings.h" #include #include #include "kis_brush_based_paintop_options_widget.h" #include #include "kis_brush_server.h" #include #include "kis_signals_blocker.h" #include "kis_brush_option.h" struct BrushReader { BrushReader(const KisBrushBasedPaintOpSettings *parent) : m_parent(parent) { m_option.readOptionSetting(m_parent); } KisBrushSP brush() { return m_option.brush(); } const KisBrushBasedPaintOpSettings *m_parent; KisBrushOption m_option; }; struct BrushWriter { BrushWriter(KisBrushBasedPaintOpSettings *parent) : m_parent(parent) { m_option.readOptionSetting(m_parent); } ~BrushWriter() { m_option.writeOptionSetting(m_parent); } KisBrushSP brush() { return m_option.brush(); } KisBrushBasedPaintOpSettings *m_parent; KisBrushOption m_option; }; KisBrushBasedPaintOpSettings::KisBrushBasedPaintOpSettings() : KisOutlineGenerationPolicy(KisCurrentOutlineFetcher::SIZE_OPTION | KisCurrentOutlineFetcher::ROTATION_OPTION | KisCurrentOutlineFetcher::MIRROR_OPTION) { } bool KisBrushBasedPaintOpSettings::paintIncremental() { if (hasProperty("PaintOpAction")) { return (enumPaintActionType)getInt("PaintOpAction", WASH) == BUILDUP; } return true; } bool KisBrushBasedPaintOpSettings::isAirbrushing() const { return getBool(AIRBRUSH_ENABLED); } int KisBrushBasedPaintOpSettings::rate() const { return getInt(AIRBRUSH_RATE); } KisPaintOpSettingsSP KisBrushBasedPaintOpSettings::clone() const { KisPaintOpSettingsSP _settings = KisOutlineGenerationPolicy::clone(); KisBrushBasedPaintOpSettingsSP settings = dynamic_cast(_settings.data()); settings->m_savedBrush = this->brush(); return settings; } KisBrushSP KisBrushBasedPaintOpSettings::brush() const { KisBrushSP brush = m_savedBrush; if (!brush) { BrushReader w(this); brush = w.brush(); m_savedBrush = brush; } return brush; } QPainterPath KisBrushBasedPaintOpSettings::brushOutlineImpl(const KisPaintInformation &info, OutlineMode mode, qreal additionalScale, bool forceOutline) { QPainterPath path; if (forceOutline || mode == CursorIsOutline || mode == CursorIsCircleOutline || mode == CursorTiltOutline) { KisBrushSP brush = this->brush(); if (!brush) return path; qreal finalScale = brush->scale() * additionalScale; QPainterPath realOutline = brush->outline(); if (mode == CursorIsCircleOutline || mode == CursorTiltOutline || (forceOutline && mode == CursorNoOutline)) { QPainterPath ellipse; ellipse.addEllipse(realOutline.boundingRect()); realOutline = ellipse; } path = outlineFetcher()->fetchOutline(info, this, realOutline, finalScale, brush->angle()); if (mode == CursorTiltOutline) { QPainterPath tiltLine = makeTiltIndicator(info, realOutline.boundingRect().center(), realOutline.boundingRect().width() * 0.5, 3.0); path.addPath(outlineFetcher()->fetchOutline(info, this, tiltLine, finalScale, 0.0, true, realOutline.boundingRect().center().x(), realOutline.boundingRect().center().y())); } } return path; } QPainterPath KisBrushBasedPaintOpSettings::brushOutline(const KisPaintInformation &info, OutlineMode mode) { return brushOutlineImpl(info, mode, 1.0); } bool KisBrushBasedPaintOpSettings::isValid() const { - QString filename = getString("requiredBrushFile", ""); + QString filename = getString("requiredBrushFile", QString()); if (!filename.isEmpty()) { KisBrushSP brush = KisBrushServer::instance()->brushServer()->resourceByFilename(filename); if (!brush) { return false; } } return true; } bool KisBrushBasedPaintOpSettings::isLoadable() { return (KisBrushServer::instance()->brushServer()->resources().count() > 0); } void KisBrushBasedPaintOpSettings::setAngle(qreal value) { BrushWriter w(this); if (!w.brush()) return; w.brush()->setAngle(value); } qreal KisBrushBasedPaintOpSettings::angle() { return this->brush()->angle(); } void KisBrushBasedPaintOpSettings::setSpacing(qreal value) { BrushWriter w(this); if (!w.brush()) return; w.brush()->setSpacing(value); } qreal KisBrushBasedPaintOpSettings::spacing() { return this->brush()->spacing(); } void KisBrushBasedPaintOpSettings::setAutoSpacing(bool active, qreal coeff) { BrushWriter w(this); if (!w.brush()) return; w.brush()->setAutoSpacing(active, coeff); } bool KisBrushBasedPaintOpSettings::autoSpacingActive() { return this->brush()->autoSpacingActive(); } qreal KisBrushBasedPaintOpSettings::autoSpacingCoeff() { return this->brush()->autoSpacingCoeff(); } void KisBrushBasedPaintOpSettings::setPaintOpSize(qreal value) { BrushWriter w(this); if (!w.brush()) return; w.brush()->setUserEffectiveSize(value); } qreal KisBrushBasedPaintOpSettings::paintOpSize() const { return this->brush()->userEffectiveSize(); } #include #include "kis_paintop_preset.h" #include "kis_paintop_settings_update_proxy.h" QList KisBrushBasedPaintOpSettings::uniformProperties(KisPaintOpSettingsSP settings) { QList props = listWeakToStrong(m_uniformProperties); if (props.isEmpty()) { { KisIntSliderBasedPaintOpPropertyCallback *prop = new KisIntSliderBasedPaintOpPropertyCallback( KisIntSliderBasedPaintOpPropertyCallback::Int, "angle", "Angle", settings, 0); prop->setRange(0, 360); prop->setReadCallback( [](KisUniformPaintOpProperty *prop) { KisBrushBasedPaintOpSettings *s = dynamic_cast(prop->settings().data()); const qreal angleResult = kisRadiansToDegrees(s->angle()); prop->setValue(angleResult); }); prop->setWriteCallback( [](KisUniformPaintOpProperty *prop) { KisBrushBasedPaintOpSettings *s = dynamic_cast(prop->settings().data()); s->setAngle(kisDegreesToRadians(prop->value().toReal())); }); QObject::connect(preset()->updateProxy(), SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue())); prop->requestReadValue(); props << toQShared(prop); } { KisUniformPaintOpPropertyCallback *prop = new KisUniformPaintOpPropertyCallback( KisUniformPaintOpPropertyCallback::Bool, "auto_spacing", "Auto Spacing", settings, 0); prop->setReadCallback( [](KisUniformPaintOpProperty *prop) { KisBrushBasedPaintOpSettings *s = dynamic_cast(prop->settings().data()); prop->setValue(s->autoSpacingActive()); }); prop->setWriteCallback( [](KisUniformPaintOpProperty *prop) { KisBrushBasedPaintOpSettings *s = dynamic_cast(prop->settings().data()); s->setAutoSpacing(prop->value().toBool(), s->autoSpacingCoeff()); }); QObject::connect(preset()->updateProxy(), SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue())); prop->requestReadValue(); props << toQShared(prop); } { KisDoubleSliderBasedPaintOpPropertyCallback *prop = new KisDoubleSliderBasedPaintOpPropertyCallback( KisDoubleSliderBasedPaintOpPropertyCallback::Double, "spacing", "Spacing", settings, 0); prop->setRange(0.01, 10); prop->setSingleStep(0.01); prop->setReadCallback( [](KisUniformPaintOpProperty *prop) { KisBrushBasedPaintOpSettings *s = dynamic_cast(prop->settings().data()); const qreal value = s->autoSpacingActive() ? s->autoSpacingCoeff() : s->spacing(); prop->setValue(value); }); prop->setWriteCallback( [](KisUniformPaintOpProperty *prop) { KisBrushBasedPaintOpSettings *s = dynamic_cast(prop->settings().data()); if (s->autoSpacingActive()) { s->setAutoSpacing(true, prop->value().toReal()); } else { s->setSpacing(prop->value().toReal()); } }); QObject::connect(preset()->updateProxy(), SIGNAL(sigSettingsChanged()), prop, SLOT(requestReadValue())); prop->requestReadValue(); props << toQShared(prop); } } return KisPaintOpSettings::uniformProperties(settings) + props; } void KisBrushBasedPaintOpSettings::onPropertyChanged() { m_savedBrush.clear(); KisOutlineGenerationPolicy::onPropertyChanged(); } diff --git a/plugins/paintops/libpaintop/kis_filter_option.cpp b/plugins/paintops/libpaintop/kis_filter_option.cpp index bdf1a57c02..eddff6d354 100644 --- a/plugins/paintops/libpaintop/kis_filter_option.cpp +++ b/plugins/paintops/libpaintop/kis_filter_option.cpp @@ -1,215 +1,215 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_filter_option.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_wdgfilteroption.h" #include class KisFilterOptionWidget : public QWidget, public Ui::FilterOpOptions { public: KisFilterOptionWidget(QWidget* parent = 0) : QWidget(parent) { setupUi(this); } }; KisFilterOption::KisFilterOption() : KisPaintOpOption(KisPaintOpOption::FILTER, true) { setObjectName("KisFilterOption"); m_checkable = false; m_filterOptionWidget = new KisFilterOptionWidget(); m_filterOptionWidget->hide(); setConfigurationPage(m_filterOptionWidget); m_layout = new QGridLayout(m_filterOptionWidget->grpFilterOptions); // Check which filters support painting QList l = KisFilterRegistry::instance()->keys(); QList l2; QList::iterator it; for (it = l.begin(); it != l.end(); ++it) { KisFilterSP f = KisFilterRegistry::instance()->value((*it)); if (f->supportsPainting()) { l2.push_back(KoID(*it, f->name())); } } m_filterOptionWidget->filtersList->setIDList(l2); connect(m_filterOptionWidget->filtersList, SIGNAL(activated(const KoID &)), SLOT(setCurrentFilter(const KoID &))); if (!l2.empty()) { setCurrentFilter(l2.first()); } connect(m_filterOptionWidget->checkBoxSmudgeMode, SIGNAL(stateChanged(int)), this, SLOT(emitSettingChanged())); } KisFilterOption::~KisFilterOption() { } const KisFilterSP KisFilterOption::filter() const { return m_currentFilter; } KisFilterConfigurationSP KisFilterOption::filterConfig() const { if (!m_currentFilterConfigWidget) return 0; return static_cast(m_currentFilterConfigWidget->configuration().data()); } bool KisFilterOption::smudgeMode() const { return m_filterOptionWidget->checkBoxSmudgeMode->isChecked(); } void KisFilterOption::setNode(KisNodeWSP node) { if (node && node->paintDevice()) { m_paintDevice = node->paintDevice(); // The "not m_currentFilterConfigWidget" is a corner case // which happens because the first configuration settings is // created before any layer is selected in the view if (!m_currentFilterConfigWidget || (m_currentFilterConfigWidget && static_cast(m_currentFilterConfigWidget->configuration().data())->isCompatible(m_paintDevice) ) ) { if (m_currentFilter) { KisPropertiesConfigurationSP configuration = 0; if (m_currentFilterConfigWidget) { configuration = m_currentFilterConfigWidget->configuration(); } setCurrentFilter(KoID(m_currentFilter->id())); if (configuration) { m_currentFilterConfigWidget->setConfiguration(configuration); } } } } else { m_paintDevice = 0; } } void KisFilterOption::setImage(KisImageWSP image) { m_image = image; if (!m_currentFilterConfigWidget) { updateFilterConfigWidget(); } } void KisFilterOption::setCurrentFilter(const KoID& id) { m_currentFilter = KisFilterRegistry::instance()->get(id.id()); m_filterOptionWidget->filtersList->setCurrent(id); updateFilterConfigWidget(); emitSettingChanged(); } void KisFilterOption::updateFilterConfigWidget() { if (m_currentFilterConfigWidget) { m_currentFilterConfigWidget->hide(); m_layout->removeWidget(m_currentFilterConfigWidget); m_layout->invalidate(); delete m_currentFilterConfigWidget; } m_currentFilterConfigWidget = 0; if (m_currentFilter && m_image && m_paintDevice) { m_currentFilterConfigWidget = m_currentFilter->createConfigurationWidget(m_filterOptionWidget->grpFilterOptions, m_paintDevice); if (m_currentFilterConfigWidget) { m_layout->addWidget(m_currentFilterConfigWidget); m_filterOptionWidget->grpFilterOptions->updateGeometry(); m_currentFilterConfigWidget->show(); connect(m_currentFilterConfigWidget, SIGNAL(sigConfigurationUpdated()), this, SLOT(emitSettingChanged())); } } m_layout->update(); } void KisFilterOption::writeOptionSetting(KisPropertiesConfigurationSP setting) const { if (!m_currentFilter) return; setting->setProperty(FILTER_ID, m_currentFilter->id()); setting->setProperty(FILTER_SMUDGE_MODE, smudgeMode()); if (filterConfig()) { setting->setProperty(FILTER_CONFIGURATION, filterConfig()->toXML()); } } void KisFilterOption::readOptionSetting(const KisPropertiesConfigurationSP setting) { - KoID id(setting->getString(FILTER_ID), ""); + KoID id(setting->getString(FILTER_ID), QString()); if (id.id() != m_currentFilter->id()) { setCurrentFilter(id); } m_filterOptionWidget->checkBoxSmudgeMode->setChecked(setting->getBool(FILTER_SMUDGE_MODE)); KisFilterConfigurationSP configuration = filterConfig(); if (configuration && m_currentFilterConfigWidget) { configuration->fromXML(setting->getString(FILTER_CONFIGURATION)); m_currentFilterConfigWidget->blockSignals(true); m_currentFilterConfigWidget->setConfiguration(configuration); m_currentFilterConfigWidget->blockSignals(false); } } void KisFilterOption::lodLimitations(KisPaintopLodLimitations *l) const { KisFilterConfigurationSP config = filterConfig(); if (m_currentFilter && config) { QRect testRect(0,0,100,100); if (m_currentFilter->neededRect(testRect, config, 0) != testRect || m_currentFilter->changedRect(testRect, config, 0) != testRect) { l->blockers << KoID("filter-nonlinear", i18nc("PaintOp instant preview limitation", "\"%1\" does not support scaled preview (non-linear filter)", config->name())); } } } #include "moc_kis_filter_option.cpp" diff --git a/plugins/paintops/libpaintop/tests/kis_embedded_pattern_manager_test.cpp b/plugins/paintops/libpaintop/tests/kis_embedded_pattern_manager_test.cpp index 47ca53179e..2f382f3d7e 100644 --- a/plugins/paintops/libpaintop/tests/kis_embedded_pattern_manager_test.cpp +++ b/plugins/paintops/libpaintop/tests/kis_embedded_pattern_manager_test.cpp @@ -1,233 +1,233 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_embedded_pattern_manager_test.h" #include #include "kis_embedded_pattern_manager.h" #include #include #include #include #include KoPattern *createPattern() { QImage image(512, 512, QImage::Format_ARGB32); image.fill(255); QPainter gc(&image); gc.fillRect(100, 100, 312, 312, Qt::red); return new KoPattern(image, "__test_pattern", KoResourceServerProvider::instance()->patternServer()->saveLocation()); } void KisEmbeddedPatternManagerTest::initTestCase() { // touch all the barriers KisResourceServerProvider::instance()->paintOpPresetServer(); KoResourceServerProvider::instance()->patternServer(); KisResourceServerProvider::instance()->workspaceServer(); } void KisEmbeddedPatternManagerTest::init() { cleanUp(); } void KisEmbeddedPatternManagerTest::cleanUp() { Q_FOREACH (KoPattern * p, KoResourceServerProvider::instance()->patternServer()->resources()) { if (p->filename().contains("__test_pattern")) { QFile file(p->filename()); file.remove(); } QVERIFY(KoResourceServerProvider::instance()->patternServer()->removeResourceFromServer(p)); } } void KisEmbeddedPatternManagerTest::testRoundTrip() { KoPattern *pattern = createPattern(); - KisPropertiesConfiguration config; + KisPropertiesConfigurationSP config(new KisPropertiesConfiguration); - KisEmbeddedPatternManager::saveEmbeddedPattern(&config, pattern); + KisEmbeddedPatternManager::saveEmbeddedPattern(config, pattern); - KoPattern *newPattern = KisEmbeddedPatternManager::loadEmbeddedPattern(&config); + KoPattern *newPattern = KisEmbeddedPatternManager::loadEmbeddedPattern(config); QCOMPARE(newPattern->pattern(), pattern->pattern()); QCOMPARE(newPattern->name(), pattern->name()); QCOMPARE(QFileInfo(newPattern->filename()).fileName(), QFileInfo(pattern->filename()).fileName()); delete pattern; // will be deleted by the server // delete newPattern; } enum NameStatus { VALID, PATH, EMPTY }; -KisPropertiesConfiguration createXML(NameStatus nameStatus, +KisPropertiesConfigurationSP createXML(NameStatus nameStatus, bool hasMd5) { QString fileName("./__test_pattern_path.pat"); QString name; switch (nameStatus) { case VALID: name = "__test_pattern_name"; break; case PATH: name = "./path/some_weird_path.pat"; break; case EMPTY: name = ""; break; } - KisPropertiesConfiguration setting; + KisPropertiesConfigurationSP setting(new KisPropertiesConfiguration); { KoPattern *pattern = createPattern(); if (hasMd5) { QByteArray patternMD5 = pattern->md5(); - setting.setProperty("Texture/Pattern/PatternMD5", patternMD5.toBase64()); + setting->setProperty("Texture/Pattern/PatternMD5", patternMD5.toBase64()); } QByteArray ba; QBuffer buffer(&ba); buffer.open(QIODevice::WriteOnly); pattern->pattern().save(&buffer, "PNG"); - setting.setProperty("Texture/Pattern/Pattern", ba.toBase64()); + setting->setProperty("Texture/Pattern/Pattern", ba.toBase64()); delete pattern; } - setting.setProperty("Texture/Pattern/PatternFileName", fileName); - setting.setProperty("Texture/Pattern/Name", name); + setting->setProperty("Texture/Pattern/PatternFileName", fileName); + setting->setProperty("Texture/Pattern/Name", name); return setting; } KoPattern* findOnServer(QByteArray md5) { KoPattern *pattern = 0; if (!md5.isEmpty()) { Q_FOREACH (KoResource * res, KoResourceServerProvider::instance()->patternServer()->resources()) { KoPattern *pat = static_cast(res); if (pat->md5() == md5) { pattern = pat; break; } } } return pattern; } void checkOneConfig(NameStatus nameStatus, bool hasMd5, QString expectedName, bool isOnServer) { KoPattern *basePattern = createPattern(); KoPattern *initialPattern = findOnServer(basePattern->md5()); QCOMPARE((bool)initialPattern, isOnServer); - KisPropertiesConfiguration setting = createXML(nameStatus, hasMd5); - KoPattern *pattern = KisEmbeddedPatternManager::loadEmbeddedPattern(&setting); + KisPropertiesConfigurationSP setting = createXML(nameStatus, hasMd5); + KoPattern *pattern = KisEmbeddedPatternManager::loadEmbeddedPattern(setting); QVERIFY(pattern); QCOMPARE(pattern->pattern(), basePattern->pattern()); QCOMPARE(pattern->name(), QString(expectedName)); QFileInfo info(pattern->filename()); QVERIFY(info.baseName().startsWith(expectedName)); QCOMPARE(info.dir().path(), QDir(KoResourceServerProvider::instance()->patternServer()->saveLocation()).path()); if (isOnServer) { QCOMPARE(initialPattern, pattern); } // will be deleted by the server // delete pattern; delete basePattern; } void KisEmbeddedPatternManagerTest::testLoadingNoOnServerValidName() { checkOneConfig(VALID, false, "__test_pattern_name", false); } void KisEmbeddedPatternManagerTest::testLoadingNoOnServerEmptyName() { checkOneConfig(EMPTY, false, "__test_pattern_path", false); } void KisEmbeddedPatternManagerTest::testLoadingNoOnServerPathName() { checkOneConfig(PATH, false, "__test_pattern_path", false); } void KisEmbeddedPatternManagerTest::testLoadingOnServerValidName() { KoResourceServerProvider::instance()->patternServer()->addResource(createPattern(), false); checkOneConfig(VALID, false, "__test_pattern", true); } void KisEmbeddedPatternManagerTest::testLoadingOnServerEmptyName() { KoResourceServerProvider::instance()->patternServer()->addResource(createPattern(), false); checkOneConfig(EMPTY, false, "__test_pattern", true); } void KisEmbeddedPatternManagerTest::testLoadingOnServerPathName() { KoResourceServerProvider::instance()->patternServer()->addResource(createPattern(), false); checkOneConfig(PATH, false, "__test_pattern", true); } void KisEmbeddedPatternManagerTest::testLoadingOnServerValidNameMd5() { KoResourceServerProvider::instance()->patternServer()->addResource(createPattern(), false); checkOneConfig(VALID, true, "__test_pattern", true); } void KisEmbeddedPatternManagerTest::testLoadingOnServerEmptyNameMd5() { KoResourceServerProvider::instance()->patternServer()->addResource(createPattern(), false); checkOneConfig(EMPTY, true, "__test_pattern", true); } void KisEmbeddedPatternManagerTest::testLoadingOnServerPathNameMd5() { KoResourceServerProvider::instance()->patternServer()->addResource(createPattern(), false); checkOneConfig(PATH, true, "__test_pattern", true); } QTEST_MAIN(KisEmbeddedPatternManagerTest)