diff --git a/libs/ui/dialogs/KisDlgPaletteEditor.cpp b/libs/ui/dialogs/KisDlgPaletteEditor.cpp index 686a430cd7..59abd11580 100644 --- a/libs/ui/dialogs/KisDlgPaletteEditor.cpp +++ b/libs/ui/dialogs/KisDlgPaletteEditor.cpp @@ -1,230 +1,232 @@ /* * Copyright (c) 2018 Michael Zhou * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisPaletteEditor.h" #include "ui_WdgDlgPaletteEditor.h" #include "KisDlgPaletteEditor.h" KisDlgPaletteEditor::KisDlgPaletteEditor() : m_ui(new Ui_WdgDlgPaletteEditor) , m_actAddGroup(new QAction(i18n("Add a group"))) , m_actDelGroup(new QAction(i18n("Delete this group"))) , m_actRenGroup(new QAction(i18n("Rename this group"))) , m_paletteEditor(new KisPaletteEditor(this)) , m_currentGroupOriginalName(KoColorSet::GLOBAL_GROUP_NAME) { + setWindowTitle(i18n("Palette Editor")); + m_ui->setupUi(this); m_ui->gbxPalette->setTitle(i18n("Palette settings")); m_ui->labelFilename->setText(i18n("Filename")); m_ui->labelName->setText(i18n("Palette Name")); m_ui->bnAddGroup->setDefaultAction(m_actAddGroup.data()); m_ui->gbxGroup->setTitle(i18n("Group settings")); m_ui->labelColCount->setText(i18n("Column count")); m_ui->labelRowCount->setText(i18n("Row count")); m_ui->bnDelGroup->setDefaultAction(m_actDelGroup.data()); m_ui->bnRenGroup->setDefaultAction(m_actRenGroup.data()); connect(m_actAddGroup.data(), SIGNAL(triggered(bool)), SLOT(slotAddGroup())); connect(m_actDelGroup.data(), SIGNAL(triggered(bool)), SLOT(slotDelGroup())); connect(m_actRenGroup.data(), SIGNAL(triggered(bool)), SLOT(slotRenGroup())); connect(m_ui->spinBoxRow, SIGNAL(valueChanged(int)), SLOT(slotRowCountChanged(int))); connect(m_ui->spinBoxCol, SIGNAL(valueChanged(int)), SLOT(slotColCountChanged(int))); connect(m_ui->lineEditName, SIGNAL(editingFinished()), SLOT(slotNameChanged())); connect(m_ui->lineEditFilename, SIGNAL(textEdited(QString)), SLOT(slotFilenameChanged(QString))); connect(m_ui->lineEditFilename, SIGNAL(editingFinished()), SLOT(slotFilenameInputFinished())); connect(m_ui->ckxGlobal, SIGNAL(stateChanged(int)), SLOT(slotSetGlobal(int))); connect(m_ui->ckxReadOnly, SIGNAL(stateChanged(int)), SLOT(slotSetReadOnly(int))); connect(this, SIGNAL(accepted()), SLOT(slotAccepted())); m_warnPalette.setColor(QPalette::Text, Qt::red); } KisDlgPaletteEditor::~KisDlgPaletteEditor() { } void KisDlgPaletteEditor::setPaletteModel(KisPaletteModel *model) { m_colorSet = model->colorSet(); if (m_colorSet.isNull()) { return; } m_paletteEditor->setPaletteModel(model); // don't let editor make changes when initializing const QSignalBlocker blocker1(m_ui->lineEditFilename); const QSignalBlocker blocker2(m_ui->lineEditName); const QSignalBlocker blocker3(m_ui->spinBoxCol); const QSignalBlocker blocker4(m_ui->spinBoxRow); const QSignalBlocker blocker5(m_ui->ckxGlobal); const QSignalBlocker blocker6(m_ui->ckxReadOnly); const QSignalBlocker blocker7(m_ui->cbxGroup); m_ui->lineEditName->setText(m_colorSet->name()); m_ui->lineEditFilename->setText(m_colorSet->filename()); m_ui->spinBoxCol->setValue(m_colorSet->columnCount()); m_ui->ckxGlobal->setCheckState(m_colorSet->isGlobal() ? Qt::Checked : Qt::Unchecked); m_ui->ckxReadOnly->setCheckState(!m_colorSet->isEditable() ? Qt::Checked : Qt::Unchecked); Q_FOREACH (const QString & groupName, m_colorSet->getGroupNames()) { m_ui->cbxGroup->addItem(groupName); } connect(m_ui->cbxGroup, SIGNAL(currentTextChanged(QString)), SLOT(slotGroupChosen(QString))); m_ui->cbxGroup->setCurrentText(KoColorSet::GLOBAL_GROUP_NAME); m_ui->bnDelGroup->setEnabled(false); m_ui->bnRenGroup->setEnabled(false); m_ui->spinBoxRow->setValue(m_paletteEditor->rowNumberOfGroup(KoColorSet::GLOBAL_GROUP_NAME)); bool canWrite = m_colorSet->isEditable(); m_ui->lineEditName->setEnabled(canWrite); m_ui->lineEditFilename->setEnabled(canWrite); m_ui->spinBoxCol->setEnabled(canWrite); m_ui->spinBoxRow->setEnabled(canWrite); m_ui->ckxGlobal->setEnabled(canWrite); m_ui->ckxReadOnly->setEnabled(canWrite && m_colorSet->isGlobal()); m_ui->bnAddGroup->setEnabled(canWrite); } void KisDlgPaletteEditor::setView(KisViewManager *view) { m_paletteEditor->setView(view); } void KisDlgPaletteEditor::slotAddGroup() { QString newGroupName = m_paletteEditor->addGroup(); if (!newGroupName.isEmpty()) { m_ui->cbxGroup->addItem(newGroupName); m_ui->cbxGroup->setCurrentIndex(m_ui->cbxGroup->count() - 1); }; } void KisDlgPaletteEditor::slotRenGroup() { QString newName = m_paletteEditor->renameGroup(m_currentGroupOriginalName); if (!newName.isEmpty()) { int idx = m_ui->cbxGroup->currentIndex(); m_ui->cbxGroup->removeItem(idx); m_ui->cbxGroup->insertItem(idx, newName); m_ui->cbxGroup->setCurrentIndex(idx); } } void KisDlgPaletteEditor::slotDelGroup() { int deletedIdx = m_ui->cbxGroup->currentIndex(); if (m_paletteEditor->removeGroup(m_currentGroupOriginalName)) { m_ui->cbxGroup->setCurrentIndex(0); m_ui->cbxGroup->removeItem(deletedIdx); } } void KisDlgPaletteEditor::slotGroupChosen(const QString &groupName) { if (groupName == KoColorSet::GLOBAL_GROUP_NAME) { m_ui->bnDelGroup->setEnabled(false); m_ui->bnRenGroup->setEnabled(false); } else { m_ui->bnDelGroup->setEnabled(true); m_ui->bnRenGroup->setEnabled(true); } m_currentGroupOriginalName = m_paletteEditor->oldNameFromNewName(groupName); m_ui->spinBoxRow->setValue(m_paletteEditor->rowNumberOfGroup(m_currentGroupOriginalName)); } void KisDlgPaletteEditor::slotRowCountChanged(int newCount) { m_paletteEditor->changeGroupRowCount(m_currentGroupOriginalName, newCount); } void KisDlgPaletteEditor::slotSetGlobal(int state) { bool toGlobal = (state == Qt::Checked); m_paletteEditor->setGlobal(toGlobal); if (!toGlobal) { m_ui->ckxReadOnly->setCheckState(Qt::Unchecked); } m_ui->ckxReadOnly->setEnabled(toGlobal); } void KisDlgPaletteEditor::slotSetReadOnly(int state) { m_paletteEditor->setReadOnly(state == Qt::Checked); } void KisDlgPaletteEditor::slotNameChanged() { m_paletteEditor->rename(qobject_cast(sender())->text()); } void KisDlgPaletteEditor::slotFilenameChanged(const QString &newFilename) { if (m_paletteEditor->duplicateExistsFilename(newFilename)) { m_ui->lineEditFilename->setPalette(m_warnPalette); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); return; } m_ui->lineEditFilename->setPalette(m_normalPalette); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); m_paletteEditor->changeFilename(newFilename); } void KisDlgPaletteEditor::slotFilenameInputFinished() { QString newName = m_ui->lineEditFilename->text(); if (m_paletteEditor->duplicateExistsFilename(newName)) { return; } m_paletteEditor->changeFilename(newName); } void KisDlgPaletteEditor::slotColCountChanged(int newCount) { m_paletteEditor->changeColCount(newCount); } void KisDlgPaletteEditor::slotAccepted() { m_paletteEditor->updatePalette(); } diff --git a/libs/widgets/KisPaletteComboBox.cpp b/libs/widgets/KisPaletteComboBox.cpp index 481bb6e3c7..7c780010fc 100644 --- a/libs/widgets/KisPaletteComboBox.cpp +++ b/libs/widgets/KisPaletteComboBox.cpp @@ -1,159 +1,156 @@ /* * Copyright (c) 2018 Michael Zhou * * 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. */ // Qt #include #include #include #include // STL #include #include "kis_palette_view.h" #include "KisPaletteComboBox.h" KisPaletteComboBox::KisPaletteComboBox(QWidget *parent) : QComboBox(parent) , m_model(Q_NULLPTR) { setEditable(true); setInsertPolicy(NoInsert); completer()->setCompletionMode(QCompleter::PopupCompletion); completer()->setCaseSensitivity(Qt::CaseInsensitive); completer()->setFilterMode(Qt::MatchContains); connect(this, SIGNAL(currentIndexChanged(int)), SLOT(slotIndexUpdated(int))); } KisPaletteComboBox::~KisPaletteComboBox() { } void KisPaletteComboBox::setPaletteModel(const KisPaletteModel *paletteModel) { if (!m_model.isNull()) { m_model->disconnect(this); } m_model = paletteModel; if (m_model.isNull()) { return; } slotPaletteChanged(); connect(m_model, SIGNAL(sigPaletteChanged()), SLOT(slotPaletteChanged())); connect(m_model, SIGNAL(sigPaletteModified()), SLOT(slotPaletteChanged())); } void KisPaletteComboBox::setCompanionView(KisPaletteView *view) { if (!m_view.isNull()) { m_view->disconnect(this); disconnect(m_view.data()); } m_view = view; setPaletteModel(view->paletteModel()); connect(view, SIGNAL(sigIndexSelected(QModelIndex)), SLOT(slotSwatchSelected(QModelIndex))); connect(this, SIGNAL(sigColorSelected(KoColor)), view, SLOT(slotFGColorChanged(KoColor))); } void KisPaletteComboBox::slotPaletteChanged() { clear(); m_groupMapMap.clear(); m_idxSwatchMap.clear(); if (QPointer(m_model->colorSet()).isNull()) { return; } for (const QString &groupName : m_model->colorSet()->getGroupNames()) { QVector infoList; PosIdxMapType posIdxMap; const KisSwatchGroup *group = m_model->colorSet()->getGroup(groupName); for (const SwatchInfoType &info : group->infoList()) { infoList.append(info); } std::sort(infoList.begin(), infoList.end(), swatchInfoLess); for (const SwatchInfoType &info : infoList) { const KisSwatch &swatch = info.swatch; QString name = swatch.name(); if (!swatch.id().isEmpty()){ name = swatch.id() + " - " + swatch.name(); } addItem(QIcon(createColorSquare(swatch)), name); posIdxMap[SwatchPosType(info.column, info.row)] = count() - 1; m_idxSwatchMap.push_back(swatch); } m_groupMapMap[group->name()] = posIdxMap; } - if (!m_view.isNull()) { + if (m_view.isNull()) { setCurrentIndex(0); } QModelIndex idx = m_view->currentIndex(); if (!idx.isValid()) { return; } - if (!qvariant_cast(idx.data(KisPaletteModel::IsGroupNameRole))) { return; } + if (qvariant_cast(idx.data(KisPaletteModel::IsGroupNameRole))) { return; } if (!qvariant_cast(idx.data(KisPaletteModel::CheckSlotRole))) { return; } - QString groupName = qvariant_cast(idx.data(KisPaletteModel::GroupNameRole)); - int rowInGroup = qvariant_cast(idx.data(KisPaletteModel::RowInGroupRole)); - blockSignals(true); // this is a passive selection; this shouldn't make others change - setCurrentIndex(m_groupMapMap[groupName][SwatchPosType(idx.column(), rowInGroup)]); + slotSwatchSelected(idx); blockSignals(false); } bool KisPaletteComboBox::swatchInfoLess(const SwatchInfoType &first, const SwatchInfoType &second) { return first.swatch.name() < second.swatch.name(); } QPixmap KisPaletteComboBox::createColorSquare(const KisSwatch &swatch) const { QPixmap colorSquare(32, 32); if (swatch.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(swatch.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(swatch.color().toQColor()); } return colorSquare; } void KisPaletteComboBox::slotSwatchSelected(const QModelIndex &index) { QString gName = qvariant_cast(index.data(KisPaletteModel::GroupNameRole)); int rowInGroup = qvariant_cast(index.data(KisPaletteModel::RowInGroupRole)); setCurrentIndex(m_groupMapMap[gName][SwatchPosType(index.column(), rowInGroup)]); } void KisPaletteComboBox::slotIndexUpdated(int idx) { if (idx >= 0 && idx < m_idxSwatchMap.size()) { emit sigColorSelected(m_idxSwatchMap[idx].color()); } } diff --git a/libs/widgets/KisPaletteModel.cpp b/libs/widgets/KisPaletteModel.cpp index dc0227b009..0cd85e93cc 100644 --- a/libs/widgets/KisPaletteModel.cpp +++ b/libs/widgets/KisPaletteModel.cpp @@ -1,483 +1,483 @@ /* * Copyright (c) 2013 Sven Langkamp * Copyright (c) 2018 Michael Zhou * * 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 KisPaletteModel::KisPaletteModel(QObject* parent) : QAbstractTableModel(parent) , m_colorSet(0) , m_displayRenderer(KoDumbColorDisplayRenderer::instance()) { connect(this, SIGNAL(sigPaletteModified()), SLOT(slotPaletteModified())); } KisPaletteModel::~KisPaletteModel() { } QVariant KisPaletteModel::data(const QModelIndex& index, int role) const { bool groupNameRow = m_groupNameRows.contains(index.row()); if (role == IsGroupNameRole) { return groupNameRow; } if (groupNameRow) { return dataForGroupNameRow(index, role); } else { return dataForSwatch(index, role); } } int KisPaletteModel::rowCount(const QModelIndex& /*parent*/) const { if (!m_colorSet) return 0; return m_colorSet->rowCount() // count of color rows + m_groupNameRows.size() // rows for names - 1; // global doesn't have a name } int KisPaletteModel::columnCount(const QModelIndex& /*parent*/) const { if (m_colorSet && m_colorSet->columnCount() > 0) { return m_colorSet->columnCount(); } if (!m_colorSet) { return 0; } return 16; } 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 { Q_UNUSED(parent); Q_ASSERT(m_colorSet); int groupNameRow = groupNameRowForRow(row); KisSwatchGroup *group = m_colorSet->getGroup(m_groupNameRows[groupNameRow]); Q_ASSERT(group); return createIndex(row, column, group); } void KisPaletteModel::setPalette(KoColorSet* palette) { beginResetModel(); m_groupNameRows.clear(); m_colorSet = palette; if (palette) { int row = -1; for (const QString &groupName : m_colorSet->getGroupNames()) { m_groupNameRows[row] = groupName; row += m_colorSet->getGroup(groupName)->rowCount(); row += 1; // row for group name } } endResetModel(); emit sigPaletteChanged(); } KoColorSet* KisPaletteModel::colorSet() const { return m_colorSet; } int KisPaletteModel::rowNumberInGroup(int rowInModel) const { if (m_groupNameRows.contains(rowInModel)) { return -1; } for (auto it = m_groupNameRows.keys().rbegin(); it != m_groupNameRows.keys().rend(); it++) { if (*it < rowInModel) { return rowInModel - *it - 1; } } return rowInModel; } bool KisPaletteModel::addEntry(const KisSwatch &entry, const QString &groupName) { - beginResetModel(); + beginInsertRows(QModelIndex(), rowCount(), rowCount() + 1); m_colorSet->add(entry, groupName); - endResetModel(); + endInsertRows(); if (m_colorSet->isGlobal()) { m_colorSet->save(); } emit sigPaletteModified(); return true; } bool KisPaletteModel::removeEntry(const QModelIndex &index, bool keepColors) { if (!qvariant_cast(data(index, IsGroupNameRole))) { static_cast(index.internalPointer())->removeEntry(index.column(), rowNumberInGroup(index.row())); emit dataChanged(index, index); } else { int groupNameRow = groupNameRowForRow(index.row()); QString groupName = m_groupNameRows[groupNameRow]; removeGroup(groupName, keepColors); } emit sigPaletteModified(); return true; } void KisPaletteModel::removeGroup(const QString &groupName, bool keepColors) { beginResetModel(); m_colorSet->removeGroup(groupName, keepColors); m_groupNameRows.clear(); int row = -1; for (const QString &groupName : m_colorSet->getGroupNames()) { m_groupNameRows[row] = groupName; row += m_colorSet->getGroup(groupName)->rowCount(); row += 1; // row for group name } endResetModel(); } bool KisPaletteModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { Q_UNUSED(row); Q_UNUSED(column); if (!data->hasFormat("krita/x-colorsetentry") && !data->hasFormat("krita/x-colorsetgroup")) { return false; } if (action == Qt::IgnoreAction) { return false; } if (data->hasFormat("krita/x-colorsetgroup")) { // dragging group not supported for now /* 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; } */ return true; } QModelIndex finalIdx = parent; if (!finalIdx.isValid()) { return false; } if (qvariant_cast(finalIdx.data(KisPaletteModel::IsGroupNameRole))) { return true; } QByteArray encodedData = data->data("krita/x-colorsetentry"); QDataStream stream(&encodedData, QIODevice::ReadOnly); while (!stream.atEnd()) { KisSwatch entry; QString name, id; bool spotColor; QString oldGroupName; int oriRow; int oriColumn; QString colorXml; stream >> name >> id >> spotColor >> oriRow >> oriColumn >> 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.setColor(KoColor::fromXML(c, colorDepthId)); } if (action == Qt::MoveAction){ KisSwatchGroup *g = m_colorSet->getGroup(oldGroupName); if (g) { if (qvariant_cast(finalIdx.data(KisPaletteModel::CheckSlotRole))) { g->setEntry(getEntry(finalIdx), oriColumn, oriRow); } else { g->removeEntry(oriColumn, oriRow); } } setEntry(entry, finalIdx); emit sigPaletteModified(); if (m_colorSet->isGlobal()) { m_colorSet->save(); } } } return true; } QMimeData *KisPaletteModel::mimeData(const QModelIndexList &indexes) const { QMimeData *mimeData = new QMimeData(); QByteArray encodedData; QDataStream stream(&encodedData, QIODevice::WriteOnly); QModelIndex index = indexes.last(); if (index.isValid() && qvariant_cast(index.data(CheckSlotRole))) { QString mimeTypeName = "krita/x-colorsetentry"; if (qvariant_cast(index.data(IsGroupNameRole))==false) { KisSwatch entry = getEntry(index); QDomDocument doc; QDomElement root = doc.createElement("Color"); root.setAttribute("bitdepth", entry.color().colorSpace()->colorDepthId().id()); doc.appendChild(root); entry.color().toXML(doc, root); stream << entry.name() << entry.id() << entry.spotColor() << rowNumberInGroup(index.row()) << index.column() << qvariant_cast(index.data(GroupNameRole)) << 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; } void KisPaletteModel::setEntry(const KisSwatch &entry, const QModelIndex &index) { KisSwatchGroup *group = static_cast(index.internalPointer()); Q_ASSERT(group); group->setEntry(entry, index.column(), rowNumberInGroup(index.row())); emit sigPaletteModified(); emit dataChanged(index, index); if (m_colorSet->isGlobal()) { m_colorSet->save(); } } bool KisPaletteModel::renameGroup(const QString &groupName, const QString &newName) { beginResetModel(); bool success = m_colorSet->changeGroupName(groupName, newName); for (auto it = m_groupNameRows.begin(); it != m_groupNameRows.end(); it++) { if (it.value() == groupName) { m_groupNameRows[it.key()] = newName; break; } } endResetModel(); emit sigPaletteModified(); return success; } void KisPaletteModel::addGroup(const KisSwatchGroup &group) { beginInsertRows(QModelIndex(), rowCount(), rowCount() + group.rowCount()); m_colorSet->addGroup(group.name()); *m_colorSet->getGroup(group.name()) = group; endInsertColumns(); emit sigPaletteModified(); } void KisPaletteModel::setRowNumber(const QString &groupName, int rowCount) { beginResetModel(); KisSwatchGroup *g = m_colorSet->getGroup(groupName); if (g) { g->setRowCount(rowCount); } endResetModel(); } QVariant KisPaletteModel::dataForGroupNameRow(const QModelIndex &idx, int role) const { KisSwatchGroup *group = static_cast(idx.internalPointer()); Q_ASSERT(group); QString groupName = group->name(); switch (role) { case Qt::ToolTipRole: case Qt::DisplayRole: { return groupName; } case GroupNameRole: { return groupName; } case CheckSlotRole: { return true; } case RowInGroupRole: { return -1; } default: { return QVariant(); } } } QVariant KisPaletteModel::dataForSwatch(const QModelIndex &idx, int role) const { KisSwatchGroup *group = static_cast(idx.internalPointer()); Q_ASSERT(group); int rowInGroup = rowNumberInGroup(idx.row()); bool entryPresent = group->checkEntry(idx.column(), rowInGroup); KisSwatch entry; if (entryPresent) { entry = group->getEntry(idx.column(), rowInGroup); } switch (role) { case Qt::ToolTipRole: case Qt::DisplayRole: { return entryPresent ? entry.name() : i18n("Empty slot"); } case Qt::BackgroundRole: { QColor color(0, 0, 0, 0); if (entryPresent) { color = m_displayRenderer->toQColor(entry.color()); } return QBrush(color); } case GroupNameRole: { return group->name(); } case CheckSlotRole: { return entryPresent; } case RowInGroupRole: { return rowInGroup; } default: { return QVariant(); } } } void KisPaletteModel::setDisplayRenderer(const 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(); } void KisPaletteModel::slotPaletteModified() { m_colorSet->setPaletteType(KoColorSet::KPL); } QModelIndex KisPaletteModel::indexForClosest(const KoColor &compare) { KisSwatchGroup::SwatchInfo info = colorSet()->getClosestColorInfo(compare); return createIndex(indexRowForInfo(info), info.column, colorSet()->getGroup(info.group)); } int KisPaletteModel::indexRowForInfo(const KisSwatchGroup::SwatchInfo &info) { for (auto it = m_groupNameRows.begin(); it != m_groupNameRows.end(); it++) { if (it.value() == info.group) { return it.key() + info.row + 1; } } return info.row; } KisSwatch KisPaletteModel::getEntry(const QModelIndex &index) const { KisSwatchGroup *group = static_cast(index.internalPointer()); if (!group || !group->checkEntry(index.column(), rowNumberInGroup(index.row()))) { return KisSwatch(); } return group->getEntry(index.column(), rowNumberInGroup(index.row())); } int KisPaletteModel::groupNameRowForRow(int rowInModel) const { return rowInModel - rowNumberInGroup(rowInModel) - 1; } diff --git a/plugins/dockers/palettedocker/palettedocker_dock.cpp b/plugins/dockers/palettedocker/palettedocker_dock.cpp index 5748e33570..d20017c69d 100644 --- a/plugins/dockers/palettedocker/palettedocker_dock.cpp +++ b/plugins/dockers/palettedocker/palettedocker_dock.cpp @@ -1,358 +1,366 @@ /* * 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 #include #include #include #include #include #include #include #include "ui_wdgpalettedock.h" PaletteDockerDock::PaletteDockerDock( ) : QDockWidget(i18n("Palette")) , m_ui(new Ui_WdgPaletteDock()) , m_model(new KisPaletteModel(this)) , m_paletteChooser(new KisPaletteListWidget(this)) , m_view(Q_NULLPTR) , m_resourceProvider(Q_NULLPTR) , m_rServer(KoResourceServerProvider::instance()->paletteServer()) , m_rAdapter(new KoResourceServerAdapter(KoResourceServerProvider::instance()->paletteServer())) , m_activeDocument(Q_NULLPTR) , m_paletteEditor(new KisPaletteEditor) , m_actAdd(new QAction(KisIconUtils::loadIcon("list-add"), i18n("Add foreground color"))) , m_actRemove(new QAction(KisIconUtils::loadIcon("edit-delete"), i18n("Delete color"))) , m_actModify(new QAction(KisIconUtils::loadIcon("edit-rename"), i18n("Modify this spot"))) , m_actEditPalette(new QAction(KisIconUtils::loadIcon("groupLayer"), i18n("Edit this palette"))) { QWidget *mainWidget = new QWidget(this); setWidget(mainWidget); m_ui->setupUi(mainWidget); m_ui->bnAdd->setDefaultAction(m_actAdd.data()); m_ui->bnRemove->setDefaultAction(m_actRemove.data()); m_ui->bnRename->setDefaultAction(m_actModify.data()); m_ui->bnEditPalette->setDefaultAction(m_actEditPalette.data()); // to make sure their icons have the same size m_ui->bnRemove->setIconSize(QSize(16, 16)); m_ui->bnRename->setIconSize(QSize(16, 16)); m_ui->bnAdd->setIconSize(QSize(16, 16)); m_ui->bnEditPalette->setIconSize(QSize(16, 16)); m_ui->paletteView->setPaletteModel(m_model); m_ui->paletteView->setAllowModification(true); m_ui->cmbNameList->setCompanionView(m_ui->paletteView); m_paletteEditor->setPaletteModel(m_model); connect(m_actAdd.data(), SIGNAL(triggered()), SLOT(slotAddColor())); connect(m_actRemove.data(), SIGNAL(triggered()), SLOT(slotRemoveColor())); connect(m_actModify.data(), SIGNAL(triggered()), SLOT(slotEditEntry())); connect(m_actEditPalette.data(), SIGNAL(triggered()), SLOT(slotEditPalette())); connect(m_ui->paletteView, SIGNAL(sigIndexSelected(QModelIndex)), SLOT(slotPaletteIndexSelected(QModelIndex))); connect(m_ui->paletteView, SIGNAL(doubleClicked(QModelIndex)), SLOT(slotPaletteIndexDoubleClicked(QModelIndex))); - m_viewContextMenu.addAction(m_actRemove.data()); m_viewContextMenu.addAction(m_actModify.data()); + m_viewContextMenu.addAction(m_actRemove.data()); + connect(m_ui->paletteView, SIGNAL(pressed(QModelIndex)), SLOT(slotContextMenu(QModelIndex))); m_paletteChooser->setAllowModification(true); connect(m_paletteChooser, SIGNAL(sigPaletteSelected(KoColorSet*)), SLOT(slotSetColorSet(KoColorSet*))); connect(m_paletteChooser, SIGNAL(sigAddPalette()), SLOT(slotAddPalette())); connect(m_paletteChooser, SIGNAL(sigImportPalette()), SLOT(slotImportPalette())); connect(m_paletteChooser, SIGNAL(sigRemovePalette(KoColorSet*)), SLOT(slotRemovePalette(KoColorSet*))); connect(m_paletteChooser, SIGNAL(sigExportPalette(KoColorSet*)), SLOT(slotExportPalette(KoColorSet*))); m_ui->bnColorSets->setIcon(KisIconUtils::loadIcon("hi16-palette_library")); m_ui->bnColorSets->setToolTip(i18n("Choose palette")); m_ui->bnColorSets->setPopupWidget(m_paletteChooser); KisConfig cfg(true); QString defaultPaletteName = cfg.defaultPalette(); KoColorSet* defaultPalette = m_rServer->resourceByName(defaultPaletteName); if (defaultPalette) { slotSetColorSet(defaultPalette); } else { m_ui->bnAdd->setEnabled(false); m_ui->bnRename->setEnabled(false); m_ui->bnRemove->setEnabled(false); m_ui->bnEditPalette->setEnabled(false); m_ui->paletteView->setAllowModification(false); } } PaletteDockerDock::~PaletteDockerDock() { } void PaletteDockerDock::setViewManager(KisViewManager* kisview) { m_view = 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_ui->paletteView, SLOT(slotFGColorChanged(KoColor))); kisview->nodeManager()->disconnect(m_model); } +void PaletteDockerDock::slotContextMenu(const QModelIndex &) +{ + if (QApplication::mouseButtons() == Qt::RightButton) { + m_viewContextMenu.exec(QCursor::pos()); + } +} + void PaletteDockerDock::slotAddPalette() { m_paletteEditor->addPalette(); } void PaletteDockerDock::slotRemovePalette(KoColorSet *cs) { m_paletteEditor->removePalette(cs); } void PaletteDockerDock::slotImportPalette() { m_paletteEditor->importPalette(); } void PaletteDockerDock::slotExportPalette(KoColorSet *palette) { KoFileDialog dialog(this, KoFileDialog::SaveFile, "Save Palette"); dialog.setDefaultDir(palette->filename()); dialog.setMimeTypeFilters(QStringList() << "krita/x-colorset"); QString newPath; bool isStandAlone = palette->isGlobal(); QString oriPath = palette->filename(); if ((newPath = dialog.filename()).isEmpty()) { return; } palette->setFilename(newPath); palette->setIsGlobal(true); palette->save(); palette->setFilename(oriPath); palette->setIsGlobal(isStandAlone); } void PaletteDockerDock::setCanvas(KoCanvasBase *canvas) { setEnabled(canvas != Q_NULLPTR); if (canvas) { KisCanvas2 *cv = qobject_cast(canvas); m_ui->paletteView->setDisplayRenderer(cv->displayColorConverter()->displayRendererInterface()); } if (m_activeDocument) { for (KoColorSet * &cs : m_activeDocument->paletteList()) { KoColorSet *tmpAddr = cs; cs = new KoColorSet(*cs); m_rAdapter->removeResource(tmpAddr); } } if (m_view && m_view->document()) { m_activeDocument = m_view->document(); m_paletteEditor->setView(m_view); for (KoColorSet *cs : m_activeDocument->paletteList()) { m_rAdapter->addResource(cs); } } if (!m_currentColorSet) { slotSetColorSet(Q_NULLPTR); } } void PaletteDockerDock::unsetCanvas() { setEnabled(false); m_ui->paletteView->setDisplayRenderer(Q_NULLPTR); m_paletteEditor->setView(Q_NULLPTR); for (KoResource *r : m_rServer->resources()) { KoColorSet *g = static_cast(r); if (!g->isGlobal()) { m_rAdapter->removeResource(r); } } if (!m_currentColorSet) { slotSetColorSet(Q_NULLPTR); } } void PaletteDockerDock::slotSetColorSet(KoColorSet* colorSet) { if (colorSet && colorSet->isEditable()) { m_ui->bnAdd->setEnabled(true); m_ui->bnRename->setEnabled(true); m_ui->bnRemove->setEnabled(true); m_ui->bnEditPalette->setEnabled(true); m_ui->paletteView->setAllowModification(true); } else { m_ui->bnAdd->setEnabled(false); m_ui->bnRename->setEnabled(false); m_ui->bnRemove->setEnabled(false); m_ui->bnEditPalette->setEnabled(false); m_ui->paletteView->setAllowModification(false); } m_currentColorSet = colorSet; m_model->setPalette(colorSet); if (colorSet) { KisConfig cfg(true); cfg.setDefaultPalette(colorSet->name()); m_ui->bnColorSets->setText(colorSet->name()); } else { m_ui->bnColorSets->setText(""); } } void PaletteDockerDock::slotEditPalette() { KisDlgPaletteEditor dlg; if (!m_currentColorSet) { return; } dlg.setPaletteModel(m_model); dlg.setView(m_view); if (dlg.exec() != QDialog::Accepted){ return; } slotSetColorSet(m_currentColorSet); // update GUI } void PaletteDockerDock::slotAddColor() { if (m_currentColorSet->isEditable()) { if (m_resourceProvider) { m_paletteEditor->addEntry(m_resourceProvider->fgColor()); } } } void PaletteDockerDock::slotRemoveColor() { if (m_currentColorSet->isEditable()) { QModelIndex index = m_ui->paletteView->currentIndex(); if (!index.isValid()) { return; } m_paletteEditor->removeEntry(index); m_ui->bnRemove->setEnabled(false); } } void PaletteDockerDock::setFGColorByPalette(const KisSwatch &entry) { if (m_resourceProvider) { m_resourceProvider->setFGColor(entry.color()); } } void PaletteDockerDock::saveToWorkspace(KisWorkspaceResource* workspace) { if (!m_currentColorSet.isNull()) { 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) { slotSetColorSet(colorSet); } } } void PaletteDockerDock::slotPaletteIndexSelected(const QModelIndex &index) { bool slotEmpty = !(qvariant_cast(index.data(KisPaletteModel::CheckSlotRole))); if (slotEmpty) { if (!m_currentColorSet->isEditable()) { return; } setEntryByForeground(index); } else { m_ui->bnRemove->setEnabled(true); KisSwatch entry = m_model->getEntry(index); setFGColorByPalette(entry); } } void PaletteDockerDock::slotPaletteIndexDoubleClicked(const QModelIndex &index) { m_paletteEditor->modifyEntry(index); } void PaletteDockerDock::setEntryByForeground(const QModelIndex &index) { m_paletteEditor->setEntry(m_resourceProvider->fgColor(), index); if (m_currentColorSet->isEditable()) { m_ui->bnRemove->setEnabled(true); } } void PaletteDockerDock::slotEditEntry() { if (m_currentColorSet->isEditable()) { QModelIndex index = m_ui->paletteView->currentIndex(); if (!index.isValid()) { return; } m_paletteEditor->modifyEntry(index); } } void PaletteDockerDock::slotNameListSelection(const KoColor &color) { m_resourceProvider->setFGColor(color); } diff --git a/plugins/dockers/palettedocker/palettedocker_dock.h b/plugins/dockers/palettedocker/palettedocker_dock.h index 5925c0fd3f..e144d80248 100644 --- a/plugins/dockers/palettedocker/palettedocker_dock.h +++ b/plugins/dockers/palettedocker/palettedocker_dock.h @@ -1,110 +1,113 @@ /* * 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. */ #ifndef PALETTEDOCKER_DOCK_H #define PALETTEDOCKER_DOCK_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class KisViewManager; class KisCanvasResourceProvider; class KisWorkspaceResource; class KisPaletteListWidget; class KisPaletteModel; class KisPaletteEditor; class Ui_WdgPaletteDock; class PaletteDockerDock : public QDockWidget, public KisMainwindowObserver { Q_OBJECT public: PaletteDockerDock(); ~PaletteDockerDock() override; public: // QDockWidget void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; public: // KisMainWindowObserver void setViewManager(KisViewManager* kisview) override; + private Q_SLOTS: + void slotContextMenu(const QModelIndex &); + void slotAddPalette(); void slotRemovePalette(KoColorSet *); void slotImportPalette(); void slotExportPalette(KoColorSet *); void slotAddColor(); void slotRemoveColor(); void slotEditEntry(); void slotEditPalette(); void slotPaletteIndexSelected(const QModelIndex &index); void slotPaletteIndexDoubleClicked(const QModelIndex &index); void slotNameListSelection(const KoColor &color); void slotSetColorSet(KoColorSet* colorSet); void saveToWorkspace(KisWorkspaceResource* workspace); void loadFromWorkspace(KisWorkspaceResource* workspace); private: void setEntryByForeground(const QModelIndex &index); void setFGColorByPalette(const KisSwatch &entry); private /* member variables */: QScopedPointer m_ui; KisPaletteModel *m_model; KisPaletteListWidget *m_paletteChooser; QPointer m_view; KisCanvasResourceProvider *m_resourceProvider; KoResourceServer * const m_rServer; QScopedPointer > m_rAdapter; QPointer m_activeDocument; QPointer m_currentColorSet; QScopedPointer m_paletteEditor; QScopedPointer m_actAdd; QScopedPointer m_actRemove; QScopedPointer m_actModify; QScopedPointer m_actEditPalette; QMenu m_viewContextMenu; }; #endif