File indexing completed on 2024-05-12 16:02:01
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_palette_view.h" 0008 0009 #include <QWheelEvent> 0010 #include <QHeaderView> 0011 #include <QFormLayout> 0012 #include <QLabel> 0013 #include <QLineEdit> 0014 #include <QCheckBox> 0015 #include <QComboBox> 0016 #include <QMenu> 0017 0018 #include <KConfigGroup> 0019 #include <KSharedConfig> 0020 #include <KLocalizedString> 0021 0022 #include <kis_icon_utils.h> 0023 0024 #include <KisKineticScroller.h> 0025 0026 #include <KoDialog.h> 0027 #include <KoColorDisplayRendererInterface.h> 0028 0029 #include "KisPaletteDelegate.h" 0030 #include "KisPaletteModel.h" 0031 #include "kis_color_button.h" 0032 #include <KisSwatch.h> 0033 #include <KisResourceModel.h> 0034 #include <kis_debug.h> 0035 #include <KisResourceUserOperations.h> 0036 0037 int KisPaletteView::MININUM_ROW_HEIGHT = 10; 0038 0039 struct KisPaletteView::Private 0040 { 0041 QPointer<KisPaletteModel> model; 0042 bool allowPaletteModification {false}; // if modification is allowed from this widget 0043 }; 0044 0045 KisPaletteView::KisPaletteView(QWidget *parent) 0046 : QTableView(parent) 0047 , m_d(new Private) 0048 { 0049 setItemDelegate(new KisPaletteDelegate(this)); 0050 0051 setShowGrid(true); 0052 setDropIndicatorShown(true); 0053 setDragDropMode(QAbstractItemView::DragDrop); 0054 setSelectionMode(QAbstractItemView::SingleSelection); 0055 setDragEnabled(true); 0056 setAcceptDrops(false); 0057 0058 /* 0059 * without this, a cycle might be created: 0060 * the view stretches to right border, and this make it need a scroll bar; 0061 * after the bar is added, the view shrinks to the bar, and this makes it 0062 * no longer need the bar any more, and the bar is removed again 0063 */ 0064 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); 0065 0066 // set the size of swatches 0067 horizontalHeader()->setVisible(false); 0068 verticalHeader()->setVisible(false); 0069 horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); 0070 horizontalHeader()->setMinimumSectionSize(MININUM_ROW_HEIGHT); 0071 verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); 0072 verticalHeader()->setMinimumSectionSize(MININUM_ROW_HEIGHT); 0073 0074 connect(horizontalHeader(), SIGNAL(sectionResized(int,int,int)), 0075 SLOT(slotHorizontalHeaderResized(int,int,int))); 0076 setAutoFillBackground(true); 0077 0078 QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this); 0079 if (scroller) { 0080 connect(scroller, SIGNAL(stateChanged(QScroller::State)), 0081 this, SLOT(slotScrollerStateChanged(QScroller::State))); 0082 } 0083 0084 connect(this, SIGNAL(clicked(QModelIndex)), SLOT(slotCurrentSelectionChanged(QModelIndex))); 0085 } 0086 0087 KisPaletteView::~KisPaletteView() 0088 { 0089 } 0090 0091 void KisPaletteView::setCrossedKeyword(const QString &value) 0092 { 0093 KisPaletteDelegate *delegate = 0094 dynamic_cast<KisPaletteDelegate*>(itemDelegate()); 0095 KIS_ASSERT_RECOVER_RETURN(delegate); 0096 0097 delegate->setCrossedKeyword(value); 0098 } 0099 0100 bool KisPaletteView::addEntryWithDialog(KoColor color) 0101 { 0102 KoDialog dialog; 0103 dialog.setWindowTitle(i18nc("@title:dialog", "Add a new Color Swatch")); 0104 QFormLayout *editableItems = new QFormLayout(dialog.mainWidget()); 0105 0106 QComboBox *cmbGroups = new QComboBox; 0107 QString defaultGroupName = i18nc("Name for default swatch group", "Default"); 0108 cmbGroups->addItem(defaultGroupName); 0109 cmbGroups->addItems(m_d->model->colorSet()->getGroupNames()); 0110 QLineEdit *lnIDName = new QLineEdit; 0111 QLineEdit *lnName = new QLineEdit; 0112 KisColorButton *bnColor = new KisColorButton; 0113 QCheckBox *chkSpot = new QCheckBox; 0114 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.")); 0115 editableItems->addRow(i18n("Swatch Group:"), cmbGroups); 0116 editableItems->addRow(i18n("Swatch ID:"), lnIDName); 0117 editableItems->addRow(i18n("Color swatch name:"), lnName); 0118 editableItems->addRow(i18nc("Color as the Color of a Swatch in a Palette", "Color:"), bnColor); 0119 editableItems->addRow(i18n("Spot color:"), chkSpot); 0120 cmbGroups->setCurrentIndex(0); 0121 lnName->setText(i18nc("Prefix of a color swatch default name, as in Color 1","Color")+" " + QString::number(m_d->model->colorSet()->colorCount()+1)); 0122 lnIDName->setText(QString::number(m_d->model->colorSet()->colorCount() + 1)); 0123 bnColor->setColor(color); 0124 chkSpot->setChecked(false); 0125 0126 if (dialog.exec() == KoDialog::Accepted) { 0127 QString groupName = cmbGroups->currentText(); 0128 if (groupName == defaultGroupName) { 0129 groupName = QString(); 0130 } 0131 KisSwatch newEntry; 0132 newEntry.setColor(bnColor->color()); 0133 newEntry.setName(lnName->text()); 0134 newEntry.setId(lnIDName->text()); 0135 newEntry.setSpotColor(chkSpot->isChecked()); 0136 m_d->model->addEntry(newEntry, groupName); 0137 saveModification(); 0138 return true; 0139 } 0140 0141 return false; 0142 } 0143 0144 bool KisPaletteView::addGroupWithDialog() 0145 { 0146 KoDialog dialog; 0147 dialog.setWindowTitle(i18nc("@title:dialog","Add a new group")); 0148 QFormLayout *editableItems = new QFormLayout(dialog.mainWidget()); 0149 QLineEdit *lnName = new QLineEdit(); 0150 lnName->setText(i18nc("Part of default name for a new group", "Color Group")+""+QString::number(m_d->model->colorSet()->getGroupNames().size()+1)); 0151 editableItems->addRow(i18nc("Name for a group", "Name"), lnName); 0152 0153 if (dialog.exec() == KoDialog::Accepted) { 0154 KisSwatchGroup group; 0155 group.setName(lnName->text()); 0156 m_d->model->addGroup(group); 0157 saveModification(); 0158 return true; 0159 } 0160 return false; 0161 } 0162 0163 bool KisPaletteView::removeEntryWithDialog(QModelIndex index) 0164 { 0165 bool keepColors = false; 0166 if (qvariant_cast<bool>(index.data(KisPaletteModel::IsGroupNameRole))) { 0167 KoDialog dialog; 0168 dialog.setWindowTitle(i18nc("@title:dialog","Removing Group")); 0169 QFormLayout *editableItems = new QFormLayout(dialog.mainWidget()); 0170 QCheckBox *chkKeep = new QCheckBox(); 0171 editableItems->addRow(i18nc("Shows up when deleting a swatch group", "Keep the Colors"), chkKeep); 0172 0173 if (dialog.exec() != KoDialog::Accepted) { return false; } 0174 keepColors = chkKeep->isChecked(); 0175 } 0176 m_d->model->removeEntry(index, keepColors); 0177 0178 saveModification(); 0179 0180 return true; 0181 } 0182 0183 void KisPaletteView::selectClosestColor(const KoColor &color) 0184 { 0185 KoColorSetSP color_set = m_d->model->colorSet(); 0186 if (!color_set) { 0187 return; 0188 } 0189 //also don't select if the color is the same as the current selection 0190 if (m_d->model->getEntry(currentIndex()).color() == color) { 0191 return; 0192 } 0193 0194 selectionModel()->clearSelection(); 0195 QModelIndex index = m_d->model->indexForClosest(color); 0196 0197 selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select); 0198 } 0199 0200 const KoColor KisPaletteView::closestColor(const KoColor &color) const 0201 { 0202 QModelIndex index = m_d->model->indexForClosest(color); 0203 KisSwatch swatch = m_d->model->getEntry(index); 0204 return swatch.color(); 0205 } 0206 0207 void KisPaletteView::slotFGColorChanged(const KoColor &color) 0208 { 0209 selectClosestColor(color); 0210 } 0211 0212 void KisPaletteView::setPaletteModel(KisPaletteModel *model) 0213 { 0214 if (m_d->model) { 0215 disconnect(m_d->model, 0, this, 0); 0216 } 0217 m_d->model = model; 0218 setModel(model); 0219 slotAdditionalGuiUpdate(); 0220 0221 connect(model, SIGNAL(sigPaletteModified()), SLOT(slotAdditionalGuiUpdate())); 0222 connect(model, SIGNAL(sigPaletteChanged()), SLOT(slotAdditionalGuiUpdate())); 0223 } 0224 0225 KisPaletteModel* KisPaletteView::paletteModel() const 0226 { 0227 return m_d->model; 0228 } 0229 0230 void KisPaletteView::setAllowModification(bool allow) 0231 { 0232 m_d->allowPaletteModification = allow; 0233 setAcceptDrops(allow); 0234 } 0235 0236 void KisPaletteView::slotHorizontalHeaderResized(int, int, int newSize) 0237 { 0238 resizeRows(newSize); 0239 slotAdditionalGuiUpdate(); 0240 } 0241 0242 void KisPaletteView::resizeRows(int newSize) 0243 { 0244 verticalHeader()->setDefaultSectionSize(newSize); 0245 verticalHeader()->resizeSections(QHeaderView::Fixed); 0246 } 0247 0248 void KisPaletteView::saveModification() 0249 { 0250 //qDebug() << "saving modification in palette view" << m_d->model->colorSet()->filename() << m_d->model->colorSet()->storageLocation(); 0251 KisResourceUserOperations::updateResourceWithUserInput(this, m_d->model->colorSet()); 0252 } 0253 0254 void KisPaletteView::removeSelectedEntry() 0255 { 0256 if (selectedIndexes().size() <= 0) { 0257 return; 0258 } 0259 m_d->model->removeEntry(currentIndex()); 0260 } 0261 0262 void KisPaletteView::slotAdditionalGuiUpdate() 0263 { 0264 clearSpans(); 0265 resizeRows(verticalHeader()->defaultSectionSize()); 0266 for (int groupNameRowNumber : m_d->model->m_rowGroupNameMap.keys()) { 0267 if (groupNameRowNumber == -1) { continue; } 0268 setSpan(groupNameRowNumber, 0, 1, m_d->model->columnCount()); 0269 setRowHeight(groupNameRowNumber, fontMetrics().lineSpacing() + 6); 0270 verticalHeader()->resizeSection(groupNameRowNumber, fontMetrics().lineSpacing() + 6); 0271 } 0272 emit sigPaletteUpdatedFromModel(); 0273 } 0274 0275 void KisPaletteView::slotCurrentSelectionChanged(const QModelIndex &newCurrent) 0276 { 0277 if (!newCurrent.isValid()) { return; } 0278 0279 const bool isGroupName = newCurrent.data(KisPaletteModel::IsGroupNameRole).toBool(); 0280 const bool isCheckSlot = newCurrent.data(KisPaletteModel::CheckSlotRole).toBool(); 0281 0282 const KisSwatch newEntry = m_d->model->getEntry(newCurrent); 0283 0284 emit sigIndexSelected(newCurrent); 0285 if (isGroupName) { 0286 return; 0287 } 0288 0289 if (isCheckSlot) { 0290 emit sigColorSelected(newEntry.color()); 0291 } 0292 } 0293 0294 void KisPaletteView::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) 0295 { 0296 Q_ASSERT(m_d->model); 0297 m_d->model->setDisplayRenderer(displayRenderer); 0298 }