diff --git a/libs/libkis/CMakeLists.txt b/libs/libkis/CMakeLists.txt index 538fd12bda..20226c368c 100644 --- a/libs/libkis/CMakeLists.txt +++ b/libs/libkis/CMakeLists.txt @@ -1,36 +1,37 @@ set(kritalibkis_LIB_SRCS Action.cpp Canvas.cpp Channel.cpp DockWidget.cpp DockWidgetFactoryBase.cpp Document.cpp Filter.cpp InfoObject.cpp Krita.cpp ManagedColor.cpp Node.cpp Notifier.cpp PresetChooser Palette.cpp + PaletteView.cpp Resource.cpp Selection.cpp View.cpp Extension.cpp Window.cpp ) add_library(kritalibkis SHARED ${kritalibkis_LIB_SRCS} ) generate_export_header(kritalibkis) target_link_libraries(kritalibkis kritaui kritaimage kritaversion) target_link_libraries(kritalibkis LINK_INTERFACE_LIBRARIES kritaimage kritaui) set_target_properties(kritalibkis PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritalibkis ${INSTALL_TARGETS_DEFAULT_ARGS}) add_subdirectory(tests) diff --git a/libs/libkis/ManagedColor.h b/libs/libkis/ManagedColor.h index 52e8c1d830..86afa24e73 100644 --- a/libs/libkis/ManagedColor.h +++ b/libs/libkis/ManagedColor.h @@ -1,209 +1,210 @@ /* * Copyright (C) 2017 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef MANAGEDCOLOR_H #define MANAGEDCOLOR_H #include #include #include #include "kritalibkis_export.h" #include "libkis.h" class KoColor; /** * @brief The ManagedColor class is a class to handle colors that are color managed. * A managed color is a color of which we know the model(RGB, LAB, CMYK, etc), the bitdepth and * the specific properties of its colorspace, such as the whitepoint, chromacities, trc, etc, as represented * by the color profile. * * Krita has two color management systems. LCMS and OCIO. * LCMS is the one handling the ICC profile stuff, and the major one handling that ManagedColor deals with. * OCIO support is only in the display of the colors. ManagedColor has some support for it in colorForCanvas() * * All colors in Krita are color managed. QColors are understood as RGB-type colors in the sRGB space. * * We recommend you make a color like this: * * @code * colorYellow = ManagedColor("RGBA", "U8", "") * QVector yellowComponents = colorYellow.components() * yellowComponents[0] = 1.0 * yellowComponents[1] = 1.0 * yellowComponents[2] = 0 * yellowComponents[3] = 1.0 * * colorYellow.setComponents(yellowComponents) * QColor yellow = colorYellow.colorForCanvas(canvas) * @endcode */ class KRITALIBKIS_EXPORT ManagedColor : public QObject { Q_OBJECT public: /** * @brief ManagedColor * Create a ManagedColor that is black and transparent. */ explicit ManagedColor(QObject *parent = 0); /** * @brief ManagedColor create a managed color with the given color space properties. * @see setColorModel() for more details. */ ManagedColor(const QString &colorModel, const QString &colorDepth, const QString &colorProfile, QObject *parent = 0); ManagedColor(KoColor color, QObject *parent = 0); ~ManagedColor() override; bool operator==(const ManagedColor &other) const; /** * @brief colorForCanvas * @param canvas the canvas whose color management you'd like to use. In Krita, different views have * seperate canvasses, and these can have different OCIO configurations active. * @return the QColor as it would be displaying on the canvas. This result can be used to draw widgets with * the correct configuration applied. */ QColor colorForCanvas(Canvas *canvas) const; /** * colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @return the color depth. */ QString colorDepth() const; /** * @brief colorModel retrieve the current color model of this document: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @return the internal color model string. */ QString colorModel() const; /** * @return the name of the current color profile */ QString colorProfile() const; /** * @brief setColorProfile set the color profile of the image to the given profile. The profile has to * be registered with krita and be compatible with the current color model and depth; the image data * is not converted. * @param colorProfile * @return false if the colorProfile name does not correspond to to a registered profile or if assigning * the profile failed. */ bool setColorProfile(const QString &colorProfile); /** * @brief setColorSpace convert the nodes and the image to the given colorspace. The conversion is * done with Perceptual as intent, High Quality and No LCMS Optimizations as flags and no blackpoint * compensation. * * @param colorModel A string describing the color model of the image: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @param colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @param colorProfile a valid color profile for this color model and color depth combination. * @return false the combination of these arguments does not correspond to a colorspace. */ bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile); /** * @brief components * @return a QVector containing the channel/components of this color normalized. This includes the alphachannel. */ QVector components() const; /** * @brief componentsOrdered() * @return same as Components, except the values are ordered to the display. */ QVector componentsOrdered() const; /** * @brief setComponents * Set the channel/components with normalized values. For integer colorspace, this obviously means the limit * is between 0.0-1.0, but for floating point colorspaces, 2.4 or 103.5 are still meaningful (if bright) values. * @param values the QVector containing the new channel/component values. These should be normalized. */ void setComponents(const QVector &values); /** * Serialize this color following Create's swatch color specification available * at http://create.freedesktop.org/wiki/index.php/Swatches_-_colour_file_format */ QString toXML() const; /** * Unserialize a color following Create's swatch color specification available * at http://create.freedesktop.org/wiki/index.php/Swatches_-_colour_file_format * * @param XXX * * @return the unserialized color, or an empty color object if the function failed * to unserialize the color */ void fromXML(const QString &xml); /** * @brief toQString create a user-visible string of the channel names and the channel values * @param color the color to create the string from * @return a string that can be used to display the values of this color to the user. */ QString toQString(); private: friend class View; + friend class PaletteView; KoColor color() const; struct Private; const QScopedPointer d; }; #endif // MANAGEDCOLOR_H diff --git a/libs/libkis/Palette.cpp b/libs/libkis/Palette.cpp index 8851186a78..ca02e02aea 100644 --- a/libs/libkis/Palette.cpp +++ b/libs/libkis/Palette.cpp @@ -1,102 +1,107 @@ /* * 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(); } 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::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); return color; } + +KoColorSet *Palette::colorSet() +{ + return d->palette; +} diff --git a/libs/libkis/Palette.h b/libs/libkis/Palette.h index 50297d6a4a..cf7332f19c 100644 --- a/libs/libkis/Palette.h +++ b/libs/libkis/Palette.h @@ -1,123 +1,130 @@ /* * 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()) * @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(); //setcomment /** * @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 succesful. */ 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 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); KoColorSetEntry colorSetEntryByIndex(int index); KoColorSetEntry colorSetEntryFromGroup(int index, const QString &groupName); ManagedColor *colorForEntry(KoColorSetEntry entry); //getcolorgroup //Add //Remove //Insert 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/libkis/PaletteView.cpp b/libs/libkis/PaletteView.cpp new file mode 100644 index 0000000000..36c8c669b6 --- /dev/null +++ b/libs/libkis/PaletteView.cpp @@ -0,0 +1,83 @@ +/* + * 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 +#include + +struct PaletteView::Private +{ + KisPaletteModel *model = 0; + KisPaletteView *widget = 0; + bool allowPaletteModification = true; +}; + +PaletteView::PaletteView(QWidget *parent) + : QWidget(parent), d(new Private) +{ + d->widget = new KisPaletteView(parent); + d->model = new KisPaletteModel(); + d->widget->setModel(d->model); + this->setLayout(new QVBoxLayout()); + this->layout()->addWidget(d->widget); + + //forward signals. + connect(d->widget, SIGNAL(entrySelected(KoColorSetEntry)), + this, SIGNAL(entrySelectedForeGround(KoColorSetEntry))); + connect(d->widget, SIGNAL(entrySelectedBackGround(KoColorSetEntry)), + this, SIGNAL(entrySelectedBackGround(KoColorSetEntry))); +} + +PaletteView::~PaletteView() +{ + +} + +void PaletteView::setPalette(Palette *palette) +{ + d->model->setColorSet(palette->colorSet()); + d->widget->setPaletteModel(d->model); +} + +bool PaletteView::addEntryWithDialog(ManagedColor *color) +{ + if (d->model->colorSet()) { + return d->widget->addEntryWithDialog(color->color()); + } + return false; +} + +bool PaletteView::addGroupWithDialog() +{ + if (d->model->colorSet()) { + return d->widget->addGroupWithDialog(); + } + return false; +} + +bool PaletteView::removeSelectedEntryWithDialog() +{ + if (d->model->colorSet()) { + return d->widget->removeEntryWithDialog(d->widget->currentIndex()); + } + return false; +} + +void PaletteView::trySelectClosestColor(ManagedColor *color) +{ + d->widget->trySelectClosestColor(color->color()); +} diff --git a/libs/libkis/PaletteView.h b/libs/libkis/PaletteView.h new file mode 100644 index 0000000000..a88e810ee0 --- /dev/null +++ b/libs/libkis/PaletteView.h @@ -0,0 +1,58 @@ +/* + * 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_VIEW_H +#define LIBKIS_PALETTE_VIEW_H + +#include +#include +#include "kritalibkis_export.h" +#include "libkis.h" +#include "Palette.h" +#include "ManagedColor.h" +#include "KoColorSet.h" +#include +#include + +/** + * @brief The PaletteView class is a wrapper around a MVC method for handling + * palettes. This class shows a nice widget. + */ + +class KRITALIBKIS_EXPORT PaletteView : public QWidget +{ + Q_OBJECT +public: + PaletteView(QWidget *parent = 0); + ~PaletteView(); +public Q_SLOTS: + void setPalette(Palette *palette); + bool addEntryWithDialog(ManagedColor *color); + bool addGroupWithDialog(); + bool removeSelectedEntryWithDialog(); + void trySelectClosestColor(ManagedColor *color); +Q_SIGNALS: + void entrySelectedForeGround(KoColorSetEntry entry); + void entrySelectedBackGround(KoColorSetEntry entry); +private: + struct Private; + const QScopedPointer d; + +}; + +#endif // LIBKIS_PALETTE_VIEW_H diff --git a/libs/ui/kis_palette_view.cpp b/libs/ui/kis_palette_view.cpp index 36602fab6f..085587af55 100644 --- a/libs/ui/kis_palette_view.cpp +++ b/libs/ui/kis_palette_view.cpp @@ -1,315 +1,321 @@ /* * 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 struct KisPaletteView::Private { KisPaletteModel *model = 0; bool allowPaletteModification = true; }; KisPaletteView::KisPaletteView(QWidget *parent) : 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(); 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(i18n("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(); m_d->model->addColorSetEntry(newEntry, groupName); m_d->model->colorSet()->save(); return true; } return false; } 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 (qVariantValue(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; 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(); - for (int r=0; r<=m_d->model->rowCount(); r++) { - QModelIndex index = m_d->model->index(r, 0); - if (qVariantValue(index.data(KisPaletteModel::IsHeaderRole))) { - setSpan(r, 0, 1, m_d->model->columnCount()); - setRowHeight(r, this->fontMetrics().lineSpacing()+6); + if (m_d->model) { + for (int r=0; r<=m_d->model->rowCount(); r++) { + QModelIndex index = m_d->model->index(r, 0); + if (qVariantValue(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 ( setSize >= 12 ) { 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 (qVariantValue(index.data(KisPaletteModel::IsHeaderRole))==false) { KoColorSetEntry entry = m_d->model->colorSetEntryFromIndex(index); if (foreground) { emit(entrySelected(entry)); } else { emit(entrySelectedBackGround(entry)); } } } 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(); QCheckBox *chkSpot = new QCheckBox(); if (qVariantValue(index.data(KisPaletteModel::IsHeaderRole))) { QString groupName = qVariantValue(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 = qVariantValue(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); if (group->exec() == KoDialog::Accepted) { entry.name = lnGroupName->text(); entry.id = lnIDName->text(); entry.color = bnColor->color(); entry.spotColor = chkSpot->isChecked(); m_d->model->colorSet()->changeColorSetEntry(entry, entryList.at(0), entryList.at(1).toUInt()); m_d->model->colorSet()->save(); } } } } diff --git a/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_docker.py b/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_docker.py index 641a521430..27ec9ce094 100644 --- a/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_docker.py +++ b/plugins/extensions/pykrita/plugin/plugins/palette_docker/palette_docker.py @@ -1,157 +1,163 @@ # Description: A Python based docker that allows you to edit KPL color palettes. # By Wolthera # Importing the relevant dependancies: import sys from PyQt5.QtGui import * from PyQt5.QtWidgets import * import math from krita import * class palette_swatch_widget(QWidget): colorSelected = pyqtSignal(['ManagedColor']) def __init__(self, parent, color, mColor): super().__init__(parent) self.setMinimumHeight(12) self.setMinimumWidth(12) self.setSizePolicy(QSizePolicy().MinimumExpanding,QSizePolicy().MinimumExpanding) self.color = color self.mColor = mColor def paintEvent(self, event): painter = QPainter(self) painter.setBrush(self.color) painter.setPen(self.color) painter.drawRect(self.contentsRect()) def mousePressEvent(self, event): print("Color selected: "+self.toolTip()) self.colorSelected.emit(self.mColor) def sizeHint(self): return QSize(12,12); class Palette_Docker(DockWidget): #Init the docker def __init__(self): super().__init__() # make base-widget and layout widget = QWidget() layout = QVBoxLayout(self) 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.currentPalette = Palette(allPalettes["Default"]) self.cmb_palettes.currentTextChanged.connect(self.slot_paletteChanged) layout.addWidget(self.cmb_palettes) # add combobox to the layout - self.palette_frame = QScrollArea() - self.palette_frame.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) - self.palette_container = QWidget() - self.palette_frame.setContentsMargins(0,0,0,0) - self.palette_layout = QVBoxLayout() - self.palette_layout.setSpacing(0) - self.palette_layout.setContentsMargins(0,0,0,0) - self.palette_container.setLayout(self.palette_layout) - self.palette_frame.setWidget(self.palette_container) - layout.addWidget(self.palette_frame) - print("palette") - self.fill_palette_frame() + self.paletteView = PaletteView() + self.paletteView.setPalette(self.currentPalette) + layout.addWidget(self.paletteView) + self.paletteView.entrySelectedForeGround.connect(self.slot_swatchSelected) + #self.palette_frame = QScrollArea() + #self.palette_frame.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) + #self.palette_container = QWidget() + #self.palette_frame.setContentsMargins(0,0,0,0) + #self.palette_layout = QVBoxLayout() + #self.palette_layout.setSpacing(0) + #self.palette_layout.setContentsMargins(0,0,0,0) + #self.palette_container.setLayout(self.palette_layout) + #self.palette_frame.setWidget(self.palette_container) + #layout.addWidget(self.palette_frame) + #print("palette") + #self.fill_palette_frame() self.setWidget(widget) # add widget to the docker def fill_palette_frame(self): for i in reversed(range(self.palette_layout.count())): self.palette_layout.itemAt(i).widget().setParent(None) columnCount = self.currentPalette.columnCount() groupNames = self.currentPalette.groupNames() self.palette_container.setMinimumHeight(0) self.palette_container.setContentsMargins(0, 0, 0, 0) self.palette_container.setSizePolicy(QSizePolicy().Ignored,QSizePolicy().MinimumExpanding) swatchSize = math.floor(self.width()/(columnCount+2)) if swatchSize < 12: swatchSize = 12 self.palette_container.setFixedWidth((columnCount+1)*swatchSize) gb_defaultGroup = QWidget() gb_defaultGroup.setLayout(QGridLayout()) gb_defaultGroup.layout().setSpacing(0) colorCount = self.currentPalette.colorsCountGroup("") rowsForGroup = math.ceil(colorCount/(columnCount+1)) gb_defaultGroup.setMinimumWidth(columnCount*swatchSize) gb_defaultGroup.setContentsMargins(0, 0, 0, 0) gb_defaultGroup.setMinimumHeight(rowsForGroup*swatchSize+gb_defaultGroup.style().pixelMetric(QStyle.PM_TitleBarHeight)) for c in range(columnCount): gb_defaultGroup.layout().setColumnMinimumWidth(c, swatchSize) for i in range(colorCount): entry = self.currentPalette.colorSetEntryFromGroup(i, "") color = self.currentPalette.colorForEntry(entry); swatch = palette_swatch_widget(self, color.colorForCanvas(self.canvas()), color) swatch.setToolTip(entry.name) column = i % columnCount row = math.floor(i/columnCount) gb_defaultGroup.layout().addWidget(swatch, row, column) #print("palette swatch added "+entry.name+" "+str(column)+", "+str(row)) swatch.colorSelected.connect(self.slot_swatchSelected) self.palette_layout.addWidget(gb_defaultGroup) self.palette_container.setMinimumHeight(self.palette_container.minimumHeight()+gb_defaultGroup.minimumHeight()) for groupName in groupNames: gb_groupBox = QGroupBox() gb_groupBox.setTitle(groupName) gb_groupBox.setLayout(QGridLayout()) gb_groupBox.setFlat(True) gb_groupBox.setFixedWidth((columnCount)*swatchSize) colorCount = self.currentPalette.colorsCountGroup(groupName) rowsForGroup = math.ceil(colorCount/(columnCount+1)) for c in range(columnCount): gb_groupBox.layout().setColumnMinimumWidth(c, swatchSize) gb_groupBox.layout().setSpacing(0) gb_groupBox.setContentsMargins(0, 0, 0, 0) for i in range(colorCount): entry = self.currentPalette.colorSetEntryFromGroup(i, groupName) - color = self.currentPalette.colorForEntry(entry); + color = self.currentPalette.colorForEntry(entry) swatch = palette_swatch_widget(self, color.colorForCanvas(self.canvas()), color) swatch.setToolTip(entry.name) swatch.setFixedHeight(swatchSize) column = i % columnCount row = math.floor(i/columnCount) gb_groupBox.layout().addWidget(swatch, row, column) #print("palette swatch added "+entry.name+" "+str(column)+", "+str(row)) - swatch.colorSelected.connect(self.slot_swatchSelected) + #swatch.colorSelected.connect(self.slot_swatchSelected) self.palette_layout.addWidget(gb_groupBox) gb_groupBox.adjustSize() self.palette_container.setMinimumHeight(self.palette_container.minimumHeight()+gb_groupBox.height()) self.palette_container.setMaximumHeight(self.palette_container.minimumHeight()) def slot_paletteChanged(self, name): self.currentPalette = Palette(Application.resources("palette")[name]) - self.fill_palette_frame() + self.paletteView.setPalette(self.currentPalette) + #self.fill_palette_frame() - @pyqtSlot('ManagedColor') - def slot_swatchSelected(self, color): - print("color "+color.toQString()) + @pyqtSlot('KoColorSetEntry') + def slot_swatchSelected(self, entry): + print("entry "+entry.name) if (self.canvas()) is not None: if (self.canvas().view()) is not None: + color = self.currentPalette.colorForEntry(entry) self.canvas().view().setForeGroundColor(color) def canvasChanged(self, canvas): - self.fill_palette_frame() + #self.fill_palette_frame() pass #Add docker to the application :) Application.addDockWidgetFactory(DockWidgetFactory("palette_docker", DockWidgetFactoryBase.DockRight, Palette_Docker)) diff --git a/plugins/extensions/pykrita/sip/krita/PaletteView.sip b/plugins/extensions/pykrita/sip/krita/PaletteView.sip new file mode 100644 index 0000000000..21bc77be93 --- /dev/null +++ b/plugins/extensions/pykrita/sip/krita/PaletteView.sip @@ -0,0 +1,20 @@ +class PaletteView : QWidget +{ +%TypeHeaderCode +#include "PaletteView.h" +%End +PaletteView(const PaletteView & __0); +public: + PaletteView(QWidget *parent = 0); + ~PaletteView(); +public Q_SLOTS: + void setPalette(Palette *palette); + bool addEntryWithDialog(ManagedColor *color); + bool addGroupWithDialog(); + bool removeSelectedEntryWithDialog(); + void trySelectClosestColor(ManagedColor *color); +Q_SIGNALS: + void entrySelectedForeGround(KoColorSetEntry entry); + void entrySelectedBackGround(KoColorSetEntry entry); +private: +}; diff --git a/plugins/extensions/pykrita/sip/krita/kritamod.sip b/plugins/extensions/pykrita/sip/krita/kritamod.sip index 24638caef7..962ec2f4b5 100644 --- a/plugins/extensions/pykrita/sip/krita/kritamod.sip +++ b/plugins/extensions/pykrita/sip/krita/kritamod.sip @@ -1,34 +1,35 @@ %Module PyKrita.krita %ModuleHeaderCode #pragma GCC visibility push(default) %End %Import QtCore/QtCoremod.sip %Import QtGui/QtGuimod.sip %Import QtXml/QtXmlmod.sip %Import QtWidgets/QtWidgetsmod.sip %Include Conversions.sip %Include Action.sip %Include Canvas.sip %Include Channel.sip %Include DockWidgetFactoryBase.sip %Include DockWidget.sip %Include Document.sip %Include Filter.sip %Include InfoObject.sip %Include Extension.sip %Include View.sip %Include Window.sip %Include Krita.sip %Include Node.sip %Include Notifier.sip %Include Resource.sip %Include Selection.sip %Include Extension.sip %Include PresetChooser.sip %Include Palette.sip +%Include PaletteView.sip %Include ManagedColor.sip %Include KisCubicCurve.sip