diff --git a/3rdparty/README.md b/3rdparty/README.md index 7070589e3b..7a93ac00f8 100644 --- a/3rdparty/README.md +++ b/3rdparty/README.md @@ -1,259 +1,260 @@ = CMake external projects to build krita's dependencies on Linux, Windows or OSX = If you need to build Krita's dependencies for the following reasons: * you develop on Windows and aren't using Craft * you develop on OSX and aren't using Homebrew, or are on OSX and want to make distributable app bundles * you want to build a generic, distro-agnostic version of Krita for Linux * you develop on Linux, but some dependencies aren't available for your distribution and you know what you're doing, you can use the following guide to build the dependencies that Krita needs. If you develop on Linux and your distribution has all dependencies available, YOU DO NOT NEED THIS GUIDE AND YOU SHOULD STOP READING NOW Otherwise you risk major confusion. == Prerequisites == Note: on all operating systems the entire procedure is done in a terminal window. 1. git: https://git-scm.com/downloads. Make sure git is in your path 2. CMake 3.3.2 or later: https://cmake.org/download/. Make sure cmake is in your path. * CMake 3.9 does not build Krita properly at the moment, please use 3.8 instead. 3. Make sure you have a compiler: * Linux: gcc, minimum version 4.8 * OSX: clang, you need to install xcode for this * Windows: mingw-w64 7.1 (by mingw-builds) - 32-bit (x86) target: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/7.1.0/threads-posix/dwarf/ - 64-bit (x64) target: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/7.1.0/threads-posix/seh/ Make sure mingw's bin folder is in your path. It might be a good idea to create a batch file which sets the path and start cmd. MSVC is *not* supported at the moment. 4. On Windows, you will also need Python 3.6.2 (technically any versions of 3.6 is fine, but it's not tested): https://www.python.org. Make sure to have that version of python.exe in your path. This version of Python will be used for two things: to configure Qt and to build the Python scripting module. Make sure the version you download is exactly python-3.6.2. Make sure that this version of Python comes first in your path. Do not set PYTHONHOME or PYTHONPATH. Make sure that your Python will have the correct architecture for the version you are trying to build: https://www.python.org/downloads/windows/ 5. On Windows, if you want to compile Qt with ANGLE support, you will need to install Windows 10 SDK and have the environment variable `WindowsSdkDir` set to it (typically `C:\Program Files (x86)\Windows Kits\10`) == Setup your environment == == Prepare your directory layout == 1. Make a toplevel build directory, say $HOME/dev or c:\dev. We'll refer to this directory as BUILDROOT. You can use a variable for this, on WINDOWS %BUILDROOT%, on OSX and Linux $BUILDROOT. You will have to replace BUILDROOT with $BUILDROOT or %BUILDROOT whenever you copy and paste a command, depending on your operating system. 2. Checkout krita in BUILDROOT cd BUILDROOT git clone git://anongit.kde.org/krita.git 3. Create the build directory mkdir BUILDROOT/b 4. Create the downloads directory mkdir BUILDROOT/d 5. Create the install directory mkdir BUILDROOT/i == Prepare the externals build == 1. enter the BUILDROOT/b directory 2. run cmake: * Linux: export PATH=$BUILDROOT/i/bin:$PATH export PYTHONHOME=$BUILDROOT/i (only if you want to build your own python) cmake ../krita/3rdparty \ -DINSTALL_ROOT=$BUILDROOT/i \ -DEXTERNALS_DOWNLOAD_DIR=$BUILDROOT/d \ -DCMAKE_INSTALL_PREFIX=BUILDROOT/i * OSX: export PATH=$BUILDROOT/i/bin:$PATH export PYTHONHOME=$BUILDROOT/i (only if you want to build your own python) cmake ../krita/3rdparty/ \ -DCMAKE_INSTALL_PREFIX=$BUILDROOT/i \ -DEXTERNALS_DOWNLOAD_DIR=$BUILDROOT/d \ -DINSTALL_ROOT=$BUILDROOT/i * Windows 32-bit / 64-bit: Note that the cmake command needs to point to your BUILDROOT like /dev/d, not c:\dev\d. set PATH=%BUILDROOT%\i\bin\;%BUILDROOT%\i\lib;%PATH% set PATH=BUILDROOT\i\bin\;BUILDROOT\i\lib;%PATH% cmake ..\krita\3rdparty -DEXTERNALS_DOWNLOAD_DIR=/dev/d -DINSTALL_ROOT=/dev/i -G "MinGW Makefiles" - If you want to build Qt and some other dependencies with parallel jobs, add `-DSUBMAKE_JOBS=` to the cmake command where is the number of jobs to run (if your PC has 4 CPU cores, you might want to set it to 5). - If you don't have Windows 10 SDK and don't want to build Qt with ANGLE, add `-DQT_ENABLE_DYNAMIC_OPENGL=OFF` to the CMake command line args. 3. build the packages: With a judicious application of DEPENDS statements, it's possible to build it all in one go, but in my experience that fails always, so it's better to build the dependencies independently. On Windows: cmake --build . --config RelWithDebInfo --target ext_patch cmake --build . --config RelWithDebInfo --target ext_png2ico cmake --build . --config RelWithDebInfo --target ext_gettext On OSX: cmake --build . --config RelWithDebInfo --target ext_gettext On all operating systems: cmake --build . --config RelWithDebInfo --target ext_qt cmake --build . --config RelWithDebInfo --target ext_zlib cmake --build . --config RelWithDebInfo --target ext_boost Note about boost: check if the headers are installed into i/include/boost, but not into i/include/boost-1.61/boost cmake --build . --config RelWithDebInfo --target ext_eigen3 cmake --build . --config RelWithDebInfo --target ext_exiv2 cmake --build . --config RelWithDebInfo --target ext_fftw3 On all operating systems cmake --build . --config RelWithDebInfo --target ext_ilmbase cmake --build . --config RelWithDebInfo --target ext_jpeg cmake --build . --config RelWithDebInfo --target ext_lcms2 cmake --build . --config RelWithDebInfo --target ext_ocio cmake --build . --config RelWithDebInfo --target ext_openexr Note for OSX: On OSX, you need to first build openexr; that will fail; then you need to set the rpath for the two utilities correctly, then try to build openexr again. install_name_tool -add_rpath $BUILD_ROOT/i/lib $BUILD_ROOT/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./b44ExpLogTable install_name_tool -add_rpath $BUILD_ROOT/i/lib $BUILD_ROOT/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./dwaLookups On All operating systems: cmake --build . --config RelWithDebInfo --target ext_png cmake --build . --config RelWithDebInfo --target ext_tiff cmake --build . --config RelWithDebInfo --target ext_gsl cmake --build . --config RelWithDebInfo --target ext_vc cmake --build . --config RelWithDebInfo --target ext_libraw cmake --build . --config RelWithDebInfo --target ext_giflib On Linux, if you want to build your own SIP and PyQt instead of the system one: cmake --build . --config RelWithDebInfo --target ext_sip cmake --build . --config RelWithDebInfo --target ext_pyqt On Windows cmake --build . --config RelWithDebInfo --target ext_freetype cmake --build . --config RelWithDebInfo --target ext_poppler On Linux cmake --build . --config RelWithDebInfo --target ext_kcrash Everywhere else: cmake --build . --config RelWithDebInfo --target ext_kwindowsystem On Windows, if you want to include DrMingw for dumping backtrace on crash: cmake --build . --config RelWithDebInfo --target ext_drmingw On Windows, if you want to include Python scripting: cmake --build . --config RelWithDebInfo --target ext_python cmake --build . --config RelWithDebInfo --target ext_sip cmake --build . --config RelWithDebInfo --target ext_pyqt On Windows and Linux, if you want to build gmic-qt: cmake --build . --config RelWithDebInfo --target ext_gmic Note: poppler should be buildable on Linux as well with a home-built freetype and fontconfig, but I don't know how to make fontconfig find freetype, and on Linux, fontconfig is needed for poppler. Poppler is needed for PDF import. -Note 2: if you want to build a release, you need to get the binary gettext Note 3: in order to build fontconfig on macOS, you need to have pkg-config installed. You probably need homebrew for that... See http://macappstore.org/pkg-config/ . archives from files.kde.org/krita/build/dependencies: +Note 2: if you want to build on Windows, you need to get the binary gettext + http://files.kde.org/krita/build/dependencies/gettext0.19.8.1-iconv1.14-shared-32.zip http://files.kde.org/krita/build/dependencies/gettext0.19.8.1-iconv1.14-shared-64.zip Take care, these zips contain a libstdc++-6.dll that you don't want in your path when building. == Build Krita == 1. Make a krita build directory: mkdir BUILDROOT/build 2. Enter the BUILDROOT/build 3. Run On Windows Depending on what you want to use, run this command for MSBuild: cmake ..\krita -G "MinGW Makefiles" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -Wno-dev -DDEFINE_NO_DEPRECATED=1 Or this to use jom (faster compiling, uses all cores, ships with QtCreator/pre-built Qt binaries): cmake ..\krita -G "MinGW Makefiles" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -Wno-dev -DDEFINE_NO_DEPRECATED=1 On Linux cmake ../krita -DCMAKE_INSTALL_PREFIX=BUILDROOT/i -DDEFINE_NO_DEPRECATED=1 -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo # Troubleshooting: if you built your own SIP and CMake fails to find it, please set # the following environment variable to the SIP installation directory: export PYTHONPATH=$BUILDROOT/i/sip/ # If you also have KIO installed in the system, don't forget to disable it by bassing to cmake: # cmake -DCMAKE_DISABLE_FIND_PACKAGE_KF5KIO=true . On OSX cmake ../krita -DCMAKE_INSTALL_PREFIX=$BUILDROOT/i -DDEFINE_NO_DEPRECATED=1 -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DBUNDLE_INSTALL_DIR=$BUILDROOT/i/bin -DCMAKE_BUILD_TYPE=RelWithDebInfo 4. Run On Linux and OSX make make install On Windows (replace 4 with the number of jobs to run in parallel) cmake --build . --target install -- -j4 6. Run krita: On Linux BUILDROOT/i/bin/krita On Windows BUILDROOT\i\bin\krita.exe On OSX BUILDROOT/i/bin/krita.app/Contents/MacOS/krita == Packaging a Windows Build == If you want to create a stripped down version of Krita to distribute, after building everything just copy the package_2.cmd file from the "windows" folder inside krita root source folder to BUILDROOT and run it (most likely C:\dev\). That script will copy the necessary files into the specified folder and leave out developer related files. After the script runs there will be two new ZIP files that contain a small portable version of Krita and a separate portable debug version. diff --git a/libs/libkis/Palette.cpp b/libs/libkis/Palette.cpp index 02270710ae..8ccde32577 100644 --- a/libs/libkis/Palette.cpp +++ b/libs/libkis/Palette.cpp @@ -1,158 +1,158 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 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 Lesser 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 "Palette.h" #include #include struct Palette::Private { KoColorSet *palette {0}; }; Palette::Palette(Resource *resource): d(new Private()) { d->palette = dynamic_cast(resource->resource()); } Palette::~Palette() { delete d; } int Palette::numberOfEntries() const { if (!d->palette) return 0; return d->palette->nColors(); } int Palette::columnCount() { if (!d->palette) return 0; return d->palette->columnCount(); } void Palette::setColumnCount(int columns) { if (d->palette) d->palette->setColumnCount(columns); } QString Palette::comment() { if (!d->palette) return ""; return d->palette->comment(); } void Palette::setComment(QString comment) { if (!d->palette) return; return d->palette->setComment(comment); } QStringList Palette::groupNames() { if (!d->palette) return QStringList(); return d->palette->getGroupNames(); } bool Palette::addGroup(QString name) { if (!d->palette) return false; return d->palette->addGroup(name); } bool Palette::removeGroup(QString name, bool keepColors) { if (!d->palette) return false; return d->palette->removeGroup(name, keepColors); } int Palette::colorsCountTotal() { if (!d->palette) return 0; return d->palette->nColors(); } int Palette::colorsCountGroup(QString name) { if (!d->palette) return 0; return d->palette->nColorsGroup(name); } KoColorSetEntry Palette::colorSetEntryByIndex(int index) { if (!d->palette) return KoColorSetEntry(); return d->palette->getColorGlobal(index); } KoColorSetEntry Palette::colorSetEntryFromGroup(int index, const QString &groupName) { if (!d->palette) return KoColorSetEntry(); return d->palette->getColorGroup(index, groupName); } ManagedColor *Palette::colorForEntry(KoColorSetEntry entry) { if (!d->palette) return 0; - ManagedColor *color = new ManagedColor(entry.color); + ManagedColor *color = new ManagedColor(entry.color()); return color; } void Palette::addEntry(KoColorSetEntry entry, QString groupName) { d->palette->add(entry, groupName); } void Palette::removeEntry(int index, const QString &groupName) { d->palette->removeAt(index, groupName); } void Palette::insertEntry(int index, KoColorSetEntry entry, QString groupName) { d->palette->insertBefore(entry, index, groupName); } bool Palette::editEntry(int index, KoColorSetEntry entry, QString groupName) { return d->palette->changeColorSetEntry(entry, groupName, index); } bool Palette::changeGroupName(QString oldGroupName, QString newGroupName) { return d->palette->changeGroupName(oldGroupName, newGroupName); } bool Palette::moveGroup(const QString &groupName, const QString &groupNameInsertBefore) { return d->palette->moveGroup(groupName, groupNameInsertBefore); } bool Palette::save() { if (d->palette->filename().size()>0) { return d->palette->save(); } //if there's no filename the palette proly doesn't even exist... return false; } KoColorSet *Palette::colorSet() { return d->palette; } diff --git a/libs/libkis/Palette.h b/libs/libkis/Palette.h index 4904f94ac0..901fd60c5f 100644 --- a/libs/libkis/Palette.h +++ b/libs/libkis/Palette.h @@ -1,204 +1,204 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 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 Lesser 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 LIBKIS_PALETTE_H #define LIBKIS_PALETTE_H #include #include "kritalibkis_export.h" #include "libkis.h" #include "Resource.h" #include "KoColorSet.h" class ManagedColor; /** * @brief The Palette class * Palette is a resource object that stores organised color data. * It's purpose is to allow artists to save colors and store them. * * An example for printing all the palettes and the entries: * * @code import sys from krita import * resources = Application.resources("palette") for (k, v) in resources.items(): print(k) palette = Palette(v) for x in range(palette.numberOfEntries()): entry = palette.colorSetEntryByIndex(x) c = palette.colorForEntry(entry); - print(x, entry.name, entry.id, entry.spotColor, c.toQString()) + print(x, entry.name(), entry.id(), entry.spotColor(), c.toQString()) * @endcode */ class KRITALIBKIS_EXPORT Palette : public QObject { public: Palette(Resource *resource); ~Palette() override; /** * @brief numberOfEntries * @return */ int numberOfEntries() const; /** * @brief columnCount * @return the amount of columns this palette is set to use. */ int columnCount(); /** * @brief setColumnCount * Set the amount of columns this palette should use. */ void setColumnCount(int columns); /** * @brief comment * @return the comment or description associated with the palette. */ QString comment(); /** * @brief setComment * set the comment or description associated with the palette. * @param comment */ void setComment(QString comment); /** * @brief groupNames * @return the list of group names. This is list is in the order these groups are in the file. */ QStringList groupNames(); /** * @brief addGroup * @param name of the new group * @return whether adding the group was successful. */ bool addGroup(QString name); /** * @brief removeGroup * @param name the name of the group to remove. * @param keepColors whether or not to delete all the colors inside, or to move them to the default group. * @return */ bool removeGroup(QString name, bool keepColors = true); /** * @brief colorsCountTotal * @return the total amount of entries in the whole group */ int colorsCountTotal(); /** * @brief colorsCountGroup * @param name of the group to check. Empty is the default group. * @return the amount of colors within that group. */ int colorsCountGroup(QString name); /** * @brief colorSetEntryByIndex * get the colorsetEntry from the global index. * @param index the global index * @return the colorset entry */ KoColorSetEntry colorSetEntryByIndex(int index); /** * @brief colorSetEntryFromGroup * @param index index in the group. * @param groupName the name of the group to get the color from. * @return the colorsetentry. */ KoColorSetEntry colorSetEntryFromGroup(int index, const QString &groupName); /** * @brief colorForEntry * special function to retrieve a ManagedColor object from the colorsetentry. * @param entry the entry * @return the ManagedColorObject */ ManagedColor *colorForEntry(KoColorSetEntry entry); /** * @brief addEntry * add an entry to a group. Gets appended to the end. * @param entry the entry * @param groupName the name of the group to add to. */ void addEntry(KoColorSetEntry entry, QString groupName = QString()); /** * @brief removeEntry * remove the entry at @param index from the group @param groupName. */ void removeEntry(int index, const QString &groupName); /** * @brief insertEntry * like addentry, but allows you to pick the index to insertBefore. * @param index * @param entry * @param groupName */ void insertEntry(int index, KoColorSetEntry entry, QString groupName = QString()); /** * @brief editEntry * Changes the entry at @param index by replacing it with @param entry. * @param groupName the group at which the index is. * @return whether it was successful. */ bool editEntry (int index, KoColorSetEntry entry, QString groupName = QString()); /** * @brief changeGroupName * change the group name. * @param oldGroupName the old groupname to change. * @param newGroupName the new name to change it into. * @return whether successful. Reasons for failure include not knowing have oldGroupName */ bool changeGroupName(QString oldGroupName, QString newGroupName); /** * @brief moveGroup * move the group to before groupNameInsertBefore. * @param groupName group to move. * @param groupNameInsertBefore group to inset before. * @return whether successful. Reasons for failure include either group not existing. */ bool moveGroup(const QString &groupName, const QString &groupNameInsertBefore = QString()); /** * @brief save * save the palette * @return whether it was successful. */ bool save(); private: friend class PaletteView; struct Private; Private *const d; /** * @brief colorSet * @return gives qa KoColorSet object back */ KoColorSet *colorSet(); }; #endif // LIBKIS_PALETTE_H diff --git a/libs/libqml/plugins/kritasketchplugin/models/PaletteColorsModel.cpp b/libs/libqml/plugins/kritasketchplugin/models/PaletteColorsModel.cpp index 90af9b254d..4e5c027001 100644 --- a/libs/libqml/plugins/kritasketchplugin/models/PaletteColorsModel.cpp +++ b/libs/libqml/plugins/kritasketchplugin/models/PaletteColorsModel.cpp @@ -1,147 +1,147 @@ /* This file is part of the KDE project * Copyright (C) 2012 Dan Leinir Turthra Jensen * * 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 "PaletteColorsModel.h" #include #include #include class PaletteColorsModel::Private { public: Private() : colorSet(0) , view(0) {} KoColorSet* colorSet; KisViewManager* view; }; PaletteColorsModel::PaletteColorsModel(QObject *parent) : QAbstractListModel(parent) , d(new Private) { } PaletteColorsModel::~PaletteColorsModel() { delete d; } QHash PaletteColorsModel::roleNames() const { QHash roles; roles[ImageRole] = "image"; roles[TextRole] = "text"; return roles; } int PaletteColorsModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; if (!d->colorSet) return 0; return d->colorSet->nColors(); } QVariant PaletteColorsModel::data(const QModelIndex &index, int role) const { QVariant result; QColor color; if (index.isValid() && d->colorSet) { switch(role) { case ImageRole: - color = d->colorSet->getColorGlobal(index.row()).color.toQColor(); + color = d->colorSet->getColorGlobal(index.row()).color().toQColor(); result = QString("image://color/%1,%2,%3,%4").arg(color.redF()).arg(color.greenF()).arg(color.blueF()).arg(color.alphaF()); break; case TextRole: - result = d->colorSet->getColorGlobal(index.row()).name; + result = d->colorSet->getColorGlobal(index.row()).name(); break; default: break; } } return result; } QVariant PaletteColorsModel::headerData(int section, Qt::Orientation orientation, int role) const { Q_UNUSED(orientation); QVariant result; if (section == 0) { switch(role) { case ImageRole: result = QString("Thumbnail"); break; case TextRole: result = QString("Name"); break; default: break; } } return result; } void PaletteColorsModel::setColorSet(QObject *newColorSet) { d->colorSet = qobject_cast(newColorSet); beginResetModel(); endResetModel(); emit colorSetChanged(); } QObject* PaletteColorsModel::colorSet() const { return d->colorSet; } QObject* PaletteColorsModel::view() const { return d->view; } void PaletteColorsModel::setView(QObject* newView) { d->view = qobject_cast( newView ); emit viewChanged(); } void PaletteColorsModel::activateColor(int index, bool setBackgroundColor) { if ( !d->view ) return; if (index >= 0 && index < (int)d->colorSet->nColors()) { if (setBackgroundColor) - d->view->resourceProvider()->setBGColor(d->colorSet->getColorGlobal(index).color); + d->view->resourceProvider()->setBGColor(d->colorSet->getColorGlobal(index).color()); else - d->view->resourceProvider()->setFGColor( d->colorSet->getColorGlobal(index).color); - emit colorChanged(d->colorSet->getColorGlobal(index).color.toQColor(), setBackgroundColor); + d->view->resourceProvider()->setFGColor( d->colorSet->getColorGlobal(index).color()); + emit colorChanged(d->colorSet->getColorGlobal(index).color().toQColor(), setBackgroundColor); } } diff --git a/libs/pigment/CMakeLists.txt b/libs/pigment/CMakeLists.txt index 9e98621272..1d2c1a58f9 100644 --- a/libs/pigment/CMakeLists.txt +++ b/libs/pigment/CMakeLists.txt @@ -1,121 +1,122 @@ project(kritapigment) # we have to repeat platform specifics from top-level if (WIN32) include_directories(${CMAKE_SOURCE_DIR}/winquirks) add_definitions(-D_USE_MATH_DEFINES) add_definitions(-DNOMINMAX) set(WIN32_PLATFORM_NET_LIBS ws2_32.lib netapi32.lib) endif () include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/resources ${CMAKE_CURRENT_SOURCE_DIR}/compositeops) set(FILE_OPENEXR_SOURCES) set(LINK_OPENEXR_LIB) if(OPENEXR_FOUND) include_directories(SYSTEM ${OPENEXR_INCLUDE_DIR}) set(LINK_OPENEXR_LIB ${OPENEXR_LIBRARIES}) add_definitions(${OPENEXR_DEFINITIONS}) endif() set(LINK_VC_LIB) if(HAVE_VC) include_directories(SYSTEM ${Vc_INCLUDE_DIR}) set(LINK_VC_LIB ${Vc_LIBRARIES}) ko_compile_for_all_implementations_no_scalar(__per_arch_factory_objs compositeops/KoOptimizedCompositeOpFactoryPerArch.cpp) message("Following objects are generated from the per-arch lib") message("${__per_arch_factory_objs}") endif() add_subdirectory(tests) add_subdirectory(benchmarks) set(kritapigment_SRCS DebugPigment.cpp KoBasicHistogramProducers.cpp KoColor.cpp KoColorDisplayRendererInterface.cpp KoColorConversionAlphaTransformation.cpp KoColorConversionCache.cpp KoColorConversions.cpp KoColorConversionSystem.cpp KoColorConversionTransformation.cpp KoColorProofingConversionTransformation.cpp KoColorConversionTransformationFactory.cpp KoColorModelStandardIds.cpp KoColorProfile.cpp KoColorSpace.cpp KoColorSpaceEngine.cpp KoColorSpaceFactory.cpp KoColorSpaceMaths.cpp KoColorSpaceRegistry.cpp KoColorProfileStorage.cpp KoColorTransformation.cpp KoColorTransformationFactory.cpp KoColorTransformationFactoryRegistry.cpp KoCompositeColorTransformation.cpp KoCompositeOp.cpp KoCompositeOpRegistry.cpp KoCopyColorConversionTransformation.cpp KoFallBackColorTransformation.cpp KoHistogramProducer.cpp KoMultipleColorConversionTransformation.cpp KoUniqueNumberForIdServer.cpp colorspaces/KoAlphaColorSpace.cpp colorspaces/KoLabColorSpace.cpp colorspaces/KoRgbU16ColorSpace.cpp colorspaces/KoRgbU8ColorSpace.cpp colorspaces/KoSimpleColorSpaceEngine.cpp compositeops/KoOptimizedCompositeOpFactory.cpp compositeops/KoOptimizedCompositeOpFactoryPerArch_Scalar.cpp ${__per_arch_factory_objs} colorprofiles/KoDummyColorProfile.cpp resources/KoAbstractGradient.cpp resources/KoColorSet.cpp + resources/KoColorSetEntry.cpp resources/KoPattern.cpp resources/KoResource.cpp resources/KoMD5Generator.cpp resources/KoHashGeneratorProvider.cpp resources/KoStopGradient.cpp resources/KoSegmentGradient.cpp ) set (EXTRA_LIBRARIES ${LINK_OPENEXR_LIB} ${LINK_VC_LIB}) if(MSVC OR (WIN32 AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")) # avoid "cannot open file 'LIBC.lib'" error set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:LIBC.LIB") endif() add_library(kritapigment SHARED ${kritapigment_SRCS}) generate_export_header(kritapigment) target_include_directories( kritapigment PUBLIC $ $ ) target_link_libraries( kritapigment PUBLIC kritaplugin kritastore kritaglobal ${EXTRA_LIBRARIES} KF5::I18n KF5::ConfigCore Qt5::Core Qt5::Gui Qt5::Xml ${WIN32_PLATFORM_NET_LIBS} ) set_target_properties(kritapigment PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritapigment ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/pigment/resources/KoColorSet.cpp b/libs/pigment/resources/KoColorSet.cpp index 9fa531c60d..26ae96982e 100644 --- a/libs/pigment/resources/KoColorSet.cpp +++ b/libs/pigment/resources/KoColorSet.cpp @@ -1,1569 +1,1573 @@ /* This file is part of the KDE project Copyright (c) 2005 Boudewijn Rempt Copyright (c) 2016 L. E. Segovia This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include // qFromLittleEndian #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoColor.h" +#include "KoColorSetEntry.h" #include "KoColorProfile.h" #include "KoColorSpaceRegistry.h" #include "KoColorModelStandardIds.h" struct KoColorSet::Private { KoColorSet::PaletteType paletteType; QByteArray data; QString comment; qint32 columns; QVector colors; //ungrouped colors QStringList groupNames; //names of the groups, this is used to determine the order they are in. QMap> groups; //grouped colors. }; KoColorSet::PaletteType detectFormat(const QString &fileName, const QByteArray &ba) { QFileInfo fi(fileName); // .pal if (ba.startsWith("RIFF") && ba.indexOf("PAL data", 8)) { return KoColorSet::RIFF_PAL; } // .gpl else if (ba.startsWith("GIMP Palette")) { return KoColorSet::GPL; } // .pal else if (ba.startsWith("JASC-PAL")) { return KoColorSet::PSP_PAL; } else if (fi.suffix().toLower() == "aco") { return KoColorSet::ACO; } else if (fi.suffix().toLower() == "act") { return KoColorSet::ACT; } else if (fi.suffix().toLower() == "xml") { return KoColorSet::XML; } else if (fi.suffix().toLower() == "kpl") { return KoColorSet::KPL; } else if (fi.suffix().toLower() == "sbz") { return KoColorSet::SBZ; } return KoColorSet::UNKNOWN; } KoColorSet::KoColorSet(const QString& filename) : KoResource(filename) , d(new Private()) { // Implemented in KoResource class d->columns = 0; // Set the default value that the GIMP uses... } KoColorSet::KoColorSet() : KoResource(QString()) , d(new Private()) { d->columns = 0; // Set the default value that the GIMP uses... } /// Create an copied palette KoColorSet::KoColorSet(const KoColorSet& rhs) : QObject(0) , KoResource(QString()) , d(new Private()) { setFilename(rhs.filename()); d->comment = rhs.d->comment; d->columns = rhs.d->columns; d->colors = rhs.d->colors; d->groupNames = rhs.d->groupNames; d->groups = rhs.d->groups; setValid(true); } KoColorSet::~KoColorSet() { } bool KoColorSet::load() { QFile file(filename()); if (file.size() == 0) return false; if (!file.open(QIODevice::ReadOnly)) { warnPigment << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool KoColorSet::loadFromDevice(QIODevice *dev) { if (!dev->isOpen()) dev->open(QIODevice::ReadOnly); d->data = dev->readAll(); Q_ASSERT(d->data.size() != 0); return init(); } bool KoColorSet::save() { QFile file(filename()); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } saveToDevice(&file); file.close(); return true; } bool KoColorSet::saveToDevice(QIODevice *dev) const { bool res; switch(d->paletteType) { case GPL: res = saveGpl(dev); break; default: res = saveKpl(dev); } if (res) { KoResource::saveToDevice(dev); } return res; } bool KoColorSet::init() { d->colors.clear(); // just in case this is a reload (eg by KoEditColorSetDialog), d->groups.clear(); d->groupNames.clear(); if (filename().isNull()) { warnPigment << "Cannot load palette" << name() << "there is no filename set"; return false; } if (d->data.isNull()) { QFile file(filename()); if (file.size() == 0) { warnPigment << "Cannot load palette" << name() << "there is no data available"; return false; } file.open(QIODevice::ReadOnly); d->data = file.readAll(); file.close(); } bool res = false; d->paletteType = detectFormat(filename(), d->data); switch(d->paletteType) { case GPL: res = loadGpl(); break; case ACT: res = loadAct(); break; case RIFF_PAL: res = loadRiff(); break; case PSP_PAL: res = loadPsp(); break; case ACO: res = loadAco(); break; case XML: res = loadXml(); break; case KPL: res = loadKpl(); break; case SBZ: res = loadSbz(); break; default: res = false; } setValid(res); if (d->columns == 0) { d->columns = 10; } QImage img(d->columns * 4, (d->colors.size() / d->columns) * 4, QImage::Format_ARGB32); QPainter gc(&img); gc.fillRect(img.rect(), Qt::darkGray); int counter = 0; for(int i = 0; i < d->columns; ++i) { for (int j = 0; j < (d->colors.size() / d->columns); ++j) { if (counter < d->colors.size()) { - QColor c = d->colors.at(counter).color.toQColor(); + QColor c = d->colors.at(counter).color().toQColor(); gc.fillRect(i * 4, j * 4, 4, 4, c); counter++; } else { break; } } } setImage(img); // save some memory d->data.clear(); return res; } bool KoColorSet::saveGpl(QIODevice *dev) const { QTextStream stream(dev); stream << "GIMP Palette\nName: " << name() << "\nColumns: " << d->columns << "\n#\n"; for (int i = 0; i < d->colors.size(); i++) { const KoColorSetEntry& entry = d->colors.at(i); - QColor c = entry.color.toQColor(); + QColor c = entry.color().toQColor(); stream << c.red() << " " << c.green() << " " << c.blue() << "\t"; - if (entry.name.isEmpty()) + if (entry.name().isEmpty()) stream << "Untitled\n"; else - stream << entry.name << "\n"; + stream << entry.name() << "\n"; } return true; } quint32 KoColorSet::nColors() { if (d->colors.isEmpty()) return 0; quint32 total = d->colors.size(); if (!d->groups.empty()) { Q_FOREACH (const QVector &group, d->groups.values()) { total += group.size(); } } return total; } quint32 KoColorSet::nColorsGroup(QString groupName) { if (d->groups.contains(groupName)) { return d->groups.value(groupName).size(); } else if (groupName.isEmpty() && !d->colors.isEmpty()){ return d->colors.size(); } else { return 0; } } quint32 KoColorSet::getIndexClosestColor(const KoColor color, bool useGivenColorSpace) { quint32 closestIndex = 0; quint8 highestPercentage = 0; quint8 testPercentage = 0; KoColor compare = color; for (quint32 i=0; idifference(compare.data(), entry.data())); if (testPercentage>highestPercentage) { closestIndex = i; highestPercentage = testPercentage; } } return closestIndex; } QString KoColorSet::closestColorName(const KoColor color, bool useGivenColorSpace) { int i = getIndexClosestColor(color, useGivenColorSpace); - QString name = getColorGlobal(i).name; - return name; + return getColorGlobal(i).name(); } void KoColorSet::add(const KoColorSetEntry & c, QString groupName) { if (d->groups.contains(groupName) || d->groupNames.contains(groupName)) { d->groups[groupName].push_back(c); } else { d->colors.push_back(c); } } quint32 KoColorSet::insertBefore(const KoColorSetEntry &c, qint32 index, const QString &groupName) { quint32 newIndex = index; if (d->groups.contains(groupName)) { d->groups[groupName].insert(index, c); } else if (groupName.isEmpty()){ d->colors.insert(index, c); } else { warnPigment << "Couldn't find group to insert to"; } return newIndex; } void KoColorSet::removeAt(quint32 index, QString groupName) { if (d->groups.contains(groupName)){ if ((quint32)d->groups.value(groupName).size()>index) { d->groups[groupName].remove(index); } } else { if ((quint32)d->colors.size()>index) { d->colors.remove(index); } } } void KoColorSet::clear() { d->colors.clear(); d->groups.clear(); } KoColorSetEntry KoColorSet::getColorGlobal(quint32 index) { KoColorSetEntry e; quint32 groupIndex = index; QString groupName = findGroupByGlobalIndex(index, &groupIndex); e = getColorGroup(groupIndex, groupName); return e; } KoColorSetEntry KoColorSet::getColorGroup(quint32 index, QString groupName) { KoColorSetEntry e; if (d->groups.contains(groupName)) { if (nColorsGroup(groupName)>index) { e = d->groups.value(groupName).at(index); } else { warnPigment<index) { e = d->colors.at(index); } else { warnPigment<colors.size()<=*index) { *index -= (quint32)d->colors.size(); if (!d->groups.empty() || !d->groupNames.empty()) { QStringList groupNames = getGroupNames(); Q_FOREACH (QString name, groupNames) { quint32 size = (quint32)d->groups.value(name).size(); if (size<=*index) { *index -= size; } else { groupName = name; return groupName; } } } } return groupName; } QString KoColorSet::findGroupByColorName(const QString &name, quint32 *index) { *index = 0; QString groupName = QString(); for (int i = 0; icolors.size(); i++) { - if(d->colors.at(i).name == name) { + if(d->colors.at(i).name() == name) { *index = (quint32)i; return groupName; } } QStringList groupNames = getGroupNames(); Q_FOREACH (QString name, groupNames) { for (int i=0; igroups[name].size(); i++) { - if(d->groups[name].at(i).name == name) { + if(d->groups[name].at(i).name() == name) { *index = (quint32)i; groupName = name; return groupName; } } } return groupName; } QString KoColorSet::findGroupByID(const QString &id, quint32 *index) { *index = 0; QString groupName = QString(); for (int i = 0; icolors.size(); i++) { - if(d->colors.at(i).id == id) { + if(d->colors.at(i).id() == id) { *index = (quint32)i; return groupName; } } QStringList groupNames = getGroupNames(); Q_FOREACH (QString name, groupNames) { for (int i=0; igroups[name].size(); i++) { - if(d->groups[name].at(i).id == id) { + if(d->groups[name].at(i).id() == id) { *index = (quint32)i; groupName = name; return groupName; } } } return groupName; } QStringList KoColorSet::getGroupNames() { if (d->groupNames.size()groups.size()) { warnPigment << "mismatch between groups and the groupnames list."; return QStringList(d->groups.keys()); } return d->groupNames; } bool KoColorSet::changeGroupName(QString oldGroupName, QString newGroupName) { if (d->groupNames.contains(oldGroupName)==false) { return false; } QVector dummyList = d->groups.value(oldGroupName); d->groups.remove(oldGroupName); d->groups[newGroupName] = dummyList; //rename the string in the stringlist; int index = d->groupNames.indexOf(oldGroupName); d->groupNames.replace(index, newGroupName); return true; } bool KoColorSet::changeColorSetEntry(KoColorSetEntry entry, QString groupName, quint32 index) { if (index>=nColorsGroup(groupName) || (d->groupNames.contains(groupName)==false && groupName.size()>0)) { return false; } if (groupName==QString()) { d->colors[index] = entry; } else { d->groups[groupName][index] = entry; } return true; } void KoColorSet::setColumnCount(int columns) { d->columns = columns; } int KoColorSet::columnCount() { return d->columns; } QString KoColorSet::comment() { return d->comment; } void KoColorSet::setComment(QString comment) { d->comment = comment; } bool KoColorSet::addGroup(const QString &groupName) { if (d->groups.contains(groupName) || d->groupNames.contains(groupName)) { return false; } d->groupNames.append(groupName); d->groups[groupName] = QVector(); return true; } bool KoColorSet::moveGroup(const QString &groupName, const QString &groupNameInsertBefore) { if (d->groupNames.contains(groupName)==false || d->groupNames.contains(groupNameInsertBefore)==false) { return false; } d->groupNames.removeAt(d->groupNames.indexOf(groupName)); int index = d->groupNames.size(); if (groupNameInsertBefore!=QString()) { index = d->groupNames.indexOf(groupNameInsertBefore); } d->groupNames.insert(index, groupName); return true; } bool KoColorSet::removeGroup(const QString &groupName, bool keepColors) { if (!d->groups.contains(groupName)) { return false; } if (keepColors) { for (int i = 0; igroups.value(groupName).size(); i++) { d->colors.append(d->groups.value(groupName).at(i)); } } for(int n = 0; ngroupNames.size(); n++) { if (d->groupNames.at(n) == groupName) { d->groupNames.removeAt(n); } } d->groups.remove(groupName); return true; } QString KoColorSet::defaultFileExtension() const { return QString(".kpl"); } bool KoColorSet::loadGpl() { QString s = QString::fromUtf8(d->data.data(), d->data.count()); if (s.isEmpty() || s.isNull() || s.length() < 50) { warnPigment << "Illegal Gimp palette file: " << filename(); return false; } quint32 index = 0; QStringList lines = s.split('\n', QString::SkipEmptyParts); if (lines.size() < 3) { return false; } QString columns; qint32 r, g, b; KoColorSetEntry e; // Read name if (!lines[0].startsWith("GIMP") || !lines[1].startsWith("Name: ")) { warnPigment << "Illegal Gimp palette file: " << filename(); return false; } setName(i18n(lines[1].mid(strlen("Name: ")).trimmed().toLatin1())); index = 2; // Read columns if (lines[index].startsWith("Columns: ")) { columns = lines[index].mid(strlen("Columns: ")).trimmed(); d->columns = columns.toInt(); index = 3; } for (qint32 i = index; i < lines.size(); i++) { if (lines[i].startsWith('#')) { d->comment += lines[i].mid(1).trimmed() + ' '; } else if (!lines[i].isEmpty()) { QStringList a = lines[i].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() < 3) { break; } r = a[0].toInt(); a.pop_front(); g = a[0].toInt(); a.pop_front(); b = a[0].toInt(); a.pop_front(); r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); - e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); - e.color.fromQColor(QColor(r, g, b)); + e.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8())); QString name = a.join(" "); - e.name = name.isEmpty() ? i18n("Untitled") : name; + e.setName(name.isEmpty() ? i18n("Untitled") : name); add(e); } } return true; } bool KoColorSet::loadAct() { QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; for (int i = 0; i < d->data.size(); i += 3) { quint8 r = d->data[i]; quint8 g = d->data[i+1]; quint8 b = d->data[i+2]; - e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); - e.color.fromQColor(QColor(r, g, b)); + e.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8())); add(e); } return true; } struct RiffHeader { quint32 riff; quint32 size; quint32 signature; quint32 data; quint32 datasize; quint16 version; quint16 colorcount; }; bool KoColorSet::loadRiff() { // http://worms2d.info/Palette_file QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; RiffHeader header; memcpy(&header, d->data.constData(), sizeof(RiffHeader)); header.colorcount = qFromBigEndian(header.colorcount); for (int i = sizeof(RiffHeader); (i < (int)(sizeof(RiffHeader) + header.colorcount) && i < d->data.size()); i += 4) { quint8 r = d->data[i]; quint8 g = d->data[i+1]; quint8 b = d->data[i+2]; - e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); - e.color.fromQColor(QColor(r, g, b)); + e.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8())); add(e); } return true; } bool KoColorSet::loadPsp() { QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; qint32 r, g, b; QString s = QString::fromUtf8(d->data.data(), d->data.count()); QStringList l = s.split('\n', QString::SkipEmptyParts); if (l.size() < 4) return false; if (l[0] != "JASC-PAL") return false; if (l[1] != "0100") return false; int entries = l[2].toInt(); for (int i = 0; i < entries; ++i) { QStringList a = l[i + 3].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() != 3) { continue; } r = a[0].toInt(); a.pop_front(); g = a[0].toInt(); a.pop_front(); b = a[0].toInt(); a.pop_front(); r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); - e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); - e.color.fromQColor(QColor(r, g, b)); + e.setColor(KoColor(QColor(r, g, b), + KoColorSpaceRegistry::instance()->rgb8())); QString name = a.join(" "); - e.name = name.isEmpty() ? i18n("Untitled") : name; + e.setName(name.isEmpty() ? i18n("Untitled") : name); add(e); } return true; } void scribusParseColor(KoColorSet *set, QXmlStreamReader *xml) { - KoColorSetEntry currentColor; - //It's a color, retrieve it + KoColorSetEntry colorEntry; + // It's a color, retrieve it QXmlStreamAttributes colorProperties = xml->attributes(); - QStringRef colorValue; + + QStringRef colorName = colorProperties.value("NAME"); + colorEntry.setName(colorName.isEmpty() || colorName.isNull() ? i18n("Untitled") : colorName.toString()); // RGB or CMYK? if (colorProperties.hasAttribute("RGB")) { dbgPigment << "Color " << colorProperties.value("NAME") << ", RGB " << colorProperties.value("RGB"); - QStringRef colorName = colorProperties.value("NAME"); - currentColor.name = colorName.isEmpty() || colorName.isNull() ? i18n("Untitled") : colorName.toString(); - - currentColor.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); + KoColor currentColor(KoColorSpaceRegistry::instance()->rgb8()); + QStringRef colorValue = colorProperties.value("RGB"); - colorValue = colorProperties.value("RGB"); if (colorValue.length() != 7 && colorValue.at(0) != '#') { // Color is a hexadecimal number xml->raiseError("Invalid rgb8 color (malformed): " + colorValue); return; - } - else { + } else { bool rgbOk; quint32 rgb = colorValue.mid(1).toUInt(&rgbOk, 16); if (!rgbOk) { xml->raiseError("Invalid rgb8 color (unable to convert): " + colorValue); return; } quint8 r = rgb >> 16 & 0xff; quint8 g = rgb >> 8 & 0xff; quint8 b = rgb & 0xff; dbgPigment << "Color parsed: "<< r << g << b; - currentColor.color.data()[0] = r; - currentColor.color.data()[1] = g; - currentColor.color.data()[2] = b; - currentColor.color.setOpacity(OPACITY_OPAQUE_U8); + currentColor.data()[0] = r; + currentColor.data()[1] = g; + currentColor.data()[2] = b; + currentColor.setOpacity(OPACITY_OPAQUE_U8); + colorEntry.setColor(currentColor); - set->add(currentColor); + set->add(colorEntry); while(xml->readNextStartElement()) { //ignore - these are all unknown or the /> element tag xml->skipCurrentElement(); } return; } } else if (colorProperties.hasAttribute("CMYK")) { dbgPigment << "Color " << colorProperties.value("NAME") << ", CMYK " << colorProperties.value("CMYK"); - QStringRef colorName = colorProperties.value("NAME"); - currentColor.name = colorName.isEmpty() || colorName.isNull() ? i18n("Untitled") : colorName.toString(); - - currentColor.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer8BitsColorDepthID.id(), QString())); + KoColor currentColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer8BitsColorDepthID.id(), QString())); - colorValue = colorProperties.value("CMYK"); + QStringRef colorValue = colorProperties.value("CMYK"); if (colorValue.length() != 9 && colorValue.at(0) != '#') { // Color is a hexadecimal number xml->raiseError("Invalid cmyk color (malformed): " % colorValue); return; } else { bool cmykOk; quint32 cmyk = colorValue.mid(1).toUInt(&cmykOk, 16); // cmyk uses the full 32 bits if (!cmykOk) { xml->raiseError("Invalid cmyk color (unable to convert): " % colorValue); return; } quint8 c = cmyk >> 24 & 0xff; quint8 m = cmyk >> 16 & 0xff; quint8 y = cmyk >> 8 & 0xff; quint8 k = cmyk & 0xff; dbgPigment << "Color parsed: "<< c << m << y << k; - currentColor.color.data()[0] = c; - currentColor.color.data()[1] = m; - currentColor.color.data()[2] = y; - currentColor.color.data()[3] = k; - currentColor.color.setOpacity(OPACITY_OPAQUE_U8); + currentColor.data()[0] = c; + currentColor.data()[1] = m; + currentColor.data()[2] = y; + currentColor.data()[3] = k; + currentColor.setOpacity(OPACITY_OPAQUE_U8); + colorEntry.setColor(currentColor); - set->add(currentColor); + set->add(colorEntry); while(xml->readNextStartElement()) { //ignore - these are all unknown or the /> element tag xml->skipCurrentElement(); } return; } } else { - xml->raiseError("Unknown color space for color " + currentColor.name); + xml->raiseError("Unknown color space for color " + colorEntry.name()); } } bool loadScribusXmlPalette(KoColorSet *set, QXmlStreamReader *xml) { //1. Get name QXmlStreamAttributes paletteProperties = xml->attributes(); QStringRef paletteName = paletteProperties.value("Name"); dbgPigment << "Processed name of palette:" << paletteName; set->setName(paletteName.toString()); //2. Inside the SCRIBUSCOLORS, there are lots of colors. Retrieve them while(xml->readNextStartElement()) { QStringRef currentElement = xml->name(); if(QStringRef::compare(currentElement, "COLOR", Qt::CaseInsensitive) == 0) { scribusParseColor(set, xml); } else { xml->skipCurrentElement(); } } if(xml->hasError()) { return false; } return true; } bool KoColorSet::loadXml() { bool res = false; QXmlStreamReader *xml = new QXmlStreamReader(d->data); if (xml->readNextStartElement()) { QStringRef paletteId = xml->name(); if (QStringRef::compare(paletteId, "SCRIBUSCOLORS", Qt::CaseInsensitive) == 0) { // Scribus dbgPigment << "XML palette: " << filename() << ", Scribus format"; res = loadScribusXmlPalette(this, xml); } else { // Unknown XML format xml->raiseError("Unknown XML palette format. Expected SCRIBUSCOLORS, found " + paletteId); } } // If there is any error (it should be returned through the stream) if (xml->hasError() || !res) { warnPigment << "Illegal XML palette:" << filename(); warnPigment << "Error (line"<< xml->lineNumber() << ", column" << xml->columnNumber() << "):" << xml->errorString(); return false; } else { dbgPigment << "XML palette parsed successfully:" << filename(); return true; } } bool KoColorSet::saveKpl(QIODevice *dev) const { QScopedPointer store(KoStore::createStore(dev, KoStore::Write, "application/x-krita-palette", KoStore::Zip)); if (!store || store->bad()) return false; QSet profiles; QMap profileMap; { QDomDocument doc; QDomElement root = doc.createElement("Colorset"); root.setAttribute("version", "1.0"); root.setAttribute("name", name()); root.setAttribute("comment", d->comment); root.setAttribute("columns", d->columns); Q_FOREACH(const KoColorSetEntry &entry, d->colors) { // Only save non-builtin profiles.= - const KoColorProfile *profile = entry.color.colorSpace()->profile(); + const KoColorProfile *profile = entry.color().colorSpace()->profile(); if (!profile->fileName().isEmpty()) { profiles << profile; - profileMap[profile] = entry.color.colorSpace(); + profileMap[profile] = entry.color().colorSpace(); } QDomElement el = doc.createElement("ColorSetEntry"); - el.setAttribute("name", entry.name); - el.setAttribute("id", entry.id); - el.setAttribute("spot", entry.spotColor ? "true" : "false"); - el.setAttribute("bitdepth", entry.color.colorSpace()->colorDepthId().id()); - entry.color.toXML(doc, el); + el.setAttribute("name", entry.name()); + el.setAttribute("id", entry.id()); + el.setAttribute("spot", entry.spotColor() ? "true" : "false"); + el.setAttribute("bitdepth", entry.color().colorSpace()->colorDepthId().id()); + entry.color().toXML(doc, el); root.appendChild(el); } Q_FOREACH(const QString &groupName, d->groupNames) { QDomElement gl = doc.createElement("Group"); gl.setAttribute("name", groupName); root.appendChild(gl); Q_FOREACH(const KoColorSetEntry &entry, d->groups.value(groupName)) { // Only save non-builtin profiles.= - const KoColorProfile *profile = entry.color.colorSpace()->profile(); + const KoColorProfile *profile = entry.color().colorSpace()->profile(); if (!profile->fileName().isEmpty()) { profiles << profile; - profileMap[profile] = entry.color.colorSpace(); + profileMap[profile] = entry.color().colorSpace(); } QDomElement el = doc.createElement("ColorSetEntry"); - el.setAttribute("name", entry.name); - el.setAttribute("id", entry.id); - el.setAttribute("spot", entry.spotColor ? "true" : "false"); - el.setAttribute("bitdepth", entry.color.colorSpace()->colorDepthId().id()); - entry.color.toXML(doc, el); + el.setAttribute("name", entry.name()); + el.setAttribute("id", entry.id()); + el.setAttribute("spot", entry.spotColor() ? "true" : "false"); + el.setAttribute("bitdepth", entry.color().colorSpace()->colorDepthId().id()); + entry.color().toXML(doc, el); gl.appendChild(el); } } doc.appendChild(root); if (!store->open("colorset.xml")) { return false; } QByteArray ba = doc.toByteArray(); if (store->write(ba) != ba.size()) { return false; } if (!store->close()) { return false; } } QDomDocument doc; QDomElement profileElement = doc.createElement("Profiles"); Q_FOREACH(const KoColorProfile *profile, profiles) { QString fn = QFileInfo(profile->fileName()).fileName(); if (!store->open(fn)) { return false; } QByteArray profileRawData = profile->rawData(); if (!store->write(profileRawData)) { return false; } if (!store->close()) { return false; } QDomElement el = doc.createElement("Profile"); el.setAttribute("filename", fn); el.setAttribute("name", profile->name()); el.setAttribute("colorModelId", profileMap[profile]->colorModelId().id()); el.setAttribute("colorDepthId", profileMap[profile]->colorDepthId().id()); profileElement.appendChild(el); } doc.appendChild(profileElement); if (!store->open("profiles.xml")) { return false; } QByteArray ba = doc.toByteArray(); if (store->write(ba) != ba.size()) { return false; } if (!store->close()) { return false; } return store->finalize(); } bool KoColorSet::loadKpl() { QBuffer buf(&d->data); buf.open(QBuffer::ReadOnly); QScopedPointer store(KoStore::createStore(&buf, KoStore::Read, "application/x-krita-palette", KoStore::Zip)); if (!store || store->bad()) return false; if (store->hasFile("profiles.xml")) { if (!store->open("profiles.xml")) { return false; } QByteArray data; data.resize(store->size()); QByteArray ba = store->read(store->size()); store->close(); QDomDocument doc; doc.setContent(ba); QDomElement e = doc.documentElement(); QDomElement c = e.firstChildElement("Profiles"); while (!c.isNull()) { QString name = c.attribute("name"); QString filename = c.attribute("filename"); QString colorModelId = c.attribute("colorModelId"); QString colorDepthId = c.attribute("colorDepthId"); if (!KoColorSpaceRegistry::instance()->profileByName(name)) { store->open(filename); QByteArray data; data.resize(store->size()); data = store->read(store->size()); store->close(); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(colorModelId, colorDepthId, data); if (profile && profile->valid()) { KoColorSpaceRegistry::instance()->addProfile(profile); } } c = c.nextSiblingElement(); } } { if (!store->open("colorset.xml")) { return false; } QByteArray data; data.resize(store->size()); QByteArray ba = store->read(store->size()); store->close(); QDomDocument doc; doc.setContent(ba); QDomElement e = doc.documentElement(); setName(e.attribute("name")); d->comment = e.attribute("comment"); d->columns = e.attribute("columns").toInt(); QDomElement c = e.firstChildElement("ColorSetEntry"); while (!c.isNull()) { QString colorDepthId = c.attribute("bitdepth", Integer8BitsColorDepthID.id()); KoColorSetEntry entry; - entry.color = KoColor::fromXML(c.firstChildElement(), colorDepthId); - entry.name = c.attribute("name"); - entry.id = c.attribute("id"); - entry.spotColor = c.attribute("spot", "false") == "true" ? true : false; + entry.setColor(KoColor::fromXML(c.firstChildElement(), colorDepthId)); + entry.setName(c.attribute("name")); + entry.setId(c.attribute("id")); + entry.setSpotColor(c.attribute("spot", "false") == "true" ? true : false); d->colors << entry; c = c.nextSiblingElement("ColorSetEntry"); } QDomElement g = e.firstChildElement("Group"); while (!g.isNull()) { QString groupName = g.attribute("name"); addGroup(groupName); QDomElement cg = g.firstChildElement("ColorSetEntry"); while (!cg.isNull()) { QString colorDepthId = cg.attribute("bitdepth", Integer8BitsColorDepthID.id()); KoColorSetEntry entry; - entry.color = KoColor::fromXML(cg.firstChildElement(), colorDepthId); - entry.name = cg.attribute("name"); - entry.id = cg.attribute("id"); - entry.spotColor = cg.attribute("spot", "false") == "true" ? true : false; + entry.setColor(KoColor::fromXML(cg.firstChildElement(), colorDepthId)); + entry.setName(cg.attribute("name")); + entry.setId(cg.attribute("id")); + entry.setSpotColor(cg.attribute("spot", "false") == "true" ? true : false); add(entry, groupName); cg = cg.nextSiblingElement("ColorSetEntry"); } g = g.nextSiblingElement("Group"); } } buf.close(); return true; } quint16 readShort(QIODevice *io) { quint16 val; quint64 read = io->read((char*)&val, 2); if (read != 2) return false; return qFromBigEndian(val); } bool KoColorSet::loadAco() { QFileInfo info(filename()); setName(info.baseName()); QBuffer buf(&d->data); buf.open(QBuffer::ReadOnly); quint16 version = readShort(&buf); quint16 numColors = readShort(&buf); KoColorSetEntry e; if (version == 1 && buf.size() > 4+numColors*10) { buf.seek(4+numColors*10); version = readShort(&buf); numColors = readShort(&buf); } const quint16 quint16_MAX = 65535; for (int i = 0; i < numColors && !buf.atEnd(); ++i) { quint16 colorSpace = readShort(&buf); quint16 ch1 = readShort(&buf); quint16 ch2 = readShort(&buf); quint16 ch3 = readShort(&buf); quint16 ch4 = readShort(&buf); bool skip = false; if (colorSpace == 0) { // RGB const KoColorProfile *srgb = KoColorSpaceRegistry::instance()->rgb8()->profile(); - e.color = KoColor(KoColorSpaceRegistry::instance()->rgb16(srgb)); - reinterpret_cast(e.color.data())[0] = ch3; - reinterpret_cast(e.color.data())[1] = ch2; - reinterpret_cast(e.color.data())[2] = ch1; - e.color.setOpacity(OPACITY_OPAQUE_U8); + KoColor c(KoColorSpaceRegistry::instance()->rgb16(srgb)); + reinterpret_cast(c.data())[0] = ch3; + reinterpret_cast(c.data())[1] = ch2; + reinterpret_cast(c.data())[2] = ch1; + c.setOpacity(OPACITY_OPAQUE_U8); + e.setColor(c); } else if (colorSpace == 1) { // HSB - e.color = KoColor(KoColorSpaceRegistry::instance()->rgb16()); - QColor c; - c.setHsvF(ch1 / 65536.0, ch2 / 65536.0, ch3 / 65536.0); - e.color.fromQColor(c); - e.color.setOpacity(OPACITY_OPAQUE_U8); + QColor qc; + qc.setHsvF(ch1 / 65536.0, ch2 / 65536.0, ch3 / 65536.0); + KoColor c(qc, KoColorSpaceRegistry::instance()->rgb16()); + c.setOpacity(OPACITY_OPAQUE_U8); + e.setColor(c); } else if (colorSpace == 2) { // CMYK - e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer16BitsColorDepthID.id(), QString())); - reinterpret_cast(e.color.data())[0] = quint16_MAX - ch1; - reinterpret_cast(e.color.data())[1] = quint16_MAX - ch2; - reinterpret_cast(e.color.data())[2] = quint16_MAX - ch3; - reinterpret_cast(e.color.data())[3] = quint16_MAX - ch4; - e.color.setOpacity(OPACITY_OPAQUE_U8); + KoColor c(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer16BitsColorDepthID.id(), QString())); + reinterpret_cast(c.data())[0] = quint16_MAX - ch1; + reinterpret_cast(c.data())[1] = quint16_MAX - ch2; + reinterpret_cast(c.data())[2] = quint16_MAX - ch3; + reinterpret_cast(c.data())[3] = quint16_MAX - ch4; + c.setOpacity(OPACITY_OPAQUE_U8); + e.setColor(c); } else if (colorSpace == 7) { // LAB - e.color = KoColor(KoColorSpaceRegistry::instance()->lab16()); - reinterpret_cast(e.color.data())[0] = ch3; - reinterpret_cast(e.color.data())[1] = ch2; - reinterpret_cast(e.color.data())[2] = ch1; - e.color.setOpacity(OPACITY_OPAQUE_U8); + KoColor c = KoColor(KoColorSpaceRegistry::instance()->lab16()); + reinterpret_cast(c.data())[0] = ch3; + reinterpret_cast(c.data())[1] = ch2; + reinterpret_cast(c.data())[2] = ch1; + c.setOpacity(OPACITY_OPAQUE_U8); + e.setColor(c); } else if (colorSpace == 8) { // GRAY - e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer16BitsColorDepthID.id(), QString())); - reinterpret_cast(e.color.data())[0] = ch1 * (quint16_MAX / 10000); - e.color.setOpacity(OPACITY_OPAQUE_U8); + KoColor c(KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer16BitsColorDepthID.id(), QString())); + reinterpret_cast(c.data())[0] = ch1 * (quint16_MAX / 10000); + c.setOpacity(OPACITY_OPAQUE_U8); + e.setColor(c); } else { warnPigment << "Unsupported colorspace in palette" << filename() << "(" << colorSpace << ")"; skip = true; } if (version == 2) { quint16 v2 = readShort(&buf); //this isn't a version, it's a marker and needs to be skipped. Q_UNUSED(v2); quint16 size = readShort(&buf) -1; //then comes the length if (size>0) { QByteArray ba = buf.read(size*2); if (ba.size() == size*2) { QTextCodec *Utf16Codec = QTextCodec::codecForName("UTF-16BE"); - e.name = Utf16Codec->toUnicode(ba); + e.setName(Utf16Codec->toUnicode(ba)); } else { warnPigment << "Version 2 name block is the wrong size" << filename(); } } v2 = readShort(&buf); //end marker also needs to be skipped. Q_UNUSED(v2); } if (!skip) { add(e); } } return true; } bool KoColorSet::loadSbz() { QBuffer buf(&d->data); buf.open(QBuffer::ReadOnly); // &buf is a subclass of QIODevice QScopedPointer store(KoStore::createStore(&buf, KoStore::Read, "application/x-swatchbook", KoStore::Zip)); if (!store || store->bad()) return false; if (store->hasFile("swatchbook.xml")) { // Try opening... if (!store->open("swatchbook.xml")) { return false; } QByteArray data; data.resize(store->size()); QByteArray ba = store->read(store->size()); store->close(); dbgPigment << "XML palette: " << filename() << ", SwatchBooker format"; QDomDocument doc; int errorLine, errorColumn; QString errorMessage; bool status = doc.setContent(ba, &errorMessage, &errorLine, &errorColumn); if (!status) { warnPigment << "Illegal XML palette:" << filename(); warnPigment << "Error (line" << errorLine << ", column" << errorColumn << "):" << errorMessage; return false; } QDomElement e = doc.documentElement(); // SwatchBook // Start reading properties... QDomElement metadata = e.firstChildElement("metadata"); if (e.isNull()) { warnPigment << "Palette metadata not found"; return false; } QDomElement title = metadata.firstChildElement("dc:title"); QString colorName = title.text(); colorName = colorName.isEmpty() ? i18n("Untitled") : colorName; setName(colorName); dbgPigment << "Processed name of palette:" << name(); // End reading properties // Now read colors... QDomElement materials = e.firstChildElement("materials"); if (materials.isNull()) { warnPigment << "Materials (color definitions) not found"; return false; } // This one has lots of "color" elements QDomElement colorElement = materials.firstChildElement("color"); if (colorElement.isNull()) { warnPigment << "Color definitions not found (line" << materials.lineNumber() << ", column" << materials.columnNumber() << ")"; return false; } // Also read the swatch book... QDomElement book = e.firstChildElement("book"); if (book.isNull()) { warnPigment << "Palette book (swatch composition) not found (line" << e.lineNumber() << ", column" << e.columnNumber() << ")"; return false; } // Which has lots of "swatch"es (todo: support groups) QDomElement swatch = book.firstChildElement(); if (swatch.isNull()) { warnPigment << "Swatches/groups definition not found (line" << book.lineNumber() << ", column" << book.columnNumber() << ")"; return false; } // We'll store colors here, and as we process swatches // we'll add them to the palette QHash materialsBook; QHash fileColorSpaces; // Color processing for(; !colorElement.isNull(); colorElement = colorElement.nextSiblingElement("color")) { - KoColorSetEntry currentColor; + KoColorSetEntry currentEntry; // Set if color is spot - currentColor.spotColor = colorElement.attribute("usage") == "spot"; + currentEntry.setSpotColor(colorElement.attribute("usage") == "spot"); // inside contains id and name // one or more define the color QDomElement currentColorMetadata = colorElement.firstChildElement("metadata"); QDomNodeList currentColorValues = colorElement.elementsByTagName("values"); // Get color name QDomElement colorTitle = currentColorMetadata.firstChildElement("dc:title"); QDomElement colorId = currentColorMetadata.firstChildElement("dc:identifier"); // Is there an id? (we need that at the very least for identifying a color) if (colorId.text().isEmpty()) { warnPigment << "Unidentified color (line" << colorId.lineNumber()<< ", column" << colorId.columnNumber() << ")"; return false; } if (materialsBook.contains(colorId.text())) { warnPigment << "Duplicated color definition (line" << colorId.lineNumber()<< ", column" << colorId.columnNumber() << ")"; return false; } // Get a valid color name - currentColor.id = colorId.text(); - currentColor.name = colorTitle.text().isEmpty() ? colorId.text() : colorTitle.text(); + currentEntry.setId(colorId.text()); + currentEntry.setName(colorTitle.text().isEmpty() ? colorId.text() : colorTitle.text()); // Get a valid color definition if (currentColorValues.isEmpty()) { warnPigment << "Color definitions not found (line" << colorElement.lineNumber() << ", column" << colorElement.columnNumber() << ")"; return false; } bool firstDefinition = false; const KoColorProfile *srgb = KoColorSpaceRegistry::instance()->rgb8()->profile(); // Priority: Lab, otherwise the first definition found for(int j = 0; j < currentColorValues.size(); j++) { QDomNode colorValue = currentColorValues.at(j); QDomElement colorValueE = colorValue.toElement(); QString model = colorValueE.attribute("model", QString()); // sRGB,RGB,HSV,HSL,CMY,CMYK,nCLR: 0 -> 1 // YIQ: Y 0 -> 1 : IQ -0.5 -> 0.5 // Lab: L 0 -> 100 : ab -128 -> 127 // XYZ: 0 -> ~100 if (model == "Lab") { QStringList lab = colorValueE.text().split(" "); if (lab.length() != 3) { warnPigment << "Invalid Lab color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float l = lab.at(0).toFloat(&status); float a = lab.at(1).toFloat(&status); float b = lab.at(2).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } - currentColor.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(LABAColorModelID.id(), Float32BitsColorDepthID.id(), QString())); - reinterpret_cast(currentColor.color.data())[0] = l; - reinterpret_cast(currentColor.color.data())[1] = a; - reinterpret_cast(currentColor.color.data())[2] = b; - currentColor.color.setOpacity(OPACITY_OPAQUE_F); + KoColor c(KoColorSpaceRegistry::instance()->colorSpace(LABAColorModelID.id(), Float32BitsColorDepthID.id(), QString())); + reinterpret_cast(c.data())[0] = l; + reinterpret_cast(c.data())[1] = a; + reinterpret_cast(c.data())[2] = b; + c.setOpacity(OPACITY_OPAQUE_F); firstDefinition = true; + currentEntry.setColor(c); break; // Immediately add this one } else if (model == "sRGB" && !firstDefinition) { QStringList rgb = colorValueE.text().split(" "); if (rgb.length() != 3) { warnPigment << "Invalid sRGB color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float r = rgb.at(0).toFloat(&status); float g = rgb.at(1).toFloat(&status); float b = rgb.at(2).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } - currentColor.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), srgb)); - reinterpret_cast(currentColor.color.data())[0] = r; - reinterpret_cast(currentColor.color.data())[1] = g; - reinterpret_cast(currentColor.color.data())[2] = b; - currentColor.color.setOpacity(OPACITY_OPAQUE_F); + KoColor c(KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), srgb)); + reinterpret_cast(c.data())[0] = r; + reinterpret_cast(c.data())[1] = g; + reinterpret_cast(c.data())[2] = b; + c.setOpacity(OPACITY_OPAQUE_F); + currentEntry.setColor(c); firstDefinition = true; } else if (model == "XYZ" && !firstDefinition) { QStringList xyz = colorValueE.text().split(" "); if (xyz.length() != 3) { warnPigment << "Invalid XYZ color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float x = xyz.at(0).toFloat(&status); float y = xyz.at(1).toFloat(&status); float z = xyz.at(2).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } - currentColor.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(XYZAColorModelID.id(), Float32BitsColorDepthID.id(), QString())); - reinterpret_cast(currentColor.color.data())[0] = x; - reinterpret_cast(currentColor.color.data())[1] = y; - reinterpret_cast(currentColor.color.data())[2] = z; - currentColor.color.setOpacity(OPACITY_OPAQUE_F); + KoColor c(KoColorSpaceRegistry::instance()->colorSpace(XYZAColorModelID.id(), Float32BitsColorDepthID.id(), QString())); + reinterpret_cast(c.data())[0] = x; + reinterpret_cast(c.data())[1] = y; + reinterpret_cast(c.data())[2] = z; + c.setOpacity(OPACITY_OPAQUE_F); + currentEntry.setColor(c); firstDefinition = true; } // The following color spaces admit an ICC profile (in SwatchBooker) else if (model == "CMYK" && !firstDefinition) { QStringList cmyk = colorValueE.text().split(" "); if (cmyk.length() != 4) { warnPigment << "Invalid CMYK color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float c = cmyk.at(0).toFloat(&status); float m = cmyk.at(1).toFloat(&status); float y = cmyk.at(2).toFloat(&status); float k = cmyk.at(3).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } QString space = colorValueE.attribute("space"); const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), QString()); if (!space.isEmpty()) { // Try loading the profile and add it to the registry if (!fileColorSpaces.contains(space)) { store->enterDirectory("profiles"); store->open(space); QByteArray data; data.resize(store->size()); data = store->read(store->size()); store->close(); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), data); if (profile && profile->valid()) { KoColorSpaceRegistry::instance()->addProfile(profile); colorSpace = KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), profile); fileColorSpaces.insert(space, colorSpace); } } else { colorSpace = fileColorSpaces.value(space); } } - currentColor.color = KoColor(colorSpace); - reinterpret_cast(currentColor.color.data())[0] = c; - reinterpret_cast(currentColor.color.data())[1] = m; - reinterpret_cast(currentColor.color.data())[2] = y; - reinterpret_cast(currentColor.color.data())[3] = k; - currentColor.color.setOpacity(OPACITY_OPAQUE_F); + KoColor color(colorSpace); + reinterpret_cast(color.data())[0] = c; + reinterpret_cast(color.data())[1] = m; + reinterpret_cast(color.data())[2] = y; + reinterpret_cast(color.data())[3] = k; + color.setOpacity(OPACITY_OPAQUE_F); + currentEntry.setColor(color); firstDefinition = true; } else if (model == "GRAY" && !firstDefinition) { QString gray = colorValueE.text(); float g = gray.toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } QString space = colorValueE.attribute("space"); const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Float32BitsColorDepthID.id(), QString()); if (!space.isEmpty()) { // Try loading the profile and add it to the registry if (!fileColorSpaces.contains(space)) { store->enterDirectory("profiles"); store->open(space); QByteArray data; data.resize(store->size()); data = store->read(store->size()); store->close(); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), data); if (profile && profile->valid()) { KoColorSpaceRegistry::instance()->addProfile(profile); colorSpace = KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), profile); fileColorSpaces.insert(space, colorSpace); } } else { colorSpace = fileColorSpaces.value(space); } } - currentColor.color = KoColor(colorSpace); - reinterpret_cast(currentColor.color.data())[0] = g; - currentColor.color.setOpacity(OPACITY_OPAQUE_F); + KoColor c(colorSpace); + reinterpret_cast(c.data())[0] = g; + c.setOpacity(OPACITY_OPAQUE_F); + currentEntry.setColor(c); firstDefinition = true; } else if (model == "RGB" && !firstDefinition) { QStringList rgb = colorValueE.text().split(" "); if (rgb.length() != 3) { warnPigment << "Invalid RGB color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float r = rgb.at(0).toFloat(&status); float g = rgb.at(1).toFloat(&status); float b = rgb.at(2).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } QString space = colorValueE.attribute("space"); const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), srgb); if (!space.isEmpty()) { // Try loading the profile and add it to the registry if (!fileColorSpaces.contains(space)) { store->enterDirectory("profiles"); store->open(space); QByteArray data; data.resize(store->size()); data = store->read(store->size()); store->close(); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), data); if (profile && profile->valid()) { KoColorSpaceRegistry::instance()->addProfile(profile); colorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), profile); fileColorSpaces.insert(space, colorSpace); } } else { colorSpace = fileColorSpaces.value(space); } } - currentColor.color = KoColor(colorSpace); - reinterpret_cast(currentColor.color.data())[0] = r; - reinterpret_cast(currentColor.color.data())[1] = g; - reinterpret_cast(currentColor.color.data())[2] = b; - currentColor.color.setOpacity(OPACITY_OPAQUE_F); + KoColor c(colorSpace); + reinterpret_cast(c.data())[0] = r; + reinterpret_cast(c.data())[1] = g; + reinterpret_cast(c.data())[2] = b; + c.setOpacity(OPACITY_OPAQUE_F); + currentEntry.setColor(c); firstDefinition = true; } else { warnPigment << "Color space not implemented:" << model << "(line" << colorValueE.lineNumber() << ", column "<< colorValueE.columnNumber() << ")"; } } if (firstDefinition) { - materialsBook.insert(currentColor.id, currentColor); + materialsBook.insert(currentEntry.id(), currentEntry); } else { warnPigment << "No supported color spaces for the current color (line" << colorElement.lineNumber() << ", column "<< colorElement.columnNumber() << ")"; return false; } } // End colors // Now decide which ones will go into the palette for(;!swatch.isNull(); swatch = swatch.nextSiblingElement()) { QString type = swatch.tagName(); if (type.isEmpty() || type.isNull()) { warnPigment << "Invalid swatch/group definition (no id) (line" << swatch.lineNumber() << ", column" << swatch.columnNumber() << ")"; return false; } else if (type == "swatch") { QString id = swatch.attribute("material"); if (id.isEmpty() || id.isNull()) { warnPigment << "Invalid swatch definition (no material id) (line" << swatch.lineNumber() << ", column" << swatch.columnNumber() << ")"; return false; } if (materialsBook.contains(id)) { add(materialsBook.value(id)); } else { warnPigment << "Invalid swatch definition (material not found) (line" << swatch.lineNumber() << ", column" << swatch.columnNumber() << ")"; return false; } } else if (type == "group") { QDomElement groupMetadata = swatch.firstChildElement("metadata"); if (groupMetadata.isNull()) { warnPigment << "Invalid group definition (missing metadata) (line" << groupMetadata.lineNumber() << ", column" << groupMetadata.columnNumber() << ")"; return false; } QDomElement groupTitle = metadata.firstChildElement("dc:title"); if (groupTitle.isNull()) { warnPigment << "Invalid group definition (missing title) (line" << groupTitle.lineNumber() << ", column" << groupTitle.columnNumber() << ")"; return false; } QString currentGroupName = groupTitle.text(); QDomElement groupSwatch = swatch.firstChildElement("swatch"); while(!groupSwatch.isNull()) { QString id = groupSwatch.attribute("material"); if (id.isEmpty() || id.isNull()) { warnPigment << "Invalid swatch definition (no material id) (line" << groupSwatch.lineNumber() << ", column" << groupSwatch.columnNumber() << ")"; return false; } if (materialsBook.contains(id)) { add(materialsBook.value(id), currentGroupName); } else { warnPigment << "Invalid swatch definition (material not found) (line" << groupSwatch.lineNumber() << ", column" << groupSwatch.columnNumber() << ")"; return false; } groupSwatch = groupSwatch.nextSiblingElement("swatch"); } } } // End palette } buf.close(); return true; } diff --git a/libs/pigment/resources/KoColorSet.h b/libs/pigment/resources/KoColorSet.h index 36e66eb29b..e8ba024596 100644 --- a/libs/pigment/resources/KoColorSet.h +++ b/libs/pigment/resources/KoColorSet.h @@ -1,232 +1,219 @@ /* This file is part of the KDE project Copyright (c) 2005 Boudewijn Rempt Copyright (c) 2016 L. E. Segovia This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KOCOLORSET #define KOCOLORSET #include #include #include #include #include #include "KoColor.h" - -struct KoColorSetEntry { - KoColorSetEntry() {} - KoColorSetEntry(const KoColor &_color, const QString &_name) - : color(_color), name(_name) {} - - KoColor color; - QString name; - QString id; - bool spotColor {false}; - - bool operator==(const KoColorSetEntry& rhs) const { - return color == rhs.color && name == rhs.name; - } -}; +#include "KoColorSetEntry.h" /** * Open Gimp, Photoshop or RIFF palette files. This is a straight port * from the Gimp. */ class KRITAPIGMENT_EXPORT KoColorSet : public QObject, public KoResource { Q_OBJECT public: enum PaletteType { UNKNOWN = 0, GPL, // GIMP RIFF_PAL, // RIFF ACT, // Photoshop binary PSP_PAL, // PaintShop Pro ACO, // Photoshop Swatches XML, // XML palette (Scribus) KPL, // KoColor-based XML palette SBZ // SwatchBooker }; /** * Load a color set from a file. This can be a Gimp * palette, a RIFF palette, a Photoshop palette, + * a Krita palette, * a Scribus palette or a SwatchBooker palette. */ explicit KoColorSet(const QString &filename); /// Create an empty color set KoColorSet(); /// Explicit copy constructor (KoResource copy constructor is private) KoColorSet(const KoColorSet& rhs); ~KoColorSet() override; bool load() override; bool loadFromDevice(QIODevice *dev) override; bool save() override; bool saveToDevice(QIODevice* dev) const override; QString defaultFileExtension() const override; void setColumnCount(int columns); int columnCount(); /** * @brief comment * @return the comment. */ QString comment(); void setComment(QString comment); public: /** * @brief add Add a color to the palette. * @param groupName color to add the group to. If empty, it will be added to the unsorted. */ void add(const KoColorSetEntry &, QString groupName = QString()); /** * @brief insertBefore insert color before index into group. * @param index * @param groupName name of the group that the color goes into. * @return new index of index after the prepending. */ quint32 insertBefore(const KoColorSetEntry &, qint32 index, const QString &groupName = QString()); void removeAt(quint32 index, QString groupName = QString()); /** * @brief getColorGlobal * A function for getting a color based on a global index. Useful for itterating through all color entries. * @param globalIndex the global index over the whole palette. * @return the entry. */ KoColorSetEntry getColorGlobal(quint32 globalIndex); /** * @brief getColorGroup * A function for getting the color from a specific group. * @param groupName the name of the group, will give unosrted when not defined. * @param index the index within the group. * @return the entry */ KoColorSetEntry getColorGroup(quint32 index, QString groupName = QString()); QString findGroupByGlobalIndex(quint32 globalIndex, quint32 *index); QString findGroupByColorName(const QString &name, quint32 *index); QString findGroupByID(const QString &id,quint32 *index); /** * @brief getGroupNames * @return returns a list of group names, excluding the unsorted group. */ QStringList getGroupNames(); bool changeGroupName(QString oldGroupName, QString newGroupName); bool changeColorSetEntry(KoColorSetEntry entry, QString groupName, quint32 index); /** * @brief nColorsGroup * @param groupName string name of the group, when not specified, returns unsorted colors. * @return the amount of colors in this group. */ quint32 nColorsGroup(QString groupName = QString()); /** * @brief nColors * @return total colors in palette. */ quint32 nColors(); /** * @brief addGroup * Adds a new group. * @param groupName the name of the new group. When not specified, this will fail. * @return whether thegroup was made. */ bool addGroup(const QString &groupName); /** * @brief moveGroup * Move a group in the internal stringlist. * @param groupName the groupname to move. * @param groupNameInsertBefore the groupname to insert before. Empty means it will be added to the end. * @return */ bool moveGroup(const QString &groupName, const QString &groupNameInsertBefore = QString()); /** * @brief removeGroup * Remove a group from the KoColorSet * @param groupName the name of the group you want to remove. * @param keepColors Whether you wish to keep the colorsetentries. These will be added to the unsorted. * @return whether it could find the group to remove. */ bool removeGroup(const QString &groupName, bool keepColors = true); void clear(); /** * @brief getIndexClosestColor * function that matches the color to all colors in the colorset, and returns the index * of the closest match. * @param color the color you wish to compare. * @param useGivenColorSpace whether to use the color space of the color given * when the two colors' colorspaces don't match. Else it'll use the entry's colorspace. * @return returns the int of the closest match. */ quint32 getIndexClosestColor(KoColor color, bool useGivenColorSpace = true); /** * @brief closestColorName * convenience function to get the name of the closest match. * @param color * @param useGivenColorSpace * @return */ QString closestColorName(KoColor color, bool useGivenColorSpace = true); private: bool init(); bool saveGpl(QIODevice *dev) const; bool loadGpl(); bool loadAct(); bool loadRiff(); bool loadPsp(); bool loadAco(); bool loadXml(); bool loadSbz(); bool saveKpl(QIODevice *dev) const; bool loadKpl(); struct Private; const QScopedPointer d; }; #endif // KOCOLORSET diff --git a/libs/pigment/resources/KoColorSetEntry.cpp b/libs/pigment/resources/KoColorSetEntry.cpp new file mode 100644 index 0000000000..4610540ead --- /dev/null +++ b/libs/pigment/resources/KoColorSetEntry.cpp @@ -0,0 +1,12 @@ +#include "KoColorSetEntry.h" + +KoColorSetEntry::KoColorSetEntry() + : m_spotColor(false) +{ } + +KoColorSetEntry::KoColorSetEntry(const KoColor &color, const QString &name) + : m_color(color) + , m_name(name) + , m_spotColor(false) +{ } + diff --git a/libs/pigment/resources/KoColorSetEntry.h b/libs/pigment/resources/KoColorSetEntry.h new file mode 100644 index 0000000000..9b2c775152 --- /dev/null +++ b/libs/pigment/resources/KoColorSetEntry.h @@ -0,0 +1,36 @@ +#ifndef KOCOLORSETENTRY_H +#define KOCOLORSETENTRY_H + +#include "kritapigment_export.h" +#include +#include "KoColor.h" + +class KRITAPIGMENT_EXPORT KoColorSetEntry +{ +public: + KoColorSetEntry(); + KoColorSetEntry(const KoColor &color, const QString &name); + +public: + QString name() const { return m_name; } + void setName(const QString &name) { m_name = name; } + QString id() const { return m_id; } + void setId(const QString &id) { m_id = id; } + KoColor color() const { return m_color; } + void setColor(const KoColor &color) { m_color = color; } + bool spotColor() const { return m_spotColor; } + void setSpotColor(bool spotColor) { m_spotColor = spotColor; } + +public: + bool operator==(const KoColorSetEntry& rhs) const { + return m_color == rhs.m_color && m_name == rhs.m_name; + } + +private: + KoColor m_color; + QString m_name; + QString m_id; + bool m_spotColor; +}; + +#endif // KOCOLORSETENTRY_H diff --git a/libs/ui/KisColorsetChooser.cpp b/libs/ui/KisColorsetChooser.cpp index a48d199b3c..6a3c9e396d 100644 --- a/libs/ui/KisColorsetChooser.cpp +++ b/libs/ui/KisColorsetChooser.cpp @@ -1,166 +1,166 @@ /* This file is part of the KDE project * Copyright (C) 2013 Sven Langkamp * * 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 "KisColorsetChooser.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "KisResourceServerProvider.h" #include "KisViewManager.h" #include #include #include #include #include #include #include "kis_int_parse_spin_box.h" class ColorSetDelegate : public QAbstractItemDelegate { public: ColorSetDelegate(QObject * parent = 0) : QAbstractItemDelegate(parent) {} ~ColorSetDelegate() override {} /// reimplemented void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override; /// reimplemented QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex &) const override { return option.decorationSize; } }; void ColorSetDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { painter->save(); if (! index.isValid()) return; KoResource* resource = static_cast(index.internalPointer()); KoColorSet* colorSet = static_cast(resource); if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, option.palette.highlight()); painter->setPen(option.palette.highlightedText().color()); } else { painter->setBrush(option.palette.text().color()); } painter->drawText(option.rect.x() + 5, option.rect.y() + painter->fontMetrics().ascent() + 5, colorSet->name()); int size = 7; for (quint32 i = 0; i < colorSet->nColors() && i*size < (quint32)option.rect.width(); i++) { QRect rect(option.rect.x() + i*size, option.rect.y() + option.rect.height() - size, size, size); - painter->fillRect(rect, colorSet->getColorGlobal(i).color.toQColor()); + painter->fillRect(rect, colorSet->getColorGlobal(i).color().toQColor()); } painter->restore(); } KisColorsetChooser::KisColorsetChooser(QWidget* parent): QWidget(parent) { KoResourceServer * rserver = KoResourceServerProvider::instance()->paletteServer(); QSharedPointer adapter(new KoResourceServerAdapter(rserver)); m_itemChooser = new KoResourceItemChooser(adapter, this); m_itemChooser->setItemDelegate(new ColorSetDelegate(this)); m_itemChooser->showTaggingBar(true); m_itemChooser->setFixedSize(250, 250); m_itemChooser->setRowHeight(30); m_itemChooser->setColumnCount(1); connect(m_itemChooser, SIGNAL(resourceSelected(KoResource*)), this, SLOT(resourceSelected(KoResource*))); KisConfig cfg; m_itemChooser->configureKineticScrolling(cfg.kineticScrollingGesture(), cfg.kineticScrollingSensitivity(), cfg.kineticScrollingScrollbar()); QPushButton* saveButton = new QPushButton(i18n("Save")); connect(saveButton, SIGNAL(clicked(bool)), this, SLOT(slotSave())); m_nameEdit = new QLineEdit(this); m_nameEdit->setPlaceholderText(i18n("Insert name")); m_nameEdit->setClearButtonEnabled(true); m_columnEdit = new KisIntParseSpinBox(this); m_columnEdit->setRange(1, 30); m_columnEdit->setValue(10); QGridLayout* layout = new QGridLayout(this); layout->addWidget(m_itemChooser, 0, 0, 1, 3); - layout->addWidget(new QLabel(i18n("Name:"), this), 1, 0, 1, 1); + layout->setColumnStretch(1, 1); + layout->addWidget(saveButton, 2, 2, 1, 1); layout->addWidget(m_nameEdit, 1, 1, 1, 2); - layout->addWidget(new QLabel(i18n("Columns:"), this), 2, 0, 1, 1); + layout->addWidget(new QLabel(i18n("Name:"), this), 1, 0, 1, 1); layout->addWidget(m_columnEdit, 2, 1, 1, 1); - layout->addWidget(saveButton, 2, 2, 1, 1); - layout->setColumnStretch(1, 1); + layout->addWidget(new QLabel(i18n("Columns:"), this), 2, 0, 1, 1); } KisColorsetChooser::~KisColorsetChooser() { } void KisColorsetChooser::resourceSelected(KoResource* resource) { emit paletteSelected(static_cast(resource)); } void KisColorsetChooser::slotSave() { KoResourceServer * rserver = KoResourceServerProvider::instance()->paletteServer(); KoColorSet* colorset = new KoColorSet(); colorset->setValid(true); QString saveLocation = rserver->saveLocation(); QString name = m_nameEdit->text(); int columns = m_columnEdit->value(); bool newName = false; if(name.isEmpty()) { newName = true; name = i18n("Palette"); } QFileInfo fileInfo(saveLocation + name + colorset->defaultFileExtension()); int i = 1; while (fileInfo.exists()) { fileInfo.setFile(saveLocation + name + QString("%1").arg(i) + colorset->defaultFileExtension()); i++; } colorset->setFilename(fileInfo.filePath()); if(newName) { name = i18n("Palette %1", i); } colorset->setName(name); colorset->setColumnCount(columns); rserver->addResource(colorset); } diff --git a/libs/ui/KisPaletteModel.cpp b/libs/ui/KisPaletteModel.cpp index 8c16b0d757..f801701940 100644 --- a/libs/ui/KisPaletteModel.cpp +++ b/libs/ui/KisPaletteModel.cpp @@ -1,639 +1,644 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisPaletteModel.h" #include #include #include #include #include #include #include #include #include #include KisPaletteModel::KisPaletteModel(QObject* parent) : QAbstractTableModel(parent), m_colorSet(0), m_displayRenderer(KoDumbColorDisplayRenderer::instance()) { } KisPaletteModel::~KisPaletteModel() { } void KisPaletteModel::setDisplayRenderer(KoColorDisplayRendererInterface *displayRenderer) { if (displayRenderer) { if (m_displayRenderer) { disconnect(m_displayRenderer, 0, this, 0); } m_displayRenderer = displayRenderer; connect(m_displayRenderer, SIGNAL(displayConfigurationChanged()), SLOT(slotDisplayConfigurationChanged())); } else { m_displayRenderer = KoDumbColorDisplayRenderer::instance(); } } void KisPaletteModel::slotDisplayConfigurationChanged() { beginResetModel(); endResetModel(); } QModelIndex KisPaletteModel::getLastEntryIndex() { int endRow = rowCount(); int endColumn = columnCount(); if (m_colorSet->nColors()>0) { QModelIndex i = this->index(endRow, endColumn, QModelIndex()); while (qvariant_cast(i.data(RetrieveEntryRole)).isEmpty()) { i = this->index(endRow, endColumn); endColumn -=1; if (endColumn<0) { endColumn = columnCount(); endRow-=1; } } return i; } return QModelIndex(); } QVariant KisPaletteModel::data(const QModelIndex& index, int role) const { KoColorSetEntry entry; if (m_colorSet && m_displayRenderer) { //now to figure out whether we have a groupname row or not. bool groupNameRow = false; quint32 indexInGroup = 0; QString indexGroupName = QString(); int rowstotal = m_colorSet->nColorsGroup()/columnCount(); if (index.row()<=rowstotal && (quint32)(index.row()*columnCount()+index.column())nColorsGroup()) { indexInGroup = (quint32)(index.row()*columnCount()+index.column()); } if (m_colorSet->nColorsGroup()==0) { rowstotal+=1; //always add one for the default group when considering groups. } Q_FOREACH (QString groupName, m_colorSet->getGroupNames()){ //we make an int for the rows added by the current group. int newrows = 1+m_colorSet->nColorsGroup(groupName)/columnCount(); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { newrows+=1; } if (newrows==0) { newrows+=1; //always add one for the group when considering groups. } quint32 tempIndex = (quint32)((index.row()-(rowstotal+2))*columnCount()+index.column()); if (index.row() == rowstotal+1) { //rowstotal+1 is taken up by the groupname. indexGroupName = groupName; groupNameRow = true; } else if (index.row() > (rowstotal+1) && index.row() <= rowstotal+newrows && tempIndexnColorsGroup(groupName)){ //otherwise it's an index to the colors in the group. indexGroupName = groupName; indexInGroup = tempIndex; } //add the new rows to the totalrows we've looked at. rowstotal += newrows; } if (groupNameRow) { switch (role) { case Qt::ToolTipRole: case Qt::DisplayRole: { return indexGroupName; } case IsHeaderRole: { return true; } case RetrieveEntryRole: { QStringList entryList; entryList.append(indexGroupName); entryList.append(QString::number(0)); return entryList; } } } else { if (indexInGroup < m_colorSet->nColorsGroup(indexGroupName)) { entry = m_colorSet->getColorGroup(indexInGroup, indexGroupName); switch (role) { case Qt::ToolTipRole: case Qt::DisplayRole: { - return entry.name; + return entry.name(); } case Qt::BackgroundRole: { - QColor color = m_displayRenderer->toQColor(entry.color); + QColor color = m_displayRenderer->toQColor(entry.color()); return QBrush(color); } case IsHeaderRole: { return false; } case RetrieveEntryRole: { QStringList entryList; entryList.append(indexGroupName); entryList.append(QString::number(indexInGroup)); return entryList; } } } } } return QVariant(); } int KisPaletteModel::rowCount(const QModelIndex& /*parent*/) const { if (!m_colorSet) { return 0; } if (m_colorSet->nColors()==0) { return 0; } if (columnCount() > 0) { int countedrows = m_colorSet->nColorsGroup("")/columnCount(); if (m_colorSet->nColorsGroup()%columnCount() > 0) { countedrows+=1; } if (m_colorSet->nColorsGroup()==0) { countedrows+=1; } Q_FOREACH (QString groupName, m_colorSet->getGroupNames()) { countedrows += 1; //add one for the name; countedrows += 1+(m_colorSet->nColorsGroup(groupName)/ columnCount()); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { countedrows+=1; } if (m_colorSet->nColorsGroup(groupName)==0) { countedrows+=1; } } countedrows +=1; //Our code up till now doesn't take 0 into account. return countedrows; } return m_colorSet->nColors()/15 + 1; } int KisPaletteModel::columnCount(const QModelIndex& /*parent*/) const { if (m_colorSet && m_colorSet->columnCount() > 0) { return m_colorSet->columnCount(); } return 15; } Qt::ItemFlags KisPaletteModel::flags(const QModelIndex& index) const { if (index.isValid()) { return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } return Qt::ItemIsDropEnabled; } QModelIndex KisPaletteModel::index(int row, int column, const QModelIndex& parent) const { if (m_colorSet) { //make an int to hold the amount of rows we've looked at. The initial is the total rows in the default group. int rowstotal = m_colorSet->nColorsGroup()/columnCount(); if (row<=rowstotal && (quint32)(row*columnCount()+column)nColorsGroup()) { //if the total rows are in the default group, we just return an index. return QAbstractTableModel::index(row, column, parent); } else if(row<0 && column<0) { return QAbstractTableModel::index(0, 0, parent); } if (m_colorSet->nColorsGroup()==0) { rowstotal+=1; //always add one for the default group when considering groups. } Q_FOREACH (QString groupName, m_colorSet->getGroupNames()){ //we make an int for the rows added by the current group. int newrows = 1+m_colorSet->nColorsGroup(groupName)/columnCount(); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { newrows+=1; } if (m_colorSet->nColorsGroup(groupName)==0) { newrows+=1; //always add one for the group when considering groups. } if (rowstotal + newrows>rowCount()) { newrows = rowCount() - rowstotal; } quint32 tempIndex = (quint32)((row-(rowstotal+2))*columnCount()+column); if (row == rowstotal+1) { //rowstotal+1 is taken up by the groupname. return QAbstractTableModel::index(row, 0, parent); } else if (row > (rowstotal+1) && row <= rowstotal+newrows && tempIndexnColorsGroup(groupName)){ //otherwise it's an index to the colors in the group. return QAbstractTableModel::index(row, column, parent); } //add the new rows to the totalrows we've looked at. rowstotal += newrows; } } return QModelIndex(); } void KisPaletteModel::setColorSet(KoColorSet* colorSet) { m_colorSet = colorSet; beginResetModel(); endResetModel(); } KoColorSet* KisPaletteModel::colorSet() const { return m_colorSet; } QModelIndex KisPaletteModel::indexFromId(int i) const { QModelIndex index = QModelIndex(); if (!colorSet() || colorSet()->nColors() == 0) { return index; } if (i > (int)colorSet()->nColors()) { qWarning()<<"index is too big"<nColors(); index = this->index(0,0); } if (i < (int)colorSet()->nColorsGroup(0)) { index = QAbstractTableModel::index(i/columnCount(), i % columnCount()); if (!index.isValid()) { index = QAbstractTableModel::index(0, 0, QModelIndex()); } return index; } else { int rowstotal = 1 + m_colorSet->nColorsGroup() / columnCount(); if (m_colorSet->nColorsGroup() == 0) { rowstotal += 1; } int totalIndexes = colorSet()->nColorsGroup(); Q_FOREACH (QString groupName, m_colorSet->getGroupNames()){ if (i + 1 <= (int)(totalIndexes + colorSet()->nColorsGroup(groupName)) && i + 1 > (int)totalIndexes) { int col = (i - totalIndexes) % columnCount(); int row = rowstotal + 1 + ((i - totalIndexes) / columnCount()); index = this->index(row, col); return index; } else { rowstotal += 1 + m_colorSet->nColorsGroup(groupName) / columnCount(); totalIndexes += colorSet()->nColorsGroup(groupName); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { rowstotal += 1; } if (m_colorSet->nColorsGroup(groupName)==0) { rowstotal += 1; //always add one for the group when considering groups. } } } } return index; } int KisPaletteModel::idFromIndex(const QModelIndex &index) const { if (index.isValid()==false) { return -1; qWarning()<<"invalid index"; } int i=0; QStringList entryList = qvariant_cast(data(index, RetrieveEntryRole)); if (entryList.isEmpty()) { return -1; qWarning()<<"invalid index, there's no data to retrieve here"; } if (entryList.at(0)==QString()) { return entryList.at(1).toUInt(); } i = colorSet()->nColorsGroup(""); //find at which position the group is. int groupIndex = colorSet()->getGroupNames().indexOf(entryList.at(0)); //add all the groupsizes onto it till we get to our group. for(int g=0; gnColorsGroup(colorSet()->getGroupNames().at(g)); } //then add the index. i += entryList.at(1).toUInt(); return i; } KoColorSetEntry KisPaletteModel::colorSetEntryFromIndex(const QModelIndex &index) const { KoColorSetEntry blank = KoColorSetEntry(); if (!index.isValid()) { return blank; } QStringList entryList = qvariant_cast(data(index, RetrieveEntryRole)); if (entryList.isEmpty()) { return blank; } QString groupName = entryList.at(0); quint32 indexInGroup = entryList.at(1).toUInt(); return m_colorSet->getColorGroup(indexInGroup, groupName); } bool KisPaletteModel::addColorSetEntry(KoColorSetEntry entry, QString groupName) { int col = m_colorSet->nColorsGroup(groupName)%columnCount(); QModelIndex i = getLastEntryIndex(); if (col+1 > columnCount()) { beginInsertRows(QModelIndex(), i.row(), i.row()+1); } if ((int)m_colorSet->nColors() < columnCount()) { beginInsertColumns(QModelIndex(), m_colorSet->nColors(), m_colorSet->nColors()+1); } m_colorSet->add(entry, groupName); if (col + 1 > columnCount()) { endInsertRows(); } if (m_colorSet->nColors() < (quint32)columnCount()) { endInsertColumns(); } return true; } bool KisPaletteModel::removeEntry(QModelIndex index, bool keepColors) { QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); if (entryList.empty()) { return false; } QString groupName = entryList.at(0); quint32 indexInGroup = entryList.at(1).toUInt(); if (qvariant_cast(index.data(IsHeaderRole))==false) { if (index.column()-1<0 && m_colorSet->nColorsGroup(groupName)%columnCount() <1 && index.row()-1>0 && m_colorSet->nColorsGroup(groupName)/columnCount()>0) { beginRemoveRows(QModelIndex(), index.row(), index.row()-1); } m_colorSet->removeAt(indexInGroup, groupName); if (index.column()-1<0 && m_colorSet->nColorsGroup(groupName)%columnCount() <1 && index.row()-1>0 && m_colorSet->nColorsGroup(groupName)/columnCount()>0) { endRemoveRows(); } } else { beginRemoveRows(QModelIndex(), index.row(), index.row()-1); m_colorSet->removeGroup(groupName, keepColors); endRemoveRows(); } return true; } bool KisPaletteModel::addGroup(QString groupName) { QModelIndex i = getLastEntryIndex(); beginInsertRows(QModelIndex(), i.row(), i.row()+1); m_colorSet->addGroup(groupName); endInsertRows(); return true; } bool KisPaletteModel::removeRows(int row, int count, const QModelIndex &parent) { Q_ASSERT(!parent.isValid()); int beginRow = qMax(0, row); int endRow = qMin(row + count - 1, (int)m_colorSet->nColors() - 1); beginRemoveRows(parent, beginRow, endRow); // Find the palette entry at row, count, remove from KoColorSet endRemoveRows(); return true; } bool KisPaletteModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { if (!data->hasFormat("krita/x-colorsetentry") && !data->hasFormat("krita/x-colorsetgroup")) { return false; } if (action == Qt::IgnoreAction) { return false; } int endRow; int endColumn; if (!parent.isValid()) { if (row < 0) { endRow = indexFromId(m_colorSet->nColors()).row(); endColumn = indexFromId(m_colorSet->nColors()).column(); } else { endRow = qMin(row, indexFromId(m_colorSet->nColors()).row()); endColumn = qMin(column, m_colorSet->columnCount()); } } else { endRow = qMin(parent.row(), rowCount()); endColumn = qMin(parent.column(), columnCount()); } if (data->hasFormat("krita/x-colorsetgroup")) { QByteArray encodedData = data->data("krita/x-colorsetgroup"); QDataStream stream(&encodedData, QIODevice::ReadOnly); while (!stream.atEnd()) { QString groupName; stream >> groupName; QModelIndex index = this->index(endRow, 0); if (index.isValid()) { QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); QString groupDroppedOn = QString(); if (!entryList.isEmpty()) { groupDroppedOn = entryList.at(0); } int groupIndex = colorSet()->getGroupNames().indexOf(groupName); beginMoveRows( QModelIndex(), groupIndex, groupIndex, QModelIndex(), endRow); m_colorSet->moveGroup(groupName, groupDroppedOn); m_colorSet->save(); endMoveRows(); ++endRow; } } } else { QByteArray encodedData = data->data("krita/x-colorsetentry"); QDataStream stream(&encodedData, QIODevice::ReadOnly); while (!stream.atEnd()) { KoColorSetEntry entry; QString oldGroupName; int indexInGroup; QString colorXml; - stream >> entry.name - >> entry.id - >> entry.spotColor + QString name, id; + bool spotColor; + stream >> name + >> id + >> spotColor >> indexInGroup >> oldGroupName >> colorXml; + entry.setName(name); + entry.setId(id); + entry.setSpotColor(spotColor); QDomDocument doc; doc.setContent(colorXml); QDomElement e = doc.documentElement(); QDomElement c = e.firstChildElement(); if (!c.isNull()) { QString colorDepthId = c.attribute("bitdepth", Integer8BitsColorDepthID.id()); - entry.color = KoColor::fromXML(c, colorDepthId); + entry.setColor(KoColor::fromXML(c, colorDepthId)); } QModelIndex index = this->index(endRow, endColumn); if (qvariant_cast(index.data(IsHeaderRole))){ endRow+=1; } if (index.isValid()) { /*this is to figure out the row of the old color. * That way we can in turn avoid moverows from complaining the * index is out of bounds when using index. * Makes me wonder if we shouldn't just insert the index of the * old color when requesting the mimetype... */ int i = indexInGroup; if (oldGroupName != QString()) { colorSet()->nColorsGroup(""); //find at which position the group is. int groupIndex = colorSet()->getGroupNames().indexOf(oldGroupName); //add all the groupsizes onto it till we get to our group. for(int g=0; gnColorsGroup(colorSet()->getGroupNames().at(g)); } } QModelIndex indexOld = indexFromId(i); if (action == Qt::MoveAction){ if (indexOld.row()!=qMax(endRow, 0) && indexOld.row()!=qMax(endRow+1,1)) { beginMoveRows(QModelIndex(), indexOld.row(), indexOld.row(), QModelIndex(), qMax(endRow+1,1)); } if (indexOld.column()!=qMax(endColumn, 0) && indexOld.column()!=qMax(endColumn+1,1)) { beginMoveColumns(QModelIndex(), indexOld.column(), indexOld.column(), QModelIndex(), qMax(endColumn+1,1)); } } else { beginInsertRows(QModelIndex(), endRow, endRow); } QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); QString entryInGroup = "0"; QString groupName = QString(); if (!entryList.isEmpty()) { groupName = entryList.at(0); entryInGroup = entryList.at(1); } int location = entryInGroup.toInt(); // Insert the entry if (groupName==oldGroupName && qvariant_cast(index.data(IsHeaderRole))==true) { groupName=QString(); location=m_colorSet->nColorsGroup(); } m_colorSet->insertBefore(entry, location, groupName); if (groupName==oldGroupName && locationremoveAt(indexInGroup, oldGroupName); } m_colorSet->save(); if (action == Qt::MoveAction){ if (indexOld.row()!=qMax(endRow, 0) && indexOld.row()!=qMax(endRow+1,1)) { endMoveRows(); } if (indexOld.column()!=qMax(endColumn, 0) && indexOld.column()!=qMax(endColumn+1,1)) { endMoveColumns(); } } else { endInsertRows(); } ++endRow; } } } return true; } QMimeData *KisPaletteModel::mimeData(const QModelIndexList &indexes) const { QMimeData *mimeData = new QMimeData(); QByteArray encodedData; QDataStream stream(&encodedData, QIODevice::WriteOnly); QString mimeTypeName = "krita/x-colorsetentry"; //Q_FOREACH(const QModelIndex &index, indexes) { QModelIndex index = indexes.last(); if (index.isValid()) { if (qvariant_cast(index.data(IsHeaderRole))==false) { KoColorSetEntry entry = colorSetEntryFromIndex(index); QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); QString groupName = QString(); int indexInGroup = 0; if (!entryList.isEmpty()) { groupName = entryList.at(0); QString iig = entryList.at(1); indexInGroup = iig.toInt(); } QDomDocument doc; QDomElement root = doc.createElement("Color"); - root.setAttribute("bitdepth", entry.color.colorSpace()->colorDepthId().id()); + root.setAttribute("bitdepth", entry.color().colorSpace()->colorDepthId().id()); doc.appendChild(root); - entry.color.toXML(doc, root); + entry.color().toXML(doc, root); - stream << entry.name - << entry.id - << entry.spotColor + stream << entry.name() + << entry.id() + << entry.spotColor() << indexInGroup << groupName << doc.toString(); } else { mimeTypeName = "krita/x-colorsetgroup"; QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); QString groupName = QString(); if (!entryList.isEmpty()) { groupName = entryList.at(0); } stream << groupName; } } mimeData->setData(mimeTypeName, encodedData); return mimeData; } QStringList KisPaletteModel::mimeTypes() const { return QStringList() << "krita/x-colorsetentry" << "krita/x-colorsetgroup"; } Qt::DropActions KisPaletteModel::supportedDropActions() const { return Qt::MoveAction; } diff --git a/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp b/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp index e15c0779fb..f77bfceff2 100644 --- a/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp +++ b/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp @@ -1,378 +1,378 @@ /* * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 * * 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 "KoColorSpaceRegistry.h" #include #include #include #include #include #include #include "kis_signal_compressor.h" #include "KisViewManager.h" #include "KoColorDisplayRendererInterface.h" #include "kis_spinbox_color_selector.h" #include "kis_dlg_internal_color_selector.h" #include "ui_wdgdlginternalcolorselector.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_color_input.h" #include "kis_icon_utils.h" #include "squeezedcombobox.h" struct KisDlgInternalColorSelector::Private { bool allowUpdates = true; KoColor currentColor; KoColor previousColor; KoColor sRGB = KoColor(KoColorSpaceRegistry::instance()->rgb8()); const KoColorSpace *currentColorSpace; bool lockUsedCS = false; bool chooseAlpha = false; KisSignalCompressor *compressColorChanges; const KoColorDisplayRendererInterface *displayRenderer; KisHexColorInput *hexColorInput = 0; KisPaletteModel *paletteModel = 0; KisColorsetChooser *colorSetChooser = 0; }; KisDlgInternalColorSelector::KisDlgInternalColorSelector(QWidget *parent, KoColor color, Config config, const QString &caption, const KoColorDisplayRendererInterface *displayRenderer) : QDialog(parent) , m_d(new Private) { setModal(config.modal); this->setFocusPolicy(Qt::ClickFocus); m_ui = new Ui_WdgDlgInternalColorSelector(); m_ui->setupUi(this); setWindowTitle(caption); m_d->currentColor = color; m_d->currentColorSpace = m_d->currentColor.colorSpace(); m_d->displayRenderer = displayRenderer; m_ui->spinboxselector->slotSetColor(color); connect(m_ui->spinboxselector, SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor))); m_ui->visualSelector->slotSetColor(color); m_ui->visualSelector->setDisplayRenderer(displayRenderer); m_ui->visualSelector->setConfig(false, config.modal); if (config.visualColorSelector) { connect(m_ui->visualSelector, SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor))); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), m_ui->visualSelector, SLOT(configurationChanged())); } else { m_ui->visualSelector->hide(); } if (config.screenColorPicker) { connect(m_ui->screenColorPicker, SIGNAL(sigNewColorPicked(KoColor)),this, SLOT(slotColorUpdated(KoColor))); } else { m_ui->screenColorPicker->hide(); } if (!m_d->paletteModel) { m_d->paletteModel = new KisPaletteModel(this); m_ui->paletteBox->setPaletteModel(m_d->paletteModel); } m_ui->paletteList->setIcon(KisIconUtils::loadIcon("hi16-palette_library")); // For some bizare reason, the modal dialog doesn't like having the colorset set, so let's not. if (config.paletteBox) { //TODO: Add disable signal as well. Might be not necessary...? KisConfig cfg; QString paletteName = cfg.readEntry("internal_selector_active_color_set", QString()); KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(); KoColorSet *savedPal = rServer->resourceByName(paletteName); if (savedPal) { this->slotChangePalette(savedPal); } else { Q_ASSERT(rServer->resources().count()); if (rServer->resources().count()) { savedPal = rServer->resources().first(); if (savedPal) { this->slotChangePalette(savedPal); } } } connect(m_ui->paletteBox, SIGNAL(entrySelected(KoColorSetEntry)), this, SLOT(slotSetColorFromColorSetEntry(KoColorSetEntry))); connect(m_ui->cmbNameList, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetColorFromColorList())); //m_ui->paletteBox->setDisplayRenderer(displayRenderer); m_d->colorSetChooser = new KisColorsetChooser(this); connect(m_d->colorSetChooser, SIGNAL(paletteSelected(KoColorSet*)), this, SLOT(slotChangePalette(KoColorSet*))); m_ui->paletteList->setPopupWidget(m_d->colorSetChooser); } else { m_ui->paletteBox->setEnabled(false); m_ui->cmbNameList->setEnabled(false); m_ui->paletteList->setEnabled(false); } if (config.prevNextButtons) { m_ui->currentColor->setColor(m_d->currentColor); m_ui->currentColor->setDisplayRenderer(displayRenderer); m_ui->previousColor->setColor(m_d->currentColor); m_ui->previousColor->setDisplayRenderer(displayRenderer); connect(m_ui->previousColor, SIGNAL(triggered(KoColorPatch*)), SLOT(slotSetColorFromPatch(KoColorPatch*))); } else { m_ui->currentColor->hide(); m_ui->previousColor->hide(); } if (config.hexInput) { m_d->sRGB.fromKoColor(m_d->currentColor); m_d->hexColorInput = new KisHexColorInput(this, &m_d->sRGB); m_d->hexColorInput->update(); connect(m_d->hexColorInput, SIGNAL(updated()), SLOT(slotSetColorFromHex())); m_ui->rightPane->addWidget(m_d->hexColorInput); m_d->hexColorInput->setToolTip(i18n("This is a hexcode input, for webcolors. It can only get colors in the sRGB space.")); } connect(this, SIGNAL(signalForegroundColorChosen(KoColor)), this, SLOT(slotLockSelector())); m_d->compressColorChanges = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this); connect(m_d->compressColorChanges, SIGNAL(timeout()), this, SLOT(endUpdateWithNewColor())); connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(this, SIGNAL(finished(int)), SLOT(slotFinishUp())); } KisDlgInternalColorSelector::~KisDlgInternalColorSelector() { delete m_ui; } void KisDlgInternalColorSelector::slotColorUpdated(KoColor newColor) { //if the update did not come from this selector... if (m_d->allowUpdates || QObject::sender() == this->parent()) { if (m_d->lockUsedCS){ newColor.convertTo(m_d->currentColorSpace); m_d->currentColor = newColor; } else { m_d->currentColor = newColor; } updateAllElements(QObject::sender()); } } void KisDlgInternalColorSelector::slotSetColorFromPatch(KoColorPatch *patch) { slotColorUpdated(patch->color()); } void KisDlgInternalColorSelector::colorSpaceChanged(const KoColorSpace *cs) { if (cs == m_d->currentColorSpace) { return; } m_d->currentColorSpace = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile()); m_ui->spinboxselector->slotSetColorSpace(m_d->currentColorSpace); m_ui->visualSelector->slotsetColorSpace(m_d->currentColorSpace); } void KisDlgInternalColorSelector::lockUsedColorSpace(const KoColorSpace *cs) { colorSpaceChanged(cs); m_d->lockUsedCS = true; } void KisDlgInternalColorSelector::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) { if (displayRenderer) { m_d->displayRenderer = displayRenderer; m_ui->visualSelector->setDisplayRenderer(displayRenderer); m_ui->currentColor->setDisplayRenderer(displayRenderer); m_ui->previousColor->setDisplayRenderer(displayRenderer); //m_ui->paletteBox->setDisplayRenderer(displayRenderer); } else { m_d->displayRenderer = KoDumbColorDisplayRenderer::instance(); } } KoColor KisDlgInternalColorSelector::getModalColorDialog(const KoColor color, QWidget* parent, QString caption) { Config config = Config(); KisDlgInternalColorSelector dialog(parent, color, config, caption); dialog.setPreviousColor(color); dialog.exec(); return dialog.getCurrentColor(); } KoColor KisDlgInternalColorSelector::getCurrentColor() { return m_d->currentColor; } void KisDlgInternalColorSelector::chooseAlpha(bool chooseAlpha) { m_d->chooseAlpha = chooseAlpha; } void KisDlgInternalColorSelector::slotConfigurationChanged() { //m_d->canvas->displayColorConverter()-> //slotColorSpaceChanged(m_d->canvas->image()->colorSpace()); } void KisDlgInternalColorSelector::slotLockSelector() { m_d->allowUpdates = false; } void KisDlgInternalColorSelector::setPreviousColor(KoColor c) { m_d->previousColor = c; } void KisDlgInternalColorSelector::reject() { slotColorUpdated(m_d->previousColor); QDialog::reject(); } void KisDlgInternalColorSelector::updateAllElements(QObject *source) { //update everything!!! if (source != m_ui->spinboxselector) { m_ui->spinboxselector->slotSetColor(m_d->currentColor); } if (source != m_ui->visualSelector) { m_ui->visualSelector->slotSetColor(m_d->currentColor); } if (source != m_d->hexColorInput) { m_d->sRGB.fromKoColor(m_d->currentColor); m_d->hexColorInput->update(); } m_ui->previousColor->setColor(m_d->previousColor); m_ui->currentColor->setColor(m_d->currentColor); if (source != this->parent()) { emit(signalForegroundColorChosen(m_d->currentColor)); m_d->compressColorChanges->start(); } m_ui->screenColorPicker->updateIcons(); } void KisDlgInternalColorSelector::endUpdateWithNewColor() { m_d->allowUpdates = true; } void KisDlgInternalColorSelector::focusInEvent(QFocusEvent *) { //setPreviousColor(); } void KisDlgInternalColorSelector::slotFinishUp() { setPreviousColor(m_d->currentColor); KisConfig cfg; if (m_d->paletteModel) { if (m_d->paletteModel->colorSet()) { cfg.writeEntry("internal_selector_active_color_set", m_d->paletteModel->colorSet()->name()); } } } void KisDlgInternalColorSelector::slotSetColorFromHex() { slotColorUpdated(m_d->sRGB); } void KisDlgInternalColorSelector::slotChangePalette(KoColorSet *set) { if (!set) { return; } m_d->paletteModel->setColorSet(set); m_ui->cmbNameList->clear(); for (quint32 i = 0; i< set->nColors(); i++) { KoColorSetEntry entry = set->getColorGlobal(i); QPixmap colorSquare = QPixmap(32, 32); - if (entry.spotColor) { + if (entry.spotColor()) { QImage img = QImage(32, 32, QImage::Format_ARGB32); QPainter circlePainter; img.fill(Qt::transparent); circlePainter.begin(&img); QBrush brush = QBrush(Qt::SolidPattern); - brush.setColor(entry.color.toQColor()); + brush.setColor(entry.color().toQColor()); circlePainter.setBrush(brush); QPen pen = circlePainter.pen(); pen.setColor(Qt::transparent); pen.setWidth(0); circlePainter.setPen(pen); circlePainter.drawEllipse(0, 0, 32, 32); circlePainter.end(); colorSquare = QPixmap::fromImage(img); } else { - colorSquare.fill(entry.color.toQColor()); + colorSquare.fill(entry.color().toQColor()); } - QString name = entry.name; - if (!entry.id.isEmpty()){ - name = entry.id + " - " + entry.name; + QString name = entry.name(); + if (!entry.id().isEmpty()){ + name = entry.id() + " - " + entry.name(); } m_ui->cmbNameList->addSqueezedItem(QIcon(colorSquare), name); } QCompleter *completer = new QCompleter(m_ui->cmbNameList->model()); completer->setCompletionMode(QCompleter::PopupCompletion); completer->setCaseSensitivity(Qt::CaseInsensitive); completer->setFilterMode(Qt::MatchContains); m_ui->cmbNameList->setCompleter(completer); } void KisDlgInternalColorSelector::slotSetColorFromColorList() { int index = m_ui->cmbNameList->currentIndex(); if (m_d->paletteModel) { slotSetColorFromColorSetEntry(m_d->paletteModel->colorSet()->getColorGlobal(index)); m_ui->paletteBox->blockSignals(true); m_ui->paletteBox->selectionModel()->clearSelection(); m_ui->paletteBox->selectionModel()->setCurrentIndex(m_d->paletteModel->indexFromId(index), QItemSelectionModel::Select); m_ui->paletteBox->blockSignals(false); } } void KisDlgInternalColorSelector::slotSetColorFromColorSetEntry(KoColorSetEntry entry) { - slotColorUpdated(entry.color); + slotColorUpdated(entry.color()); } void KisDlgInternalColorSelector::showEvent(QShowEvent *event) { updateAllElements(0); QDialog::showEvent(event); } diff --git a/libs/ui/kis_palette_view.cpp b/libs/ui/kis_palette_view.cpp index c67e965374..04c70c32af 100644 --- a/libs/ui/kis_palette_view.cpp +++ b/libs/ui/kis_palette_view.cpp @@ -1,342 +1,344 @@ /* * Copyright (c) 2016 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_palette_view.h" #include #include #include "kis_palette_delegate.h" #include "KisPaletteModel.h" #include "kis_config.h" #include #include #include #include #include #include #include #include +#include struct KisPaletteView::Private { - KisPaletteModel *model = 0; + KisPaletteModel *model = nullptr; bool allowPaletteModification = true; }; KisPaletteView::KisPaletteView(QWidget *parent) - : KoTableView(parent), - m_d(new Private) + : KoTableView(parent) + , m_d(new Private) { setShowGrid(false); horizontalHeader()->setVisible(false); verticalHeader()->setVisible(false); setItemDelegate(new KisPaletteDelegate()); // setDragEnabled(true); // setDragDropMode(QAbstractItemView::InternalMove); setDropIndicatorShown(true); KisConfig cfg; //QPalette pal(palette()); //pal.setColor(QPalette::Base, cfg.getMDIBackgroundColor()); //setAutoFillBackground(true); //setPalette(pal); int defaultSectionSize = cfg.paletteDockerPaletteViewSectionSize(); horizontalHeader()->setDefaultSectionSize(defaultSectionSize); verticalHeader()->setDefaultSectionSize(defaultSectionSize); connect(this, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(modifyEntry(QModelIndex))); } KisPaletteView::~KisPaletteView() { } void KisPaletteView::setCrossedKeyword(const QString &value) { KisPaletteDelegate *delegate = dynamic_cast(itemDelegate()); KIS_ASSERT_RECOVER_RETURN(delegate); delegate->setCrossedKeyword(value); } bool KisPaletteView::addEntryWithDialog(KoColor color) { KoDialog *window = new KoDialog(); window->setWindowTitle(i18nc("@title:window", "Add a new Colorset Entry")); QFormLayout *editableItems = new QFormLayout(); window->mainWidget()->setLayout(editableItems); QComboBox *cmbGroups = new QComboBox(); QString defaultGroupName = i18nc("Name for default group", "Default"); cmbGroups->addItem(defaultGroupName); cmbGroups->addItems(m_d->model->colorSet()->getGroupNames()); QLineEdit *lnIDName = new QLineEdit(); QLineEdit *lnName = new QLineEdit(); KisColorButton *bnColor = new KisColorButton(); bnColor->setPaletteViewEnabled(false); QCheckBox *chkSpot = new QCheckBox(); chkSpot->setToolTip(i18nc("@info:tooltip", "A spot color is a color that the printer is able to print without mixing the paints it has available to it. The opposite is called a process color.")); editableItems->addRow(i18n("Group"), cmbGroups); editableItems->addRow(i18n("ID"), lnIDName); editableItems->addRow(i18n("Name"), lnName); editableItems->addRow(i18n("Color"), bnColor); editableItems->addRow(i18nc("Spot color", "Spot"), chkSpot); cmbGroups->setCurrentIndex(0); lnName->setText(i18nc("Part of a default name for a color","Color")+" "+QString::number(m_d->model->colorSet()->nColors()+1)); lnIDName->setText(QString::number(m_d->model->colorSet()->nColors()+1)); bnColor->setColor(color); chkSpot->setChecked(false); // if (window->exec() == KoDialog::Accepted) { QString groupName = cmbGroups->currentText(); if (groupName == defaultGroupName) { groupName = QString(); } KoColorSetEntry newEntry; - newEntry.color = bnColor->color(); - newEntry.name = lnName->text(); - newEntry.id = lnIDName->text(); - newEntry.spotColor = chkSpot->isChecked(); + newEntry.setColor(bnColor->color()); + newEntry.setName(lnName->text()); + newEntry.setId(lnIDName->text()); + newEntry.setSpotColor(chkSpot->isChecked()); m_d->model->addColorSetEntry(newEntry, groupName); m_d->model->colorSet()->save(); return true; } return false; } +// should be move to colorSetChooser bool KisPaletteView::addGroupWithDialog() { KoDialog *window = new KoDialog(); window->setWindowTitle(i18nc("@title:window","Add a new group")); QFormLayout *editableItems = new QFormLayout(); window->mainWidget()->setLayout(editableItems); QLineEdit *lnName = new QLineEdit(); editableItems->addRow(i18nc("Name for a group", "Name"), lnName); lnName->setText(i18nc("Part of default name for a new group", "Color Group")+""+QString::number(m_d->model->colorSet()->getGroupNames().size()+1)); if (window->exec() == KoDialog::Accepted) { QString groupName = lnName->text(); m_d->model->addGroup(groupName); m_d->model->colorSet()->save(); return true; } return false; } bool KisPaletteView::removeEntryWithDialog(QModelIndex index) { bool keepColors = true; if (qvariant_cast(index.data(KisPaletteModel::IsHeaderRole))) { KoDialog *window = new KoDialog(); window->setWindowTitle(i18nc("@title:window","Removing Group")); QFormLayout *editableItems = new QFormLayout(); QCheckBox *chkKeep = new QCheckBox(); window->mainWidget()->setLayout(editableItems); editableItems->addRow(i18nc("Shows up when deleting a group","Keep the Colors"), chkKeep); chkKeep->setChecked(keepColors); if (window->exec() == KoDialog::Accepted) { keepColors = chkKeep->isChecked(); m_d->model->removeEntry(index, keepColors); m_d->model->colorSet()->save(); } } else { m_d->model->removeEntry(index, keepColors); m_d->model->colorSet()->save(); } return true; } void KisPaletteView::trySelectClosestColor(KoColor color) { KoColorSet* color_set = m_d->model->colorSet(); if (!color_set) return; //also don't select if the color is the same as the current selection if (selectedIndexes().size()>0) { QModelIndex currentI = currentIndex(); if (!currentI.isValid()) { currentI = selectedIndexes().last(); } if (!currentI.isValid()) { currentI = selectedIndexes().first(); } if (currentI.isValid()) { - if (m_d->model->colorSetEntryFromIndex(currentI).color==color) { + if (m_d->model->colorSetEntryFromIndex(currentI).color()==color) { return; } } } quint32 i = color_set->getIndexClosestColor(color); QModelIndex index = m_d->model->indexFromId(i); this->selectionModel()->clearSelection(); this->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select); } void KisPaletteView::mouseReleaseEvent(QMouseEvent *event) { bool foreground = false; if (event->button()== Qt::LeftButton) { foreground = true; } entrySelection(foreground); } void KisPaletteView::paletteModelChanged() { updateView(); updateRows(); } void KisPaletteView::setPaletteModel(KisPaletteModel *model) { if (m_d->model) { disconnect(m_d->model, 0, this, 0); } m_d->model = model; setModel(model); paletteModelChanged(); connect(m_d->model, SIGNAL(layoutChanged(QList,QAbstractItemModel::LayoutChangeHint)), this, SLOT(paletteModelChanged())); connect(m_d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(paletteModelChanged())); connect(m_d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(paletteModelChanged())); connect(m_d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(paletteModelChanged())); connect(m_d->model, SIGNAL(modelReset()), this, SLOT(paletteModelChanged())); } KisPaletteModel* KisPaletteView::paletteModel() const { return m_d->model; } void KisPaletteView::updateRows() { this->clearSpans(); if (m_d->model) { for (int r=0; r<=m_d->model->rowCount(); r++) { QModelIndex index = m_d->model->index(r, 0); if (qvariant_cast(index.data(KisPaletteModel::IsHeaderRole))) { setSpan(r, 0, 1, m_d->model->columnCount()); setRowHeight(r, this->fontMetrics().lineSpacing()+6); } else { this->setRowHeight(r, this->columnWidth(0)); } } } } void KisPaletteView::setAllowModification(bool allow) { m_d->allowPaletteModification = allow; } void KisPaletteView::wheelEvent(QWheelEvent *event) { if (event->modifiers() & Qt::ControlModifier) { int numDegrees = event->delta() / 8; int numSteps = numDegrees / 7; int curSize = horizontalHeader()->sectionSize(0); int setSize = numSteps + curSize; if ( (event->delta() <= 0) && (setSize <= 8) ) { // Ignore scroll-zooming down below a certain size } else { horizontalHeader()->setDefaultSectionSize(setSize); verticalHeader()->setDefaultSectionSize(setSize); KisConfig cfg; cfg.setPaletteDockerPaletteViewSectionSize(setSize); } event->accept(); } else { KoTableView::wheelEvent(event); } } void KisPaletteView::entrySelection(bool foreground) { QModelIndex index; if (selectedIndexes().size()<=0) { return; } if (selectedIndexes().last().isValid()) { index = selectedIndexes().last(); } else if (selectedIndexes().first().isValid()) { index = selectedIndexes().first(); } else { return; } if (qvariant_cast(index.data(KisPaletteModel::IsHeaderRole))==false) { KoColorSetEntry entry = m_d->model->colorSetEntryFromIndex(index); if (foreground) { emit(entrySelected(entry)); emit(indexEntrySelected(index)); } else { emit(entrySelectedBackGround(entry)); emit(indexEntrySelected(index)); } } } void KisPaletteView::modifyEntry(QModelIndex index) { if (m_d->allowPaletteModification) { KoDialog *group = new KoDialog(); QFormLayout *editableItems = new QFormLayout(); group->mainWidget()->setLayout(editableItems); QLineEdit *lnIDName = new QLineEdit(); QLineEdit *lnGroupName = new QLineEdit(); KisColorButton *bnColor = new KisColorButton(); bnColor->setPaletteViewEnabled(false); QCheckBox *chkSpot = new QCheckBox(); if (qvariant_cast(index.data(KisPaletteModel::IsHeaderRole))) { QString groupName = qvariant_cast(index.data(Qt::DisplayRole)); editableItems->addRow(i18nc("Name for a colorgroup","Name"), lnGroupName); lnGroupName->setText(groupName); if (group->exec() == KoDialog::Accepted) { m_d->model->colorSet()->changeGroupName(groupName, lnGroupName->text()); m_d->model->colorSet()->save(); updateRows(); } //rename the group. } else { KoColorSetEntry entry = m_d->model->colorSetEntryFromIndex(index); QStringList entryList = qvariant_cast(index.data(KisPaletteModel::RetrieveEntryRole)); chkSpot->setToolTip(i18nc("@info:tooltip", "A spot color is a color that the printer is able to print without mixing the paints it has available to it. The opposite is called a process color.")); editableItems->addRow(i18n("ID"), lnIDName); editableItems->addRow(i18n("Name"), lnGroupName); editableItems->addRow(i18n("Color"), bnColor); editableItems->addRow(i18n("Spot"), chkSpot); - lnGroupName->setText(entry.name); - lnIDName->setText(entry.id); - bnColor->setColor(entry.color); - chkSpot->setChecked(entry.spotColor); + lnGroupName->setText(entry.name()); + lnIDName->setText(entry.id()); + bnColor->setColor(entry.color()); + chkSpot->setChecked(entry.spotColor()); if (group->exec() == KoDialog::Accepted) { - entry.name = lnGroupName->text(); - entry.id = lnIDName->text(); - entry.color = bnColor->color(); - entry.spotColor = chkSpot->isChecked(); + entry.setName(lnGroupName->text()); + entry.setId(lnIDName->text()); + entry.setColor(bnColor->color()); + entry.setSpotColor(chkSpot->isChecked()); m_d->model->colorSet()->changeColorSetEntry(entry, entryList.at(0), entryList.at(1).toUInt()); m_d->model->colorSet()->save(); } } } } diff --git a/libs/widgets/KoColorSetWidget.cpp b/libs/widgets/KoColorSetWidget.cpp index ebdaae0e33..dbab43e153 100644 --- a/libs/widgets/KoColorSetWidget.cpp +++ b/libs/widgets/KoColorSetWidget.cpp @@ -1,332 +1,333 @@ /* This file is part of the KDE project Copyright (c) 2007, 2012 C. Boemann Copyright (c) 2007-2008 Fredy Yanardi 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 "KoColorSetWidget.h" #include "KoColorSetWidget_p.h" #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 void KoColorSetWidget::KoColorSetWidgetPrivate::fillColors() { delete colorSetContainer; colorSetContainer = new QWidget(); colorSetLayout = new QVBoxLayout(); colorSetLayout->setMargin(3); colorSetLayout->setSpacing(0); // otherwise the use can click where there is none colorSetContainer->setBackgroundRole(QPalette::Dark); int patchSize = 12; int columns = 16; if (colorSet) { columns = colorSet->columnCount(); } colorSetContainer->setMinimumWidth(columns*patchSize+6); colorSetContainer->setLayout(colorSetLayout); patchWidgetList.clear(); colornames.clear(); colorNameCmb->clear(); QWidget *defaultGroupContainer = new QWidget(); QGridLayout *colorGroupLayout = new QGridLayout(); for(int i = 0; isetColumnMinimumWidth(i, patchSize); } defaultGroupContainer->setMinimumWidth(columns*patchSize); defaultGroupContainer->setMaximumWidth(columns*patchSize); colorGroupLayout->setSpacing(0); colorGroupLayout->setMargin(0); defaultGroupContainer->setLayout(colorGroupLayout); if (colorSet) { for( quint32 i = 0, p= 0; i < colorSet->nColorsGroup(); i++) { KoColorPatch *patch = new KoColorPatch(colorSetContainer); patch->setFrameStyle(QFrame::Plain | QFrame::Box); patch->setLineWidth(1); KoColorSetEntry c = colorSet->getColorGlobal(i); - patch->setColor(c.color); - patch->setToolTip(c.name); + patch->setColor(c.color()); + patch->setToolTip(c.name()); connect(patch, SIGNAL(triggered(KoColorPatch *)), thePublic, SLOT(colorTriggered(KoColorPatch *))); colorGroupLayout->addWidget(patch, p/columns, p%columns); patch->setDisplayRenderer(displayRenderer); patchWidgetList.append(patch); - colornames.append(c.name); + colornames.append(c.name()); QPixmap colorsquare = QPixmap(12,12); - colorsquare.fill(c.color.toQColor()); - colorNameCmb->addItem(QIcon(colorsquare), c.name); + colorsquare.fill(c.color().toQColor()); + colorNameCmb->addItem(QIcon(colorsquare), c.name()); ++p; } colorSetLayout->addWidget(defaultGroupContainer); Q_FOREACH(QString groupName, colorSet->getGroupNames()) { QGroupBox *groupbox = new QGroupBox(); groupbox->setTitle(groupName); QGridLayout *groupLayout = new QGridLayout(); for(int i = 0; isetColumnMinimumWidth(i, patchSize); } groupLayout->setSpacing(0); groupLayout->setMargin(0); groupbox->setMinimumWidth(columns*patchSize); groupbox->setMaximumWidth(columns*patchSize); groupbox->setLayout(groupLayout); groupbox->setFlat(true); for( quint32 i = 0, p= 0; i < colorSet->nColorsGroup(groupName); i++) { KoColorPatch *patch = new KoColorPatch(colorSetContainer); patch->setFrameStyle(QFrame::Plain | QFrame::Box); patch->setLineWidth(1); KoColorSetEntry c = colorSet->getColorGroup(i, groupName); - patch->setColor(c.color); - patch->setToolTip(c.name); + patch->setColor(c.color()); + patch->setToolTip(c.name()); connect(patch, SIGNAL(triggered(KoColorPatch *)), thePublic, SLOT(colorTriggered(KoColorPatch *))); groupLayout->addWidget(patch, p/columns, p%columns); patch->setDisplayRenderer(displayRenderer); patchWidgetList.append(patch); - colornames.append(c.name); + colornames.append(c.name()); QPixmap colorsquare = QPixmap(12,12); - colorsquare.fill(c.color.toQColor()); - colorNameCmb->addItem(QIcon(colorsquare), c.name); + colorsquare.fill(c.color().toQColor()); + colorNameCmb->addItem(QIcon(colorsquare), c.name()); ++p; } colorSetLayout->addWidget(groupbox); } } scrollArea->setWidget(colorSetContainer); connect(colorNameCmb, SIGNAL(activated(QString)), thePublic, SLOT(setColorFromString(QString)), Qt::UniqueConnection); } void KoColorSetWidget::KoColorSetWidgetPrivate::addRemoveColors() { KoResourceServer* srv = KoResourceServerProvider::instance()->paletteServer(); QList palettes = srv->resources(); Q_ASSERT(colorSet); KoEditColorSetDialog *dlg = new KoEditColorSetDialog(palettes, colorSet->name(), thePublic); if (dlg->exec() == KoDialog::Accepted ) { // always reload the color set KoColorSet * cs = dlg->activeColorSet(); // check if the selected colorset is predefined if( cs && !palettes.contains( cs ) ) { int i = 1; QFileInfo fileInfo; QString savePath = srv->saveLocation(); do { fileInfo.setFile(savePath + QString("%1.%2").arg(i++, 4, 10, QChar('0')).arg(colorSet->defaultFileExtension())); } while (fileInfo.exists()); cs->setFilename( fileInfo.filePath() ); cs->setValid( true ); // add new colorset to predefined colorsets if (!srv->addResource(cs)) { delete cs; cs = 0; } } if (cs) { thePublic->setColorSet(cs); } } delete dlg; } void KoColorSetWidget::KoColorSetWidgetPrivate::addRecent(const KoColor &color) { if(numRecents<6) { recentPatches[numRecents] = new KoColorPatch(thePublic); recentPatches[numRecents]->setFrameShape(QFrame::StyledPanel); recentPatches[numRecents]->setDisplayRenderer(displayRenderer); recentsLayout->insertWidget(numRecents+1, recentPatches[numRecents]); connect(recentPatches[numRecents], SIGNAL(triggered(KoColorPatch *)), thePublic, SLOT(colorTriggered(KoColorPatch *))); numRecents++; } // shift colors to the right for (int i = numRecents- 1; i >0; i--) { recentPatches[i]->setColor(recentPatches[i-1]->color()); } //Finally set the recent color recentPatches[0]->setColor(color); } void KoColorSetWidget::KoColorSetWidgetPrivate::activateRecent(int i) { KoColor color = recentPatches[i]->color(); while (i >0) { recentPatches[i]->setColor(recentPatches[i-1]->color()); i--; } recentPatches[0]->setColor(color); } KoColorSetWidget::KoColorSetWidget(QWidget *parent) : QFrame(parent) ,d(new KoColorSetWidgetPrivate()) { d->thePublic = this; d->colorSet = 0; d->firstShowOfContainer = true; d->mainLayout = new QVBoxLayout(); d->mainLayout->setMargin(4); d->mainLayout->setSpacing(2); d->colorSetContainer = 0; d->numRecents = 0; d->recentsLayout = new QHBoxLayout(); d->mainLayout->addLayout(d->recentsLayout); d->recentsLayout->setMargin(0); d->recentsLayout->addWidget(new QLabel(i18n("Recent:"))); d->recentsLayout->addStretch(1); KoColor color(KoColorSpaceRegistry::instance()->rgb8()); color.fromQColor(QColor(128,0,0)); d->addRecent(color); d->scrollArea = new QScrollArea(); d->scrollArea->setBackgroundRole(QPalette::Dark); d->mainLayout->addWidget(d->scrollArea); d->colorNameCmb = new QComboBox(this); d->colorNameCmb->setEditable(true); d->colorNameCmb->setInsertPolicy(QComboBox::NoInsert); d->mainLayout->addWidget(d->colorNameCmb); d->fillColors(); d->addRemoveButton = new QToolButton(this); d->addRemoveButton->setText(i18n("Add / Remove Colors...")); d->addRemoveButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); connect(d->addRemoveButton, SIGNAL(clicked()), SLOT(addRemoveColors())); d->mainLayout->addWidget(d->addRemoveButton); setLayout(d->mainLayout); KoColorSet *colorSet = new KoColorSet(); d->colorSet = colorSet; d->fillColors(); } KoColorSetWidget::~KoColorSetWidget() { KoResourceServer* srv = KoResourceServerProvider::instance()->paletteServer(); QList palettes = srv->resources(); if (!palettes.contains(d->colorSet)) { delete d->colorSet; } delete d; } void KoColorSetWidget::KoColorSetWidgetPrivate::colorTriggered(KoColorPatch *patch) { int i; emit thePublic->colorChanged(patch->color(), true); colorNameCmb->setCurrentIndex(colornames.indexOf(QRegExp(patch->toolTip()+"|Fixed"))); for (i = 0; i color()); } void KoColorSetWidget::KoColorSetWidgetPrivate::setColorFromString(QString s) { int i = colornames.indexOf(QRegExp(s+"|Fixed")); i = qMax(i,0); colorTriggered(patchWidgetList.at(i)); } void KoColorSetWidget::setColorSet(QPointer colorSet) { if (!colorSet) return; if (colorSet == d->colorSet) return; KoResourceServer* srv = KoResourceServerProvider::instance()->paletteServer(); QList palettes = srv->resources(); if (!palettes.contains(d->colorSet)) { delete d->colorSet; } d->colorSet = colorSet; d->fillColors(); } KoColorSet* KoColorSetWidget::colorSet() { return d->colorSet; } void KoColorSetWidget::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) { if (displayRenderer) { d->displayRenderer = displayRenderer; Q_FOREACH(KoColorPatch *p, d->patchWidgetList) { p->setDisplayRenderer(displayRenderer); } for (int i=0; i<6; i++) { if (d->recentPatches[i]) { d->recentPatches[i]->setDisplayRenderer(displayRenderer); } } } } void KoColorSetWidget::resizeEvent(QResizeEvent *event) { emit widgetSizeChanged(event->size()); QFrame::resizeEvent(event); } //have to include this because of Q_PRIVATE_SLOT #include "moc_KoColorSetWidget.cpp" diff --git a/libs/widgets/KoEditColorSetDialog.cpp b/libs/widgets/KoEditColorSetDialog.cpp index 01bcb73b90..ce19ad921a 100644 --- a/libs/widgets/KoEditColorSetDialog.cpp +++ b/libs/widgets/KoEditColorSetDialog.cpp @@ -1,243 +1,243 @@ /* This file is part of the KDE project * Copyright (C) 2007 Fredy Yanardi * * 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 "KoEditColorSetDialog.h" #include #include #include #include #include #include #include #include #include #include #include #include // debug #include KoEditColorSetWidget::KoEditColorSetWidget(const QList &palettes, const QString &activePalette, QWidget *parent) : QWidget(parent), m_colorSets(palettes), m_gridLayout(0), m_activeColorSet(0), m_activePatch(0), m_initialColorSetCount(palettes.count()), m_activeColorSetRequested(false) { widget.setupUi(this); foreach (KoColorSet *colorSet, m_colorSets) { //colorSet->load(); resources are loaded at startup... widget.selector->addItem(colorSet->name()); } connect(widget.selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setActiveColorSet(int))); // A widget that shows all colors from active palette // FIXME no need to handcode the QScrollArea if designer can add QScrollArea (Qt 4.4?) m_scrollArea = new QScrollArea(widget.patchesFrame); int index = 0; foreach (KoColorSet *set, m_colorSets) { if (set->name() == activePalette) { m_activeColorSet = set; index = widget.selector->findText(set->name()); widget.selector->setCurrentIndex(index); } } if (!m_activeColorSet && !palettes.isEmpty()) { m_activeColorSet = palettes.first(); index = widget.selector->findText(m_activeColorSet->name()); } int columns = 16; if(m_activeColorSet) { columns = m_activeColorSet->columnCount(); if (columns==0){ columns = 16; } } m_scrollArea->setMinimumWidth(columns*(12+2)); QHBoxLayout *layout = new QHBoxLayout(); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(m_scrollArea); widget.patchesFrame->setLayout(layout); widget.add->setIcon(koIcon("list-add")); widget.remove->setIcon(koIcon("list-remove")); widget.open->setIcon(koIcon("document-open")); widget.save->setIcon(koIcon("document-save")); setEnabled(m_activeColorSet != 0); setActiveColorSet(index); widget.remove->setEnabled(false); // initially no color selected connect(widget.add, SIGNAL(clicked()), this, SLOT(addColor())); connect(widget.remove, SIGNAL(clicked()), this, SLOT(removeColor())); connect(widget.open, SIGNAL(clicked()), this, SLOT(open())); connect(widget.save, SIGNAL(clicked()), this, SLOT(save())); } KoEditColorSetWidget::~KoEditColorSetWidget() { // only delete new color sets uint colorSetCount = m_colorSets.count(); for( uint i = m_initialColorSetCount; i < colorSetCount; ++i ) { KoColorSet * cs = m_colorSets[i]; // if the active color set was requested by activeColorSet() // the caller takes ownership and then we do not delete it here if( cs == m_activeColorSet && m_activeColorSetRequested ) continue; delete cs; } } void KoEditColorSetWidget::setActiveColorSet(int index) { if (m_gridLayout) { qDeleteAll(m_gridLayout->children()); delete m_gridLayout; m_activePatch = 0; } QWidget *wdg = new QWidget(m_scrollArea); m_gridLayout = new QGridLayout(); m_gridLayout->setMargin(0); m_gridLayout->setSpacing(2); m_activeColorSet = m_colorSets.value(index); setEnabled(m_activeColorSet != 0); int columns = 16; if (m_activeColorSet) { columns = m_activeColorSet->columnCount(); if (columns==0){columns=16;} widget.remove->setEnabled(false); for (quint32 i = 0; i < m_activeColorSet->nColors(); i++) { KoColorPatch *patch = new KoColorPatch(widget.patchesFrame); KoColorSetEntry c = m_activeColorSet->getColorGlobal(i); - patch->setColor(c.color); - patch->setToolTip(c.name); + patch->setColor(c.color()); + patch->setToolTip(c.name()); connect(patch, SIGNAL(triggered(KoColorPatch *)), this, SLOT(setTextLabel(KoColorPatch *))); m_gridLayout->addWidget(patch, i/columns, i%columns); } } m_scrollArea->setMinimumWidth(columns*(12+2)); wdg->setLayout(m_gridLayout); m_scrollArea->setWidget(wdg); } void KoEditColorSetWidget::setTextLabel(KoColorPatch *patch) { widget.colorName->setText(patch->toolTip()); if (m_activePatch) { m_activePatch->setFrameShape(QFrame::NoFrame); m_activePatch->setFrameShadow(QFrame::Plain); } m_activePatch = patch; m_activePatch->setFrameShape(QFrame::Panel); m_activePatch->setFrameShadow(QFrame::Raised); widget.remove->setEnabled(true); } void KoEditColorSetWidget::addColor() { QColor color; color = QColorDialog::getColor(color); if (color.isValid()) { - KoColorSetEntry newEntry; - newEntry.color = KoColor(color, KoColorSpaceRegistry::instance()->rgb8()); - newEntry.name = QInputDialog::getText(this, i18n("Add Color To Palette"), i18n("Color name:")); + KoColorSetEntry newEntry( + KoColor(color, KoColorSpaceRegistry::instance()->rgb8()), + QInputDialog::getText(this, i18n("Add Color To Palette"), i18n("Color name:"))); KoColorPatch *patch = new KoColorPatch(widget.patchesFrame); - patch->setColor(newEntry.color); - patch->setToolTip(newEntry.name); + patch->setColor(newEntry.color()); + patch->setToolTip(newEntry.name()); connect(patch, SIGNAL(triggered(KoColorPatch *)), this, SLOT(setTextLabel(KoColorPatch *))); Q_ASSERT(m_gridLayout); Q_ASSERT(m_activeColorSet); m_gridLayout->addWidget(patch, m_activeColorSet->nColors()/m_activeColorSet->columnCount(), m_activeColorSet->nColors()%m_activeColorSet->columnCount()); m_activeColorSet->add(newEntry); } } void KoEditColorSetWidget::removeColor() { Q_ASSERT(m_activeColorSet); for (quint32 i = 0; i < m_activeColorSet->nColors(); i++) { KoColorSetEntry c = m_activeColorSet->getColorGlobal(i); - if (m_activePatch->color() == c.color) { + if (m_activePatch->color() == c.color()) { m_activeColorSet->removeAt(i); setActiveColorSet(widget.selector->currentIndex()); break; } } } void KoEditColorSetWidget::open() { Q_ASSERT(m_activeColorSet); KoFileDialog dialog(this, KoFileDialog::OpenFile, "OpenColorSet"); dialog.setDefaultDir(m_activeColorSet->filename()); dialog.setMimeTypeFilters(QStringList() << "application/x-gimp-color-palette"); QString fileName = dialog.filename(); KoColorSet *colorSet = new KoColorSet(fileName); colorSet->load(); m_colorSets.append(colorSet); widget.selector->addItem(colorSet->name()); widget.selector->setCurrentIndex(widget.selector->count() - 1); } void KoEditColorSetWidget::save() { Q_ASSERT(m_activeColorSet); if (!m_activeColorSet->save()) KMessageBox::error(0, i18n("Cannot write to palette file %1. Maybe it is read-only. ", m_activeColorSet->filename()), i18n("Palette")); } KoColorSet *KoEditColorSetWidget::activeColorSet() { m_activeColorSetRequested = true; return m_activeColorSet; } KoEditColorSetDialog::KoEditColorSetDialog(const QList &palettes, const QString &activePalette, QWidget *parent) : KoDialog(parent) { ui = new KoEditColorSetWidget(palettes, activePalette, this); setMainWidget(ui); setCaption(i18n("Add/Remove Colors")); enableButton(KoDialog::Ok, ui->isEnabled()); } KoEditColorSetDialog::~KoEditColorSetDialog() { delete ui; } KoColorSet *KoEditColorSetDialog::activeColorSet() { return ui->activeColorSet(); } diff --git a/plugins/dockers/palettedocker/palettedocker_dock.cpp b/plugins/dockers/palettedocker/palettedocker_dock.cpp index defae3400c..599b919a25 100644 --- a/plugins/dockers/palettedocker/palettedocker_dock.cpp +++ b/plugins/dockers/palettedocker/palettedocker_dock.cpp @@ -1,309 +1,309 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "palettedocker_dock.h" #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 "KisPaletteModel.h" #include "KisColorsetChooser.h" #include "ui_wdgpalettedock.h" #include "kis_palette_delegate.h" #include "kis_palette_view.h" PaletteDockerDock::PaletteDockerDock( ) : QDockWidget(i18n("Palette")) , m_wdgPaletteDock(new Ui_WdgPaletteDock()) , m_currentColorSet(0) , m_resourceProvider(0) , m_canvas(0) { QWidget* mainWidget = new QWidget(this); setWidget(mainWidget); m_wdgPaletteDock->setupUi(mainWidget); m_wdgPaletteDock->bnAdd->setIcon(KisIconUtils::loadIcon("list-add")); m_wdgPaletteDock->bnAdd->setIconSize(QSize(16, 16)); m_wdgPaletteDock->bnRemove->setIcon(KisIconUtils::loadIcon("edit-delete")); m_wdgPaletteDock->bnRemove->setIconSize(QSize(16, 16)); m_wdgPaletteDock->bnAdd->setEnabled(false); m_wdgPaletteDock->bnRemove->setEnabled(false); m_wdgPaletteDock->bnAddDialog->setVisible(false); m_wdgPaletteDock->bnAddGroup->setIcon(KisIconUtils::loadIcon("groupLayer")); m_wdgPaletteDock->bnAddGroup->setIconSize(QSize(16, 16)); m_model = new KisPaletteModel(this); m_wdgPaletteDock->paletteView->setPaletteModel(m_model); connect(m_wdgPaletteDock->bnAdd, SIGNAL(clicked(bool)), this, SLOT(addColorForeground())); connect(m_wdgPaletteDock->bnRemove, SIGNAL(clicked(bool)), this, SLOT(removeColor())); connect(m_wdgPaletteDock->bnAddGroup, SIGNAL(clicked(bool)), m_wdgPaletteDock->paletteView, SLOT(addGroupWithDialog())); connect(m_wdgPaletteDock->paletteView, SIGNAL(entrySelected(KoColorSetEntry)), this, SLOT(entrySelected(KoColorSetEntry))); connect(m_wdgPaletteDock->paletteView, SIGNAL(entrySelectedBackGround(KoColorSetEntry)), this, SLOT(entrySelectedBack(KoColorSetEntry))); KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(); m_serverAdapter = QSharedPointer(new KoResourceServerAdapter(rServer)); m_serverAdapter->connectToResourceServer(); rServer->addObserver(this); m_colorSetChooser = new KisColorsetChooser(this); connect(m_colorSetChooser, SIGNAL(paletteSelected(KoColorSet*)), this, SLOT(setColorSet(KoColorSet*))); m_wdgPaletteDock->bnColorSets->setIcon(KisIconUtils::loadIcon("hi16-palette_library")); m_wdgPaletteDock->bnColorSets->setToolTip(i18n("Choose palette")); m_wdgPaletteDock->bnColorSets->setPopupWidget(m_colorSetChooser); connect(m_wdgPaletteDock->cmbNameList, SIGNAL(currentIndexChanged(int)), this, SLOT(setColorFromNameList(int))); KisConfig cfg; QString defaultPalette = cfg.defaultPalette(); KoColorSet* defaultColorSet = rServer->resourceByName(defaultPalette); if (defaultColorSet) { setColorSet(defaultColorSet); } } PaletteDockerDock::~PaletteDockerDock() { KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(); rServer->removeObserver(this); if (m_currentColorSet) { KisConfig cfg; cfg.setDefaultPalette(m_currentColorSet->name()); } delete m_wdgPaletteDock->paletteView->itemDelegate(); delete m_wdgPaletteDock; } void PaletteDockerDock::setMainWindow(KisViewManager* kisview) { m_resourceProvider = kisview->resourceProvider(); connect(m_resourceProvider, SIGNAL(sigSavingWorkspace(KisWorkspaceResource*)), SLOT(saveToWorkspace(KisWorkspaceResource*))); connect(m_resourceProvider, SIGNAL(sigLoadingWorkspace(KisWorkspaceResource*)), SLOT(loadFromWorkspace(KisWorkspaceResource*))); connect(m_resourceProvider, SIGNAL(sigFGColorChanged(KoColor)),m_wdgPaletteDock->paletteView, SLOT(trySelectClosestColor(KoColor))); kisview->nodeManager()->disconnect(m_model); } void PaletteDockerDock::setCanvas(KoCanvasBase *canvas) { setEnabled(canvas != 0); if (canvas) { KisCanvas2 *cv = qobject_cast(canvas); m_model->setDisplayRenderer(cv->displayColorConverter()->displayRendererInterface()); } m_canvas = static_cast(canvas); } void PaletteDockerDock::unsetCanvas() { setEnabled(false); m_model->setDisplayRenderer(0); m_canvas = 0; } void PaletteDockerDock::unsetResourceServer() { KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(); rServer->removeObserver(this); } void PaletteDockerDock::removingResource(KoColorSet *resource) { if (resource == m_currentColorSet) { setColorSet(0); } } void PaletteDockerDock::resourceChanged(KoColorSet *resource) { setColorSet(resource); } void PaletteDockerDock::setColorSet(KoColorSet* colorSet) { m_model->setColorSet(colorSet); m_wdgPaletteDock->paletteView->updateView(); m_wdgPaletteDock->paletteView->updateRows(); m_wdgPaletteDock->cmbNameList->clear(); if (colorSet && colorSet->nColors()>0) { for (quint32 i = 0; i< colorSet->nColors(); i++) { KoColorSetEntry entry = colorSet->getColorGlobal(i); QPixmap colorSquare = QPixmap(32, 32); - if (entry.spotColor) { + if (entry.spotColor()) { QImage img = QImage(32, 32, QImage::Format_ARGB32); QPainter circlePainter; img.fill(Qt::transparent); circlePainter.begin(&img); QBrush brush = QBrush(Qt::SolidPattern); - brush.setColor(entry.color.toQColor()); + brush.setColor(entry.color().toQColor()); circlePainter.setBrush(brush); QPen pen = circlePainter.pen(); pen.setColor(Qt::transparent); pen.setWidth(0); circlePainter.setPen(pen); circlePainter.drawEllipse(0, 0, 32, 32); circlePainter.end(); colorSquare = QPixmap::fromImage(img); } else { - colorSquare.fill(entry.color.toQColor()); + colorSquare.fill(entry.color().toQColor()); } - QString name = entry.name; - if (!entry.id.isEmpty()){ - name = entry.id + " - " + entry.name; + QString name = entry.name(); + if (!entry.id().isEmpty()){ + name = entry.id() + " - " + entry.name(); } m_wdgPaletteDock->cmbNameList->addSqueezedItem(QIcon(colorSquare), name); } } QCompleter *completer = new QCompleter(m_wdgPaletteDock->cmbNameList->model()); completer->setCompletionMode(QCompleter::PopupCompletion); completer->setCaseSensitivity(Qt::CaseInsensitive); completer->setFilterMode(Qt::MatchContains); m_wdgPaletteDock->cmbNameList->setCompleter(completer); if (colorSet && colorSet->removable()) { m_wdgPaletteDock->bnAdd->setEnabled(true); m_wdgPaletteDock->bnRemove->setEnabled(true); } else { m_wdgPaletteDock->bnAdd->setEnabled(false); m_wdgPaletteDock->bnRemove->setEnabled(false); } m_currentColorSet = colorSet; } void PaletteDockerDock::setColorFromNameList(int index) { if (m_model && m_currentColorSet) { entrySelected(m_currentColorSet->getColorGlobal(index)); m_wdgPaletteDock->paletteView->blockSignals(true); m_wdgPaletteDock->cmbNameList->blockSignals(true); m_wdgPaletteDock->cmbNameList->setCurrentIndex(index); m_wdgPaletteDock->paletteView->selectionModel()->clearSelection(); m_wdgPaletteDock->paletteView->selectionModel()->setCurrentIndex(m_model->indexFromId(index), QItemSelectionModel::Select); m_wdgPaletteDock->paletteView->blockSignals(false); m_wdgPaletteDock->cmbNameList->blockSignals(false); } } void PaletteDockerDock::addColorForeground() { if (m_resourceProvider) { //setup dialog m_wdgPaletteDock->paletteView->addEntryWithDialog(m_resourceProvider->fgColor()); } } void PaletteDockerDock::removeColor() { QModelIndex index = m_wdgPaletteDock->paletteView->currentIndex(); if (!index.isValid()) { return; } m_wdgPaletteDock->paletteView->removeEntryWithDialog(index); } void PaletteDockerDock::entrySelected(KoColorSetEntry entry) { if (m_wdgPaletteDock->paletteView->currentIndex().isValid()) { quint32 index = m_model->idFromIndex(m_wdgPaletteDock->paletteView->currentIndex()); m_wdgPaletteDock->cmbNameList->setCurrentIndex(index); } if (m_resourceProvider) { - m_resourceProvider->setFGColor(entry.color); + m_resourceProvider->setFGColor(entry.color()); } if (m_currentColorSet->removable()) { m_wdgPaletteDock->bnRemove->setEnabled(true); } } void PaletteDockerDock::entrySelectedBack(KoColorSetEntry entry) { if (m_wdgPaletteDock->paletteView->currentIndex().isValid()) { quint32 index = m_model->idFromIndex(m_wdgPaletteDock->paletteView->currentIndex()); m_wdgPaletteDock->cmbNameList->setCurrentIndex(index); } if (m_resourceProvider) { - m_resourceProvider->setBGColor(entry.color); + m_resourceProvider->setBGColor(entry.color()); } if (m_currentColorSet->removable()) { m_wdgPaletteDock->bnRemove->setEnabled(true); } } void PaletteDockerDock::saveToWorkspace(KisWorkspaceResource* workspace) { if (m_currentColorSet) { workspace->setProperty("palette", m_currentColorSet->name()); } } void PaletteDockerDock::loadFromWorkspace(KisWorkspaceResource* workspace) { if (workspace->hasProperty("palette")) { KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(); KoColorSet* colorSet = rServer->resourceByName(workspace->getString("palette")); if (colorSet) { setColorSet(colorSet); } } } diff --git a/plugins/extensions/pykrita/sip/krita/Palette.sip b/plugins/extensions/pykrita/sip/krita/Palette.sip index f32fc47b9a..4780b3c65c 100644 --- a/plugins/extensions/pykrita/sip/krita/Palette.sip +++ b/plugins/extensions/pykrita/sip/krita/Palette.sip @@ -1,45 +1,48 @@ +/* struct KoColorSetEntry { %TypeHeaderCode #include "KoColorSet.h" %End public: KoColorSetEntry(); QString name; QString id; bool spotColor; bool operator==(const KoColorSetEntry& rhs) const; }; +*/ +class KoColorSetEntry; class Palette : QObject { %TypeHeaderCode #include "Palette.h" %End Palette(const Palette & __0); public: Palette(Resource *resource); int numberOfEntries() const; int columnCount(); void setColumnCount(int columns); QString comment(); void setComment(QString comment); QStringList groupNames(); bool addGroup(QString name); bool removeGroup(QString name, bool keepColors); int colorsCountTotal(); int colorsCountGroup(QString name); KoColorSetEntry colorSetEntryByIndex(int index); KoColorSetEntry colorSetEntryFromGroup(int index, const QString &groupName); ManagedColor *colorForEntry(KoColorSetEntry entry) /Factory/; void addEntry(KoColorSetEntry entry, QString groupName); void removeEntry(int index, const QString &groupName); void insertEntry(int index, KoColorSetEntry entry, QString groupName); bool editEntry(int index, KoColorSetEntry entry, QString groupName); bool changeGroupName(QString oldGroupName, QString newGroupName); bool moveGroup(const QString &groupName, const QString &groupNameInsertBefore); bool save(); private: }; diff --git a/plugins/python/palette_docker/palette_docker.py b/plugins/python/palette_docker/palette_docker.py index 8ccbb248fd..f097b33b63 100644 --- a/plugins/python/palette_docker/palette_docker.py +++ b/plugins/python/palette_docker/palette_docker.py @@ -1,259 +1,259 @@ ''' Description: A Python based docker that allows you to edit KPL color palettes. By Wolthera(originally) This script is licensed CC 0 1.0, so that you can learn from it. ------ CC 0 1.0 --------------- The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. https://creativecommons.org/publicdomain/zero/1.0/legalcode @package palette_docker ''' # Importing the relevant dependencies: import sys from PyQt5.QtGui import QPixmap, QIcon, QImage, QPainter, QBrush, QPalette from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QComboBox, QAction, QTabWidget, QLineEdit, QSpinBox, QDialogButtonBox, QToolButton, QDialog, QPlainTextEdit, QCompleter, QMenu from PyQt5.Qt import Qt, pyqtSignal, pyqtSlot import math from krita import * # import the exporters from . import palette_exporter_gimppalette, palette_exporter_inkscapeSVG, palette_sortColors class Palette_Docker(DockWidget): # Init the docker def __init__(self): super(Palette_Docker, self).__init__() # make base-widget and layout widget = QWidget() layout = QVBoxLayout() buttonLayout = QHBoxLayout() widget.setLayout(layout) self.setWindowTitle("Python Palette Docker") # Make a combobox and add palettes self.cmb_palettes = QComboBox() allPalettes = Application.resources("palette") for palette_name in allPalettes: self.cmb_palettes.addItem(palette_name) self.cmb_palettes.model().sort(0) if len(allPalettes.keys()) > 0: self.currentPalette = Palette(allPalettes[list(allPalettes.keys())[0]]) else: self.currentPalette = None self.cmb_palettes.currentTextChanged.connect(self.slot_paletteChanged) layout.addWidget(self.cmb_palettes) # add combobox to the layout self.paletteView = PaletteView() self.paletteView.setPalette(self.currentPalette) layout.addWidget(self.paletteView) self.paletteView.entrySelectedForeGround.connect(self.slot_swatchSelected) self.colorComboBox = QComboBox() self.colorList = list() buttonLayout.addWidget(self.colorComboBox) self.addEntry = QAction(self) self.addEntry.setIconText("+") self.addEntry.triggered.connect(self.slot_add_entry) self.addGroup = QAction(self) self.addGroup.triggered.connect(self.slot_add_group) self.addGroup.setText("Add Group") self.addGroup.setIconText(str("\U0001F4C2")) self.removeEntry = QAction(self) self.removeEntry.setText("Remove Entry") self.removeEntry.setIconText("-") self.removeEntry.triggered.connect(self.slot_remove_entry) addEntryButton = QToolButton() addEntryButton.setDefaultAction(self.addEntry) buttonLayout.addWidget(addEntryButton) addGroupButton = QToolButton() addGroupButton.setDefaultAction(self.addGroup) buttonLayout.addWidget(addGroupButton) removeEntryButton = QToolButton() removeEntryButton.setDefaultAction(self.removeEntry) buttonLayout.addWidget(removeEntryButton) # QActions self.extra = QToolButton() self.editPaletteData = QAction(self) self.editPaletteData.setText("Edit Palette Settings") self.editPaletteData.triggered.connect(self.slot_edit_palette_data) self.extra.setDefaultAction(self.editPaletteData) buttonLayout.addWidget(self.extra) self.actionMenu = QMenu() self.exportToGimp = QAction(self) self.exportToGimp.setText("Export as GIMP palette file.") self.exportToGimp.triggered.connect(self.slot_export_to_gimp_palette) self.exportToInkscape = QAction(self) self.exportToInkscape.setText("Export as Inkscape SVG with swatches.") self.exportToInkscape.triggered.connect(self.slot_export_to_inkscape_svg) self.sortColors = QAction(self) self.sortColors.setText("Sort colors") self.sortColors.triggered.connect(self.slot_sort_colors) self.actionMenu.addAction(self.editPaletteData) self.actionMenu.addAction(self.exportToGimp) self.actionMenu.addAction(self.exportToInkscape) # self.actionMenu.addAction(self.sortColors) self.extra.setMenu(self.actionMenu) layout.addLayout(buttonLayout) self.slot_fill_combobox() self.setWidget(widget) # add widget to the docker def slot_paletteChanged(self, name): allPalettes = Application.resources("palette") if len(allPalettes) > 0 and name in allPalettes: self.currentPalette = Palette(Application.resources("palette")[name]) self.paletteView.setPalette(self.currentPalette) self.slot_fill_combobox() - @pyqtSlot('KoColorSetEntry') + @pyqtSlot('PaletteEntry') def slot_swatchSelected(self, entry): - print("entry " + entry.name) + print("entry " + entry.name()) if (self.canvas()) is not None: if (self.canvas().view()) is not None: - name = entry.name + name = entry.name() if len(entry.id) > 0: - name = entry.id + " - " + entry.name + name = entry.id() + " - " + entry.name() if len(name) > 0: if name in self.colorList: self.colorComboBox.setCurrentIndex(self.colorList.index(name)) color = self.currentPalette.colorForEntry(entry) self.canvas().view().setForeGroundColor(color) ''' A function for making a combobox with the available colors. We use QCompleter on the colorComboBox so that people can type in the name of a color to select it. This is useful for people with carefully made palettes where the colors are named properly, which makes it easier for them to find colors. ''' def slot_fill_combobox(self): if self.currentPalette is None: pass palette = self.currentPalette self.colorComboBox.clear() self.colorList = list() for i in range(palette.colorsCountTotal()): entry = palette.colorSetEntryByIndex(i) color = palette.colorForEntry(entry).colorForCanvas(self.canvas()) colorSquare = QPixmap(12, 12) - if entry.spotColor is True: + if entry.spotColor() is True: img = colorSquare.toImage() circlePainter = QPainter() img.fill(self.colorComboBox.palette().color(QPalette.Base)) circlePainter.begin(img) brush = QBrush(Qt.SolidPattern) brush.setColor(color) circlePainter.setBrush(brush) circlePainter.pen().setWidth(0) circlePainter.drawEllipse(0, 0, 11, 11) circlePainter.end() colorSquare = QPixmap.fromImage(img) else: colorSquare.fill(color) - name = entry.name - if len(entry.id) > 0: - name = entry.id + " - " + entry.name + name = entry.name() + if len(entry.id()) > 0: + name = entry.id() + " - " + entry.name() self.colorList.append(name) self.colorComboBox.addItem(QIcon(colorSquare), name) self.colorComboBox.setEditable(True) self.colorComboBox.setInsertPolicy(QComboBox.NoInsert) self.colorComboBox.completer().setCompletionMode(QCompleter.PopupCompletion) self.colorComboBox.completer().setCaseSensitivity(False) self.colorComboBox.completer().setFilterMode(Qt.MatchContains) self.colorComboBox.currentIndexChanged.connect(self.slot_get_color_from_combobox) def slot_get_color_from_combobox(self): if self.currentPalette is not None: entry = self.currentPalette.colorSetEntryByIndex(self.colorComboBox.currentIndex()) self.slot_swatchSelected(entry) def slot_add_entry(self): if (self.canvas()) is not None: if (self.canvas().view()) is not None: color = self.canvas().view().foregroundColor() success = self.paletteView.addEntryWithDialog(color) if success is True: self.slot_fill_combobox() def slot_add_group(self): success = self.paletteView.addGroupWithDialog() if success is True: self.slot_fill_combobox() def slot_remove_entry(self): success = self.paletteView.removeSelectedEntryWithDialog() if success is True: self.slot_fill_combobox() ''' A function for giving a gui to edit palette metadata... I also want this to be the way to edit the settings of the palette docker. ''' def slot_edit_palette_data(self): dialog = QDialog(self) tabWidget = QTabWidget() dialog.setWindowTitle("Edit Palette Data") dialog.setLayout(QVBoxLayout()) dialog.layout().addWidget(tabWidget) paletteWidget = QWidget() paletteWidget.setLayout(QVBoxLayout()) tabWidget.addTab(paletteWidget, "Palette Data") paletteName = QLineEdit() paletteName.setText(self.cmb_palettes.currentText()) paletteWidget.layout().addWidget(paletteName) paletteColumns = QSpinBox() paletteColumns.setValue(self.currentPalette.columnCount()) paletteWidget.layout().addWidget(paletteColumns) paletteComment = QPlainTextEdit() paletteComment.appendPlainText(self.currentPalette.comment()) paletteWidget.layout().addWidget(paletteComment) buttons = QDialogButtonBox(QDialogButtonBox.Ok) dialog.layout().addWidget(buttons) buttons.accepted.connect(dialog.accept) # buttons.rejected.connect(dialog.reject()) if dialog.exec_() == QDialog.Accepted: Resource = Application.resources("palette")[self.cmb_palettes.currentText()] Resource.setName(paletteName.text()) self.currentPalette = Palette(Resource) print(paletteColumns.value()) self.currentPalette.setColumnCount(paletteColumns.value()) self.paletteView.setPalette(self.currentPalette) self.slot_fill_combobox() self.currentPalette.setComment(paletteComment.toPlainText()) self.currentPalette.save() def slot_export_to_gimp_palette(self): palette_exporter_gimppalette.gimpPaletteExporter(self.cmb_palettes.currentText()) def slot_export_to_inkscape_svg(self): palette_exporter_inkscapeSVG.inkscapeSVGExporter(self.cmb_palettes.currentText()) def slot_sort_colors(self): colorSorter = palette_sortColors.sortColors(self.cmb_palettes.currentText()) self.paletteView.setPalette(colorSorter.palette()) def canvasChanged(self, canvas): self.cmb_palettes.clear() allPalettes = Application.resources("palette") for palette_name in allPalettes: self.cmb_palettes.addItem(palette_name) self.cmb_palettes.model().sort(0) if self.currentPalette == None and len(allPalettes.keys()) > 0: self.currentPalette = Palette(allPalettes[list(allPalettes.keys())[0]]) # Add docker to the application :) Application.addDockWidgetFactory(DockWidgetFactory("palette_docker", DockWidgetFactoryBase.DockRight, Palette_Docker)) diff --git a/plugins/python/palette_docker/palette_exporter_gimppalette.py b/plugins/python/palette_docker/palette_exporter_gimppalette.py index e5f4f6c020..c0f7091f66 100644 --- a/plugins/python/palette_docker/palette_exporter_gimppalette.py +++ b/plugins/python/palette_docker/palette_exporter_gimppalette.py @@ -1,73 +1,73 @@ ''' A script that converts the palette with the given name to a gimp palette at the location asked for. By Wolthera(originally) This script is licensed CC 0 1.0, so that you can learn from it. ------ CC 0 1.0 --------------- The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. https://creativecommons.org/publicdomain/zero/1.0/legalcode @package palette_docker ''' # Importing the relevant dependencies: import sys from PyQt5.QtWidgets import QFileDialog, QMessageBox import math from krita import * class gimpPaletteExporter: def __init__(self, name): # We want people to select a palette and a location to save to... self.fileName = QFileDialog.getExistingDirectory() allPalettes = Application.resources("palette") self.paletteName = name self.currentPalette = Palette(allPalettes[self.paletteName]) self.export() done = QMessageBox() done.setWindowTitle("Export successful") done.setText(self.paletteName + " has been exported to " + self.fileName + "!") done.exec_() pass def export(self): # open the appropriate file... gplFile = open(self.fileName + "/" + self.paletteName + ".gpl", "w") gplFile.write("GIMP Palette\n") gplFile.write("Name: " + self.paletteName + "\n") gplFile.write("Columns: " + str(self.currentPalette.columnCount()) + "\n") gplFile.write("#" + self.currentPalette.comment() + "\n") colorCount = self.currentPalette.colorsCountGroup("") for i in range(colorCount): entry = self.currentPalette.colorSetEntryFromGroup(i, "") color = self.currentPalette.colorForEntry(entry) # convert to sRGB color.setColorSpace("RGBA", "U8", "sRGB built-in") red = max(min(int(color.componentsOrdered()[0] * 255), 255), 0) green = max(min(int(color.componentsOrdered()[1] * 255), 255), 0) blue = max(min(int(color.componentsOrdered()[2] * 255), 255), 0) - gplFile.write(str(red) + " " + str(green) + " " + str(blue) + " " + entry.id + "-" + entry.name + "\n") + gplFile.write(str(red) + " " + str(green) + " " + str(blue) + " " + entry.id() + "-" + entry.name() + "\n") groupNames = self.currentPalette.groupNames() for groupName in groupNames: colorCount = self.currentPalette.colorsCountGroup(groupName) for i in range(colorCount): entry = self.currentPalette.colorSetEntryFromGroup(i, groupName) color = self.currentPalette.colorForEntry(entry) # convert to sRGB color.setColorSpace("RGBA", "U8", "sRGB built-in") red = max(min(int(color.componentsOrdered()[0] * 255), 255), 0) green = max(min(int(color.componentsOrdered()[1] * 255), 255), 0) blue = max(min(int(color.componentsOrdered()[2] * 255), 255), 0) - gplFile.write(str(red) + " " + str(green) + " " + str(blue) + " " + entry.id + "-" + entry.name + "\n") + gplFile.write(str(red) + " " + str(green) + " " + str(blue) + " " + entry.id() + "-" + entry.name() + "\n") gplFile.close() diff --git a/plugins/python/palette_docker/palette_exporter_inkscapeSVG.py b/plugins/python/palette_docker/palette_exporter_inkscapeSVG.py index 4e92bd5735..913600db37 100644 --- a/plugins/python/palette_docker/palette_exporter_inkscapeSVG.py +++ b/plugins/python/palette_docker/palette_exporter_inkscapeSVG.py @@ -1,186 +1,186 @@ ''' A script that converts the palette named "Default" to a SVG so that Inkscape may use the colors The icc-color stuff doesn't work right, because we'd need the ability to get the url of the colorprofile somehow, and then we can make color-profile things in the definitions. By Wolthera(originally) This script is licensed CC 0 1.0, so that you can learn from it. ------ CC 0 1.0 --------------- The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. https://creativecommons.org/publicdomain/zero/1.0/legalcode @package palette_docker ''' # Importing the relevant dependencies: import sys from PyQt5.QtXml import QDomDocument from PyQt5.QtWidgets import QFileDialog, QMessageBox import math from krita import * class inkscapeSVGExporter: def __init__(self, name): # We want people to select a palette and a location to save to... self.fileName = QFileDialog.getExistingDirectory() allPalettes = Application.resources("palette") self.paletteName = name self.currentPalette = Palette(allPalettes[self.paletteName]) self.export() done = QMessageBox() done.setWindowTitle("Export successful") done.setText(self.paletteName + " has been exported to " + self.fileName + "!") done.exec_() pass def export(self): # open the appropriate file... svgFile = open(self.fileName + "/" + self.paletteName + ".svg", "w") svgDoc = QDomDocument() svgBaseElement = svgDoc.createElement("svg") svgBaseElement.setAttribute("xmlns:osb", "http://www.openswatchbook.org/uri/2009/osb") svgBaseElement.setAttribute("xmlns:svg", "http://www.w3.org/2000/svg") svgBaseElement.setAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/") svgBaseElement.setAttribute("xmlns:cc", "http://creativecommons.org/ns#") svgBaseElement.setAttribute("xmlns:rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#") svgDefs = svgDoc.createElement("defs") svgSwatches = svgDoc.createElement("g") svgSwatches.setAttribute("id", "Swatches") svgMeta = svgDoc.createElement("metadata") svgBaseElement.appendChild(svgMeta) rdf = svgDoc.createElement("rdf:RDF") ccwork = svgDoc.createElement("cc:Work") dctitle = svgDoc.createElement("dc:title") dcdescription = svgDoc.createElement("dc:description") dctitle.appendChild(svgDoc.createTextNode(self.paletteName)) dcdescription.appendChild(svgDoc.createTextNode(self.currentPalette.comment())) ccwork.appendChild(dctitle) ccwork.appendChild(dcdescription) rdf.appendChild(ccwork) svgMeta.appendChild(rdf) Row = 0 Column = 0 iccProfileList = [] colorCount = self.currentPalette.colorsCountGroup("") for i in range(colorCount): entry = self.currentPalette.colorSetEntryFromGroup(i, "") color = self.currentPalette.colorForEntry(entry) iccColor = "icc-color(" + color.colorProfile() for c in range(len(color.componentsOrdered()) - 1): iccColor = iccColor + "," + str(color.componentsOrdered()[c]) iccColor = iccColor + ")" if color.colorProfile() not in iccProfileList: iccProfileList.append(color.colorProfile()) # convert to sRGB color.setColorSpace("RGBA", "U8", "sRGB built-in") red = max(min(int(color.componentsOrdered()[0] * 255), 255), 0) green = max(min(int(color.componentsOrdered()[1] * 255), 255), 0) blue = max(min(int(color.componentsOrdered()[2] * 255), 255), 0) hexcode = "#" + str(format(red, '02x')) + str(format(green, '02x')) + str(format(blue, '02x')) - swatchName = str(i) + "-" + entry.name + swatchName = str(i) + "-" + entry.name() swatchName = swatchName.replace(" ", "-") swatchName = swatchName.replace("(", "-") swatchName = swatchName.replace(")", "-") swatchMain = svgDoc.createElement("linearGradient") swatchMain.setAttribute("osb:paint", "solid") swatchMain.setAttribute("id", swatchName) swatchSub = svgDoc.createElement("stop") swatchSub.setAttribute("style", "stop-color: " + hexcode + " " + iccColor + ";stop-opacity:1;") swatchMain.appendChild(swatchSub) svgDefs.appendChild(swatchMain) svgSingleSwatch = svgDoc.createElement("rect") svgSingleSwatch.setAttribute("x", str(int(Column * 20))) svgSingleSwatch.setAttribute("y", str(int(Row * 20))) svgSingleSwatch.setAttribute("width", str(int(20))) svgSingleSwatch.setAttribute("height", str(int(20))) svgSingleSwatch.setAttribute("fill", "url(#" + swatchName + ")") svgSingleSwatch.setAttribute("id", "swatch" + swatchName) - if entry.spotColor is True: + if entry.spotColor() is True: svgSingleSwatch.setAttribute("rx", str(10)) svgSingleSwatch.setAttribute("ry", str(10)) svgSwatches.appendChild(svgSingleSwatch) Column += 1 if (Column >= self.currentPalette.columnCount()): Column = 0 Row += 1 groupNames = self.currentPalette.groupNames() for groupName in groupNames: Column = 0 Row += 1 groupTitle = svgDoc.createElement("text") groupTitle.setAttribute("x", str(int(Column * 20))) groupTitle.setAttribute("y", str(int(Row * 20) + 15)) groupTitle.appendChild(svgDoc.createTextNode(groupName)) svgSwatches.appendChild(groupTitle) Row += 1 colorCount = self.currentPalette.colorsCountGroup(groupName) for i in range(colorCount): entry = self.currentPalette.colorSetEntryFromGroup(i, groupName) color = self.currentPalette.colorForEntry(entry) iccColor = "icc-color(" + color.colorProfile() for c in range(len(color.componentsOrdered()) - 1): iccColor = iccColor + "," + str(color.componentsOrdered()[c]) iccColor = iccColor + ")" if color.colorProfile() not in iccProfileList: iccProfileList.append(color.colorProfile()) # convert to sRGB color.setColorSpace("RGBA", "U8", "sRGB built-in") red = max(min(int(color.componentsOrdered()[0] * 255), 255), 0) green = max(min(int(color.componentsOrdered()[1] * 255), 255), 0) blue = max(min(int(color.componentsOrdered()[2] * 255), 255), 0) hexcode = "#" + str(format(red, '02x')) + str(format(green, '02x')) + str(format(blue, '02x')) - swatchName = groupName + str(i) + "-" + entry.name + swatchName = groupName + str(i) + "-" + entry.name() swatchName = swatchName.replace(" ", "-") swatchName = swatchName.replace("(", "-") swatchName = swatchName.replace(")", "-") swatchMain = svgDoc.createElement("linearGradient") swatchMain.setAttribute("osb:paint", "solid") swatchMain.setAttribute("id", swatchName) swatchSub = svgDoc.createElement("stop") swatchSub.setAttribute("style", "stop-color: " + hexcode + " " + iccColor + ";stop-opacity:1;") swatchMain.appendChild(swatchSub) svgDefs.appendChild(swatchMain) svgSingleSwatch = svgDoc.createElement("rect") svgSingleSwatch.setAttribute("x", str(int(Column * 20))) svgSingleSwatch.setAttribute("y", str(int(Row * 20))) svgSingleSwatch.setAttribute("width", str(int(20))) svgSingleSwatch.setAttribute("height", str(int(20))) svgSingleSwatch.setAttribute("fill", "url(#" + swatchName + ")") svgSingleSwatch.setAttribute("id", "swatch " + swatchName) - if entry.spotColor is True: + if entry.spotColor() is True: svgSingleSwatch.setAttribute("rx", str(10)) svgSingleSwatch.setAttribute("ry", str(10)) svgSwatches.appendChild(svgSingleSwatch) Column += 1 if (Column >= self.currentPalette.columnCount()): Column = 0 Row += 1 for profile in iccProfileList: svgProfileDesc = svgDoc.createElement("color-profile") svgProfileDesc.setAttribute("name", profile) # This is incomplete because python api doesn't have any way to ask for this data yet. # svgProfileDesc.setAttribute("local", "sRGB") # svgProfileDesc.setAttribute("xlink:href", colorprofileurl) svgProfileDesc.setAttribute("rendering-intent", "perceptual") svgDefs.appendChild(svgProfileDesc) svgBaseElement.appendChild(svgDefs) svgBaseElement.appendChild(svgSwatches) svgBaseElement.setAttribute("viewBox", "0 0 " + str(self.currentPalette.columnCount() * 20) + " " + str(int((Row + 1) * 20))) svgDoc.appendChild(svgBaseElement) svgFile.write(svgDoc.toString()) svgFile.close() diff --git a/plugins/python/palette_docker/palette_sortColors.py b/plugins/python/palette_docker/palette_sortColors.py index d497a09d46..304ff9d6eb 100644 --- a/plugins/python/palette_docker/palette_sortColors.py +++ b/plugins/python/palette_docker/palette_sortColors.py @@ -1,78 +1,78 @@ ''' A script that sorts the colors in the group. By Wolthera(originally) This script is licensed CC 0 1.0, so that you can learn from it. ------ CC 0 1.0 --------------- The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. https://creativecommons.org/publicdomain/zero/1.0/legalcode @package palette_docker ''' # Importing the relevant dependencies: from krita import * class sortColors(object): def __init__(self, name): # We want people to select a palette... allPalettes = Application.resources("palette") self.paletteName = name self.currentPalette = Palette(allPalettes[self.paletteName]) self.sort_all_groups() def sort_all_groups(self): self.sort_color_by_name(str()) groupNames = self.currentPalette.groupNames() for groupName in groupNames: self.sort_color_by_name(groupName) def sort_color_by_name(self, groupName): l = {} colorCount = self.currentPalette.colorsCountGroup(groupName) for i in range(colorCount - 1, -1, -1): entry = self.currentPalette.colorSetEntryFromGroup((i), groupName) l[entry.name + str(i)] = entry self.currentPalette.removeEntry((i), groupName) for s in sorted(l): self.currentPalette.addEntry(l[s], groupName) def sort_color_by_id(self, groupName): l = {} colorCount = self.currentPalette.colorsCountGroup(groupName) for i in range(colorCount - 1, -1, -1): entry = self.currentPalette.colorSetEntryFromGroup((i), groupName) - l[entry.id + " " + str(i)] = entry + l[entry.id() + " " + str(i)] = entry self.currentPalette.removeEntry((i), groupName) for s in sorted(l): self.currentPalette.addEntry(l[s], groupName) def sort_by_value(self, groupName): l = {} colorCount = self.currentPalette.colorsCountGroup(groupName) for i in range(colorCount - 1, -1, -1): entry = self.currentPalette.colorSetEntryFromGroup((i), groupName) color = self.currentPalette.colorForEntry(entry) color.setColorSpace("RGBA", "U8", "sRGB built-in") l[color.components()[0] + color.components()[1] + color.components()[2]] = entry self.currentPalette.removeEntry((i), groupName) for s in sorted(l): self.currentPalette.addEntry(l[s], groupName) def sort_by_hue(self, stepsize, groupName): pass def palette(self): return self.currentPalette diff --git a/plugins/tools/basictools/kis_tool_colorpicker.cc b/plugins/tools/basictools/kis_tool_colorpicker.cc index c79eea2d94..d5d981ffc0 100644 --- a/plugins/tools/basictools/kis_tool_colorpicker.cc +++ b/plugins/tools/basictools/kis_tool_colorpicker.cc @@ -1,350 +1,350 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2002 Patrick Julien * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2018 Emmet & Eoin O'Neill * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_colorpicker.h" #include #include #include "kis_cursor.h" #include "KisDocument.h" #include "kis_canvas2.h" #include "KisReferenceImagesLayer.h" #include "KoCanvasBase.h" #include "kis_random_accessor_ng.h" #include "KoResourceServerProvider.h" #include #include "kis_wrapped_rect.h" #include "kis_tool_utils.h" namespace { // GUI ComboBox index constants const int SAMPLE_MERGED = 0; } KisToolColorPicker::KisToolColorPicker(KoCanvasBase *canvas) : KisTool(canvas, KisCursor::pickerCursor()), m_config(new KisToolUtils::ColorPickerConfig) { setObjectName("tool_colorpicker"); m_isActivated = false; m_optionsWidget = 0; m_pickedColor = KoColor(); } KisToolColorPicker::~KisToolColorPicker() { if (m_isActivated) { m_config->save(m_toolActivationSource == KisTool::DefaultActivation); } } void KisToolColorPicker::paint(QPainter &gc, const KoViewConverter &converter) { Q_UNUSED(gc); Q_UNUSED(converter); } void KisToolColorPicker::activate(ToolActivation activation, const QSet &shapes) { m_isActivated = true; m_toolActivationSource = activation; m_config->load(m_toolActivationSource == KisTool::DefaultActivation); updateOptionWidget(); KisTool::activate(activation, shapes); } void KisToolColorPicker::deactivate() { m_config->save(m_toolActivationSource == KisTool::DefaultActivation); m_isActivated = false; KisTool::deactivate(); } void KisToolColorPicker::pickColor(const QPointF &pos) { // Timer check. if (m_colorPickerDelayTimer.isActive()) { return; } else { m_colorPickerDelayTimer.setSingleShot(true); m_colorPickerDelayTimer.start(100); } QScopedPointer> imageLocker; m_pickedColor.setOpacity(0.0); // Pick from reference images. if (m_optionsWidget->cmbSources->currentIndex() == SAMPLE_MERGED) { auto *kisCanvas = dynamic_cast(canvas()); KIS_SAFE_ASSERT_RECOVER_RETURN(kisCanvas); KisReferenceImagesLayer *referenceImageLayer = kisCanvas->imageView()->document()->referenceImagesLayer(); if (referenceImageLayer) { QColor color = referenceImageLayer->getPixel(pos); if (color.isValid()) { m_pickedColor.fromQColor(color); } } } if (m_pickedColor.opacityU8() == OPACITY_TRANSPARENT_U8) { KisPaintDeviceSP dev; if (m_optionsWidget->cmbSources->currentIndex() != SAMPLE_MERGED && currentNode() && currentNode()->colorPickSourceDevice()) { dev = currentNode()->colorPickSourceDevice(); } else { imageLocker.reset(new boost::lock_guard(*currentImage())); dev = currentImage()->projection(); } KoColor previousColor = canvas()->resourceManager()->foregroundColor(); KisToolUtils::pickColor(m_pickedColor, dev, pos.toPoint(), &previousColor, m_config->radius, m_config->blend); /*!*/ if (m_config->updateColor && m_pickedColor.opacityU8() != OPACITY_TRANSPARENT_U8) { KoColor publicColor = m_pickedColor; publicColor.setOpacity(OPACITY_OPAQUE_U8); if (m_config->toForegroundColor) { canvas()->resourceManager()->setResource(KoCanvasResourceManager::ForegroundColor, publicColor); } else { canvas()->resourceManager()->setResource(KoCanvasResourceManager::BackgroundColor, publicColor); } } } } void KisToolColorPicker::beginPrimaryAction(KoPointerEvent *event) { bool sampleMerged = m_optionsWidget->cmbSources->currentIndex() == SAMPLE_MERGED; if (!sampleMerged) { if (!currentNode()) { QMessageBox::information(0, i18nc("@title:window", "Krita"), i18n("Cannot pick a color as no layer is active.")); event->ignore(); return; } if (!currentNode()->visible()) { QMessageBox::information(0, i18nc("@title:window", "Krita"), i18n("Cannot pick a color as the active layer is not visible.")); event->ignore(); return; } } QPoint pos = convertToImagePixelCoordFloored(event); // Color picking has to start in the visible part of the layer if (!currentImage()->bounds().contains(pos) && !currentImage()->wrapAroundModePermitted()) { event->ignore(); return; } setMode(KisTool::PAINT_MODE); pickColor(pos); displayPickedColor(); } void KisToolColorPicker::continuePrimaryAction(KoPointerEvent *event) { CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); QPoint pos = convertToImagePixelCoordFloored(event); pickColor(pos); displayPickedColor(); } void KisToolColorPicker::endPrimaryAction(KoPointerEvent *event) { Q_UNUSED(event); CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); if (m_config->addPalette) { KoColorSetEntry ent; - ent.color = m_pickedColor; + ent.setColor(m_pickedColor); // We don't ask for a name, too intrusive here KoColorSet *palette = m_palettes.at(m_optionsWidget->cmbPalette->currentIndex()); palette->add(ent); if (!palette->save()) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Cannot write to palette file %1. Maybe it is read-only.", palette->filename())); } } } struct PickedChannel { QString name; QString valueText; }; void KisToolColorPicker::displayPickedColor() { if (m_pickedColor.data() && m_optionsWidget) { QList channels = m_pickedColor.colorSpace()->channels(); m_optionsWidget->listViewChannels->clear(); QVector pickedChannels; for (int i = 0; i < channels.count(); ++i) { pickedChannels.append(PickedChannel()); } for (int i = 0; i < channels.count(); ++i) { PickedChannel pc; pc.name = channels[i]->name(); if (m_config->normaliseValues) { pc.valueText = m_pickedColor.colorSpace()->normalisedChannelValueText(m_pickedColor.data(), i); } else { pc.valueText = m_pickedColor.colorSpace()->channelValueText(m_pickedColor.data(), i); } pickedChannels[channels[i]->displayPosition()] = pc; } Q_FOREACH (const PickedChannel &pc, pickedChannels) { QTreeWidgetItem *item = new QTreeWidgetItem(m_optionsWidget->listViewChannels); item->setText(0, pc.name); item->setText(1, pc.valueText); } } } QWidget* KisToolColorPicker::createOptionWidget() { m_optionsWidget = new ColorPickerOptionsWidget(0); m_optionsWidget->setObjectName(toolId() + " option widget"); m_optionsWidget->listViewChannels->setSortingEnabled(false); // See https://bugs.kde.org/show_bug.cgi?id=316896 QWidget *specialSpacer = new QWidget(m_optionsWidget); specialSpacer->setObjectName("SpecialSpacer"); specialSpacer->setFixedSize(0, 0); m_optionsWidget->layout()->addWidget(specialSpacer); // Initialize blend KisSliderSpinBox m_optionsWidget->blend->setRange(0,100); m_optionsWidget->blend->setSuffix("%"); updateOptionWidget(); connect(m_optionsWidget->cbUpdateCurrentColor, SIGNAL(toggled(bool)), SLOT(slotSetUpdateColor(bool))); connect(m_optionsWidget->cbNormaliseValues, SIGNAL(toggled(bool)), SLOT(slotSetNormaliseValues(bool))); connect(m_optionsWidget->cbPalette, SIGNAL(toggled(bool)), SLOT(slotSetAddPalette(bool))); connect(m_optionsWidget->radius, SIGNAL(valueChanged(int)), SLOT(slotChangeRadius(int))); connect(m_optionsWidget->blend, SIGNAL(valueChanged(int)), SLOT(slotChangeBlend(int))); connect(m_optionsWidget->cmbSources, SIGNAL(currentIndexChanged(int)), SLOT(slotSetColorSource(int))); KoResourceServer *srv = KoResourceServerProvider::instance()->paletteServer(); if (!srv) { return m_optionsWidget; } QList palettes = srv->resources(); Q_FOREACH (KoColorSet *palette, palettes) { if (palette) { m_optionsWidget->cmbPalette->addSqueezedItem(palette->name()); m_palettes.append(palette); } } return m_optionsWidget; } void KisToolColorPicker::updateOptionWidget() { if (!m_optionsWidget) return; m_optionsWidget->cbNormaliseValues->setChecked(m_config->normaliseValues); m_optionsWidget->cbUpdateCurrentColor->setChecked(m_config->updateColor); m_optionsWidget->cmbSources->setCurrentIndex(SAMPLE_MERGED + !m_config->sampleMerged); m_optionsWidget->cbPalette->setChecked(m_config->addPalette); m_optionsWidget->radius->setValue(m_config->radius); m_optionsWidget->blend->setValue(m_config->blend); } void KisToolColorPicker::setToForeground(bool newValue) { m_config->toForegroundColor = newValue; emit toForegroundChanged(); } bool KisToolColorPicker::toForeground() const { return m_config->toForegroundColor; } void KisToolColorPicker::slotSetUpdateColor(bool state) { m_config->updateColor = state; } void KisToolColorPicker::slotSetNormaliseValues(bool state) { m_config->normaliseValues = state; displayPickedColor(); } void KisToolColorPicker::slotSetAddPalette(bool state) { m_config->addPalette = state; } void KisToolColorPicker::slotChangeRadius(int value) { m_config->radius = value; } void KisToolColorPicker::slotChangeBlend(int value) { m_config->blend = value; } void KisToolColorPicker::slotSetColorSource(int value) { m_config->sampleMerged = value == SAMPLE_MERGED; } void KisToolColorPicker::slotAddPalette(KoResource *resource) { KoColorSet *palette = dynamic_cast(resource); if (palette) { m_optionsWidget->cmbPalette->addSqueezedItem(palette->name()); m_palettes.append(palette); } } diff --git a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp index 8431d4cf7d..9321f28d58 100644 --- a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp +++ b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp @@ -1,377 +1,377 @@ /* * Copyright (c) 2016 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_lazy_brush_options_widget.h" #include "ui_kis_tool_lazy_brush_options_widget.h" #include #include "KisPaletteModel.h" #include "kis_config.h" #include #include "kis_canvas_resource_provider.h" #include "kis_signal_auto_connection.h" #include "lazybrush/kis_colorize_mask.h" #include "kis_image.h" #include "kis_signals_blocker.h" #include "kis_signal_compressor.h" #include "kis_layer_properties_icons.h" struct KisToolLazyBrushOptionsWidget::Private { Private() : transparentColorIndex(-1), baseNodeChangedCompressor(500, KisSignalCompressor::FIRST_ACTIVE) { } Ui_KisToolLazyBrushOptionsWidget *ui; KisPaletteModel *colorModel; KisCanvasResourceProvider *provider; KisSignalAutoConnectionsStore providerSignals; KisSignalAutoConnectionsStore maskSignals; KisColorizeMaskSP activeMask; KoColorSet colorSet; int transparentColorIndex = -1; KisSignalCompressor baseNodeChangedCompressor; }; KisToolLazyBrushOptionsWidget::KisToolLazyBrushOptionsWidget(KisCanvasResourceProvider *provider, QWidget *parent) : QWidget(parent), m_d(new Private) { m_d->ui = new Ui_KisToolLazyBrushOptionsWidget(); m_d->ui->setupUi(this); m_d->colorModel = new KisPaletteModel(this); m_d->ui->colorView->setPaletteModel(m_d->colorModel); m_d->ui->colorView->setAllowModification(false); //people proly shouldn't be able to edit the colorentries themselves. m_d->ui->colorView->setCrossedKeyword("transparent"); connect(m_d->ui->chkUseEdgeDetection, SIGNAL(toggled(bool)), SLOT(slotUseEdgeDetectionChanged(bool))); connect(m_d->ui->intEdgeDetectionSize, SIGNAL(valueChanged(int)), SLOT(slotEdgeDetectionSizeChanged(int))); connect(m_d->ui->intRadius, SIGNAL(valueChanged(int)), SLOT(slotRadiusChanged(int))); connect(m_d->ui->intCleanUp, SIGNAL(valueChanged(int)), SLOT(slotCleanUpChanged(int))); connect(m_d->ui->chkLimitToDevice, SIGNAL(toggled(bool)), SLOT(slotLimitToDeviceChanged(bool))); m_d->ui->intEdgeDetectionSize->setRange(0, 100); m_d->ui->intEdgeDetectionSize->setExponentRatio(2.0); m_d->ui->intEdgeDetectionSize->setSuffix(i18n(" px")); m_d->ui->intEdgeDetectionSize->setPrefix(i18n("Edge detection: ")); m_d->ui->intEdgeDetectionSize->setToolTip( i18nc("@info:tooltip", "Activate for images with vast solid areas. " "Set the value to the width of the thinnest " "lines on the image")); m_d->ui->intRadius->setRange(0, 1000); m_d->ui->intRadius->setExponentRatio(3.0); m_d->ui->intRadius->setSuffix(i18n(" px")); m_d->ui->intRadius->setPrefix(i18n("Gap close hint: ")); m_d->ui->intRadius->setToolTip( i18nc("@info:tooltip", "The mask will try to close non-closed contours " "if the gap is smaller than \"Gap close hint\" value")); m_d->ui->intCleanUp->setRange(0, 100); m_d->ui->intCleanUp->setSuffix(i18n(" %")); m_d->ui->intCleanUp->setPrefix(i18n("Clean up: ")); m_d->ui->intCleanUp->setToolTip( i18nc("@info:tooltip", "The mask will try to remove parts of the key strokes " "that are placed outside the closed contours. 0% - no effect, 100% - max effect")); connect(m_d->ui->colorView, SIGNAL(indexEntrySelected(QModelIndex)), this, SLOT(entrySelected(QModelIndex))); connect(m_d->ui->btnTransparent, SIGNAL(toggled(bool)), this, SLOT(slotMakeTransparent(bool))); connect(m_d->ui->btnRemove, SIGNAL(clicked()), this, SLOT(slotRemove())); connect(m_d->ui->chkAutoUpdates, SIGNAL(toggled(bool)), m_d->ui->btnUpdate, SLOT(setDisabled(bool))); connect(m_d->ui->btnUpdate, SIGNAL(clicked()), this, SLOT(slotUpdate())); connect(m_d->ui->chkAutoUpdates, SIGNAL(toggled(bool)), this, SLOT(slotSetAutoUpdates(bool))); connect(m_d->ui->chkShowKeyStrokes, SIGNAL(toggled(bool)), this, SLOT(slotSetShowKeyStrokes(bool))); connect(m_d->ui->chkShowOutput, SIGNAL(toggled(bool)), this, SLOT(slotSetShowOutput(bool))); connect(&m_d->baseNodeChangedCompressor, SIGNAL(timeout()), this, SLOT(slotUpdateNodeProperties())); m_d->provider = provider; const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); m_d->colorSet.add(KoColorSetEntry(KoColor(Qt::red, cs), "color1")); m_d->colorSet.add(KoColorSetEntry(KoColor(Qt::green, cs), "color2")); m_d->colorSet.add(KoColorSetEntry(KoColor(Qt::blue, cs), "color3")); m_d->colorModel->setColorSet(&m_d->colorSet); } KisToolLazyBrushOptionsWidget::~KisToolLazyBrushOptionsWidget() { } void KisToolLazyBrushOptionsWidget::showEvent(QShowEvent *event) { QWidget::showEvent(event); m_d->providerSignals.addConnection( m_d->provider, SIGNAL(sigNodeChanged(KisNodeSP)), this, SLOT(slotCurrentNodeChanged(KisNodeSP))); m_d->providerSignals.addConnection( m_d->provider, SIGNAL(sigFGColorChanged(const KoColor&)), this, SLOT(slotCurrentFgColorChanged(const KoColor&))); slotCurrentNodeChanged(m_d->provider->currentNode()); slotCurrentFgColorChanged(m_d->provider->fgColor()); } void KisToolLazyBrushOptionsWidget::hideEvent(QHideEvent *event) { QWidget::hideEvent(event); m_d->providerSignals.clear(); } void KisToolLazyBrushOptionsWidget::entrySelected(QModelIndex index) { if (!index.isValid()) return; const int i = m_d->colorModel->idFromIndex(index); if (i >= 0 && i < (int)m_d->colorSet.nColors()) { KoColorSetEntry entry = m_d->colorModel->colorSetEntryFromIndex(index); - m_d->provider->setFGColor(entry.color); + m_d->provider->setFGColor(entry.color()); } const bool transparentChecked = i >= 0 && i == m_d->transparentColorIndex; KisSignalsBlocker b(m_d->ui->btnTransparent); m_d->ui->btnTransparent->setChecked(transparentChecked); } void KisToolLazyBrushOptionsWidget::slotCurrentFgColorChanged(const KoColor &color) { int selectedIndex = -1; for (quint32 i = 0; i < m_d->colorSet.nColors(); i++) { KoColorSetEntry entry = m_d->colorSet.getColorGlobal(i); - if (entry.color == color) { + if (entry.color() == color) { selectedIndex = (int)i; break; } } m_d->ui->btnRemove->setEnabled(selectedIndex >= 0); m_d->ui->btnTransparent->setEnabled(selectedIndex >= 0); if (selectedIndex < 0) { KisSignalsBlocker b(m_d->ui->btnTransparent); m_d->ui->btnTransparent->setChecked(false); } QModelIndex newIndex = selectedIndex >= 0 ? m_d->colorModel->indexFromId(selectedIndex) : QModelIndex(); if (newIndex != m_d->ui->colorView->currentIndex()) { m_d->ui->colorView->setCurrentIndex(newIndex); } } void KisToolLazyBrushOptionsWidget::slotColorLabelsChanged() { m_d->colorSet.clear(); m_d->transparentColorIndex = -1; if (m_d->activeMask) { KisColorizeMask::KeyStrokeColors colors = m_d->activeMask->keyStrokesColors(); m_d->transparentColorIndex = colors.transparentIndex; for (int i = 0; i < colors.colors.size(); i++) { const QString name = i == m_d->transparentColorIndex ? "transparent" : ""; m_d->colorSet.add(KoColorSetEntry(colors.colors[i], name)); } } m_d->colorModel->setColorSet(&m_d->colorSet); slotCurrentFgColorChanged(m_d->provider->fgColor()); } void KisToolLazyBrushOptionsWidget::slotUpdateNodeProperties() { KisSignalsBlocker b1(m_d->ui->chkAutoUpdates, m_d->ui->btnUpdate, m_d->ui->chkShowKeyStrokes, m_d->ui->chkShowOutput); KisSignalsBlocker b2(m_d->ui->chkUseEdgeDetection, m_d->ui->intEdgeDetectionSize, m_d->ui->intRadius, m_d->ui->intCleanUp, m_d->ui->chkLimitToDevice); // not implemented yet! //m_d->ui->chkAutoUpdates->setEnabled(m_d->activeMask); m_d->ui->chkAutoUpdates->setEnabled(false); m_d->ui->chkAutoUpdates->setVisible(false); bool value = false; value = m_d->activeMask && KisLayerPropertiesIcons::nodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeNeedsUpdate, true).toBool(); m_d->ui->btnUpdate->setEnabled(m_d->activeMask && !m_d->ui->chkAutoUpdates->isChecked() && value); value = m_d->activeMask && KisLayerPropertiesIcons::nodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeEditKeyStrokes, true).toBool(); m_d->ui->chkShowKeyStrokes->setEnabled(m_d->activeMask); m_d->ui->chkShowKeyStrokes->setChecked(value); value = m_d->activeMask && KisLayerPropertiesIcons::nodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeShowColoring, true).toBool(); m_d->ui->chkShowOutput->setEnabled(m_d->activeMask); m_d->ui->chkShowOutput->setChecked(value); m_d->ui->chkUseEdgeDetection->setEnabled(m_d->activeMask); m_d->ui->chkUseEdgeDetection->setChecked(m_d->activeMask && m_d->activeMask->useEdgeDetection()); m_d->ui->intEdgeDetectionSize->setEnabled(m_d->activeMask && m_d->ui->chkUseEdgeDetection->isChecked()); m_d->ui->intEdgeDetectionSize->setValue(m_d->activeMask ? m_d->activeMask->edgeDetectionSize() : 4.0); m_d->ui->intRadius->setEnabled(m_d->activeMask); m_d->ui->intRadius->setValue(2 * (m_d->activeMask ? m_d->activeMask->fuzzyRadius() : 15)); m_d->ui->intCleanUp->setEnabled(m_d->activeMask); m_d->ui->intCleanUp->setValue(100 * (m_d->activeMask ? m_d->activeMask->cleanUpAmount() : 0.7)); m_d->ui->chkLimitToDevice->setEnabled(m_d->activeMask); m_d->ui->chkLimitToDevice->setChecked(m_d->activeMask && m_d->activeMask->limitToDeviceBounds()); } void KisToolLazyBrushOptionsWidget::slotCurrentNodeChanged(KisNodeSP node) { m_d->maskSignals.clear(); KisColorizeMask *mask = dynamic_cast(node.data()); m_d->activeMask = mask; if (m_d->activeMask) { m_d->maskSignals.addConnection( m_d->activeMask, SIGNAL(sigKeyStrokesListChanged()), this, SLOT(slotColorLabelsChanged())); m_d->maskSignals.addConnection( m_d->provider->currentImage(), SIGNAL(sigNodeChanged(KisNodeSP)), this, SLOT(slotUpdateNodeProperties())); } slotColorLabelsChanged(); slotUpdateNodeProperties(); m_d->ui->colorView->setEnabled(m_d->activeMask); } void KisToolLazyBrushOptionsWidget::slotMakeTransparent(bool value) { KIS_ASSERT_RECOVER_RETURN(m_d->activeMask); QModelIndex index = m_d->ui->colorView->currentIndex(); if (!index.isValid()) return; const int activeIndex = m_d->colorModel->idFromIndex(index); KIS_ASSERT_RECOVER_RETURN(activeIndex >= 0); KisColorizeMask::KeyStrokeColors colors; for (quint32 i = 0; i < m_d->colorSet.nColors(); i++) { - colors.colors << m_d->colorSet.getColorGlobal(i).color; + colors.colors << m_d->colorSet.getColorGlobal(i).color(); } colors.transparentIndex = value ? activeIndex : -1; m_d->activeMask->setKeyStrokesColors(colors); } void KisToolLazyBrushOptionsWidget::slotRemove() { KIS_ASSERT_RECOVER_RETURN(m_d->activeMask); QModelIndex index = m_d->ui->colorView->currentIndex(); if (!index.isValid()) return; const int activeIndex = m_d->colorModel->idFromIndex(index); KIS_ASSERT_RECOVER_RETURN(activeIndex >= 0); - const KoColor color = m_d->colorSet.getColorGlobal((quint32)activeIndex).color; + const KoColor color = m_d->colorSet.getColorGlobal((quint32)activeIndex).color(); m_d->activeMask->removeKeyStroke(color); } void KisToolLazyBrushOptionsWidget::slotUpdate() { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); KisLayerPropertiesIcons::setNodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeNeedsUpdate, false, m_d->provider->currentImage()); } void KisToolLazyBrushOptionsWidget::slotSetAutoUpdates(bool value) { // not implemented yet! ENTER_FUNCTION() << ppVar(value); } void KisToolLazyBrushOptionsWidget::slotSetShowKeyStrokes(bool value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); KisLayerPropertiesIcons::setNodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeEditKeyStrokes, value, m_d->provider->currentImage()); } void KisToolLazyBrushOptionsWidget::slotSetShowOutput(bool value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); KisLayerPropertiesIcons::setNodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeShowColoring, value, m_d->provider->currentImage()); } void KisToolLazyBrushOptionsWidget::slotUseEdgeDetectionChanged(bool value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setUseEdgeDetection(value); m_d->ui->intEdgeDetectionSize->setEnabled(value); } void KisToolLazyBrushOptionsWidget::slotEdgeDetectionSizeChanged(int value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setEdgeDetectionSize(value); } void KisToolLazyBrushOptionsWidget::slotRadiusChanged(int value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setFuzzyRadius(0.5 * value); } void KisToolLazyBrushOptionsWidget::slotCleanUpChanged(int value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setCleanUpAmount(qreal(value) / 100.0); } void KisToolLazyBrushOptionsWidget::slotLimitToDeviceChanged(bool value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setLimitToDeviceBounds(value); }