diff --git a/.gitignore b/.gitignore index 23b9e3aa56..920395f108 100644 --- a/.gitignore +++ b/.gitignore @@ -1,30 +1,31 @@ *.trace build qtcreator-build *.kdev4 *~ .kateconfig CMakeLists.txt.user* .directory *.rej *.orig *.patch *.autosave *.swp .gdb_history .kdev_include_paths *.config *.creator *.creator.user *.files *.includes .DS_Store *.kate-swap *.diff *.patch .idea GTAGS GPATH GRTAGS GSYMS BROWSE +*.kate-swp diff --git a/CMakeLists.txt b/CMakeLists.txt index 97172a6c63..5ebd53b444 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,685 +1,683 @@ project(krita) message(STATUS "Using CMake version: ${CMAKE_VERSION}") cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) set(MIN_QT_VERSION 5.3.0) set(MIN_FRAMEWORKS_VERSION 5.7.0) cmake_policy(SET CMP0002 OLD) #cmake_policy CMP0017 was introduced in version 2.8.4 if (NOT ${CMAKE_VERSION} VERSION_LESS 2.8.3) cmake_policy(SET CMP0017 NEW) endif () if (NOT ${CMAKE_VERSION} VERSION_LESS 2.8.12) cmake_policy(SET CMP0022 OLD) endif () if (NOT ${CMAKE_VERSION} VERSION_LESS 3.0.0) cmake_policy(SET CMP0026 OLD) cmake_policy(SET CMP0046 OLD) endif () if(NOT ${CMAKE_VERSION} VERSION_LESS 3.3.0) cmake_policy(SET CMP0059 OLD) cmake_policy(SET CMP0063 OLD) endif() # QT5TODO: remove KDE4_BUILD_TESTS once all kde4_add_unit_test have been converted # transitional forward compatibility: # BUILD_TESTING is cmake standard, KDE4_BUILD_TESTS not used by ECM/KF5, but only # macros in cmake/transitional. Just, Macros from cmake/transitional, # incl. kde4_add_unit_test, are only picked up if no macros from kdelibs4 are installed, # because that transitional path is appended. Prepending instead might possibly unwantedly # mask ECM/KF5 macros. Not tested. # So have BUILD_TESTING define KDE4_BUILD_TESTS. if (BUILD_TESTING) set(KDE4_BUILD_TESTS TRUE) else() set(KDE4_BUILD_TESTS FALSE) endif() ###################### ####################### ## Constants defines ## ####################### ###################### # define common versions of Calligra applications, used to generate calligraversion.h # update these version for every release: set(CALLIGRA_VERSION_STRING "3.0 Alpha") set(CALLIGRA_STABLE_VERSION_MAJOR 3) # 3 for 3.x, 4 for 4.x, etc. set(CALLIGRA_STABLE_VERSION_MINOR 0) # 0 for 3.0, 1 for 3.1, etc. set(CALLIGRA_VERSION_RELEASE 89) # 89 for Alpha, increase for next test releases, set 0 for first Stable, etc. set(CALLIGRA_ALPHA 1) # uncomment only for Alpha #set(CALLIGRA_BETA 1) # uncomment only for Beta #set(CALLIGRA_RC 1) # uncomment only for RC set(CALLIGRA_YEAR 2015) # update every year if(NOT DEFINED CALLIGRA_ALPHA AND NOT DEFINED CALLIGRA_BETA AND NOT DEFINED CALLIGRA_RC) set(CALLIGRA_STABLE 1) # do not edit endif() message(STATUS "Krita version: ${CALLIGRA_VERSION_STRING}") # Define the generic version of the Calligra libraries here # This makes it easy to advance it when the next Calligra release comes. # 14 was the last GENERIC_CALLIGRA_LIB_VERSION_MAJOR of the previous Calligra series # (2.x) so we're starting with 15 in 3.x series. if(CALLIGRA_STABLE_VERSION_MAJOR EQUAL 3) math(EXPR GENERIC_CALLIGRA_LIB_VERSION_MAJOR "${CALLIGRA_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_CALLIGRA_LIB_VERSION_MAJOR to something bigger") endif() set(GENERIC_CALLIGRA_LIB_VERSION "${GENERIC_CALLIGRA_LIB_VERSION_MAJOR}.0.0") set(GENERIC_CALLIGRA_LIB_SOVERSION "${GENERIC_CALLIGRA_LIB_VERSION_MAJOR}") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules") LIST (APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/kde_macro") message("Module path:" ${CMAKE_MODULE_PATH}) # fetch git revision for the current build set(CALLIGRA_GIT_SHA1_STRING "") set(CALLIGRA_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(CALLIGRA_GIT_SHA1_STRING ${GIT_SHA1}) set(CALLIGRA_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}") ############ ############# ## Options ## ############# ############ option(USEOPENGL "Allow the use of OpenGL for Krita" ON) if (WIN32) option(USE_BREAKPAD "Build the crash handler for Krita (only on windows)" OFF) endif () option(PACKAGERS_BUILD "Build support of multiple CPU architectures in one binary. Should be used by packagers only." OFF) ####################### ######################## ## Productset setting ## ######################## ####################### # For predefined productsets see the definitions in CalligraProducts.cmake and # in the files in the folder cmake/productsets. # 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) # get the definitions of products, features and product sets include(CalligraProducts.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(ECMInstallIcons) include(ECMAddAppIcon) include(ECMSetupVersion) include(ECMMarkNonGuiExecutable) include(ECMGenerateHeaders) include(GenerateExportHeader) include(ECMMarkAsTest) include(CMakePackageConfigHelpers) include(WriteBasicConfigVersionFile) include(CheckFunctionExists) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings) include(FeatureSummary) include(KDE4Macros) -find_package(KF5 ${MIN_FRAMEWORKS_VERSION} REQUIRED COMPONENTS +find_package(KF5 ${MIN_FRAMEWORKS_VERSION} REQUIRED Archive Completion Config CoreAddons GuiAddons I18n - IconThemes ItemModels ItemViews WidgetsAddons WindowSystem OPTIONAL_COMPONENTS KIO ) -find_package(Qt5 ${MIN_QT_VERSION} REQUIRED COMPONENTS +find_package(Qt5 ${MIN_QT_VERSION} REQUIRED Core Gui Widgets Xml Network PrintSupport Svg Test Concurrent OPTIONAL_COMPONENTS Qml - Declarative X11Extras DBus ) +find_package(Qt5::Declarative ${MIN_QT_VERSION}) set(HAVE_DBUS Qt5DBus_FOUND) set(QT_QTTEST_LIBRARY Qt5::Test) if (USEOPENGL) find_package(Qt5 ${MIN_QT_VERSION} REQUIRED OpenGL) set(QT_QTOPENGL_FOUND ${Qt5OpenGL_FOUND}) if (NOT WIN32) find_package(Qt5 ${MIN_QT_VERSION} REQUIRED X11Extras) endif() endif () include (MacroLibrary) include (MacroAdditionalCleanFiles) include (MacroAddFileDependencies) include (ECMInstallIcons) macro_ensure_out_of_source_build("Compiling Calligra inside the source directory is not possible. Please refer to the build instruction http://community.kde.org/Calligra/Building/Building_Calligra") macro_bool_to_01(KF5KIO_FOUND HAVE_KIO) find_package(X11) if(X11_FOUND) find_package(Qt5 ${MIN_QT_VERSION} REQUIRED NO_MODULE COMPONENTS X11Extras ) set(HAVE_X11 TRUE) add_definitions(-DHAVE_X11) else() set(HAVE_X11 FALSE) endif() # use sane compile flags 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 ) # 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() # 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(CALLIGRA_PLUGIN_INSTALL_DIR ${LIB_INSTALL_DIR}/krita) ########################### ############################ ## Required dependencies ## ############################ ########################### find_package(Perl REQUIRED) find_package(ZLIB REQUIRED) 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(${PNG_INCLUDE_DIR}) endif() add_definitions(-DBOOST_ALL_NO_LIB) find_package(Boost REQUIRED COMPONENTS system) # for pigment and stage if (NOT Boost_FOUND) message(FATAL_ERROR "Did not find Boost. Boost is required for the core libraries, stage, sheets and krita.") endif () if (APPLE) find_package(Carbon REQUIRED) endif () ########################### ############################ ## Optional dependencies ## ############################ ########################### ## ## Check for OpenEXR ## macro_optional_find_package(OpenEXR) macro_bool_to_01(OPENEXR_FOUND HAVE_OPENEXR) ## ## Look for OpenGL ## set(HAVE_OPENGL 0) if (USEOPENGL) macro_optional_find_package(OpenGL) if(OPENGL_FOUND) message(STATUS "Found OpenGL: ${OPENGL_LIBRARIES}") if(QT_QTOPENGL_FOUND) message(STATUS "Found Qt OpenGL support") set(HAVE_OPENGL 1) else() message(STATUS "Did NOT find Qt OpenGL support. Check your Qt configuration") endif() else() message(STATUS "Did NOT find OpenGL libraries") endif() macro_log_feature(HAVE_OPENGL "OpenGL" "OpenGL support" "" FALSE "" "Required by Gemini, parts of Krita and optionally by flake") endif() ## ## Test for GNU Scientific Library ## macro_optional_find_package(GSL) macro_log_feature(GSL_FOUND "GSL" "GNU Scientific Library" "http://www.gnu.org/software/gsl" FALSE "1.7" "Required by Krita's Transform tool and Sheets' solver plugin") macro_bool_to_01(GSL_FOUND HAVE_GSL) configure_file(config-gsl.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-gsl.h ) ## ## Test for eigen3 ## macro_optional_find_package(Eigen3) macro_log_feature(EIGEN3_FOUND "Eigen" "C++ template library for linear algebra" "http://eigen.tuxfamily.org" FALSE "3.0" "Required by Calligra Sheets and Krita") ## ## Test for exiv2 ## set(EXIV2_MIN_VERSION "0.16") macro_optional_find_package(Exiv2) macro_log_feature(EXIV2_FOUND "Exiv2" "Image metadata library and tools" "http://www.exiv2.org" FALSE "0.16" "Required by Krita") ## ## Test for lcms ## macro_optional_find_package(LCMS2) macro_log_feature(LCMS2_FOUND "LittleCMS" "Color management engine" "http://www.littlecms.com" FALSE "2.4" "Will be used for color management and is necesary 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 ) macro_optional_find_package(Vc 0.6.70) macro_log_feature(Vc_FOUND "Vc" "Portable, zero-overhead SIMD library for C++" "http://code.compeng.uni-frankfurt.de/projects/vc" FALSE "" "Required by the Krita for vectorization") macro_bool_to_01(Vc_FOUND HAVE_VC) macro_bool_to_01(PACKAGERS_BUILD DO_PACKAGERS_BUILD) 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") else() set(ADDITIONAL_VC_FLAGS "-Wabi -fabi-version=0 -ffp-contract=fast") endif() #Handle Vc master if(Vc_VERSION_MAJOR GREATER 0 OR Vc_VERSION_MINOR GREATER 7) message(STATUS "Vc version is greater than 0.7, enabling AVX2 support") 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} -fPIC ONLY SSE2 SSSE3 SSE4_1 AVX AVX2) 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} -fPIC ONLY Scalar SSE2 SSSE3 SSE4_1 AVX AVX2) else() set(${_objs} ${_src}) endif() endmacro() else() macro(ko_compile_for_all_implementations_no_scalar _objs _src) if(PACKAGERS_BUILD) vc_compile_for_all_implementations(${_objs} ${_src} FLAGS ${ADDITIONAL_VC_FLAGS} -fPIC ONLY SSE2 SSSE3 SSE4_1 AVX) 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} -fPIC ONLY Scalar SSE2 SSSE3 SSE4_1 AVX) else() set(${_objs} ${_src}) endif() endmacro() endif() if (NOT PACKAGERS_BUILD) # Optimize the whole Calligra for 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} ${KDE4_DEFINITIONS} ${QT_QTDBUS_DEFINITIONS}) if(WIN32) set(KDE4_ICON_DIR ${KDE_INSTALL_FULL_ICONDIR}) message(STATUS "using oxygen application icons from ${KDE4_ICON_DIR}") set(LIB_INSTALL_DIR ${LIB_INSTALL_DIR} RUNTIME DESTINATION ${BIN_INSTALL_DIR} LIBRARY ${INSTALL_TARGETS_DEFAULT_ARGS} ARCHIVE ${INSTALL_TARGETS_DEFAULT_ARGS} ) else() set (KDE4_ICON_DIR ${CMAKE_INSTALL_PREFIX}/share/icons) endif() ## ## Test endianess ## include (TestBigEndian) test_big_endian(CMAKE_WORDS_BIGENDIAN) ## ## Test SharedMimeInfo ## macro_optional_find_package(SharedMimeInfo) macro_log_feature(SHARED_MIME_INFO_FOUND "SharedMimeInfo" "Shared Mime Info" "http://freedesktop.org/wiki/Software/shared-mime-info" FALSE "" "Required to determine file types OpenRaster (Krita default format).") ## ## Test for qt-poppler ## macro_optional_find_package(Poppler) macro_log_feature( POPPLER_FOUND "Poppler-Qt5" "A PDF rendering library" "http://poppler.freedesktop.org" FALSE "" "Required by the Krita PDF filter, Karbon PDF import filter and CSTester PDF feature") ## ## Generate a file for prefix information ## ############################### ################################ ## Add Calligra helper macros ## ################################ ############################### include(MacroCalligraAddBenchmark) include(MacroCalligraAddTest) #################### ##################### ## Define includes ## ##################### #################### # for config.h and includes (if any?) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/interfaces ) set(KOVERSION_INCLUDES ${CMAKE_SOURCE_DIR}/libs/version ${CMAKE_BINARY_DIR}/libs/version ) include_directories(${KOVERSION_INCLUDES}) # koplugin is at the bottom of the stack set(KOPLUGIN_INCLUDES ${CMAKE_SOURCE_DIR}/libs/koplugin) set(KUNDO2_INCLUDES ${CMAKE_SOURCE_DIR}/libs/kundo2 ${CMAKE_BINARY_DIR}/libs/kundo2 ${CMAKE_SOURCE_DIR}/libs/widgetutils ${CMAKE_SOURCE_DIR}/libs/widgetutils/config ${CMAKE_SOURCE_DIR}/libs/widgetutils/xmlgui ) # koodf is at the bottom of the stack set(KOODF_INCLUDES ${CMAKE_SOURCE_DIR}/libs/odf ${CMAKE_SOURCE_DIR}/libs/store ${CMAKE_BINARY_DIR}/libs/odf ${CMAKE_BINARY_DIR}/libs/store ${KOVERSION_INCLUDES} ) # pigment depends on koplugin and lcms set(PIGMENT_INCLUDES ${KOPLUGIN_INCLUDES} ${KOVERSION_INCLUDES} ${CMAKE_SOURCE_DIR}/libs/pigment ${CMAKE_BINARY_DIR}/libs/pigment ${CMAKE_SOURCE_DIR}/libs/pigment/compositeops ${CMAKE_SOURCE_DIR}/libs/pigment/resources ${Boost_INCLUDE_DIRS} ) # flake depends on koodf and pigment set(FLAKE_INCLUDES ${CMAKE_SOURCE_DIR}/libs/flake ${KOODF_INCLUDES} ${PIGMENT_INCLUDES} ${KUNDO2_INCLUDES} ${CMAKE_SOURCE_DIR}/libs/flake/commands ${CMAKE_SOURCE_DIR}/libs/flake/tools ${CMAKE_SOURCE_DIR}/libs/flake/svg ${CMAKE_BINARY_DIR}/libs/flake) # vectorimage set(VECTORIMAGE_INCLUDES ${CMAKE_SOURCE_DIR}/libs/vectorimage ${CMAKE_SOURCE_DIR}/libs/vectorimage/libemf ${CMAKE_SOURCE_DIR}/libs/vectorimage/libsvm ${CMAKE_SOURCE_DIR}/libs/vectorimage/libwmf) # KoText depends on koplugin, odf set(KOTEXT_INCLUDES ${CMAKE_SOURCE_DIR}/libs/kotext ${CMAKE_BINARY_DIR}/libs/kotext ${CMAKE_SOURCE_DIR}/libs/kotext/changetracker ${CMAKE_SOURCE_DIR}/libs/kotext/styles ${CMAKE_SOURCE_DIR}/libs/kotext/opendocument ${FLAKE_INCLUDES} ${KOODF_INCLUDES}) # TextLayout depends on kotext set(TEXTLAYOUT_INCLUDES ${KOTEXT_INCLUDES} ${CMAKE_SOURCE_DIR}/libs/textlayout ${CMAKE_BINARY_DIR}/libs/textlayout) # Widgets depends on kritatext and flake set(KOWIDGETS_INCLUDES ${KOTEXT_INCLUDES} ${CMAKE_SOURCE_DIR}/libs/widgetutils ${CMAKE_BINARY_DIR}/libs/widgetutils ${CMAKE_SOURCE_DIR}/libs/widgets ${CMAKE_BINARY_DIR}/libs/widgets) # BasicFlakes depends on flake, widgets set(BASICFLAKES_INCLUDES ${KOWIDGETS_INCLUDES} ${CMAKE_SOURCE_DIR}/libs/basicflakes ${CMAKE_BINARY_DIR}/libs/basicflakes ${CMAKE_SOURCE_DIR}/libs/basicflakes/tools) ################################################### #################################################### ## Detect which products/features can be compiled ## #################################################### ################################################### if (NOT WIN32) set(NOT_WIN TRUE) endif() if (NOT QT_MAC_USE_COCOA) set(NOT_COCOA TRUE) endif() 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" SHARED_MIME_INFO_FOUND "SharedMimeInfo 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(3rdparty) add_subdirectory(interfaces) -add_subdirectory(pics) add_subdirectory(plugins) macro_display_feature_log() calligra_product_deps_report("product_deps") calligra_log_should_build() add_custom_target(apidox doc/api/gendocs.pl WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) configure_file(KoConfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/KoConfig.h ) ## temporary warning if (WARN_ABOUT_CREATIVEONLY) message(STATUS "WARNING:\n You are using a deprecated build flag,\n switch from \"-DCREATIVEONLY=ON\" to \"-DPRODUCTSET=CREATIVE\"\n and remove the line \"CREATIVEONLY:BOOL=ON\" from CMakeCache.txt") message(STATUS "-------------------------------------------------------------------" ) endif () diff --git a/krita/CMakeLists.txt b/krita/CMakeLists.txt index 589c947461..d21f1c77e6 100644 --- a/krita/CMakeLists.txt +++ b/krita/CMakeLists.txt @@ -1,177 +1,188 @@ project(krita) add_definitions( -DTRANSLATION_DOMAIN=\"krita\" -DQT_USE_QSTRINGBUILDER -DQT_STRICT_ITERATORS -DQT_NO_URL_CAST_FROM_STRING -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DQT_USE_FAST_OPERATOR_PLUS -DQT_USE_FAST_CONCATENATION ) kde_enable_exceptions() # To avoid the confusion of an endless stream of Eigen warnings. if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC) add_definitions(-Wno-unused-local-typedefs -Wno-deprecated -Wno-deprecated-declarations) endif () set(KRITA_DEFAULT_TEST_DATA_DIR ${CMAKE_CURRENT_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() # # 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) endif() if(MSVC OR (WIN32 AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") if (USE_BREAKPAD) include_directories(${CMAKE_SOURCE_DIR}/3rdparty/google-breakpad/src) endif () # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:16777216") # for g'mic... # set(CMAKE_CXX_STACK_SIZE "999999999") endif() macro_optional_find_package(FFTW3) macro_log_feature(FFTW3_FOUND "FFTW3" "A fast, free C FFT library" "http://www.fftw.org/" FALSE "" "Required by the Krita for fast convolution operators") macro_bool_to_01(FFTW3_FOUND HAVE_FFTW3) configure_file(image/config_convolution.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/image/config_convolution.h) include(CheckFunctionExists) if(HAVE_OPENGL) message(STATUS "OpenGL found -- krita will be able to use OpenGL for hardware accelerated rendering.") else() message(STATUS "OpenGL NOT found - krita will not be able to use OpenGL for hardware accelerated rendering.") endif() macro_optional_find_package(OCIO) macro_log_feature(OCIO_FOUND "OCIO" "The OpenColorIO Library" "http://www.opencolorio.org" FALSE "" "Required by the Krita LUT docker") macro_bool_to_01(OCIO_FOUND HAVE_OCIO) configure_file(config-ocio.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ocio.h ) if(UNIX) set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};m") endif() check_function_exists(powf HAVE_POWF) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-powf.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-powf.h) set(LINK_OPENEXR_LIB) if(OPENEXR_FOUND) include_directories(${OPENEXR_INCLUDE_DIR}) set(LINK_OPENEXR_LIB ${OPENEXR_LIBRARIES}) add_definitions(${OPENEXR_DEFINITIONS}) endif() if(WIN32) if(MSVC) # C4522: 'class' : multiple assignment operators specified set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4522") endif() endif() set(KRITA_INCLUDES # For config-*.h ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/image ${CMAKE_SOURCE_DIR}/krita/libglobal ${CMAKE_SOURCE_DIR}/krita/libpsd ${CMAKE_SOURCE_DIR}/krita/image ${CMAKE_SOURCE_DIR}/krita/image/brushengine ${CMAKE_SOURCE_DIR}/krita/image/tiles ${CMAKE_SOURCE_DIR}/krita/libbrush ${CMAKE_SOURCE_DIR}/krita/libcolor ${CMAKE_SOURCE_DIR}/krita/ui ${CMAKE_SOURCE_DIR}/krita/ui/canvas ${CMAKE_SOURCE_DIR}/krita/ui/tool ${CMAKE_SOURCE_DIR}/krita/ui/flake ${CMAKE_SOURCE_DIR}/krita/ui/widgets # For generated files from .ui ${CMAKE_BINARY_DIR}/krita/ui ${PIGMENT_INCLUDES} ${BASICFLAKES_INCLUDES} ${TEXTLAYOUT_INCLUDES} ${CMAKE_SOURCE_DIR}/libs/widgets ${CMAKE_SOURCE_DIR}/libs/widgets/resources ${CMAKE_SOURCE_DIR}/libs/widgets/colorwidgets ${CMAKE_SOURCE_DIR}/libs/widgetutils ${EIGEN3_INCLUDE_DIR} ${Vc_INCLUDE_DIR} # 'Export' this for use by filters CACHE INTERNAL "" ) include_directories(${KRITA_INCLUDES}) if(HAVE_OPENGL) include_directories(${OPENGL_INCLUDE_DIR}) endif() add_subdirectory( libglobal ) add_subdirectory( libpsd ) add_subdirectory( image ) add_subdirectory( libbrush ) add_subdirectory( libcolor ) add_subdirectory( ui ) add_subdirectory( dtd ) add_subdirectory( plugins ) add_subdirectory( data ) add_subdirectory( integration ) -add_subdirectory( pics ) +add_subdirectory( pics/app ) if (WIN32 AND USE_BREAKPAD) add_subdirectory( crashreporter ) endif () if (NOT WIN32) add_subdirectory( benchmarks ) endif () set(krita_SRCS main.cc) if(WIN32 AND USE_BREAKPAD) set(krita_SRCS ${krita_SRCS} kis_crash_handler.cpp) set(BREAKPAD_LIBS breakpad) endif() -file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/pics/app/hi*-apps-calligrakrita.png") +file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/pics/app/*-apps-calligrakrita.png") ecm_add_app_icon(krita_SRCS ICONS ${ICONS_SRCS}) -qt5_add_resources(krita_SRCS krita.qrc) +qt5_add_resources(krita_SRCS krita.qrc + pics/Breeze-dark/breeze-dark-icons.qrc + pics/Breeze-light/breeze-light-icons.qrc + pics/layerbox/layerbox-icons.qrc + pics/layerbox/svg/layerbox-svg-icons.qrc + pics/misc-light/misc-light-icons.qrc + pics/misc-dark/misc-dark-icons.qrc + pics/tools/16/tools-16-icons.qrc + pics/tools/SVG/16/tools-svg-16-icons.qrc + pics/tool_transform/tool-transform-icons.qrc + pics/svg/svg-icons.qrc +) add_executable(krita ${krita_SRCS}) target_link_libraries(krita kritaui ${BREAKPAD_LIBS}) if (APPLE) set_target_properties(krita PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.template) set_target_properties(krita PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "org.krita") set_target_properties(krita PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Krita") endif () install(TARGETS krita ${INSTALL_TARGETS_DEFAULT_ARGS}) install(PROGRAMS krita.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) install(FILES krita.rc DESTINATION ${DATA_INSTALL_DIR}/krita) install(FILES krita.action DESTINATION ${DATA_INSTALL_DIR}/krita/actions) install(FILES krita.appdata.xml DESTINATION ${SHARE_INSTALL_PREFIX}/appdata/ ) #if (${QTVERSION} VERSION_GREATER 4.7.0 AND NOT APPLE AND HAVE_OPENGL) # add_subdirectory(sketch) # add_subdirectory(gemini) #endif () diff --git a/krita/data/templates/comics/hi128-actions-template_comics_empty.png b/krita/data/templates/comics/128-actions-template_comics_empty.png similarity index 100% rename from krita/data/templates/comics/hi128-actions-template_comics_empty.png rename to krita/data/templates/comics/128-actions-template_comics_empty.png diff --git a/krita/data/templates/comics/hi128-actions-template_comics_empty.svg b/krita/data/templates/comics/128-actions-template_comics_empty.svg similarity index 100% rename from krita/data/templates/comics/hi128-actions-template_comics_empty.svg rename to krita/data/templates/comics/128-actions-template_comics_empty.svg diff --git a/krita/data/templates/comics/CMakeLists.txt b/krita/data/templates/comics/CMakeLists.txt index a6c8ea3e1d..77dd504f85 100644 --- a/krita/data/templates/comics/CMakeLists.txt +++ b/krita/data/templates/comics/CMakeLists.txt @@ -1,15 +1,21 @@ -ecm_install_icons(${DATA_INSTALL_DIR}/krita/icons ) +ecm_install_icons( +ICONS +128-actions-template_comics_empty.png +DESTINATION +${DATA_INSTALL_DIR}/krita/icons +) + install( FILES a4_waffle_grid.kra BD-EuroTemplate.kra Comics-USTemplate.kra Manga-JpTemplate.kra DESTINATION ${DATA_INSTALL_DIR}/krita/templates/comics/.source) install( FILES .directory a4_waffle_grid.desktop BD-EuroTemplate.desktop Comics-USTemplate.desktop Manga-JpTemplate.desktop DESTINATION ${DATA_INSTALL_DIR}/krita/templates/comics) diff --git a/krita/data/templates/design/hi128-actions-template_DIN_A3_landscape.png b/krita/data/templates/design/128-actions-template_DIN_A3_landscape.png similarity index 100% rename from krita/data/templates/design/hi128-actions-template_DIN_A3_landscape.png rename to krita/data/templates/design/128-actions-template_DIN_A3_landscape.png diff --git a/krita/data/templates/design/hi128-actions-template_DIN_A4_portrait.png b/krita/data/templates/design/128-actions-template_DIN_A4_portrait.png similarity index 100% rename from krita/data/templates/design/hi128-actions-template_DIN_A4_portrait.png rename to krita/data/templates/design/128-actions-template_DIN_A4_portrait.png diff --git a/krita/data/templates/design/hi128-actions-template_ratio_1610.png b/krita/data/templates/design/128-actions-template_ratio_1610.png similarity index 100% rename from krita/data/templates/design/hi128-actions-template_ratio_1610.png rename to krita/data/templates/design/128-actions-template_ratio_1610.png diff --git a/krita/data/templates/design/hi128-actions-template_ratio_2391.png b/krita/data/templates/design/128-actions-template_ratio_2391.png similarity index 100% rename from krita/data/templates/design/hi128-actions-template_ratio_2391.png rename to krita/data/templates/design/128-actions-template_ratio_2391.png diff --git a/krita/data/templates/design/hi128-actions-template_ratio_43.png b/krita/data/templates/design/128-actions-template_ratio_43.png similarity index 100% rename from krita/data/templates/design/hi128-actions-template_ratio_43.png rename to krita/data/templates/design/128-actions-template_ratio_43.png diff --git a/krita/data/templates/design/hi128-actions-template_web_design.png b/krita/data/templates/design/128-actions-template_web_design.png similarity index 100% rename from krita/data/templates/design/hi128-actions-template_web_design.png rename to krita/data/templates/design/128-actions-template_web_design.png diff --git a/krita/data/templates/design/CMakeLists.txt b/krita/data/templates/design/CMakeLists.txt index 3bd641fb29..10f2333dbd 100644 --- a/krita/data/templates/design/CMakeLists.txt +++ b/krita/data/templates/design/CMakeLists.txt @@ -1,19 +1,29 @@ -ecm_install_icons(${DATA_INSTALL_DIR}/krita/icons ) +ecm_install_icons( +ICONS +128-actions-template_DIN_A3_landscape.png +128-actions-template_DIN_A4_portrait.png +128-actions-template_ratio_1610.png +128-actions-template_ratio_2391.png +128-actions-template_ratio_43.png +128-actions-template_web_design.png +DESTINATION +${DATA_INSTALL_DIR}/krita/icons ) + install( FILES Designcinema16_10_2484x1200_96dpiRGB_8bit_.kra Designcinema2.39_1_2484x1040_96dpiRGB_8bit_.kra DesignpresentationA3Landscape_4960x3508_300dpiRGB_8bit_.kra DesignpresentationA4portrait_2480x3508_300dpiRGB_8bit_.kra Designscreen4_3_2250x1680_96dpiRGB_8bit_.kra web_design.kra DESTINATION ${DATA_INSTALL_DIR}/krita/templates/design/.source) install( FILES .directory Designcinema16_10_2484x1200_96dpiRGB_8bit_.desktop Designcinema2.39_1_2484x1040_96dpiRGB_8bit_.desktop DesignpresentationA3Landscape_4960x3508_300dpiRGB_8bit_.desktop DesignpresentationA4portrait_2480x3508_300dpiRGB_8bit_.desktop Designscreen4_3_2250x1680_96dpiRGB_8bit_.desktop web_design.desktop DESTINATION ${DATA_INSTALL_DIR}/krita/templates/design) diff --git a/krita/data/templates/dslr/hi128-actions-template_dslr.png b/krita/data/templates/dslr/128-actions-template_dslr.png similarity index 100% rename from krita/data/templates/dslr/hi128-actions-template_dslr.png rename to krita/data/templates/dslr/128-actions-template_dslr.png diff --git a/krita/data/templates/dslr/CMakeLists.txt b/krita/data/templates/dslr/CMakeLists.txt index 3c3d7dfeb6..4541a43718 100644 --- a/krita/data/templates/dslr/CMakeLists.txt +++ b/krita/data/templates/dslr/CMakeLists.txt @@ -1,17 +1,22 @@ -ecm_install_icons(${DATA_INSTALL_DIR}/krita/icons ) +ecm_install_icons( +ICONS +128-actions-template_dslr.png +DESTINATION +${DATA_INSTALL_DIR}/krita/icons ) + install( FILES Canon_550D_5184x3456.kra Canon_5Dmk3_5760x3840.kra Nikon_D3000_3872x2592.kra Nikon_D5000_4288x2848.kra Nikon_D7000_4928x3264.kra DESTINATION ${DATA_INSTALL_DIR}/krita/templates/dslr/.source) install( FILES .directory Canon_550D_5184x3456.desktop Canon_5Dmk3_5760x3840.desktop Nikon_D3000_3872x2592.desktop Nikon_D5000_4288x2848.desktop Nikon_D7000_4928x3264.desktop DESTINATION ${DATA_INSTALL_DIR}/krita/templates/dslr) diff --git a/krita/data/templates/film/hi128-action-template_film.png b/krita/data/templates/film/128-action-template_film.png similarity index 100% rename from krita/data/templates/film/hi128-action-template_film.png rename to krita/data/templates/film/128-action-template_film.png diff --git a/krita/data/templates/film/CMakeLists.txt b/krita/data/templates/film/CMakeLists.txt index cc6de71ca4..2f805a9214 100644 --- a/krita/data/templates/film/CMakeLists.txt +++ b/krita/data/templates/film/CMakeLists.txt @@ -1,19 +1,23 @@ -ecm_install_icons(${DATA_INSTALL_DIR}/krita/icons ) +ecm_install_icons( +ICONS +128-action-template_film.png +DESTINATION +${DATA_INSTALL_DIR}/krita/icons ) install( FILES 1K_super35_fullAp_1024x778.kra 2K_super35_fullAp_2048x1556.kra 4K_super35_fullAp_4096x3112.kra HD_720p_1280x720.kra HD_full_1920x1080.kra HD_half_960x540.kra DESTINATION ${DATA_INSTALL_DIR}/krita/templates/film/.source) install( FILES .directory 1K_super35_fullAp_1024x778.desktop 2K_super35_fullAp_2048x1556.desktop 4K_super35_fullAp_4096x3112.desktop HD_720p_1280x720.desktop HD_full_1920x1080.desktop HD_half_960x540.desktop DESTINATION ${DATA_INSTALL_DIR}/krita/templates/film) diff --git a/krita/data/templates/texture/hi128-actions-template_texture.png b/krita/data/templates/texture/128-actions-template_texture.png similarity index 100% rename from krita/data/templates/texture/hi128-actions-template_texture.png rename to krita/data/templates/texture/128-actions-template_texture.png diff --git a/krita/data/templates/texture/CMakeLists.txt b/krita/data/templates/texture/CMakeLists.txt index c50be49717..e1e1f798af 100644 --- a/krita/data/templates/texture/CMakeLists.txt +++ b/krita/data/templates/texture/CMakeLists.txt @@ -1,35 +1,39 @@ -ecm_install_icons(${DATA_INSTALL_DIR}/krita/icons ) +ecm_install_icons( +ICONS +128-actions-template_texture.png +DESTINATION +${DATA_INSTALL_DIR}/krita/icons ) install( FILES Texture1024x10248bitsrgb.kra Texture1k32bitscalar.kra Texture1k8bitsrgb.kra Texture2048x20488bitsrgb.kra Texture256x2568bitsrgb.kra Texture2k32bitscalar.kra Texture2k8bitsrgb.kra Texture4096x40968bitsrgb.kra Texture4k32bitscalar.kra Texture4k8bitsrgb.kra Texture512x5128bitsrgb.kra Texture8k32bitscalar.kra Texture8k8bitsrgb.kra DESTINATION ${DATA_INSTALL_DIR}/krita/templates/texture/.source) install( FILES .directory Texture1024x10248bitsrgb.desktop Texture1k32bitscalar.desktop Texture1k8bitsrgb.desktop Texture2048x20488bitsrgb.desktop Texture256x2568bitsrgb.desktop Texture2k32bitscalar.desktop Texture2k8bitsrgb.desktop Texture4096x40968bitsrgb.desktop Texture4k32bitscalar.desktop Texture4k8bitsrgb.desktop Texture512x5128bitsrgb.desktop Texture8k32bitscalar.desktop Texture8k8bitsrgb.desktop DESTINATION ${DATA_INSTALL_DIR}/krita/templates/texture) diff --git a/krita/gemini/icon/CMakeLists.txt b/krita/gemini/icon/CMakeLists.txt index 832a8e552a..af0f2f7301 100644 --- a/krita/gemini/icon/CMakeLists.txt +++ b/krita/gemini/icon/CMakeLists.txt @@ -1 +1,11 @@ -ecm_install_icons( ${ICON_INSTALL_DIR} ) +ecm_install_icons( +ICONS +128-app-kritagemini.png +16-app-kritagemini.png +22-app-kritagemini.png +256-app-kritagemini.png +32-app-kritagemini.png +48-app-kritagemini.png +64-app-kritagemini.png +DESTINATION + ${ICON_INSTALL_DIR} ) diff --git a/krita/krita.qrc b/krita/krita.qrc index 7719571aa1..0094de113f 100644 --- a/krita/krita.qrc +++ b/krita/krita.qrc @@ -1,386 +1,73 @@ pics/broken-preset.png pics/delete.png pics/height_icon.png pics/height.png pics/hi16-add_dialog.png pics/hi16-palette_library.png pics/icon-kritasketch-256.png pics/landscape.png pics/linked.png pics/local_selection_active.png pics/local_selection_inactive.png pics/offset_horizontal.png pics/offset_vertical.png pics/portrait.png pics/ratio_icon.png pics/selection_add.png pics/selection_exclude.png pics/selection_intersect.png pics/selection_replace.png pics/selection_subtract.png pics/select_pixel.png pics/select_shape.png pics/shade.png pics/shear_horizontal.png pics/shear_vertical.png pics/sidebaricon.png pics/tablet.png pics/tool_screenshot.png pics/transparency-locked.png pics/transparency-unlocked.png pics/light_passthrough-enabled.png pics/dark_passthrough-enabled.png pics/light_passthrough-disabled.png pics/dark_passthrough-disabled.png pics/layer-style-enabled.png pics/layer-style-disabled.png pics/unlinked.png pics/width_icon.png pics/width.png pics/workspace-chooser.png pics/onionA.png pics/onionB.png pics/mirrorAxis-HorizontalMove.png pics/mirrorAxis-VerticalMove.png pics/visible.svg pics/novisible.svg pics/dirty-preset.svg pics/dark_selection-mode_ants.png pics/dark_selection-mode_invisible.png pics/dark_selection-mode_mask.png pics/dark_trim-to-image.png pics/dark_layer-locked.png pics/dark_layer-unlocked.png pics/dark_transparency-enabled.png pics/dark_transparency-disabled.png pics/dark_novisible.svg pics/dark_visible.svg pics/light_transparency-enabled.png pics/light_transparency-disabled.png pics/light_layer-locked.png pics/light_layer-unlocked.png pics/light_selection-mode_ants.png pics/light_selection-mode_invisible.png pics/light_selection-mode_mask.png pics/light_trim-to-image.png pics/light_novisible.svg pics/light_visible.svg - pics/layerbox/dark_addlayer.png - pics/layerbox/dark_addtofolder.png - pics/layerbox/dark_arrowdown.png - pics/layerbox/dark_arrowupblr.png - pics/layerbox/dark_deletelayer.png - pics/layerbox/dark_duplicatelayer.png - pics/layerbox/dark_properties.png - pics/layerbox/dark_removefromfolder.png - pics/layerbox/light_addlayer.png - pics/layerbox/light_addtofolder.png - pics/layerbox/light_arrowdown.png - pics/layerbox/light_arrowupblr.png - pics/layerbox/light_deletelayer.png - pics/layerbox/light_duplicatelayer.png - pics/layerbox/light_properties.png - pics/layerbox/light_removefromfolder.png - - pics/misc-light/light_draw-eraser.svg - pics/misc-light/light_ox16-action-object-align-horizontal-center-calligra.svg - pics/misc-light/light_ox16-action-object-align-horizontal-left-calligra.svg - pics/misc-light/light_ox16-action-object-align-horizontal-right-calligra.svg - pics/misc-light/light_ox16-action-object-align-vertical-bottom-calligra.svg - pics/misc-light/light_ox16-action-object-align-vertical-center-calligra.svg - pics/misc-light/light_ox16-action-object-align-vertical-top-calligra.svg - pics/misc-light/light_ox16-action-object-group-calligra.svg - pics/misc-light/light_ox16-action-object-order-back-calligra.svg - pics/misc-light/light_ox16-action-object-order-front-calligra.svg - pics/misc-light/light_ox16-action-object-order-lower-calligra.svg - pics/misc-light/light_ox16-action-object-order-raise-calligra.svg - pics/misc-light/light_ox16-action-object-ungroup-calligra.svg - pics/misc-light/light_paintop_settings_01.svg - pics/misc-light/light_paintop_settings_02.svg - pics/misc-light/light_stroke-cap-butt.svg - pics/misc-light/light_stroke-cap-round.svg - pics/misc-light/light_stroke-cap-square.svg - pics/misc-light/light_stroke-join-bevel.svg - pics/misc-light/light_stroke-join-miter.svg - pics/misc-light/light_stroke-join-round.svg - pics/misc-light/light_symmetry-horizontal.svg - pics/misc-light/light_symmetry-vertical.svg - - pics/misc-dark/dark_draw-eraser.svg - pics/misc-dark/dark_ox16-action-object-align-horizontal-center-calligra.svg - pics/misc-dark/dark_ox16-action-object-align-horizontal-left-calligra.svg - pics/misc-dark/dark_ox16-action-object-align-horizontal-right-calligra.svg - pics/misc-dark/dark_ox16-action-object-align-vertical-bottom-calligra.svg - pics/misc-dark/dark_ox16-action-object-align-vertical-center-calligra.svg - pics/misc-dark/dark_ox16-action-object-align-vertical-top-calligra.svg - pics/misc-dark/dark_ox16-action-object-group-calligra.svg - pics/misc-dark/dark_ox16-action-object-order-back-calligra.svg - pics/misc-dark/dark_ox16-action-object-order-front-calligra.svg - pics/misc-dark/dark_ox16-action-object-order-lower-calligra.svg - pics/misc-dark/dark_ox16-action-object-order-raise-calligra.svg - pics/misc-dark/dark_ox16-action-object-ungroup-calligra.svg - pics/misc-dark/dark_paintop_settings_01.svg - pics/misc-dark/dark_paintop_settings_02.svg - pics/misc-dark/dark_stroke-cap-butt.svg - pics/misc-dark/dark_stroke-cap-round.svg - pics/misc-dark/dark_stroke-cap-square.svg - pics/misc-dark/dark_stroke-join-bevel.svg - pics/misc-dark/dark_stroke-join-miter.svg - pics/misc-dark/dark_stroke-join-round.svg - pics/misc-dark/dark_symmetry-horizontal.svg - pics/misc-dark/dark_symmetry-vertical.svg - - pics/tools/16/dark_calligraphy.png - pics/tools/16/dark_draw-text.png - pics/tools/16/dark_format-fill-color.png - pics/tools/16/dark_krita_draw_path.png - pics/tools/16/dark_krita_tool_color_fill.png - pics/tools/16/dark_krita_tool_color_picker.png - pics/tools/16/dark_krita_tool_dyna.png - pics/tools/16/dark_krita_tool_ellipse.png - pics/tools/16/dark_krita_tool_freehand.png - pics/tools/16/dark_krita_tool_freehandvector.png - pics/tools/16/dark_krita_tool_gradient.png - pics/tools/16/dark_krita_tool_grid.png - pics/tools/16/dark_krita_tool_line.png - pics/tools/16/dark_krita_tool_measure.png - pics/tools/16/dark_krita_tool_move.png - pics/tools/16/dark_krita_tool_multihand.png - pics/tools/16/dark_krita_tool_polygon.png - pics/tools/16/dark_krita_tool_rectangle.png - pics/tools/16/dark_krita_tool_ruler_assistant.png - pics/tools/16/dark_krita_tool_transform.png - pics/tools/16/dark_pattern.png - pics/tools/16/dark_polyline.png - pics/tools/16/dark_select.png - pics/tools/16/dark_tool_contiguous_selection.png - pics/tools/16/dark_tool_crop.png - pics/tools/16/dark_tool_elliptical_selection.png - pics/tools/16/dark_tool_outline_selection.png - pics/tools/16/dark_tool_path_selection.png - pics/tools/16/dark_tool_perspectivegrid.png - pics/tools/16/dark_tool_polygonal_selection.png - pics/tools/16/dark_tool_rect_selection.png - pics/tools/16/dark_tool_similar_selection.png - - pics/tools/16/light_calligraphy.png - pics/tools/16/light_draw-text.png - pics/tools/16/light_format-fill-color.png - pics/tools/16/light_krita_draw_path.png - pics/tools/16/light_krita_tool_color_fill.png - pics/tools/16/light_krita_tool_color_picker.png - pics/tools/16/light_krita_tool_dyna.png - pics/tools/16/light_krita_tool_ellipse.png - pics/tools/16/light_krita_tool_freehand.png - pics/tools/16/light_krita_tool_freehandvector.png - pics/tools/16/light_krita_tool_gradient.png - pics/tools/16/light_krita_tool_grid.png - pics/tools/16/light_krita_tool_line.png - pics/tools/16/light_krita_tool_measure.png - pics/tools/16/light_krita_tool_move.png - pics/tools/16/light_krita_tool_multihand.png - pics/tools/16/light_krita_tool_polygon.png - pics/tools/16/light_krita_tool_rectangle.png - pics/tools/16/light_krita_tool_ruler_assistant.png - pics/tools/16/light_krita_tool_transform.png - pics/tools/16/light_pattern.png - pics/tools/16/light_polyline.png - pics/tools/16/light_select.png - pics/tools/16/light_tool_contiguous_selection.png - pics/tools/16/light_tool_crop.png - pics/tools/16/light_tool_elliptical_selection.png - pics/tools/16/light_tool_outline_selection.png - pics/tools/16/light_tool_path_selection.png - pics/tools/16/light_tool_perspectivegrid.png - pics/tools/16/light_tool_polygon.png - pics/tools/16/light_tool_polygonal_selection.png - pics/tools/16/light_tool_rect_selection.png - pics/tools/16/light_tool_similar_selection.png - - pics/tool_transform/dark_transform_icons_cage.png - pics/tool_transform/dark_transform_icons_liquify_erase.png - pics/tool_transform/dark_transform_icons_liquify_main.png - pics/tool_transform/dark_transform_icons_liquify_move.png - pics/tool_transform/dark_transform_icons_liquify_offset.png - pics/tool_transform/dark_transform_icons_liquify_resize.png - pics/tool_transform/dark_transform_icons_liquify_rotate.png - pics/tool_transform/dark_transform_icons_liquify_rotateCCW.png - pics/tool_transform/dark_transform_icons_main.png - pics/tool_transform/dark_transform_icons_perspective.png - pics/tool_transform/dark_transform_icons_warp.png - pics/tool_transform/dark_transform_icons_penPressure.png - pics/tool_transform/dark_krita_tool_transform_recursive.png - - pics/tool_transform/light_transform_icons_cage.png - pics/tool_transform/light_transform_icons_liquify_erase.png - pics/tool_transform/light_transform_icons_liquify_main.png - pics/tool_transform/light_transform_icons_liquify_move.png - pics/tool_transform/light_transform_icons_liquify_offset.png - pics/tool_transform/light_transform_icons_liquify_resize.png - pics/tool_transform/light_transform_icons_liquify_rotate.png - pics/tool_transform/light_transform_icons_liquify_rotateCCW.png - pics/tool_transform/light_transform_icons_main.png - pics/tool_transform/light_transform_icons_perspective.png - pics/tool_transform/light_transform_icons_warp.png - pics/tool_transform/light_transform_icons_penPressure.png - pics/tool_transform/light_krita_tool_transform_recursive.png - - pics/Breeze-dark/dark_application-exit.svg - pics/Breeze-dark/dark_application-pdf.svg - pics/Breeze-dark/dark_applications-system.svg - pics/Breeze-dark/dark_arrow-down.svg - pics/Breeze-dark/dark_arrow-left.svg - pics/Breeze-dark/dark_arrow-right.svg - pics/Breeze-dark/dark_arrow-up.svg - pics/Breeze-dark/dark_bookmarks.svg - pics/Breeze-dark/dark_configure-shortcuts.svg - pics/Breeze-dark/dark_configure-toolbars.svg - pics/Breeze-dark/dark_configure.svg - pics/Breeze-dark/dark_dialog-cancel.svg - pics/Breeze-dark/dark_dialog-close.svg - pics/Breeze-dark/dark_dialog-ok.svg - pics/Breeze-dark/dark_dialog-warning.svg - pics/Breeze-dark/dark_document-edit.svg - pics/Breeze-dark/dark_document-export.svg - pics/Breeze-dark/dark_document-import.svg - pics/Breeze-dark/dark_document-new.svg - pics/Breeze-dark/dark_document-open-recent.svg - pics/Breeze-dark/dark_document-open.svg - pics/Breeze-dark/dark_document-print-preview.svg - pics/Breeze-dark/dark_document-print.svg - pics/Breeze-dark/dark_document-save-as.svg - pics/Breeze-dark/dark_document-save.svg - pics/Breeze-dark/dark_download.svg - pics/Breeze-dark/dark_drive-harddisk.svg - pics/Breeze-dark/dark_edit-clear.svg - pics/Breeze-dark/dark_edit-copy.svg - pics/Breeze-dark/dark_edit-cut.svg - pics/Breeze-dark/dark_edit-delete.svg - pics/Breeze-dark/dark_edit-paste.svg - pics/Breeze-dark/dark_edit-redo.svg - pics/Breeze-dark/dark_edit-undo.svg - pics/Breeze-dark/dark_folder-documents.svg - pics/Breeze-dark/dark_folder-pictures.svg - pics/Breeze-dark/dark_folder.svg - pics/Breeze-dark/dark_format-list-unordered.svg - pics/Breeze-dark/dark_go-home.svg - pics/Breeze-dark/dark_help-contents.svg - pics/Breeze-dark/dark_im-user.svg - pics/Breeze-dark/dark_kde.svg - pics/Breeze-dark/dark_layer-visible-off.svg - pics/Breeze-dark/dark_link.svg - pics/Breeze-dark/dark_list-add.svg - pics/Breeze-dark/dark_locked.svg - pics/Breeze-dark/dark_media-playback-start.svg - pics/Breeze-dark/dark_media-playback-stop.svg - pics/Breeze-dark/dark_media-record.svg - pics/Breeze-dark/dark_object-locked.svg - pics/Breeze-dark/dark_object-rotate-left.svg - pics/Breeze-dark/dark_object-rotate-right.svg - pics/Breeze-dark/dark_object-unlocked.svg - pics/Breeze-dark/dark_preferences-desktop-color.svg - pics/Breeze-dark/dark_preferences-desktop-display.svg - pics/Breeze-dark/dark_preferences-desktop-locale.svg - pics/Breeze-dark/dark_process-stop.svg - pics/Breeze-dark/dark_select-all.svg - pics/Breeze-dark/dark_select-clear.svg - pics/Breeze-dark/dark_system-help.svg - pics/Breeze-dark/dark_tools-report-bug.svg - pics/Breeze-dark/dark_tools-wizard.svg - pics/Breeze-dark/dark_unlocked.svg - pics/Breeze-dark/dark_view-choose.svg - pics/Breeze-dark/dark_view-filter.svg - pics/Breeze-dark/dark_view-fullscreen.svg - pics/Breeze-dark/dark_view-grid.svg - pics/Breeze-dark/dark_view-list-details.svg - pics/Breeze-dark/dark_view-list-text.svg - pics/Breeze-dark/dark_view-preview.svg - pics/Breeze-dark/dark_view-refresh.svg - pics/Breeze-dark/dark_window-close.svg - pics/Breeze-dark/dark_window-new.svg - pics/Breeze-dark/dark_zoom-in.svg - pics/Breeze-dark/dark_zoom-original.svg - pics/Breeze-dark/dark_zoom-out.svg - - pics/Breeze-light/light_application-exit.svg - pics/Breeze-light/light_application-pdf.svg - pics/Breeze-light/light_applications-system.svg - pics/Breeze-light/light_arrow-down.svg - pics/Breeze-light/light_arrow-left.svg - pics/Breeze-light/light_arrow-right.svg - pics/Breeze-light/light_arrow-up.svg - pics/Breeze-light/light_bookmarks.svg - pics/Breeze-light/light_configure-shortcuts.svg - pics/Breeze-light/light_configure-toolbars.svg - pics/Breeze-light/light_configure.svg - pics/Breeze-light/light_dialog-cancel.svg - pics/Breeze-light/light_dialog-close.svg - pics/Breeze-light/light_dialog-ok.svg - pics/Breeze-light/light_dialog-warning.svg - pics/Breeze-light/light_document-edit.svg - pics/Breeze-light/light_document-export.svg - pics/Breeze-light/light_document-import.svg - pics/Breeze-light/light_document-new.svg - pics/Breeze-light/light_document-open-recent.svg - pics/Breeze-light/light_document-open.svg - pics/Breeze-light/light_document-print-preview.svg - pics/Breeze-light/light_document-print.svg - pics/Breeze-light/light_document-save-as.svg - pics/Breeze-light/light_document-save.svg - pics/Breeze-light/light_download.svg - pics/Breeze-light/light_drive-harddisk.svg - pics/Breeze-light/light_edit-clear.svg - pics/Breeze-light/light_edit-copy.svg - pics/Breeze-light/light_edit-cut.svg - pics/Breeze-light/light_edit-delete.svg - pics/Breeze-light/light_edit-paste.svg - pics/Breeze-light/light_edit-redo.svg - pics/Breeze-light/light_edit-undo.svg - pics/Breeze-light/light_folder-documents.svg - pics/Breeze-light/light_folder-pictures.svg - pics/Breeze-light/light_folder.svg - pics/Breeze-light/light_format-list-unordered.svg - pics/Breeze-light/light_go-home.svg - pics/Breeze-light/light_help-contents.svg - pics/Breeze-light/light_im-user.svg - pics/Breeze-light/light_kde.svg - pics/Breeze-light/light_layer-visible-off.svg - pics/Breeze-light/light_link.svg - pics/Breeze-light/light_list-add.svg - pics/Breeze-light/light_locked.svg - pics/Breeze-light/light_media-playback-start.svg - pics/Breeze-light/light_media-playback-stop.svg - pics/Breeze-light/light_media-record.svg - pics/Breeze-light/light_object-locked.svg - pics/Breeze-light/light_object-rotate-left.svg - pics/Breeze-light/light_object-rotate-right.svg - pics/Breeze-light/light_object-unlocked.svg - pics/Breeze-light/light_preferences-desktop-color.svg - pics/Breeze-light/light_preferences-desktop-display.svg - pics/Breeze-light/light_preferences-desktop-locale.svg - pics/Breeze-light/light_process-stop.svg - pics/Breeze-light/light_select-all.svg - pics/Breeze-light/light_select-clear.svg - pics/Breeze-light/light_system-help.svg - pics/Breeze-light/light_tools-report-bug.svg - pics/Breeze-light/light_tools-wizard.svg - pics/Breeze-light/light_unlocked.svg - pics/Breeze-light/light_view-choose.svg - pics/Breeze-light/light_view-filter.svg - pics/Breeze-light/light_view-fullscreen.svg - pics/Breeze-light/light_view-grid.svg - pics/Breeze-light/light_view-list-details.svg - pics/Breeze-light/light_view-list-text.svg - pics/Breeze-light/light_view-preview.svg - pics/Breeze-light/light_view-refresh.svg - pics/Breeze-light/light_window-close.svg - pics/Breeze-light/light_window-new.svg - pics/Breeze-light/light_zoom-in.svg - pics/Breeze-light/light_zoom-original.svg - pics/Breeze-light/light_zoom-out.svg diff --git a/krita/libglobal/CMakeLists.txt b/krita/libglobal/CMakeLists.txt index 9cfb9dd514..ab60cf3490 100644 --- a/krita/libglobal/CMakeLists.txt +++ b/krita/libglobal/CMakeLists.txt @@ -1,24 +1,24 @@ include(CheckFunctionExists) check_function_exists(backtrace HAVE_BACKTRACE) configure_file(config-debug.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-debug.h) include_directories(${KOWIDGETS_INCLUDES}) set(kritaglobal_LIB_SRCS kis_assert.cpp kis_debug.cpp kis_icon_utils.cpp ) add_library(kritaglobal SHARED ${kritaglobal_LIB_SRCS} ) generate_export_header(kritaglobal BASE_NAME kritaglobal) -target_link_libraries(kritaglobal kritawidgets KF5::IconThemes Qt5::Concurrent Qt5::Core Qt5::Gui) -target_link_libraries(kritaglobal LINK_INTERFACE_LIBRARIES kritawidgets KF5::IconThemes Qt5::Concurrent Qt5::Concurrent Qt5::Core Qt5::Gui) +target_link_libraries(kritaglobal kritawidgets Qt5::Concurrent Qt5::Core Qt5::Gui) +target_link_libraries(kritaglobal LINK_INTERFACE_LIBRARIES kritawidgets Qt5::Concurrent Qt5::Concurrent Qt5::Core Qt5::Gui) set_target_properties(kritaglobal PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS kritaglobal ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/krita/libglobal/kis_icon_utils.cpp b/krita/libglobal/kis_icon_utils.cpp index 9509d1a658..f1e6f5b674 100644 --- a/krita/libglobal/kis_icon_utils.cpp +++ b/krita/libglobal/kis_icon_utils.cpp @@ -1,144 +1,111 @@ /* * Copyright (c) 2015 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_icon_utils.h" #include "kis_debug.h" +#include #include #include #include #include #include #include #include namespace KisIconUtils { QIcon loadIcon(const QString &name) { - QString realName; - - // try load themed icon - QColor background = qApp->palette().background().color(); - bool useDarkIcons = background.value() > 100; - const char * const prefix = useDarkIcons ? "dark" : "light"; - - realName = QLatin1String(prefix) + '_' + name; - - QStringList names = QStringList() << ":/pics/" + realName + ".svg" - << ":/pics/" + realName + ".png" - << ":/pics/layerbox/" + realName + ".svg" - << ":/pics/layerbox/" + realName + ".png" - << ":/pics/misc-" + QLatin1String(prefix) + '/' + realName + ".svg" - << ":/pics/misc-" + QLatin1String(prefix) + '/' + realName + ".png" - << ":/pics/tools/16/" + realName + ".svg" - << ":/pics/tools/16/" + realName + ".png" - << ":/pics/tool_transform/16/" + realName + ".svg" - << ":/pics/tool_transform/16/" + realName + ".png" - << ":/pics/Breeze-" + QLatin1String(prefix) + '/' + realName + ".svg" - << ":/pics/Breeze-" + QLatin1String(prefix) + '/' + realName + ".png" - << ":/" + name - << ":/" + name + ".png" - << ":/pics/" + name + ".svg" - << ":/pics/" + name + ".png" - ; - - foreach(const QString &resname, names) { - if (QFile(resname).exists()) { - QIcon icon(resname); - return icon; - } - } - //qDebug() << "\tfailed to retrieve icon" << name; return KoIconUtils::themedIcon(name); } bool adjustIcon(QIcon *icon) { bool result = false; QString iconName = icon->name(); if (iconName.isNull()) return result; QString realIconName = iconName; if (iconName.startsWith("dark_")) { realIconName = iconName.mid(5); } if (iconName.startsWith("light_")) { realIconName = iconName.mid(6); } if (!realIconName.isNull()) { *icon = loadIcon(realIconName); result = !icon->isNull(); } return result; } void updateIconCommon(QObject *object) { QAbstractButton* button = dynamic_cast(object); if (button) { updateIcon(button); } QComboBox* comboBox = dynamic_cast(object); if (comboBox) { updateIcon(comboBox); } QAction* action = dynamic_cast(object); if (action) { updateIcon(action); } } void updateIcon(QAbstractButton *button) { QIcon icon = button->icon(); if (adjustIcon(&icon)) { button->setIcon(icon); } } void updateIcon(QComboBox *comboBox) { for (int i = 0; i < comboBox->count(); i++) { QIcon icon = comboBox->itemIcon(i); if (adjustIcon(&icon)) { comboBox->setItemIcon(i, icon); } } } void updateIcon(QAction *action) { QIcon icon = action->icon(); if (adjustIcon(&icon)) { action->setIcon(icon); } } } diff --git a/krita/main.cc b/krita/main.cc index 313dc03ef1..00d2c06a32 100644 --- a/krita/main.cc +++ b/krita/main.cc @@ -1,160 +1,159 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2002 Patrick Julien * Copyright (c) 2015 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "data/splash/splash_screen.xpm" #include "data/splash/splash_holidays.xpm" #include "ui/KisDocument.h" #include "kis_splash_screen.h" #include "KisPart.h" #include "opengl/kis_opengl.h" #include "KisApplicationArguments.h" #if defined Q_OS_WIN #include #include #include #ifdef USE_BREAKPAD #include "kis_crash_handler.h" #endif #elif defined HAVE_X11 #include #endif extern "C" int main(int argc, char **argv) { bool runningInKDE = !qgetenv("KDE_FULL_SESSION").isEmpty(); #ifdef HAVE_X11 if (runningInKDE) { qputenv("QT_NO_GLIB", "1"); } #endif #ifdef USE_BREAKPAD qputenv("KDE_DEBUG", "1"); KisCrashHandler crashHandler; Q_UNUSED(crashHandler); #endif // Disable most debug output by default. // krita.input is kept on for tablet debugging. // You can re-enable debug output by starting Krita like "QT_LOGGING_RULES="krita*=true" krita" // See: http://doc.qt.io/qt-5/qloggingcategory.html QLoggingCategory::setFilterRules("calligra*=false\n" "krita*=false\n" "krita.input=true"); // A per-user unique string, without /, because QLocalServer cannot use names with a / in it QString key = "Krita3" + QDesktopServices::storageLocation(QDesktopServices::HomeLocation).replace("/", "_"); key = key.replace(":", "_").replace("\\","_"); #if defined HAVE_X11 // we need to call XInitThreads() (which this does) because of gmic (and possibly others) // do their own X11 stuff in their own threads // this call must happen before the creation of the application (see AA_X11InitThreads docs) QCoreApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif #if defined HAVE_OPENGL QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); #endif QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); - KLocalizedString::setApplicationDomain("krita"); // first create the application so we can create a pixmap KisApplication app(key, argc, argv); // If we should clear the config, it has to be done as soon as possible after // KisApplication has been created. Otherwise the config file may have been read // and stored in a KConfig object we have no control over. app.askClearConfig(); KisApplicationArguments args(app); if (app.isRunning()) { // only pass arguments to main instance if they are not for batch processing // any batch processing would be done in this separate instance const bool batchRun = (args.print() || args.exportAs() || args.exportAsPdf()); if (!batchRun) { QByteArray ba = args.serialize(); if (app.sendMessage(ba)) { return 0; } } } if (!runningInKDE) { // Icons in menus are ugly and distracting app.setAttribute(Qt::AA_DontShowIconsInMenus); } // then create the pixmap from an xpm: we cannot get the // location of our datadir before we've started our components, // so use an xpm. QDate currentDate = QDate::currentDate(); QWidget *splash = 0; if (currentDate > QDate(currentDate.year(), 12, 4) || currentDate < QDate(currentDate.year(), 1, 9)) { splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_holidays_xpm)); } else { splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_screen_xpm)); } app.setSplashScreen(splash); if (!app.start(args)) { return 1; } // Set up remote arguments. QObject::connect(&app, SIGNAL(messageReceived(QByteArray,QObject*)), &app, SLOT(remoteArguments(QByteArray,QObject*))); QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), &app, SLOT(fileOpenRequested(QString))); int state = app.exec(); return state; } diff --git a/krita/pics/Breeze-dark/breeze-dark-icons.qrc b/krita/pics/Breeze-dark/breeze-dark-icons.qrc new file mode 100644 index 0000000000..3f19653c79 --- /dev/null +++ b/krita/pics/Breeze-dark/breeze-dark-icons.qrc @@ -0,0 +1,82 @@ + + + + dark_application-exit.svg + dark_application-pdf.svg + dark_applications-system.svg + dark_arrow-down.svg + dark_arrow-left.svg + dark_arrow-right.svg + dark_arrow-up.svg + dark_bookmarks.svg + dark_configure-shortcuts.svg + dark_configure.svg + dark_configure-toolbars.svg + dark_dialog-cancel.svg + dark_dialog-close.svg + dark_dialog-ok.svg + dark_dialog-warning.svg + dark_document-edit.svg + dark_document-export.svg + dark_document-import.svg + dark_document-new.svg + dark_document-open-recent.svg + dark_document-open.svg + dark_document-print-preview.svg + dark_document-print.svg + dark_document-save-as.svg + dark_document-save.svg + dark_download.svg + dark_drive-harddisk.svg + dark_edit-clear.svg + dark_edit-copy.svg + dark_edit-cut.svg + dark_edit-delete.svg + dark_edit-paste.svg + dark_edit-redo.svg + dark_edit-undo.svg + dark_folder-documents.svg + dark_folder-pictures.svg + dark_folder.svg + dark_format-list-unordered.svg + dark_go-home.svg + dark_help-contents.svg + dark_im-user.svg + dark_kde.svg + dark_layer-visible-off.svg + dark_link.svg + dark_list-add.svg + dark_locked.svg + dark_media-playback-start.svg + dark_media-playback-stop.svg + dark_media-record.svg + dark_object-locked.svg + dark_object-rotate-left.svg + dark_object-rotate-right.svg + dark_object-unlocked.svg + dark_preferences-desktop-color.svg + dark_preferences-desktop-display.svg + dark_preferences-desktop-locale.svg + dark_process-stop.svg + dark_select-all.svg + dark_select-clear.svg + dark_system-help.svg + dark_tools-report-bug.svg + dark_tools-wizard.svg + dark_unlocked.svg + dark_view-choose.svg + dark_view-filter.svg + dark_view-fullscreen.svg + dark_view-grid.svg + dark_view-list-details.svg + dark_view-list-text.svg + dark_view-preview.svg + dark_view-refresh.svg + dark_window-close.svg + dark_window-new.svg + dark_zoom-in.svg + dark_zoom-original.svg + dark_zoom-out.svg + + + diff --git a/krita/pics/Breeze-light/breeze-light-icons.qrc b/krita/pics/Breeze-light/breeze-light-icons.qrc new file mode 100644 index 0000000000..a05cd5fa4b --- /dev/null +++ b/krita/pics/Breeze-light/breeze-light-icons.qrc @@ -0,0 +1,82 @@ + + + + light_application-exit.svg + light_application-pdf.svg + light_applications-system.svg + light_arrow-down.svg + light_arrow-left.svg + light_arrow-right.svg + light_arrow-up.svg + light_bookmarks.svg + light_configure-shortcuts.svg + light_configure.svg + light_configure-toolbars.svg + light_dialog-cancel.svg + light_dialog-close.svg + light_dialog-ok.svg + light_dialog-warning.svg + light_document-edit.svg + light_document-export.svg + light_document-import.svg + light_document-new.svg + light_document-open-recent.svg + light_document-open.svg + light_document-print-preview.svg + light_document-print.svg + light_document-save-as.svg + light_document-save.svg + light_download.svg + light_drive-harddisk.svg + light_edit-clear.svg + light_edit-copy.svg + light_edit-cut.svg + light_edit-delete.svg + light_edit-paste.svg + light_edit-redo.svg + light_edit-undo.svg + light_folder-documents.svg + light_folder-pictures.svg + light_folder.svg + light_format-list-unordered.svg + light_go-home.svg + light_help-contents.svg + light_im-user.svg + light_kde.svg + light_layer-visible-off.svg + light_link.svg + light_list-add.svg + light_locked.svg + light_media-playback-start.svg + light_media-playback-stop.svg + light_media-record.svg + light_object-locked.svg + light_object-rotate-left.svg + light_object-rotate-right.svg + light_object-unlocked.svg + light_preferences-desktop-color.svg + light_preferences-desktop-display.svg + light_preferences-desktop-locale.svg + light_process-stop.svg + light_select-all.svg + light_select-clear.svg + light_system-help.svg + light_tools-report-bug.svg + light_tools-wizard.svg + light_unlocked.svg + light_view-choose.svg + light_view-filter.svg + light_view-fullscreen.svg + light_view-grid.svg + light_view-list-details.svg + light_view-list-text.svg + light_view-preview.svg + light_view-refresh.svg + light_window-close.svg + light_window-new.svg + light_zoom-in.svg + light_zoom-original.svg + light_zoom-out.svg + + + diff --git a/krita/pics/CMakeLists.txt b/krita/pics/CMakeLists.txt deleted file mode 100644 index 12975112ea..0000000000 --- a/krita/pics/CMakeLists.txt +++ /dev/null @@ -1,410 +0,0 @@ -install(FILES -broken-preset.png -delete.png -height_icon.png -height.png -hi16-add_dialog.png -hi16-palette_library.png -icon-kritasketch-256.png -landscape.png -linked.png -local_selection_active.png -local_selection_inactive.png -offset_horizontal.png -offset_vertical.png -portrait.png -ratio_icon.png -selection_add.png -selection_exclude.png -selection_intersect.png -selection_replace.png -selection_subtract.png -select_pixel.png -select_shape.png -shade.png -shear_horizontal.png -shear_vertical.png -sidebaricon.png -tablet.png -tool_screenshot.png -transparency-locked.png -transparency-unlocked.png -layer-style-enabled.png -layer-style-disabled.png -unlinked.png -width_icon.png -width.png -workspace-chooser.png -onionA.png -onionB.png -onionOn.png -onionOff.png - -dark_prevframe.png -dark_nextframe.png -dark_playpause.png -dark_addblankframe.png -dark_addduplicateframe.png -dark_deletekeyframe.png -dark_timeline_keyframe.png -dark_onion_skin_options.png - -light_prevframe.png -light_nextframe.png -light_playpause.png -light_addblankframe.png -light_addduplicateframe.png -light_deletekeyframe.png -light_timeline_keyframe.png -light_onion_skin_options.png - -mirrorAxis-HorizontalMove.png -mirrorAxis-VerticalMove.png -visible.svg -novisible.svg -dirty-preset.svg - -dark_selection-mode_ants.png -dark_selection-mode_invisible.png -dark_selection-mode_mask.png -dark_trim-to-image.png -dark_layer-locked.png -dark_layer-unlocked.png -dark_transparency-enabled.png -dark_transparency-disabled.png -dark_novisible.svg -dark_visible.svg -dark_passthrough-enabled.png -dark_passthrough-disabled.png - -light_transparency-enabled.png -light_transparency-disabled.png -light_layer-locked.png -light_layer-unlocked.png -light_selection-mode_ants.png -light_selection-mode_invisible.png -light_selection-mode_mask.png -light_trim-to-image.png -light_novisible.svg -light_visible.svg -light_passthrough-enabled.png -light_passthrough-disabled.png - -layerbox/dark_addlayer.png -layerbox/dark_addtofolder.png -layerbox/dark_arrowdown.png -layerbox/dark_arrowupblr.png -layerbox/dark_deletelayer.png -layerbox/dark_duplicatelayer.png -layerbox/dark_properties.png -layerbox/dark_removefromfolder.png -layerbox/light_addlayer.png -layerbox/light_addtofolder.png -layerbox/light_arrowdown.png -layerbox/light_arrowupblr.png -layerbox/light_deletelayer.png -layerbox/light_duplicatelayer.png -layerbox/light_properties.png -layerbox/light_removefromfolder.png - -misc-light/light_draw-eraser.svg -misc-light/light_ox16-action-object-align-horizontal-center-calligra.svg -misc-light/light_ox16-action-object-align-horizontal-left-calligra.svg -misc-light/light_ox16-action-object-align-horizontal-right-calligra.svg -misc-light/light_ox16-action-object-align-vertical-bottom-calligra.svg -misc-light/light_ox16-action-object-align-vertical-center-calligra.svg -misc-light/light_ox16-action-object-align-vertical-top-calligra.svg -misc-light/light_ox16-action-object-group-calligra.svg -misc-light/light_ox16-action-object-order-back-calligra.svg -misc-light/light_ox16-action-object-order-front-calligra.svg -misc-light/light_ox16-action-object-order-lower-calligra.svg -misc-light/light_ox16-action-object-order-raise-calligra.svg -misc-light/light_ox16-action-object-ungroup-calligra.svg -misc-light/light_paintop_settings_01.svg -misc-light/light_paintop_settings_02.svg -misc-light/light_stroke-cap-butt.svg -misc-light/light_stroke-cap-round.svg -misc-light/light_stroke-cap-square.svg -misc-light/light_stroke-join-bevel.svg -misc-light/light_stroke-join-miter.svg -misc-light/light_stroke-join-round.svg -misc-light/light_symmetry-horizontal.svg -misc-light/light_symmetry-vertical.svg - -misc-dark/dark_draw-eraser.svg -misc-dark/dark_ox16-action-object-align-horizontal-center-calligra.svg -misc-dark/dark_ox16-action-object-align-horizontal-left-calligra.svg -misc-dark/dark_ox16-action-object-align-horizontal-right-calligra.svg -misc-dark/dark_ox16-action-object-align-vertical-bottom-calligra.svg -misc-dark/dark_ox16-action-object-align-vertical-center-calligra.svg -misc-dark/dark_ox16-action-object-align-vertical-top-calligra.svg -misc-dark/dark_ox16-action-object-group-calligra.svg -misc-dark/dark_ox16-action-object-order-back-calligra.svg -misc-dark/dark_ox16-action-object-order-front-calligra.svg -misc-dark/dark_ox16-action-object-order-lower-calligra.svg -misc-dark/dark_ox16-action-object-order-raise-calligra.svg -misc-dark/dark_ox16-action-object-ungroup-calligra.svg -misc-dark/dark_paintop_settings_01.svg -misc-dark/dark_paintop_settings_02.svg -misc-dark/dark_stroke-cap-butt.svg -misc-dark/dark_stroke-cap-round.svg -misc-dark/dark_stroke-cap-square.svg -misc-dark/dark_stroke-join-bevel.svg -misc-dark/dark_stroke-join-miter.svg -misc-dark/dark_stroke-join-round.svg -misc-dark/dark_symmetry-horizontal.svg -misc-dark/dark_symmetry-vertical.svg - -tools/16/dark_calligraphy.png -tools/16/dark_draw-text.png -tools/16/dark_format-fill-color.png -tools/16/dark_krita_draw_path.png -tools/16/dark_krita_tool_color_fill.png -tools/16/dark_krita_tool_color_picker.png -tools/16/dark_krita_tool_dyna.png -tools/16/dark_krita_tool_ellipse.png -tools/16/dark_krita_tool_freehand.png -tools/16/dark_krita_tool_freehandvector.png -tools/16/dark_krita_tool_gradient.png -tools/16/dark_krita_tool_grid.png -tools/16/dark_krita_tool_line.png -tools/16/dark_krita_tool_measure.png -tools/16/dark_krita_tool_move.png -tools/16/dark_krita_tool_multihand.png -tools/16/dark_krita_tool_polygon.png -tools/16/dark_krita_tool_rectangle.png -tools/16/dark_krita_tool_ruler_assistant.png -tools/16/dark_krita_tool_transform.png -tools/16/dark_pattern.png -tools/16/dark_polyline.png -tools/16/dark_select.png -tools/16/dark_tool_contiguous_selection.png -tools/16/dark_tool_crop.png -tools/16/dark_tool_elliptical_selection.png -tools/16/dark_tool_outline_selection.png -tools/16/dark_tool_path_selection.png -tools/16/dark_tool_perspectivegrid.png -tools/16/dark_tool_polygonal_selection.png -tools/16/dark_tool_rect_selection.png -tools/16/dark_tool_similar_selection.png -tools/16/light_calligraphy.png -tools/16/light_draw-text.png -tools/16/light_format-fill-color.png -tools/16/light_krita_draw_path.png -tools/16/light_krita_tool_color_fill.png -tools/16/light_krita_tool_color_picker.png -tools/16/light_krita_tool_dyna.png -tools/16/light_krita_tool_ellipse.png -tools/16/light_krita_tool_freehand.png -tools/16/light_krita_tool_freehandvector.png -tools/16/light_krita_tool_gradient.png -tools/16/light_krita_tool_grid.png -tools/16/light_krita_tool_line.png -tools/16/light_krita_tool_measure.png -tools/16/light_krita_tool_move.png -tools/16/light_krita_tool_multihand.png -tools/16/light_krita_tool_polygon.png -tools/16/light_krita_tool_rectangle.png -tools/16/light_krita_tool_ruler_assistant.png -tools/16/light_krita_tool_transform.png -tools/16/light_pattern.png -tools/16/light_polyline.png -tools/16/light_select.png -tools/16/light_tool_contiguous_selection.png -tools/16/light_tool_crop.png -tools/16/light_tool_elliptical_selection.png -tools/16/light_tool_outline_selection.png -tools/16/light_tool_path_selection.png -tools/16/light_tool_perspectivegrid.png -tools/16/light_tool_polygon.png -tools/16/light_tool_polygonal_selection.png -tools/16/light_tool_rect_selection.png -tools/16/light_tool_similar_selection.png - -tool_transform/dark_transform_icons_cage.png -tool_transform/dark_transform_icons_liquify_erase.png -tool_transform/dark_transform_icons_liquify_main.png -tool_transform/dark_transform_icons_liquify_move.png -tool_transform/dark_transform_icons_liquify_offset.png -tool_transform/dark_transform_icons_liquify_resize.png -tool_transform/dark_transform_icons_liquify_rotate.png -tool_transform/dark_transform_icons_liquify_rotateCCW.png -tool_transform/dark_transform_icons_main.png -tool_transform/dark_transform_icons_perspective.png -tool_transform/dark_transform_icons_warp.png -tool_transform/dark_transform_icons_penPressure.png -tool_transform/dark_krita_tool_transform_recursive.png - -tool_transform/light_transform_icons_cage.png -tool_transform/light_transform_icons_liquify_erase.png -tool_transform/light_transform_icons_liquify_main.png -tool_transform/light_transform_icons_liquify_move.png -tool_transform/light_transform_icons_liquify_offset.png -tool_transform/light_transform_icons_liquify_resize.png -tool_transform/light_transform_icons_liquify_rotate.png -tool_transform/light_transform_icons_liquify_rotateCCW.png -tool_transform/light_transform_icons_main.png -tool_transform/light_transform_icons_perspective.png -tool_transform/light_transform_icons_warp.png -tool_transform/light_transform_icons_penPressure.png -tool_transform/light_krita_tool_transform_recursive.png - -Breeze-dark/dark_application-exit.svg -Breeze-dark/dark_application-pdf.svg -Breeze-dark/dark_applications-system.svg -Breeze-dark/dark_arrow-down.svg -Breeze-dark/dark_arrow-left.svg -Breeze-dark/dark_arrow-right.svg -Breeze-dark/dark_arrow-up.svg -Breeze-dark/dark_bookmarks.svg -Breeze-dark/dark_configure-shortcuts.svg -Breeze-dark/dark_configure-toolbars.svg -Breeze-dark/dark_configure.svg -Breeze-dark/dark_dialog-cancel.svg -Breeze-dark/dark_dialog-close.svg -Breeze-dark/dark_dialog-ok.svg -Breeze-dark/dark_dialog-warning.svg -Breeze-dark/dark_document-edit.svg -Breeze-dark/dark_document-export.svg -Breeze-dark/dark_document-import.svg -Breeze-dark/dark_document-new.svg -Breeze-dark/dark_document-open-recent.svg -Breeze-dark/dark_document-open.svg -Breeze-dark/dark_document-print-preview.svg -Breeze-dark/dark_document-print.svg -Breeze-dark/dark_document-save-as.svg -Breeze-dark/dark_document-save.svg -Breeze-dark/dark_download.svg -Breeze-dark/dark_drive-harddisk.svg -Breeze-dark/dark_edit-clear.svg -Breeze-dark/dark_edit-copy.svg -Breeze-dark/dark_edit-cut.svg -Breeze-dark/dark_edit-delete.svg -Breeze-dark/dark_edit-paste.svg -Breeze-dark/dark_edit-redo.svg -Breeze-dark/dark_edit-undo.svg -Breeze-dark/dark_folder-documents.svg -Breeze-dark/dark_folder-pictures.svg -Breeze-dark/dark_folder.svg -Breeze-dark/dark_format-list-unordered.svg -Breeze-dark/dark_go-home.svg -Breeze-dark/dark_help-contents.svg -Breeze-dark/dark_im-user.svg -Breeze-dark/dark_kde.svg -Breeze-dark/dark_layer-visible-off.svg -Breeze-dark/dark_link.svg -Breeze-dark/dark_list-add.svg -Breeze-dark/dark_locked.svg -Breeze-dark/dark_media-playback-start.svg -Breeze-dark/dark_media-playback-stop.svg -Breeze-dark/dark_media-record.svg -Breeze-dark/dark_object-locked.svg -Breeze-dark/dark_object-rotate-left.svg -Breeze-dark/dark_object-rotate-right.svg -Breeze-dark/dark_object-unlocked.svg -Breeze-dark/dark_preferences-desktop-color.svg -Breeze-dark/dark_preferences-desktop-display.svg -Breeze-dark/dark_preferences-desktop-locale.svg -Breeze-dark/dark_process-stop.svg -Breeze-dark/dark_select-all.svg -Breeze-dark/dark_select-clear.svg -Breeze-dark/dark_system-help.svg -Breeze-dark/dark_tools-report-bug.svg -Breeze-dark/dark_tools-wizard.svg -Breeze-dark/dark_unlocked.svg -Breeze-dark/dark_view-choose.svg -Breeze-dark/dark_view-filter.svg -Breeze-dark/dark_view-fullscreen.svg -Breeze-dark/dark_view-grid.svg -Breeze-dark/dark_view-list-details.svg -Breeze-dark/dark_view-list-text.svg -Breeze-dark/dark_view-preview.svg -Breeze-dark/dark_view-refresh.svg -Breeze-dark/dark_window-close.svg -Breeze-dark/dark_window-new.svg -Breeze-dark/dark_zoom-in.svg -Breeze-dark/dark_zoom-original.svg -Breeze-dark/dark_zoom-out.svg - -Breeze-light/light_application-exit.svg -Breeze-light/light_application-pdf.svg -Breeze-light/light_applications-system.svg -Breeze-light/light_arrow-down.svg -Breeze-light/light_arrow-left.svg -Breeze-light/light_arrow-right.svg -Breeze-light/light_arrow-up.svg -Breeze-light/light_bookmarks.svg -Breeze-light/light_configure-shortcuts.svg -Breeze-light/light_configure-toolbars.svg -Breeze-light/light_configure.svg -Breeze-light/light_dialog-cancel.svg -Breeze-light/light_dialog-close.svg -Breeze-light/light_dialog-ok.svg -Breeze-light/light_dialog-warning.svg -Breeze-light/light_document-edit.svg -Breeze-light/light_document-export.svg -Breeze-light/light_document-import.svg -Breeze-light/light_document-new.svg -Breeze-light/light_document-open-recent.svg -Breeze-light/light_document-open.svg -Breeze-light/light_document-print-preview.svg -Breeze-light/light_document-print.svg -Breeze-light/light_document-save-as.svg -Breeze-light/light_document-save.svg -Breeze-light/light_download.svg -Breeze-light/light_drive-harddisk.svg -Breeze-light/light_edit-clear.svg -Breeze-light/light_edit-copy.svg -Breeze-light/light_edit-cut.svg -Breeze-light/light_edit-delete.svg -Breeze-light/light_edit-paste.svg -Breeze-light/light_edit-redo.svg -Breeze-light/light_edit-undo.svg -Breeze-light/light_folder-documents.svg -Breeze-light/light_folder-pictures.svg -Breeze-light/light_folder.svg -Breeze-light/light_format-list-unordered.svg -Breeze-light/light_go-home.svg -Breeze-light/light_help-contents.svg -Breeze-light/light_im-user.svg -Breeze-light/light_kde.svg -Breeze-light/light_layer-visible-off.svg -Breeze-light/light_link.svg -Breeze-light/light_list-add.svg -Breeze-light/light_locked.svg -Breeze-light/light_media-playback-start.svg -Breeze-light/light_media-playback-stop.svg -Breeze-light/light_media-record.svg -Breeze-light/light_object-locked.svg -Breeze-light/light_object-rotate-left.svg -Breeze-light/light_object-rotate-right.svg -Breeze-light/light_object-unlocked.svg -Breeze-light/light_preferences-desktop-color.svg -Breeze-light/light_preferences-desktop-display.svg -Breeze-light/light_preferences-desktop-locale.svg -Breeze-light/light_process-stop.svg -Breeze-light/light_select-all.svg -Breeze-light/light_select-clear.svg -Breeze-light/light_system-help.svg -Breeze-light/light_tools-report-bug.svg -Breeze-light/light_tools-wizard.svg -Breeze-light/light_unlocked.svg -Breeze-light/light_view-choose.svg -Breeze-light/light_view-filter.svg -Breeze-light/light_view-fullscreen.svg -Breeze-light/light_view-grid.svg -Breeze-light/light_view-list-details.svg -Breeze-light/light_view-list-text.svg -Breeze-light/light_view-preview.svg -Breeze-light/light_view-refresh.svg -Breeze-light/light_window-close.svg -Breeze-light/light_window-new.svg -Breeze-light/light_zoom-in.svg -Breeze-light/light_zoom-original.svg -Breeze-light/light_zoom-out.svg - -DESTINATION ${DATA_INSTALL_DIR}/krita/pics) - -add_subdirectory(app) - - diff --git a/krita/pics/app/hi1024-apps-calligrakrita.png b/krita/pics/app/1024-apps-calligrakrita.png similarity index 100% rename from krita/pics/app/hi1024-apps-calligrakrita.png rename to krita/pics/app/1024-apps-calligrakrita.png diff --git a/krita/pics/app/hi128-apps-calligrakrita.png b/krita/pics/app/128-apps-calligrakrita.png similarity index 100% rename from krita/pics/app/hi128-apps-calligrakrita.png rename to krita/pics/app/128-apps-calligrakrita.png diff --git a/krita/pics/app/hi16-apps-calligrakrita.png b/krita/pics/app/16-apps-calligrakrita.png similarity index 100% rename from krita/pics/app/hi16-apps-calligrakrita.png rename to krita/pics/app/16-apps-calligrakrita.png diff --git a/krita/pics/app/hi22-apps-calligrakrita.png b/krita/pics/app/22-apps-calligrakrita.png similarity index 100% rename from krita/pics/app/hi22-apps-calligrakrita.png rename to krita/pics/app/22-apps-calligrakrita.png diff --git a/krita/pics/app/hi256-apps-calligrakrita.png b/krita/pics/app/256-apps-calligrakrita.png similarity index 100% rename from krita/pics/app/hi256-apps-calligrakrita.png rename to krita/pics/app/256-apps-calligrakrita.png diff --git a/krita/pics/app/hi32-apps-calligrakrita.png b/krita/pics/app/32-apps-calligrakrita.png similarity index 100% rename from krita/pics/app/hi32-apps-calligrakrita.png rename to krita/pics/app/32-apps-calligrakrita.png diff --git a/krita/pics/app/hi48-apps-calligrakrita.png b/krita/pics/app/48-apps-calligrakrita.png similarity index 100% rename from krita/pics/app/hi48-apps-calligrakrita.png rename to krita/pics/app/48-apps-calligrakrita.png diff --git a/krita/pics/app/hi512-apps-calligrakrita.png b/krita/pics/app/512-apps-calligrakrita.png similarity index 100% rename from krita/pics/app/hi512-apps-calligrakrita.png rename to krita/pics/app/512-apps-calligrakrita.png diff --git a/krita/pics/app/hi64-apps-calligrakrita.png b/krita/pics/app/64-apps-calligrakrita.png similarity index 100% rename from krita/pics/app/hi64-apps-calligrakrita.png rename to krita/pics/app/64-apps-calligrakrita.png diff --git a/krita/pics/app/CMakeLists.txt b/krita/pics/app/CMakeLists.txt index 832a8e552a..7d0de0086e 100644 --- a/krita/pics/app/CMakeLists.txt +++ b/krita/pics/app/CMakeLists.txt @@ -1 +1,14 @@ -ecm_install_icons( ${ICON_INSTALL_DIR} ) +ecm_install_icons( +ICONS +1024-apps-calligrakrita.png +128-apps-calligrakrita.png +16-apps-calligrakrita.png +22-apps-calligrakrita.png +256-apps-calligrakrita.png +32-apps-calligrakrita.png +48-apps-calligrakrita.png +512-apps-calligrakrita.png +64-apps-calligrakrita.png +sc-apps-calligrakrita.svgz +DESTINATION + ${ICON_INSTALL_DIR} ) diff --git a/krita/pics/app/a b/krita/pics/app/a new file mode 100644 index 0000000000..b96c500861 --- /dev/null +++ b/krita/pics/app/a @@ -0,0 +1,10 @@ +git mv hi1024-apps-calligrakrita.png 1024-apps-calligrakrita.png +git mv hi128-apps-calligrakrita.png 128-apps-calligrakrita.png +git mv hi16-apps-calligrakrita.png 16-apps-calligrakrita.png +git mv hi22-apps-calligrakrita.png 22-apps-calligrakrita.png +git mv hi256-apps-calligrakrita.png 256-apps-calligrakrita.png +git mv hi32-apps-calligrakrita.png 32-apps-calligrakrita.png +git mv hi48-apps-calligrakrita.png 48-apps-calligrakrita.png +git mv hi512-apps-calligrakrita.png 512-apps-calligrakrita.png +git mv hi64-apps-calligrakrita.png 64-apps-calligrakrita.png +git mv hisc-apps-calligrakrita.svgz sc-apps-calligrakrita.svgz diff --git a/krita/pics/app/hisc-apps-calligrakrita.svgz b/krita/pics/app/sc-apps-calligrakrita.svgz similarity index 100% rename from krita/pics/app/hisc-apps-calligrakrita.svgz rename to krita/pics/app/sc-apps-calligrakrita.svgz diff --git a/krita/pics/layerbox/layerbox-icons.qrc b/krita/pics/layerbox/layerbox-icons.qrc new file mode 100644 index 0000000000..b8519d019b --- /dev/null +++ b/krita/pics/layerbox/layerbox-icons.qrc @@ -0,0 +1,21 @@ + + + + dark_addlayer.png + dark_addtofolder.png + dark_arrowdown.png + dark_arrowupblr.png + dark_deletelayer.png + dark_duplicatelayer.png + dark_properties.png + dark_removefromfolder.png + light_addlayer.png + light_addtofolder.png + light_arrowdown.png + light_arrowupblr.png + light_deletelayer.png + light_duplicatelayer.png + light_properties.png + light_removefromfolder.png + + diff --git a/krita/pics/layerbox/svg/layerbox-svg-icons.qrc b/krita/pics/layerbox/svg/layerbox-svg-icons.qrc new file mode 100644 index 0000000000..0be0857b9e --- /dev/null +++ b/krita/pics/layerbox/svg/layerbox-svg-icons.qrc @@ -0,0 +1,21 @@ + + + + dark_addlayer.svg + dark_addtofolder.svg + dark_arrowdown.svg + dark_arrowupblr.svg + dark_deletelayer.svg + dark_duplicatelayer.svg + dark_properties.svg + dark_removefromfolder.svg + light_addlayer.svg + light_addtofolder.svg + light_arrowdown.svg + light_arrowupblr.svg + light_deletelayer.svg + light_duplicatelayer.svg + light_properties.svg + light_removefromfolder.svg + + diff --git a/krita/pics/misc-dark/misc-dark-icons.qrc b/krita/pics/misc-dark/misc-dark-icons.qrc new file mode 100644 index 0000000000..e5a30e36da --- /dev/null +++ b/krita/pics/misc-dark/misc-dark-icons.qrc @@ -0,0 +1,28 @@ + + + + dark_draw-eraser.svg + dark_ox16-action-object-align-horizontal-center-calligra.svg + dark_ox16-action-object-align-horizontal-left-calligra.svg + dark_ox16-action-object-align-horizontal-right-calligra.svg + dark_ox16-action-object-align-vertical-bottom-calligra.svg + dark_ox16-action-object-align-vertical-center-calligra.svg + dark_ox16-action-object-align-vertical-top-calligra.svg + dark_ox16-action-object-group-calligra.svg + dark_ox16-action-object-order-back-calligra.svg + dark_ox16-action-object-order-front-calligra.svg + dark_ox16-action-object-order-lower-calligra.svg + dark_ox16-action-object-order-raise-calligra.svg + dark_ox16-action-object-ungroup-calligra.svg + dark_paintop_settings_01.svg + dark_paintop_settings_02.svg + dark_stroke-cap-butt.svg + dark_stroke-cap-round.svg + dark_stroke-cap-square.svg + dark_stroke-join-bevel.svg + dark_stroke-join-miter.svg + dark_stroke-join-round.svg + dark_symmetry-horizontal.svg + dark_symmetry-vertical.svg + + diff --git a/krita/pics/misc-light/misc-light-icons.qrc b/krita/pics/misc-light/misc-light-icons.qrc new file mode 100644 index 0000000000..25843fb17c --- /dev/null +++ b/krita/pics/misc-light/misc-light-icons.qrc @@ -0,0 +1,29 @@ + + + + light_draw-eraser.svg + light_ox16-action-object-align-horizontal-center-calligra.svg + light_ox16-action-object-align-horizontal-left-calligra.svg + light_ox16-action-object-align-horizontal-right-calligra.svg + light_ox16-action-object-align-vertical-bottom-calligra.svg + light_ox16-action-object-align-vertical-center-calligra.svg + light_ox16-action-object-align-vertical-top-calligra.svg + light_ox16-action-object-group-calligra.svg + light_ox16-action-object-order-back-calligra.svg + light_ox16-action-object-order-front-calligra.svg + light_ox16-action-object-order-lower-calligra.svg + light_ox16-action-object-order-raise-calligra.svg + light_ox16-action-object-ungroup-calligra.svg + light_paintop_settings_01.svg + light_paintop_settings_02.svg + light_stroke-cap-butt.svg + light_stroke-cap-round.svg + light_stroke-cap-square.svg + light_stroke-join-bevel.svg + light_stroke-join-miter.svg + light_stroke-join-round.svg + light_symmetry-horizontal.svg + light_symmetry-vertical.svg + + + diff --git a/krita/pics/svg/svg-icons.qrc b/krita/pics/svg/svg-icons.qrc new file mode 100644 index 0000000000..d50e023dc7 --- /dev/null +++ b/krita/pics/svg/svg-icons.qrc @@ -0,0 +1,64 @@ + + + + broken-preset.svgz + dark_addblankframe.svg + dark_addcolor.svg + dark_addduplicateframe.svg + dark_deletekeyframe.svg + dark_docker_lock_a.svg + dark_docker_lock_b.svg + dark_layer-locked.svg + dark_layer-unlocked.svg + dark_nextframe.svg + dark_onion_skin_options.svg + dark_pallete_librarysvg.svg + dark_passthrough-disabled.svg + dark_passthrough-enabled.svg + dark_playpause.svg + dark_prevframe.svg + dark_selection-mode_ants.svg + dark_selection-mode_invisible.svg + dark_selection-mode_mask.svg + dark_transparency-disabled.svg + dark_transparency-enabled.svg + dark_trim-to-image.svg + delete.svgz + layer-style-disabled.svg + layer-style-enabled.svg + light_addblankframe.svg + light_addcolor.svg + light_addduplicateframe.svg + light_deletekeyframe.svg + light_docker_lock_a.svg + light_docker_lock_b.svg + light_layer-locked.svg + light_layer-unlocked.svg + light_nextframe.svg + light_onion_skin_options.svg + light_pallete_library.svg + light_passthrough-disabled.svgz + light_passthrough-enabled.svgz + light_playpause.svg + light_prevframe.svg + light_selection-mode_ants.svg + light_selection-mode_invisible.svg + light_selection-mode_mask.svg + light_timeline_keyframe.svg + light_transparency-disabled.svg + light_transparency-enabled.svg + light_trim-to-image.svg + onionA.svg + onionB.svg + onionOff.svg + onionOn.svg + paintop_presets_disabled.svgz + paintop_settings_01.svgz + selection-info.svg + selection-mode_invisible.svg + svg-icons.qrc + transparency-locked.svg + transparency-unlocked.svg + workspace-chooser.svg + + diff --git a/krita/pics/tool_transform/tool-transform-icons.qrc b/krita/pics/tool_transform/tool-transform-icons.qrc new file mode 100644 index 0000000000..8e320d7164 --- /dev/null +++ b/krita/pics/tool_transform/tool-transform-icons.qrc @@ -0,0 +1,33 @@ + + + + dark_transform_icons_cage.png + dark_transform_icons_liquify_erase.png + dark_transform_icons_liquify_main.png + dark_transform_icons_liquify_move.png + dark_transform_icons_liquify_offset.png + dark_transform_icons_liquify_resize.png + dark_transform_icons_liquify_rotate.png + dark_transform_icons_liquify_rotateCCW.png + dark_transform_icons_main.png + dark_transform_icons_perspective.png + dark_transform_icons_warp.png + dark_transform_icons_penPressure.png + dark_krita_tool_transform_recursive.png + + light_transform_icons_cage.png + light_transform_icons_liquify_erase.png + light_transform_icons_liquify_main.png + light_transform_icons_liquify_move.png + light_transform_icons_liquify_offset.png + light_transform_icons_liquify_resize.png + light_transform_icons_liquify_rotate.png + light_transform_icons_liquify_rotateCCW.png + light_transform_icons_main.png + light_transform_icons_perspective.png + light_transform_icons_warp.png + light_transform_icons_penPressure.png + light_krita_tool_transform_recursive.png + + + diff --git a/krita/pics/tools/16/tools-16-icons.qrc b/krita/pics/tools/16/tools-16-icons.qrc new file mode 100644 index 0000000000..519184b248 --- /dev/null +++ b/krita/pics/tools/16/tools-16-icons.qrc @@ -0,0 +1,73 @@ + + + + + dark_calligraphy.png + dark_draw-text.png + dark_format-fill-color.png + dark_krita_draw_path.png + dark_krita_tool_color_fill.png + dark_krita_tool_color_picker.png + dark_krita_tool_dyna.png + dark_krita_tool_ellipse.png + dark_krita_tool_freehand.png + dark_krita_tool_freehandvector.png + dark_krita_tool_gradient.png + dark_krita_tool_grid.png + dark_krita_tool_line.png + dark_krita_tool_measure.png + dark_krita_tool_move.png + dark_krita_tool_multihand.png + dark_krita_tool_polygon.png + dark_krita_tool_rectangle.png + dark_krita_tool_ruler_assistant.png + dark_krita_tool_transform.png + dark_pattern.png + dark_polyline.png + dark_select.png + dark_tool_contiguous_selection.png + dark_tool_crop.png + dark_tool_elliptical_selection.png + dark_tool_outline_selection.png + dark_tool_path_selection.png + dark_tool_perspectivegrid.png + dark_tool_polygonal_selection.png + dark_tool_rect_selection.png + dark_tool_similar_selection.png + + light_calligraphy.png + light_draw-text.png + light_format-fill-color.png + light_krita_draw_path.png + light_krita_tool_color_fill.png + light_krita_tool_color_picker.png + light_krita_tool_dyna.png + light_krita_tool_ellipse.png + light_krita_tool_freehand.png + light_krita_tool_freehandvector.png + light_krita_tool_gradient.png + light_krita_tool_grid.png + light_krita_tool_line.png + light_krita_tool_measure.png + light_krita_tool_move.png + light_krita_tool_multihand.png + light_krita_tool_polygon.png + light_krita_tool_rectangle.png + light_krita_tool_ruler_assistant.png + light_krita_tool_transform.png + light_pattern.png + light_polyline.png + light_select.png + light_tool_contiguous_selection.png + light_tool_crop.png + light_tool_elliptical_selection.png + light_tool_outline_selection.png + light_tool_path_selection.png + light_tool_perspectivegrid.png + light_tool_polygon.png + light_tool_polygonal_selection.png + light_tool_rect_selection.png + light_tool_similar_selection.png + + + diff --git a/krita/pics/tools/SVG/16/tools-svg-16-icons.qrc b/krita/pics/tools/SVG/16/tools-svg-16-icons.qrc new file mode 100644 index 0000000000..d6ee79b765 --- /dev/null +++ b/krita/pics/tools/SVG/16/tools-svg-16-icons.qrc @@ -0,0 +1,69 @@ + + + + dark_calligraphy.svg + dark_draw-text.svg + dark_format-fill-color.svg + dark_krita_draw_path.svg + dark_krita_tool_color_fill.svg + dark_krita_tool_color_picker.svg + dark_krita_tool_dyna.svg + dark_krita_tool_ellipse.svg + dark_krita_tool_freehand.svg + dark_krita_tool_freehandvector.svg + dark_krita_tool_gradient.svg + dark_krita_tool_grid.svg + dark_krita_tool_line.svg + dark_krita_tool_measure.svg + dark_krita_tool_move.svg + dark_krita_tool_multihand.svg + dark_krita_tool_polygon.svg + dark_krita_tool_rectangle.svg + dark_krita_tool_ruler_assistant.svg + dark_krita_tool_transform.svg + dark_pattern.svg + dark_polyline.svg + dark_select.svg + dark_tool_contiguous_selection.svg + dark_tool_crop.svg + dark_tool_elliptical_selection.svg + dark_tool_outline_selection.svg + dark_tool_path_selection.svg + dark_tool_perspectivegrid.svg + dark_tool_polygonal_selection.svg + dark_tool_rect_selection.svg + dark_tool_similar_selection.svg + light_calligraphy.svg + light_draw-text.svg + light_format-fill-color.svg + light_krita_draw_path.svg + light_krita_tool_color_fill.svg + light_krita_tool_color_picker.svg + light_krita_tool_dyna.svg + light_krita_tool_ellipse.svg + light_krita_tool_freehand.svg + light_krita_tool_freehandvector.svg + light_krita_tool_gradient.svg + light_krita_tool_grid.svg + light_krita_tool_line.svg + light_krita_tool_measure.svg + light_krita_tool_move.svg + light_krita_tool_multihand.svg + light_krita_tool_polygon.svg + light_krita_tool_rectangle.svg + light_krita_tool_ruler_assistant.svg + light_krita_tool_transform.svg + light_pattern.svg + light_polyline.svg + light_select.svg + light_tool_contiguous_selection.svg + light_tool_crop.svg + light_tool_elliptical_selection.svg + light_tool_outline_selection.svg + light_tool_path_selection.svg + light_tool_perspectivegrid.svg + light_tool_polygonal_selection.svg + light_tool_rect_selection.svg + light_tool_similar_selection.svg + + diff --git a/krita/sketch/icon/CMakeLists.txt b/krita/sketch/icon/CMakeLists.txt index 832a8e552a..6e431b2135 100644 --- a/krita/sketch/icon/CMakeLists.txt +++ b/krita/sketch/icon/CMakeLists.txt @@ -1 +1,11 @@ -ecm_install_icons( ${ICON_INSTALL_DIR} ) +ecm_install_icons( +ICONS +128-app-kritasketch.png +16-app-kritasketch.png +22-app-kritasketch.png +256-app-kritasketch.png +32-app-kritasketch.png +48-app-kritasketch.png +64-app-kritasketch.png +DESTINATION +${ICON_INSTALL_DIR} ) diff --git a/krita/ui/KisApplication.cpp b/krita/ui/KisApplication.cpp index d0da863cb9..dea71b49c1 100644 --- a/krita/ui/KisApplication.cpp +++ b/krita/ui/KisApplication.cpp @@ -1,648 +1,646 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright (C) 2009 Thomas Zander Copyright (C) 2012 Boudewijn Rempt 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 "KisApplication.h" #include #ifdef Q_OS_WIN #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include "KoGlobal.h" #include "KoConfig.h" #include #include #include "KisPrintJob.h" #include "KisDocumentEntry.h" #include "KisDocument.h" #include "KisMainWindow.h" #include "KisAutoSaveRecoveryDialog.h" #include "KisPart.h" #include #include "kis_md5_generator.h" #include "kis_config.h" #include "flake/kis_shape_selection.h" #include #include #include #include #include #include #include #include "kisexiv2/kis_exiv2.h" #include "KisApplicationArguments.h" #include #ifdef HAVE_OPENGL #include "opengl/kis_opengl.h" #endif #include namespace { const QTime appStartTime(QTime::currentTime()); } class KisApplicationPrivate { public: KisApplicationPrivate() : splashScreen(0) {} QWidget *splashScreen; }; class KisApplication::ResetStarting { public: ResetStarting(QWidget *splash = 0) : m_splash(splash) { } ~ResetStarting() { if (m_splash) { KConfigGroup cfg( KSharedConfig::openConfig(), "SplashScreen"); bool hideSplash = cfg.readEntry("HideSplashAfterStartup", false); if (hideSplash) { m_splash->hide(); } else { m_splash->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); QRect r(QPoint(), m_splash->size()); m_splash->move(QApplication::desktop()->availableGeometry().center() - r.center()); m_splash->setWindowTitle(qAppName()); foreach(QObject *o, m_splash->children()) { QWidget *w = qobject_cast(o); if (w && w->isHidden()) { w->setVisible(true); } } m_splash->show(); } } } QWidget *m_splash; }; KisApplication::KisApplication(const QString &key, int &argc, char **argv) : QtSingleApplication(key, argc, argv) , d(new KisApplicationPrivate) { setApplicationDisplayName("Krita"); setApplicationName("krita"); QString version = CalligraVersionWrapper::versionString(true); setApplicationVersion(version); // Initialize all Calligra directories etc. KoGlobal::initialize(); // for cursors KoResourcePaths::addResourceType("kis_pics", "data", "krita/pics/"); // for images in the paintop box KoResourcePaths::addResourceType("kis_images", "data", "krita/images/"); KoResourcePaths::addResourceType("icc_profiles", "data", "krita/profiles/"); setWindowIcon(KisIconUtils::loadIcon("calligrakrita")); - #ifdef HAVE_OPENGL KisOpenGL::initialize(); #endif #ifdef Q_OS_MACX if ( QSysInfo::MacintoshVersion > QSysInfo::MV_10_8 ) { // fix Mac OS X 10.9 (mavericks) font issue // https://bugreports.qt-project.org/browse/QTBUG-32789 QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande"); } setAttribute(Qt::AA_DontShowIconsInMenus, true); #endif qDebug() << "Available styles:" << QStyleFactory::keys(); QStringList styles = QStringList() /*<< "Breeze"*/ << "Oxygen" << "Plastique" << "Fusion"; foreach(const QString & style, styles) { if (!setStyle(style)) { qDebug() << "No" << style << "available."; } else { break; } } qDebug() << "Style:" << QApplication::style(); KoHashGeneratorProvider::instance()->setGenerator("MD5", new KisMD5Generator()); } #if defined(Q_OS_WIN) && defined(ENV32BIT) typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); LPFN_ISWOW64PROCESS fnIsWow64Process; BOOL isWow64() { BOOL bIsWow64 = FALSE; //IsWow64Process is not available on all supported versions of Windows. //Use GetModuleHandle to get a handle to the DLL that contains the function //and GetProcAddress to get a pointer to the function if available. fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( GetModuleHandle(TEXT("kernel32")),"IsWow64Process"); if(NULL != fnIsWow64Process) { if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) { //handle error } } return bIsWow64; } #endif bool KisApplication::createNewDocFromTemplate(const QString &fileName, KisMainWindow *mainWindow) { QString templatePath; const QUrl templateUrl = QUrl::fromLocalFile(fileName); if (QFile::exists(fileName)) { templatePath = templateUrl.toLocalFile(); dbgUI << "using full path..."; } else { QString desktopName(fileName); const QString templatesResourcePath = KisPart::instance()->templatesResourcePath(); QStringList paths = KoResourcePaths::findAllResources("data", templatesResourcePath + "*/" + desktopName); if (paths.isEmpty()) { paths = KoResourcePaths::findAllResources("data", templatesResourcePath + desktopName); } if (paths.isEmpty()) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("No template found for: %1", desktopName)); } else if (paths.count() > 1) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Too many templates found for: %1", desktopName)); } else { templatePath = paths.at(0); } } if (!templatePath.isEmpty()) { QUrl templateBase; templateBase.setPath(templatePath); KDesktopFile templateInfo(templatePath); QString templateName = templateInfo.readUrl(); QUrl templateURL; templateURL.setPath(templateBase.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash).path() + '/' + templateName); KisDocument *doc = KisPart::instance()->createDocument(); if (mainWindow->openDocumentInternal(templateURL, doc)) { doc->resetURL(); doc->setEmpty(); doc->setTitleModified(); dbgUI << "Template loaded..."; return true; } else { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Template %1 failed to load.", templateURL.toDisplayString())); } } return false; } void KisApplication::clearConfig() { KIS_ASSERT_RECOVER_RETURN(qApp->thread() == QThread::currentThread()); KSharedConfigPtr config = KSharedConfig::openConfig(); // find user settings file bool createDir = false; QString kritarcPath = KoResourcePaths::locateLocal("config", "kritarc", createDir); QFile configFile(kritarcPath); if (configFile.exists()) { // clear file if (configFile.open(QFile::WriteOnly)) { configFile.close(); } else { QMessageBox::warning(0, i18nc("@title:window", "Krita"), i18n("Failed to clear %1\n\n" "Please make sure no other program is using the file and try again.", kritarcPath), QMessageBox::Ok, QMessageBox::Ok); } } // reload from disk; with the user file settings cleared, // this should load any default configuration files shipping with the program config->reparseConfiguration(); config->sync(); } void KisApplication::askClearConfig() { Qt::KeyboardModifiers mods = QApplication::queryKeyboardModifiers(); bool askClearConfig = (mods & Qt::ControlModifier) && (mods & Qt::ShiftModifier) && (mods & Qt::AltModifier); if (askClearConfig) { bool ok = QMessageBox::question(0, i18nc("@title:window", "Krita"), i18n("Do you want to clear the settings file?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes; if (ok) { clearConfig(); } } } bool KisApplication::start(const KisApplicationArguments &args) { #if defined(Q_OS_WIN) || defined (Q_OS_MACX) #ifdef ENV32BIT KisConfig cfg; if (isWow64() && !cfg.readEntry("WarnedAbout32Bits", false)) { QMessageBox::information(0, i18nc("@title:window", "Krita: Warning"), i18n("You are running a 32 bits build on a 64 bits Windows.\n" "This is not recommended.\n" "Please download and install the x64 build instead.")); cfg.writeEntry("WarnedAbout32Bits", true); } #endif QDir appdir(applicationDirPath()); appdir.cdUp(); KoResourcePaths::addXdgDataPrefix(appdir.absolutePath() + "/share"); KoResourcePaths::addPrefix(appdir.absolutePath()); QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); // If there's no kdehome, set it and restart the process. if (!env.contains("KDEHOME")) { qputenv("KDEHOME", QFile::encodeName(QDesktopServices::storageLocation(QDesktopServices::DataLocation))); } if (!env.contains("XDG_DATA_DIRS")) { qputenv("XDG_DATA_DIRS", QFile::encodeName(appdir.absolutePath() + "/share")); } if (!env.contains("KDEDIR")) { qputenv("KDEDIR", QFile::encodeName(appdir.absolutePath())); } if (!env.contains("KDEDIRS")) { qputenv("KDEDIRS", QFile::encodeName(appdir.absolutePath())); } qputenv("PATH", QFile::encodeName(appdir.absolutePath() + "/bin" + ";" + appdir.absolutePath() + "/lib" + ";" + appdir.absolutePath() + "/lib/kde4" + ";" + appdir.absolutePath() + "/Frameworks" + ";" + appdir.absolutePath())); #endif int dpiX = args.dpiX(); int dpiY = args.dpiY(); if (dpiX > 0 && dpiY > 0) { KoDpi::setDPI(dpiX, dpiY); } const bool doTemplate = args.doTemplate(); const bool print = args.print(); const bool exportAs = args.exportAs(); const bool exportAsPdf = args.exportAsPdf(); const QString exportFileName = args.exportFileName(); const QString profileFileName = args.profileFileName(); const bool batchRun = (print || exportAs || exportAsPdf); // print & exportAsPdf do user interaction ATM const bool needsMainWindow = !exportAs; // only show the mainWindow when no command-line mode option is passed // TODO: fix print & exportAsPdf to work without mainwindow shown const bool showmainWindow = !exportAs; // would be !batchRun; const bool runningInGnome = (qgetenv("XDG_CURRENT_DESKTOP") == "GNOME"); const bool showSplashScreen = !batchRun && !runningInGnome; if (d->splashScreen && showSplashScreen) { d->splashScreen->show(); d->splashScreen->repaint(); processEvents(); } ResetStarting resetStarting(d->splashScreen); // remove the splash when done Q_UNUSED(resetStarting); // Load various global plugins KoShapeRegistry* r = KoShapeRegistry::instance(); r->add(new KisShapeSelectionFactory()); KisFilterRegistry::instance(); KisGeneratorRegistry::instance(); KisPaintOpRegistry::instance(); // Load the krita-specific tools KoPluginLoader::instance()->load(QString::fromLatin1("Krita/Tool"), QString::fromLatin1("[X-Krita-Version] == 28")); // Load dockers KoPluginLoader::instance()->load(QString::fromLatin1("Krita/Dock"), QString::fromLatin1("[X-Krita-Version] == 28")); // XXX_EXIV: make the exiv io backends real plugins KisExiv2::initialize(); KisMainWindow *mainWindow = 0; if (needsMainWindow) { // show a mainWindow asap, if we want that mainWindow = KisPart::instance()->createMainWindow(); if (showmainWindow) { QTimer::singleShot(1, mainWindow, SLOT(show())); } } short int numberOfOpenDocuments = 0; // number of documents open // Check for autosave files that can be restored, if we're not running a batchrun (test, print, export to pdf) QList urls = checkAutosaveFiles(); if (!batchRun && mainWindow) { foreach(const QUrl &url, urls) { KisDocument *doc = KisPart::instance()->createDocument(); mainWindow->openDocumentInternal(url, doc); } } // Get the command line arguments which we have to parse int argsCount = args.filenames().count(); if (argsCount > 0) { QTextStream profileoutput; QFile profileFile(profileFileName); if (!profileFileName.isEmpty() && profileFile.open(QFile::WriteOnly | QFile::Truncate)) { profileoutput.setDevice(&profileFile); } // Loop through arguments short int nPrinted = 0; for (int argNumber = 0; argNumber < argsCount; argNumber++) { QString fileName = args.filenames().at(argNumber); // are we just trying to open a template? if (doTemplate) { // called in mix with batch options? ignore and silently skip if (batchRun) { continue; } if (createNewDocFromTemplate(fileName, mainWindow)) { ++numberOfOpenDocuments; } // now try to load } else { if (exportAs) { QMimeType outputMimetype; QMimeDatabase db; outputMimetype = db.mimeTypeForFile(exportFileName); if (outputMimetype.isDefault()) { dbgKrita << i18n("Mimetype not found, try using the -mimetype option") << endl; return 1; } QApplication::setOverrideCursor(Qt::WaitCursor); QString outputFormat = outputMimetype.name(); KisImportExportFilter::ConversionStatus status = KisImportExportFilter::OK; KisImportExportManager manager(fileName); manager.setBatchMode(true); QByteArray mime(outputFormat.toLatin1()); status = manager.exportDocument(exportFileName, mime); if (status != KisImportExportFilter::OK) { dbgKrita << "Could not export " << fileName << "to" << exportFileName << ":" << (int)status; } nPrinted++; QTimer::singleShot(0, this, SLOT(quit())); } else if (mainWindow) { KisDocument *doc = KisPart::instance()->createDocument(); if (mainWindow->openDocumentInternal(QUrl::fromLocalFile(fileName), doc)) { if (print) { mainWindow->slotFilePrint(); nPrinted++; // TODO: trigger closing of app once printing is done } else if (exportAsPdf) { KisPrintJob *job = mainWindow->exportToPdf(exportFileName); if (job) connect (job, SIGNAL(destroyed(QObject*)), mainWindow, SLOT(slotFileQuit()), Qt::QueuedConnection); nPrinted++; } else { // Normal case, success numberOfOpenDocuments++; } } else { // .... if failed // delete doc; done by openDocument } } } } if (batchRun) { return nPrinted > 0; } } // not calling this before since the program will quit there. return true; } KisApplication::~KisApplication() { delete d; } void KisApplication::setSplashScreen(QWidget *splashScreen) { d->splashScreen = splashScreen; } bool KisApplication::notify(QObject *receiver, QEvent *event) { try { return QApplication::notify(receiver, event); } catch (std::exception &e) { qWarning("Error %s sending event %i to object %s", e.what(), event->type(), qPrintable(receiver->objectName())); } catch (...) { qWarning("Error sending event %i to object %s", event->type(), qPrintable(receiver->objectName())); } return false; } void KisApplication::remoteArguments(QByteArray message, QObject *socket) { Q_UNUSED(socket); // check if we have any mainwindow KisMainWindow *mw = qobject_cast(qApp->activeWindow()); if (!mw) { mw = KisPart::instance()->mainWindows().first(); } if (!mw) { return; } KisApplicationArguments args = KisApplicationArguments::deserialize(message); const bool doTemplate = args.doTemplate(); const int argsCount = args.filenames().count(); if (argsCount > 0) { // Loop through arguments for (int argNumber = 0; argNumber < argsCount; ++argNumber) { QString filename = args.filenames().at(argNumber); // are we just trying to open a template? if (doTemplate) { createNewDocFromTemplate(filename, mw); } else if (QFile(filename).exists()) { KisDocument *doc = KisPart::instance()->createDocument(); mw->openDocumentInternal(QUrl::fromLocalFile(filename), doc); } } } } void KisApplication::fileOpenRequested(const QString &url) { KisMainWindow *mainWindow = KisPart::instance()->mainWindows().first(); if (mainWindow) { KisDocument *doc = KisPart::instance()->createDocument(); mainWindow->openDocumentInternal(QUrl::fromLocalFile(url), doc); } } QList KisApplication::checkAutosaveFiles() { // Check for autosave files from a previous run. There can be several, and // we want to offer a restore for every one. Including a nice thumbnail! QStringList autoSaveFiles; QStringList filters; filters << QString(".krita-*-*-autosave.kra"); #ifdef Q_OS_WIN QDir dir = QDir::temp(); #else QDir dir = QDir::home(); #endif // all autosave files for our application autoSaveFiles = dir.entryList(filters, QDir::Files | QDir::Hidden); // Allow the user to make their selection if (autoSaveFiles.size() > 0) { KisAutoSaveRecoveryDialog *dlg = new KisAutoSaveRecoveryDialog(autoSaveFiles, activeWindow()); if (dlg->exec() == QDialog::Accepted) { QStringList filesToRecover = dlg->recoverableFiles(); foreach (const QString &autosaveFile, autoSaveFiles) { if (!filesToRecover.contains(autosaveFile)) { QFile::remove(dir.absolutePath() + "/" + autosaveFile); } } autoSaveFiles = filesToRecover; } else { // don't recover any of the files, but don't delete them either autoSaveFiles.clear(); } } QList autosaveUrls; if (autoSaveFiles.size() > 0) { foreach(const QString &autoSaveFile, autoSaveFiles) { const QUrl url = QUrl::fromLocalFile(dir.absolutePath() + QLatin1Char('/') + autoSaveFile); autosaveUrls << url; } } return autosaveUrls; } diff --git a/krita/ui/KisDocumentSectionView.cpp b/krita/ui/KisDocumentSectionView.cpp index 299e7bf3c6..5f3e0fc739 100644 --- a/krita/ui/KisDocumentSectionView.cpp +++ b/krita/ui/KisDocumentSectionView.cpp @@ -1,453 +1,453 @@ /* Copyright (c) 2006 Gábor Lehel 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 "KisDocumentSectionView.h" #include "KisDocumentSectionPropertyAction_p.h" #include "KisDocumentSectionDelegate.h" #include "KisDocumentSectionModel.h" #include #include -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_X11 #define DRAG_WHILE_DRAG_WORKAROUND #endif #ifdef DRAG_WHILE_DRAG_WORKAROUND #define DRAG_WHILE_DRAG_WORKAROUND_START() d->isDragging = true #define DRAG_WHILE_DRAG_WORKAROUND_STOP() d->isDragging = false #else #define DRAG_WHILE_DRAG_WORKAROUND_START() #define DRAG_WHILE_DRAG_WORKAROUND_STOP() #endif class Q_DECL_HIDDEN KisDocumentSectionView::Private { public: Private() : delegate(0) , mode(DetailedMode) #ifdef DRAG_WHILE_DRAG_WORKAROUND , isDragging(false) #endif { KSharedConfigPtr config = KSharedConfig::openConfig(); KConfigGroup group = config->group("DocumentSectionView"); mode = (DisplayMode) group.readEntry("DocumentSectionViewMode", (int)DetailedMode); } KisDocumentSectionDelegate *delegate; DisplayMode mode; QPersistentModelIndex hovered; QPoint lastPos; #ifdef DRAG_WHILE_DRAG_WORKAROUND bool isDragging; #endif }; KisDocumentSectionView::KisDocumentSectionView(QWidget *parent) : QTreeView(parent) , m_draggingFlag(false) , d(new Private) { d->delegate = new KisDocumentSectionDelegate(this, this); setMouseTracking(true); setVerticalScrollMode(ScrollPerPixel); setSelectionMode(SingleSelection); setSelectionBehavior(SelectItems); header()->hide(); setDragEnabled(true); setDragDropMode(QAbstractItemView::DragDrop); setAcceptDrops(true); setDropIndicatorShown(true); } KisDocumentSectionView::~KisDocumentSectionView() { delete d; } void KisDocumentSectionView::setDisplayMode(DisplayMode mode) { if (d->mode != mode) { d->mode = mode; KSharedConfigPtr config = KSharedConfig::openConfig(); KConfigGroup group = config->group("DocumentSectionView"); group.writeEntry("DocumentSectionViewMode", (int)mode); scheduleDelayedItemsLayout(); } } KisDocumentSectionView::DisplayMode KisDocumentSectionView::displayMode() const { return d->mode; } void KisDocumentSectionView::addPropertyActions(QMenu *menu, const QModelIndex &index) { Model::PropertyList list = index.data(Model::PropertiesRole).value(); for (int i = 0, n = list.count(); i < n; ++i) { if (list.at(i).isMutable) { PropertyAction *a = new PropertyAction(i, list.at(i), index, menu); connect(a, SIGNAL(toggled(bool, const QPersistentModelIndex&, int)), this, SLOT(slotActionToggled(bool, const QPersistentModelIndex&, int))); menu->addAction(a); } } } void KisDocumentSectionView::updateNode(const QModelIndex &index) { dataChanged(index, index); } bool KisDocumentSectionView::viewportEvent(QEvent *e) { if (model()) { switch(e->type()) { case QEvent::MouseButtonPress: { DRAG_WHILE_DRAG_WORKAROUND_STOP(); const QPoint pos = static_cast(e)->pos(); d->lastPos = pos; if (!indexAt(pos).isValid()) { return QTreeView::viewportEvent(e); } QModelIndex index = model()->buddy(indexAt(pos)); if (d->delegate->editorEvent(e, model(), optionForIndex(index), index)) { return true; } } break; case QEvent::Leave: { QEvent e(QEvent::Leave); d->delegate->editorEvent(&e, model(), optionForIndex(d->hovered), d->hovered); d->hovered = QModelIndex(); } break; case QEvent::MouseMove: { #ifdef DRAG_WHILE_DRAG_WORKAROUND if (d->isDragging) { return false; } #endif const QPoint pos = static_cast(e)->pos(); QModelIndex hovered = indexAt(pos); if (hovered != d->hovered) { if (d->hovered.isValid()) { QEvent e(QEvent::Leave); d->delegate->editorEvent(&e, model(), optionForIndex(d->hovered), d->hovered); } if (hovered.isValid()) { QEvent e(QEvent::Enter); d->delegate->editorEvent(&e, model(), optionForIndex(hovered), hovered); } d->hovered = hovered; } /* This is a workaround for a bug in QTreeView that immediately begins a dragging action when the mouse lands on the decoration/icon of a different index and moves 1 pixel or more */ Qt::MouseButtons buttons = static_cast(e)->buttons(); if ((Qt::LeftButton | Qt::MidButton) & buttons) { if ((pos - d->lastPos).manhattanLength() > qApp->startDragDistance()) { return QTreeView::viewportEvent(e); } return true; } } break; case QEvent::ToolTip: { const QPoint pos = static_cast(e)->pos(); if (!indexAt(pos).isValid()) { return QTreeView::viewportEvent(e); } QModelIndex index = model()->buddy(indexAt(pos)); return d->delegate->editorEvent(e, model(), optionForIndex(index), index); } break; case QEvent::Resize: { scheduleDelayedItemsLayout(); break; } default: break; } } return QTreeView::viewportEvent(e); } void KisDocumentSectionView::contextMenuEvent(QContextMenuEvent *e) { QTreeView::contextMenuEvent(e); QModelIndex i = indexAt(e->pos()); if (model()) i = model()->buddy(i); showContextMenu(e->globalPos(), i); } void KisDocumentSectionView::showContextMenu(const QPoint &globalPos, const QModelIndex &index) { emit contextMenuRequested(globalPos, index); } void KisDocumentSectionView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { QTreeView::currentChanged(current, previous); if (current != previous) { Q_ASSERT(!current.isValid() || current.model() == model()); model()->setData(current, true, Model::ActiveRole); } } void KisDocumentSectionView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &/*roles*/) { QTreeView::dataChanged(topLeft, bottomRight); for (int x = topLeft.row(); x <= bottomRight.row(); ++x) { for (int y = topLeft.column(); y <= bottomRight.column(); ++y) { if (topLeft.sibling(x, y).data(Model::ActiveRole).toBool()) { setCurrentIndex(topLeft.sibling(x, y)); return; } } } } void KisDocumentSectionView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { QTreeView::selectionChanged(selected, deselected); emit selectionChanged(selectedIndexes()); } void KisDocumentSectionView::slotActionToggled(bool on, const QPersistentModelIndex &index, int num) { Model::PropertyList list = index.data(Model::PropertiesRole).value(); list[num].state = on; const_cast(index.model())->setData(index, QVariant::fromValue(list), Model::PropertiesRole); } QStyleOptionViewItem KisDocumentSectionView::optionForIndex(const QModelIndex &index) const { QStyleOptionViewItem option = viewOptions(); option.rect = visualRect(index); if (index == currentIndex()) option.state |= QStyle::State_HasFocus; return option; } void KisDocumentSectionView::startDrag(Qt::DropActions supportedActions) { DRAG_WHILE_DRAG_WORKAROUND_START(); if (displayMode() == KisDocumentSectionView::ThumbnailMode) { const QModelIndexList indexes = selectionModel()->selectedIndexes(); if (!indexes.isEmpty()) { QMimeData *data = model()->mimeData(indexes); if (!data) { return; } QDrag *drag = new QDrag(this); drag->setPixmap(createDragPixmap()); drag->setMimeData(data); //m_dragSource = this; drag->exec(supportedActions); } } else { QTreeView::startDrag(supportedActions); } } QPixmap KisDocumentSectionView::createDragPixmap() const { const QModelIndexList selectedIndexes = selectionModel()->selectedIndexes(); Q_ASSERT(!selectedIndexes.isEmpty()); const int itemCount = selectedIndexes.count(); // If more than one item is dragged, align the items inside a // rectangular grid. The maximum grid size is limited to 4 x 4 items. int xCount = 2; int size = 96; if (itemCount > 9) { xCount = 4; - size = KIconLoader::SizeLarge; + size = KoIconUtils::SizeLarge; } else if (itemCount > 4) { xCount = 3; - size = KIconLoader::SizeHuge; + size = KoIconUtils::SizeHuge; } else if (itemCount < xCount) { xCount = itemCount; } int yCount = itemCount / xCount; if (itemCount % xCount != 0) { ++yCount; } if (yCount > xCount) { yCount = xCount; } // Draw the selected items into the grid cells QPixmap dragPixmap(xCount * size + xCount - 1, yCount * size + yCount - 1); dragPixmap.fill(Qt::transparent); QPainter painter(&dragPixmap); int x = 0; int y = 0; foreach (const QModelIndex &selectedIndex, selectedIndexes) { const QImage img = selectedIndex.data(int(Model::BeginThumbnailRole) + size).value(); painter.drawPixmap(x, y, QPixmap().fromImage(img.scaled(QSize(size, size), Qt::KeepAspectRatio))); x += size + 1; if (x >= dragPixmap.width()) { x = 0; y += size + 1; } if (y >= dragPixmap.height()) { break; } } return dragPixmap; } void KisDocumentSectionView::paintEvent(QPaintEvent *event) { event->accept(); QTreeView::paintEvent(event); // Paint the line where the slide should go if (isDragging() && (displayMode() == KisDocumentSectionView::ThumbnailMode)) { QSize size(visualRect(model()->index(0, 0, QModelIndex())).width(), visualRect(model()->index(0, 0, QModelIndex())).height()); int numberRow = cursorPageIndex(); int scrollBarValue = verticalScrollBar()->value(); QPoint point1(0, numberRow * size.height() - scrollBarValue); QPoint point2(size.width(), numberRow * size.height() - scrollBarValue); QLineF line(point1, point2); QPainter painter(this->viewport()); QPen pen = QPen(palette().brush(QPalette::Highlight), 8); pen.setCapStyle(Qt::RoundCap); painter.setPen(pen); painter.setOpacity(0.8); painter.drawLine(line); } } void KisDocumentSectionView::dropEvent(QDropEvent *ev) { if (displayMode() == KisDocumentSectionView::ThumbnailMode) { setDraggingFlag(false); ev->accept(); clearSelection(); if (!model()) { return; } int newIndex = cursorPageIndex(); model()->dropMimeData(ev->mimeData(), ev->dropAction(), newIndex, -1, QModelIndex()); return; } QTreeView::dropEvent(ev); DRAG_WHILE_DRAG_WORKAROUND_STOP(); } int KisDocumentSectionView::cursorPageIndex() const { QSize size(visualRect(model()->index(0, 0, QModelIndex())).width(), visualRect(model()->index(0, 0, QModelIndex())).height()); int scrollBarValue = verticalScrollBar()->value(); QPoint cursorPosition = QWidget::mapFromGlobal(QCursor::pos()); int numberRow = (cursorPosition.y() + scrollBarValue) / size.height(); //If cursor is at the half button of the page then the move action is performed after the slide, otherwise it is //performed before the page if (abs((cursorPosition.y() + scrollBarValue) - size.height()*numberRow) > (size.height()/2)) { numberRow++; } if (numberRow > model()->rowCount(QModelIndex())) { numberRow = model()->rowCount(QModelIndex()); } return numberRow; } void KisDocumentSectionView::dragEnterEvent(QDragEnterEvent *ev) { DRAG_WHILE_DRAG_WORKAROUND_START(); QTreeView::dragEnterEvent(ev); } void KisDocumentSectionView::dragMoveEvent(QDragMoveEvent *ev) { DRAG_WHILE_DRAG_WORKAROUND_START(); if (displayMode() == KisDocumentSectionView::ThumbnailMode) { ev->accept(); if (!model()) { return; } QTreeView::dragMoveEvent(ev); setDraggingFlag(); viewport()->update(); return; } QTreeView::dragMoveEvent(ev); } void KisDocumentSectionView::dragLeaveEvent(QDragLeaveEvent *e) { if (displayMode() == KisDocumentSectionView::ThumbnailMode) { setDraggingFlag(false); } else { QTreeView::dragLeaveEvent(e); } DRAG_WHILE_DRAG_WORKAROUND_STOP(); } bool KisDocumentSectionView::isDragging() const { return m_draggingFlag; } void KisDocumentSectionView::setDraggingFlag(bool flag) { m_draggingFlag = flag; } #include diff --git a/krita/ui/KisTemplate.cpp b/krita/ui/KisTemplate.cpp index bc888763e9..85bbc816e6 100644 --- a/krita/ui/KisTemplate.cpp +++ b/krita/ui/KisTemplate.cpp @@ -1,61 +1,62 @@ /* This file is part of the KDE project Copyright (C) 2000 Werner Trobin 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 "KisTemplate.h" #include #include +#include #include -#include +#include KisTemplate::KisTemplate(const QString &name, const QString &description, const QString &file, const QString &picture, const QString &fileName, const QString &_measureSystem, bool hidden, bool touched) : m_name(name), m_descr(description), m_file(file), m_picture(picture), m_fileName(fileName), m_hidden(hidden), m_touched(touched), m_cached(false), m_measureSystem(_measureSystem) { } const QPixmap &KisTemplate::loadPicture() { if (m_cached) return m_pixmap; m_cached = true; if (m_picture[ 0 ] == '/') { QImage img(m_picture); if (img.isNull()) { dbgKrita << "Couldn't find icon " << m_picture; m_pixmap = QPixmap(); return m_pixmap; } const int maxHeightWidth = 128; // ### TODO: some people would surely like to have 128x128 if (img.width() > maxHeightWidth || img.height() > maxHeightWidth) { img = img.scaled(maxHeightWidth, maxHeightWidth, Qt::KeepAspectRatio, Qt::SmoothTransformation); } m_pixmap = QPixmap::fromImage(img); return m_pixmap; } else { // relative path - m_pixmap = KIconLoader::global()->loadIcon(m_picture, KIconLoader::Desktop, 128); + m_pixmap = KoIconUtils::themedIcon(m_picture).pixmap(KoIconUtils::SizeEnormous); return m_pixmap; } } diff --git a/krita/ui/KisTemplateCreateDia.cpp b/krita/ui/KisTemplateCreateDia.cpp index f510afec48..ff67494066 100644 --- a/krita/ui/KisTemplateCreateDia.cpp +++ b/krita/ui/KisTemplateCreateDia.cpp @@ -1,522 +1,522 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Reginald Stadlbauer 2000 Werner Trobin Copyright (C) 2004 Nicolas GOUTTE 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 #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #include -#include +#include #include #include #include // ODF thumbnail extent static const int thumbnailExtent = 128; class KisTemplateCreateDiaPrivate { public: KisTemplateCreateDiaPrivate(const QString &templatesResourcePath, const QString &filePath, const QPixmap &thumbnail) : m_tree(templatesResourcePath, true) , m_filePath(filePath) , m_thumbnail(thumbnail) { } KisTemplateTree m_tree; QLineEdit *m_name; QRadioButton *m_default; QRadioButton *m_custom; QPushButton *m_select; QLabel *m_preview; QString m_customFile; QPixmap m_customPixmap; QTreeWidget *m_groups; QPushButton *m_add; QPushButton *m_remove; QCheckBox *m_defaultTemplate; QString m_filePath; QPixmap m_thumbnail; bool m_changed; }; /**************************************************************************** * * Class: KisTemplateCreateDia * ****************************************************************************/ KisTemplateCreateDia::KisTemplateCreateDia(const QString &templatesResourcePath, const QString &filePath, const QPixmap &thumbnail, QWidget *parent) : KoDialog(parent) , d(new KisTemplateCreateDiaPrivate(templatesResourcePath, filePath, thumbnail)) { setButtons( KoDialog::Ok|KoDialog::Cancel ); setDefaultButton( KoDialog::Ok ); setCaption( i18n( "Create Template" ) ); setModal( true ); setObjectName( "template create dia" ); QWidget *mainwidget = mainWidget(); QHBoxLayout *mbox=new QHBoxLayout( mainwidget ); QVBoxLayout* leftbox = new QVBoxLayout(); mbox->addLayout( leftbox ); QLabel *label=new QLabel(i18nc("Template name", "Name:"), mainwidget); QHBoxLayout *namefield=new QHBoxLayout(); leftbox->addLayout( namefield ); namefield->addWidget(label); d->m_name=new QLineEdit(mainwidget); d->m_name->setFocus(); connect(d->m_name, SIGNAL(textChanged(const QString &)), this, SLOT(slotNameChanged(const QString &))); namefield->addWidget(d->m_name); label=new QLabel(i18n("Group:"), mainwidget); leftbox->addWidget(label); d->m_groups = new QTreeWidget(mainwidget); leftbox->addWidget(d->m_groups); d->m_groups->setColumnCount(1); d->m_groups->setHeaderHidden(true); d->m_groups->setRootIsDecorated(true); d->m_groups->setSortingEnabled(true); fillGroupTree(); d->m_groups->sortItems(0, Qt::AscendingOrder); QHBoxLayout *bbox=new QHBoxLayout(); leftbox->addLayout( bbox ); d->m_add=new QPushButton(i18n("&Add Group..."), mainwidget); connect(d->m_add, SIGNAL(clicked()), this, SLOT(slotAddGroup())); bbox->addWidget(d->m_add); d->m_remove=new QPushButton(i18n("&Remove"), mainwidget); connect(d->m_remove, SIGNAL(clicked()), this, SLOT(slotRemove())); bbox->addWidget(d->m_remove); QVBoxLayout *rightbox=new QVBoxLayout(); mbox->addLayout( rightbox ); QGroupBox *pixbox = new QGroupBox(i18n("Picture"), mainwidget); rightbox->addWidget(pixbox); QVBoxLayout *pixlayout=new QVBoxLayout(pixbox ); d->m_default=new QRadioButton(i18n("&Preview"), pixbox); d->m_default->setChecked(true); connect(d->m_default, SIGNAL(clicked()), this, SLOT(slotDefault())); pixlayout->addWidget(d->m_default); QHBoxLayout *custombox=new QHBoxLayout(); d->m_custom=new QRadioButton(i18n("Custom:"), pixbox); d->m_custom->setChecked(false); connect(d->m_custom, SIGNAL(clicked()), this, SLOT(slotCustom())); custombox->addWidget(d->m_custom); d->m_select=new QPushButton(i18n("&Select..."), pixbox); connect(d->m_select, SIGNAL(clicked()), this, SLOT(slotSelect())); custombox->addWidget(d->m_select); custombox->addStretch(1); pixlayout->addLayout(custombox); d->m_preview=new QLabel(pixbox); // setPixmap() -> auto resize? pixlayout->addWidget(d->m_preview, 0, Qt::AlignCenter); pixlayout->addStretch(1); d->m_defaultTemplate = new QCheckBox( i18n("Use the new template as default"), mainwidget ); d->m_defaultTemplate->setChecked( true ); d->m_defaultTemplate->setToolTip(i18n("Use the new template every time Krita starts")); rightbox->addWidget( d->m_defaultTemplate ); enableButtonOk(false); d->m_changed=false; updatePixmap(); connect(d->m_groups, SIGNAL(itemSelectionChanged()), this, SLOT(slotSelectionChanged())); d->m_remove->setEnabled(d->m_groups->currentItem()); connect(this,SIGNAL(okClicked()),this,SLOT(slotOk())); } KisTemplateCreateDia::~KisTemplateCreateDia() { delete d; } void KisTemplateCreateDia::slotSelectionChanged() { const QTreeWidgetItem* item = d->m_groups->currentItem(); d->m_remove->setEnabled( item ); if ( ! item ) return; if ( item->parent() != NULL ) { d->m_name->setText( item->text( 0 ) ); } } void KisTemplateCreateDia::createTemplate(const QString &templatesResourcePath, const char *suffix, KisDocument *document, QWidget *parent) { QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/krita_XXXXXX") + QLatin1String(QLatin1String(suffix))); //Check that creation of temp file was successful if (!tempFile->open()) { delete tempFile; qWarning("Creation of temporary file to store template failed."); return; } const QString fileName = tempFile->fileName(); tempFile->close(); // need to close on Windows before we can open it again to save delete tempFile; // now the file has disappeared and we can create a new file with the generated name document->saveNativeFormat(fileName); const QPixmap thumbnail = document->generatePreview(QSize(thumbnailExtent, thumbnailExtent)); KisTemplateCreateDia *dia = new KisTemplateCreateDia(templatesResourcePath, fileName, thumbnail, parent); dia->exec(); delete dia; QDir d; d.remove(fileName); } static void saveAsQuadraticPng(const QPixmap &pixmap, const QString &fileName) { QImage icon = pixmap.toImage(); icon = icon.convertToFormat(QImage::Format_ARGB32); const int iconExtent = qMax(icon.width(), icon.height()); icon = icon.copy((icon.width() - iconExtent) / 2, (icon.height() - iconExtent) / 2, iconExtent, iconExtent); icon.save(fileName, "PNG"); } void KisTemplateCreateDia::slotOk() { // get the current item, if there is one... QTreeWidgetItem *item = d->m_groups->currentItem(); if(!item) item = d->m_groups->topLevelItem(0); if(!item) { // safe :) d->m_tree.writeTemplateTree(); slotButtonClicked( KoDialog::Cancel ); return; } // is it a group or a template? anyway - get the group :) if(item->parent() != NULL) item=item->parent(); if(!item) { // *very* safe :P d->m_tree.writeTemplateTree(); slotButtonClicked( KoDialog::Cancel ); return; } KisTemplateGroup *group=d->m_tree.find(item->text(0)); if(!group) { // even safer d->m_tree.writeTemplateTree(); slotButtonClicked( KoDialog::Cancel ); return; } if(d->m_name->text().isEmpty()) { d->m_tree.writeTemplateTree(); slotButtonClicked( KoDialog::Cancel ); return; } // copy the tmp file and the picture the app provides QString dir = KoResourcePaths::saveLocation("data", d->m_tree.templatesResourcePath()); dir+=group->name(); QString templateDir=dir+"/.source/"; QString iconDir=dir+"/.icon/"; QString file=KisTemplates::trimmed(d->m_name->text()); QString tmpIcon=".icon/"+file; tmpIcon+=".png"; QString icon=iconDir+file; icon+=".png"; // try to find the extension for the template file :P const int pos = d->m_filePath.lastIndexOf(QLatin1Char('.')); QString ext; if ( pos > -1 ) ext = d->m_filePath.mid(pos); else warnUI << "Template extension not found!"; QUrl dest; dest.setPath(templateDir+file+ext); if (QFile::exists(dest.toLocalFile())) { do { file.prepend( '_' ); dest.setPath( templateDir + file + ext ); tmpIcon=".icon/" + file + ".png"; icon=iconDir + file + ".png"; } while (QFile(dest.toLocalFile()).exists()); } bool ignore = false; dbgUI <<"Trying to create template:" << d->m_name->text() <<"URL=" <<".source/"+file+ext <<" ICON=" << tmpIcon; KisTemplate *t=new KisTemplate(d->m_name->text(), QString(), ".source/"+file+ext, tmpIcon, "", "", false, true); if (!group->add(t)) { KisTemplate *existingTemplate=group->find(d->m_name->text()); if (existingTemplate && !existingTemplate->isHidden()) { if (QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Do you really want to overwrite the existing '%1' template?", existingTemplate->name()), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) { group->add(t, true); } else { delete t; return; } } else { ignore = true; } } QDir path; if (!path.mkpath(templateDir) || !path.mkpath(iconDir)) { d->m_tree.writeTemplateTree(); slotButtonClicked( KoDialog::Cancel ); return; } QUrl orig; orig.setPath(d->m_filePath); // don't overwrite the hidden template file with a new non-hidden one if ( !ignore ) { QFile::copy(d->m_filePath, dest.toLocalFile()); // save the picture as icon - // (needs to be square, otherwise KIconLoader dpes nasty changes) if(d->m_default->isChecked() && !d->m_thumbnail.isNull()) { saveAsQuadraticPng(d->m_thumbnail, icon); } else if(!d->m_customPixmap.isNull()) { saveAsQuadraticPng(d->m_customPixmap, icon); } else { warnUI << "Could not save the preview picture!"; } } // if there's a .directory file, we copy this one, too bool ready=false; QStringList tmp=group->dirs(); for(QStringList::ConstIterator it=tmp.constBegin(); it!=tmp.constEnd() && !ready; ++it) { if((*it).contains(dir)==0) { orig.setPath( (*it)+".directory" ); // Check if we can read the file if (QFile(orig.toLocalFile()).exists()) { dest.setPath(dir + "/.directory"); // We copy the file with overwrite if (!QFile(orig.toLocalFile()).copy(dest.toLocalFile())) { warnKrita << "Failed to copy from" << orig.toLocalFile() << "to" << dest.toLocalFile(); } ready = true; } } } d->m_tree.writeTemplateTree(); if ( d->m_defaultTemplate->isChecked() ) { KConfigGroup grp( KSharedConfig::openConfig(), "TemplateChooserDialog"); grp.writeEntry( "LastReturnType", "Template" ); grp.writePathEntry( "FullTemplateName", dir + '/' + t->file() ); grp.writePathEntry( "AlwaysUseTemplate", dir + '/' + t->file() ); } } void KisTemplateCreateDia::slotDefault() { d->m_default->setChecked(true); d->m_custom->setChecked(false); updatePixmap(); } void KisTemplateCreateDia::slotCustom() { d->m_default->setChecked(false); d->m_custom->setChecked(true); if(d->m_customFile.isEmpty()) slotSelect(); else updatePixmap(); } void KisTemplateCreateDia::slotSelect() { d->m_default->setChecked(false); d->m_custom->setChecked(true); - QString name = KIconDialog::getIcon(); - if( name.isEmpty() ) { - if(d->m_customFile.isEmpty()) { - d->m_default->setChecked(true); - d->m_custom->setChecked(false); - } - return; - } - const QString path = KIconLoader::global()->iconPath(name, -thumbnailExtent); - d->m_customFile = path; - d->m_customPixmap=QPixmap(); + // QT5TODO +// QString name = KIconDialog::getIcon(); +// if( name.isEmpty() ) { +// if(d->m_customFile.isEmpty()) { +// d->m_default->setChecked(true); +// d->m_custom->setChecked(false); +// } +// return; +// } + +// const QString path = KIconLoader::global()->iconPath(name, -thumbnailExtent); + d->m_customFile = QString();// path; + d->m_customPixmap = QPixmap(); updatePixmap(); } void KisTemplateCreateDia::slotNameChanged(const QString &name) { if( ( name.trimmed().isEmpty() || !d->m_groups->topLevelItem(0) ) && !d->m_changed ) enableButtonOk(false); else enableButtonOk(true); } void KisTemplateCreateDia::slotAddGroup() { const QString name = QInputDialog::getText(this, i18n("Add Group"), i18n("Enter group name:")); KisTemplateGroup *group = d->m_tree.find(name); if (group && !group->isHidden()) { QMessageBox::information( this, i18n("This name is already used."), i18n("Add Group") ); return; } QString dir = KoResourcePaths::saveLocation("data", d->m_tree.templatesResourcePath()); dir+=name; KisTemplateGroup *newGroup=new KisTemplateGroup(name, dir, 0, true); d->m_tree.add(newGroup); QTreeWidgetItem *item = new QTreeWidgetItem(d->m_groups, QStringList() << name); d->m_groups->setCurrentItem(item); d->m_groups->sortItems(0, Qt::AscendingOrder); d->m_name->setFocus(); enableButtonOk(true); d->m_changed=true; } void KisTemplateCreateDia::slotRemove() { QTreeWidgetItem *item = d->m_groups->currentItem(); if(!item) return; QString what; QString removed; if (item->parent() == NULL) { what = i18n("Do you really want to remove that group?"); removed = i18nc("@title:window", "Remove Group"); } else { what = i18n("Do you really want to remove that template?"); removed = i18nc("@title:window", "Remove Template"); } if (QMessageBox::warning(this, removed, what, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox:: No) { d->m_name->setFocus(); return; } if(item->parent() == NULL) { KisTemplateGroup *group=d->m_tree.find(item->text(0)); if(group) group->setHidden(true); } else { bool done=false; QList groups = d->m_tree.groups(); QList::const_iterator it = groups.constBegin(); for(; it != groups.constEnd() && !done; ++it) { KisTemplate *t = (*it)->find(item->text(0)); if(t) { t->setHidden(true); done=true; } } } delete item; item=0; enableButtonOk(true); d->m_name->setFocus(); d->m_changed=true; } void KisTemplateCreateDia::updatePixmap() { if(d->m_default->isChecked() && !d->m_thumbnail.isNull()) d->m_preview->setPixmap(d->m_thumbnail); else if(d->m_custom->isChecked() && !d->m_customFile.isEmpty()) { if(d->m_customPixmap.isNull()) { dbgUI <<"Trying to load picture" << d->m_customFile; // use the code in KisTemplate to load the image... hacky, I know :) KisTemplate t("foo", "bar", QString(), d->m_customFile); d->m_customPixmap=t.loadPicture(); } else warnUI << "Trying to load picture"; if(!d->m_customPixmap.isNull()) d->m_preview->setPixmap(d->m_customPixmap); else d->m_preview->setText(i18n("Could not load picture.")); } else d->m_preview->setText(i18n("No picture available.")); } void KisTemplateCreateDia::fillGroupTree() { foreach(KisTemplateGroup *group, d->m_tree.groups()) { if(group->isHidden()) continue; QTreeWidgetItem *groupItem=new QTreeWidgetItem(d->m_groups, QStringList() << group->name()); foreach(KisTemplate *t, group->templates()) { if(t->isHidden()) continue; (void)new QTreeWidgetItem(groupItem, QStringList() << t->name()); } } } diff --git a/krita/ui/widgets/kis_cie_tongue_widget.cpp b/krita/ui/widgets/kis_cie_tongue_widget.cpp index 7760a5b5e2..19285d9de6 100644 --- a/krita/ui/widgets/kis_cie_tongue_widget.cpp +++ b/krita/ui/widgets/kis_cie_tongue_widget.cpp @@ -1,683 +1,683 @@ /* * Copyright (C) 2015 by Wolthera van Hövell tot Westerflier * * Based on the Digikam CIE Tongue widget * Copyright (C) 2006-2013 by Gilles Caulier * * Any source code are inspired from lprof project and * Copyright (C) 1998-2001 Marti Maria * * 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, 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. **/ /** The following table gives the CIE color matching functions \f$\bar{x}(\lambda)\f$, \f$\bar{y}(\lambda)\f$, and \f$\bar{z}(\lambda)\f$, for wavelengths \f$\lambda\f$ at 5 nanometer increments from 380 nm through 780 nm. This table is used in conjunction with Planck's law for the energy spectrum of a black body at a given temperature to plot the black body curve on the CIE chart. The following table gives the spectral chromaticity co-ordinates \f$x(\lambda)\f$ and \f$y(\lambda)\f$ for wavelengths in 5 nanometer increments from 380 nm through 780 nm. These coordinates represent the position in the CIE x-y space of pure spectral colors of the given wavelength, and thus define the outline of the CIE "tongue" diagram. */ #include #include #include #include #include #include #include #include -#include #include +#include #include #include "kis_cie_tongue_widget.h" static const double spectral_chromaticity[81][3] = { { 0.1741, 0.0050 }, // 380 nm { 0.1740, 0.0050 }, { 0.1738, 0.0049 }, { 0.1736, 0.0049 }, { 0.1733, 0.0048 }, { 0.1730, 0.0048 }, { 0.1726, 0.0048 }, { 0.1721, 0.0048 }, { 0.1714, 0.0051 }, { 0.1703, 0.0058 }, { 0.1689, 0.0069 }, { 0.1669, 0.0086 }, { 0.1644, 0.0109 }, { 0.1611, 0.0138 }, { 0.1566, 0.0177 }, { 0.1510, 0.0227 }, { 0.1440, 0.0297 }, { 0.1355, 0.0399 }, { 0.1241, 0.0578 }, { 0.1096, 0.0868 }, { 0.0913, 0.1327 }, { 0.0687, 0.2007 }, { 0.0454, 0.2950 }, { 0.0235, 0.4127 }, { 0.0082, 0.5384 }, { 0.0039, 0.6548 }, { 0.0139, 0.7502 }, { 0.0389, 0.8120 }, { 0.0743, 0.8338 }, { 0.1142, 0.8262 }, { 0.1547, 0.8059 }, { 0.1929, 0.7816 }, { 0.2296, 0.7543 }, { 0.2658, 0.7243 }, { 0.3016, 0.6923 }, { 0.3373, 0.6589 }, { 0.3731, 0.6245 }, { 0.4087, 0.5896 }, { 0.4441, 0.5547 }, { 0.4788, 0.5202 }, { 0.5125, 0.4866 }, { 0.5448, 0.4544 }, { 0.5752, 0.4242 }, { 0.6029, 0.3965 }, { 0.6270, 0.3725 }, { 0.6482, 0.3514 }, { 0.6658, 0.3340 }, { 0.6801, 0.3197 }, { 0.6915, 0.3083 }, { 0.7006, 0.2993 }, { 0.7079, 0.2920 }, { 0.7140, 0.2859 }, { 0.7190, 0.2809 }, { 0.7230, 0.2770 }, { 0.7260, 0.2740 }, { 0.7283, 0.2717 }, { 0.7300, 0.2700 }, { 0.7311, 0.2689 }, { 0.7320, 0.2680 }, { 0.7327, 0.2673 }, { 0.7334, 0.2666 }, { 0.7340, 0.2660 }, { 0.7344, 0.2656 }, { 0.7346, 0.2654 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 }, { 0.7347, 0.2653 } // 780 nm }; class Q_DECL_HIDDEN KisCIETongueWidget::Private { public: Private() : profileDataAvailable(false), needUpdatePixmap(false), cieTongueNeedsUpdate(true), uncalibratedColor(false), xBias(0), yBias(0), pxcols(0), pxrows(0), progressCount(0), gridside(0), progressTimer(0), Primaries(9), whitePoint(3) { - progressPix = KPixmapSequence("process-working", KIconLoader::SizeSmallMedium); + progressPix = KPixmapSequence("process-working", KoIconUtils::SizeSmallMedium); } bool profileDataAvailable; bool needUpdatePixmap; bool cieTongueNeedsUpdate; bool uncalibratedColor; int xBias; int yBias; int pxcols; int pxrows; int progressCount; // Position of animation during loading/calculation. double gridside; QPainter painter; QTimer* progressTimer; QPixmap pixmap; QPixmap cietongue; KPixmapSequence progressPix; QVector Primaries; QVector whitePoint; model colorModel; }; KisCIETongueWidget::KisCIETongueWidget(QWidget *parent) : QWidget(parent), d(new Private) { d->progressTimer = new QTimer(this); setAttribute(Qt::WA_DeleteOnClose); d->Primaries.resize(9); d->Primaries.fill(0.0); d->whitePoint.resize(3); d->whitePoint<<0.34773<<0.35952<<1.0; connect(d->progressTimer, SIGNAL(timeout()), this, SLOT(slotProgressTimerDone())); } KisCIETongueWidget::~KisCIETongueWidget() { delete d; } int KisCIETongueWidget::grids(double val) const { return (int) floor(val * d->gridside + 0.5); } void KisCIETongueWidget::setProfileData(QVector p, QVector w, bool profileData) { d->profileDataAvailable = profileData; if (profileData){ d->Primaries= p; d->whitePoint = w; d->needUpdatePixmap = true; } else { return; } } void KisCIETongueWidget::setRGBData(QVector whitepoint, QVector colorants) { if (colorants.size()==9){ d->Primaries= colorants; d->whitePoint = whitepoint; d->needUpdatePixmap = true; d->colorModel = KisCIETongueWidget::RGBA; d->profileDataAvailable = true; } else { return; } } void KisCIETongueWidget::setCMYKData(QVector whitepoint) { if (whitepoint.size()==3){ //d->Primaries= colorants; d->whitePoint = whitepoint; d->needUpdatePixmap = true; d->colorModel = KisCIETongueWidget::CMYKA; d->profileDataAvailable = true; } else { return; } } void KisCIETongueWidget::setXYZData(QVector whitepoint) { if (whitepoint.size()==3){ d->whitePoint = whitepoint; d->needUpdatePixmap = true; d->colorModel = KisCIETongueWidget::XYZA; d->profileDataAvailable = true; } else { return; } } void KisCIETongueWidget::setGrayData(QVector whitepoint) { if (whitepoint.size()==3){ d->whitePoint = whitepoint; d->needUpdatePixmap = true; d->colorModel = KisCIETongueWidget::GRAYA; d->profileDataAvailable = true; } else { return; } } void KisCIETongueWidget::setLABData(QVector whitepoint) { if (whitepoint.size()==3){ d->whitePoint = whitepoint; d->needUpdatePixmap = true; d->colorModel = KisCIETongueWidget::LABA; d->profileDataAvailable = true; } else { return; } } void KisCIETongueWidget::setYCbCrData(QVector whitepoint) { if (whitepoint.size()==3){ d->whitePoint = whitepoint; d->needUpdatePixmap = true; d->colorModel = KisCIETongueWidget::YCbCrA; d->profileDataAvailable = true; } else { return; } } void KisCIETongueWidget::setProfileDataAvailable(bool dataAvailable) { d->profileDataAvailable = dataAvailable; } void KisCIETongueWidget::mapPoint(int& icx, int& icy, QPointF xy) { icx = (int) floor((xy.x() * (d->pxcols - 1)) + .5); icy = (int) floor(((d->pxrows - 1) - xy.y() * (d->pxrows - 1)) + .5); } void KisCIETongueWidget::biasedLine(int x1, int y1, int x2, int y2) { d->painter.drawLine(x1 + d->xBias, y1, x2 + d->xBias, y2); } void KisCIETongueWidget::biasedText(int x, int y, const QString& txt) { d->painter.drawText(QPoint(d->xBias + x, y), txt); } QRgb KisCIETongueWidget::colorByCoord(double x, double y) { // Get xyz components scaled from coordinates double cx = ((double) x) / (d->pxcols - 1); double cy = 1.0 - ((double) y) / (d->pxrows - 1); double cz = 1.0 - cx - cy; // Project xyz to XYZ space. Note that in this // particular case we are substituting XYZ with xyz //Need to use KoColor here. QString space = KoColorSpaceRegistry::instance()->colorSpaceId("XYZA", "U8"); QString profile = KoColorSpaceRegistry::instance()->colorSpaceFactory(space)->defaultProfile(); const KoColorSpace* xyzColorSpace = KoColorSpaceRegistry::instance()->colorSpace("XYZA", "U8", profile); quint8 data[4]; data[0]= cx*255; data[1]= cy*255; data[2]= cz*255; data[3]= 1.0*255; KoColor colXYZ(data, xyzColorSpace); QColor colRGB = colXYZ.toQColor(); return qRgb(colRGB.red(), colRGB.green(), colRGB.blue()); } void KisCIETongueWidget::outlineTongue() { int lx=0, ly=0; int fx=0, fy=0; for (int x = 380; x <= 700; x += 5) { int ix = (x - 380) / 5; QPointF * p = new QPointF(spectral_chromaticity[ix][0], spectral_chromaticity[ix][1]); int icx, icy; mapPoint(icx, icy, * p); if (x > 380) { biasedLine(lx, ly, icx, icy); } else { fx = icx; fy = icy; } lx = icx; ly = icy; } biasedLine(lx, ly, fx, fy); } void KisCIETongueWidget::fillTongue() { QImage Img = d->cietongue.toImage(); int x; for (int y = 0; y < d->pxrows; ++y) { int xe = 0; // Find horizontal extents of tongue on this line. for (x = 0; x < d->pxcols; ++x) { if (QColor(Img.pixel(x + d->xBias, y)) != QColor(Qt::black)) { for (xe = d->pxcols - 1; xe >= x; --xe) { if (QColor(Img.pixel(xe + d->xBias, y)) != QColor(Qt::black)) { break; } } break; } } if (x < d->pxcols) { for ( ; x <= xe; ++x) { QRgb Color = colorByCoord(x, y); Img.setPixel(x + d->xBias, y, Color); } } } d->cietongue = QPixmap::fromImage(Img, Qt::AvoidDither); } void KisCIETongueWidget::drawTongueAxis() { QFont font; font.setPointSize(6); d->painter.setFont(font); d->painter.setPen(qRgb(255, 255, 255)); biasedLine(0, 0, 0, d->pxrows - 1); biasedLine(0, d->pxrows-1, d->pxcols-1, d->pxrows - 1); for (int y = 1; y <= 9; y += 1) { QString s; int xstart = (y * (d->pxcols - 1)) / 10; int ystart = (y * (d->pxrows - 1)) / 10; s.sprintf("0.%d", y); biasedLine(xstart, d->pxrows - grids(1), xstart, d->pxrows - grids(4)); biasedText(xstart - grids(11), d->pxrows + grids(15), s); s.sprintf("0.%d", 10 - y); biasedLine(0, ystart, grids(3), ystart); biasedText(grids(-25), ystart + grids(5), s); } } void KisCIETongueWidget::drawTongueGrid() { d->painter.setPen(qRgb(128, 128, 128)); d->painter.setOpacity(0.5); for (int y = 1; y <= 9; y += 1) { int xstart = (y * (d->pxcols - 1)) / 10; int ystart = (y * (d->pxrows - 1)) / 10; biasedLine(xstart, grids(4), xstart, d->pxrows - grids(4) - 1); biasedLine(grids(7), ystart, d->pxcols-1-grids(7), ystart); } d->painter.setOpacity(1.0); } void KisCIETongueWidget::drawLabels() { QFont font; font.setPointSize(5); d->painter.setFont(font); for (int x = 450; x <= 650; x += (x > 470 && x < 600) ? 5 : 10) { QString wl; int bx = 0, by = 0, tx, ty; if (x < 520) { bx = grids(-22); by = grids(2); } else if (x < 535) { bx = grids(-8); by = grids(-6); } else { bx = grids(4); } int ix = (x - 380) / 5; QPointF * p = new QPointF(spectral_chromaticity[ix][0], spectral_chromaticity[ix][1]); int icx, icy; mapPoint(icx, icy, * p); tx = icx + ((x < 520) ? grids(-2) : ((x >= 535) ? grids(2) : 0)); ty = icy + ((x < 520) ? 0 : ((x >= 535) ? grids(-1) : grids(-2))); d->painter.setPen(qRgb(255, 255, 255)); biasedLine(icx, icy, tx, ty); QRgb Color = colorByCoord(icx, icy); d->painter.setPen(Color); wl.sprintf("%d", x); biasedText(icx+bx, icy+by, wl); } } void KisCIETongueWidget::drawSmallElipse(QPointF xy, int r, int g, int b, int sz) { int icx, icy; mapPoint(icx, icy, xy); d->painter.save(); d->painter.setRenderHint(QPainter::Antialiasing); d->painter.setPen(qRgb(r, g, b)); d->painter.drawEllipse(icx + d->xBias- sz/2, icy-sz/2, sz, sz); d->painter.setPen(qRgb(r/2, g/2, b/2)); int sz2 = sz-2; d->painter.drawEllipse(icx + d->xBias- sz2/2, icy-sz2/2, sz2, sz2); d->painter.restore(); } void KisCIETongueWidget::drawColorantTriangle() { d->painter.save(); d->painter.setPen(qRgb(80, 80, 80)); d->painter.setRenderHint(QPainter::Antialiasing); if (d->colorModel ==KisCIETongueWidget::RGBA) { drawSmallElipse((QPointF(d->Primaries[0],d->Primaries[1])), 255, 128, 128, 6); drawSmallElipse((QPointF(d->Primaries[3],d->Primaries[4])), 128, 255, 128, 6); drawSmallElipse((QPointF(d->Primaries[6],d->Primaries[7])), 128, 128, 255, 6); int x1, y1, x2, y2, x3, y3; mapPoint(x1, y1, (QPointF(d->Primaries[0],d->Primaries[1])) ); mapPoint(x2, y2, (QPointF(d->Primaries[3],d->Primaries[4])) ); mapPoint(x3, y3, (QPointF(d->Primaries[6],d->Primaries[7])) ); biasedLine(x1, y1, x2, y2); biasedLine(x2, y2, x3, y3); biasedLine(x3, y3, x1, y1); } /*else if (d->colorModel ==CMYK){ for (i=0; iPrimaries.size();i+++){ drawSmallElipse((QPointF(d->Primaries[0],d->Primaries[1])), 160, 160, 160, 6);//greyscale for now //int x1, y1, x2, y2; //mapPoint(x1, y1, (QPointF(d->Primaries[i],d->Primaries[i+1])) ); //mapPoint(x2, y2, (QPointF(d->Primaries[i+3],d->Primaries[i+4])) ); //biasedLine(x1, y1, x2, y2); } } */ d->painter.restore(); } void KisCIETongueWidget::drawWhitePoint() { drawSmallElipse(QPointF (d->whitePoint[0],d->whitePoint[1]), 255, 255, 255, 8); } void KisCIETongueWidget::updatePixmap() { d->needUpdatePixmap = false; d->pixmap = QPixmap(size()); if (d->cieTongueNeedsUpdate){ // Draw the CIE tongue curve. I don't see why we need to redraw it every time the whitepoint and such changes so we cache it. d->cieTongueNeedsUpdate = false; d->cietongue = QPixmap(size()); d->cietongue.fill(Qt::black); d->painter.begin(&d->cietongue); int pixcols = d->pixmap.width(); int pixrows = d->pixmap.height(); d->gridside = (qMin(pixcols, pixrows)) / 512.0; d->xBias = grids(32); d->yBias = grids(20); d->pxcols = pixcols - d->xBias; d->pxrows = pixrows - d->yBias; d->painter.setBackground(QBrush(qRgb(0, 0, 0))); d->painter.setPen(qRgb(255, 255, 255)); outlineTongue(); d->painter.end(); fillTongue(); d->painter.begin(&d->cietongue); drawTongueAxis(); drawLabels(); drawTongueGrid(); d->painter.end(); } d->pixmap = d->cietongue; d->painter.begin(&d->pixmap); //draw whitepoint and colorants if (d->whitePoint[2] > 0.0) { drawWhitePoint(); } if (d->Primaries[2] != 0.0) { drawColorantTriangle(); } d->painter.end(); } void KisCIETongueWidget::paintEvent(QPaintEvent*) { QPainter p(this); // Widget is disable : drawing grayed frame. if ( !isEnabled() ) { p.fillRect(0, 0, width(), height(), palette().color(QPalette::Disabled, QPalette::Background)); QPen pen(palette().color(QPalette::Disabled, QPalette::Foreground)); pen.setStyle(Qt::SolidLine); pen.setWidth(1); p.setPen(pen); p.drawRect(0, 0, width(), height()); return; } // No profile data to show, or RAW file if (!d->profileDataAvailable) { p.fillRect(0, 0, width(), height(), palette().color(QPalette::Active, QPalette::Background)); QPen pen(palette().color(QPalette::Active, QPalette::Text)); pen.setStyle(Qt::SolidLine); pen.setWidth(1); p.setPen(pen); p.drawRect(0, 0, width(), height()); if (d->uncalibratedColor) { p.drawText(0, 0, width(), height(), Qt::AlignCenter, i18n("Uncalibrated color space")); } else { p.setPen(Qt::red); p.drawText(0, 0, width(), height(), Qt::AlignCenter, i18n("No profile available...")); } return; } // Create CIE tongue if needed if (d->needUpdatePixmap) { updatePixmap(); } // draw prerendered tongue p.drawPixmap(0, 0, d->pixmap); } void KisCIETongueWidget::resizeEvent(QResizeEvent* event) { Q_UNUSED(event); setMinimumHeight(width()); setMaximumHeight(width()); d->needUpdatePixmap = true; d->cieTongueNeedsUpdate = true; } void KisCIETongueWidget::slotProgressTimerDone() { update(); d->progressTimer->start(200); } diff --git a/libs/flake/CMakeLists.txt b/libs/flake/CMakeLists.txt index e5fb412bab..b5ba4f3d70 100644 --- a/libs/flake/CMakeLists.txt +++ b/libs/flake/CMakeLists.txt @@ -1,229 +1,230 @@ project(kritaflake) include_directories(${FLAKE_INCLUDES} ) add_subdirectory(styles) add_subdirectory(tests) -add_subdirectory(pics) set(kritaflake_SRCS KoGradientHelper.cpp KoFlake.cpp KoCanvasBase.cpp KoResourceManager_p.cpp KoCanvasResourceManager.cpp KoDocumentResourceManager.cpp KoCanvasObserverBase.cpp KoCanvasSupervisor.cpp KoCutController.cpp KoCopyController.cpp KoDockFactoryBase.cpp KoDockRegistry.cpp KoDataCenterBase.cpp KoInsets.cpp KoGuidesData.cpp KoGridData.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 KoShapePainter.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 KoShapeConfigFactoryBase.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 SnapGuideConfigWidget.cpp KoShapeShadow.cpp KoSharedSavingData.cpp KoViewConverter.cpp KoInputDeviceHandler.cpp KoInputDeviceHandlerEvent.cpp KoInputDeviceHandlerRegistry.cpp KoEventAction.cpp KoEventActionFactoryBase.cpp KoEventActionRegistry.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 KoAnnotationLayoutManager.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/KoEventActionAddCommand.cpp commands/KoEventActionRemoveCommand.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/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 SnapGuideConfigWidget.ui tools/KoZoomToolWidget.ui ) +qt5_add_resources(kritaiflake_SRCS flake.qrc) + add_library(kritaflake SHARED ${kritaflake_SRCS}) generate_export_header(kritaflake BASE_NAME kritaflake) -target_link_libraries(kritaflake kritapigment kritawidgetutils kritaodf kritaundo2 KF5::WidgetsAddons KF5::IconThemes Qt5::Svg) +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 ) if(HAVE_OPENGL) target_link_libraries(kritaflake ${OPENGL_LIBRARIES} Qt5::OpenGL) endif() set_target_properties(kritaflake PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS kritaflake ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/flake/KoShapeFactoryBase.h b/libs/flake/KoShapeFactoryBase.h index 6d11fb3e35..9707c5c5e3 100644 --- a/libs/flake/KoShapeFactoryBase.h +++ b/libs/flake/KoShapeFactoryBase.h @@ -1,330 +1,329 @@ /* This file is part of the KDE project * Copyright (c) 2006 Boudewijn Rempt (boud@valdyas.org) * Copyright (C) 2006-2007 Thomas Zander * Copyright (C) 2008 Thorsten Zachmann * * 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 KOSHAPEFACTORYBASE_H #define KOSHAPEFACTORYBASE_H #include #include #include #include #include "kritaflake_export.h" #include class KoShape; class KoProperties; class KoShapeConfigFactoryBase; class KoShapeConfigWidgetBase; class KoShapeLoadingContext; class KoDocumentResourceManager; #define SHAPETEMPLATE_MIMETYPE "application/x-flake-shapetemplate" #define SHAPEID_MIMETYPE "application/x-flake-shapeId" /** * Contains a KoProperties object that describes the settings of a * particular variant of a shape object, together with a name, a description * and an icon for use in the user interface. */ struct KRITAFLAKE_EXPORT KoShapeTemplate { KoShapeTemplate() { properties = 0; } QString id; ///< The id of the shape QString templateId; ///< The id of this particular template - only has to be unique with the shape QString name; ///< The name to be shown for this template QString family; ///< The family of the shape (possible values are: "funny","arrow") QString toolTip; ///< The tooltip text for the template QString iconName; ///< Icon name /** * The properties which, when passed to the KoShapeFactoryBase::createShape() method * result in the shape this template represents. */ const KoProperties *properties; }; /** * A factory for KoShape objects. * The baseclass for all shape plugins. Each plugin that ships a KoShape should also * ship a factory. That factory will extend this class and set variable data like * a toolTip and icon in the constructor of that extending class. * * An example usage would be: @code class MyShapeFactory : public KoShapeFactoryBase { public: MyShapeFactory() : KoShapeFactoryBase("MyShape", i18n("My Shape")) { setToolTip(i18n("A nice shape")); } ~MyShapeFactory() {} // more methods here }; @endcode * After you created the factory you should create a plugin that can announce the factory to the * KoShapeRegistry. See the KoPluginLoader as well. */ class KRITAFLAKE_EXPORT KoShapeFactoryBase : public QObject { Q_OBJECT public: /** * Create the new factory * @param id a string that will be used internally for referencing the shape, for * example for use by the KoToolBase::activateTemporary. * @param name the user visible name of the shape this factory creates. */ KoShapeFactoryBase(const QString &id, const QString &name, const QString &deferredPluginName = QString()); virtual ~KoShapeFactoryBase(); /** * Create a list of option panels to show on creating a new shape. * The shape type this factory creates may have general or specific setting panels * that will be shown after inserting a new shape. * The first item in the list will be shown as the first tab in the list of panels, * behind all app specific panels. * This is a separate list as set by setOptionPanels() and fetched by panelFactories() */ virtual QList createShapeOptionPanels() { return QList(); } /** * Set app specific panel factories to show config options after creating a new shape. * The application that lets the user create shapes is able to set option * widgets that will be shown after the user inserted a new shape of the * type that this factory presents. * Example: * @code * // Init shape Factories with our frame based configuration panels. * QList panels; * panels.append(new AppConfigFactory()); // insert some factory * foreach(QString id, KoShapeRegistry::instance()->keys()) * KoShapeRegistry::instance()->value(id)->setOptionPanels(panels); * @endcode * @see panelFactories() */ void setOptionPanels(const QList &panelFactories); /** * Return the app-specific panels. * @see setOptionPanels() */ QList panelFactories() const; /** * return the id for the shape this factory creates. * @return the id for the shape this factory creates. */ QString id() const; /** * Return all the templates this factory knows about. * Each template shows a different way to create a shape this factory is specialized in. */ QList templates() const; /** * return a translated tooltip Text for a selector of shapes * @return a translated tooltip Text */ QString toolTip() const; /** * return the basename of the icon for a selector of shapes * @return the basename of the icon for a selector of shapes */ QString iconName() const; /** * return the user visible (and translated) name to be seen by the user. * @return the user visible (and translated) name to be seen by the user. */ QString name() const; /** * return the non-visible name of the family the default shape belongs to. * @return the family name. */ QString family() const; /// lower prio means the shape is more generic and will be checked later int loadingPriority() const; /** * The list of namespaces to the supported elements the factory supports. */ QList > odfElements() const; /// returns true if this shapeFactory is able to load the ODF type /// started at argument element. ('draw:line' / 'draw:frame' / etc) virtual bool supports(const KoXmlElement &element, KoShapeLoadingContext &context) const = 0; /** * The hidden boolean requests if the shape should be hidden in the * shape selector or shown with all its templates. * The default is false * @see setHidden() */ bool hidden() const; /** * This method is called whenever there is a new document resource * manager that is created. The factory may reimplement this in * order to get existing resources or put factory specific resources in. * In case the factory creates new resources it is adviced to parent * them to the manager (which is a QObject) for memory management * purposes. * * FIXME: this method is only used by Tables. We should refactor so * it is no longer necessary. * * NOTE: this actually is also used somehow to create the imagecollection * for the picture shape? * * NOTE: we store the documentmanagers in a list, and remove them * from the list on delete. * * @param manager the new manager */ virtual void newDocumentResourceManager(KoDocumentResourceManager *manager) const; QList documentResourceManagers() const; /** * This method should be implemented by factories to create a shape that the user * gets when doing a base insert. For example from a script. The created shape * should have its values set to good defaults that the user can then adjust further if * needed. Including the KoShape:setShapeId(), with the Id from this factory * The default shape position is not relevant, it will be moved by the caller. * @param documentResources the resources manager that has all the document wide * resources which can be used to create the object. * @return a new shape * @see createShape() newDocumentResourceManager() */ virtual KoShape *createDefaultShape(KoDocumentResourceManager *documentResources = 0) const; /** * This method should be implemented by factories to create a shape based on a set of * properties that are specifically made for this shape-type. * This method should also set this factories shapeId on the shape using KoShape::setShapeId() * The default implementation just ignores 'params' and calls createDefaultShape() * @return a new shape * @param params the parameters to use when creating the shape * @param documentResources the resources manager that has all the document wide * resources which can be used to create the object. * @see createDefaultShape() newDocumentResourceManager() addTemplate() * @see KoShapeTemplate::properties */ virtual KoShape *createShape(const KoProperties *params, KoDocumentResourceManager *documentResources = 0) const; /** * This method provides the default implementation for creating a shape * from a specified xml element of an odf document. * Most derived factories do not need to reimplement this method, however if a factory * has some special requirements or does something special it is still possible. * One example is creating different shapes depending on the content of the passed * xml element. */ virtual KoShape *createShapeFromOdf(const KoXmlElement &element, KoShapeLoadingContext &context); protected: /** * Add a template with the properties of a specific type of shape this factory can generate * using the createShape() method. The factory will take ownership of the properties object * to which the member @p properties of @p params points to and destroy it only in its own destructor. * @param params the new template this factory knows to produce */ void addTemplate(const KoShapeTemplate ¶ms); /** * Set the tooltip to be used for a selector of shapes * @param tooltip the tooltip */ void setToolTip(const QString &tooltip); /** * Set an icon to be used in a selector of shapes * @param iconName the basename (without extension) of the icon - * @see KIconLoader */ void setIconName(const char *iconName); /** * Set the family name of the default shape * @param family the family name of the default shape this factory creates. * for example "funny", "arrows", "geometrics". Use "" for default */ void setFamily(const QString &family); /** * Set the loading priority for this icon; higher priority means * the shape is more specific which means it will be earlier in * the queue to try loading a particular odf element. */ void setLoadingPriority(int priority); /** * Set the namespace and element tags used for quick checking whether this shapefactory * is able to create a shape from xml identified by this element * name. * * @param nameSpace the ODF name space (like * urn:oasis:names:tc:opendocument:xmlns:text:1.0, * take it from KoXmlNS.h) * @param elementNames the name of the element itself, like "path" * */ void setXmlElementNames(const QString &nameSpace, const QStringList &elementNames); /** * Set the namespaces and according element tags used for quick checking whether this shapefactory * is able to create a shape from xml identified by this element * name. * * @param elementNamesList containing a list of namespace (like * urn:oasis:names:tc:opendocument:xmlns:text:1.0, * take it from KoXmlNS.h) to a list of elementName of the element itself, like "path" */ void setXmlElements(const QList > &elementNamesList); /** * The hidden boolean requests if the shape should be hidden in the * shape selector or shown with all its templates. * The default is false * @see hidden() */ void setHidden(bool hidden); private: void getDeferredPlugin(); private Q_SLOTS: /// called whenever a document KoDocumentResourceManager is deleted void pruneDocumentResourceManager(QObject *); private: class Private; Private * const d; }; #endif diff --git a/libs/flake/KoToolFactoryBase.h b/libs/flake/KoToolFactoryBase.h index 58d85b5bab..842c74fc74 100644 --- a/libs/flake/KoToolFactoryBase.h +++ b/libs/flake/KoToolFactoryBase.h @@ -1,238 +1,237 @@ /* This file is part of the KDE project * Copyright (c) 2004 Boudewijn Rempt * Copyright (C) 2006 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. */ #ifndef KO_TOOL_FACTORY_H #define KO_TOOL_FACTORY_H #include "kritaflake_export.h" #include class KoCanvasBase; class KoToolBase; class QKeySequence; /** * A factory for KoToolBase objects. * The baseclass for all tool plugins. Each plugin that ships a KoToolBase should also * ship a factory. That factory will extend this class and set variable data like * a toolTip and icon in the constructor of that extending class. * * An example usage would be:
 class MyToolFactory : public KoToolFactoryBase {
 public:
     MyToolFactory(const QStringList&)
         : KoToolFactoryBase("MyTool") {
         setToolTip(i18n("Create object"));
         setToolType("dynamic");
         setPriority(5);
     }
     ~MyToolFactory() {}
     KoToolBase *createTool(KoCanvasBase *canvas);
 };
 K_PLUGIN_FACTORY_WITH_JSON((MyToolFactoryFactory, "mytool.json", registerPlugin();)
 
*/ class KRITAFLAKE_EXPORT KoToolFactoryBase { public: /** * Create the new factory * @param id a string that will be used internally for referencing the tool, for * example for use by the KoToolBase::activateTemporary. */ explicit KoToolFactoryBase(const QString &id); virtual ~KoToolFactoryBase(); /** * Instantiate a new tool * @param canvas the canvas that the new tool will work on. Should be passed * to the constructor of the tool. * @return a new KoToolBase instance, or zero if the tool doesn't want to show up. */ virtual KoToolBase *createTool(KoCanvasBase *canvas) = 0; /** * return the id for the tool this factory creates. * @return the id for the tool this factory creates. */ QString id() const; /** * Returns The priority of this tool in its section in the toolbox * @return The priority of this tool. */ int priority() const; /** * returns the type of tool, used to group tools in the toolbox * @return the type of tool */ QString toolType() const; /** * return a translated tooltip Text * @return a translated tooltip Text */ QString toolTip() const; /** * return the basename of the icon for this tool * @return the basename of the icon for this tool */ QString iconName() const; /** * Return the id of the shape we can process. * This is the shape Id the tool we create is associated with. So a TextTool for a TextShape. * In combination with the toolType the following situations can occur;
TypeshapeIdResult
'main' Foo Tool will always be visible, but only active when shape with shapeId 'Foo' is in the selection.
'main' '' Tool will always be visible, but only active when at least one shape is selected
'main' 'flake/always' Tool will always be visible and enabled.
'main' 'flake/edit' Tool will be visible no matter which shape is selected (if any), but only be enabled when the current layer is editable.
'dynamic' Foo Tool will only be visible when shape with shapeId 'Foo' is in the selection.
'dynamic' '' Tool will always be visible. We recommend you don't use this one.
"comma separated list of application names" see main type Similar to the 'main' item if the application name matches with the current application. Otherwise it's similar to 'dynamic', but segmented in its own section. If the list includes 'dynamic' it's even added to the dynamic section, when not matching the application name
'other' any similar to the 'dynamic' items, but segmented in its own section.
n/a /always An activation shape id ending with '/always' will make the tool always visible and enabled.
* @see KoShapeFactoryBase::shapeId() * @see setActivationShapeId() * @return the id of a shape, or an empty string for all shapes. */ QString activationShapeId() const; /** * Return the default keyboard shortcut for activation of this tool (if * the shape this tool belongs to is active). * * @return the shortcut */ QKeySequence shortcut() const; /** * Returns the main toolType * Each tool has a toolType which it uses to be grouped in the toolbox. * The predefined areas are main and dynamic. "main" tools are always * shown. * * @see toolType() * @see setToolType() */ static QString mainToolType() { return "main"; } /** * Returns the navigation toolType * Each tool has a toolType which it uses to be grouped in the toolbox. * The predefined areas are main and dynamic. "navigation" tools are always * shown and are for tools that change the settings of the canvas, zoom, pan... * * @see toolType() * @see setToolType() */ static QString navigationToolType() { return "navigation"; } /** * Returns the dynamic toolType * Each tool has a toolType which it uses to be grouped in the toolbox. * The predefined areas are main and dynamic. Dynamic tools are hidden * until the shape they belong to is activated. * * @see toolType() * @see setToolType() */ static QString dynamicToolType() { return "dynamic"; } /** * Set the default shortcut for activation of this tool. */ void setShortcut(const QKeySequence & shortcut); protected: /** * Set the tooltip to be used for this tool * @param tooltip the tooltip */ void setToolTip(const QString &tooltip); /** * Set the toolType. used to group tools in the toolbox * @param toolType the toolType */ void setToolType(const QString &toolType); /** * Set an icon to be used in the toolBox. * @param iconName the basename (without extension) of the icon - * @see KIconLoader */ void setIconName(const char *iconName); void setIconName(const QString &iconName); /** * Set the priority of this tool, as it is shown in the toolBox; lower number means * it will be show more to the front of the list. * @param newPriority the priority */ void setPriority(int newPriority); /** * Set the id of the shape we can process. * This is the Id, as passed to the constructor of a KoShapeFactoryBase, that the tool * we create is associated with. This means that if a KoTextShape is selected, then * all tools that have its id set here will be added to the dynamic part of the toolbox. * @param activationShapeId the Id of the shape * @see activationShapeId() */ void setActivationShapeId(const QString &activationShapeId); private: class Private; Private * const d; }; #endif diff --git a/libs/flake/KoUnavailShape.cpp b/libs/flake/KoUnavailShape.cpp index 6f65db6a13..0e0494f36b 100644 --- a/libs/flake/KoUnavailShape.cpp +++ b/libs/flake/KoUnavailShape.cpp @@ -1,656 +1,656 @@ /* This file is part of the KDE project * * Copyright (C) 2010-2011 Inge Wallin * * 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. */ // Own #include "KoUnavailShape.h" // Qt #include #include #include #include #include #include #include #include #include // Calligra #include #include #include #include #include #include #include #include #include "KoShapeLoadingContext.h" #include "KoShapeSavingContext.h" #include "KoShapeContainerDefaultModel.h" #include "KoShapeBackground.h" #include // The XML of a frame looks something like this: // // 1. // 2. // 3. // 4. // // or // // 1. // 2. ...inline xml here... // 3. // 4. // // We define each Xml statement on lines 2 and 3 above as an "object". // (Strictly only the first child element is an object in the ODF sense, // but we have to have some terminology here.) // // In an ODF frame, only the first line, i.e. the first object // contains the real contents. All the rest of the objects are used / // shown if we cannot handle the first one. The most common cases are // that there is only one object inside the frame OR that there are 2 // and the 2nd is a picture. // // Sometimes, e.g. in the case of an embedded document, the reference // points not to a file but to a directory structure inside the ODF // store. // // When we load and save in the UnavailShape, we have to be general // enough to cover all possible cases of references and inline XML, // embedded files and embedded directory structures. // // We also have to be careful because we cannot reuse the object names // that are in the original files when saving. Instead we need to // create new object names because the ones that were used in the // original file may already be used by other embedded files/objects // that are saved by other shapes. // // FIXME: There should only be ONE place where new object / file names // are generated, not 2(?) like there are now: // KoEmbeddedDocumentSaver and the KoImageCollection. // // An ObjectEntry is used to store information about objects in the // frame, as defined above. struct ObjectEntry { QByteArray objectXmlContents; // the XML tree in the object QString objectName; // object name in the frame without "./" // This is extracted from objectXmlContents. bool isDir; KoOdfManifestEntry *manifestEntry; // manifest entry for the above. }; // A FileEntry is used to store information about embedded files // inside (i.e. referred to by) an object. struct FileEntry { QString path; // Normalized filename, i.e. without "./". QString mimeType; bool isDir; QByteArray contents; }; class KoUnavailShape::Private { public: Private(KoUnavailShape* qq); ~Private(); void draw(QPainter &painter) const; void drawNull(QPainter &painter) const; void storeObjects(const KoXmlElement &element); void storeXmlRecursive(const KoXmlElement &el, KoXmlWriter &writer, ObjectEntry *object, QHash &unknownNamespaces); void storeFile(const QString &filename, KoShapeLoadingContext &context); QByteArray loadFile(const QString &filename, KoShapeLoadingContext &context); // Objects inside the frame. For each file, we store: // - The XML code for the object // - Any embedded files (names, contents) that are referenced by xlink:href // - Whether they are directories, i.e. if they contain a file tree and not just one file. // - The manifest entries QList objectEntries; // Embedded files QList embeddedFiles; // List of embedded files. // Some cached values. QPixmap questionMark; QPixmap pixmapPreview; QSvgRenderer *scalablePreview; KoUnavailShape* q; }; KoUnavailShape::Private::Private(KoUnavailShape* qq) : scalablePreview(new QSvgRenderer()) , q(qq) { // Get the question mark "icon". - questionMark.load(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "krita/icons/questionmark.png")); + questionMark.load(":/questionmark.png"); } KoUnavailShape::Private::~Private() { qDeleteAll(objectEntries); qDeleteAll(embeddedFiles); // It's a QObject, but we haven't parented it. delete(scalablePreview); } // ---------------------------------------------------------------- // The main class KoUnavailShape::KoUnavailShape() : KoFrameShape( "", "" ) , KoShapeContainer(new KoShapeContainerDefaultModel()) , d(new Private(this)) { setShapeId(KoUnavailShape_SHAPEID); // Default size of the shape. KoShape::setSize( QSizeF( CM_TO_POINT( 5 ), CM_TO_POINT( 3 ) ) ); } KoUnavailShape::~KoUnavailShape() { delete d; } void KoUnavailShape::paint(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &paintContext) { applyConversion(painter, converter); // If the frame is empty, just draw a background. debugFlake << "Number of objects:" << d->objectEntries.size(); if (d->objectEntries.isEmpty()) { // But... only try to draw the background if there's one such if (background()) { QPainterPath p; p.addRect(QRectF(QPointF(), size())); background()->paint(painter, converter, paintContext, p); } } else { if(shapes().isEmpty()) { d->draw(painter); } } } void KoUnavailShape::paintComponent(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &) { Q_UNUSED(painter); Q_UNUSED(converter); } void KoUnavailShape::Private::draw(QPainter &painter) const { painter.save(); painter.setRenderHint(QPainter::Antialiasing); // Run through the previews in order of preference. Draw a placeholder // questionmark if there is no preview available for rendering. if (scalablePreview->isValid()) { QRect bounds(0, 0, q->boundingRect().width(), q->boundingRect().height()); scalablePreview->render(&painter, bounds); } else if (!pixmapPreview.isNull()) { QRect bounds(0, 0, q->boundingRect().width(), q->boundingRect().height()); painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.drawPixmap(bounds, pixmapPreview); } else if (q->shapes().isEmpty()) { // Draw a nice question mark with a frame around it if there // is no other preview image. If there is a contained image // shape, we don't need to draw anything. // Get the question mark "icon". // FIXME: We should be able to use d->questionMark here. QPixmap questionMark; - questionMark.load(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "krita/icons/questionmark.png")); + questionMark.load(":/questionmark.png"); // The size of the image is: // - the size of the shape if shapesize < 2cm // - 2 cm if 2cm <= shapesize <= 8cm // - shapesize / 4 if shapesize > 8cm qreal width = q->size().width(); qreal height = q->size().height(); qreal picSize = CM_TO_POINT(2); // Default size is 2 cm. if (width < CM_TO_POINT(2) || height < CM_TO_POINT(2)) picSize = qMin(width, height); else if (width > CM_TO_POINT(8) && height > CM_TO_POINT(8)) picSize = qMin(width, height) / qreal(4.0); painter.drawPixmap((width - picSize) / qreal(2.0), (height - picSize) / qreal(2.0), picSize, picSize, questionMark); // Draw a gray rectangle around the shape. painter.setPen(QPen(QColor(172, 196, 206))); painter.drawRect(QRectF(QPointF(0,0), q->size())); } painter.restore(); } void KoUnavailShape::Private::drawNull(QPainter &painter) const { QRectF rect(QPointF(0,0), q->size()); painter.save(); // Draw a simple cross in a rectangle just to indicate that there is something here. painter.drawLine(rect.topLeft(), rect.bottomRight()); painter.drawLine(rect.bottomLeft(), rect.topRight()); painter.restore(); } // ---------------------------------------------------------------- // Loading and Saving void KoUnavailShape::saveOdf(KoShapeSavingContext & context) const { debugFlake << "START SAVING ##################################################"; KoEmbeddedDocumentSaver &fileSaver = context.embeddedSaver(); KoXmlWriter &writer = context.xmlWriter(); writer.startElement("draw:frame"); // See also loadOdf() in loadOdfAttributes. saveOdfAttributes( context, OdfAllAttributes ); // Write the stored XML to the file, but don't reuse object names. int lap = 0; QString newName; foreach (const ObjectEntry *object, d->objectEntries) { QByteArray xmlArray(object->objectXmlContents); QString objectName(object->objectName); // Possibly empty. KoOdfManifestEntry *manifestEntry(object->manifestEntry); // Create a name for this object. If this is not the first // object, i.e. a replacement object (most likely a picture), // then reuse the name but put it in ReplacementObjects. if (++lap == 1) { // The first lap in the loop is the actual object. All // other laps are replacement objects. newName = fileSaver.getFilename("Object "); } else if (lap == 2) { newName = "ObjectReplacements/" + newName; } else // FIXME: what should replacement 2 and onwards be called? newName = newName + "_"; // If there was a previous object name, replace it with the new one. if (!objectName.isEmpty() && manifestEntry) { // FIXME: We must make a copy of the byte array here because // otherwise we won't be able to save > 1 time. xmlArray.replace(objectName.toLatin1(), newName.toLatin1()); } writer.addCompleteElement(xmlArray.data()); // If the objectName is empty, this may be inline XML. // If so, we are done now. if (objectName.isEmpty() || !manifestEntry) { continue; } // Save embedded files for this object. foreach (FileEntry *entry, d->embeddedFiles) { QString fileName(entry->path); // If we found a file for this object, we need to write it // but with the new object name instead of the old one. if (!fileName.startsWith(objectName)) continue; debugFlake << "Object name: " << objectName << "newName: " << newName << "filename: " << fileName << "isDir: " << entry->isDir; fileName.replace(objectName, newName); fileName.prepend("./"); debugFlake << "New filename: " << fileName; // FIXME: Check if we need special treatment of directories. fileSaver.saveFile(fileName, entry->mimeType.toLatin1(), entry->contents); } // Write the manifest entry for the object itself. If it's a // file, the manifest is already written by saveFile, so skip // it here. if (object->isDir) { fileSaver.saveManifestEntry(newName + '/', manifestEntry->mediaType(), manifestEntry->version()); } } writer.endElement(); // draw:frame } bool KoUnavailShape::loadOdf(const KoXmlElement &frameElement, KoShapeLoadingContext &context) { debugFlake << "START LOADING ##################################################"; //debugFlake << "Loading ODF frame in the KoUnavailShape. Element = " // << frameElement.tagName(); loadOdfAttributes(frameElement, context, OdfAllAttributes); // NOTE: We cannot use loadOdfFrame() because we want to save all // the things inside the frame, not just one of them, like // loadOdfFrame() provides. // Get the manifest. QList manifest = context.odfLoadingContext().manifestEntries(); #if 0 // Enable to show all manifest entries. debugFlake << "MANIFEST: "; foreach (KoOdfManifestEntry *entry, manifest) { debugFlake << entry->mediaType() << entry->fullPath() << entry->version(); } #endif // 1. Get the XML contents of the objects from the draw:frame. As // a side effect, this extracts the object names from all // xlink:href and stores them into d->objectNames. The saved // xml contents itself is saved into d->objectXmlContents // (QByteArray) so we can save it back from saveOdf(). d->storeObjects(frameElement); #if 1 // Debug only debugFlake << "----------------------------------------------------------------"; debugFlake << "After storeObjects():"; foreach (ObjectEntry *object, d->objectEntries) { debugFlake << "objectXmlContents: " << object->objectXmlContents << "objectName: " << object->objectName; // Note: at this point, isDir and manifestEntry are not set. #endif } // 2. Loop through the objects that were found in the frame and // save all the files associated with them. Some of the // objects are files, and some are directories. The // directories are searched and the files within are saved as // well. // // In this loop, isDir and manifestEntry of each ObjectEntry are set. bool foundPreview = false; foreach (ObjectEntry *object, d->objectEntries) { QString objectName = object->objectName; if (objectName.isEmpty()) continue; debugFlake << "Storing files for object named:" << objectName; // Try to find out if the entry is a directory. // If the object is a directory, then save all the files // inside it, otherwise save the file as it is. QString dirName = objectName + '/'; bool isDir = !context.odfLoadingContext().mimeTypeForPath(dirName).isEmpty(); if (isDir) { // A directory: the files can be found in the manifest. foreach (KoOdfManifestEntry *entry, manifest) { if (entry->fullPath() == dirName) continue; if (entry->fullPath().startsWith(dirName)) { d->storeFile(entry->fullPath(), context); } } } else { // A file: save it. d->storeFile(objectName, context); } // Get the manifest entry for this object. KoOdfManifestEntry *entry = 0; QString entryName = isDir ? dirName : objectName; for (int j = 0; j < manifest.size(); ++j) { KoOdfManifestEntry *temp = manifest.value(j); if (temp->fullPath() == entryName) { entry = new KoOdfManifestEntry(*temp); break; } } object->isDir = isDir; object->manifestEntry = entry; // If we have not already found a preview in previous times // through the loop, then see if this one may be a preview. if (!foundPreview) { debugFlake << "Attempting to load preview from " << objectName; QByteArray previewData = d->loadFile(objectName, context); // Check to see if we know the mimetype for this entry. Specifically: // 1. Check to see if the item is a loadable SVG file // FIXME: Perhaps check in the manifest first? But this // seems to work well. d->scalablePreview->load(previewData); if (d->scalablePreview->isValid()) { debugFlake << "Found scalable preview image!"; d->scalablePreview->setViewBox(d->scalablePreview->boundsOnElement("svg")); foundPreview = true; continue; } // 2. Otherwise check to see if it's a loadable pixmap file d->pixmapPreview.loadFromData(previewData); if (!d->pixmapPreview.isNull()) { debugFlake << "Found pixel based preview image!"; foundPreview = true; } } } #if 0 // Enable to get more detailed debug messages debugFlake << "Object manifest entries:"; for (int i = 0; i < d->manifestEntries.size(); ++i) { KoOdfManifestEntry *entry = d->manifestEntries.value(i); debugFlake << i << ":" << entry; if (entry) debugFlake << entry->fullPath() << entry->mediaType() << entry->version(); else debugFlake << "--"; } debugFlake << "END LOADING ####################################################"; #endif return true; } // Load the actual contents inside the frame. bool KoUnavailShape::loadOdfFrameElement(const KoXmlElement & /*element*/, KoShapeLoadingContext &/*context*/) { return true; } // ---------------------------------------------------------------- // Private functions void KoUnavailShape::Private::storeObjects(const KoXmlElement &element) { // Loop through all the child elements of the draw:frame and save them. KoXmlNode n = element.firstChild(); for (; !n.isNull(); n = n.nextSibling()) { debugFlake << "In draw:frame, node =" << n.nodeName(); // This disregards #text, but that's not in the spec anyway so // it doesn't need to be saved. if (!n.isElement()) continue; KoXmlElement el = n.toElement(); ObjectEntry *object = new ObjectEntry; QByteArray contentsTmp; QBuffer buffer(&contentsTmp); // the member KoXmlWriter writer(&buffer); // 1. Find out the objectName // Save the normalized filename, i.e. without a starting "./". // An empty string is saved if no name is found. QString name = el.attributeNS(KoXmlNS::xlink, "href", QString()); if (name.startsWith(QLatin1String("./"))) name.remove(0, 2); object->objectName = name; // 2. Copy the XML code. QHash unknownNamespaces; storeXmlRecursive(el, writer, object, unknownNamespaces); object->objectXmlContents = contentsTmp; // 3, 4: the isDir and manifestEntry members are not set here, // but initialize them anyway. . object->isDir = false; // Has to be initialized to something. object->manifestEntry = 0; objectEntries.append(object); } } void KoUnavailShape::Private::storeXmlRecursive(const KoXmlElement &el, KoXmlWriter &writer, ObjectEntry *object, QHash &unknownNamespaces) { // Start the element; // keep the name in a QByteArray so that it stays valid until end element is called. const QByteArray name(el.nodeName().toLatin1()); writer.startElement(name.constData()); // Copy all the attributes, including namespaces. QList< QPair > attributeNames = el.attributeFullNames(); for (int i = 0; i < attributeNames.size(); ++i) { QPair attrPair(attributeNames.value(i)); if (attrPair.first.isEmpty()) { writer.addAttribute(attrPair.second.toLatin1(), el.attribute(attrPair.second)); } else { // This somewhat convoluted code is because we need the // namespace, not the namespace URI. QString nsShort = KoXmlNS::nsURI2NS(attrPair.first.toLatin1()); // in case we don't find the namespace in our list create a own one and use that // so the document created on saving is valid. if (nsShort.isEmpty()) { nsShort = unknownNamespaces.value(attrPair.first); if (nsShort.isEmpty()) { nsShort = QString("ns%1").arg(unknownNamespaces.size() + 1); unknownNamespaces.insert(attrPair.first, nsShort); } QString name = QString("xmlns:") + nsShort; writer.addAttribute(name.toLatin1(), attrPair.first.toLatin1()); } QString attr(nsShort + ':' + attrPair.second); writer.addAttribute(attr.toLatin1(), el.attributeNS(attrPair.first, attrPair.second)); } } // Child elements // Loop through all the child elements of the draw:frame. KoXmlNode n = el.firstChild(); for (; !n.isNull(); n = n.nextSibling()) { if (n.isElement()) { storeXmlRecursive(n.toElement(), writer, object, unknownNamespaces); } else if (n.isText()) { writer.addTextNode(n.toText().data()/*.toUtf8()*/); } } // End the element writer.endElement(); } /** * This function stores the embedded file in an internal store - it does not save files to disk, * and thus it is named in this manner, to avoid the function being confused with functions which * save files to disk. */ void KoUnavailShape::Private::storeFile(const QString &fileName, KoShapeLoadingContext &context) { debugFlake << "Saving file: " << fileName; // Directories need to be saved too, but they don't have any file contents. if (fileName.endsWith('/')) { FileEntry *entry = new FileEntry; entry->path = fileName; entry->mimeType = context.odfLoadingContext().mimeTypeForPath(entry->path); entry->isDir = true; embeddedFiles.append(entry); } QByteArray fileContent = loadFile(fileName, context); if (fileContent.isNull()) return; // Actually store the file in the list. FileEntry *entry = new FileEntry; entry->path = fileName; if (entry->path.startsWith(QLatin1String("./"))) entry->path.remove(0, 2); entry->mimeType = context.odfLoadingContext().mimeTypeForPath(entry->path); entry->isDir = false; entry->contents = fileContent; embeddedFiles.append(entry); debugFlake << "File length: " << fileContent.size(); } QByteArray KoUnavailShape::Private::loadFile(const QString &fileName, KoShapeLoadingContext &context) { // Can't load a file which is a directory, return an invalid QByteArray if (fileName.endsWith('/')) return QByteArray(); KoStore *store = context.odfLoadingContext().store(); QByteArray fileContent; if (!store->open(fileName)) { store->close(); return QByteArray(); } int fileSize = store->size(); fileContent = store->read(fileSize); store->close(); //debugFlake << "File content: " << fileContent; return fileContent; } diff --git a/libs/flake/flake.qrc b/libs/flake/flake.qrc new file mode 100644 index 0000000000..86b5bc6b1a --- /dev/null +++ b/libs/flake/flake.qrc @@ -0,0 +1,30 @@ + + + + pics/16-actions-snap-boundingbox.png + pics/16-actions-snap-extension.png + pics/22-actions-convert-to-path.png + pics/22-actions-createpath.png + pics/22-actions-editpath.png + pics/22-actions-hand.png + pics/22-actions-path-break-point.png + pics/22-actions-path-break-segment.png + pics/22-actions-pathpoint-corner.png + pics/22-actions-pathpoint-curve.png + pics/22-actions-pathpoint-insert.png + pics/22-actions-pathpoint-join.png + pics/22-actions-pathpoint-line.png + pics/22-actions-pathpoint-merge.png + pics/22-actions-pathpoint-remove.png + pics/22-actions-pathpoint-smooth.png + pics/22-actions-pathpoint-symmetric.png + pics/22-actions-pathsegment-curve.png + pics/22-actions-pathsegment-line.png + pics/22-actions-pathshape.png + pics/questionmark.png + pics/sc-actions-snap-boundingbox.svg + pics/sc-actions-snap-extension.svg + pics/zoom_in_cursor.png + pics/zoom_out_cursor.png + + diff --git a/libs/flake/pics/CMakeLists.txt b/libs/flake/pics/CMakeLists.txt deleted file mode 100644 index cb4ff827b7..0000000000 --- a/libs/flake/pics/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -ecm_install_icons( ICONS - 16-actions-snap-boundingbox.png - 16-actions-snap-extension.png - 22-actions-convert-to-path.png - 22-actions-createpath.png - 22-actions-editpath.png - 22-actions-hand.png - 22-actions-path-break-point.png - 22-actions-path-break-segment.png - 22-actions-pathpoint-corner.png - 22-actions-pathpoint-curve.png - 22-actions-pathpoint-insert.png - 22-actions-pathpoint-join.png - 22-actions-pathpoint-line.png - 22-actions-pathpoint-merge.png - 22-actions-pathpoint-remove.png - 22-actions-pathpoint-smooth.png - 22-actions-pathpoint-symmetric.png - 22-actions-pathsegment-curve.png - 22-actions-pathsegment-line.png - 22-actions-pathshape.png - sc-actions-snap-boundingbox.svg - sc-actions-snap-extension.svg - DESTINATION ${DATA_INSTALL_DIR}/krita/icons - THEME oxygen -) - -install( FILES - zoom_in_cursor.png - zoom_out_cursor.png - questionmark.png - DESTINATION ${DATA_INSTALL_DIR}/krita/icons -) - diff --git a/libs/flake/tools/KoZoomTool.cpp b/libs/flake/tools/KoZoomTool.cpp index b6f59c580f..d4123b33f7 100644 --- a/libs/flake/tools/KoZoomTool.cpp +++ b/libs/flake/tools/KoZoomTool.cpp @@ -1,137 +1,137 @@ /* This file is part of the KDE project * * Copyright (C) 2006-2007 Thomas Zander * Copyright (C) 2006 Thorsten Zachmann * * 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 "KoZoomTool.h" #include #include "KoZoomStrategy.h" #include "KoZoomToolWidget.h" #include "KoPointerEvent.h" #include "KoCanvasBase.h" #include "KoCanvasController.h" #include KoZoomTool::KoZoomTool(KoCanvasBase *canvas) : KoInteractionTool(canvas), m_temporary(false), m_zoomInMode(true) { QPixmap inPixmap, outPixmap; - inPixmap.load(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "krita/icons/zoom_in_cursor.png")); - outPixmap.load(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "krita/icons/zoom_out_cursor.png")); + inPixmap.load(":/zoom_in_cursor.png"); + outPixmap.load(":/zoom_out_cursor.png"); m_inCursor = QCursor(inPixmap, 4, 4); m_outCursor = QCursor(outPixmap, 4, 4); } void KoZoomTool::wheelEvent(KoPointerEvent *event) { // Let KoCanvasController handle this event->ignore(); } void KoZoomTool::mouseReleaseEvent(KoPointerEvent *event) { KoInteractionTool::mouseReleaseEvent(event); if (m_temporary) { emit KoToolBase::done(); } } void KoZoomTool::mouseMoveEvent(KoPointerEvent *event) { updateCursor(event->modifiers() & Qt::ControlModifier); if (currentStrategy()) { currentStrategy()->handleMouseMove(event->point, event->modifiers()); } } void KoZoomTool::keyPressEvent(QKeyEvent *event) { event->ignore(); updateCursor(event->modifiers() & Qt::ControlModifier); } void KoZoomTool::keyReleaseEvent(QKeyEvent *event) { event->ignore(); updateCursor(event->modifiers() & Qt::ControlModifier); KoInteractionTool::keyReleaseEvent(event); } void KoZoomTool::activate(ToolActivation toolActivation, const QSet &) { m_temporary = toolActivation == TemporaryActivation; updateCursor(false); } void KoZoomTool::mouseDoubleClickEvent(KoPointerEvent *event) { mousePressEvent(event); } KoInteractionStrategy *KoZoomTool::createStrategy(KoPointerEvent *event) { KoZoomStrategy *zs = new KoZoomStrategy(this, m_controller, event->point); if (event->button() == Qt::RightButton) { if (m_zoomInMode) { zs->forceZoomOut(); } else { zs->forceZoomIn(); } } else { if (m_zoomInMode) { zs->forceZoomIn(); } else { zs->forceZoomOut(); } } return zs; } QWidget *KoZoomTool::createOptionWidget() { return new KoZoomToolWidget(this); } void KoZoomTool::setZoomInMode(bool zoomIn) { m_zoomInMode = zoomIn; updateCursor(false); } void KoZoomTool::updateCursor(bool swap) { bool setZoomInCursor = m_zoomInMode; if (swap) { setZoomInCursor = !setZoomInCursor; } if (setZoomInCursor) { useCursor(m_inCursor); } else { useCursor(m_outCursor); } } diff --git a/libs/kundo2/CMakeLists.txt b/libs/kundo2/CMakeLists.txt index 2dfc92706a..cf051ceb86 100644 --- a/libs/kundo2/CMakeLists.txt +++ b/libs/kundo2/CMakeLists.txt @@ -1,28 +1,27 @@ include_directories(${KUNDO2_INCLUDES}) set(kritaundo2_LIB_SRCS kundo2stack.cpp kundo2group.cpp kundo2view.cpp kundo2model.cpp kundo2magicstring.cpp kundo2commandextradata.cpp ) add_library(kritaundo2 SHARED ${kritaundo2_LIB_SRCS}) generate_export_header(kritaundo2 BASE_NAME kritaundo2) target_link_libraries(kritaundo2 PUBLIC kritawidgetutils - KF5::IconThemes KF5::I18n KF5::ConfigGui Qt5::Core Qt5::Widgets ) set_target_properties(kritaundo2 PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS kritaundo2 ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/widgets/CMakeLists.txt b/libs/widgets/CMakeLists.txt index f7e270fecd..da098ef8d4 100644 --- a/libs/widgets/CMakeLists.txt +++ b/libs/widgets/CMakeLists.txt @@ -1,117 +1,113 @@ add_subdirectory( tests ) include_directories(${KOWIDGETS_INCLUDES}) include_directories(${CMAKE_SOURCE_DIR}/libs/widgetutils) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(kritawidgets_LIB_SRCS KoGradientEditWidget.cpp KoResourcePaths.cpp KoVBox.cpp KoDialog.cpp KoGlobal.cpp KoZoomWidget.cpp KoTagToolButton.cpp KoTagChooserWidget.cpp KoTagFilterWidget.cpp KoResourceTaggingManager.cpp KoResourceItemChooserContextMenu.cpp KoAspectButton.cpp KoPageLayoutDialog.cpp KoPageLayoutWidget.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 KoDualColorButton.cpp KoEditColorSetDialog.cpp KoTriangleColorSelector.cpp KoResourcePopupAction.cpp KoStrokeConfigWidget.cpp KoFillConfigWidget.cpp KoShadowConfigWidget.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 KoMarkerModel.cpp KoMarkerItemDelegate.cpp KoMarkerSelector.cpp KoDockWidgetTitleBar.cpp KoDockWidgetTitleBarButton.cpp - KoViewItemContextBar.cpp - KoContextBarButton.cpp KoResourceFiltering.cpp KoResourceModelBase.cpp KoToolBoxButton.cpp KoToolBox.cpp KoToolBoxDocker.cpp KoToolBoxFactory.cpp KoToolDocker.cpp KoDocumentInfoDlg.cpp KoGlobal.cpp KoTableView.cpp - KoIconUtils.cpp - WidgetsDebug.cpp kis_url_requester.cpp ) ki18n_wrap_ui( kritawidgets_LIB_SRCS KoConfigAuthorPage.ui koDocumentInfoAboutWidget.ui koDocumentInfoAuthorWidget.ui KoEditColorSet.ui KoPageLayoutWidget.ui KoShadowConfigWidget.ui wdg_url_requester.ui ) qt5_add_resources(kritawidgets_LIB_SRCS kritawidgets.qrc) add_library(kritawidgets SHARED ${kritawidgets_LIB_SRCS}) generate_export_header(kritawidgets BASE_NAME kritawidgets) -target_link_libraries(kritawidgets kritatext kritapigment kritawidgetutils KF5::GuiAddons KF5::WidgetsAddons KF5::ConfigCore KF5::IconThemes KF5::Completion) +target_link_libraries(kritawidgets kritatext kritapigment kritawidgetutils 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 kritatext kritapigment kritawidgetutils) set_target_properties(kritawidgets PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS kritawidgets ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/widgets/KoContextBarButton.cpp b/libs/widgets/KoContextBarButton.cpp deleted file mode 100644 index bd98ff2de9..0000000000 --- a/libs/widgets/KoContextBarButton.cpp +++ /dev/null @@ -1,188 +0,0 @@ -// vim: set tabstop=4 shiftwidth=4 noexpandtab: -/* This file is part of the KDE project -Copyright 2011 Aurélien Gâteau -Copyright 2011 Paul Mendez - - 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 "KoContextBarButton.h" - -// KDE -#include -#include - -// Qt -#include -#include -#include - -/** How lighter is the border of context bar buttons */ -const int CONTEXTBAR_BORDER_LIGHTNESS = 140; - -/** How darker is the background of context bar buttons */ -const int CONTEXTBAR_BACKGROUND_DARKNESS = 80; - -/** How lighter are context bar buttons when under mouse */ -const int CONTEXTBAR_MOUSEOVER_LIGHTNESS = 120; - -/** Radius of ContextBarButtons */ -const int CONTEXTBAR_RADIUS = 50; - -KoContextBarButton::KoContextBarButton(const QString &iconName, QWidget* parent) -: QToolButton(parent) -, m_isHovered(false) -, m_fadingValue(0) -, m_fadingTimeLine(0) -{ - const int size = IconSize(KIconLoader::Small); - setIconSize(QSize(size, size)); - setAutoRaise(true); - setIcon(QIcon::fromTheme(iconName)); -} - - -KoContextBarButton::~KoContextBarButton() -{ -} - - -void KoContextBarButton::paintEvent(QPaintEvent*) -{ - QStylePainter painter(this); - painter.setRenderHint(QPainter::Antialiasing); - QStyleOptionToolButton opt; - initStyleOption(&opt); - - const QColor bgColor = palette().color(QPalette::Highlight); - QColor color = bgColor.dark(CONTEXTBAR_BACKGROUND_DARKNESS); - QColor borderColor = bgColor.light(CONTEXTBAR_BORDER_LIGHTNESS); - - if (opt.state & QStyle::State_MouseOver && opt.state & QStyle::State_Enabled) { - color = color.light(CONTEXTBAR_MOUSEOVER_LIGHTNESS); - borderColor = borderColor.lighter(CONTEXTBAR_MOUSEOVER_LIGHTNESS); - } - - const QRectF rectF = QRectF(opt.rect).adjusted(0.5, 0.5, -0.5, -0.5); - QPainterPath path; - path.addRoundRect(rectF, CONTEXTBAR_RADIUS, CONTEXTBAR_RADIUS); - - if (m_fadingValue < 255) { - color.setAlpha(m_fadingValue); - } - - // Background - painter.fillPath(path, color); - - if (opt.state & QStyle::State_Raised && opt.state & QStyle::State_Enabled) { - // Bottom shadow - QLinearGradient gradient(rectF.bottomLeft(), rectF.bottomLeft() - QPoint(0, 5)); - gradient.setColorAt(0, QColor::fromHsvF(0, 0, 0, .3)); - gradient.setColorAt(1, Qt::transparent); - painter.fillPath(path, gradient); - - // Left shadow - gradient.setFinalStop(rectF.bottomLeft() + QPoint(3, 0)); - painter.fillPath(path, gradient); - } - else { - // Top shadow - QLinearGradient gradient(rectF.topLeft(), rectF.topLeft() + QPoint(0, 5)); - gradient.setColorAt(0, QColor::fromHsvF(0, 0, 0, .3)); - gradient.setColorAt(1, Qt::transparent); - painter.fillPath(path, gradient); - - // Left shadow - gradient.setFinalStop(rectF.topLeft() + QPoint(5, 0)); - painter.fillPath(path, gradient); - } - - // Border - painter.setPen(borderColor); - painter.drawPath(path); - - // Content - painter.drawControl(QStyle::CE_ToolButtonLabel, opt); -} - -void KoContextBarButton::startFading() -{ - Q_ASSERT(!m_fadingTimeLine); - - const int duration = 300; - - m_fadingTimeLine = new QTimeLine(duration, this); - connect(m_fadingTimeLine, SIGNAL(frameChanged(int)), - this, SLOT(setFadingValue(int))); - m_fadingTimeLine->setFrameRange(0, 255); - m_fadingTimeLine->start(); - m_fadingValue = 0; -} - -void KoContextBarButton::stopFading() -{ - if (m_fadingTimeLine) { - m_fadingTimeLine->stop(); - delete m_fadingTimeLine; - m_fadingTimeLine = 0; - } - m_fadingValue = 0; -} - -void KoContextBarButton::enterEvent(QEvent *event) -{ - QToolButton::enterEvent(event); - - // if the mouse cursor is above the selection toggle, display - // it immediately without fading timer - m_isHovered = true; - if (m_fadingTimeLine) { - m_fadingTimeLine->stop(); - } - m_fadingValue = 255; - update(); -} - -void KoContextBarButton::leaveEvent(QEvent *event) -{ - QToolButton::leaveEvent(event); - - m_isHovered = false; - update(); -} - -void KoContextBarButton::setFadingValue(int value) -{ - m_fadingValue = value; - if (m_fadingValue >= 255) { - Q_ASSERT(m_fadingTimeLine); - m_fadingTimeLine->stop(); - } - update(); -} - -void KoContextBarButton::showEvent(QShowEvent *event) -{ - stopFading(); - startFading(); - QToolButton::showEvent(event); -} - -void KoContextBarButton::hideEvent(QHideEvent *event) -{ - stopFading(); - QToolButton::hideEvent(event); -} diff --git a/libs/widgets/KoContextBarButton.h b/libs/widgets/KoContextBarButton.h deleted file mode 100644 index d46c475c8b..0000000000 --- a/libs/widgets/KoContextBarButton.h +++ /dev/null @@ -1,62 +0,0 @@ -// vim: set tabstop=4 shiftwidth=4 noexpandtab: -/* This file is part of the KDE project -Copyright 2011 Aurélien Gâteau -Copyright 2011 Paul Mendez - - 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 KOCONTEXTBARBUTTON_H -#define KOCONTEXTBARBUTTON_H - -// KDE - -// Qt -#include -#include - -class QTimeLine; -/** - * A button with a special look, appears when hovering over thumbnails - */ -class KoContextBarButton : public QToolButton { - Q_OBJECT -public: - explicit KoContextBarButton(const QString &iconName, QWidget *parent = 0); - ~KoContextBarButton(); - -public Q_SLOTS: - void setFadingValue(int value); - -protected: - void paintEvent(QPaintEvent*); - virtual void enterEvent(QEvent *event); - virtual void leaveEvent(QEvent *event); - virtual void showEvent(QShowEvent *event); - virtual void hideEvent(QHideEvent *event); - - -private: - /** Starts button fading animation */ - void startFading(); - - /** Stops button fading animation */ - void stopFading(); - bool m_isHovered; - int m_fadingValue; - QTimeLine *m_fadingTimeLine; -}; - -#endif /* KOCONTEXTBARBUTTON_H */ diff --git a/libs/widgets/KoDockWidgetTitleBar.cpp b/libs/widgets/KoDockWidgetTitleBar.cpp index 22d7074761..89e5a2e0db 100644 --- a/libs/widgets/KoDockWidgetTitleBar.cpp +++ b/libs/widgets/KoDockWidgetTitleBar.cpp @@ -1,375 +1,375 @@ /* This file is part of the KDE project Copyright (c) 2007 Marijn Kruisselbrink Copyright (C) 2007 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 "KoDockWidgetTitleBar.h" #include "KoDockWidgetTitleBar_p.h" #include "KoDockWidgetTitleBarButton.h" #include #include #include #include #include #include #include #include #include #include #include static inline bool hasFeature(const QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature) { return (dockwidget->features() & feature) == feature; } KoDockWidgetTitleBar::KoDockWidgetTitleBar(QDockWidget* dockWidget) : QWidget(dockWidget), d(new Private(this)) { QDockWidget *q = dockWidget; d->floatIcon = KoIconUtils::themedIcon("docker_float"); d->floatButton = new KoDockWidgetTitleBarButton(this); d->floatButton->setIcon(d->floatIcon); connect(d->floatButton, SIGNAL(clicked()), SLOT(toggleFloating())); d->floatButton->setVisible(true); d->floatButton->setToolTip(i18nc("@info:tooltip", "Float Docker")); d->floatButton->setStyleSheet("border: 0"); d->removeIcon = KoIconUtils::themedIcon("docker_close"); d->closeButton = new KoDockWidgetTitleBarButton(this); d->closeButton->setIcon(d->removeIcon); connect(d->closeButton, SIGNAL(clicked()), q, SLOT(close())); d->closeButton->setVisible(true); d->closeButton->setToolTip(i18nc("@info:tooltip", "Close Docker")); d->closeButton->setStyleSheet("border: 0"); // border makes the header busy looking (appears on some OSs) d->openIcon = KoIconUtils::themedIcon("docker_collapse_a"); - d->closeIcon = KoIconUtils::themedIcon("docker_collapsed_b"); + d->closeIcon = KoIconUtils::themedIcon("docker_collapse_b"); d->collapseButton = new KoDockWidgetTitleBarButton(this); d->collapseButton->setIcon(d->openIcon); connect(d->collapseButton, SIGNAL(clicked()), SLOT(toggleCollapsed())); d->collapseButton->setVisible(true); d->collapsable = true; d->collapseButton->setToolTip(i18nc("@info:tooltip", "Collapse Docker")); d->collapseButton->setStyleSheet("border: 0"); d->lockIcon = KoIconUtils::themedIcon("docker_lock_a"); d->lockButton = new KoDockWidgetTitleBarButton(this); d->lockButton->setCheckable(true); d->lockButton->setIcon(d->lockIcon); connect(d->lockButton, SIGNAL(toggled(bool)), SLOT(setLocked(bool))); d->lockButton->setVisible(true); d->lockable = true; d->lockButton->setToolTip(i18nc("@info:tooltip", "Lock Docker")); d->lockButton->setStyleSheet("border: 0"); connect(dockWidget, SIGNAL(featuresChanged(QDockWidget::DockWidgetFeatures)), SLOT(featuresChanged(QDockWidget::DockWidgetFeatures))); connect(dockWidget, SIGNAL(topLevelChanged(bool)), SLOT(topLevelChanged(bool))); d->featuresChanged(0); } KoDockWidgetTitleBar::~KoDockWidgetTitleBar() { delete d; } QSize KoDockWidgetTitleBar::minimumSizeHint() const { return sizeHint(); } QSize KoDockWidgetTitleBar::sizeHint() const { if (isHidden()) { return QSize(0, 0); } QDockWidget *q = qobject_cast(parentWidget()); int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, 0, q); int fw = q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q); // get size of buttons... QSize closeSize(0, 0); if (d->closeButton && hasFeature(q, QDockWidget::DockWidgetClosable)) { closeSize = d->closeButton->sizeHint(); } QSize floatSize(0, 0); if (d->floatButton && hasFeature(q, QDockWidget::DockWidgetFloatable)) { floatSize = d->floatButton->sizeHint(); } QSize hideSize(0, 0); if (d->collapseButton && d->collapsable) { hideSize = d->collapseButton->sizeHint(); } QSize lockSize(0, 0); if (d->lockButton && d->lockable) { lockSize = d->lockButton->sizeHint(); } int buttonHeight = qMax(qMax(qMax(closeSize.height(), floatSize.height()), hideSize.height()), lockSize.height()) + 2; int buttonWidth = closeSize.width() + floatSize.width() + hideSize.width() + lockSize.width(); int height = buttonHeight; if (d->textVisibilityMode == FullTextAlwaysVisible) { // get font size QFontMetrics titleFontMetrics = q->fontMetrics(); int fontHeight = titleFontMetrics.lineSpacing() + 2 * mw; height = qMax(height, fontHeight); } /* * Calculate the width of title and add to the total width of the docker window when collapsed. */ const int titleWidth = (d->textVisibilityMode == FullTextAlwaysVisible) ? (q->fontMetrics().width(q->windowTitle()) + 2*mw) : 0; if (d->preCollapsedWidth > 0) { return QSize(d->preCollapsedWidth, height); } else { if (d->textVisibilityMode == FullTextAlwaysVisible) { return QSize(buttonWidth /*+ height*/ + 2*mw + 2*fw + titleWidth, height); } else { if (q->widget()) { return QSize(qMin(q->widget()->sizeHint().width(), buttonWidth), height); } else { return QSize(buttonWidth, height); } } } } void KoDockWidgetTitleBar::paintEvent(QPaintEvent*) { QStylePainter p(this); QDockWidget *q = qobject_cast(parentWidget()); int fw = q->isFloating() ? q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q) : 0; int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, 0, q); QStyleOptionDockWidgetV2 titleOpt; titleOpt.initFrom(q); QSize collapseButtonSize(0,0); if (d->collapsable) { collapseButtonSize = d->collapseButton->size(); } QSize lockButtonSize(0,0); if (d->lockable) { lockButtonSize = d->lockButton->size(); } titleOpt.rect = QRect(QPoint(fw + mw + collapseButtonSize.width() + lockButtonSize.width(), 0), QSize(geometry().width() - (fw * 2) - mw - collapseButtonSize.width() - lockButtonSize.width(), geometry().height())); titleOpt.title = q->windowTitle(); titleOpt.closable = hasFeature(q, QDockWidget::DockWidgetClosable); titleOpt.floatable = hasFeature(q, QDockWidget::DockWidgetFloatable); p.drawControl(QStyle::CE_DockWidgetTitle, titleOpt); } void KoDockWidgetTitleBar::resizeEvent(QResizeEvent*) { QDockWidget *q = qobject_cast(parentWidget()); int fw = q->isFloating() ? q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q) : 0; QStyleOptionDockWidgetV2 opt; opt.initFrom(q); opt.rect = QRect(QPoint(fw, fw), QSize(geometry().width() - (fw * 2), geometry().height() - (fw * 2))); opt.title = q->windowTitle(); opt.closable = hasFeature(q, QDockWidget::DockWidgetClosable); opt.floatable = hasFeature(q, QDockWidget::DockWidgetFloatable); QRect floatRect = q->style()->subElementRect(QStyle::SE_DockWidgetFloatButton, &opt, q); if (!floatRect.isNull()) d->floatButton->setGeometry(floatRect); QRect closeRect = q->style()->subElementRect(QStyle::SE_DockWidgetCloseButton, &opt, q); if (!closeRect.isNull()) d->closeButton->setGeometry(closeRect); int top = fw; if (!floatRect.isNull()) top = floatRect.y(); else if (!closeRect.isNull()) top = closeRect.y(); QSize size = d->collapseButton->size(); if (!closeRect.isNull()) { size = d->closeButton->size(); } else if (!floatRect.isNull()) { size = d->floatButton->size(); } QRect collapseRect = QRect(QPoint(fw, top), size); d->collapseButton->setGeometry(collapseRect); size = d->lockButton->size(); if (!closeRect.isNull()) { size = d->closeButton->size(); } else if (!floatRect.isNull()) { size = d->floatButton->size(); } int offset = 0; if (d->collapsable) { offset = collapseRect.width(); } QRect lockRect = QRect(QPoint(fw + 2 + offset, top), size); d->lockButton->setGeometry(lockRect); if (width() < (closeRect.width() + lockRect.width()) + 50) { d->collapsable = false; d->collapseButton->setVisible(false); d->lockButton->setVisible(false); d->lockable = false; } else { d->collapsable = d->collapsableSet; d->collapseButton->setVisible(d->collapsableSet); d->lockButton->setVisible(true); d->lockable = true; } } void KoDockWidgetTitleBar::setCollapsed(bool collapsed) { QDockWidget *q = qobject_cast(parentWidget()); if (q && q->widget() && q->widget()->isHidden() != collapsed) d->toggleCollapsed(); } void KoDockWidgetTitleBar::setLocked(bool locked) { QDockWidget *q = qobject_cast(parentWidget()); d->locked = locked; d->lockButton->blockSignals(true); d->lockButton->setChecked(locked); d->lockButton->blockSignals(false); //qDebug() << "setlocked" << q << d->locked << locked; if (locked) { d->features = q->features(); q->setFeatures(QDockWidget::NoDockWidgetFeatures); } else { q->setFeatures(d->features); } q->toggleViewAction()->setEnabled(!locked); d->closeButton->setEnabled(!locked); d->floatButton->setEnabled(!locked); d->collapseButton->setEnabled(!locked); d->updateIcons(); q->setProperty("Locked", locked); resizeEvent(0); } void KoDockWidgetTitleBar::setCollapsable(bool collapsable) { d->collapsableSet = collapsable; d->collapsable = collapsable; d->collapseButton->setVisible(collapsable); } void KoDockWidgetTitleBar::setTextVisibilityMode(TextVisibilityMode textVisibilityMode) { d->textVisibilityMode = textVisibilityMode; } void KoDockWidgetTitleBar::updateIcons() { d->updateIcons(); } void KoDockWidgetTitleBar::Private::toggleFloating() { QDockWidget *q = qobject_cast(thePublic->parentWidget()); q->setFloating(!q->isFloating()); } void KoDockWidgetTitleBar::Private::topLevelChanged(bool topLevel) { lockButton->setEnabled(!topLevel); } void KoDockWidgetTitleBar::Private::toggleCollapsed() { QDockWidget *q = qobject_cast(thePublic->parentWidget()); if (q == 0) // there does not *have* to be anything on the dockwidget. return; preCollapsedWidth = q->widget()->isHidden() ? -1 : thePublic->width(); q->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); // will be overwritten again next if (q->widget()) { q->widget()->setVisible(q->widget()->isHidden()); collapseButton->setIcon(q->widget()->isHidden() ? KoIconUtils::themedIcon("docker_collapse_b") : KoIconUtils::themedIcon("docker_collapse_a")); } } void KoDockWidgetTitleBar::Private::featuresChanged(QDockWidget::DockWidgetFeatures) { QDockWidget *q = qobject_cast(thePublic->parentWidget()); closeButton->setVisible(hasFeature(q, QDockWidget::DockWidgetClosable)); floatButton->setVisible(hasFeature(q, QDockWidget::DockWidgetFloatable)); thePublic->resizeEvent(0); } void KoDockWidgetTitleBar::Private::updateIcons() { QDockWidget *q = qobject_cast(thePublic->parentWidget()); lockIcon = (!locked) ? KoIconUtils::themedIcon("docker_lock_a") : KoIconUtils::themedIcon("docker_lock_b"); lockButton->setIcon(lockIcon); // this method gets called when switching themes, so update all of the themed icons now floatButton->setIcon(KoIconUtils::themedIcon("docker_float")); closeButton->setIcon(KoIconUtils::themedIcon("docker_close")); if (q->widget()) { collapseButton->setIcon(q->widget()->isHidden() ? KoIconUtils::themedIcon("docker_collapse_b") : KoIconUtils::themedIcon("docker_collapse_a")); } thePublic->resizeEvent(0); } //have to include this because of Q_PRIVATE_SLOT #include "moc_KoDockWidgetTitleBar.cpp" diff --git a/libs/widgets/KoViewItemContextBar.cpp b/libs/widgets/KoViewItemContextBar.cpp deleted file mode 100644 index bf25f5754f..0000000000 --- a/libs/widgets/KoViewItemContextBar.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* This file is part of the KDE project -* -* Copyright (C) 2008 Peter Penz -* Copyright (C) 2011 Paul Mendez -* -* 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 "KoViewItemContextBar.h" - -//Calligra headers -#include "KoContextBarButton.h" -#include - -//KDE headers -#include - -//Qt Headers -#include -#include -#include -#include -#include - -/** Space between the item outer rect and the context bar */ -const int CONTEXTBAR_MARGIN = 4; -const int MIN_BUTTON_WIDTH = 24; - -KoViewItemContextBar::KoViewItemContextBar(QAbstractItemView *parent) - : QObject(parent) - , m_view(parent) - , m_enabled(true) - , m_showToggleButton(true) -{ - connect(parent, SIGNAL(entered(const QModelIndex&)), - this, SLOT(slotEntered(const QModelIndex&))); - connect(parent, SIGNAL(viewportEntered()), - this, SLOT(slotViewportEntered())); - - m_ContextBar = new QWidget(m_view->viewport()); - m_ContextBar->hide(); - m_ToggleSelectionButton = new KoContextBarButton("list-add"); - - m_Layout = new QHBoxLayout(m_ContextBar); - m_Layout->setMargin(2); - m_Layout->setSpacing(2); - m_Layout->addWidget(m_ToggleSelectionButton); - - connect(m_ToggleSelectionButton, SIGNAL(clicked()), - this, SLOT(setItemSelected())); - // Hides context bar if item removed - connect(m_view->model(), SIGNAL(rowsRemoved(const QModelIndex&, int, int)), - this, SLOT(slotRowsRemoved(const QModelIndex&, int, int))); - - connect(m_view->model(), SIGNAL(modelReset()), this, SLOT(slotModelReset())); - - m_ContextBar->installEventFilter(this); - m_view->viewport()->installEventFilter(this); - m_view->setMouseTracking(true); -} - -KoViewItemContextBar::~KoViewItemContextBar() -{ -} - -bool KoViewItemContextBar::eventFilter(QObject *watched, QEvent *event) -{ - if (watched == m_view->viewport()) { - switch (event->type()) { - case QEvent::Leave: - if (m_ContextBar->isVisible()) { - m_ContextBar->hide(); - } - break; - default: - break; - } - } - return QObject::eventFilter(watched, event); -} - -void KoViewItemContextBar::slotEntered(const QModelIndex &index) -{ - const bool isSelectionCandidate = index.isValid() && - (QApplication::mouseButtons() == Qt::NoButton); - - if (!m_ContextBar || !m_enabled) { - return; - } - - m_ContextBar->hide(); - if (isSelectionCandidate) { - updateHoverUi(index); - } - else { - updateHoverUi(QModelIndex()); - } -} - -void KoViewItemContextBar::updateHoverUi(const QModelIndex &index) -{ - QModelIndex oldIndex = m_IndexUnderCursor; - m_IndexUnderCursor = index; - m_view->update(oldIndex); - - const bool isSelectionCandidate = index.isValid(); - - m_ContextBar->hide(); - if (isSelectionCandidate) { - updateToggleSelectionButton(); - const QRect rect = m_view->visualRect(m_IndexUnderCursor); - showContextBar(rect); - m_view->update(m_IndexUnderCursor); - } else { - m_ContextBar->hide(); - } -} - -void KoViewItemContextBar::showContextBar(const QRect &rect) -{ - // Center bar in FullContextBar mode, left align in - // SelectionOnlyContextBar mode - const int posX = 0; - const int posY = CONTEXTBAR_MARGIN / 4; - int numButtons = 0; - m_ContextBar->move(rect.topLeft() + QPoint(posX, posY)); - //Hide buttons if item is too small - int width = m_ToggleSelectionButton->width(); - if (!m_showToggleButton) { - m_ToggleSelectionButton->setVisible(false); - width = qMin(m_contextBarButtons.at(0)->width(), MIN_BUTTON_WIDTH); - } - for (int i=m_contextBarButtons.size()-1; i>=0; --i) { - if ((rect.width() - 2 * CONTEXTBAR_MARGIN) > ((i + 1) * width)) { - m_contextBarButtons.at(i)->setVisible(true); - numButtons++; - continue; - } - m_contextBarButtons.at(i)->setVisible(false); - } - m_ContextBar->adjustSize(); - if (numButtons > 0) { - const int centerX = (rect.width() - m_ContextBar->rect().width()) / 2; - m_ContextBar->move(rect.topLeft() + QPoint(centerX, posY)); - } - m_ContextBar->show(); -} - -void KoViewItemContextBar::slotViewportEntered() -{ - m_ContextBar->hide(); -} - -void KoViewItemContextBar::setItemSelected() -{ - emit selectionChanged(); - - if (m_IndexUnderCursor.isValid()) { - QItemSelectionModel *selModel = m_view->selectionModel(); - if (!selModel->isSelected(m_IndexUnderCursor)) { - selModel->select(m_IndexUnderCursor, QItemSelectionModel::Select); - } - else { - selModel->select(m_IndexUnderCursor, QItemSelectionModel::Deselect); - } - selModel->setCurrentIndex(m_IndexUnderCursor, QItemSelectionModel::Current); - } - updateHoverUi(m_IndexUnderCursor); -} - -void KoViewItemContextBar::slotRowsRemoved(const QModelIndex &parent, int start, int end) -{ - Q_UNUSED(parent); - Q_UNUSED(start); - Q_UNUSED(end); - if (m_ContextBar) { - m_ContextBar->hide(); - } -} - -void KoViewItemContextBar::updateToggleSelectionButton() -{ - const bool isHoveredIndexSelected = m_view->selectionModel()->isSelected(m_IndexUnderCursor); - const char *const iconName = (isHoveredIndexSelected ? koIconNameCStr("list-remove") : koIconNameCStr("list-add")); - - m_ToggleSelectionButton->setIcon(QIcon::fromTheme(QLatin1String(iconName))); - m_ToggleSelectionButton->setToolTip(isHoveredIndexSelected ? i18n("deselect item") : i18n("select item")); -} - -void KoViewItemContextBar::update() -{ - // Check if the current index is still valid and then update the context bar - if (m_view->model()->index(currentIndex().row(), currentIndex().column(), currentIndex().parent()).isValid()) { - updateHoverUi(currentIndex()); - } - else { - updateHoverUi(QModelIndex()); - } -} - -QToolButton * KoViewItemContextBar::addContextButton(const QString &text, const QString &iconName) -{ - KoContextBarButton *newContexButton = new KoContextBarButton(iconName); - newContexButton->setToolTip(text); - m_Layout->addWidget(newContexButton); - m_contextBarButtons.append(newContexButton); - return newContexButton; -} - -QModelIndex KoViewItemContextBar::currentIndex() -{ - return m_IndexUnderCursor; -} - -int KoViewItemContextBar::preferredWidth() -{ - return ((m_contextBarButtons.count()+1)*m_ToggleSelectionButton->sizeHint().width() + 2*CONTEXTBAR_MARGIN); -} - -void KoViewItemContextBar::setShowSelectionToggleButton(bool enabled) -{ - m_showToggleButton = enabled; -} - -void KoViewItemContextBar::reset() -{ - if (m_ContextBar) { - m_ContextBar->hide(); - } -} - -void KoViewItemContextBar::slotModelReset() -{ - // reset the model index so it does no longer point to suff no longer available. - m_IndexUnderCursor = QModelIndex(); -} - -void KoViewItemContextBar::enableContextBar() -{ - m_enabled = true; -} - -void KoViewItemContextBar::disableContextBar() -{ - m_enabled = false; -} diff --git a/libs/widgets/KoViewItemContextBar.h b/libs/widgets/KoViewItemContextBar.h deleted file mode 100644 index 02c115eaad..0000000000 --- a/libs/widgets/KoViewItemContextBar.h +++ /dev/null @@ -1,100 +0,0 @@ -/* This file is part of the KDE project -* -* Copyright (C) 2008 Peter Penz -* Copyright (C) 2011 Paul Mendez -* -* 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 KOVIEWITEMCONTEXTBAR_H -#define KOVIEWITEMCONTEXTBAR_H - -#include -#include "kritawidgets_export.h" -#include - -class QAbstractItemView; -class QToolButton; -class QHBoxLayout; -class QRect; - -/** - * @brief Add context buttons to items of QAbstractView subclasses - * - * Whenever an item is hovered by the mouse, a toggle button is shown - * which allows to select/deselect the current item, other buttons for - * custom actions could be added using addContextButton method. - */ -class KRITAWIDGETS_EXPORT KoViewItemContextBar : public QObject -{ - Q_OBJECT - -public: - explicit KoViewItemContextBar(QAbstractItemView *parent); - virtual ~KoViewItemContextBar(); - virtual bool eventFilter(QObject *watched, QEvent *event); - - /** - * Add a button to the context bar - * @param text to be used for button tool tip - * @param iconName or name of the icon displayed on the button - * @return a QToolButton, so it could be connected to a slot. - */ - QToolButton *addContextButton(const QString &text, const QString &iconName); - //Returns the index of the item under the mouse cursor - QModelIndex currentIndex(); - - int preferredWidth(); - void setShowSelectionToggleButton(bool enabled); - -Q_SIGNALS: - /** Is emitted if the selection has been changed by the toggle button. */ - void selectionChanged(); - -public Q_SLOTS: - /** Hide context bar */ - void reset(); - void enableContextBar(); - void disableContextBar(); - -private Q_SLOTS: - void slotEntered(const QModelIndex &index); - void slotViewportEntered(); - void setItemSelected(); - /** Hide context bar if the selectem item has been removed */ - void slotRowsRemoved(const QModelIndex &parent, int start, int end); - /** Updates contex bar buttons state*/ - void updateHoverUi(const QModelIndex& index); - void showContextBar(const QRect &rect); - /** Updates Selection Button state*/ - void updateToggleSelectionButton(); - /** Update Bar */ - void update(); - /** Called when model resets */ - void slotModelReset(); - -private: - QAbstractItemView *m_view; - bool m_enabled; - QModelIndex m_IndexUnderCursor; - QWidget *m_ContextBar; - QToolButton *m_ToggleSelectionButton; - QHBoxLayout *m_Layout; - QList m_contextBarButtons; - bool m_showToggleButton; -}; - -#endif // KOVIEWITEMCONTEXTBAR_H diff --git a/libs/widgetutils/CMakeLists.txt b/libs/widgetutils/CMakeLists.txt index 260af79cbd..2a23941943 100644 --- a/libs/widgetutils/CMakeLists.txt +++ b/libs/widgetutils/CMakeLists.txt @@ -1,102 +1,104 @@ add_subdirectory(tests) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/config) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/xmlgui) configure_file(xmlgui/config-xmlgui.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-xmlgui.h ) set(kritawidgetutils_LIB_SRCS + + KoIconUtils.cpp KoGroupButton.cpp KoProgressBar.cpp KoProgressUpdater.cpp KoUpdater.cpp KoUpdaterPrivate_p.cpp KoProperties.cpp KoFileDialog.cpp config/kcolorscheme.cpp config/kcolorschememanager.cpp config/khelpclient.cpp config/klanguagebutton.cpp config/krecentfilesaction.cpp config/kstandardaction.cpp xmlgui/kaboutkdedialog_p.cpp xmlgui/kactioncategory.cpp xmlgui/kactioncollection.cpp xmlgui/kactionconflictdetector.cpp xmlgui/kbugreport.cpp xmlgui/kcheckaccelerators.cpp xmlgui/kedittoolbar.cpp xmlgui/kgesture.cpp xmlgui/kgesturemap.cpp xmlgui/khelpmenu.cpp xmlgui/kkeysequencewidget.cpp xmlgui/kmainwindow.cpp xmlgui/kmenumenuhandler_p.cpp xmlgui/kshortcuteditwidget.cpp xmlgui/kshortcutschemeseditor.cpp xmlgui/kshortcutschemeshelper.cpp xmlgui/kshortcutsdialog.cpp xmlgui/kshortcutseditor.cpp xmlgui/kshortcutseditordelegate.cpp xmlgui/kshortcutseditoritem.cpp xmlgui/kshortcutwidget.cpp xmlgui/kswitchlanguagedialog_p.cpp xmlgui/ktoggletoolbaraction.cpp xmlgui/ktoolbar.cpp xmlgui/ktoolbarhandler.cpp xmlgui/kundoactions.cpp xmlgui/kxmlguibuilder.cpp xmlgui/kxmlguiclient.cpp xmlgui/kxmlguifactory.cpp xmlgui/kxmlguifactory_p.cpp xmlgui/kxmlguiversionhandler.cpp xmlgui/kxmlguiwindow.cpp ) if (HAVE_DBUS) set(kritawidgetutils_LIB_SRCS ${kritawidgetutils_LIB_SRCS} xmlgui/kmainwindowiface.cpp ) endif() ki18n_wrap_ui(kritawidgetutils_LIB_SRCS xmlgui/kshortcutsdialog.ui xmlgui/kshortcutwidget.ui ) qt5_add_resources(kritawidgetutils_LIB_SRCS xmlgui/kxmlgui.qrc) add_library(kritawidgetutils SHARED ${kritawidgetutils_LIB_SRCS}) generate_export_header(kritawidgetutils BASE_NAME kritawidgetutils) if (HAVE_DBUS) set (KRITA_WIDGET_UTILS_EXTRA_LIBS ${KRITA_WIDGET_UTILS_EXTRA_LIBS} Qt5::DBus) endif () target_link_libraries(kritawidgetutils PUBLIC Qt5::Widgets Qt5::Gui Qt5::Xml Qt5::Core PRIVATE Qt5::PrintSupport KF5::I18n KF5::ConfigCore KF5::CoreAddons KF5::ItemViews KF5::ConfigGui KF5::GuiAddons KF5::WidgetsAddons KF5::WindowSystem ${KRITA_WIDGET_UTILS_EXTRA_LIBS} ) set_target_properties(kritawidgetutils PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS kritawidgetutils ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/KoIcon.h b/libs/widgetutils/KoIcon.h similarity index 93% rename from KoIcon.h rename to libs/widgetutils/KoIcon.h index b4867f769f..358590a188 100644 --- a/KoIcon.h +++ b/libs/widgetutils/KoIcon.h @@ -1,59 +1,51 @@ /* This file is part of the Calligra project, made within the KDE community. Copyright 2012 Friedrich W. H. Kossebau 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 KOICON_H #define KOICON_H -// Qt - -#include -#include -#include -#include - - - +#include /** * Macros to support collecting the icons in use. * * After any change to this list of macros the file /CheckIcons.sh needs to be * updated accordingly, to ensure that the icon names of the affected macros are * still considered in the extraction. * * The naming pattern of the macros is like this: * * koIcon* returns a QIcon object * * koIconName* returns a QLatin1String (aligned with usual API where "iconName" property is of type QString) * * koIconNameCStr* returns a const char* */ /// Use these macros for icons without any issues -#define koIcon(name) (QIcon::fromTheme(QLatin1String(name))) +#define koIcon(name) (KoIconUtils::themedIcon(QLatin1String(name))) #define koIconName(name) (QLatin1String(name)) #define koIconNameCStr(name) (name) /// Use these macros if there is a proper icon missing #define koIconNeeded(comment, neededName) (QIcon::fromTheme(QLatin1String(neededName))) #define koIconNeededWithSubs(comment, neededName, substituteName) (QIcon::fromTheme(QLatin1String(substituteName))) #define koIconNameNeeded(comment, neededName) (QLatin1String(neededName)) #define koIconNameNeededWithSubs(comment, neededName, substituteName) (QLatin1String(substituteName)) #define koIconNameCStrNeeded(comment, neededName) (neededName) #define koIconNameCStrNeededWithSubs(comment, neededName, substituteName) (substituteName) #endif diff --git a/libs/widgets/KoIconUtils.cpp b/libs/widgetutils/KoIconUtils.cpp similarity index 72% rename from libs/widgets/KoIconUtils.cpp rename to libs/widgetutils/KoIconUtils.cpp index 931e0af13c..24a6839a13 100644 --- a/libs/widgets/KoIconUtils.cpp +++ b/libs/widgetutils/KoIconUtils.cpp @@ -1,85 +1,68 @@ /* * Copyright (c) 2015 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 "KoIconUtils.h" #include #include #include #include #include -#include -#include - -void initWidgetIcons() -{ - Q_INIT_RESOURCE(kritawidgets); -} - namespace KoIconUtils { QIcon themedIcon(const QString &name) { - initWidgetIcons(); - - QString realName; - // try load themed icon QColor background = qApp->palette().background().color(); bool useDarkIcons = background.value() > 100; const char * const prefix = useDarkIcons ? "dark_" : "light_"; - realName = QLatin1String(prefix) + name; + QString realName = QLatin1String(prefix) + name; - QStringList names = QStringList() << ":/pics/" + realName + ".svg" - << ":/pics/" + realName + ".png" + QStringList names = QStringList() << ":/pics/" + realName + ".png" + << ":/pics/" + realName + ".svg" + << ":/pics/" + realName + ".svgz" + << ":/pics/" + name + ".png" + << ":/pics/" + name + ".svg" + << ":/pics/" + name + ".svz" + << ":/" + realName + ".png" + << ":/" + realName + ".svg" + << ":/" + realName + ".svz" << ":/" + name - << ":/" + name + ".svg" << ":/" + name + ".png" - << ":/pics/" + name + ".svg" - << ":/pics/" + name + ".png"; + << ":/" + name + ".svg" + << ":/" + name + ".svgz" + ; foreach(const QString &resname, names) { if (QFile(resname).exists()) { QIcon icon(resname); return icon; } } -// qDebug() << ">>>>>>>" << realName << KIconLoader::global()->iconPath(realName, KIconLoader::User, true) << "\n\t" -// << name << KIconLoader::global()->iconPath(name, KIconLoader::User, true); - - if (KIconLoader::global()->iconPath(realName, KIconLoader::User, true).isEmpty()) { - realName = name; - } - - QIcon icon = QIcon(new KIconEngine(realName, KIconLoader::global())); - - // fallback - if (icon.isNull()) - icon = QIcon::fromTheme(name); - + QIcon icon = QIcon::fromTheme(name); + qDebug() << "\tfalling back on QIcon::FromTheme:" << name; return icon; - } } diff --git a/libs/widgets/KoIconUtils.h b/libs/widgetutils/KoIconUtils.h similarity index 65% rename from libs/widgets/KoIconUtils.h rename to libs/widgetutils/KoIconUtils.h index 4345224581..32dacdda1e 100644 --- a/libs/widgets/KoIconUtils.h +++ b/libs/widgetutils/KoIconUtils.h @@ -1,36 +1,55 @@ /* * Copyright (c) 2015 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. */ #ifndef __KO_ICON_UTILS_H #define __KO_ICON_UTILS_H -#include "kritawidgets_export.h" +#include "kritawidgetutils_export.h" class QIcon; class QString; namespace KoIconUtils { - /** - * Load a themed icon using its base name. Use it in - * Krita instead of previous themedIcon() - */ - KRITAWIDGETS_EXPORT QIcon themedIcon(const QString &name); + +enum StdSizes { + SizeSmall = 16, SizeSmallMedium = 22, SizeMedium = 32, SizeLarge = 48, + SizeHuge = 64, SizeEnormous = 128 +}; + +enum Group { + NoGroup = -1, + Desktop = 0, + FirstGroup = 0, + Toolbar, + MainToolbar, + Small, + Panel, + Dialog, + LastGroup, + User +}; + +/** + * Load a themed icon using its base name. Use it in + * Krita instead of previous themedIcon() + */ +KRITAWIDGETUTILS_EXPORT QIcon themedIcon(const QString &name); } #endif /* __KIS_ICON_UTILS_H */ diff --git a/libs/widgetutils/xmlgui/kedittoolbar.cpp b/libs/widgetutils/xmlgui/kedittoolbar.cpp index 98146cfc19..ff4d7332be 100644 --- a/libs/widgetutils/xmlgui/kedittoolbar.cpp +++ b/libs/widgetutils/xmlgui/kedittoolbar.cpp @@ -1,1739 +1,1621 @@ /* This file is part of the KDE libraries Copyright (C) 2000 Kurt Granroth Copyright (C) 2006 Hamish Rodda Copyright 2007 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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 "kedittoolbar.h" #include "kedittoolbar_p.h" #include "config-xmlgui.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ICONTHEMES #include #endif #include #include #include #include #include #include "kactioncollection.h" #include "kxmlguifactory.h" #include "ktoolbar.h" #include "../kxmlgui_version.h" static const char separatorstring[] = I18N_NOOP("--- separator ---"); #define SEPARATORSTRING i18n(separatorstring) //static const char *const s_XmlTypeToString[] = { "Shell", "Part", "Local", "Merged" }; typedef QList ToolBarList; namespace KDEPrivate { /** * Return a list of toolbar elements given a toplevel element */ static ToolBarList findToolBars(const QDomElement &start) { ToolBarList list; for (QDomElement elem = start; !elem.isNull(); elem = elem.nextSiblingElement()) { if (elem.tagName() == QStringLiteral("ToolBar")) { if (elem.attribute(QStringLiteral("noEdit")) != QLatin1String("true")) { list.append(elem); } } else { if (elem.tagName() != QStringLiteral("MenuBar")) { // there are no toolbars inside the menubar :) list += findToolBars(elem.firstChildElement()); // recursive } } } return list; } class XmlData { public: enum XmlType { Shell = 0, Part, Local, Merged }; explicit XmlData(XmlType xmlType, const QString &xmlFile, KActionCollection *collection) : m_isModified(false), m_xmlFile(xmlFile), m_type(xmlType), m_actionCollection(collection) { } void dump() const { #if 0 qDebug(240) << "XmlData" << this << "type" << s_XmlTypeToString[m_type] << "xmlFile:" << m_xmlFile; foreach (const QDomElement &element, m_barList) { qDebug(240) << " ToolBar:" << toolBarText(element); } if (m_actionCollection) { qDebug(240) << " " << m_actionCollection->actions().count() << "actions in the collection."; } else { qDebug(240) << " no action collection."; } #endif } QString xmlFile() const { return m_xmlFile; } XmlType type() const { return m_type; } KActionCollection *actionCollection() const { return m_actionCollection; } void setDomDocument(const QDomDocument &domDoc) { m_document = domDoc.cloneNode().toDocument(); m_barList = findToolBars(m_document.documentElement()); } // Return reference, for e.g. actionPropertiesElement() to modify the document QDomDocument &domDocument() { return m_document; } const QDomDocument &domDocument() const { return m_document; } /** * Return the text (user-visible name) of a given toolbar */ QString toolBarText(const QDomElement &it) const; bool m_isModified; ToolBarList &barList() { return m_barList; } const ToolBarList &barList() const { return m_barList; } private: ToolBarList m_barList; QString m_xmlFile; QDomDocument m_document; XmlType m_type; KActionCollection *m_actionCollection; }; QString XmlData::toolBarText(const QDomElement &it) const { const QLatin1String attrName("name"); QString name; QByteArray txt(it.namedItem(QStringLiteral("text")).toElement().text().toUtf8()); if (txt.isEmpty()) { txt = it.namedItem(QStringLiteral("text")).toElement().text().toUtf8(); } if (txt.isEmpty()) { name = it.attribute(attrName); } else { QByteArray domain = it.namedItem(QStringLiteral("text")).toElement().attribute(QStringLiteral("translationDomain")).toUtf8(); if (domain.isEmpty()) { domain = it.ownerDocument().documentElement().attribute(QStringLiteral("translationDomain")).toUtf8(); if (domain.isEmpty()) { domain = KLocalizedString::applicationDomain(); } } name = i18nd(domain.constData(), txt.constData()); } // the name of the toolbar might depend on whether or not // it is in kparts if ((m_type == XmlData::Shell) || (m_type == XmlData::Part)) { QString doc_name(m_document.documentElement().attribute(attrName)); name += QStringLiteral(" <") + doc_name + QLatin1Char('>'); } return name; } typedef QList XmlDataList; class ToolBarItem : public QListWidgetItem { public: ToolBarItem(QListWidget *parent, const QString &tag = QString(), const QString &name = QString(), const QString &statusText = QString()) : QListWidgetItem(parent), m_internalTag(tag), m_internalName(name), m_statusText(statusText), m_isSeparator(false), m_isTextAlongsideIconHidden(false) { // Drop between items, not onto items setFlags((flags() | Qt::ItemIsDragEnabled) & ~Qt::ItemIsDropEnabled); } void setInternalTag(const QString &tag) { m_internalTag = tag; } void setInternalName(const QString &name) { m_internalName = name; } void setStatusText(const QString &text) { m_statusText = text; } void setSeparator(bool sep) { m_isSeparator = sep; } void setTextAlongsideIconHidden(bool hidden) { m_isTextAlongsideIconHidden = hidden; } QString internalTag() const { return m_internalTag; } QString internalName() const { return m_internalName; } QString statusText() const { return m_statusText; } bool isSeparator() const { return m_isSeparator; } bool isTextAlongsideIconHidden() const { return m_isTextAlongsideIconHidden; } int index() const { return listWidget()->row(const_cast(this)); } private: QString m_internalTag; QString m_internalName; QString m_statusText; bool m_isSeparator; bool m_isTextAlongsideIconHidden; }; static QDataStream &operator<< (QDataStream &s, const ToolBarItem &item) { s << item.internalTag(); s << item.internalName(); s << item.statusText(); s << item.isSeparator(); s << item.isTextAlongsideIconHidden(); return s; } static QDataStream &operator>> (QDataStream &s, ToolBarItem &item) { QString internalTag; s >> internalTag; item.setInternalTag(internalTag); QString internalName; s >> internalName; item.setInternalName(internalName); QString statusText; s >> statusText; item.setStatusText(statusText); bool sep; s >> sep; item.setSeparator(sep); bool hidden; s >> hidden; item.setTextAlongsideIconHidden(hidden); return s; } //// ToolBarListWidget::ToolBarListWidget(QWidget *parent) : QListWidget(parent), m_activeList(true) { setDragDropMode(QAbstractItemView::DragDrop); // no internal moves } QMimeData *ToolBarListWidget::mimeData(const QList items) const { if (items.isEmpty()) { return 0; } QMimeData *mimedata = new QMimeData(); QByteArray data; { QDataStream stream(&data, QIODevice::WriteOnly); // we only support single selection ToolBarItem *item = static_cast(items.first()); stream << *item; } mimedata->setData(QStringLiteral("application/x-kde-action-list"), data); mimedata->setData(QStringLiteral("application/x-kde-source-treewidget"), m_activeList ? "active" : "inactive"); return mimedata; } bool ToolBarListWidget::dropMimeData(int index, const QMimeData *mimeData, Qt::DropAction action) { Q_UNUSED(action) const QByteArray data = mimeData->data(QStringLiteral("application/x-kde-action-list")); if (data.isEmpty()) { return false; } QDataStream stream(data); const bool sourceIsActiveList = mimeData->data(QStringLiteral("application/x-kde-source-treewidget")) == "active"; ToolBarItem *item = new ToolBarItem(this); // needs parent, use this temporarily stream >> *item; emit dropped(this, index, item, sourceIsActiveList); return true; } ToolBarItem *ToolBarListWidget::currentItem() const { return static_cast(QListWidget::currentItem()); } IconTextEditDialog::IconTextEditDialog(QWidget *parent) : QDialog(parent) { setWindowTitle(i18n("Change Text")); setModal(true); QVBoxLayout *layout = new QVBoxLayout; setLayout(layout); QGridLayout *grid = new QGridLayout; grid->setMargin(0); m_lineEdit = new QLineEdit(this); m_lineEdit->setClearButtonEnabled(true); QLabel *label = new QLabel(i18n("Icon te&xt:"), this); label->setBuddy(m_lineEdit); grid->addWidget(label, 0, 0); grid->addWidget(m_lineEdit, 0, 1); m_cbHidden = new QCheckBox(i18n("&Hide text when toolbar shows text alongside icons"), this); grid->addWidget(m_cbHidden, 1, 1); layout->addLayout(grid); m_buttonBox = new QDialogButtonBox(this); m_buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); layout->addWidget(m_buttonBox); connect(m_lineEdit, SIGNAL(textChanged(QString)), SLOT(slotTextChanged(QString))); m_lineEdit->setFocus(); setFixedHeight(sizeHint().height()); } void IconTextEditDialog::setIconText(const QString &text) { m_lineEdit->setText(text); } QString IconTextEditDialog::iconText() const { return m_lineEdit->text().trimmed(); } void IconTextEditDialog::setTextAlongsideIconHidden(bool hidden) { m_cbHidden->setChecked(hidden); } bool IconTextEditDialog::textAlongsideIconHidden() const { return m_cbHidden->isChecked(); } void IconTextEditDialog::slotTextChanged(const QString &text) { // Do not allow empty icon text m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.trimmed().isEmpty()); } class KEditToolBarWidgetPrivate { public: /** * * @param collection In the old-style constructor, this is the collection passed * to the KEditToolBar constructor. * In the xmlguifactory-based constructor, we let KXMLGUIClient create a dummy one, * but it probably isn't used. */ KEditToolBarWidgetPrivate(KEditToolBarWidget *widget, const QString &cName, KActionCollection *collection) : m_collection(collection), m_widget(widget), m_factory(NULL), m_loadedOnce(false) { m_componentName = cName; m_isPart = false; m_helpArea = 0L; // We want items with an icon to align with items without icon // So we use an empty QPixmap for that const int iconSize = widget->style()->pixelMetric(QStyle::PM_SmallIconSize); m_emptyIcon = QPixmap(iconSize, iconSize); m_emptyIcon.fill(Qt::transparent); } ~KEditToolBarWidgetPrivate() { } // private slots void slotToolBarSelected(int index); void slotInactiveSelectionChanged(); void slotActiveSelectionChanged(); void slotInsertButton(); void slotRemoveButton(); void slotUpButton(); void slotDownButton(); void selectActiveItem(const QString &); - void slotChangeIcon(); - void slotChangeIconText(); - void slotDropped(ToolBarListWidget *list, int index, ToolBarItem *item, bool sourceIsActiveList); void setupLayout(); void initOldStyle(const QString &file, bool global, const QString &defaultToolbar); void initFromFactory(KXMLGUIFactory *factory, const QString &defaultToolbar); void loadToolBarCombo(const QString &defaultToolbar); void loadActions(const QDomElement &elem); QString xmlFile(const QString &xml_file) const { return xml_file.isEmpty() ? m_componentName + QStringLiteral("ui.rc") : xml_file; } /** * Load in the specified XML file and dump the raw xml */ QString loadXMLFile(const QString &_xml_file) { QString raw_xml; QString xml_file = xmlFile(_xml_file); //qDebug() << "loadXMLFile xml_file=" << xml_file; if (!QDir::isRelativePath(xml_file)) { raw_xml = KXMLGUIFactory::readConfigFile(xml_file); } else { raw_xml = KXMLGUIFactory::readConfigFile(xml_file, m_componentName); } return raw_xml; } /** * Look for a given item in the current toolbar */ QDomElement findElementForToolBarItem(const ToolBarItem *item) const { //qDebug(240) << "looking for name=" << item->internalName() << "and tag=" << item->internalTag(); for (QDomNode n = m_currentToolBarElem.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement elem = n.toElement(); if ((elem.attribute(QStringLiteral("name")) == item->internalName()) && (elem.tagName() == item->internalTag())) { return elem; } } //qDebug(240) << "no item found in the DOM with name=" << item->internalName() << "and tag=" << item->internalTag(); return QDomElement(); } void insertActive(ToolBarItem *item, ToolBarItem *before, bool prepend = false); void removeActive(ToolBarItem *item); void moveActive(ToolBarItem *item, ToolBarItem *before); void updateLocal(QDomElement &elem); #ifndef NDEBUG void dump() const { XmlDataList::const_iterator xit = m_xmlFiles.begin(); for (; xit != m_xmlFiles.end(); ++xit) { (*xit).dump(); } } #endif QComboBox *m_toolbarCombo; QToolButton *m_upAction; QToolButton *m_removeAction; QToolButton *m_insertAction; QToolButton *m_downAction; //QValueList m_actionList; KActionCollection *m_collection; KEditToolBarWidget *m_widget; KXMLGUIFactory *m_factory; QString m_componentName; QPixmap m_emptyIcon; XmlData *m_currentXmlData; QDomElement m_currentToolBarElem; QString m_xmlFile; QString m_globalFile; QString m_rcFile; QDomDocument m_localDoc; ToolBarList m_barList; ToolBarListWidget *m_inactiveList; ToolBarListWidget *m_activeList; XmlDataList m_xmlFiles; QLabel *m_comboLabel; KSeparator *m_comboSeparator; QLabel *m_helpArea; - QPushButton *m_changeIcon; - QPushButton *m_changeIconText; bool m_isPart : 1; bool m_loadedOnce : 1; }; } using namespace KDEPrivate; class KEditToolBarPrivate { public: KEditToolBarPrivate(KEditToolBar *q): q(q), m_accept(false), m_global(false), m_collection(0), m_factory(0), m_widget(0) {} void init(); void _k_slotButtonClicked(QAbstractButton *button); void _k_acceptOK(bool); void _k_enableApply(bool); void okClicked(); void applyClicked(); void defaultClicked(); KEditToolBar *q; bool m_accept; // Save parameters for recreating widget after resetting toolbar bool m_global; KActionCollection *m_collection; QString m_file; QString m_defaultToolBar; KXMLGUIFactory *m_factory; KEditToolBarWidget *m_widget; QVBoxLayout *m_layout; QDialogButtonBox *m_buttonBox; }; Q_GLOBAL_STATIC(QString, s_defaultToolBarName) KEditToolBar::KEditToolBar(KActionCollection *collection, QWidget *parent) : QDialog(parent), d(new KEditToolBarPrivate(this)) { d->m_widget = new KEditToolBarWidget(collection, this); d->init(); d->m_collection = collection; } KEditToolBar::KEditToolBar(KXMLGUIFactory *factory, QWidget *parent) : QDialog(parent), d(new KEditToolBarPrivate(this)) { d->m_widget = new KEditToolBarWidget(this); d->init(); d->m_factory = factory; } void KEditToolBarPrivate::init() { m_accept = false; m_factory = 0; q->setDefaultToolBar(QString()); q->setWindowTitle(i18n("Configure Toolbars")); q->setModal(false); m_layout = new QVBoxLayout; q->setLayout(m_layout); m_layout->addWidget(m_widget); m_buttonBox = new QDialogButtonBox(q); m_buttonBox->setStandardButtons(QDialogButtonBox::RestoreDefaults | QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel); KGuiItem::assign(m_buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok()); KGuiItem::assign(m_buttonBox->button(QDialogButtonBox::Apply), KStandardGuiItem::apply()); KGuiItem::assign(m_buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); KGuiItem::assign(m_buttonBox->button(QDialogButtonBox::RestoreDefaults), KStandardGuiItem::defaults()); q->connect(m_buttonBox, SIGNAL(clicked(QAbstractButton*)), SLOT(_k_slotButtonClicked(QAbstractButton*))); q->connect(m_buttonBox, SIGNAL(rejected()), SLOT(reject())); m_layout->addWidget(m_buttonBox); q->connect(m_widget, SIGNAL(enableOk(bool)), SLOT(_k_acceptOK(bool))); q->connect(m_widget, SIGNAL(enableOk(bool)), SLOT(_k_enableApply(bool))); _k_enableApply(false); q->setMinimumSize(q->sizeHint()); } void KEditToolBar::setResourceFile(const QString &file, bool global) { d->m_file = file; d->m_global = global; d->m_widget->load(d->m_file, d->m_global, d->m_defaultToolBar); } KEditToolBar::~KEditToolBar() { delete d; s_defaultToolBarName()->clear(); } void KEditToolBar::setDefaultToolBar(const QString &toolBarName) { if (toolBarName.isEmpty()) { d->m_defaultToolBar = *s_defaultToolBarName(); } else { d->m_defaultToolBar = toolBarName; } } void KEditToolBarPrivate::_k_acceptOK(bool b) { m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(b); m_accept = b; } void KEditToolBarPrivate::_k_enableApply(bool b) { m_buttonBox->button(QDialogButtonBox::Apply)->setEnabled(b); } void KEditToolBarPrivate::defaultClicked() { if (KMessageBox::warningContinueCancel(q, i18n("Do you really want to reset all toolbars of this application to their default? The changes will be applied immediately."), i18n("Reset Toolbars"), KGuiItem(i18n("Reset"))) != KMessageBox::Continue) { return; } KEditToolBarWidget *oldWidget = m_widget; m_widget = 0; m_accept = false; if (m_factory) { foreach (KXMLGUIClient *client, m_factory->clients()) { const QString file = client->localXMLFile(); if (file.isEmpty()) { continue; } //qDebug(240) << "Deleting local xml file" << file; // << "for client" << client << typeid(*client).name(); if (QFile::exists(file)) if (!QFile::remove(file)) { qWarning() << "Could not delete" << file; } } // Reload the xml files in all clients, now that the local files are gone oldWidget->rebuildKXMLGUIClients(); m_widget = new KEditToolBarWidget(q); m_widget->load(m_factory, m_defaultToolBar); } else { int slash = m_file.lastIndexOf(QLatin1Char('/')) + 1; if (slash) { m_file = m_file.mid(slash); } const QString xml_file = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kxmlgui5/") + QCoreApplication::instance()->applicationName() + QLatin1Char('/') + m_file; if (QFile::exists(xml_file)) if (!QFile::remove(xml_file)) { qWarning() << "Could not delete " << xml_file; } m_widget = new KEditToolBarWidget(m_collection, q); q->setResourceFile(m_file, m_global); } // Copy the geometry to minimize UI flicker m_widget->setGeometry(oldWidget->geometry()); delete oldWidget; m_layout->insertWidget(0, m_widget); q->connect(m_widget, SIGNAL(enableOk(bool)), SLOT(_k_acceptOK(bool))); q->connect(m_widget, SIGNAL(enableOk(bool)), SLOT(_k_enableApply(bool))); _k_enableApply(false); emit q->newToolBarConfig(); emit q->newToolbarConfig(); // compat } void KEditToolBarPrivate::_k_slotButtonClicked(QAbstractButton *button) { QDialogButtonBox::StandardButton type = m_buttonBox->standardButton(button); switch (type) { case QDialogButtonBox::Ok: okClicked(); break; case QDialogButtonBox::Apply: applyClicked(); break; case QDialogButtonBox::RestoreDefaults: defaultClicked(); break; default: break; } } void KEditToolBarPrivate::okClicked() { if (!m_accept) { q->reject(); return; } if (!m_widget->save()) { // some error box here is needed } else { // Do not emit the "newToolBarConfig" signal again here if the "Apply" // button was already pressed and no further changes were made. if (m_buttonBox->button(QDialogButtonBox::Apply)->isEnabled()) { emit q->newToolBarConfig(); emit q->newToolbarConfig(); // compat } q->accept(); } } void KEditToolBarPrivate::applyClicked() { (void)m_widget->save(); _k_enableApply(false); emit q->newToolBarConfig(); emit q->newToolbarConfig(); // compat } void KEditToolBar::setGlobalDefaultToolBar(const char *toolbarName) { *s_defaultToolBarName() = QString::fromLatin1(toolbarName); } KEditToolBarWidget::KEditToolBarWidget(KActionCollection *collection, QWidget *parent) : QWidget(parent), d(new KEditToolBarWidgetPrivate(this, componentName(), collection)) { d->setupLayout(); } KEditToolBarWidget::KEditToolBarWidget(QWidget *parent) : QWidget(parent), d(new KEditToolBarWidgetPrivate(this, componentName(), KXMLGUIClient::actionCollection() /*create new one*/)) { d->setupLayout(); } KEditToolBarWidget::~KEditToolBarWidget() { delete d; } void KEditToolBarWidget::load(const QString &file, bool global, const QString &defaultToolBar) { d->initOldStyle(file, global, defaultToolBar); } void KEditToolBarWidget::load(KXMLGUIFactory *factory, const QString &defaultToolBar) { d->initFromFactory(factory, defaultToolBar); } void KEditToolBarWidgetPrivate::initOldStyle(const QString &resourceFile, bool global, const QString &defaultToolBar) { //TODO: make sure we can call this multiple times? if (m_loadedOnce) { return; } m_loadedOnce = true; //d->m_actionList = collection->actions(); // handle the merging if (global) { m_widget->loadStandardsXmlFile(); // ui_standards.rc } const QString localXML = loadXMLFile(resourceFile); m_widget->setXML(localXML, global ? true /*merge*/ : false); // first, get all of the necessary info for our local xml XmlData local(XmlData::Local, xmlFile(resourceFile), m_collection); QDomDocument domDoc; domDoc.setContent(localXML); local.setDomDocument(domDoc); m_xmlFiles.append(local); // then, the merged one (ui_standards + local xml) XmlData merge(XmlData::Merged, QString(), m_collection); merge.setDomDocument(m_widget->domDocument()); m_xmlFiles.append(merge); #ifndef NDEBUG dump(); #endif // now load in our toolbar combo box loadToolBarCombo(defaultToolBar); m_widget->adjustSize(); m_widget->setMinimumSize(m_widget->sizeHint()); } void KEditToolBarWidgetPrivate::initFromFactory(KXMLGUIFactory *factory, const QString &defaultToolBar) { //TODO: make sure we can call this multiple times? if (m_loadedOnce) { return; } m_loadedOnce = true; m_factory = factory; // add all of the client data bool first = true; foreach (KXMLGUIClient *client, factory->clients()) { if (client->xmlFile().isEmpty()) { continue; } XmlData::XmlType type = XmlData::Part; if (first) { type = XmlData::Shell; first = false; Q_ASSERT(!client->localXMLFile().isEmpty()); // where would we save changes?? } XmlData data(type, client->localXMLFile(), client->actionCollection()); QDomDocument domDoc = client->domDocument(); data.setDomDocument(domDoc); m_xmlFiles.append(data); //d->m_actionList += client->actionCollection()->actions(); } #ifndef NDEBUG //d->dump(); #endif // now load in our toolbar combo box loadToolBarCombo(defaultToolBar); m_widget->adjustSize(); m_widget->setMinimumSize(m_widget->sizeHint()); m_widget->actionCollection()->addAssociatedWidget(m_widget); foreach (QAction *action, m_widget->actionCollection()->actions()) { action->setShortcutContext(Qt::WidgetWithChildrenShortcut); } } bool KEditToolBarWidget::save() { //qDebug(240) << "KEditToolBarWidget::save"; XmlDataList::Iterator it = d->m_xmlFiles.begin(); for (; it != d->m_xmlFiles.end(); ++it) { // let's not save non-modified files if (!((*it).m_isModified)) { continue; } // let's also skip (non-existent) merged files if ((*it).type() == XmlData::Merged) { continue; } // Add noMerge="1" to all the menus since we are saving the merged data QDomNodeList menuNodes = (*it).domDocument().elementsByTagName(QStringLiteral("Menu")); for (int i = 0; i < menuNodes.length(); ++i) { QDomNode menuNode = menuNodes.item(i); QDomElement menuElement = menuNode.toElement(); if (menuElement.isNull()) { continue; } menuElement.setAttribute(QStringLiteral("noMerge"), QLatin1String("1")); } //qDebug() << (*it).domDocument().toString(); //qDebug(240) << "Saving " << (*it).xmlFile(); // if we got this far, we might as well just save it KXMLGUIFactory::saveConfigFile((*it).domDocument(), (*it).xmlFile()); } if (!d->m_factory) { return true; } rebuildKXMLGUIClients(); return true; } void KEditToolBarWidget::rebuildKXMLGUIClients() { if (!d->m_factory) { return; } const QList clients = d->m_factory->clients(); //qDebug(240) << "factory: " << clients.count() << " clients"; // remove the elements starting from the last going to the first if (!clients.count()) { return; } QListIterator clientIterator = clients; clientIterator.toBack(); while (clientIterator.hasPrevious()) { KXMLGUIClient *client = clientIterator.previous(); //qDebug(240) << "factory->removeClient " << client; d->m_factory->removeClient(client); } KXMLGUIClient *firstClient = clients.first(); // now, rebuild the gui from the first to the last //qDebug(240) << "rebuilding the gui"; foreach (KXMLGUIClient *client, clients) { //qDebug(240) << "updating client " << client << " " << client->componentName() << " xmlFile=" << client->xmlFile(); QString file(client->xmlFile()); // before setting ui_standards! if (!file.isEmpty()) { // passing an empty stream forces the clients to reread the XML client->setXMLGUIBuildDocument(QDomDocument()); // for the shell, merge in ui_standards.rc if (client == firstClient) { // same assumption as in the ctor: first==shell client->loadStandardsXmlFile(); } // and this forces it to use the *new* XML file client->setXMLFile(file, client == firstClient /* merge if shell */); // [we can't use reloadXML, it doesn't load ui_standards.rc] } } // Now we can add the clients to the factory // We don't do it in the loop above because adding a part automatically // adds its plugins, so we must make sure the plugins were updated first. foreach (KXMLGUIClient *client, clients) { d->m_factory->addClient(client); } } void KEditToolBarWidgetPrivate::setupLayout() { // the toolbar name combo m_comboLabel = new QLabel(i18n("&Toolbar:"), m_widget); m_toolbarCombo = new QComboBox(m_widget); m_comboLabel->setBuddy(m_toolbarCombo); m_comboSeparator = new KSeparator(m_widget); QObject::connect(m_toolbarCombo, SIGNAL(activated(int)), m_widget, SLOT(slotToolBarSelected(int))); // QPushButton *new_toolbar = new QPushButton(i18n("&New"), this); -// new_toolbar->setPixmap(BarIcon("document-new", KIconLoader::SizeSmall)); +// new_toolbar->setPixmap(BarIcon("document-new", KoIconUtils::SizeSmall)); // new_toolbar->setEnabled(false); // disabled until implemented // QPushButton *del_toolbar = new QPushButton(i18n("&Delete"), this); -// del_toolbar->setPixmap(BarIcon("edit-delete", KIconLoader::SizeSmall)); +// del_toolbar->setPixmap(BarIcon("edit-delete", KoIconUtils::SizeSmall)); // del_toolbar->setEnabled(false); // disabled until implemented // our list of inactive actions QLabel *inactive_label = new QLabel(i18n("A&vailable actions:"), m_widget); m_inactiveList = new ToolBarListWidget(m_widget); m_inactiveList->setDragEnabled(true); m_inactiveList->setActiveList(false); m_inactiveList->setMinimumSize(180, 250); m_inactiveList->setDropIndicatorShown(false); // #165663 inactive_label->setBuddy(m_inactiveList); QObject::connect(m_inactiveList, SIGNAL(itemSelectionChanged()), m_widget, SLOT(slotInactiveSelectionChanged())); QObject::connect(m_inactiveList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), m_widget, SLOT(slotInsertButton())); QObject::connect(m_inactiveList, SIGNAL(dropped(ToolBarListWidget*,int,ToolBarItem*,bool)), m_widget, SLOT(slotDropped(ToolBarListWidget*,int,ToolBarItem*,bool))); KListWidgetSearchLine *inactiveListSearchLine = new KListWidgetSearchLine(m_widget, m_inactiveList); inactiveListSearchLine->setPlaceholderText(i18n("Filter")); // our list of active actions QLabel *active_label = new QLabel(i18n("Curr&ent actions:"), m_widget); m_activeList = new ToolBarListWidget(m_widget); m_activeList->setDragEnabled(true); m_activeList->setActiveList(true); // With Qt-4.1 only setting MiniumWidth results in a 0-width icon column ... m_activeList->setMinimumSize(m_inactiveList->minimumWidth(), 100); active_label->setBuddy(m_activeList); QObject::connect(m_activeList, SIGNAL(itemSelectionChanged()), m_widget, SLOT(slotActiveSelectionChanged())); QObject::connect(m_activeList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), m_widget, SLOT(slotRemoveButton())); QObject::connect(m_activeList, SIGNAL(dropped(ToolBarListWidget*,int,ToolBarItem*,bool)), m_widget, SLOT(slotDropped(ToolBarListWidget*,int,ToolBarItem*,bool))); KListWidgetSearchLine *activeListSearchLine = new KListWidgetSearchLine(m_widget, m_activeList); activeListSearchLine->setPlaceholderText(i18n("Filter")); - // "change icon" button - m_changeIcon = new QPushButton(i18n("Change &Icon..."), m_widget); - m_changeIcon->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-icons"))); - m_changeIcon->setEnabled(m_activeList->currentItem()); - - QObject::connect(m_changeIcon, SIGNAL(clicked()), - m_widget, SLOT(slotChangeIcon())); -#ifndef HAVE_ICONTHEMES - m_changeIcon->hide(); -#endif - // "change icon text" button - m_changeIconText = new QPushButton(i18n("Change Te&xt..."), m_widget); - m_changeIconText->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename"))); - m_changeIconText->setEnabled(m_activeList->currentItem() != 0); - - QObject::connect(m_changeIconText, SIGNAL(clicked()), - m_widget, SLOT(slotChangeIconText())); - // The buttons in the middle m_upAction = new QToolButton(m_widget); m_upAction->setIcon(QIcon::fromTheme(QStringLiteral("go-up"))); m_upAction->setEnabled(false); m_upAction->setAutoRepeat(true); QObject::connect(m_upAction, SIGNAL(clicked()), m_widget, SLOT(slotUpButton())); m_insertAction = new QToolButton(m_widget); m_insertAction->setIcon(QIcon::fromTheme(QApplication::isRightToLeft() ? QStringLiteral("go-previous") : QLatin1String("go-next"))); m_insertAction->setEnabled(false); QObject::connect(m_insertAction, SIGNAL(clicked()), m_widget, SLOT(slotInsertButton())); m_removeAction = new QToolButton(m_widget); m_removeAction->setIcon(QIcon::fromTheme(QApplication::isRightToLeft() ? QStringLiteral("go-next") : QLatin1String("go-previous"))); m_removeAction->setEnabled(false); QObject::connect(m_removeAction, SIGNAL(clicked()), m_widget, SLOT(slotRemoveButton())); m_downAction = new QToolButton(m_widget); m_downAction->setIcon(QIcon::fromTheme(QStringLiteral("go-down"))); m_downAction->setEnabled(false); m_downAction->setAutoRepeat(true); QObject::connect(m_downAction, SIGNAL(clicked()), m_widget, SLOT(slotDownButton())); m_helpArea = new QLabel(m_widget); m_helpArea->setWordWrap(true); // now start with our layouts QVBoxLayout *top_layout = new QVBoxLayout(m_widget); top_layout->setMargin(0); QVBoxLayout *name_layout = new QVBoxLayout(); QHBoxLayout *list_layout = new QHBoxLayout(); QVBoxLayout *inactive_layout = new QVBoxLayout(); QVBoxLayout *active_layout = new QVBoxLayout(); - QHBoxLayout *changeIcon_layout = new QHBoxLayout(); QGridLayout *button_layout = new QGridLayout(); name_layout->addWidget(m_comboLabel); name_layout->addWidget(m_toolbarCombo); // name_layout->addWidget(new_toolbar); // name_layout->addWidget(del_toolbar); button_layout->setSpacing(0); button_layout->setRowStretch(0, 10); button_layout->addWidget(m_upAction, 1, 1); button_layout->addWidget(m_removeAction, 2, 0); button_layout->addWidget(m_insertAction, 2, 2); button_layout->addWidget(m_downAction, 3, 1); button_layout->setRowStretch(4, 10); inactive_layout->addWidget(inactive_label); inactive_layout->addWidget(inactiveListSearchLine); inactive_layout->addWidget(m_inactiveList, 1); active_layout->addWidget(active_label); active_layout->addWidget(activeListSearchLine); active_layout->addWidget(m_activeList, 1); - active_layout->addLayout(changeIcon_layout); - - changeIcon_layout->addWidget(m_changeIcon); - changeIcon_layout->addStretch(1); - changeIcon_layout->addWidget(m_changeIconText); list_layout->addLayout(inactive_layout); list_layout->addLayout(button_layout); list_layout->addLayout(active_layout); top_layout->addLayout(name_layout); top_layout->addWidget(m_comboSeparator); top_layout->addLayout(list_layout, 10); top_layout->addWidget(m_helpArea); top_layout->addWidget(new KSeparator(m_widget)); } void KEditToolBarWidgetPrivate::loadToolBarCombo(const QString &defaultToolBar) { const QLatin1String attrName("name"); // just in case, we clear our combo m_toolbarCombo->clear(); int defaultToolBarId = -1; int count = 0; // load in all of the toolbar names into this combo box XmlDataList::const_iterator xit = m_xmlFiles.constBegin(); for (; xit != m_xmlFiles.constEnd(); ++xit) { // skip the merged one in favor of the local one, // so that we can change icons // This also makes the app-defined named for "mainToolBar" appear rather than the ui_standards-defined name. if ((*xit).type() == XmlData::Merged) { continue; } // each xml file may have any number of toolbars ToolBarList::const_iterator it = (*xit).barList().begin(); for (; it != (*xit).barList().constEnd(); ++it) { const QString text = (*xit).toolBarText(*it); m_toolbarCombo->addItem(text); const QString name = (*it).attribute(attrName); if (defaultToolBarId == -1 && name == defaultToolBar) { defaultToolBarId = count; } count++; } } const bool showCombo = (count > 1); m_comboLabel->setVisible(showCombo); m_comboSeparator->setVisible(showCombo); m_toolbarCombo->setVisible(showCombo); if (defaultToolBarId == -1) { defaultToolBarId = 0; } // we want to the specified item selected and its actions loaded m_toolbarCombo->setCurrentIndex(defaultToolBarId); slotToolBarSelected(m_toolbarCombo->currentIndex()); } void KEditToolBarWidgetPrivate::loadActions(const QDomElement &elem) { const QLatin1String tagSeparator("Separator"); const QLatin1String tagMerge("Merge"); const QLatin1String tagActionList("ActionList"); const QLatin1String tagAction("Action"); const QLatin1String attrName("name"); int sep_num = 0; QString sep_name(QStringLiteral("separator_%1")); // clear our lists m_inactiveList->clear(); m_activeList->clear(); m_insertAction->setEnabled(false); m_removeAction->setEnabled(false); m_upAction->setEnabled(false); m_downAction->setEnabled(false); // We'll use this action collection KActionCollection *actionCollection = m_currentXmlData->actionCollection(); // store the names of our active actions QSet active_list; // Filtering message requested by translators (scripting). KLocalizedString nameFilter = ki18nc("@item:intable Action name in toolbar editor", "%1"); // see if our current action is in this toolbar QDomNode n = elem.firstChild(); for (; !n.isNull(); n = n.nextSibling()) { QDomElement it = n.toElement(); if (it.isNull()) { continue; } if (it.tagName() == tagSeparator) { ToolBarItem *act = new ToolBarItem(m_activeList, tagSeparator, sep_name.arg(sep_num++), QString()); act->setSeparator(true); act->setText(SEPARATORSTRING); it.setAttribute(attrName, act->internalName()); continue; } if (it.tagName() == tagMerge) { // Merge can be named or not - use the name if there is one QString name = it.attribute(attrName); ToolBarItem *act = new ToolBarItem(m_activeList, tagMerge, name, i18n("This element will be replaced with all the elements of an embedded component.")); if (name.isEmpty()) { act->setText(i18n("")); } else { act->setText(i18n("", name)); } continue; } if (it.tagName() == tagActionList) { ToolBarItem *act = new ToolBarItem(m_activeList, tagActionList, it.attribute(attrName), i18n("This is a dynamic list of actions. You can move it, but if you remove it you will not be able to re-add it.")); act->setText(i18n("ActionList: %1", it.attribute(attrName))); continue; } // iterate through this client's actions // This used to iterate through _all_ actions, but we don't support // putting any action into any client... foreach (QAction *action, actionCollection->actions()) { // do we have a match? if (it.attribute(attrName) == action->objectName()) { // we have a match! ToolBarItem *act = new ToolBarItem(m_activeList, it.tagName(), action->objectName(), action->toolTip()); act->setText(nameFilter.subs(KLocalizedString::removeAcceleratorMarker(action->iconText())).toString()); act->setIcon(!action->icon().isNull() ? action->icon() : m_emptyIcon); act->setTextAlongsideIconHidden(action->priority() < QAction::NormalPriority); active_list.insert(action->objectName()); break; } } } // go through the rest of the collection foreach (QAction *action, actionCollection->actions()) { // skip our active ones if (active_list.contains(action->objectName())) { continue; } ToolBarItem *act = new ToolBarItem(m_inactiveList, tagAction, action->objectName(), action->toolTip()); act->setText(nameFilter.subs(KLocalizedString::removeAcceleratorMarker(action->text())).toString()); act->setIcon(!action->icon().isNull() ? action->icon() : m_emptyIcon); } m_inactiveList->sortItems(Qt::AscendingOrder); // finally, add default separators to the inactive list ToolBarItem *act = new ToolBarItem(0L, tagSeparator, sep_name.arg(sep_num++), QString()); act->setSeparator(true); act->setText(SEPARATORSTRING); m_inactiveList->insertItem(0, act); } KActionCollection *KEditToolBarWidget::actionCollection() const { return d->m_collection; } void KEditToolBarWidgetPrivate::slotToolBarSelected(int index) { const QLatin1String attrName("name"); // We need to find the XmlData and toolbar element for this index // To do that, we do the same iteration as the one which filled in the combobox. int toolbarNumber = 0; XmlDataList::iterator xit = m_xmlFiles.begin(); for (; xit != m_xmlFiles.end(); ++xit) { // skip the merged one in favor of the local one, // so that we can change icons if ((*xit).type() == XmlData::Merged) { continue; } // each xml file may have any number of toolbars ToolBarList::Iterator it = (*xit).barList().begin(); for (; it != (*xit).barList().end(); ++it) { // is this our toolbar? if (toolbarNumber == index) { // save our current settings m_currentXmlData = & (*xit); m_currentToolBarElem = *it; //qDebug() << "found toolbar" << m_currentXmlData->toolBarText(*it) << "m_currentXmlData set to"; m_currentXmlData->dump(); // If this is a Merged xmldata, clicking the "change icon" button would assert... Q_ASSERT(m_currentXmlData->type() != XmlData::Merged); // load in our values loadActions(m_currentToolBarElem); if ((*xit).type() == XmlData::Part || (*xit).type() == XmlData::Shell) { m_widget->setDOMDocument((*xit).domDocument()); } return; } ++toolbarNumber; } } } void KEditToolBarWidgetPrivate::slotInactiveSelectionChanged() { if (m_inactiveList->selectedItems().count()) { m_insertAction->setEnabled(true); QString statusText = static_cast(m_inactiveList->selectedItems().first())->statusText(); m_helpArea->setText(i18nc("@label Action tooltip in toolbar editor, below the action list", "%1", statusText)); } else { m_insertAction->setEnabled(false); m_helpArea->setText(QString()); } } void KEditToolBarWidgetPrivate::slotActiveSelectionChanged() { ToolBarItem *toolitem = 0; if (!m_activeList->selectedItems().isEmpty()) { toolitem = static_cast(m_activeList->selectedItems().first()); } m_removeAction->setEnabled(toolitem); - m_changeIcon->setEnabled(toolitem && - toolitem->internalTag() == QStringLiteral("Action")); - - m_changeIconText->setEnabled(toolitem && - toolitem->internalTag() == QStringLiteral("Action")); - if (toolitem) { m_upAction->setEnabled(toolitem->index() != 0); m_downAction->setEnabled(toolitem->index() != toolitem->listWidget()->count() - 1); QString statusText = toolitem->statusText(); m_helpArea->setText(i18nc("@label Action tooltip in toolbar editor, below the action list", "%1", statusText)); } else { m_upAction->setEnabled(false); m_downAction->setEnabled(false); m_helpArea->setText(QString()); } } void KEditToolBarWidgetPrivate::slotInsertButton() { QString internalName = static_cast(m_inactiveList->currentItem())->internalName(); insertActive(m_inactiveList->currentItem(), m_activeList->currentItem(), false); // we're modified, so let this change emit m_widget->enableOk(true); slotToolBarSelected(m_toolbarCombo->currentIndex()); selectActiveItem(internalName); } void KEditToolBarWidgetPrivate::selectActiveItem(const QString &internalName) { int activeItemCount = m_activeList->count(); for (int i = 0; i < activeItemCount; i++) { ToolBarItem *item = static_cast(m_activeList->item(i)); if (item->internalName() == internalName) { m_activeList->setCurrentItem(item); break; } } } void KEditToolBarWidgetPrivate::slotRemoveButton() { removeActive(m_activeList->currentItem()); slotToolBarSelected(m_toolbarCombo->currentIndex()); } void KEditToolBarWidgetPrivate::insertActive(ToolBarItem *item, ToolBarItem *before, bool prepend) { if (!item) { return; } QDomElement new_item; // let's handle the separator specially if (item->isSeparator()) { new_item = m_widget->domDocument().createElement(QStringLiteral("Separator")); } else { new_item = m_widget->domDocument().createElement(QStringLiteral("Action")); } new_item.setAttribute(QStringLiteral("name"), item->internalName()); Q_ASSERT(!m_currentToolBarElem.isNull()); if (before) { // we have the item in the active list which is before the new // item.. so let's try our best to add our new item right after it QDomElement elem = findElementForToolBarItem(before); Q_ASSERT(!elem.isNull()); m_currentToolBarElem.insertAfter(new_item, elem); } else { // simply put it at the beginning or the end of the list. if (prepend) { m_currentToolBarElem.insertBefore(new_item, m_currentToolBarElem.firstChild()); } else { m_currentToolBarElem.appendChild(new_item); } } // and set this container as a noMerge m_currentToolBarElem.setAttribute(QStringLiteral("noMerge"), QLatin1String("1")); // update the local doc updateLocal(m_currentToolBarElem); } void KEditToolBarWidgetPrivate::removeActive(ToolBarItem *item) { if (!item) { return; } // we're modified, so let this change emit m_widget->enableOk(true); // now iterate through to find the child to nuke QDomElement elem = findElementForToolBarItem(item); if (!elem.isNull()) { // nuke myself! m_currentToolBarElem.removeChild(elem); // and set this container as a noMerge m_currentToolBarElem.setAttribute(QStringLiteral("noMerge"), QLatin1String("1")); // update the local doc updateLocal(m_currentToolBarElem); } } void KEditToolBarWidgetPrivate::slotUpButton() { ToolBarItem *item = m_activeList->currentItem(); if (!item) { Q_ASSERT(false); return; } int row = item->listWidget()->row(item) - 1; // make sure we're not the top item already if (row < 0) { Q_ASSERT(false); return; } // we're modified, so let this change emit m_widget->enableOk(true); moveActive(item, static_cast(item->listWidget()->item(row - 1))); } void KEditToolBarWidgetPrivate::moveActive(ToolBarItem *item, ToolBarItem *before) { QDomElement e = findElementForToolBarItem(item); if (e.isNull()) { return; } // remove item m_activeList->takeItem(m_activeList->row(item)); // put it where it's supposed to go m_activeList->insertItem(m_activeList->row(before) + 1, item); // make it selected again m_activeList->setCurrentItem(item); // and do the real move in the DOM if (!before) { m_currentToolBarElem.insertBefore(e, m_currentToolBarElem.firstChild()); } else { m_currentToolBarElem.insertAfter(e, findElementForToolBarItem((ToolBarItem *)before)); } // and set this container as a noMerge m_currentToolBarElem.setAttribute(QStringLiteral("noMerge"), QLatin1String("1")); // update the local doc updateLocal(m_currentToolBarElem); } void KEditToolBarWidgetPrivate::slotDownButton() { ToolBarItem *item = m_activeList->currentItem(); if (!item) { Q_ASSERT(false); return; } // make sure we're not the bottom item already int newRow = item->listWidget()->row(item) + 1; if (newRow >= item->listWidget()->count()) { Q_ASSERT(false); return; } // we're modified, so let this change emit m_widget->enableOk(true); moveActive(item, static_cast(item->listWidget()->item(newRow))); } void KEditToolBarWidgetPrivate::updateLocal(QDomElement &elem) { XmlDataList::Iterator xit = m_xmlFiles.begin(); for (; xit != m_xmlFiles.end(); ++xit) { if ((*xit).type() == XmlData::Merged) { continue; } if ((*xit).type() == XmlData::Shell || (*xit).type() == XmlData::Part) { if (m_currentXmlData->xmlFile() == (*xit).xmlFile()) { (*xit).m_isModified = true; return; } continue; } (*xit).m_isModified = true; const QLatin1String attrName("name"); ToolBarList::Iterator it = (*xit).barList().begin(); for (; it != (*xit).barList().end(); ++it) { QString name((*it).attribute(attrName)); QString tag((*it).tagName()); if ((tag != elem.tagName()) || (name != elem.attribute(attrName))) { continue; } QDomElement toolbar = (*xit).domDocument().documentElement().toElement(); toolbar.replaceChild(elem, (*it)); return; } // just append it QDomElement toolbar = (*xit).domDocument().documentElement().toElement(); Q_ASSERT(!toolbar.isNull()); toolbar.appendChild(elem); } } -void KEditToolBarWidgetPrivate::slotChangeIcon() -{ -#ifdef HAVE_ICONTHEMES - m_currentXmlData->dump(); - Q_ASSERT(m_currentXmlData->type() != XmlData::Merged); - - QString icon = KIconDialog::getIcon(KIconLoader::Toolbar, - KIconLoader::Action, - false, 0, false, // all defaults - m_widget, - i18n("Change Icon")); - - if (icon.isEmpty()) { - return; - } - - ToolBarItem *item = m_activeList->currentItem(); - //qDebug() << item; - if (item) { - item->setIcon(QIcon::fromTheme(icon)); - - m_currentXmlData->m_isModified = true; - - // Get hold of ActionProperties tag - QDomElement elem = KXMLGUIFactory::actionPropertiesElement(m_currentXmlData->domDocument()); - // Find or create an element for this action - QDomElement act_elem = KXMLGUIFactory::findActionByName(elem, item->internalName(), true /*create*/); - Q_ASSERT(!act_elem.isNull()); - act_elem.setAttribute(QStringLiteral("icon"), icon); - - // we're modified, so let this change - emit m_widget->enableOk(true); - } -#endif -} - -void KEditToolBarWidgetPrivate::slotChangeIconText() -{ - m_currentXmlData->dump(); - ToolBarItem *item = m_activeList->currentItem(); - - if (item) { - QString iconText = item->text(); - bool hidden = item->isTextAlongsideIconHidden(); - - IconTextEditDialog dialog(m_widget); - dialog.setIconText(iconText); - dialog.setTextAlongsideIconHidden(hidden); - - bool ok = dialog.exec() == QDialog::Accepted; - iconText = dialog.iconText(); - hidden = dialog.textAlongsideIconHidden(); - - bool hiddenChanged = hidden != item->isTextAlongsideIconHidden(); - bool iconTextChanged = iconText != item->text(); - - if (!ok || (!hiddenChanged && !iconTextChanged)) { - return; - } - - item->setText(iconText); - item->setTextAlongsideIconHidden(hidden); - - Q_ASSERT(m_currentXmlData->type() != XmlData::Merged); - - m_currentXmlData->m_isModified = true; - - // Get hold of ActionProperties tag - QDomElement elem = KXMLGUIFactory::actionPropertiesElement(m_currentXmlData->domDocument()); - // Find or create an element for this action - QDomElement act_elem = KXMLGUIFactory::findActionByName(elem, item->internalName(), true /*create*/); - Q_ASSERT(!act_elem.isNull()); - if (iconTextChanged) { - act_elem.setAttribute(QString::fromLatin1("iconText"), iconText); - } - if (hiddenChanged) { - act_elem.setAttribute(QString::fromLatin1("priority"), hidden ? QAction::LowPriority : QAction::NormalPriority); - } - - // we're modified, so let this change - emit m_widget->enableOk(true); - } -} void KEditToolBarWidgetPrivate::slotDropped(ToolBarListWidget *list, int index, ToolBarItem *item, bool sourceIsActiveList) { //qDebug() << "slotDropped list=" << (list==m_activeList?"activeList":"inactiveList") // << "index=" << index << "sourceIsActiveList=" << sourceIsActiveList; if (list == m_activeList) { ToolBarItem *after = index > 0 ? static_cast(list->item(index - 1)) : 0; //qDebug() << "after" << after->text() << after->internalTag(); if (sourceIsActiveList) { // has been dragged within the active list (moved). moveActive(item, after); } else { // dragged from the inactive list to the active list insertActive(item, after, true); } } else if (list == m_inactiveList) { // has been dragged to the inactive list -> remove from the active list. removeActive(item); } delete item; // not needed anymore. must be deleted before slotToolBarSelected clears the lists // we're modified, so let this change emit m_widget->enableOk(true); slotToolBarSelected(m_toolbarCombo->currentIndex()); } void KEditToolBar::showEvent(QShowEvent *event) { if (!event->spontaneous()) { // The dialog has been shown, enable toolbar editing if (d->m_factory) { // call the xmlgui-factory version d->m_widget->load(d->m_factory, d->m_defaultToolBar); } else { // call the action collection version d->m_widget->load(d->m_file, d->m_global, d->m_defaultToolBar); } KToolBar::setToolBarsEditable(true); } QDialog::showEvent(event); } void KEditToolBar::hideEvent(QHideEvent *event) { // The dialog has been hidden, disable toolbar editing KToolBar::setToolBarsEditable(false); QDialog::hideEvent(event); } #include "moc_kedittoolbar.cpp" #include "moc_kedittoolbar_p.cpp" diff --git a/libs/widgetutils/xmlgui/kedittoolbar_p.h b/libs/widgetutils/xmlgui/kedittoolbar_p.h index 73152efd7e..685a8a8d04 100644 --- a/libs/widgetutils/xmlgui/kedittoolbar_p.h +++ b/libs/widgetutils/xmlgui/kedittoolbar_p.h @@ -1,260 +1,257 @@ /* This file is part of the KDE libraries Copyright (C) 2000 Kurt Granroth Copyright (C) 2006 Hamish Rodda This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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 KEDITTOOLBARP_H #define KEDITTOOLBARP_H #include "kxmlguiclient.h" #include #include class QDialogButtonBox; class QLineEdit; class QCheckBox; namespace KDEPrivate { class ToolBarItem; class KEditToolBarWidgetPrivate; class ToolBarListWidget : public QListWidget { Q_OBJECT public: ToolBarListWidget(QWidget *parent = 0); void makeVisible(QListWidgetItem *item) { scrollTo(indexFromItem(item)); } ToolBarItem *currentItem() const; void setActiveList(bool isActiveList) { m_activeList = isActiveList; } Q_SIGNALS: void dropped(ToolBarListWidget *list, int index, ToolBarItem *item, bool sourceIsActiveList); protected: virtual Qt::DropActions supportedDropActions() const { return Qt::MoveAction; } virtual QStringList mimeTypes() const { return QStringList() << QStringLiteral("application/x-kde-action-list"); } virtual QMimeData *mimeData(const QList items) const; virtual bool dropMimeData(int index, const QMimeData *data, Qt::DropAction action); // Skip internal dnd handling in QListWidget ---- how is one supposed to figure this out // without reading the QListWidget code !? virtual void dropEvent(QDropEvent *ev) { QAbstractItemView::dropEvent(ev); } private: bool m_activeList; }; class IconTextEditDialog : public QDialog { Q_OBJECT public: explicit IconTextEditDialog(QWidget *parent = 0); public: void setIconText(const QString &text); QString iconText() const; void setTextAlongsideIconHidden(bool hidden); bool textAlongsideIconHidden() const; private Q_SLOTS: void slotTextChanged(const QString &text); private: QLineEdit *m_lineEdit; QCheckBox *m_cbHidden; QDialogButtonBox *m_buttonBox; }; /** * @short A widget used to customize or configure toolbars * * This is the widget that does all of the work for the * KEditToolBar dialog. In most cases, you will want to use the * dialog instead of this widget directly. * * Typically, you would use this widget only if you wanted to embed * the toolbar editing directly into your existing configure or * preferences dialog. * * This widget only works if your application uses the XML UI * framework for creating menus and toolbars. It depends on the XML * files to describe the toolbar layouts and it requires the actions * to determine which buttons are active. * * @author Kurt Granroth * @internal */ class KEditToolBarWidget : public QWidget, virtual public KXMLGUIClient { Q_OBJECT public: /** * Old constructor for apps that do not use components. * This constructor is somewhat deprecated, since it doesn't work * with any KXMLGuiClient being added to the mainwindow. * You really want to use the other constructor. * * You @em must pass along your collection of actions (some of which appear in your toolbars). * Then call old-style load. * * @param collection The collection of actions to work on * @param parent This widget's parent */ explicit KEditToolBarWidget(KActionCollection *collection, QWidget *parent = 0L); /** * Main constructor. * * Use this like so: * \code * KEditToolBarWidget widget(this); * widget.load(factory()); * ... * \endcode * * @param factory Your application's factory object * @param parent This widget's parent */ explicit KEditToolBarWidget(QWidget *parent = 0L); /** * Destructor. Note that any changes done in this widget will * @p NOT be saved in the destructor. You @p must call save() * to do that. */ virtual ~KEditToolBarWidget(); /** * Old-style load. * * Loads the toolbar configuration into the widget. Should be called before being shown. * * @param resourceFile the name (absolute or relative) of your application's UI * resource file. If it is left blank, then the resource file: share/apps/appname/appnameui.rc * is used. This is the same resource file that is used by the * default createGUI function in KMainWindow so you're usually * pretty safe in leaving it blank. * * @param global controls whether or not the * global resource file is used. If this is true, then you may * edit all of the actions in your toolbars -- global ones and * local one. If it is false, then you may edit only your * application's entries. The only time you should set this to * false is if your application does not use the global resource * file at all (very rare) * * @param defaultToolBar the default toolbar that will be selected when the dialog is shown. * If not set, or QString() is passed in, the global default tool bar name * will be used. * * @see KEditToolBar */ void load(const QString &resourceFile, bool global = true, const QString &defaultToolBar = QString()); /** * Loads the toolbar configuration into the widget. Should be called before being shown. * * @param factory pointer to the XML GUI factory object for your application. * It contains a list of all of the GUI clients (along with the action * collections and xml files) and the toolbar editor uses that. * * @param defaultToolBar the default toolbar that will be selected when the dialog is shown. * If not set, or QString() is passed in, the global default tool bar name * will be used. * * @see KEditToolBar */ void load(KXMLGUIFactory *factory, const QString &defaultToolBar = QString()); /** * @internal Reimplemented for internal purposes. */ virtual KActionCollection *actionCollection() const; /** * Save any changes the user made. The file will be in the user's * local directory (usually $HOME/.kde/share/apps/\). The * filename will be the one specified in the constructor.. or the * made up one if the filename was NULL. * * @return The status of whether or not the save succeeded. */ bool save(); /** * Remove and readd all KMXLGUIClients to update the GUI */ void rebuildKXMLGUIClients(); Q_SIGNALS: /** * Emitted whenever any modifications are made by the user. */ void enableOk(bool); private: Q_PRIVATE_SLOT(d, void slotToolBarSelected(int index)) Q_PRIVATE_SLOT(d, void slotInactiveSelectionChanged()) Q_PRIVATE_SLOT(d, void slotActiveSelectionChanged()) Q_PRIVATE_SLOT(d, void slotInsertButton()) Q_PRIVATE_SLOT(d, void slotRemoveButton()) Q_PRIVATE_SLOT(d, void slotUpButton()) Q_PRIVATE_SLOT(d, void slotDownButton()) - Q_PRIVATE_SLOT(d, void slotChangeIcon()) - Q_PRIVATE_SLOT(d, void slotChangeIconText()) - Q_PRIVATE_SLOT(d, void slotDropped(ToolBarListWidget *, int, ToolBarItem *, bool)) private: friend class KEditToolBarWidgetPrivate; KEditToolBarWidgetPrivate *const d; Q_DISABLE_COPY(KEditToolBarWidget) }; } #endif diff --git a/libs/widgetutils/xmlgui/ktoolbar.cpp b/libs/widgetutils/xmlgui/ktoolbar.cpp index 8c5c3ab97e..13d737d976 100644 --- a/libs/widgetutils/xmlgui/ktoolbar.cpp +++ b/libs/widgetutils/xmlgui/ktoolbar.cpp @@ -1,1450 +1,1435 @@ /* This file is part of the KDE libraries Copyright (C) 2000 Reginald Stadlbauer (reggie@kde.org) (C) 1997, 1998 Stephan Kulow (coolo@kde.org) (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) (C) 1997, 1998 Sven Radej (radej@kde.org) (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) (C) 1999 Chris Schlaeger (cs@kde.org) (C) 1999 Kurt Granroth (granroth@kde.org) (C) 2005-2006 Hamish Rodda (rodda@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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 "ktoolbar.h" #include "config-xmlgui.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_DBUS #include #include #endif #include #include #include #include #ifdef HAVE_ICONTHEMES #include #endif #include #include #include #include #include "kactioncollection.h" #include "kedittoolbar.h" #include "kxmlguifactory.h" #include "kxmlguiwindow.h" /* Toolbar settings (e.g. icon size or toolButtonStyle) ===================================================== We have the following stack of settings (in order of priority) : - user-specified settings (loaded/saved in KConfig) - developer-specified settings in the XMLGUI file (if using xmlgui) (cannot change at runtime) - KDE-global default (user-configurable; can change at runtime) and when switching between kparts, they are saved as xml in memory, which, in the unlikely case of no-kmainwindow-autosaving, could be different from the user-specified settings saved in KConfig and would have priority over it. So, in summary, without XML: Global config / User settings (loaded/saved in kconfig) and with XML: Global config / App-XML attributes / User settings (loaded/saved in kconfig) And all those settings (except the KDE-global defaults) have to be stored in memory since we cannot retrieve them at random points in time, not knowing the xml document nor config file that holds these settings. Hence the iconSizeSettings and toolButtonStyleSettings arrays. For instance, if you change the KDE-global default, whether this makes a change on a given toolbar depends on whether there are settings at Level_AppXML or Level_UserSettings. Only if there are no settings at those levels, should the change of KDEDefault make a difference. */ enum SettingLevel { Level_KDEDefault, Level_AppXML, Level_UserSettings, NSettingLevels }; enum { Unset = -1 }; class KToolBar::Private { public: Private(KToolBar *qq) : q(qq), isMainToolBar(false), unlockedMovable(true), contextOrient(0), contextMode(0), contextSize(0), contextButtonTitle(0), contextShowText(0), contextButtonAction(0), contextTop(0), contextLeft(0), contextRight(0), contextBottom(0), contextIcons(0), contextTextRight(0), contextText(0), contextTextUnder(0), contextLockAction(0), dropIndicatorAction(0), context(0), dragAction(0) { } void slotAppearanceChanged(); void slotContextAboutToShow(); void slotContextAboutToHide(); void slotContextLeft(); void slotContextRight(); void slotContextShowText(); void slotContextTop(); void slotContextBottom(); void slotContextIcons(); void slotContextText(); void slotContextTextRight(); void slotContextTextUnder(); void slotContextIconSize(); void slotLockToolBars(bool lock); void init(bool readConfig = true, bool isMainToolBar = false); QString getPositionAsString() const; QMenu *contextMenu(const QPoint &globalPos); void setLocked(bool locked); void adjustSeparatorVisibility(); void loadKDESettings(); void applyCurrentSettings(); QAction *findAction(const QString &actionName, KXMLGUIClient **client = 0) const; static Qt::ToolButtonStyle toolButtonStyleFromString(const QString &style); static QString toolButtonStyleToString(Qt::ToolButtonStyle); static Qt::ToolBarArea positionFromString(const QString &position); static Qt::ToolButtonStyle toolButtonStyleSetting(); KToolBar *q; bool isMainToolBar : 1; bool unlockedMovable : 1; static bool s_editable; static bool s_locked; QSet xmlguiClients; QMenu *contextOrient; QMenu *contextMode; QMenu *contextSize; QAction *contextButtonTitle; QAction *contextShowText; QAction *contextButtonAction; QAction *contextTop; QAction *contextLeft; QAction *contextRight; QAction *contextBottom; QAction *contextIcons; QAction *contextTextRight; QAction *contextText; QAction *contextTextUnder; KToggleAction *contextLockAction; QMap contextIconSizes; class IntSetting { public: IntSetting() { for (int level = 0; level < NSettingLevels; ++level) { values[level] = Unset; } } int currentValue() const { int val = Unset; for (int level = 0; level < NSettingLevels; ++level) { if (values[level] != Unset) { val = values[level]; } } return val; } // Default value as far as the user is concerned is kde-global + app-xml. // If currentValue()==defaultValue() then nothing to write into kconfig. int defaultValue() const { int val = Unset; for (int level = 0; level < Level_UserSettings; ++level) { if (values[level] != Unset) { val = values[level]; } } return val; } QString toString() const { QString str; for (int level = 0; level < NSettingLevels; ++level) { str += QString::number(values[level]) + QLatin1Char(' '); } return str; } int &operator[](int index) { return values[index]; } private: int values[NSettingLevels]; }; IntSetting iconSizeSettings; IntSetting toolButtonStyleSettings; // either Qt::ToolButtonStyle or -1, hence "int". QList actionsBeingDragged; QAction *dropIndicatorAction; QMenu *context; QAction *dragAction; QPoint dragStartPosition; }; bool KToolBar::Private::s_editable = false; bool KToolBar::Private::s_locked = true; void KToolBar::Private::init(bool readConfig, bool _isMainToolBar) { isMainToolBar = _isMainToolBar; loadKDESettings(); // also read in our configurable settings (for non-xmlgui toolbars) if (readConfig) { KConfigGroup cg(KSharedConfig::openConfig(), QString()); q->applySettings(cg); } if (q->mainWindow()) { // Get notified when settings change connect(q, SIGNAL(allowedAreasChanged(Qt::ToolBarAreas)), q->mainWindow(), SLOT(setSettingsDirty())); connect(q, SIGNAL(iconSizeChanged(QSize)), q->mainWindow(), SLOT(setSettingsDirty())); connect(q, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)), q->mainWindow(), SLOT(setSettingsDirty())); connect(q, SIGNAL(movableChanged(bool)), q->mainWindow(), SLOT(setSettingsDirty())); connect(q, SIGNAL(orientationChanged(Qt::Orientation)), q->mainWindow(), SLOT(setSettingsDirty())); } if (!KAuthorized::authorize(QStringLiteral("movable_toolbars"))) { q->setMovable(false); } else { q->setMovable(!KToolBar::toolBarsLocked()); } connect(q, SIGNAL(movableChanged(bool)), q, SLOT(slotMovableChanged(bool))); q->setAcceptDrops(true); #ifdef HAVE_DBUS QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/KToolBar"), QStringLiteral("org.kde.KToolBar"), QStringLiteral("styleChanged"), q, SLOT(slotAppearanceChanged())); #endif -#ifdef HAVE_ICONTHEMES - connect(KIconLoader::global(), SIGNAL(iconLoaderSettingsChanged()), - q, SLOT(slotAppearanceChanged())); -#endif } QString KToolBar::Private::getPositionAsString() const { // get all of the stuff to save switch (q->mainWindow()->toolBarArea(const_cast(q))) { case Qt::BottomToolBarArea: return QStringLiteral("Bottom"); case Qt::LeftToolBarArea: return QStringLiteral("Left"); case Qt::RightToolBarArea: return QStringLiteral("Right"); case Qt::TopToolBarArea: default: return QStringLiteral("Top"); } } QMenu *KToolBar::Private::contextMenu(const QPoint &globalPos) { if (!context) { context = new QMenu(q); contextButtonTitle = context->addSection(i18nc("@title:menu", "Show Text")); contextShowText = context->addAction(QString(), q, SLOT(slotContextShowText())); context->addSection(i18nc("@title:menu", "Toolbar Settings")); contextOrient = new QMenu(i18nc("Toolbar orientation", "Orientation"), context); contextTop = contextOrient->addAction(i18nc("toolbar position string", "Top"), q, SLOT(slotContextTop())); contextTop->setChecked(true); contextLeft = contextOrient->addAction(i18nc("toolbar position string", "Left"), q, SLOT(slotContextLeft())); contextRight = contextOrient->addAction(i18nc("toolbar position string", "Right"), q, SLOT(slotContextRight())); contextBottom = contextOrient->addAction(i18nc("toolbar position string", "Bottom"), q, SLOT(slotContextBottom())); QActionGroup *positionGroup = new QActionGroup(contextOrient); Q_FOREACH (QAction *action, contextOrient->actions()) { action->setActionGroup(positionGroup); action->setCheckable(true); } contextMode = new QMenu(i18n("Text Position"), context); contextIcons = contextMode->addAction(i18n("Icons Only"), q, SLOT(slotContextIcons())); contextText = contextMode->addAction(i18n("Text Only"), q, SLOT(slotContextText())); contextTextRight = contextMode->addAction(i18n("Text Alongside Icons"), q, SLOT(slotContextTextRight())); contextTextUnder = contextMode->addAction(i18n("Text Under Icons"), q, SLOT(slotContextTextUnder())); QActionGroup *textGroup = new QActionGroup(contextMode); Q_FOREACH (QAction *action, contextMode->actions()) { action->setActionGroup(textGroup); action->setCheckable(true); } contextSize = new QMenu(i18n("Icon Size"), context); contextIconSizes.insert(contextSize->addAction(i18nc("@item:inmenu Icon size", "Default"), q, SLOT(slotContextIconSize())), iconSizeSettings.defaultValue()); QList avSizes; -#ifdef HAVE_ICONTHEME - // Query the current theme for available sizes - KIconTheme *theme = KIconLoader::global()->theme(); - if (theme) { - avSizes = theme->querySizes(isMainToolBar ? KIconLoader::MainToolbar : KIconLoader::Toolbar); - } -#else - avSizes << 16 << 22 << 24 << 32 << 48 << 64; -#endif + avSizes << 16 << 22 << 24 << 32 << 48 << 64 << 128 << 256; + qSort(avSizes); if (avSizes.count() < 10) { // Fixed or threshold type icons Q_FOREACH (int it, avSizes) { QString text; if (it < 19) { text = i18n("Small (%1x%2)", it, it); } else if (it < 25) { text = i18n("Medium (%1x%2)", it, it); } else if (it < 35) { text = i18n("Large (%1x%2)", it, it); } else { text = i18n("Huge (%1x%2)", it, it); } // save the size in the contextIconSizes map contextIconSizes.insert(contextSize->addAction(text, q, SLOT(slotContextIconSize())), it); } } else { // Scalable icons. const int progression[] = { 16, 22, 32, 48, 64, 96, 128, 192, 256 }; for (uint i = 0; i < 9; i++) { Q_FOREACH (int it, avSizes) { if (it >= progression[ i ]) { QString text; if (it < 19) { text = i18n("Small (%1x%2)", it, it); } else if (it < 25) { text = i18n("Medium (%1x%2)", it, it); } else if (it < 35) { text = i18n("Large (%1x%2)", it, it); } else { text = i18n("Huge (%1x%2)", it, it); } // save the size in the contextIconSizes map contextIconSizes.insert(contextSize->addAction(text, q, SLOT(slotContextIconSize())), it); break; } } } } QActionGroup *sizeGroup = new QActionGroup(contextSize); Q_FOREACH (QAction *action, contextSize->actions()) { action->setActionGroup(sizeGroup); action->setCheckable(true); } if (!q->toolBarsLocked() && !q->isMovable()) { unlockedMovable = false; } delete contextLockAction; contextLockAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("system-lock-screen")), i18n("Lock Toolbar Positions"), q); contextLockAction->setChecked(q->toolBarsLocked()); connect(contextLockAction, SIGNAL(toggled(bool)), q, SLOT(slotLockToolBars(bool))); // Now add the actions to the menu context->addMenu(contextMode); context->addMenu(contextSize); context->addMenu(contextOrient); context->addSeparator(); connect(context, SIGNAL(aboutToShow()), q, SLOT(slotContextAboutToShow())); } contextButtonAction = q->actionAt(q->mapFromGlobal(globalPos)); if (contextButtonAction) { contextShowText->setText(contextButtonAction->text()); contextShowText->setIcon(contextButtonAction->icon()); contextShowText->setCheckable(true); } contextOrient->menuAction()->setVisible(!q->toolBarsLocked()); // Unplugging a submenu from abouttohide leads to the popupmenu floating around // So better simply call that code from after exec() returns (DF) //connect(context, SIGNAL(aboutToHide()), this, SLOT(slotContextAboutToHide())); return context; } void KToolBar::Private::setLocked(bool locked) { if (unlockedMovable) { q->setMovable(!locked); } } void KToolBar::Private::adjustSeparatorVisibility() { bool visibleNonSeparator = false; int separatorToShow = -1; for (int index = 0; index < q->actions().count(); ++index) { QAction *action = q->actions()[ index ]; if (action->isSeparator()) { if (visibleNonSeparator) { separatorToShow = index; visibleNonSeparator = false; } else { action->setVisible(false); } } else if (!visibleNonSeparator) { if (action->isVisible()) { visibleNonSeparator = true; if (separatorToShow != -1) { q->actions()[ separatorToShow ]->setVisible(true); separatorToShow = -1; } } } } if (separatorToShow != -1) { q->actions()[ separatorToShow ]->setVisible(false); } } Qt::ToolButtonStyle KToolBar::Private::toolButtonStyleFromString(const QString &_style) { QString style = _style.toLower(); if (style == QStringLiteral("textbesideicon") || style == QLatin1String("icontextright")) { return Qt::ToolButtonTextBesideIcon; } else if (style == QStringLiteral("textundericon") || style == QLatin1String("icontextbottom")) { return Qt::ToolButtonTextUnderIcon; } else if (style == QStringLiteral("textonly")) { return Qt::ToolButtonTextOnly; } else { return Qt::ToolButtonIconOnly; } } QString KToolBar::Private::toolButtonStyleToString(Qt::ToolButtonStyle style) { switch (style) { case Qt::ToolButtonIconOnly: default: return QStringLiteral("IconOnly"); case Qt::ToolButtonTextBesideIcon: return QStringLiteral("TextBesideIcon"); case Qt::ToolButtonTextOnly: return QStringLiteral("TextOnly"); case Qt::ToolButtonTextUnderIcon: return QStringLiteral("TextUnderIcon"); } } Qt::ToolBarArea KToolBar::Private::positionFromString(const QString &position) { Qt::ToolBarArea newposition = Qt::TopToolBarArea; if (position == QStringLiteral("left")) { newposition = Qt::LeftToolBarArea; } else if (position == QStringLiteral("bottom")) { newposition = Qt::BottomToolBarArea; } else if (position == QStringLiteral("right")) { newposition = Qt::RightToolBarArea; } return newposition; } // Global setting was changed void KToolBar::Private::slotAppearanceChanged() { loadKDESettings(); applyCurrentSettings(); } Qt::ToolButtonStyle KToolBar::Private::toolButtonStyleSetting() { KConfigGroup group(KSharedConfig::openConfig(), "Toolbar style"); const QString fallback = KToolBar::Private::toolButtonStyleToString(Qt::ToolButtonTextBesideIcon); return KToolBar::Private::toolButtonStyleFromString(group.readEntry("ToolButtonStyle", fallback)); } void KToolBar::Private::loadKDESettings() { iconSizeSettings[Level_KDEDefault] = q->iconSizeDefault(); if (isMainToolBar) { toolButtonStyleSettings[Level_KDEDefault] = toolButtonStyleSetting(); } else { const QString fallBack = toolButtonStyleToString(Qt::ToolButtonTextBesideIcon); /** TODO: if we get complaints about text beside icons on small screens, try the following code out on such systems - aseigo. // if we are on a small screen with a non-landscape ratio, then // we revert to text under icons since width is probably not our // friend in such cases QDesktopWidget *desktop = QApplication::desktop(); QRect screenGeom = desktop->screenGeometry(desktop->primaryScreen()); qreal ratio = screenGeom.width() / qreal(screenGeom.height()); if (screenGeom.width() < 1024 && ratio <= 1.4) { fallBack = "TextUnderIcon"; } **/ KConfigGroup group(KSharedConfig::openConfig(), "Toolbar style"); const QString value = group.readEntry("ToolButtonStyleOtherToolbars", fallBack); toolButtonStyleSettings[Level_KDEDefault] = KToolBar::Private::toolButtonStyleFromString(value); } } // Call this after changing something in d->iconSizeSettings or d->toolButtonStyleSettings void KToolBar::Private::applyCurrentSettings() { //qDebug() << q->objectName() << "iconSizeSettings:" << iconSizeSettings.toString() << "->" << iconSizeSettings.currentValue(); const int currentIconSize = iconSizeSettings.currentValue(); q->setIconSize(QSize(currentIconSize, currentIconSize)); //qDebug() << q->objectName() << "toolButtonStyleSettings:" << toolButtonStyleSettings.toString() << "->" << toolButtonStyleSettings.currentValue(); q->setToolButtonStyle(static_cast(toolButtonStyleSettings.currentValue())); // And remember to save the new look later KMainWindow *kmw = q->mainWindow(); if (kmw) { kmw->setSettingsDirty(); } } QAction *KToolBar::Private::findAction(const QString &actionName, KXMLGUIClient **clientOut) const { Q_FOREACH (KXMLGUIClient *client, xmlguiClients) { QAction *action = client->actionCollection()->action(actionName); if (action) { if (clientOut) { *clientOut = client; } return action; } } return 0; } void KToolBar::Private::slotContextAboutToShow() { /** * The idea here is to reuse the "static" part of the menu to save time. * But the "Toolbars" action is dynamic (can be a single action or a submenu) * and ToolBarHandler::setupActions() deletes it, so better not keep it around. * So we currently plug/unplug the last two actions of the menu. * Another way would be to keep around the actions and plug them all into a (new each time) popupmenu. */ KXmlGuiWindow *kmw = qobject_cast(q->mainWindow()); // try to find "configure toolbars" action QAction *configureAction = 0; const char *actionName; actionName = KStandardAction::name(KStandardAction::ConfigureToolbars); configureAction = findAction(QLatin1String(actionName)); if (!configureAction && kmw) { configureAction = kmw->actionCollection()->action(QLatin1String(actionName)); } if (configureAction) { context->addAction(configureAction); } context->addAction(contextLockAction); if (kmw) { kmw->setupToolbarMenuActions(); // Only allow hiding a toolbar if the action is also plugged somewhere else (e.g. menubar) QAction *tbAction = kmw->toolBarMenuAction(); if (!q->toolBarsLocked() && tbAction && tbAction->associatedWidgets().count() > 0) { context->addAction(tbAction); } } KEditToolBar::setGlobalDefaultToolBar(q->QObject::objectName().toLatin1().constData()); // Check the actions that should be checked switch (q->toolButtonStyle()) { case Qt::ToolButtonIconOnly: default: contextIcons->setChecked(true); break; case Qt::ToolButtonTextBesideIcon: contextTextRight->setChecked(true); break; case Qt::ToolButtonTextOnly: contextText->setChecked(true); break; case Qt::ToolButtonTextUnderIcon: contextTextUnder->setChecked(true); break; } QMapIterator< QAction *, int > it = contextIconSizes; while (it.hasNext()) { it.next(); if (it.value() == q->iconSize().width()) { it.key()->setChecked(true); break; } } switch (q->mainWindow()->toolBarArea(q)) { case Qt::BottomToolBarArea: contextBottom->setChecked(true); break; case Qt::LeftToolBarArea: contextLeft->setChecked(true); break; case Qt::RightToolBarArea: contextRight->setChecked(true); break; default: case Qt::TopToolBarArea: contextTop->setChecked(true); break; } const bool showButtonSettings = contextButtonAction && !contextShowText->text().isEmpty() && contextTextRight->isChecked(); contextButtonTitle->setVisible(showButtonSettings); contextShowText->setVisible(showButtonSettings); if (showButtonSettings) { contextShowText->setChecked(contextButtonAction->priority() >= QAction::NormalPriority); } } void KToolBar::Private::slotContextAboutToHide() { // We have to unplug whatever slotContextAboutToShow plugged into the menu. // Unplug the toolbar menu action KXmlGuiWindow *kmw = qobject_cast(q->mainWindow()); if (kmw && kmw->toolBarMenuAction()) { if (kmw->toolBarMenuAction()->associatedWidgets().count() > 1) { context->removeAction(kmw->toolBarMenuAction()); } } // Unplug the configure toolbars action too, since it's afterwards anyway QAction *configureAction = 0; const char *actionName; actionName = KStandardAction::name(KStandardAction::ConfigureToolbars); configureAction = findAction(QLatin1String(actionName)); if (!configureAction && kmw) { configureAction = kmw->actionCollection()->action(QLatin1String(actionName)); } if (configureAction) { context->removeAction(configureAction); } context->removeAction(contextLockAction); } void KToolBar::Private::slotContextLeft() { q->mainWindow()->addToolBar(Qt::LeftToolBarArea, q); } void KToolBar::Private::slotContextRight() { q->mainWindow()->addToolBar(Qt::RightToolBarArea, q); } void KToolBar::Private::slotContextShowText() { Q_ASSERT(contextButtonAction); const QAction::Priority priority = contextShowText->isChecked() ? QAction::NormalPriority : QAction::LowPriority; contextButtonAction->setPriority(priority); // Find to which xml file and componentData the action belongs to QString componentName; QString filename; KXMLGUIClient *client; if (findAction(contextButtonAction->objectName(), &client)) { componentName = client->componentName(); filename = client->xmlFile(); } if (filename.isEmpty()) { componentName = QCoreApplication::applicationName(); filename = componentName + QStringLiteral("ui.rc"); } // Save the priority state of the action const QString configFile = KXMLGUIFactory::readConfigFile(filename, componentName); QDomDocument document; document.setContent(configFile); QDomElement elem = KXMLGUIFactory::actionPropertiesElement(document); QDomElement actionElem = KXMLGUIFactory::findActionByName(elem, contextButtonAction->objectName(), true); actionElem.setAttribute(QStringLiteral("priority"), priority); KXMLGUIFactory::saveConfigFile(document, filename, componentName); } void KToolBar::Private::slotContextTop() { q->mainWindow()->addToolBar(Qt::TopToolBarArea, q); } void KToolBar::Private::slotContextBottom() { q->mainWindow()->addToolBar(Qt::BottomToolBarArea, q); } void KToolBar::Private::slotContextIcons() { q->setToolButtonStyle(Qt::ToolButtonIconOnly); toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle(); } void KToolBar::Private::slotContextText() { q->setToolButtonStyle(Qt::ToolButtonTextOnly); toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle(); } void KToolBar::Private::slotContextTextUnder() { q->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle(); } void KToolBar::Private::slotContextTextRight() { q->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle(); } void KToolBar::Private::slotContextIconSize() { QAction *action = qobject_cast(q->sender()); if (action && contextIconSizes.contains(action)) { const int iconSize = contextIconSizes.value(action); q->setIconDimensions(iconSize); } } void KToolBar::Private::slotLockToolBars(bool lock) { q->setToolBarsLocked(lock); } KToolBar::KToolBar(QWidget *parent, bool isMainToolBar, bool readConfig) : QToolBar(parent), d(new Private(this)) { d->init(readConfig, isMainToolBar); // KToolBar is auto-added to the top area of the main window if parent is a QMainWindow if (QMainWindow *mw = qobject_cast(parent)) { mw->addToolBar(this); } } KToolBar::KToolBar(const QString &objectName, QWidget *parent, bool readConfig) : QToolBar(parent), d(new Private(this)) { setObjectName(objectName); // mainToolBar -> isMainToolBar = true -> buttonStyle is configurable // others -> isMainToolBar = false -> ### hardcoded default for buttonStyle !!! should be configurable? -> hidden key added d->init(readConfig, objectName == QStringLiteral("mainToolBar")); // KToolBar is auto-added to the top area of the main window if parent is a QMainWindow if (QMainWindow *mw = qobject_cast(parent)) { mw->addToolBar(this); } } KToolBar::KToolBar(const QString &objectName, QMainWindow *parent, Qt::ToolBarArea area, bool newLine, bool isMainToolBar, bool readConfig) : QToolBar(parent), d(new Private(this)) { setObjectName(objectName); d->init(readConfig, isMainToolBar); if (newLine) { mainWindow()->addToolBarBreak(area); } mainWindow()->addToolBar(area, this); if (newLine) { mainWindow()->addToolBarBreak(area); } } KToolBar::~KToolBar() { delete d->contextLockAction; delete d; } void KToolBar::saveSettings(KConfigGroup &cg) { Q_ASSERT(!cg.name().isEmpty()); const int currentIconSize = iconSize().width(); //qDebug() << objectName() << currentIconSize << d->iconSizeSettings.toString() << "defaultValue=" << d->iconSizeSettings.defaultValue(); if (!cg.hasDefault("IconSize") && currentIconSize == d->iconSizeSettings.defaultValue()) { cg.revertToDefault("IconSize"); d->iconSizeSettings[Level_UserSettings] = Unset; } else { cg.writeEntry("IconSize", currentIconSize); d->iconSizeSettings[Level_UserSettings] = currentIconSize; } const Qt::ToolButtonStyle currentToolButtonStyle = toolButtonStyle(); if (!cg.hasDefault("ToolButtonStyle") && currentToolButtonStyle == d->toolButtonStyleSettings.defaultValue()) { cg.revertToDefault("ToolButtonStyle"); d->toolButtonStyleSettings[Level_UserSettings] = Unset; } else { cg.writeEntry("ToolButtonStyle", d->toolButtonStyleToString(currentToolButtonStyle)); d->toolButtonStyleSettings[Level_UserSettings] = currentToolButtonStyle; } } void KToolBar::addXMLGUIClient(KXMLGUIClient *client) { d->xmlguiClients << client; } void KToolBar::removeXMLGUIClient(KXMLGUIClient *client) { d->xmlguiClients.remove(client); } void KToolBar::contextMenuEvent(QContextMenuEvent *event) { QToolBar::contextMenuEvent(event); } void KToolBar::loadState(const QDomElement &element) { QMainWindow *mw = mainWindow(); if (!mw) { return; } { QDomNode textNode = element.namedItem(QStringLiteral("text")); QByteArray domain; QByteArray text; QByteArray context; if (textNode.isElement()) { QDomElement textElement = textNode.toElement(); domain = textElement.attribute(QStringLiteral("translationDomain")).toUtf8(); text = textElement.text().toUtf8(); context = textElement.attribute(QStringLiteral("context")).toUtf8(); } else { textNode = element.namedItem(QStringLiteral("Text")); if (textNode.isElement()) { QDomElement textElement = textNode.toElement(); domain = textElement.attribute(QStringLiteral("translationDomain")).toUtf8(); text = textElement.text().toUtf8(); context = textElement.attribute(QStringLiteral("context")).toUtf8(); } } if (domain.isEmpty()) { domain = element.ownerDocument().documentElement().attribute(QStringLiteral("translationDomain")).toUtf8(); if (domain.isEmpty()) { domain = KLocalizedString::applicationDomain(); } } QString i18nText; if (!text.isEmpty() && !context.isEmpty()) { i18nText = i18ndc(domain.constData(), context.constData(), text.constData()); } else if (!text.isEmpty()) { i18nText = i18nd(domain.constData(), text.constData()); } if (!i18nText.isEmpty()) { setWindowTitle(i18nText); } } /* This method is called in order to load toolbar settings from XML. However this can be used in two rather different cases: - for the initial loading of the app's XML. In that case the settings are only the defaults (Level_AppXML), the user's KConfig settings will override them - for later re-loading when switching between parts in KXMLGUIFactory. In that case the XML contains the final settings, not the defaults. We do need the defaults, and the toolbar might have been completely deleted and recreated meanwhile. So we store the app-default settings into the XML. */ bool loadingAppDefaults = true; if (element.hasAttribute(QStringLiteral("tempXml"))) { // this isn't the first time, so the app-xml defaults have been saved into the (in-memory) XML loadingAppDefaults = false; const QString iconSizeDefault = element.attribute(QStringLiteral("iconSizeDefault")); if (!iconSizeDefault.isEmpty()) { d->iconSizeSettings[Level_AppXML] = iconSizeDefault.toInt(); } const QString toolButtonStyleDefault = element.attribute(QStringLiteral("toolButtonStyleDefault")); if (!toolButtonStyleDefault.isEmpty()) { d->toolButtonStyleSettings[Level_AppXML] = d->toolButtonStyleFromString(toolButtonStyleDefault); } } else { // loading app defaults bool newLine = false; QString attrNewLine = element.attribute(QStringLiteral("newline")).toLower(); if (!attrNewLine.isEmpty()) { newLine = attrNewLine == QStringLiteral("true"); } if (newLine && mw) { mw->insertToolBarBreak(this); } } int newIconSize = -1; if (element.hasAttribute(QStringLiteral("iconSize"))) { bool ok; newIconSize = element.attribute(QStringLiteral("iconSize")).trimmed().toInt(&ok); if (!ok) { newIconSize = -1; } } if (newIconSize != -1) { d->iconSizeSettings[loadingAppDefaults ? Level_AppXML : Level_UserSettings] = newIconSize; } const QString newToolButtonStyle = element.attribute(QStringLiteral("iconText")); if (!newToolButtonStyle.isEmpty()) { d->toolButtonStyleSettings[loadingAppDefaults ? Level_AppXML : Level_UserSettings] = d->toolButtonStyleFromString(newToolButtonStyle); } bool hidden = false; { QString attrHidden = element.attribute(QStringLiteral("hidden")).toLower(); if (!attrHidden.isEmpty()) { hidden = attrHidden == QStringLiteral("true"); } } Qt::ToolBarArea pos = Qt::NoToolBarArea; { QString attrPosition = element.attribute(QStringLiteral("position")).toLower(); if (!attrPosition.isEmpty()) { pos = KToolBar::Private::positionFromString(attrPosition); } } if (pos != Qt::NoToolBarArea) { mw->addToolBar(pos, this); } setVisible(!hidden); d->applyCurrentSettings(); } // Called when switching between xmlgui clients, in order to find any unsaved settings // again when switching back to the current xmlgui client. void KToolBar::saveState(QDomElement ¤t) const { Q_ASSERT(!current.isNull()); current.setAttribute(QStringLiteral("tempXml"), QLatin1String("true")); current.setAttribute(QStringLiteral("noMerge"), QLatin1String("1")); current.setAttribute(QStringLiteral("position"), d->getPositionAsString().toLower()); current.setAttribute(QStringLiteral("hidden"), isHidden() ? QLatin1String("true") : QLatin1String("false")); const int currentIconSize = iconSize().width(); if (currentIconSize == d->iconSizeSettings.defaultValue()) { current.removeAttribute(QStringLiteral("iconSize")); } else { current.setAttribute(QStringLiteral("iconSize"), iconSize().width()); } if (toolButtonStyle() == d->toolButtonStyleSettings.defaultValue()) { current.removeAttribute(QStringLiteral("iconText")); } else { current.setAttribute(QStringLiteral("iconText"), d->toolButtonStyleToString(toolButtonStyle())); } // Note: if this method is used by more than KXMLGUIBuilder, e.g. to save XML settings to *disk*, // then the stuff below shouldn't always be done. This is not the case currently though. if (d->iconSizeSettings[Level_AppXML] != Unset) { current.setAttribute(QStringLiteral("iconSizeDefault"), d->iconSizeSettings[Level_AppXML]); } if (d->toolButtonStyleSettings[Level_AppXML] != Unset) { const Qt::ToolButtonStyle bs = static_cast(d->toolButtonStyleSettings[Level_AppXML]); current.setAttribute(QStringLiteral("toolButtonStyleDefault"), d->toolButtonStyleToString(bs)); } } // called by KMainWindow::applyMainWindowSettings to read from the user settings void KToolBar::applySettings(const KConfigGroup &cg) { Q_ASSERT(!cg.name().isEmpty()); if (cg.hasKey("IconSize")) { d->iconSizeSettings[Level_UserSettings] = cg.readEntry("IconSize", 0); } if (cg.hasKey("ToolButtonStyle")) { d->toolButtonStyleSettings[Level_UserSettings] = d->toolButtonStyleFromString(cg.readEntry("ToolButtonStyle", QString())); } d->applyCurrentSettings(); } KMainWindow *KToolBar::mainWindow() const { return qobject_cast(const_cast(parent())); } void KToolBar::setIconDimensions(int size) { QToolBar::setIconSize(QSize(size, size)); d->iconSizeSettings[Level_UserSettings] = size; } int KToolBar::iconSizeDefault() const { -#ifdef HAVE_ICONTHEMES - return KIconLoader::global()->currentSize(d->isMainToolBar ? KIconLoader::MainToolbar : KIconLoader::Toolbar); -#else return 22; -#endif } void KToolBar::slotMovableChanged(bool movable) { if (movable && !KAuthorized::authorize(QStringLiteral("movable_toolbars"))) { setMovable(false); } } void KToolBar::dragEnterEvent(QDragEnterEvent *event) { if (toolBarsEditable() && event->proposedAction() & (Qt::CopyAction | Qt::MoveAction) && event->mimeData()->hasFormat(QStringLiteral("application/x-kde-action-list"))) { QByteArray data = event->mimeData()->data(QStringLiteral("application/x-kde-action-list")); QDataStream stream(data); QStringList actionNames; stream >> actionNames; Q_FOREACH (const QString &actionName, actionNames) { Q_FOREACH (KActionCollection *ac, KActionCollection::allCollections()) { QAction *newAction = ac->action(actionName); if (newAction) { d->actionsBeingDragged.append(newAction); break; } } } if (d->actionsBeingDragged.count()) { QAction *overAction = actionAt(event->pos()); QFrame *dropIndicatorWidget = new QFrame(this); dropIndicatorWidget->resize(8, height() - 4); dropIndicatorWidget->setFrameShape(QFrame::VLine); dropIndicatorWidget->setLineWidth(3); d->dropIndicatorAction = insertWidget(overAction, dropIndicatorWidget); insertAction(overAction, d->dropIndicatorAction); event->acceptProposedAction(); return; } } QToolBar::dragEnterEvent(event); } void KToolBar::dragMoveEvent(QDragMoveEvent *event) { if (toolBarsEditable()) Q_FOREVER { if (d->dropIndicatorAction) { QAction *overAction = 0L; Q_FOREACH (QAction *action, actions()) { // want to make it feel that half way across an action you're dropping on the other side of it QWidget *widget = widgetForAction(action); if (event->pos().x() < widget->pos().x() + (widget->width() / 2)) { overAction = action; break; } } if (overAction != d->dropIndicatorAction) { // Check to see if the indicator is already in the right spot int dropIndicatorIndex = actions().indexOf(d->dropIndicatorAction); if (dropIndicatorIndex + 1 < actions().count()) { if (actions()[ dropIndicatorIndex + 1 ] == overAction) { break; } } else if (!overAction) { break; } insertAction(overAction, d->dropIndicatorAction); } event->accept(); return; } break; } QToolBar::dragMoveEvent(event); } void KToolBar::dragLeaveEvent(QDragLeaveEvent *event) { // Want to clear this even if toolBarsEditable was changed mid-drag (unlikey) delete d->dropIndicatorAction; d->dropIndicatorAction = 0L; d->actionsBeingDragged.clear(); if (toolBarsEditable()) { event->accept(); return; } QToolBar::dragLeaveEvent(event); } void KToolBar::dropEvent(QDropEvent *event) { if (toolBarsEditable()) { Q_FOREACH (QAction *action, d->actionsBeingDragged) { if (actions().contains(action)) { removeAction(action); } insertAction(d->dropIndicatorAction, action); } } // Want to clear this even if toolBarsEditable was changed mid-drag (unlikey) delete d->dropIndicatorAction; d->dropIndicatorAction = 0L; d->actionsBeingDragged.clear(); if (toolBarsEditable()) { event->accept(); return; } QToolBar::dropEvent(event); } void KToolBar::mousePressEvent(QMouseEvent *event) { if (toolBarsEditable() && event->button() == Qt::LeftButton) { if (QAction *action = actionAt(event->pos())) { d->dragAction = action; d->dragStartPosition = event->pos(); event->accept(); return; } } QToolBar::mousePressEvent(event); } void KToolBar::mouseMoveEvent(QMouseEvent *event) { if (!toolBarsEditable() || !d->dragAction) { return QToolBar::mouseMoveEvent(event); } if ((event->pos() - d->dragStartPosition).manhattanLength() < QApplication::startDragDistance()) { event->accept(); return; } QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; QByteArray data; { QDataStream stream(&data, QIODevice::WriteOnly); QStringList actionNames; actionNames << d->dragAction->objectName(); stream << actionNames; } mimeData->setData(QStringLiteral("application/x-kde-action-list"), data); drag->setMimeData(mimeData); Qt::DropAction dropAction = drag->start(Qt::MoveAction); if (dropAction == Qt::MoveAction) // Only remove from this toolbar if it was moved to another toolbar // Otherwise the receiver moves it. if (drag->target() != this) { removeAction(d->dragAction); } d->dragAction = 0L; event->accept(); } void KToolBar::mouseReleaseEvent(QMouseEvent *event) { // Want to clear this even if toolBarsEditable was changed mid-drag (unlikey) if (d->dragAction) { d->dragAction = 0L; event->accept(); return; } QToolBar::mouseReleaseEvent(event); } bool KToolBar::eventFilter(QObject *watched, QEvent *event) { // Generate context menu events for disabled buttons too... if (event->type() == QEvent::MouseButtonPress) { QMouseEvent *me = static_cast(event); if (me->buttons() & Qt::RightButton) if (QWidget *ww = qobject_cast(watched)) if (ww->parent() == this && !ww->isEnabled()) { QCoreApplication::postEvent(this, new QContextMenuEvent(QContextMenuEvent::Mouse, me->pos(), me->globalPos())); } } else if (event->type() == QEvent::ParentChange) { // Make sure we're not leaving stale event filters around, // when a child is reparented somewhere else if (QWidget *ww = qobject_cast(watched)) { if (!this->isAncestorOf(ww)) { // New parent is not a subwidget - remove event filter ww->removeEventFilter(this); Q_FOREACH (QWidget *child, ww->findChildren()) { child->removeEventFilter(this); } } } } QToolButton *tb; if ((tb = qobject_cast(watched))) { const QList tbActions = tb->actions(); if (!tbActions.isEmpty()) { // Handle MMB on toolbar buttons if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) { QMouseEvent *me = static_cast(event); if (me->button() == Qt::MidButton /*&& act->receivers(SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)))*/) { QAction *act = tbActions.first(); if (me->type() == QEvent::MouseButtonPress) { tb->setDown(act->isEnabled()); } else { tb->setDown(false); if (act->isEnabled()) { QMetaObject::invokeMethod(act, "triggered", Qt::DirectConnection, Q_ARG(Qt::MouseButtons, me->button()), Q_ARG(Qt::KeyboardModifiers, QApplication::keyboardModifiers())); } } } } // CJK languages use more verbose accelerator marker: they add a Latin // letter in parenthesis, and put accelerator on that. Hence, the default // removal of ampersand only may not be enough there, instead the whole // parenthesis construct should be removed. Use KLocalizedString's method to do this. if (event->type() == QEvent::Show || event->type() == QEvent::Paint || event->type() == QEvent::EnabledChange) { QAction *act = tb->defaultAction(); if (act) { const QString text = KLocalizedString::removeAcceleratorMarker(act->iconText().isEmpty() ? act->text() : act->iconText()); const QString toolTip = KLocalizedString::removeAcceleratorMarker(act->toolTip()); // Filtering messages requested by translators (scripting). tb->setText(i18nc("@action:intoolbar Text label of toolbar button", "%1", text)); tb->setToolTip(i18nc("@info:tooltip Tooltip of toolbar button", "%1", toolTip)); } } } } // Redirect mouse events to the toolbar when drag + drop editing is enabled if (toolBarsEditable()) { if (QWidget *ww = qobject_cast(watched)) { switch (event->type()) { case QEvent::MouseButtonPress: { QMouseEvent *me = static_cast(event); QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(), me->button(), me->buttons(), me->modifiers()); mousePressEvent(&newEvent); return true; } case QEvent::MouseMove: { QMouseEvent *me = static_cast(event); QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(), me->button(), me->buttons(), me->modifiers()); mouseMoveEvent(&newEvent); return true; } case QEvent::MouseButtonRelease: { QMouseEvent *me = static_cast(event); QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(), me->button(), me->buttons(), me->modifiers()); mouseReleaseEvent(&newEvent); return true; } default: break; } } } return QToolBar::eventFilter(watched, event); } void KToolBar::actionEvent(QActionEvent *event) { if (event->type() == QEvent::ActionRemoved) { QWidget *widget = widgetForAction(event->action()); if (widget) { widget->removeEventFilter(this); Q_FOREACH (QWidget *child, widget->findChildren()) { child->removeEventFilter(this); } } } QToolBar::actionEvent(event); if (event->type() == QEvent::ActionAdded) { QWidget *widget = widgetForAction(event->action()); if (widget) { widget->installEventFilter(this); Q_FOREACH (QWidget *child, widget->findChildren()) { child->installEventFilter(this); } // Center widgets that do not have any use for more space. See bug 165274 if (!(widget->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag) // ... but do not center when using text besides icon in vertical toolbar. See bug 243196 && !(orientation() == Qt::Vertical && toolButtonStyle() == Qt::ToolButtonTextBesideIcon)) { const int index = layout()->indexOf(widget); if (index != -1) { layout()->itemAt(index)->setAlignment(Qt::AlignJustify); } } } } d->adjustSeparatorVisibility(); } bool KToolBar::toolBarsEditable() { return KToolBar::Private::s_editable; } void KToolBar::setToolBarsEditable(bool editable) { if (KToolBar::Private::s_editable != editable) { KToolBar::Private::s_editable = editable; } } void KToolBar::setToolBarsLocked(bool locked) { if (KToolBar::Private::s_locked != locked) { KToolBar::Private::s_locked = locked; Q_FOREACH (KMainWindow *mw, KMainWindow::memberList()) { Q_FOREACH (KToolBar *toolbar, mw->findChildren()) { toolbar->d->setLocked(locked); } } } } bool KToolBar::toolBarsLocked() { return KToolBar::Private::s_locked; } void KToolBar::emitToolbarStyleChanged() { #ifdef HAVE_DBUS QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KToolBar"), QStringLiteral("org.kde.KToolBar"), QStringLiteral("styleChanged")); QDBusConnection::sessionBus().send(message); #endif } #include "moc_ktoolbar.cpp" diff --git a/pics/breeze-dark/actions/16/format-stroke-color.svg b/pics/breeze-dark/actions/16/format-stroke-color.svg new file mode 100644 index 0000000000..9ac3a9efb1 --- /dev/null +++ b/pics/breeze-dark/actions/16/format-stroke-color.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/pics/breeze/actions/16/format-stroke-color.svg b/pics/breeze/actions/16/format-stroke-color.svg new file mode 100644 index 0000000000..45d922c357 --- /dev/null +++ b/pics/breeze/actions/16/format-stroke-color.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/pics/breeze/actions/22/format-stroke-color.svg b/pics/breeze/actions/22/format-stroke-color.svg new file mode 100644 index 0000000000..6327d4fd7e --- /dev/null +++ b/pics/breeze/actions/22/format-stroke-color.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/pics/breeze/actions/24/format-stroke-color.svg b/pics/breeze/actions/24/format-stroke-color.svg new file mode 100644 index 0000000000..f574d6c99b --- /dev/null +++ b/pics/breeze/actions/24/format-stroke-color.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/pics/hicolor/CMakeLists.txt b/pics/hicolor/CMakeLists.txt deleted file mode 100644 index 65b4ea1d32..0000000000 --- a/pics/hicolor/CMakeLists.txt +++ /dev/null @@ -1,73 +0,0 @@ -ecm_install_icons( - ICONS - 16-actions-borderpainter.png - 16-actions-format_decreaseindent.png - 16-actions-format_increaseindent.png - 16-actions-frame_edit.png - 16-actions-frame_formula.png - 16-actions-frame_image.png - 16-actions-frame_query.png - 16-actions-frame_spreadsheet.png - 16-actions-frame_text.png - 16-actions-inline_image.png - 16-actions-inline_table.png - 16-actions-insert-pagebreak.png - 16-actions-insert_table_row.png - 16-actions-kdb_form.png - 16-actions-kdb_table.png - 16-actions-linewidth.png - 16-apps-key_bindings.png - 16-apps-style.png - 22-actions-aobottom.png - 22-actions-aoleft.png - 22-actions-aoright.png - 22-actions-aotop.png - 22-actions-artistictext-attach-path.png - 22-actions-artistictext-detach-path.png - 22-actions-artistictext-tool.png - 22-actions-cancel.png - 22-actions-char.png - 22-actions-edittext.png - 22-actions-format_decreaseindent.png - 22-actions-format_increaseindent.png - 22-actions-frame_chart.png - 22-actions-frame_edit.png - 22-actions-frame_formula.png - 22-actions-frame_image.png - 22-actions-frame_query.png - 22-actions-frame_spreadsheet.png - 22-actions-frame_text.png - 22-actions-inline_image.png - 22-actions-inline_table.png - 22-actions-insert_table_row.png - 22-actions-lower.png - 22-actions-neonpen.png - 22-actions-ok.png - 22-actions-page.png - 22-actions-raise.png - 22-actions-select.png - 22-actions-shadowB.png - 22-actions-shadowLB.png - 22-actions-shadowL.png - 22-actions-shadowLU.png - 22-actions-shadow.png - 22-actions-shadowRB.png - 22-actions-shadowR.png - 22-actions-shadowRU.png - 22-actions-shadowU.png - 22-actions-toggle_docbrowser.png - 24-actions-insert-pagebreak.png - 32-actions-grid.png - 32-actions-insert-endnote.png - 32-actions-insert-footnote.png - 32-actions-insert-pagebreak.png - 32-actions-insert_table_row.png - 48-actions-format-line-spacing-simple.png - 48-apps-key_bindings.png - sc-actions-artistictext-attach-path.svg - sc-actions-artistictext-detach-path.svg - sc-actions-artistictext-tool.svg - sc-actions-send_backward.svgz - DESTINATION ${DATA_INSTALL_DIR}/krita/icons -) - diff --git a/pics/oxygen/CMakeLists.txt b/pics/oxygen/CMakeLists.txt deleted file mode 100644 index 80b0af8b75..0000000000 --- a/pics/oxygen/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -ecm_install_icons( - ICONS - 16-actions-curve-connector.png - 16-actions-lines-connector.png - 16-actions-object-align-horizontal-center-calligra.png - 16-actions-object-align-horizontal-left-calligra.png - 16-actions-object-align-horizontal-right-calligra.png - 16-actions-object-align-vertical-bottom-calligra.png - 16-actions-object-align-vertical-bottom-top-calligra.png - 16-actions-object-align-vertical-center-calligra.png - 16-actions-object-align-vertical-top-calligra.png - 16-actions-object-group-calligra.png - 16-actions-object-order-back-calligra.png - 16-actions-object-order-front-calligra.png - 16-actions-object-order-lower-calligra.png - 16-actions-object-order-raise-calligra.png - 16-actions-object-ungroup-calligra.png - 16-actions-standard-connector.png - 16-actions-straight-connector.png - 16-actions-table.png - 22-actions-table.png - 32-actions-insert-endnote.png - 32-actions-insert-footnote.png - 32-actions-insert-tableofcontents.png - 32-actions-shape-choose.png - 32-actions-table.png - 32-mimetypes-x-shape-connection.png - 32-mimetypes-x-shape-formula.png - 32-mimetypes-x-shape-image.png - 32-mimetypes-x-shape-text.png - 48-actions-table.png - sc-actions-table.svgz - DESTINATION ${DATA_INSTALL_DIR}/krita/icons - THEME oxygen - ) - - diff --git a/plugins/artistictextshape/ArtisticTextShapeFactory.cpp b/plugins/artistictextshape/ArtisticTextShapeFactory.cpp index 47f734c47d..f50935554d 100644 --- a/plugins/artistictextshape/ArtisticTextShapeFactory.cpp +++ b/plugins/artistictextshape/ArtisticTextShapeFactory.cpp @@ -1,51 +1,53 @@ /* This file is part of the KDE project * Copyright (C) 2007 Jan Hambrecht * * 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 "ArtisticTextShapeFactory.h" #include "ArtisticTextShape.h" #include #include +#include + #include #include ArtisticTextShapeFactory::ArtisticTextShapeFactory() : KoShapeFactoryBase(ArtisticTextShapeID, i18n("ArtisticTextShape")) { setToolTip(i18n("A shape which shows a single text line")); setIconName(koIconNameCStrNeeded("currently falls back to x-shape-text","x-shape-text-artistic")); setLoadingPriority( 5 ); setXmlElementNames(KoXmlNS::svg, QStringList("text")); } KoShape *ArtisticTextShapeFactory::createDefaultShape(KoDocumentResourceManager *) const { ArtisticTextShape * text = new ArtisticTextShape(); text->setBackground(QSharedPointer(new KoColorBackground( QColor( Qt::black)))); text->setPlainText(i18n("Artistic Text")); return text; } bool ArtisticTextShapeFactory::supports(const KoXmlElement &/*element*/, KoShapeLoadingContext &/*context*/) const { // the artistic text shape is embedded as svg into an odf file // so we tell the caller we do not support any element return false; } diff --git a/plugins/defaultTools/CMakeLists.txt b/plugins/defaultTools/CMakeLists.txt index 607727d2e4..6de078d5bd 100644 --- a/plugins/defaultTools/CMakeLists.txt +++ b/plugins/defaultTools/CMakeLists.txt @@ -1,57 +1,56 @@ project( defaulttools ) add_definitions(-DTRANSLATION_DOMAIN=\"krita_flaketools\") include_directories( ${TEXTLAYOUT_INCLUDES} # needed because ConnectionTool.cpp includes TextShape.h to get the id ${CMAKE_SOURCE_DIR}/libs/widgets ${FLAKE_INCLUDES} ${TEXTLAYOUT_INCLUDES} ) -add_subdirectory(pics) - - ########### Flake Plugin library ############### set ( defaulttools_SRCS Plugin.cpp defaulttool/DefaultTool.cpp defaulttool/DefaultToolFactory.cpp defaulttool/DefaultToolWidget.cpp defaulttool/DefaultToolArrangeWidget.cpp defaulttool/DefaultToolTransformWidget.cpp defaulttool/ShapeMoveStrategy.cpp defaulttool/ShapeResizeStrategy.cpp defaulttool/ShapeRotateStrategy.cpp defaulttool/ShapeShearStrategy.cpp defaulttool/SelectionDecorator.cpp defaulttool/SelectionTransformCommand.cpp guidestool/GuidesTool.cpp guidestool/GuidesToolFactory.cpp guidestool/GuidesToolOptionWidget.cpp guidestool/InsertGuidesToolOptionWidget.cpp connectionTool/ConnectionTool.cpp connectionTool/ConnectionToolFactory.cpp connectionTool/AddConnectionPointCommand.cpp connectionTool/RemoveConnectionPointCommand.cpp connectionTool/ChangeConnectionPointCommand.cpp connectionTool/MoveConnectionPointStrategy.cpp connectionTool/ConnectionPointWidget.cpp ) ki18n_wrap_ui(defaulttools_SRCS defaulttool/DefaultToolWidget.ui defaulttool/DefaultToolArrangeWidget.ui defaulttool/DefaultToolTransformWidget.ui guidestool/GuidesToolOptionWidget.ui guidestool/InsertGuidesToolOptionWidget.ui connectionTool/ConnectionPointWidget.ui ) +qt5_add_resources(defaulttools_SRCS defaulttools.qrc) + add_library(krita_flaketools MODULE ${defaulttools_SRCS}) kcoreaddons_desktop_to_json(krita_flaketools calligra_tool_defaults.desktop) -target_link_libraries(krita_flaketools kritaflake kritawidgets KF5::IconThemes ) +target_link_libraries(krita_flaketools kritaflake kritawidgets) install(TARGETS krita_flaketools DESTINATION ${CALLIGRA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/defaultTools/connectionTool/ConnectionTool.cpp b/plugins/defaultTools/connectionTool/ConnectionTool.cpp index 60417b4624..f9e009f8b2 100644 --- a/plugins/defaultTools/connectionTool/ConnectionTool.cpp +++ b/plugins/defaultTools/connectionTool/ConnectionTool.cpp @@ -1,956 +1,956 @@ /* This file is part of the KDE project * * Copyright (C) 2009 Thorsten Zachmann * Copyright (C) 2009 Jean-Nicolas Artaud * Copyright (C) 2011 Jan Hambrecht * * 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 "ConnectionTool.h" #include #include #include #include "AddConnectionPointCommand.h" #include "RemoveConnectionPointCommand.h" #include "ChangeConnectionPointCommand.h" #include "MoveConnectionPointStrategy.h" #include "ConnectionPointWidget.h" #include "../../textshape/TextShape.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ConnectionTool::ConnectionTool(KoCanvasBase * canvas) : KoToolBase(canvas) , m_editMode(Idle) , m_connectionType(KoConnectionShape::Standard) , m_currentShape(0) , m_activeHandle(-1) , m_currentStrategy(0) , m_oldSnapStrategies(0) , m_resetPaint(true) { QPixmap connectPixmap; - connectPixmap.load(KoResourcePaths::locate("data", "krita/icons/cursor_connect.png")); + connectPixmap.load(":/cursor_connect.png"); m_connectCursor = QCursor(connectPixmap, 4, 1); m_editConnectionPoint = new QAction(i18n("Edit connection points"), this); m_editConnectionPoint->setCheckable(true); addAction("toggle-edit-mode", m_editConnectionPoint); m_alignPercent = new QAction(QString("%"), this); m_alignPercent->setCheckable(true); addAction("align-relative", m_alignPercent); m_alignLeft = new QAction(koIcon("align-horizontal-left"), i18n("Align to left edge"), this); m_alignLeft->setCheckable(true); addAction("align-left", m_alignLeft); m_alignCenterH = new QAction(koIcon("align-horizontal-center"), i18n("Align to horizontal center"), this); m_alignCenterH->setCheckable(true); addAction("align-centerh", m_alignCenterH); m_alignRight = new QAction(koIcon("align-horizontal-right"), i18n("Align to right edge"), this); m_alignRight->setCheckable(true); addAction("align-right", m_alignRight); m_alignTop = new QAction(koIcon("align-vertical-top"), i18n("Align to top edge"), this); m_alignTop->setCheckable(true); addAction("align-top", m_alignTop); m_alignCenterV = new QAction(koIcon("align-vertical-center"), i18n("Align to vertical center"), this); m_alignCenterV->setCheckable(true); addAction("align-centerv", m_alignCenterV); m_alignBottom = new QAction(koIcon("align-vertical-bottom"), i18n("Align to bottom edge"), this); m_alignBottom->setCheckable(true); addAction("align-bottom", m_alignBottom); m_escapeAll = new QAction(koIcon("escape-direction-all"), i18n("Escape in all directions"), this); m_escapeAll->setCheckable(true); addAction("escape-all", m_escapeAll); m_escapeHorizontal = new QAction(koIcon("escape-direction-horizontal"), i18n("Escape in horizontal directions"), this); m_escapeHorizontal->setCheckable(true); addAction("escape-horizontal", m_escapeHorizontal); m_escapeVertical = new QAction(koIcon("escape-direction-vertical"), i18n("Escape in vertical directions"), this); m_escapeVertical->setCheckable(true); addAction("escape-vertical", m_escapeVertical); m_escapeLeft = new QAction(koIcon("escape-direction-left"), i18n("Escape in left direction"), this); m_escapeLeft->setCheckable(true); addAction("escape-left", m_escapeLeft); m_escapeRight = new QAction(koIcon("escape-direction-right"), i18n("Escape in right direction"), this); m_escapeRight->setCheckable(true); addAction("escape-right", m_escapeRight); m_escapeUp = new QAction(koIcon("escape-direction-up"), i18n("Escape in up direction"), this); m_escapeUp->setCheckable(true); addAction("escape-up", m_escapeUp); m_escapeDown = new QAction(koIcon("escape-direction-down"), i18n("Escape in down direction"), this); m_escapeDown->setCheckable(true); addAction("escape-down", m_escapeDown); m_alignHorizontal = new QActionGroup(this); m_alignHorizontal->setExclusive(true); m_alignHorizontal->addAction(m_alignLeft); m_alignHorizontal->addAction(m_alignCenterH); m_alignHorizontal->addAction(m_alignRight); connect(m_alignHorizontal, SIGNAL(triggered(QAction*)), this, SLOT(horizontalAlignChanged())); m_alignVertical = new QActionGroup(this); m_alignVertical->setExclusive(true); m_alignVertical->addAction(m_alignTop); m_alignVertical->addAction(m_alignCenterV); m_alignVertical->addAction(m_alignBottom); connect(m_alignVertical, SIGNAL(triggered(QAction*)), this, SLOT(verticalAlignChanged())); m_alignRelative = new QActionGroup(this); m_alignRelative->setExclusive(true); m_alignRelative->addAction(m_alignPercent); connect(m_alignRelative, SIGNAL(triggered(QAction*)), this, SLOT(relativeAlignChanged())); m_escapeDirections = new QActionGroup(this); m_escapeDirections->setExclusive(true); m_escapeDirections->addAction(m_escapeAll); m_escapeDirections->addAction(m_escapeHorizontal); m_escapeDirections->addAction(m_escapeVertical); m_escapeDirections->addAction(m_escapeLeft); m_escapeDirections->addAction(m_escapeRight); m_escapeDirections->addAction(m_escapeUp); m_escapeDirections->addAction(m_escapeDown); connect(m_escapeDirections, SIGNAL(triggered(QAction*)), this, SLOT(escapeDirectionChanged())); connect(this, SIGNAL(connectionPointEnabled(bool)), m_alignHorizontal, SLOT(setEnabled(bool))); connect(this, SIGNAL(connectionPointEnabled(bool)), m_alignVertical, SLOT(setEnabled(bool))); connect(this, SIGNAL(connectionPointEnabled(bool)), m_alignRelative, SLOT(setEnabled(bool))); connect(this, SIGNAL(connectionPointEnabled(bool)), m_escapeDirections, SLOT(setEnabled(bool))); resetEditMode(); } ConnectionTool::~ConnectionTool() { } void ConnectionTool::paint(QPainter &painter, const KoViewConverter &converter) { // get the correctly sized rect for painting handles QRectF handleRect = handlePaintRect(QPointF()); painter.setRenderHint(QPainter::Antialiasing, true); if (m_currentStrategy) { painter.save(); m_currentStrategy->paint(painter, converter); painter.restore(); } QList shapes = canvas()->shapeManager()->shapes(); for (QList::const_iterator end = shapes.constBegin(); end != shapes.constEnd(); ++end) { KoShape* shape = *end; if (!dynamic_cast(shape)) { // only paint connection points of textShapes not inside a tos container and other shapes if (shape->shapeId() == TextShape_SHAPEID && dynamic_cast(shape->parent())) continue; painter.save(); painter.setPen(Qt::black); QTransform transform = shape->absoluteTransformation(0); KoShape::applyConversion(painter, converter); // Draw all the connection points of the shape KoConnectionPoints connectionPoints = shape->connectionPoints(); KoConnectionPoints::const_iterator cp = connectionPoints.constBegin(); KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd(); for(; cp != lastCp; ++cp) { if (shape == findNonConnectionShapeAtPosition(transform.map(cp.value().position)) ) { handleRect.moveCenter(transform.map(cp.value().position)); painter.setBrush(cp.key() == m_activeHandle && shape == m_currentShape ? Qt::red : Qt::white); painter.drawRect(handleRect); } } painter.restore(); } } // paint connection points or connection handles depending // on the shape the mouse is currently if (m_currentShape && m_editMode == EditConnection) { KoConnectionShape *connectionShape = dynamic_cast(m_currentShape); if (connectionShape) { int radius = handleRadius()+1; int handleCount = connectionShape->handleCount(); for(int i = 0; i < handleCount; ++i) { painter.save(); painter.setPen(Qt::blue); painter.setBrush(i == m_activeHandle ? Qt::red : Qt::white); painter.setTransform(connectionShape->absoluteTransformation(&converter) * painter.transform()); connectionShape->paintHandle(painter, converter, i, radius); painter.restore(); } } } } void ConnectionTool::repaintDecorations() { const qreal radius = handleRadius(); QRectF repaintRect; if (m_currentShape) { repaintRect = m_currentShape->boundingRect(); canvas()->updateCanvas(repaintRect.adjusted(-radius, -radius, radius, radius)); KoConnectionShape * connectionShape = dynamic_cast(m_currentShape); if (!m_resetPaint && m_currentShape->isVisible(true) && !connectionShape) { // only paint connection points of textShapes not inside a tos container and other shapes if ( !(m_currentShape->shapeId() == TextShape_SHAPEID && dynamic_cast(m_currentShape->parent())) ) { KoConnectionPoints connectionPoints = m_currentShape->connectionPoints(); KoConnectionPoints::const_iterator cp = connectionPoints.constBegin(); KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd(); for(; cp != lastCp; ++cp) { repaintRect = handleGrabRect(m_currentShape->shapeToDocument(cp.value().position)); canvas()->updateCanvas(repaintRect.adjusted(-radius, -radius, radius, radius)); } } } if (m_editMode == EditConnection) { if (connectionShape) { QPointF handlePos = connectionShape->handlePosition(m_activeHandle); handlePos = connectionShape->shapeToDocument(handlePos); repaintRect = handlePaintRect(handlePos); canvas()->updateCanvas(repaintRect.adjusted(-radius, -radius, radius, radius)); } } } if (m_resetPaint) { QList shapes = canvas()->shapeManager()->shapes(); for (QList::const_iterator end = shapes.constBegin(); end != shapes.constEnd(); ++end) { KoShape* shape = *end; if (!dynamic_cast(shape)) { // only paint connection points of textShapes not inside a tos container and other shapes if (shape->shapeId() == TextShape_SHAPEID && dynamic_cast(shape->parent())) continue; KoConnectionPoints connectionPoints = shape->connectionPoints(); KoConnectionPoints::const_iterator cp = connectionPoints.constBegin(); KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd(); for(; cp != lastCp; ++cp) { repaintRect = handleGrabRect(shape->shapeToDocument(cp.value().position)); canvas()->updateCanvas(repaintRect.adjusted(-radius, -radius, radius, radius)); } } } } m_resetPaint = false; } void ConnectionTool::mousePressEvent(KoPointerEvent * event) { if (!m_currentShape) { return; } KoShape * hitShape = findShapeAtPosition(event->point); int hitHandle = handleAtPoint(m_currentShape, event->point); if (m_editMode == EditConnection && hitHandle >= 0) { // create connection handle change strategy m_currentStrategy = new KoPathConnectionPointStrategy(this, dynamic_cast(m_currentShape), hitHandle); } else if (m_editMode == EditConnectionPoint) { if (hitHandle >= KoConnectionPoint::FirstCustomConnectionPoint) { // start moving custom connection point m_currentStrategy = new MoveConnectionPointStrategy(m_currentShape, hitHandle, this); } } else if (m_editMode == CreateConnection) { // create new connection shape, connect it to the active connection point // and start editing the new connection // create the new connection shape KoShapeFactoryBase *factory = KoShapeRegistry::instance()->value("KoConnectionShape"); KoShape *shape = factory->createDefaultShape(canvas()->shapeController()->resourceManager()); KoConnectionShape * connectionShape = dynamic_cast(shape); if (!connectionShape) { delete shape; resetEditMode(); return; } //set connection type connectionShape->setType(m_connectionType); // get the position of the connection point we start our connection from QPointF cp = m_currentShape->shapeToDocument(m_currentShape->connectionPoint(m_activeHandle).position); // move both handles to that point connectionShape->moveHandle(0, cp); connectionShape->moveHandle(1, cp); // connect the first handle of the connection shape to our connection point if (!connectionShape->connectFirst(m_currentShape, m_activeHandle)) { delete shape; resetEditMode(); return; } //add connector label connectionShape->createTextShape(canvas()->shapeController()->resourceManager()); connectionShape->setPlainText(""); // create the connection edit strategy from the path tool m_currentStrategy = new KoPathConnectionPointStrategy(this, connectionShape, 1); if (!m_currentStrategy) { delete shape; resetEditMode(); return; } // update our handle data setEditMode(m_editMode, shape, 1); // add connection shape to the shape manager so it gets painted canvas()->shapeManager()->addShape(connectionShape); } else { // pressing on a shape in idle mode switches to corresponding edit mode if (hitShape) { if (dynamic_cast(hitShape)) { int hitHandle = handleAtPoint(hitShape, event->point); setEditMode(EditConnection, hitShape, hitHandle); if (hitHandle >= 0) { // start editing connection shape m_currentStrategy = new KoPathConnectionPointStrategy(this, dynamic_cast(m_currentShape), m_activeHandle); } } } else { resetEditMode(); } } } void ConnectionTool::mouseMoveEvent(KoPointerEvent *event) { if (m_currentStrategy) { repaintDecorations(); if (m_editMode != EditConnection && m_editMode != CreateConnection) { QPointF snappedPos = canvas()->snapGuide()->snap(event->point, event->modifiers()); m_currentStrategy->handleMouseMove(snappedPos, event->modifiers()); } else { m_currentStrategy->handleMouseMove(event->point, event->modifiers()); } repaintDecorations(); } else if (m_editMode == EditConnectionPoint) { KoShape *hoverShape = findNonConnectionShapeAtPosition(event->point);//TODO exclude connectors, need snap guide maybe? if (hoverShape) { m_currentShape = hoverShape; Q_ASSERT(m_currentShape); // check if we should highlight another connection point int handle = handleAtPoint(m_currentShape, event->point); if (handle >= 0) { setEditMode(m_editMode, m_currentShape, handle); useCursor(handle >= KoConnectionPoint::FirstCustomConnectionPoint ? Qt::SizeAllCursor : Qt::ArrowCursor); } else { updateStatusText(); useCursor(Qt::CrossCursor); } }else { m_currentShape = 0; useCursor(Qt::ArrowCursor); } } else if (m_editMode == EditConnection) { Q_ASSERT(m_currentShape); KoShape *hoverShape = findShapeAtPosition(event->point); // check if we should highlight another connection handle int handle = handleAtPoint(m_currentShape, event->point); setEditMode(m_editMode, m_currentShape, handle); if (m_activeHandle == KoConnectionShape::StartHandle || m_activeHandle == KoConnectionShape::EndHandle) { useCursor(Qt::SizeAllCursor); } else if (m_activeHandle >= KoConnectionShape::ControlHandle_1) { } else if (hoverShape && hoverShape != m_currentShape) { useCursor(Qt::PointingHandCursor); } else { useCursor(Qt::ArrowCursor); } } else {// Idle and no current strategy KoShape *hoverShape = findShapeAtPosition(event->point); int hoverHandle = -1; if (hoverShape) { KoConnectionShape * connectionShape = dynamic_cast(hoverShape); if (!connectionShape) { QPointF snappedPos = canvas()->snapGuide()->snap(event->point, event->modifiers()); hoverHandle = handleAtPoint(hoverShape, snappedPos); setEditMode(hoverHandle >= 0 ? CreateConnection : Idle, hoverShape, hoverHandle); } useCursor(hoverHandle >= 0 ? m_connectCursor : Qt::PointingHandCursor); } else { useCursor(Qt::ArrowCursor); } } } void ConnectionTool::mouseReleaseEvent(KoPointerEvent *event) { if (m_currentStrategy) { if (m_editMode == CreateConnection) { // check if connection handles have a minimal distance KoConnectionShape * connectionShape = dynamic_cast(m_currentShape); Q_ASSERT(connectionShape); // get both handle positions in document coordinates QPointF p1 = connectionShape->shapeToDocument(connectionShape->handlePosition(0)); QPointF p2 = connectionShape->shapeToDocument(connectionShape->handlePosition(1)); int grabDistance = grabSensitivity(); // use grabbing sensitivity as minimal distance threshold if (squareDistance(p1, p2) < grabDistance*grabDistance) { // minimal distance was not reached, so we have to undo the started work: // - cleanup and delete the strategy // - remove connection shape from shape manager and delete it // - reset edit mode to last state delete m_currentStrategy; m_currentStrategy = 0; repaintDecorations(); canvas()->shapeManager()->remove(m_currentShape); setEditMode(m_editMode, connectionShape->firstShape(), connectionShape->firstConnectionId()); repaintDecorations(); delete connectionShape; return; } else { // finalize adding the new connection shape with an undo command KUndo2Command * cmd = canvas()->shapeController()->addShape(m_currentShape); canvas()->addCommand(cmd); setEditMode(EditConnection, m_currentShape, KoConnectionShape::StartHandle); } } m_currentStrategy->finishInteraction(event->modifiers()); // TODO: Add parent command to KoInteractionStrategy::createCommand // so that we can have a single command to undo for the user KUndo2Command *command = m_currentStrategy->createCommand(); if (command) canvas()->addCommand(command); delete m_currentStrategy; m_currentStrategy = 0; } updateStatusText(); } void ConnectionTool::mouseDoubleClickEvent(KoPointerEvent *event) { if (m_editMode == EditConnectionPoint) { repaintDecorations(); //quit EditConnectionPoint mode when double click blank region on canvas if (!m_currentShape) { resetEditMode(); return; } //add connection point when double click a shape //remove connection point when double click a existed connection point int handleId = handleAtPoint(m_currentShape, event->point); if (handleId < 0) { QPointF mousePos = canvas()->snapGuide()->snap(event->point, event->modifiers()); QPointF point = m_currentShape->documentToShape(mousePos); canvas()->addCommand(new AddConnectionPointCommand(m_currentShape, point)); } else { canvas()->addCommand(new RemoveConnectionPointCommand(m_currentShape, handleId)); } setEditMode(m_editMode, m_currentShape, -1); } else { //deactivate connection tool when double click blank region on canvas KoShape *hitShape = findShapeAtPosition(event->point); if (!hitShape) { deactivate(); emit done(); } else if (dynamic_cast(hitShape)) { repaintDecorations(); setEditMode(EditConnection, m_currentShape, -1); //TODO: temporarily activate text tool to edit connection path } } } void ConnectionTool::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { deactivate(); emit done(); } else if (event->key() == Qt::Key_Backspace) { deleteSelection(); event->accept(); } } void ConnectionTool::activate(ToolActivation, const QSet &) { // save old enabled snap strategies, set bounding box snap strategy m_oldSnapStrategies = canvas()->snapGuide()->enabledSnapStrategies(); canvas()->snapGuide()->enableSnapStrategies(KoSnapGuide::BoundingBoxSnapping); canvas()->snapGuide()->reset(); m_resetPaint = true; repaintDecorations(); } void ConnectionTool::deactivate() { // Put everything to 0 to be able to begin a new shape properly delete m_currentStrategy; m_currentStrategy = 0; resetEditMode(); m_resetPaint = true; repaintDecorations(); // restore previously set snap strategies canvas()->snapGuide()->enableSnapStrategies(m_oldSnapStrategies); canvas()->snapGuide()->reset(); } qreal ConnectionTool::squareDistance(const QPointF &p1, const QPointF &p2) const { // Square of the distance const qreal dx = p2.x() - p1.x(); const qreal dy = p2.y() - p1.y(); return dx*dx + dy*dy; } KoShape * ConnectionTool::findShapeAtPosition(const QPointF &position) const { QList shapes = canvas()->shapeManager()->shapesAt(handleGrabRect(position)); if (!shapes.isEmpty()) { qSort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex); // we want to priorize connection shape handles, even if the connection shape // is not at the top of the shape stack at the mouse position KoConnectionShape *connectionShape = nearestConnectionShape(shapes, position); // use best connection shape or first shape from stack (last in the list) if not found if (connectionShape) { return connectionShape; } else { for (QList::const_iterator end = shapes.constEnd()-1; end >= shapes.constBegin(); --end) { KoShape* shape = *end; if (!dynamic_cast(shape) && shape->shapeId() != TextShape_SHAPEID) { return shape; } } } } return 0; } KoShape * ConnectionTool::findNonConnectionShapeAtPosition(const QPointF &position) const { QList shapes = canvas()->shapeManager()->shapesAt(handleGrabRect(position)); if (!shapes.isEmpty()) { qSort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex); for (QList::const_iterator end = shapes.constEnd()-1; end >= shapes.constBegin(); --end) { KoShape* shape = *end; if (!dynamic_cast(shape) && shape->shapeId() != TextShape_SHAPEID) { return shape; } } } return 0; } int ConnectionTool::handleAtPoint(KoShape *shape, const QPointF &mousePoint) const { if (!shape) return -1; const QPointF shapePoint = shape->documentToShape(mousePoint); KoConnectionShape * connectionShape = dynamic_cast(shape); if (connectionShape) { // check connection shape handles return connectionShape->handleIdAt(handleGrabRect(shapePoint)); } else { // check connection points int grabDistance = grabSensitivity(); qreal minDistance = HUGE_VAL; int handleId = -1; KoConnectionPoints connectionPoints = shape->connectionPoints(); KoConnectionPoints::const_iterator cp = connectionPoints.constBegin(); KoConnectionPoints::const_iterator lastCp = connectionPoints.constEnd(); for(; cp != lastCp; ++cp) { qreal d = squareDistance(shapePoint, cp.value().position); if (d <= grabDistance && d < minDistance) { handleId = cp.key(); minDistance = d; } } return handleId; } } KoConnectionShape * ConnectionTool::nearestConnectionShape(const QList &shapes, const QPointF &mousePos) const { int grabDistance = grabSensitivity(); KoConnectionShape * nearestConnectionShape = 0; qreal minSquaredDistance = HUGE_VAL; const qreal maxSquaredDistance = grabDistance*grabDistance; foreach(KoShape *shape, shapes) { KoConnectionShape * connectionShape = dynamic_cast(shape); if (!connectionShape || !connectionShape->isParametricShape()) continue; // convert document point to shape coordinates QPointF p = connectionShape->documentToShape(mousePos); // our region of interest, i.e. a region around our mouse position QRectF roi = handleGrabRect(p); // check all segments of this shape which intersect the region of interest QList segments = connectionShape->segmentsAt(roi); foreach (const KoPathSegment &s, segments) { qreal nearestPointParam = s.nearestPoint(p); QPointF nearestPoint = s.pointAt(nearestPointParam); QPointF diff = p - nearestPoint; qreal squaredDistance = diff.x()*diff.x() + diff.y()*diff.y(); // are we within the allowed distance ? if (squaredDistance > maxSquaredDistance) continue; // are we closer to the last closest point ? if (squaredDistance < minSquaredDistance) { nearestConnectionShape = connectionShape; minSquaredDistance = squaredDistance; } } } return nearestConnectionShape; } void ConnectionTool::setEditMode(EditMode mode, KoShape *currentShape, int handle) { repaintDecorations(); m_editMode = mode; if (m_currentShape != currentShape) { KoConnectionShape * connectionShape = dynamic_cast(currentShape); foreach (KoShapeConfigWidgetBase *cw, m_connectionShapeWidgets) { if (connectionShape) cw->open(currentShape); } } if (mode == Idle) { emit sendConnectionType(m_connectionType); } m_currentShape = currentShape; m_activeHandle = handle; repaintDecorations(); updateActions(); updateStatusText(); } void ConnectionTool::resetEditMode() { m_connectionType = KoConnectionShape::Standard; setEditMode(Idle, 0, -1); emit sendConnectionPointEditState(false); } void ConnectionTool::updateActions() { const bool connectionPointSelected = m_editMode == EditConnectionPoint && m_activeHandle >= 0; if (connectionPointSelected) { KoConnectionPoint cp = m_currentShape->connectionPoint(m_activeHandle); m_alignPercent->setChecked(false); foreach(QAction *action, m_alignHorizontal->actions()) action->setChecked(false); foreach(QAction *action, m_alignVertical->actions()) action->setChecked(false); switch(cp.alignment) { case KoConnectionPoint::AlignNone: m_alignPercent->setChecked(true); break; case KoConnectionPoint::AlignTopLeft: m_alignLeft->setChecked(true); m_alignTop->setChecked(true); break; case KoConnectionPoint::AlignTop: m_alignCenterH->setChecked(true); m_alignTop->setChecked(true); break; case KoConnectionPoint::AlignTopRight: m_alignRight->setChecked(true); m_alignTop->setChecked(true); break; case KoConnectionPoint::AlignLeft: m_alignLeft->setChecked(true); m_alignCenterV->setChecked(true); break; case KoConnectionPoint::AlignCenter: m_alignCenterH->setChecked(true); m_alignCenterV->setChecked(true); break; case KoConnectionPoint::AlignRight: m_alignRight->setChecked(true); m_alignCenterV->setChecked(true); break; case KoConnectionPoint::AlignBottomLeft: m_alignLeft->setChecked(true); m_alignBottom->setChecked(true); break; case KoConnectionPoint::AlignBottom: m_alignCenterH->setChecked(true); m_alignBottom->setChecked(true); break; case KoConnectionPoint::AlignBottomRight: m_alignRight->setChecked(true); m_alignBottom->setChecked(true); break; } foreach(QAction *action, m_escapeDirections->actions()) action->setChecked(false); switch(cp.escapeDirection) { case KoConnectionPoint::AllDirections: m_escapeAll->setChecked(true); break; case KoConnectionPoint::HorizontalDirections: m_escapeHorizontal->setChecked(true); break; case KoConnectionPoint::VerticalDirections: m_escapeVertical->setChecked(true); break; case KoConnectionPoint::LeftDirection: m_escapeLeft->setChecked(true); break; case KoConnectionPoint::RightDirection: m_escapeRight->setChecked(true); break; case KoConnectionPoint::UpDirection: m_escapeUp->setChecked(true); break; case KoConnectionPoint::DownDirection: m_escapeDown->setChecked(true); break; } } emit connectionPointEnabled(connectionPointSelected); } void ConnectionTool::updateStatusText() { switch(m_editMode) { case Idle: if (m_currentShape) { if (dynamic_cast(m_currentShape)) { if (m_activeHandle >= 0) emit statusTextChanged(i18n("Drag to edit connection.")); else emit statusTextChanged(i18n("Double click connection or press delete to remove it.")); } else if (m_activeHandle < 0) { emit statusTextChanged(i18n("Click to edit connection points.")); } } else { emit statusTextChanged(""); } break; case EditConnection: if (m_activeHandle >= 0) emit statusTextChanged(i18n("Drag to edit connection.")); else emit statusTextChanged(i18n("Double click connection or press delete to remove it.")); break; case EditConnectionPoint: if (m_activeHandle >= KoConnectionPoint::FirstCustomConnectionPoint) emit statusTextChanged(i18n("Drag to move connection point. Double click connection or press delete to remove it.")); else if (m_activeHandle >= 0) emit statusTextChanged(i18n("Double click connection point or press delete to remove it.")); else emit statusTextChanged(i18n("Double click to add connection point.")); break; case CreateConnection: emit statusTextChanged(i18n("Drag to create new connection.")); break; default: emit statusTextChanged(""); } } QList > ConnectionTool::createOptionWidgets() { QList > list; m_connectionShapeWidgets.clear(); KoShapeFactoryBase * factory = KoShapeRegistry::instance()->get(KOCONNECTIONSHAPEID); if (factory) { QList widgets = factory->createShapeOptionPanels(); foreach(KoShapeConfigWidgetBase *cw, widgets) { if (cw->showOnShapeCreate() || !cw->showOnShapeSelect()) { delete cw; continue; } connect(cw, SIGNAL(propertyChanged()), this, SLOT(connectionChanged())); KoConnectionShapeConfigWidget* cw2 = (KoConnectionShapeConfigWidget*)cw; if (cw2) { connect(cw2, SIGNAL(connectionTypeChanged(int)), this, SLOT(getConnectionType(int))); connect(this, SIGNAL(sendConnectionType(int)), cw2, SLOT(setConnectionType(int))); } m_connectionShapeWidgets.append(cw); cw->setWindowTitle(i18n("Connection")); list.append(cw); } } KoStrokeConfigWidget *strokeWidget = new KoStrokeConfigWidget(0); strokeWidget->setWindowTitle(i18n("Line")); strokeWidget->setCanvas(canvas()); list.append(strokeWidget); ConnectionPointWidget *connectPoint = new ConnectionPointWidget(this); connectPoint->setWindowTitle(i18n("Connection Point")); list.append(connectPoint); return list; } void ConnectionTool::horizontalAlignChanged() { if (m_alignPercent->isChecked()) { m_alignPercent->setChecked(false); m_alignTop->setChecked(true); } updateConnectionPoint(); } void ConnectionTool::verticalAlignChanged() { if (m_alignPercent->isChecked()) { m_alignPercent->setChecked(false); m_alignLeft->setChecked(true); } updateConnectionPoint(); } void ConnectionTool::relativeAlignChanged() { foreach(QAction *action, m_alignHorizontal->actions()) action->setChecked(false); foreach(QAction *action, m_alignVertical->actions()) action->setChecked(false); m_alignPercent->setChecked(true); updateConnectionPoint(); } void ConnectionTool::updateConnectionPoint() { if (m_editMode == EditConnectionPoint && m_currentShape && m_activeHandle >= 0) { KoConnectionPoint oldPoint = m_currentShape->connectionPoint(m_activeHandle); KoConnectionPoint newPoint = oldPoint; if (m_alignPercent->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignNone; } else if (m_alignLeft->isChecked() && m_alignTop->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignTopLeft; } else if (m_alignCenterH->isChecked() && m_alignTop->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignTop; } else if (m_alignRight->isChecked() && m_alignTop->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignTopRight; } else if (m_alignLeft->isChecked() && m_alignCenterV->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignLeft; } else if (m_alignCenterH->isChecked() && m_alignCenterV->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignCenter; } else if (m_alignRight->isChecked() && m_alignCenterV->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignRight; } else if (m_alignLeft->isChecked() && m_alignBottom->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignBottomLeft; } else if (m_alignCenterH->isChecked() && m_alignBottom->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignBottom; } else if (m_alignRight->isChecked() && m_alignBottom->isChecked()) { newPoint.alignment = KoConnectionPoint::AlignBottomRight; } canvas()->addCommand(new ChangeConnectionPointCommand(m_currentShape, m_activeHandle, oldPoint, newPoint)); } } void ConnectionTool::escapeDirectionChanged() { if (m_editMode == EditConnectionPoint && m_currentShape && m_activeHandle >= 0) { KoConnectionPoint oldPoint = m_currentShape->connectionPoint(m_activeHandle); KoConnectionPoint newPoint = oldPoint; QAction * checkedAction = m_escapeDirections->checkedAction(); if (checkedAction == m_escapeAll) { newPoint.escapeDirection = KoConnectionPoint::AllDirections; } else if (checkedAction == m_escapeHorizontal) { newPoint.escapeDirection = KoConnectionPoint::HorizontalDirections; } else if (checkedAction == m_escapeVertical) { newPoint.escapeDirection = KoConnectionPoint::VerticalDirections; } else if (checkedAction == m_escapeLeft) { newPoint.escapeDirection = KoConnectionPoint::LeftDirection; } else if (checkedAction == m_escapeRight) { newPoint.escapeDirection = KoConnectionPoint::RightDirection; } else if (checkedAction == m_escapeUp) { newPoint.escapeDirection = KoConnectionPoint::UpDirection; } else if (checkedAction == m_escapeDown) { newPoint.escapeDirection = KoConnectionPoint::DownDirection; } canvas()->addCommand(new ChangeConnectionPointCommand(m_currentShape, m_activeHandle, oldPoint, newPoint)); } } void ConnectionTool::connectionChanged() { if (m_editMode != EditConnection) { return; } KoConnectionShape * connectionShape = dynamic_cast(m_currentShape); if (!connectionShape) return; foreach(KoShapeConfigWidgetBase *cw, m_connectionShapeWidgets) { canvas()->addCommand(cw->createCommand()); } } void ConnectionTool::deleteSelection() { if (m_editMode == EditConnectionPoint && m_currentShape && m_activeHandle >= 0) { repaintDecorations(); canvas()->addCommand(new RemoveConnectionPointCommand(m_currentShape, m_activeHandle)); setEditMode(m_editMode, m_currentShape, -1); } else if (m_editMode == EditConnection && m_currentShape) { repaintDecorations(); canvas()->addCommand(canvas()->shapeController()->removeShape(m_currentShape)); resetEditMode(); } } void ConnectionTool::getConnectionType(int type) { if (m_editMode == Idle) m_connectionType = (KoConnectionShape::Type)type; } void ConnectionTool::toggleConnectionPointEditMode(int state) { if (state == Qt::Checked) setEditMode(EditConnectionPoint, 0, -1); else if (state == Qt::Unchecked) setEditMode(Idle, 0, -1); else return; } diff --git a/plugins/defaultTools/defaulttool/DefaultTool.cpp b/plugins/defaultTools/defaulttool/DefaultTool.cpp index 7e263ea758..8dac83e9fc 100644 --- a/plugins/defaultTools/defaulttool/DefaultTool.cpp +++ b/plugins/defaultTools/defaulttool/DefaultTool.cpp @@ -1,1325 +1,1325 @@ /* This file is part of the KDE project Copyright (C) 2006-2008 Thorsten Zachmann Copyright (C) 2006-2010 Thomas Zander Copyright (C) 2008-2009 Jan Hambrecht Copyright (C) 2008 C. Boemann 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 "DefaultTool.h" #include "DefaultToolWidget.h" #include "DefaultToolArrangeWidget.h" #include "SelectionDecorator.h" #include "ShapeMoveStrategy.h" #include "ShapeRotateStrategy.h" #include "ShapeShearStrategy.h" #include "ShapeResizeStrategy.h" #include "guidestool/GuidesTool.h" #include "guidestool/GuidesToolFactory.h" // for the ID #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define HANDLE_DISTANCE 10 class NopInteractionStrategy : public KoInteractionStrategy { public: explicit NopInteractionStrategy(KoToolBase* parent) : KoInteractionStrategy(parent) {} virtual KUndo2Command* createCommand() { return 0; } virtual void handleMouseMove(const QPointF& /*mouseLocation*/, Qt::KeyboardModifiers /*modifiers*/) {} virtual void finishInteraction(Qt::KeyboardModifiers /*modifiers*/) {} }; class SelectionHandler : public KoToolSelection { public: SelectionHandler(DefaultTool *parent) : KoToolSelection(parent), m_selection(parent->koSelection()) { Q_ASSERT(m_selection); } bool hasSelection() { return m_selection->count(); } private: KoSelection *m_selection; }; class DefaultTool::GuideLine { public: GuideLine() : m_orientation(Qt::Horizontal), m_index(0), m_valid(false), m_selected(false) { } GuideLine(Qt::Orientation orientation, uint index) : m_orientation(orientation), m_index(index), m_valid(true), m_selected(false) { } bool isValid() const { return m_valid; } bool isSelected() const { return m_selected; } void select() { m_selected = true; } uint index() const { return m_index; } Qt::Orientation orientation() const { return m_orientation; } private: Qt::Orientation m_orientation; uint m_index; bool m_valid; bool m_selected; }; DefaultTool::DefaultTool(KoCanvasBase *canvas) : KoInteractionTool(canvas), m_lastHandle(KoFlake::NoHandle), m_hotPosition(KoFlake::TopLeftCorner), m_mouseWasInsideHandles(false), m_moveCommand(0), m_selectionHandler(new SelectionHandler(this)), m_customEventStrategy(0), m_guideLine(new GuideLine()) { setupActions(); QPixmap rotatePixmap, shearPixmap; - rotatePixmap.load(KoResourcePaths::locate("data", "krita/icons/cursor_rotate.png")); + rotatePixmap.load(":/cursor_rotate.png"); Q_ASSERT(!rotatePixmap.isNull()); - shearPixmap.load(KoResourcePaths::locate("data", "krita/icons/cursor_shear.png")); + shearPixmap.load(":/cursor_shear.png"); Q_ASSERT(!shearPixmap.isNull()); m_rotateCursors[0] = QCursor(rotatePixmap.transformed(QTransform().rotate(45))); m_rotateCursors[1] = QCursor(rotatePixmap.transformed(QTransform().rotate(90))); m_rotateCursors[2] = QCursor(rotatePixmap.transformed(QTransform().rotate(135))); m_rotateCursors[3] = QCursor(rotatePixmap.transformed(QTransform().rotate(180))); m_rotateCursors[4] = QCursor(rotatePixmap.transformed(QTransform().rotate(225))); m_rotateCursors[5] = QCursor(rotatePixmap.transformed(QTransform().rotate(270))); m_rotateCursors[6] = QCursor(rotatePixmap.transformed(QTransform().rotate(315))); m_rotateCursors[7] = QCursor(rotatePixmap); /* m_rotateCursors[0] = QCursor(Qt::RotateNCursor); m_rotateCursors[1] = QCursor(Qt::RotateNECursor); m_rotateCursors[2] = QCursor(Qt::RotateECursor); m_rotateCursors[3] = QCursor(Qt::RotateSECursor); m_rotateCursors[4] = QCursor(Qt::RotateSCursor); m_rotateCursors[5] = QCursor(Qt::RotateSWCursor); m_rotateCursors[6] = QCursor(Qt::RotateWCursor); m_rotateCursors[7] = QCursor(Qt::RotateNWCursor); */ m_shearCursors[0] = QCursor(shearPixmap); m_shearCursors[1] = QCursor(shearPixmap.transformed(QTransform().rotate(45))); m_shearCursors[2] = QCursor(shearPixmap.transformed(QTransform().rotate(90))); m_shearCursors[3] = QCursor(shearPixmap.transformed(QTransform().rotate(135))); m_shearCursors[4] = QCursor(shearPixmap.transformed(QTransform().rotate(180))); m_shearCursors[5] = QCursor(shearPixmap.transformed(QTransform().rotate(225))); m_shearCursors[6] = QCursor(shearPixmap.transformed(QTransform().rotate(270))); m_shearCursors[7] = QCursor(shearPixmap.transformed(QTransform().rotate(315))); m_sizeCursors[0] = Qt::SizeVerCursor; m_sizeCursors[1] = Qt::SizeBDiagCursor; m_sizeCursors[2] = Qt::SizeHorCursor; m_sizeCursors[3] = Qt::SizeFDiagCursor; m_sizeCursors[4] = Qt::SizeVerCursor; m_sizeCursors[5] = Qt::SizeBDiagCursor; m_sizeCursors[6] = Qt::SizeHorCursor; m_sizeCursors[7] = Qt::SizeFDiagCursor; KoShapeManager * manager = canvas->shapeManager(); connect(manager, SIGNAL(selectionChanged()), this, SLOT(updateActions())); } DefaultTool::~DefaultTool() { delete m_guideLine; } bool DefaultTool::wantsAutoScroll() const { return true; } void DefaultTool::setupActions() { QAction * actionBringToFront = new QAction(koIcon("object-order-front-calligra"), i18n("Bring to &Front"), this); addAction("object_order_front", actionBringToFront); actionBringToFront->setShortcut(QKeySequence("Ctrl+Shift+]")); connect(actionBringToFront, SIGNAL(triggered()), this, SLOT(selectionBringToFront())); QAction * actionRaise = new QAction(koIcon("object-order-raise-calligra"), i18n("&Raise"), this); addAction("object_order_raise", actionRaise); actionRaise->setShortcut(QKeySequence("Ctrl+]")); connect(actionRaise, SIGNAL(triggered()), this, SLOT(selectionMoveUp())); QAction * actionLower = new QAction(koIcon("object-order-lower-calligra"), i18n("&Lower"), this); addAction("object_order_lower", actionLower); actionLower->setShortcut(QKeySequence("Ctrl+[")); connect(actionLower, SIGNAL(triggered()), this, SLOT(selectionMoveDown())); QAction * actionSendToBack = new QAction(koIcon("object-order-back-calligra"), i18n("Send to &Back"), this); addAction("object_order_back", actionSendToBack); actionSendToBack->setShortcut(QKeySequence("Ctrl+Shift+[")); connect(actionSendToBack, SIGNAL(triggered()), this, SLOT(selectionSendToBack())); QAction * actionAlignLeft = new QAction(koIcon("object-align-horizontal-left-calligra"), i18n("Align Left"), this); addAction("object_align_horizontal_left", actionAlignLeft); connect(actionAlignLeft, SIGNAL(triggered()), this, SLOT(selectionAlignHorizontalLeft())); QAction * actionAlignCenter = new QAction(koIcon("object-align-horizontal-center-calligra"), i18n("Horizontally Center"), this); addAction("object_align_horizontal_center", actionAlignCenter); connect(actionAlignCenter, SIGNAL(triggered()), this, SLOT(selectionAlignHorizontalCenter())); QAction * actionAlignRight = new QAction(koIcon("object-align-horizontal-right-calligra"), i18n("Align Right"), this); addAction("object_align_horizontal_right", actionAlignRight); connect(actionAlignRight, SIGNAL(triggered()), this, SLOT(selectionAlignHorizontalRight())); QAction * actionAlignTop = new QAction(koIcon("object-align-vertical-top-calligra"), i18n("Align Top"), this); addAction("object_align_vertical_top", actionAlignTop); connect(actionAlignTop, SIGNAL(triggered()), this, SLOT(selectionAlignVerticalTop())); QAction * actionAlignMiddle = new QAction(koIcon("object-align-vertical-center-calligra"), i18n("Vertically Center"), this); addAction("object_align_vertical_center", actionAlignMiddle); connect(actionAlignMiddle, SIGNAL(triggered()), this, SLOT(selectionAlignVerticalCenter())); QAction * actionAlignBottom = new QAction(koIcon("object-align-vertical-bottom-calligra"), i18n("Align Bottom"), this); addAction("object_align_vertical_bottom", actionAlignBottom); connect(actionAlignBottom, SIGNAL(triggered()), this, SLOT(selectionAlignVerticalBottom())); QAction * actionGroupBottom = new QAction(koIcon("object-group-calligra"), i18n("Group"), this); addAction("object_group", actionGroupBottom); connect(actionGroupBottom, SIGNAL(triggered()), this, SLOT(selectionGroup())); QAction * actionUngroupBottom = new QAction(koIcon("object-ungroup-calligra"), i18n("Ungroup"), this); addAction("object_ungroup", actionUngroupBottom); connect(actionUngroupBottom, SIGNAL(triggered()), this, SLOT(selectionUngroup())); } qreal DefaultTool::rotationOfHandle(KoFlake::SelectionHandle handle, bool useEdgeRotation) { QPointF selectionCenter = koSelection()->absolutePosition(); QPointF direction; switch (handle) { case KoFlake::TopMiddleHandle: if (useEdgeRotation) { direction = koSelection()->absolutePosition(KoFlake::TopRightCorner) - koSelection()->absolutePosition(KoFlake::TopLeftCorner); } else { QPointF handlePosition = koSelection()->absolutePosition(KoFlake::TopLeftCorner); handlePosition += 0.5 * (koSelection()->absolutePosition(KoFlake::TopRightCorner) - handlePosition); direction = handlePosition - selectionCenter; } break; case KoFlake::TopRightHandle: direction = (QVector2D(koSelection()->absolutePosition(KoFlake::TopRightCorner) - koSelection()->absolutePosition(KoFlake::TopLeftCorner)).normalized() + QVector2D(koSelection()->absolutePosition(KoFlake::TopRightCorner) - koSelection()->absolutePosition(KoFlake::BottomRightCorner)).normalized()).toPointF(); break; case KoFlake::RightMiddleHandle: if (useEdgeRotation) { direction = koSelection()->absolutePosition(KoFlake::BottomRightCorner) - koSelection()->absolutePosition(KoFlake::TopRightCorner); } else { QPointF handlePosition = koSelection()->absolutePosition(KoFlake::TopRightCorner); handlePosition += 0.5 * (koSelection()->absolutePosition(KoFlake::BottomRightCorner) - handlePosition); direction = handlePosition - selectionCenter; } break; case KoFlake::BottomRightHandle: direction = (QVector2D(koSelection()->absolutePosition(KoFlake::BottomRightCorner) - koSelection()->absolutePosition(KoFlake::BottomLeftCorner)).normalized() + QVector2D(koSelection()->absolutePosition(KoFlake::BottomRightCorner) - koSelection()->absolutePosition(KoFlake::TopRightCorner)).normalized()).toPointF(); break; case KoFlake::BottomMiddleHandle: if (useEdgeRotation) { direction = koSelection()->absolutePosition(KoFlake::BottomLeftCorner) - koSelection()->absolutePosition(KoFlake::BottomRightCorner); } else { QPointF handlePosition = koSelection()->absolutePosition(KoFlake::BottomLeftCorner); handlePosition += 0.5 * (koSelection()->absolutePosition(KoFlake::BottomRightCorner) - handlePosition); direction = handlePosition - selectionCenter; } break; case KoFlake::BottomLeftHandle: direction = koSelection()->absolutePosition(KoFlake::BottomLeftCorner) - selectionCenter; direction = (QVector2D(koSelection()->absolutePosition(KoFlake::BottomLeftCorner) - koSelection()->absolutePosition(KoFlake::BottomRightCorner)).normalized() + QVector2D(koSelection()->absolutePosition(KoFlake::BottomLeftCorner) - koSelection()->absolutePosition(KoFlake::TopLeftCorner)).normalized()).toPointF(); break; case KoFlake::LeftMiddleHandle: if (useEdgeRotation) { direction = koSelection()->absolutePosition(KoFlake::TopLeftCorner) - koSelection()->absolutePosition(KoFlake::BottomLeftCorner); } else { QPointF handlePosition = koSelection()->absolutePosition(KoFlake::TopLeftCorner); handlePosition += 0.5 * (koSelection()->absolutePosition(KoFlake::BottomLeftCorner) - handlePosition); direction = handlePosition - selectionCenter; } break; case KoFlake::TopLeftHandle: direction = koSelection()->absolutePosition(KoFlake::TopLeftCorner) - selectionCenter; direction = (QVector2D(koSelection()->absolutePosition(KoFlake::TopLeftCorner) - koSelection()->absolutePosition(KoFlake::TopRightCorner)).normalized() + QVector2D(koSelection()->absolutePosition(KoFlake::TopLeftCorner) - koSelection()->absolutePosition(KoFlake::BottomLeftCorner)).normalized()).toPointF(); break; case KoFlake::NoHandle: return 0.0; break; } qreal rotation = atan2(direction.y(), direction.x()) * 180.0 / M_PI; switch (handle) { case KoFlake::TopMiddleHandle: if (useEdgeRotation) rotation -= 0.0; else rotation -= 270.0; break; case KoFlake::TopRightHandle: rotation -= 315.0; break; case KoFlake::RightMiddleHandle: if (useEdgeRotation) rotation -= 90.0; else rotation -= 0.0; break; case KoFlake::BottomRightHandle: rotation -= 45.0; break; case KoFlake::BottomMiddleHandle: if (useEdgeRotation) rotation -= 180.0; else rotation -= 90.0; break; case KoFlake::BottomLeftHandle: rotation -= 135.0; break; case KoFlake::LeftMiddleHandle: if (useEdgeRotation) rotation -= 270.0; else rotation -= 180.0; break; case KoFlake::TopLeftHandle: rotation -= 225.0; break; case KoFlake::NoHandle: break; } if (rotation < 0.0) rotation += 360.0; return rotation; } void DefaultTool::updateCursor() { QCursor cursor = Qt::ArrowCursor; QString statusText; if (koSelection()->count() > 0) { // has a selection bool editable=editableShapesCount(koSelection()->selectedShapes(KoFlake::StrippedSelection)); if (!m_mouseWasInsideHandles) { m_angle = rotationOfHandle(m_lastHandle, true); int rotOctant = 8 + int(8.5 + m_angle / 45); bool rotateHandle = false; bool shearHandle = false; switch(m_lastHandle) { case KoFlake::TopMiddleHandle: cursor = m_shearCursors[(0 +rotOctant)%8]; shearHandle = true; break; case KoFlake::TopRightHandle: cursor = m_rotateCursors[(1 +rotOctant)%8]; rotateHandle = true; break; case KoFlake::RightMiddleHandle: cursor = m_shearCursors[(2 +rotOctant)%8]; shearHandle = true; break; case KoFlake::BottomRightHandle: cursor = m_rotateCursors[(3 +rotOctant)%8]; rotateHandle = true; break; case KoFlake::BottomMiddleHandle: cursor = m_shearCursors[(4 +rotOctant)%8]; shearHandle = true; break; case KoFlake::BottomLeftHandle: cursor = m_rotateCursors[(5 +rotOctant)%8]; rotateHandle = true; break; case KoFlake::LeftMiddleHandle: cursor = m_shearCursors[(6 +rotOctant)%8]; shearHandle = true; break; case KoFlake::TopLeftHandle: cursor = m_rotateCursors[(7 +rotOctant)%8]; rotateHandle = true; break; case KoFlake::NoHandle: if (m_guideLine->isValid()) { cursor = m_guideLine->orientation() == Qt::Horizontal ? Qt::SizeVerCursor : Qt::SizeHorCursor; statusText = i18n("Click and drag to move guide line."); } else cursor = Qt::ArrowCursor; break; } if (rotateHandle) statusText = i18n("Left click rotates around center, right click around highlighted position."); if (shearHandle) statusText = i18n("Click and drag to shear selection."); } else { statusText = i18n("Click and drag to resize selection."); m_angle = rotationOfHandle(m_lastHandle, false); int rotOctant = 8 + int(8.5 + m_angle / 45); bool cornerHandle = false; switch(m_lastHandle) { case KoFlake::TopMiddleHandle: cursor = m_sizeCursors[(0 +rotOctant)%8]; break; case KoFlake::TopRightHandle: cursor = m_sizeCursors[(1 +rotOctant)%8]; cornerHandle = true; break; case KoFlake::RightMiddleHandle: cursor = m_sizeCursors[(2 +rotOctant)%8]; break; case KoFlake::BottomRightHandle: cursor = m_sizeCursors[(3 +rotOctant)%8]; cornerHandle = true; break; case KoFlake::BottomMiddleHandle: cursor = m_sizeCursors[(4 +rotOctant)%8]; break; case KoFlake::BottomLeftHandle: cursor = m_sizeCursors[(5 +rotOctant)%8]; cornerHandle = true; break; case KoFlake::LeftMiddleHandle: cursor = m_sizeCursors[(6 +rotOctant)%8]; break; case KoFlake::TopLeftHandle: cursor = m_sizeCursors[(7 +rotOctant)%8]; cornerHandle = true; break; case KoFlake::NoHandle: cursor = Qt::SizeAllCursor; statusText = i18n("Click and drag to move selection."); break; } if (cornerHandle) statusText = i18n("Click and drag to resize selection. Middle click to set highlighted position."); } if (!editable) cursor = Qt::ArrowCursor; } else { if (m_guideLine->isValid()) { cursor = m_guideLine->orientation() == Qt::Horizontal ? Qt::SizeVerCursor : Qt::SizeHorCursor; statusText = i18n("Click and drag to move guide line."); } } useCursor(cursor); if (currentStrategy() == 0) emit statusTextChanged(statusText); } void DefaultTool::paint(QPainter &painter, const KoViewConverter &converter) { KoInteractionTool::paint(painter, converter); if (currentStrategy() == 0 && koSelection()->count() > 0) { SelectionDecorator decorator(m_mouseWasInsideHandles ? m_lastHandle : KoFlake::NoHandle, true, true); decorator.setSelection(koSelection()); decorator.setHandleRadius(handleRadius()); decorator.setHotPosition(m_hotPosition); decorator.paint(painter, converter); } painter.save(); KoShape::applyConversion(painter, converter); canvas()->snapGuide()->paint(painter, converter); painter.restore(); } void DefaultTool::mousePressEvent(KoPointerEvent *event) { KoInteractionTool::mousePressEvent(event); updateCursor(); } void DefaultTool::mouseMoveEvent(KoPointerEvent *event) { KoInteractionTool::mouseMoveEvent(event); if (currentStrategy() == 0 && koSelection()->count() > 0) { QRectF bound = handlesSize(); if (bound.contains(event->point)) { bool inside; KoFlake::SelectionHandle newDirection = handleAt(event->point, &inside); if (inside != m_mouseWasInsideHandles || m_lastHandle != newDirection) { m_lastHandle = newDirection; m_mouseWasInsideHandles = inside; //repaintDecorations(); } } else { /*if (m_lastHandle != KoFlake::NoHandle) repaintDecorations(); */ m_lastHandle = KoFlake::NoHandle; m_mouseWasInsideHandles = false; if (m_guideLine->isSelected()) { GuidesTool *guidesTool = dynamic_cast(KoToolManager::instance()->toolById(canvas(), GuidesToolId)); if (guidesTool) { guidesTool->moveGuideLine(m_guideLine->orientation(), m_guideLine->index()); activateTemporary(guidesTool->toolId()); } } else { selectGuideAtPosition(event->point); } } } else { if (m_guideLine->isSelected()) { GuidesTool *guidesTool = dynamic_cast(KoToolManager::instance()->toolById(canvas(), GuidesToolId)); if (guidesTool) { guidesTool->moveGuideLine(m_guideLine->orientation(), m_guideLine->index()); activateTemporary(guidesTool->toolId()); } } else { selectGuideAtPosition(event->point); } } updateCursor(); } void DefaultTool::selectGuideAtPosition(const QPointF &position) { int index = -1; Qt::Orientation orientation = Qt::Horizontal; // check if we are on a guide line KoGuidesData * guidesData = canvas()->guidesData(); if (guidesData && guidesData->showGuideLines()) { qreal minDistance = canvas()->viewConverter()->viewToDocumentX(grabSensitivity()); uint i = 0; foreach (qreal guidePos, guidesData->horizontalGuideLines()) { qreal distance = qAbs(guidePos - position.y()); if (distance < minDistance) { orientation = Qt::Horizontal; index = i; minDistance = distance; } i++; } i = 0; foreach (qreal guidePos, guidesData->verticalGuideLines()) { qreal distance = qAbs(guidePos - position.x()); if (distance < minDistance) { orientation = Qt::Vertical; index = i; minDistance = distance; } i++; } } delete m_guideLine; if (index >= 0) m_guideLine = new GuideLine(orientation, index); else m_guideLine = new GuideLine(); } QRectF DefaultTool::handlesSize() { QRectF bound = koSelection()->boundingRect(); // expansion Border if (!canvas() || !canvas()->viewConverter()) return bound; QPointF border = canvas()->viewConverter()->viewToDocument(QPointF(HANDLE_DISTANCE, HANDLE_DISTANCE)); bound.adjust(-border.x(), -border.y(), border.x(), border.y()); return bound; } void DefaultTool::mouseReleaseEvent(KoPointerEvent *event) { KoInteractionTool::mouseReleaseEvent(event); updateCursor(); } void DefaultTool::mouseDoubleClickEvent(KoPointerEvent *event) { QList shapes; foreach(KoShape *shape, koSelection()->selectedShapes()) { if (shape->boundingRect().contains(event->point) && // first 'cheap' check shape->outline().contains(event->point)) // this is more expensive but weeds out the almost hits shapes.append(shape); } if (shapes.count() == 0) { // nothing in the selection was clicked on. KoShape *shape = canvas()->shapeManager()->shapeAt (event->point, KoFlake::ShapeOnTop); if (shape) { shapes.append(shape); } else if (m_guideLine->isSelected()) { GuidesTool *guidesTool = dynamic_cast(KoToolManager::instance()->toolById(canvas(), GuidesToolId)); if (guidesTool) { guidesTool->editGuideLine(m_guideLine->orientation(), m_guideLine->index()); activateTool(guidesTool->toolId()); return; } } } QList shapes2; foreach (KoShape *shape, shapes) { QSet delegates = shape->toolDelegates(); if (delegates.isEmpty()) { shapes2.append(shape); } else { foreach (KoShape *delegatedShape, delegates) { shapes2.append(delegatedShape); } } } KoToolManager::instance()->switchToolRequested( KoToolManager::instance()->preferredToolForSelection(shapes2)); } bool DefaultTool::moveSelection(int direction, Qt::KeyboardModifiers modifiers) { qreal x=0.0, y=0.0; if (direction == Qt::Key_Left) x = -5; else if (direction == Qt::Key_Right) x = 5; else if (direction == Qt::Key_Up) y = -5; else if (direction == Qt::Key_Down) y = 5; if (x != 0.0 || y != 0.0) { // actually move if ((modifiers & Qt::ShiftModifier) != 0) { x *= 10; y *= 10; } else if ((modifiers & Qt::AltModifier) != 0) { // more precise x /= 5; y /= 5; } QList prevPos; QList newPos; QList shapes; foreach(KoShape* shape, koSelection()->selectedShapes(KoFlake::TopLevelSelection)) { if (shape->isGeometryProtected()) continue; shapes.append(shape); QPointF p = shape->position(); prevPos.append(p); p.setX(p.x() + x); p.setY(p.y() + y); newPos.append(p); } if (shapes.count() > 0) { // use a timeout to make sure we don't reuse a command possibly deleted by the commandHistory if (m_lastUsedMoveCommand.msecsTo(QTime::currentTime()) > 5000) m_moveCommand = 0; if (m_moveCommand) { // alter previous instead of creating new one. m_moveCommand->setNewPositions(newPos); m_moveCommand->redo(); } else { m_moveCommand = new KoShapeMoveCommand(shapes, prevPos, newPos); canvas()->addCommand(m_moveCommand); } m_lastUsedMoveCommand = QTime::currentTime(); return true; } } return false; } void DefaultTool::keyPressEvent(QKeyEvent *event) { KoInteractionTool::keyPressEvent(event); if (currentStrategy() == 0) { switch (event->key()) { case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: case Qt::Key_Down: if (moveSelection(event->key(), event->modifiers())) event->accept(); break; case Qt::Key_1: case Qt::Key_2: case Qt::Key_3: case Qt::Key_4: case Qt::Key_5: canvas()->resourceManager()->setResource(HotPosition, event->key()-Qt::Key_1); event->accept(); break; default: return; } } } void DefaultTool::customMoveEvent(KoPointerEvent * event) { if (! koSelection()->count()) { event->ignore(); return; } int move = qMax(qAbs(event->x()), qAbs(event->y())); int zoom = qAbs(event->z()); int rotate = qAbs(event->rotationZ()); const int threshold = 2; if (move < threshold && zoom < threshold && rotate < threshold) { if (m_customEventStrategy) { m_customEventStrategy->finishInteraction(event->modifiers()); KUndo2Command *command = m_customEventStrategy->createCommand(); if (command) canvas()->addCommand(command); delete m_customEventStrategy; m_customEventStrategy = 0; repaintDecorations(); } event->accept(); return; } // check if the z-movement is dominant if (zoom > move && zoom > rotate) { // zoom if (! m_customEventStrategy) m_customEventStrategy = new ShapeResizeStrategy(this, event->point, KoFlake::TopLeftHandle); } else if (move > zoom && move > rotate) { // check if x-/y-movement is dominant // move if (! m_customEventStrategy) m_customEventStrategy = new ShapeMoveStrategy(this, event->point); } else if (rotate > zoom && rotate > move) // rotation is dominant { // rotate if (! m_customEventStrategy) m_customEventStrategy = new ShapeRotateStrategy(this, event->point, event->buttons()); } if (m_customEventStrategy) m_customEventStrategy->handleCustomEvent(event); event->accept(); } void DefaultTool::repaintDecorations() { Q_ASSERT(koSelection()); if (koSelection()->count() > 0) canvas()->updateCanvas(handlesSize()); } void DefaultTool::copy() const { QList shapes = canvas()->shapeManager()->selection()->selectedShapes(KoFlake::TopLevelSelection); if (!shapes.empty()) { KoShapeOdfSaveHelper saveHelper(shapes); KoDrag drag; drag.setOdf(KoOdf::mimeType(KoOdf::Text), saveHelper); drag.addToClipboard(); } } void DefaultTool::deleteSelection() { QList shapes; foreach (KoShape *s, canvas()->shapeManager()->selection()->selectedShapes(KoFlake::TopLevelSelection)) { if (s->isGeometryProtected()) continue; shapes << s; } if (!shapes.empty()) { canvas()->addCommand(canvas()->shapeController()->removeShapes(shapes)); } } bool DefaultTool::paste() { // we no longer have to do anything as tool Proxy will do it for us return false; } QStringList DefaultTool::supportedPasteMimeTypes() const { QStringList list; list << KoOdf::mimeType(KoOdf::Text); return list; } KoSelection *DefaultTool::koSelection() { Q_ASSERT(canvas()); Q_ASSERT(canvas()->shapeManager()); return canvas()->shapeManager()->selection(); } KoFlake::SelectionHandle DefaultTool::handleAt(const QPointF &point, bool *innerHandleMeaning) { // check for handles in this order; meaning that when handles overlap the one on top is chosen static const KoFlake::SelectionHandle handleOrder[] = { KoFlake::BottomRightHandle, KoFlake::TopLeftHandle, KoFlake::BottomLeftHandle, KoFlake::TopRightHandle, KoFlake::BottomMiddleHandle, KoFlake::RightMiddleHandle, KoFlake::LeftMiddleHandle, KoFlake::TopMiddleHandle, KoFlake::NoHandle }; if (koSelection()->count() == 0) return KoFlake::NoHandle; recalcSelectionBox(); const KoViewConverter *converter = canvas()->viewConverter(); if (!converter) return KoFlake::NoHandle; if (innerHandleMeaning != 0) { QPainterPath path; path.addPolygon(m_selectionOutline); *innerHandleMeaning = path.contains(point) || path.intersects(handlePaintRect(point)); } for (int i = 0; i < KoFlake::NoHandle; ++i) { KoFlake::SelectionHandle handle = handleOrder[i]; QPointF pt = converter->documentToView(point) - converter->documentToView(m_selectionBox[handle]); // if just inside the outline if (qAbs(pt.x()) < HANDLE_DISTANCE && qAbs(pt.y()) < HANDLE_DISTANCE) { if (innerHandleMeaning != 0) { if (qAbs(pt.x()) < 4 && qAbs(pt.y()) < 4) *innerHandleMeaning = true; } return handle; } } return KoFlake::NoHandle; } void DefaultTool::recalcSelectionBox() { if (koSelection()->count()==0) return; if (koSelection()->count()>1) { QTransform matrix = koSelection()->absoluteTransformation(0); m_selectionOutline = matrix.map(QPolygonF(QRectF(QPointF(0, 0), koSelection()->size()))); m_angle = 0.0; //koSelection()->rotation(); } else { QTransform matrix = koSelection()->firstSelectedShape()->absoluteTransformation(0); m_selectionOutline = matrix.map(QPolygonF(QRectF(QPointF(0, 0), koSelection()->firstSelectedShape()->size()))); m_angle = 0.0; //koSelection()->firstSelectedShape()->rotation(); } QPolygonF outline = m_selectionOutline; //shorter name in the following :) m_selectionBox[KoFlake::TopMiddleHandle] = (outline.value(0)+outline.value(1))/2; m_selectionBox[KoFlake::TopRightHandle] = outline.value(1); m_selectionBox[KoFlake::RightMiddleHandle] = (outline.value(1)+outline.value(2))/2; m_selectionBox[KoFlake::BottomRightHandle] = outline.value(2); m_selectionBox[KoFlake::BottomMiddleHandle] = (outline.value(2)+outline.value(3))/2; m_selectionBox[KoFlake::BottomLeftHandle] = outline.value(3); m_selectionBox[KoFlake::LeftMiddleHandle] = (outline.value(3)+outline.value(0))/2; m_selectionBox[KoFlake::TopLeftHandle] = outline.value(0); if (koSelection()->count() == 1) { #if 0 // TODO detect mirroring KoShape *s = koSelection()->firstSelectedShape(); if (s->scaleX() < 0) { // vertically mirrored: swap left / right qSwap(m_selectionBox[KoFlake::TopLeftHandle], m_selectionBox[KoFlake::TopRightHandle]); qSwap(m_selectionBox[KoFlake::LeftMiddleHandle], m_selectionBox[KoFlake::RightMiddleHandle]); qSwap(m_selectionBox[KoFlake::BottomLeftHandle], m_selectionBox[KoFlake::BottomRightHandle]); } if (s->scaleY() < 0) { // vertically mirrored: swap top / bottom qSwap(m_selectionBox[KoFlake::TopLeftHandle], m_selectionBox[KoFlake::BottomLeftHandle]); qSwap(m_selectionBox[KoFlake::TopMiddleHandle], m_selectionBox[KoFlake::BottomMiddleHandle]); qSwap(m_selectionBox[KoFlake::TopRightHandle], m_selectionBox[KoFlake::BottomRightHandle]); } #endif } } void DefaultTool::activate(ToolActivation, const QSet &) { m_mouseWasInsideHandles = false; m_lastHandle = KoFlake::NoHandle; useCursor(Qt::ArrowCursor); repaintDecorations(); delete m_guideLine; m_guideLine = new GuideLine(); updateActions(); } void DefaultTool::selectionAlignHorizontalLeft() { selectionAlign(KoShapeAlignCommand::HorizontalLeftAlignment); } void DefaultTool::selectionAlignHorizontalCenter() { selectionAlign(KoShapeAlignCommand::HorizontalCenterAlignment); } void DefaultTool::selectionAlignHorizontalRight() { selectionAlign(KoShapeAlignCommand::HorizontalRightAlignment); } void DefaultTool::selectionAlignVerticalTop() { selectionAlign(KoShapeAlignCommand::VerticalTopAlignment); } void DefaultTool::selectionAlignVerticalCenter() { selectionAlign(KoShapeAlignCommand::VerticalCenterAlignment); } void DefaultTool::selectionAlignVerticalBottom() { selectionAlign(KoShapeAlignCommand::VerticalBottomAlignment); } void DefaultTool::selectionGroup() { KoSelection* selection = koSelection(); if (! selection) return; QList selectedShapes = selection->selectedShapes(KoFlake::TopLevelSelection); QList groupedShapes; // only group shapes with an unselected parent foreach (KoShape* shape, selectedShapes) { if (! selectedShapes.contains(shape->parent()) && shape->isEditable()) { groupedShapes << shape; } } KoShapeGroup *group = new KoShapeGroup(); // TODO what if only one shape is left? KUndo2Command *cmd = new KUndo2Command(kundo2_i18n("Group shapes")); canvas()->shapeController()->addShapeDirect(group, cmd); KoShapeGroupCommand::createCommand(group, groupedShapes, cmd); canvas()->addCommand(cmd); // update selection so we can ungroup immediately again selection->deselectAll(); selection->select(group); } void DefaultTool::selectionUngroup() { KoSelection* selection = canvas()->shapeManager()->selection(); if (! selection) return; QList selectedShapes = selection->selectedShapes(KoFlake::TopLevelSelection); QList containerSet; // only ungroup shape groups with an unselected parent foreach (KoShape* shape, selectedShapes) { if (!selectedShapes.contains(shape->parent()) && shape->isEditable()) { containerSet << shape; } } KUndo2Command *cmd = 0; // add a ungroup command for each found shape container to the macro command foreach(KoShape* shape, containerSet) { KoShapeGroup *group = dynamic_cast(shape); if (group) { cmd = cmd ? cmd : new KUndo2Command(kundo2_i18n("Ungroup shapes")); new KoShapeUngroupCommand(group, group->shapes(), group->parent()? QList(): canvas()->shapeManager()->topLevelShapes(), cmd); canvas()->shapeController()->removeShape(group, cmd); } } if (cmd) { canvas()->addCommand(cmd); } } void DefaultTool::selectionAlign(KoShapeAlignCommand::Align align) { KoSelection* selection = canvas()->shapeManager()->selection(); if (! selection) return; QList selectedShapes = selection->selectedShapes(KoFlake::TopLevelSelection); if (selectedShapes.count() < 1) return; QList editableShapes = filterEditableShapes(selectedShapes); // TODO add an option to the widget so that one can align to the page // with multiple selected shapes too QRectF bb; // single selected shape is automatically aligned to document rect if (editableShapes.count() == 1 ) { if (!canvas()->resourceManager()->hasResource(KoCanvasResourceManager::PageSize)) return; bb = QRectF(QPointF(0,0), canvas()->resourceManager()->sizeResource(KoCanvasResourceManager::PageSize)); } else { foreach( KoShape * shape, editableShapes ) { bb |= shape->boundingRect(); } } KoShapeAlignCommand *cmd = new KoShapeAlignCommand(editableShapes, align, bb); canvas()->addCommand(cmd); selection->updateSizeAndPosition(); } void DefaultTool::selectionBringToFront() { selectionReorder(KoShapeReorderCommand::BringToFront); } void DefaultTool::selectionMoveUp() { selectionReorder(KoShapeReorderCommand::RaiseShape); } void DefaultTool::selectionMoveDown() { selectionReorder(KoShapeReorderCommand::LowerShape); } void DefaultTool::selectionSendToBack() { selectionReorder(KoShapeReorderCommand::SendToBack); } void DefaultTool::selectionReorder(KoShapeReorderCommand::MoveShapeType order) { KoSelection* selection = canvas()->shapeManager()->selection(); if (! selection) return; QList selectedShapes = selection->selectedShapes(KoFlake::TopLevelSelection); if (selectedShapes.count() < 1) return; QList editableShapes = filterEditableShapes(selectedShapes); if (editableShapes.count() < 1) return; KUndo2Command * cmd = KoShapeReorderCommand::createCommand(editableShapes, canvas()->shapeManager(), order); if (cmd) { canvas()->addCommand(cmd); } } QList > DefaultTool::createOptionWidgets() { QList > widgets; DefaultToolArrangeWidget *defaultArrange = new DefaultToolArrangeWidget(this); defaultArrange->setWindowTitle(i18n("Arrange")); widgets.append(defaultArrange); DefaultToolWidget *defaultTool = new DefaultToolWidget(this); defaultTool->setWindowTitle(i18n("Geometry")); widgets.append(defaultTool); KoStrokeConfigWidget *strokeWidget = new KoStrokeConfigWidget(0); strokeWidget->setWindowTitle(i18n("Line")); strokeWidget->setCanvas(canvas()); widgets.append(strokeWidget); KoFillConfigWidget *fillWidget = new KoFillConfigWidget(0); fillWidget->setWindowTitle(i18n("Fill")); fillWidget->setCanvas(canvas()); widgets.append(fillWidget); KoShadowConfigWidget *shadowWidget = new KoShadowConfigWidget(0); shadowWidget->setWindowTitle(i18n("Shadow")); shadowWidget->setCanvas(canvas()); widgets.append(shadowWidget); return widgets; } void DefaultTool::canvasResourceChanged(int key, const QVariant & res) { if (key == HotPosition) { m_hotPosition = static_cast(res.toInt()); repaintDecorations(); } } KoInteractionStrategy *DefaultTool::createStrategy(KoPointerEvent *event) { // reset the move by keys when a new strategy is created otherwise we might change the // command after a new command was added. This happend when you where faster than the timer. m_moveCommand = 0; KoShapeManager *shapeManager = canvas()->shapeManager(); KoSelection *select = shapeManager->selection(); bool insideSelection; KoFlake::SelectionHandle handle = handleAt(event->point, &insideSelection); bool editableShape = editableShapesCount(select->selectedShapes()); if (event->buttons() & Qt::MidButton) { // change the hot selection position when middle clicking on a handle KoFlake::Position newHotPosition = m_hotPosition; switch (handle) { case KoFlake::TopLeftHandle: newHotPosition = KoFlake::TopLeftCorner; break; case KoFlake::TopRightHandle: newHotPosition = KoFlake::TopRightCorner; break; case KoFlake::BottomLeftHandle: newHotPosition = KoFlake::BottomLeftCorner; break; case KoFlake::BottomRightHandle: newHotPosition = KoFlake::BottomRightCorner; break; default: { // check if we had hit the center point const KoViewConverter * converter = canvas()->viewConverter(); QPointF pt = converter->documentToView(event->point-select->absolutePosition()); if (qAbs(pt.x()) < HANDLE_DISTANCE && qAbs(pt.y()) < HANDLE_DISTANCE) newHotPosition = KoFlake::CenteredPosition; break; } } if (m_hotPosition != newHotPosition) canvas()->resourceManager()->setResource(HotPosition, newHotPosition); return 0; } bool selectMultiple = event->modifiers() & Qt::ControlModifier; bool selectNextInStack = event->modifiers() & Qt::ShiftModifier; if (editableShape) { // manipulation of selected shapes goes first if (handle != KoFlake::NoHandle) { if (event->buttons() == Qt::LeftButton) { // resizing or shearing only with left mouse button if (insideSelection) return new ShapeResizeStrategy(this, event->point, handle); if (handle == KoFlake::TopMiddleHandle || handle == KoFlake::RightMiddleHandle || handle == KoFlake::BottomMiddleHandle || handle == KoFlake::LeftMiddleHandle) return new ShapeShearStrategy(this, event->point, handle); } // rotating is allowed for rigth mouse button too if (handle == KoFlake::TopLeftHandle || handle == KoFlake::TopRightHandle || handle == KoFlake::BottomLeftHandle || handle == KoFlake::BottomRightHandle) return new ShapeRotateStrategy(this, event->point, event->buttons()); } if (! (selectMultiple || selectNextInStack) && event->buttons() == Qt::LeftButton) { const QPainterPath outlinePath = select->transformation().map(select->outline()); if (outlinePath.contains(event->point) || outlinePath.intersects(handlePaintRect(event->point))) return new ShapeMoveStrategy(this, event->point); } } if ((event->buttons() & Qt::LeftButton) == 0) return 0; // Nothing to do for middle/right mouse button KoShape *shape = shapeManager->shapeAt(event->point, selectNextInStack ? KoFlake::NextUnselected : KoFlake::ShapeOnTop); if (!shape && handle == KoFlake::NoHandle) { // check if we have hit a guide if (m_guideLine->isValid()) { m_guideLine->select(); return 0; } if (! selectMultiple) { repaintDecorations(); select->deselectAll(); } return new KoShapeRubberSelectStrategy(this, event->point); } if (select->isSelected(shape)) { if (selectMultiple) { repaintDecorations(); select->deselect(shape); } } else if (handle == KoFlake::NoHandle) { // clicked on shape which is not selected repaintDecorations(); if (! selectMultiple) shapeManager->selection()->deselectAll(); select->select(shape, selectNextInStack ? false : true); repaintDecorations(); // tablet selection isn't precise and may lead to a move, preventing that if (event->isTabletEvent()) { return new NopInteractionStrategy(this); } return new ShapeMoveStrategy(this, event->point); } return 0; } void DefaultTool::updateActions() { KoSelection * selection(koSelection()); if (!selection) { action("object_order_front")->setEnabled(false); action("object_order_raise")->setEnabled(false); action("object_order_lower")->setEnabled(false); action("object_order_back")->setEnabled(false); action("object_align_horizontal_left")->setEnabled(false); action("object_align_horizontal_center")->setEnabled(false); action("object_align_horizontal_right")->setEnabled(false); action("object_align_vertical_top")->setEnabled(false); action("object_align_vertical_center")->setEnabled(false); action("object_align_vertical_bottom")->setEnabled(false); action("object_group")->setEnabled(false); action("object_ungroup")->setEnabled(false); return; } QList editableShapes = filterEditableShapes(selection->selectedShapes(KoFlake::TopLevelSelection)); bool enable = editableShapes.count () > 0; action("object_order_front")->setEnabled(enable); action("object_order_raise")->setEnabled(enable); action("object_order_lower")->setEnabled(enable); action("object_order_back")->setEnabled(enable); enable = (editableShapes.count () > 1) || (enable && canvas()->resourceManager()->hasResource(KoCanvasResourceManager::PageSize)); action("object_align_horizontal_left")->setEnabled(enable); action("object_align_horizontal_center")->setEnabled(enable); action("object_align_horizontal_right")->setEnabled(enable); action("object_align_vertical_top")->setEnabled(enable); action("object_align_vertical_center")->setEnabled(enable); action("object_align_vertical_bottom")->setEnabled(enable); action("object_group")->setEnabled(editableShapes.count() > 1); bool groupShape = false; foreach (KoShape * shape, editableShapes) { if (dynamic_cast(shape)) { groupShape = true; break; } } action("object_ungroup")->setEnabled(groupShape); emit selectionChanged(selection->count()); } KoToolSelection* DefaultTool::selection() { return m_selectionHandler; } QList DefaultTool::filterEditableShapes( const QList &shapes ) { QList editableShapes; foreach( KoShape * shape, shapes ) { if (shape->isEditable()) editableShapes.append(shape); } return editableShapes; } uint DefaultTool::editableShapesCount( const QList &shapes ) { uint count = 0; foreach( KoShape * shape, shapes ) { if (shape->isEditable()) count++; } return count; } diff --git a/plugins/defaultTools/defaulttool/SelectionDecorator.cpp b/plugins/defaultTools/defaulttool/SelectionDecorator.cpp index 0160199492..9cd30e9a98 100644 --- a/plugins/defaultTools/defaulttool/SelectionDecorator.cpp +++ b/plugins/defaultTools/defaulttool/SelectionDecorator.cpp @@ -1,238 +1,158 @@ /* This file is part of the KDE project Copyright (C) 2006 Thorsten Zachmann Copyright (C) 2006-2007 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 "SelectionDecorator.h" #include #include #include #define HANDLE_DISTANCE 10 KoFlake::Position SelectionDecorator::m_hotPosition = KoFlake::TopLeftCorner; SelectionDecorator::SelectionDecorator(KoFlake::SelectionHandle arrows, - bool rotationHandles, bool shearHandles) -: m_rotationHandles(rotationHandles) -, m_shearHandles(shearHandles) -, m_arrows(arrows) -, m_handleRadius( 3 ) -, m_lineWidth( 1 ) + bool rotationHandles, bool shearHandles) + : m_rotationHandles(rotationHandles) + , m_shearHandles(shearHandles) + , m_arrows(arrows) + , m_handleRadius( 3 ) + , m_lineWidth( 1 ) { -#if 0 - if(s_rotateCursor == 0) { - s_rotateCursor->load(KoResourcePaths::locate("data", "krita/icons/cursor_rotate.png")); - } -#endif } void SelectionDecorator::setSelection(KoSelection *selection) { m_selection = selection; } void SelectionDecorator::setHandleRadius( int radius ) { m_handleRadius = radius; m_lineWidth = qMax(1, (int)(radius / 2)); } void SelectionDecorator::setHotPosition( KoFlake::Position hotPosition ) { m_hotPosition = hotPosition; } KoFlake::Position SelectionDecorator::hotPosition() { return m_hotPosition; } void SelectionDecorator::paint(QPainter &painter, const KoViewConverter &converter) { QRectF handleArea; painter.save(); // save the original painter transformation QTransform painterMatrix = painter.worldTransform(); QPen pen; //Use the #00adf5 color with 50% opacity pen.setColor(QColor(0, 173, 245, 127)); pen.setWidth(m_lineWidth); pen.setJoinStyle(Qt::RoundJoin); painter.setPen( pen ); bool editable=false; foreach (KoShape *shape, m_selection->selectedShapes(KoFlake::StrippedSelection)) { // apply the shape transformation on top of the old painter transformation painter.setWorldTransform( shape->absoluteTransformation(&converter) * painterMatrix ); // apply the zoom factor KoShape::applyConversion( painter, converter ); // draw the shape bounding rect painter.drawRect( QRectF( QPointF(), shape->size() ) ); if (!shape->isGeometryProtected()) editable = true; } if (m_selection->count() > 1) { // more than one shape selected, so we need to draw the selection bounding rect painter.setPen( Qt::blue ); // apply the selection transformation on top of the old painter transformation painter.setWorldTransform(m_selection->absoluteTransformation(&converter) * painterMatrix); // apply the zoom factor KoShape::applyConversion(painter, converter); // draw the selection bounding rect painter.drawRect(QRectF(QPointF(), m_selection->size())); // save the selection bounding rect for later drawing the selection handles handleArea = QRectF(QPointF(), m_selection->size()); } else if (m_selection->firstSelectedShape()) { // only one shape selected, so we compose the correct painter matrix painter.setWorldTransform(m_selection->firstSelectedShape()->absoluteTransformation(&converter) * painterMatrix); KoShape::applyConversion(painter, converter); // save the only selected shapes bounding rect for later drawing the handles handleArea = QRectF(QPointF(), m_selection->firstSelectedShape()->size()); } painterMatrix = painter.worldTransform(); painter.restore(); // if we have no editable shape selected there is no need drawing the selection handles if (!editable) return; painter.save(); painter.setTransform(QTransform()); painter.setRenderHint( QPainter::Antialiasing, false ); painter.setPen(pen); painter.setBrush(pen.color()); QPolygonF outline = painterMatrix.map( handleArea ); // the 8 move rects QRectF rect( QPointF(0.5,0.5), QSizeF(2*m_handleRadius,2*m_handleRadius) ); rect.moveCenter(outline.value(0)); painter.drawRect(rect); rect.moveCenter(outline.value(1)); painter.drawRect(rect); rect.moveCenter(outline.value(2)); painter.drawRect(rect); rect.moveCenter(outline.value(3)); painter.drawRect(rect); rect.moveCenter((outline.value(0)+outline.value(1))/2); painter.drawRect(rect); rect.moveCenter((outline.value(1)+outline.value(2))/2); painter.drawRect(rect); rect.moveCenter((outline.value(2)+outline.value(3))/2); painter.drawRect(rect); rect.moveCenter((outline.value(3)+outline.value(0))/2); painter.drawRect(rect); // draw the hot position painter.setBrush(Qt::red); QPointF pos; switch( m_hotPosition ) { case KoFlake::TopLeftCorner: pos = handleArea.topLeft(); break; case KoFlake::TopRightCorner: pos = handleArea.topRight(); break; case KoFlake::BottomLeftCorner: pos = handleArea.bottomLeft(); break; case KoFlake::BottomRightCorner: pos = handleArea.bottomRight(); break; case KoFlake::CenteredPosition: pos = handleArea.center(); break; } rect.moveCenter( painterMatrix.map(pos )); painter.drawRect(rect); painter.restore(); - -#if 0 - // draw the move arrow(s) - if(m_arrows != KoFlake::NoHandle && bounds.width() > 45 && bounds.height() > 45) { - qreal x1,x2,y1,y2; // 2 is where the arrow head is - switch(m_arrows) { - case KoFlake::TopMiddleHandle: - x1=bounds.center().x(); x2=x1; y2=bounds.y()+8; y1=y2+20; - break; - case KoFlake::TopRightHandle: - x2=bounds.right()-8; x1=x2-20; y2=bounds.y()+8; y1=y2+20; - break; - case KoFlake::RightMiddleHandle: - x2=bounds.right()-8; x1=x2-20; y1=bounds.center().y(); y2=y1; - break; - case KoFlake::BottomRightHandle: - x2=bounds.right()-8; x1=x2-20; y2=bounds.bottom()-8; y1=y2-20; - break; - case KoFlake::BottomMiddleHandle: - x1=bounds.center().x(); x2=x1; y2=bounds.bottom()-8; y1=y2-20; - break; - case KoFlake::BottomLeftHandle: - x2=bounds.left()+8; x1=x2+20; y2=bounds.bottom()-8; y1=y2-20; - break; - case KoFlake::LeftMiddleHandle: - x2=bounds.left()+8; x1=x2+20; y1=bounds.center().y(); y2=y1; - break; - default: - case KoFlake::TopLeftHandle: - x2=bounds.left()+8; x1=x2+20; y2=bounds.y()+8; y1=y2+20; - break; - } - painter.drawLine(QLineF(x1, y1, x2, y2)); - //pen.setColor(Qt::white); - //painter.setPen(pen); - //painter.drawLine(QLineF(x1-1, y1-1, x2-1, y2-1)); - } - - QPointF border(HANDLE_DISTANCE, HANDLE_DISTANCE); - bounds.adjust(-border.x(), -border.y(), border.x(), border.y()); - - if(m_rotationHandles) { - painter.save(); - painter.translate(bounds.x(), bounds.y()); - QRectF rect(QPointF(0,0), QSizeF(22, 22)); - painter.drawImage(rect, *s_rotateCursor, rect); - painter.translate(bounds.width(), 0); - painter.rotate(90); - if(bounds.width() > 45 && bounds.height() > 45) - painter.drawImage(rect, *s_rotateCursor, rect); - painter.translate(bounds.height(), 0); - painter.rotate(90); - painter.drawImage(rect, *s_rotateCursor, rect); - painter.translate(bounds.width(), 0); - painter.rotate(90); - if(bounds.width() > 45 && bounds.height() > 45) - painter.drawImage(rect, *s_rotateCursor, rect); - painter.restore(); - } - - /*if(m_shearHandles) { - pen.setWidthF(0); - painter.setPen(pen); - QRectF rect(bounds.topLeft(), QSizeF(6, 6)); - rect.moveLeft(bounds.x() + bounds.width() /2 -3); - painter.drawRect(rect); - rect.moveBottom(bounds.bottom()); - painter.drawRect(rect); - rect.moveLeft(bounds.left()); - rect.moveTop(bounds.top() + bounds.width() / 2 -3); - painter.drawRect(rect); - rect.moveRight(bounds.right()); - painter.drawRect(rect); - } */ -#endif } diff --git a/plugins/defaultTools/defaulttools.qrc b/plugins/defaultTools/defaulttools.qrc new file mode 100644 index 0000000000..890f4b82b9 --- /dev/null +++ b/plugins/defaultTools/defaulttools.qrc @@ -0,0 +1,15 @@ + + + + pics/16-actions-escape-direction-all.png + pics/16-actions-escape-direction-down.png + pics/16-actions-escape-direction-horizontal.png + pics/16-actions-escape-direction-left.png + pics/16-actions-escape-direction-right.png + pics/16-actions-escape-direction-up.png + pics/16-actions-escape-direction-vertical.png + pics/cursor_connect.png + pics/cursor_rotate.png + pics/cursor_shear.png + + diff --git a/plugins/defaultTools/pics/CMakeLists.txt b/plugins/defaultTools/pics/CMakeLists.txt deleted file mode 100644 index 3fdd92ca91..0000000000 --- a/plugins/defaultTools/pics/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -install( FILES cursor_shear.png cursor_rotate.png cursor_connect.png DESTINATION ${DATA_INSTALL_DIR}/krita/icons) - -ecm_install_icons( ICONS - 16-actions-escape-direction-all.png - 16-actions-escape-direction-down.png - 16-actions-escape-direction-horizontal.png - 16-actions-escape-direction-left.png - 16-actions-escape-direction-right.png - 16-actions-escape-direction-up.png - 16-actions-escape-direction-vertical.png - DESTINATION ${DATA_INSTALL_DIR}/krita/icons - THEME hicolor -) diff --git a/plugins/dockers/CMakeLists.txt b/plugins/dockers/CMakeLists.txt index e0bcec3c2d..bcaef781fd 100644 --- a/plugins/dockers/CMakeLists.txt +++ b/plugins/dockers/CMakeLists.txt @@ -1,31 +1,31 @@ project(calligradockers) add_definitions(-DTRANSLATION_DOMAIN=\"krita-dockers\") include_directories( ${FLAKE_INCLUDES} ${KOWIDGETS_INCLUDES} ) set(calligradockers_SRCS snapguidedocker/SnapGuideDocker.cpp snapguidedocker/SnapGuideDockerFactory.cpp shapeproperties/ShapePropertiesDocker.cpp shapeproperties/ShapePropertiesDockerFactory.cpp shapecollection/CollectionShapeFactory.cpp shapecollection/ShapeCollectionDocker.cpp shapecollection/CollectionItemModel.cpp shapecollection/OdfCollectionLoader.cpp Plugin.cpp ) add_library(krita_docker_defaults MODULE ${calligradockers_SRCS}) kcoreaddons_desktop_to_json(krita_docker_defaults calligra_docker_defaults.desktop) -target_link_libraries(krita_docker_defaults kritawidgets KF5::IconThemes ) +target_link_libraries(krita_docker_defaults kritawidgets) install(TARGETS krita_docker_defaults DESTINATION ${CALLIGRA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/karbonplugins/tools/CMakeLists.txt b/plugins/karbonplugins/tools/CMakeLists.txt index 30736ad56c..4c4730e255 100644 --- a/plugins/karbonplugins/tools/CMakeLists.txt +++ b/plugins/karbonplugins/tools/CMakeLists.txt @@ -1,63 +1,56 @@ # plugin/tools have their own catalog add_definitions(-DTRANSLATION_DOMAIN=\"krita_karbontools\") include_directories( ${FLAKE_INCLUDES} ${CMAKE_CURRENT_SOURCE_DIR}/filterEffectTool ) ########### next target ############### set(karbon_tools_PART_SRCS KarbonToolsPlugin.cpp KarbonCursor.cpp CalligraphyTool/KarbonCalligraphyTool.cpp CalligraphyTool/KarbonCalligraphyOptionWidget.cpp CalligraphyTool/KarbonCalligraphyToolFactory.cpp CalligraphyTool/KarbonCalligraphicShape.cpp CalligraphyTool/KarbonCalligraphicShapeFactory.cpp CalligraphyTool/KarbonSimplifyPath.cpp KarbonGradientTool.cpp KarbonGradientToolFactory.cpp KarbonGradientEditStrategy.cpp KarbonPatternTool.cpp KarbonPatternToolFactory.cpp KarbonPatternEditStrategy.cpp filterEffectTool/KarbonFilterEffectsTool.cpp filterEffectTool/KarbonFilterEffectsToolFactory.cpp filterEffectTool/FilterEffectEditWidget.cpp filterEffectTool/FilterEffectScene.cpp filterEffectTool/FilterEffectSceneItems.cpp filterEffectTool/FilterInputChangeCommand.cpp filterEffectTool/FilterAddCommand.cpp filterEffectTool/FilterRemoveCommand.cpp filterEffectTool/FilterStackSetCommand.cpp filterEffectTool/FilterRegionChangeCommand.cpp filterEffectTool/FilterEffectResource.cpp filterEffectTool/FilterResourceServerProvider.cpp filterEffectTool/FilterRegionEditStrategy.cpp KarbonPatternOptionsWidget.cpp ) ki18n_wrap_ui(karbon_tools_PART_SRCS filterEffectTool/FilterEffectEditWidget.ui KarbonPatternOptionsWidget.ui ) +qt5_add_resources(karbon_tools_PART_SRCS karbontools.qrc) + add_library(krita_karbontools MODULE ${karbon_tools_PART_SRCS}) kcoreaddons_desktop_to_json(krita_karbontools karbon_tools.desktop) target_link_libraries(krita_karbontools kritawidgets KF5::Completion) install(TARGETS krita_karbontools DESTINATION ${CALLIGRA_PLUGIN_INSTALL_DIR}) -ecm_install_icons( ICONS - 22-actions-calligraphy.png - 22-actions-gradient.png - 22-actions-pattern.png - 32-actions-tool_imageeffects.png - - DESTINATION ${DATA_INSTALL_DIR}/krita/icons - THEME hicolor -) diff --git a/plugins/karbonplugins/tools/karbontools.qrc b/plugins/karbonplugins/tools/karbontools.qrc new file mode 100644 index 0000000000..262292346b --- /dev/null +++ b/plugins/karbonplugins/tools/karbontools.qrc @@ -0,0 +1,9 @@ + + + + 22-actions-calligraphy.png + 22-actions-gradient.png + 22-actions-pattern.png + 32-actions-tool_imageeffects.png + + diff --git a/plugins/pathshapes/CMakeLists.txt b/plugins/pathshapes/CMakeLists.txt index 75265a9644..14f4e77a37 100644 --- a/plugins/pathshapes/CMakeLists.txt +++ b/plugins/pathshapes/CMakeLists.txt @@ -1,47 +1,48 @@ add_definitions(-DTRANSLATION_DOMAIN=\"krita_shape_paths\") include_directories( ${CMAKE_SOURCE_DIR}/libs/widgets ${FLAKE_INCLUDES} ) -add_subdirectory(pics) - set(pathshapes_PART_SRCS ellipse/EllipseShape.cpp ellipse/EllipseShapeFactory.cpp ellipse/EllipseShapeConfigWidget.cpp ellipse/EllipseShapeConfigCommand.cpp spiral/SpiralShape.cpp spiral/SpiralShapeFactory.cpp spiral/SpiralShapeConfigWidget.cpp spiral/SpiralShapeConfigCommand.cpp star/StarShape.cpp star/StarShapeFactory.cpp star/StarShapeConfigWidget.cpp star/StarShapeConfigCommand.cpp rectangle/RectangleShape.cpp rectangle/RectangleShapeFactory.cpp rectangle/RectangleShapeConfigWidget.cpp rectangle/RectangleShapeConfigCommand.cpp enhancedpath/EnhancedPathShape.cpp enhancedpath/EnhancedPathShapeFactory.cpp enhancedpath/EnhancedPathCommand.cpp enhancedpath/EnhancedPathParameter.cpp enhancedpath/EnhancedPathFormula.cpp enhancedpath/EnhancedPathHandle.cpp PathShapesPlugin.cpp ) ki18n_wrap_ui(pathshapes_PART_SRCS star/StarShapeConfigWidget.ui rectangle/RectangleShapeConfigWidget.ui ellipse/EllipseShapeConfigWidget.ui spiral/SpiralShapeConfigWidget.ui ) + +qt5_add_resources(pathshapes_PART_SRCS pathshapes.qrc) + add_library(krita_shape_paths MODULE ${pathshapes_PART_SRCS}) kcoreaddons_desktop_to_json(krita_shape_paths calligra_shape_paths.desktop) -target_link_libraries(krita_shape_paths kritaflake kritawidgets KF5::IconThemes) +target_link_libraries(krita_shape_paths kritaflake kritawidgets) install(TARGETS krita_shape_paths DESTINATION ${CALLIGRA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/pathshapes/pathshapes.qrc b/plugins/pathshapes/pathshapes.qrc new file mode 100644 index 0000000000..30aced1c1b --- /dev/null +++ b/plugins/pathshapes/pathshapes.qrc @@ -0,0 +1,18 @@ + + + + pics/22-actions-callout-shape.png + pics/22-actions-circular-arrow-shape.png + pics/22-actions-cross-shape.png + pics/22-actions-ellipse-shape.png + pics/22-actions-flower-shape.png + pics/22-actions-gearhead-shape.png + pics/22-actions-hexagon-shape.png + pics/22-actions-pentagon-shape.png + pics/22-actions-polygon-shape.png + pics/22-actions-rectangle-shape.png + pics/22-actions-smiley-shape.png + pics/22-actions-spiral-shape.png + pics/22-actions-star-shape.png + + diff --git a/plugins/pathshapes/pics/CMakeLists.txt b/plugins/pathshapes/pics/CMakeLists.txt deleted file mode 100644 index cd0514c97d..0000000000 --- a/plugins/pathshapes/pics/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -ecm_install_icons( ICONS - 22-actions-callout-shape.png - 22-actions-circular-arrow-shape.png - 22-actions-cross-shape.png - 22-actions-ellipse-shape.png - 22-actions-flower-shape.png - 22-actions-gearhead-shape.png - 22-actions-hexagon-shape.png - 22-actions-pentagon-shape.png - 22-actions-polygon-shape.png - 22-actions-rectangle-shape.png - 22-actions-smiley-shape.png - 22-actions-spiral-shape.png - 22-actions-star-shape.png - DESTINATION ${DATA_INSTALL_DIR}/krita/icons - THEME oxygen -) diff --git a/plugins/textshape/CMakeLists.txt b/plugins/textshape/CMakeLists.txt index 3cccffca3d..b0670595be 100644 --- a/plugins/textshape/CMakeLists.txt +++ b/plugins/textshape/CMakeLists.txt @@ -1,175 +1,172 @@ project( textPlugin) add_definitions(-DTRANSLATION_DOMAIN=\"krita_shape_text\") -add_subdirectory( pics ) #add_subdirectory( tests ) include_directories( ${KOTEXT_INCLUDES} ${TEXTLAYOUT_INCLUDES} ${KOWIDGETS_INCLUDES} ${KUNDO2_INCLUDES} ) ########### Flake Plugin library ############### set ( textshape_SRCS TextPlugin.cpp TextShape.cpp TextShapeFactory.cpp TextTool.cpp TextEditingPluginContainer.cpp TextToolFactory.cpp ShrinkToFitShapeContainer.cpp SimpleRootAreaProvider.cpp AnnotationTextShape.cpp AnnotationTextShapeFactory.cpp ChangeTracker.cpp ReviewTool.cpp ReviewToolFactory.cpp TextChanges.cpp TextChange.cpp FontSizeAction.cpp FontFamilyAction.cpp ReferencesTool.cpp ReferencesToolFactory.cpp # dialogs/StylesWidget.cpp # dialogs/SpecialButton.cpp dialogs/StylesCombo.cpp dialogs/StylesComboPreview.cpp dialogs/DockerStylesComboModel.cpp dialogs/SimpleCharacterWidget.cpp dialogs/SimpleParagraphWidget.cpp dialogs/SimpleTableWidget.cpp dialogs/SimpleInsertWidget.cpp dialogs/LinkInsertionDialog.cpp dialogs/SimpleTableOfContentsWidget.cpp dialogs/SimpleCitationBibliographyWidget.cpp dialogs/SimpleLinksWidget.cpp dialogs/SimpleSpellCheckingWidget.cpp dialogs/CitationInsertionDialog.cpp dialogs/InsertBibliographyDialog.cpp dialogs/SimpleFootEndNotesWidget.cpp dialogs/NotesConfigurationDialog.cpp dialogs/SimpleCaptionsWidget.cpp dialogs/ParagraphLayout.cpp dialogs/ParagraphIndentSpacing.cpp dialogs/ParagraphDecorations.cpp dialogs/ParagraphBulletsNumbers.cpp dialogs/ParagraphSettingsDialog.cpp dialogs/ParagraphDropCaps.cpp dialogs/ListsSpinBox.cpp dialogs/StylesModel.cpp dialogs/StylesManagerModel.cpp dialogs/StylesSortFilterProxyModel.cpp dialogs/AbstractStylesModel.cpp dialogs/StylesFilteredModelBase.cpp dialogs/ValidParentStylesProxyModel.cpp dialogs/StylesDelegate.cpp dialogs/StyleManager.cpp dialogs/StyleManagerDialog.cpp dialogs/ParagraphGeneral.cpp dialogs/CharacterGeneral.cpp dialogs/CharacterHighlighting.cpp dialogs/InsertCharacter.cpp dialogs/FontDia.cpp dialogs/FontDecorations.cpp dialogs/LanguageTab.cpp dialogs/FormattingPreview.cpp dialogs/StyleManagerWelcome.cpp dialogs/TableDialog.cpp dialogs/QuickTableButton.cpp dialogs/FormattingButton.cpp dialogs/ChangeConfigureDialog.cpp dialogs/AcceptRejectChangeDialog.cpp dialogs/TrackedChangeModel.cpp dialogs/TrackedChangeManager.cpp dialogs/BibliographyConfigureDialog.cpp dialogs/TableOfContentsConfigure.cpp dialogs/TableOfContentsStyleConfigure.cpp dialogs/TableOfContentsStyleModel.cpp dialogs/TableOfContentsStyleDelegate.cpp dialogs/TableOfContentsPreview.cpp dialogs/TableOfContentsEntryDelegate.cpp dialogs/TableOfContentsEntryModel.cpp dialogs/TableOfContentsTemplate.cpp dialogs/BibliographyTemplate.cpp dialogs/BibliographyPreview.cpp dialogs/ListLevelChooser.cpp dialogs/SimpleAnnotationWidget.cpp dialogs/ManageBookmarkDialog.cpp dialogs/SectionFormatDialog.cpp dialogs/SectionsSplitDialog.cpp commands/ChangeListLevelCommand.cpp commands/ShowChangesCommand.cpp commands/AcceptChangeCommand.cpp commands/RejectChangeCommand.cpp commands/AutoResizeCommand.cpp ) ki18n_wrap_ui(textshape_SRCS dialogs/SimpleCharacterWidget.ui dialogs/SimpleParagraphWidget.ui dialogs/SimpleTableWidget.ui dialogs/SimpleInsertWidget.ui dialogs/SimpleTableOfContentsWidget.ui dialogs/SimpleCitationBibliographyWidget.ui dialogs/SimpleSpellCheckingWidget.ui dialogs/CitationInsertionDialog.ui dialogs/InsertBibliographyDialog.ui dialogs/SimpleFootEndNotesWidget.ui dialogs/NotesConfigurationDialog.ui dialogs/SimpleCaptionsWidget.ui dialogs/StylesWidget.ui dialogs/ParagraphLayout.ui dialogs/ParagraphIndentSpacing.ui dialogs/ParagraphDecorations.ui dialogs/ParagraphBulletsNumbers.ui dialogs/ParagraphDropCaps.ui dialogs/StyleManager.ui dialogs/CharacterGeneral.ui dialogs/CharacterHighlighting.ui dialogs/StyleManagerWelcome.ui dialogs/TableDialog.ui dialogs/BibliographyConfigureDialog.ui dialogs/TableOfContentsConfigure.ui dialogs/SimpleLinksWidget.ui dialogs/TableOfContentsStyleConfigure.ui dialogs/SimpleAnnotationWidget.ui dialogs/FontDecorations.ui dialogs/LanguageTab.ui dialogs/ChangeConfigureDialog.ui dialogs/AcceptRejectChangeDialog.ui dialogs/TrackedChangeManager.ui dialogs/LinkInsertionDialog.ui dialogs/ManageBookmark.ui dialogs/SectionFormatDialog.ui dialogs/SectionsSplitDialog.ui ) +qt5_add_resources(textshape_SRCS textshape.qrc) + + add_library(krita_shape_text MODULE ${textshape_SRCS}) kcoreaddons_desktop_to_json(krita_shape_text calligra_shape_text.desktop) target_link_libraries(krita_shape_text kritatext kritatextlayout kritawidgetutils kritawidgets Qt5::Network KF5::Completion KF5::ItemViews KF5::WidgetsAddons ) if( SHOULD_BUILD_FEATURE_RDF ) target_link_libraries(krita_shape_text ${SOPRANO_LIBRARIES}) endif() install(TARGETS krita_shape_text DESTINATION ${CALLIGRA_PLUGIN_INSTALL_DIR}) - -########### install files ############### - -#ecm_install_icons( ${DATA_INSTALL_DIR}/krita/icons ) - diff --git a/plugins/textshape/pics/CMakeLists.txt b/plugins/textshape/pics/CMakeLists.txt deleted file mode 100644 index b3b443492b..0000000000 --- a/plugins/textshape/pics/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -ecm_install_icons( ICONS - 22-actions-edit-table-cell-merge.png - 22-actions-edit-table-cell-split.png - DESTINATION ${DATA_INSTALL_DIR}/krita/icons - THEME oxygen -) - -ecm_install_icons( ICONS - 22-actions-tool_references.png - 22-actions-tool_review.png - 22-actions-tool-text.png - DESTINATION ${DATA_INSTALL_DIR}/krita/icons - THEME hicolor -) diff --git a/plugins/textshape/textshape.qrc b/plugins/textshape/textshape.qrc new file mode 100644 index 0000000000..3c27331676 --- /dev/null +++ b/plugins/textshape/textshape.qrc @@ -0,0 +1,14 @@ + + + + pics/22-actions-edit-table-cell-merge.png + pics/22-actions-edit-table-cell-split.png + pics/22-actions-tool_references.png + pics/22-actions-tool_review.png + pics/22-actions-tool-text.png + pics/settings-icon1_1.png + pics/tool_references.svg + pics/tool_review.svg + pics/tool-text.svg + +