Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_palette_view.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
3 * SPDX-FileCopyrightText: 2022 Halla Rempt <halla@valdyas.org>
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_palette_view.h"
8
9#include <QWheelEvent>
10#include <QHeaderView>
11#include <QFormLayout>
12#include <QLineEdit>
13#include <QCheckBox>
14#include <QComboBox>
15
16#include <KConfigGroup>
17#include <KSharedConfig>
18#include <KLocalizedString>
19
20#include <kis_icon_utils.h>
21
22#include <KisKineticScroller.h>
23
24#include <KoDialog.h>
26
27#include "KisPaletteDelegate.h"
28#include "KisPaletteModel.h"
29#include "kis_color_button.h"
30#include <KisSwatch.h>
31#include <KisResourceModel.h>
32#include <kis_debug.h>
34
36
41
43 : QTableView(parent)
44 , d(new Private)
45{
46 setItemDelegate(new KisPaletteDelegate(this));
47
48 setShowGrid(true);
49 setDropIndicatorShown(true);
50 setDragDropMode(QAbstractItemView::DragDrop);
51 setSelectionMode(QAbstractItemView::SingleSelection);
52 setDragEnabled(true);
53 setAcceptDrops(false);
54
55 /*
56 * without this, a cycle might be created:
57 * the view stretches to right border, and this make it need a scroll bar;
58 * after the bar is added, the view shrinks to the bar, and this makes it
59 * no longer need the bar any more, and the bar is removed again
60 */
61 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
62
63 // set the size of swatches
64 horizontalHeader()->setVisible(false);
65 verticalHeader()->setVisible(false);
66 horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
67 horizontalHeader()->setMinimumSectionSize(MINIMUM_ROW_HEIGHT);
68 verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
69 verticalHeader()->setMinimumSectionSize(MINIMUM_ROW_HEIGHT);
70
71 connect(horizontalHeader(), SIGNAL(sectionResized(int,int,int)),
72 SLOT(slotHorizontalHeaderResized(int,int,int)));
73 setAutoFillBackground(true);
74
75 QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this);
76 if (scroller) {
77 connect(scroller, SIGNAL(stateChanged(QScroller::State)),
78 this, SLOT(slotScrollerStateChanged(QScroller::State)));
79 }
80
81 connect(this, SIGNAL(clicked(QModelIndex)), SLOT(slotCurrentSelectionChanged(QModelIndex)));
82}
83
87
89{
90 KisPaletteDelegate *delegate =
91 dynamic_cast<KisPaletteDelegate*>(itemDelegate());
93
94 delegate->setCrossedKeyword(value);
95}
96
98{
99 KoDialog dialog;
100 dialog.setWindowTitle(i18nc("@title:dialog", "Add a new Color Swatch"));
101 QFormLayout *editableItems = new QFormLayout(dialog.mainWidget());
102
103 QComboBox *cmbGroups = new QComboBox;
104 QString defaultGroupName = i18nc("Name for default swatch group", "Default");
105 cmbGroups->addItem(defaultGroupName);
106 cmbGroups->addItems(d->model->colorSet()->swatchGroupNames());
107 QLineEdit *lnIDName = new QLineEdit;
108 QLineEdit *lnName = new QLineEdit;
109 KisColorButton *bnColor = new KisColorButton;
110 QCheckBox *chkSpot = new QCheckBox;
111 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."));
112 editableItems->addRow(i18n("Swatch Group:"), cmbGroups);
113 editableItems->addRow(i18n("Swatch ID:"), lnIDName);
114 editableItems->addRow(i18n("Color swatch name:"), lnName);
115 editableItems->addRow(i18nc("Color as the Color of a Swatch in a Palette", "Color:"), bnColor);
116 editableItems->addRow(i18n("Spot color:"), chkSpot);
117 cmbGroups->setCurrentIndex(0);
118 lnName->setText(i18nc("Prefix of a color swatch default name, as in Color 1","Color")+" " + QString::number(d->model->colorSet()->colorCount()+1));
119 lnIDName->setText(QString::number(d->model->colorSet()->colorCount() + 1));
120 bnColor->setColor(color);
121 chkSpot->setChecked(false);
122
123 if (dialog.exec() == KoDialog::Accepted) {
124 QString groupName = cmbGroups->currentText();
125 if (groupName == defaultGroupName) {
126 groupName = QString();
127 }
128 KisSwatch newEntry;
129 newEntry.setColor(bnColor->color());
130 newEntry.setName(lnName->text());
131 newEntry.setId(lnIDName->text());
132 newEntry.setSpotColor(chkSpot->isChecked());
133 d->model->addSwatch(newEntry, groupName);
135 return true;
136 }
137
138 return false;
139}
140
142{
143 KoDialog dialog;
144 dialog.setWindowTitle(i18nc("@title:dialog","Add a new group"));
145 QFormLayout *editableItems = new QFormLayout(dialog.mainWidget());
146 QLineEdit *lnName = new QLineEdit();
147 lnName->setText(i18nc("Part of default name for a new group", "Color Group")+""+QString::number(d->model->colorSet()->swatchGroupNames().size()+1));
148 editableItems->addRow(i18nc("Name for a group", "Name"), lnName);
149
150 if (dialog.exec() == KoDialog::Accepted) {
151 d->model->addGroup(lnName->text());
153 return true;
154 }
155 return false;
156}
157
159{
160 bool keepColors = false;
161 if (qvariant_cast<bool>(index.data(KisPaletteModel::IsGroupNameRole))) {
162 KoDialog dialog;
163 dialog.setWindowTitle(i18nc("@title:dialog","Removing Group"));
164 QFormLayout *editableItems = new QFormLayout(dialog.mainWidget());
165 QCheckBox *chkKeep = new QCheckBox();
166 editableItems->addRow(i18nc("Shows up when deleting a swatch group", "Keep the Colors"), chkKeep);
167
168 if (dialog.exec() != KoDialog::Accepted) { return false; }
169 keepColors = chkKeep->isChecked();
170 }
171 d->model->removeSwatch(index, keepColors);
172
174
175 return true;
176}
177
179{
180 KoColorSetSP colorSet = d->model->colorSet();
181 if (!colorSet || !colorSet->valid() || currentIndex().row() < 0) {
182 return;
183 }
184
185 //also don't select if the color is the same as the current selection
186 if (d->model->getSwatch(currentIndex()).color() == color) {
187 return;
188 }
189
190 selectionModel()->clearSelection();
191 QModelIndex index = d->model->indexForClosest(color);
192
193 selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select);
194}
195
197{
198 QModelIndex index = d->model->indexForClosest(color);
199 KisSwatch swatch = d->model->getSwatch(index);
200 return swatch.color();
201}
202
204{
205 selectClosestColor(color);
206}
207
209{
210 if (d->model) {
211 disconnect(d->model, 0, this, 0);
212 }
213 d->model = model;
214 setModel(model);
216
217 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(slotAdditionalGuiUpdate()));
218 connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(slotAdditionalGuiUpdate()));
219 connect(model, SIGNAL(modelReset()), SLOT(slotAdditionalGuiUpdate()));
220}
221
223{
224 return d->model;
225}
226
228{
229 setAcceptDrops(allow);
230}
231
233{
234 resizeRows(newSize);
236}
237
239{
240 verticalHeader()->setDefaultSectionSize(newSize);
241 verticalHeader()->resizeSections(QHeaderView::Fixed);
242}
243
248
250{
251 if (selectedIndexes().size() <= 0) {
252 return;
253 }
254 d->model->removeSwatch(currentIndex());
255}
256
258{
259 /*
260 * Note: QTableView (Qt 5.15) does not clear spans on model resets.
261 * But it does move spans on row inserts/removals, so incremental updates
262 * would be possible.
263 * Moving rows on the other hand does NOT update row spans accordingly...
264 */
265 if (!d->model->colorSet()) return;
266
267 clearSpans();
268 resizeRows(verticalHeader()->defaultSectionSize());
269
270// int row = -1;
271
272 for (const QString &groupName : d->model->colorSet()->swatchGroupNames()) {
273 if (groupName.isEmpty()) continue;
274
275// KisSwatchGroupSP group = d->model->colorSet()->getGroup(groupName);
276// row += group->rowCount() + 1;
277// setSpan(row, 0, 1, d->model->columnCount());
278// setRowHeight(row, fontMetrics().lineSpacing() + 6);
279// verticalHeader()->resizeSection(row, fontMetrics().lineSpacing() + 6);
280
281
282 int rowNumber = d->model->colorSet()->startRowForGroup(groupName);
283 setSpan(rowNumber, 0, 1, d->model->columnCount());
284 setRowHeight(rowNumber, fontMetrics().lineSpacing() + 6);
285 verticalHeader()->resizeSection(rowNumber, fontMetrics().lineSpacing() + 6);
286 }
287}
288
289void KisPaletteView::slotCurrentSelectionChanged(const QModelIndex &newCurrent)
290{
291 if (!newCurrent.isValid()) { return; }
292
293 const bool isGroupName = newCurrent.data(KisPaletteModel::IsGroupNameRole).toBool();
294 const bool isCheckSlot = newCurrent.data(KisPaletteModel::CheckSlotRole).toBool();
295
296 const KisSwatch newEntry = d->model->getSwatch(newCurrent);
297
298 Q_EMIT sigIndexSelected(newCurrent);
299 if (isGroupName) {
300 return;
301 }
302
303 if (isCheckSlot) {
304 Q_EMIT sigColorSelected(newEntry.color());
305 }
306}
307
309{
310 Q_ASSERT(d->model);
311 d->model->setDisplayRenderer(displayRenderer);
312}
313
float value(const T *src, size_t ch)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
A pushbutton to display or allow user selection of a color.
void setColor(const KoColor &c)
void setCrossedKeyword(const QString &value)
The KisPaletteModel class This, together with KisPaletteView and KisPaletteDelegate forms a mvc way t...
void setCrossedKeyword(const QString &value)
setCrossedKeyword This allows you to set keywords that can cross out colors. This is implemented to m...
void setAllowModification(bool allow)
setAllowModification Set whether doubleclick calls up a modification window. This is to prevent users...
bool removeEntryWithDialog(QModelIndex index)
void sigColorSelected(const KoColor &)
const KoColor closestColor(const KoColor &color) const
closestColor determines closest swatch in the active palette and returns it's color as KoColor
void slotFGColorChanged(const KoColor &)
const QScopedPointer< Private > d
void slotHorizontalHeaderResized(int, int, int newSize)
void slotCurrentSelectionChanged(const QModelIndex &newCurrent)
void sigIndexSelected(const QModelIndex &index)
KisPaletteModel * paletteModel() const
void setPaletteModel(KisPaletteModel *model)
~KisPaletteView() override
void slotScrollerStateChanged(QScroller::State state)
bool addEntryWithDialog(KoColor color)
KisPaletteView(QWidget *parent=0)
void resizeRows(int newSize)
static int MINIMUM_ROW_HEIGHT
void selectClosestColor(const KoColor &color)
selectClosestColor select a color that's closest to parameter color
void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer)
static bool updateResourceWithUserInput(QWidget *widgetParent, KoResourceSP resource)
void setSpotColor(bool spotColor)
Definition KisSwatch.cpp:38
KoColor color() const
Definition KisSwatch.h:30
void setColor(const KoColor &color)
Definition KisSwatch.cpp:32
void setId(const QString &id)
Definition KisSwatch.cpp:26
void setName(const QString &name)
Definition KisSwatch.cpp:20
A dialog base class with standard buttons and predefined layouts.
Definition KoDialog.h:116
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
KRITAWIDGETUTILS_EXPORT QScroller * createPreconfiguredScroller(QAbstractScrollArea *target)
QPointer< KisPaletteModel > model