File indexing completed on 2024-05-19 04:29:17

0001 /*
0002  *  SPDX-FileCopyrightText: 2018 Michael Zhou <simeirxh@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include <QHash>
0008 #include <QString>
0009 #include <QScopedPointer>
0010 #include <QPointer>
0011 #include <QFormLayout>
0012 #include <QCheckBox>
0013 #include <QLineEdit>
0014 #include <QLabel>
0015 #include <QSpinBox>
0016 #include <QComboBox>
0017 #include <QMessageBox>
0018 
0019 #include <KoDialog.h>
0020 #include <KoFileDialog.h>
0021 #include <KoColorSet.h>
0022 #include <KisSwatchGroup.h>
0023 #include <kis_signal_compressor.h>
0024 #include <KisViewManager.h>
0025 #include <KisDocument.h>
0026 #include <KoResourceServer.h>
0027 #include <KisStorageModel.h>
0028 #include <KoResourceServerProvider.h>
0029 #include <KisPaletteModel.h>
0030 #include <kis_color_button.h>
0031 
0032 #include "KisPaletteEditor.h"
0033 #include <KisGlobalResourcesInterface.h>
0034 #include <KisResourceUserOperations.h>
0035 
0036 struct KisPaletteEditor::PaletteInfo {
0037     QString name;
0038     QString filename;
0039     int columnCount;
0040     QString storageLocation;
0041     QHash<QString, KisSwatchGroupSP> groups;
0042 };
0043 
0044 struct KisPaletteEditor::Private
0045 {
0046     bool isNameModified {false};
0047     bool isColumnCountModified {false};
0048     QSet<QString> modifiedGroupNames; // key is original group name
0049     QSet<QString> newGroupNames;
0050     QSet<QString> keepColorGroups;
0051     QSet<QString> pathsToRemove;
0052     QString groupBeingRenamed;
0053     QPointer<KisPaletteModel> model;
0054     QPointer<KisViewManager> view;
0055     KisPaletteEditor::PaletteInfo modifiedPaletteInfo;
0056     QPointer<KoDialog> query;
0057     KoResourceServer<KoColorSet> *rServer {0};
0058 
0059     QPalette normalPalette;
0060     QPalette warnPalette;
0061 
0062 };
0063 
0064 KisPaletteEditor::KisPaletteEditor(QObject *parent)
0065     : QObject(parent)
0066     , m_d(new Private)
0067 {
0068     m_d->rServer = KoResourceServerProvider::instance()->paletteServer();
0069     m_d->warnPalette.setColor(QPalette::Text, Qt::red);
0070 }
0071 
0072 KisPaletteEditor::~KisPaletteEditor()
0073 { }
0074 
0075 void KisPaletteEditor::setPaletteModel(KisPaletteModel *model)
0076 {
0077     if (!model) { return; }
0078     m_d->model = model;
0079     slotPaletteChanged();
0080     connect(model, SIGNAL(sigPaletteChanged()), SLOT(slotPaletteChanged()));
0081     connect(model, SIGNAL(sigPaletteModified()), SLOT(slotSetDocumentModified()));
0082 }
0083 
0084 void KisPaletteEditor::setView(KisViewManager *view)
0085 {
0086     m_d->view = view;
0087 }
0088 
0089 KoColorSetSP KisPaletteEditor::addPalette()
0090 {
0091     if (!m_d->view) { return 0; }
0092     if (!m_d->view->document()) { return 0; }
0093 
0094     KoColorSetSP colorSet(new KoColorSet());
0095 
0096     KoDialog dialog;
0097     QFormLayout *layout = new QFormLayout(dialog.mainWidget());
0098     QLineEdit *le = new QLineEdit(i18nc("Default name for a new palette","New Palette"));
0099     layout->addRow(i18n("New palette name:"), le);
0100 
0101     QComboBox *cmbPaletteType = new QComboBox();
0102     cmbPaletteType->addItem(i18nc("Palette File Type", "Krita Palette (KPL)"));
0103     cmbPaletteType->addItem(i18nc("Palette File Type", "GIMP Palette (GPL)"));
0104     layout->addRow(cmbPaletteType);
0105 
0106     QCheckBox *chkSaveInDocument = new QCheckBox(i18n("Save Palette in the Current Document"));
0107     chkSaveInDocument->setChecked(false);
0108     layout->addRow(chkSaveInDocument);
0109 
0110 
0111     if (dialog.exec() != QDialog::Accepted) { return 0; }
0112 
0113     QString name = le->text();
0114     if (cmbPaletteType->currentIndex() == 0) {
0115         colorSet->setPaletteType(KoColorSet::KPL);
0116     }
0117     else {
0118         colorSet->setPaletteType(KoColorSet::GPL);
0119     }
0120     colorSet->setValid(true);
0121     colorSet->setName(name);
0122     colorSet->setFilename(name.split(" ").join("_")+colorSet->defaultFileExtension());
0123 
0124     QString resourceLocation = "";
0125     if (chkSaveInDocument->isChecked()) {
0126         resourceLocation = m_d->view->document()->linkedResourcesStorageId();
0127     }
0128 
0129     if (KisResourceUserOperations::addResourceWithUserInput(m_d->view->mainWindowAsQWidget(), colorSet, resourceLocation)) {
0130         return colorSet;
0131 
0132     }
0133 
0134     return 0;
0135 }
0136 
0137 KoColorSetSP KisPaletteEditor::importPalette()
0138 {
0139     KoFileDialog dialog(nullptr, KoFileDialog::OpenFile, "Open Palette");
0140     dialog.setCaption(i18n("Import Palette"));
0141 
0142     dialog.setDefaultDir(QDir::homePath());
0143     dialog.setMimeTypeFilters(QStringList() << "application/x-krita-palette" << "application/x-gimp-color-palette");
0144 
0145     QString filename = dialog.filename();
0146     if (filename.isEmpty()) {
0147         return nullptr;
0148     }
0149 
0150     QMessageBox messageBox;
0151     messageBox.setText(i18n("Do you want to store this palette in your current image?"));
0152     messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
0153     QString storageLocation = "";
0154     if (messageBox.exec() == QMessageBox::Yes) {
0155         storageLocation = m_d->view->document()->linkedResourcesStorageId();
0156     }
0157     KoResourceSP resource = KisResourceUserOperations::importResourceFileWithUserInput(m_d->view->mainWindowAsQWidget(), storageLocation, ResourceType::Palettes, filename);
0158 
0159     KoColorSetSP palette;
0160     if (resource) {
0161         palette = resource.dynamicCast<KoColorSet>();
0162     }
0163 
0164     return palette;
0165 }
0166 
0167 void KisPaletteEditor::removePalette(KoColorSetSP cs)
0168 {
0169     if (!m_d->view) { return; }
0170     if (!m_d->view->document()) { return; }
0171     if (!cs) { return; }
0172     m_d->rServer->removeResourceFromServer(cs);
0173 }
0174 
0175 int KisPaletteEditor::rowNumberOfGroup(const QString &originalName) const
0176 {
0177     if (!m_d->modifiedPaletteInfo.groups.contains(originalName)) { return 0; }
0178     return m_d->modifiedPaletteInfo.groups[originalName]->rowCount();
0179 }
0180 
0181 bool KisPaletteEditor::duplicateExistsGroupName(const QString &name) const
0182 {
0183     if (name == m_d->groupBeingRenamed) { return false; }
0184     Q_FOREACH (const KisSwatchGroupSP group, m_d->modifiedPaletteInfo.groups.values()) {
0185         if (name == group->name()) { return true; }
0186     }
0187     return false;
0188 }
0189 
0190 bool KisPaletteEditor::duplicateExistsOriginalGroupName(const QString &name) const
0191 {
0192     return m_d->modifiedPaletteInfo.groups.contains(name);
0193 }
0194 
0195 QString KisPaletteEditor::oldNameFromNewName(const QString &newName) const
0196 {
0197     Q_FOREACH (const QString &oldGroupName, m_d->modifiedPaletteInfo.groups.keys()) {
0198         if (m_d->modifiedPaletteInfo.groups[oldGroupName]->name() == newName) {
0199             return oldGroupName;
0200         }
0201     }
0202     return QString();
0203 }
0204 
0205 void KisPaletteEditor::rename(const QString &newName)
0206 {
0207     if (newName.isEmpty()) { return; }
0208     m_d->isNameModified = true;
0209     m_d->modifiedPaletteInfo.name = newName;
0210 }
0211 
0212 void KisPaletteEditor::changeColumnCount(int newCount)
0213 {
0214     m_d->isColumnCountModified = true;
0215     m_d->modifiedPaletteInfo.columnCount = newCount;
0216 }
0217 
0218 QString KisPaletteEditor::addGroup()
0219 {
0220     KoDialog dialog;
0221     m_d->query = &dialog;
0222 
0223     QVBoxLayout *layout = new QVBoxLayout(dialog.mainWidget());
0224 
0225     layout->addWidget(new QLabel(i18n("New swatch group name:")));
0226     QLineEdit *leName = new QLineEdit(newGroupName());
0227     connect(leName, SIGNAL(textChanged(QString)), SLOT(slotGroupNameChanged(QString)));
0228     layout->addWidget(leName);
0229     layout->addWidget(new QLabel(i18n("Rows of swatches in group:")));
0230     QSpinBox *spxRow = new QSpinBox();
0231     spxRow->setValue(20);
0232     layout->addWidget(spxRow);
0233 
0234     if (dialog.exec() != QDialog::Accepted) { return QString(); }
0235     if (duplicateExistsGroupName(leName->text())) { return QString(); }
0236 
0237     QString realName = leName->text();
0238     QString name = realName;
0239     if (duplicateExistsOriginalGroupName(name)) {
0240         name = newGroupName();
0241     }
0242     m_d->modifiedPaletteInfo.groups[name].reset(new KisSwatchGroup);
0243     KisSwatchGroupSP newGroup = m_d->modifiedPaletteInfo.groups[name];
0244     newGroup->setName(realName);
0245     m_d->newGroupNames.insert(name);
0246     newGroup->setRowCount(spxRow->value());
0247     return realName;
0248 }
0249 
0250 bool KisPaletteEditor::removeGroup(const QString &name)
0251 {
0252     KoDialog dialog;
0253     dialog.setWindowTitle(i18nc("@title:dialog", "Removing Swatch Group"));
0254     QFormLayout *editableItems = new QFormLayout(dialog.mainWidget());
0255     QCheckBox *chkKeep = new QCheckBox();
0256 
0257     editableItems->addRow(i18nc("Shows up when deleting a swatch group", "Keep the Colors"), chkKeep);
0258     if (dialog.exec() != KoDialog::Accepted) { return false; }
0259 
0260     m_d->modifiedPaletteInfo.groups.remove(name);
0261     m_d->newGroupNames.remove(name);
0262     if (chkKeep->isChecked()) {
0263         m_d->keepColorGroups.insert(name);
0264     }
0265     return true;
0266 }
0267 
0268 QString KisPaletteEditor::renameGroup(const QString &oldName)
0269 {
0270     if (oldName.isEmpty() || oldName == KoColorSet::GLOBAL_GROUP_NAME) { return QString(); }
0271 
0272     KoDialog dialog;
0273     m_d->query = &dialog;
0274     m_d->groupBeingRenamed = m_d->modifiedPaletteInfo.groups[oldName]->name();
0275 
0276     QFormLayout *form = new QFormLayout(dialog.mainWidget());
0277 
0278     QLineEdit *leNewName = new QLineEdit();
0279     connect(leNewName, SIGNAL(textChanged(QString)), SLOT(slotGroupNameChanged(QString)));
0280     leNewName->setText(m_d->modifiedPaletteInfo.groups[oldName]->name());
0281 
0282     form->addRow(i18n("New swatch group name:"), leNewName);
0283 
0284     if (dialog.exec() != KoDialog::Accepted) { return QString(); }
0285     if (leNewName->text().isEmpty()) { return QString(); }
0286     if (duplicateExistsGroupName(leNewName->text())) { return QString(); }
0287 
0288     m_d->modifiedPaletteInfo.groups[oldName]->setName(leNewName->text());
0289     m_d->modifiedGroupNames.insert(oldName);
0290 
0291     return leNewName->text();
0292 }
0293 
0294 void KisPaletteEditor::slotGroupNameChanged(const QString &newName)
0295 {
0296     QLineEdit *leGroupName = qobject_cast<QLineEdit*>(sender());
0297     if (duplicateExistsGroupName(newName) || newName == QString()) {
0298         leGroupName->setPalette(m_d->warnPalette);
0299         if (m_d->query->button(KoDialog::Ok)) {
0300             m_d->query->button(KoDialog::Ok)->setEnabled(false);
0301         }
0302         return;
0303     }
0304     leGroupName->setPalette(m_d->normalPalette);
0305     if (m_d->query->button(KoDialog::Ok)) {
0306         m_d->query->button(KoDialog::Ok)->setEnabled(true);
0307     }
0308 }
0309 
0310 void KisPaletteEditor::changeGroupRowCount(const QString &name, int newRowCount)
0311 {
0312     if (!m_d->modifiedPaletteInfo.groups.contains(name)) { return; }
0313     m_d->modifiedPaletteInfo.groups[name]->setRowCount(newRowCount);
0314     m_d->modifiedGroupNames.insert(name);
0315 }
0316 
0317 void KisPaletteEditor::setStorageLocation(QString location)
0318 {
0319    m_d->modifiedPaletteInfo.storageLocation = location;
0320 }
0321 
0322 void KisPaletteEditor::setEntry(const KoColor &color, const QModelIndex &index)
0323 {
0324     Q_ASSERT(m_d->model);
0325     if (!m_d->view) { return; }
0326     if (!m_d->view->document()) { return; }
0327     KisSwatch c = KisSwatch(color);
0328     c.setId(QString::number(m_d->model->colorSet()->colorCount() + 1));
0329     c.setName(i18nc("Default name for a color swatch","Color %1", QString::number(m_d->model->colorSet()->colorCount()+1)));
0330     m_d->model->setSwatch(c, index);
0331 }
0332 
0333 void KisPaletteEditor::slotSetDocumentModified()
0334 {
0335     if (m_d->modifiedPaletteInfo.storageLocation == m_d->view->document()->linkedResourcesStorageId()) {
0336         updatePalette();
0337         KisResourceUserOperations::updateResourceWithUserInput(m_d->view->mainWindowAsQWidget(), m_d->model->colorSet());
0338         m_d->view->document()->setModified(true);
0339     }
0340     m_d->model->colorSet()->setDirty(true);
0341 }
0342 
0343 void KisPaletteEditor::removeEntry(const QModelIndex &index)
0344 {
0345     Q_ASSERT(m_d->model);
0346     if (!m_d->view) { return; }
0347     if (!m_d->view->document()) { return; }
0348     if (qvariant_cast<bool>(index.data(KisPaletteModel::IsGroupNameRole))) {
0349         removeGroup(qvariant_cast<QString>(index.data(KisPaletteModel::GroupNameRole)));
0350     } else {
0351         m_d->model->removeSwatch(index, false);
0352     }
0353     updatePalette();
0354 }
0355 
0356 void KisPaletteEditor::modifyEntry(const QModelIndex &index)
0357 {
0358     if (!m_d->view) { return; }
0359     if (!m_d->view->document()) { return; }
0360 
0361     KoDialog dialog;
0362     dialog.setCaption(i18nc("@title:dialog", "Add a new Color Swatch"));
0363     QFormLayout *editableItems = new QFormLayout(dialog.mainWidget());
0364 
0365     QString groupName = qvariant_cast<QString>(index.data(Qt::DisplayRole));
0366     if (qvariant_cast<bool>(index.data(KisPaletteModel::IsGroupNameRole))) {
0367         renameGroup(groupName);
0368         updatePalette();
0369     }
0370     else {
0371 
0372         QLineEdit *lnIDName = new QLineEdit();
0373         QLineEdit *lnGroupName = new QLineEdit();
0374         KisColorButton *bnColor = new KisColorButton();
0375         QCheckBox *chkSpot = new QCheckBox();
0376         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."));
0377 
0378         KisSwatch entry = m_d->model->getSwatch(index);
0379 
0380         editableItems->addRow(i18n("Swatch ID:"), lnIDName);
0381         editableItems->addRow(i18n("Color swatch name:"), lnGroupName);
0382         editableItems->addRow(i18nc("Color as the Color of a Swatch in a Palette", "Color:"), bnColor);
0383         editableItems->addRow(i18n("Spot color:"), chkSpot);
0384 
0385         lnGroupName->setText(entry.name());
0386         lnIDName->setText(entry.id());
0387         bnColor->setColor(entry.color());
0388         chkSpot->setChecked(entry.spotColor());
0389 
0390         if (dialog.exec() == KoDialog::Accepted) {
0391             entry.setName(lnGroupName->text());
0392             entry.setId(lnIDName->text());
0393             entry.setColor(bnColor->color());
0394             entry.setSpotColor(chkSpot->isChecked());
0395             m_d->model->setSwatch(entry, index);
0396         }
0397     }
0398 }
0399 
0400 void KisPaletteEditor::addEntry(const KoColor &color)
0401 {
0402     Q_ASSERT(m_d->model);
0403     if (!m_d->view) { return; }
0404     if (!m_d->view->document()) { return; }
0405 
0406     KoDialog dialog;
0407     dialog.setWindowTitle(i18nc("@title:dialog", "Add a new Color Swatch"));
0408 
0409     QFormLayout *editableItems = new QFormLayout(dialog.mainWidget());
0410 
0411     QComboBox *cmbGroups = new QComboBox();
0412     cmbGroups->addItems(m_d->model->colorSet()->swatchGroupNames());
0413     cmbGroups->setCurrentIndex(0);
0414 
0415     QLineEdit *lnIDName = new QLineEdit();
0416     lnIDName->setText(QString::number(m_d->model->colorSet()->colorCount() + 1));
0417 
0418     QLineEdit *lnName = new QLineEdit();
0419     lnName->setText(i18nc("Default name for a color swatch","Color %1", QString::number(m_d->model->colorSet()->colorCount()+1)));
0420 
0421     KisColorButton *bnColor = new KisColorButton();
0422     bnColor->setColor(color);
0423 
0424     QCheckBox *chkSpot = new QCheckBox();
0425     chkSpot->setChecked(false);
0426     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."));
0427 
0428     editableItems->addRow(i18n("Swatch Group:"), cmbGroups);
0429     editableItems->addRow(i18n("Swatch ID:"), lnIDName);
0430     editableItems->addRow(i18n("Color swatch name:"), lnName);
0431     editableItems->addRow(i18nc("Color as the Color of a Swatch in a Palette", "Color:"), bnColor);
0432     editableItems->addRow(i18n("Spot color:"), chkSpot);
0433 
0434     if (dialog.exec() != KoDialog::Accepted) { return; }
0435 
0436     QString groupName = cmbGroups->currentText();
0437 
0438     KisSwatch newSwatch;
0439     newSwatch.setColor(bnColor->color());
0440     newSwatch.setName(lnName->text());
0441     newSwatch.setId(lnIDName->text());
0442     newSwatch.setSpotColor(chkSpot->isChecked());
0443     m_d->model->addSwatch(newSwatch, groupName);
0444     m_d->modifiedGroupNames.insert(groupName);
0445     m_d->modifiedPaletteInfo.groups[groupName]->addSwatch(newSwatch);
0446 }
0447 
0448 bool KisPaletteEditor::isModified() const
0449 {
0450     if (m_d->model->colorSet()) {
0451         return m_d->model->colorSet()->isDirty();
0452     } else {
0453         return false;
0454     }
0455 }
0456 
0457 void KisPaletteEditor::updatePalette()
0458 {
0459     if (!m_d->model) return;
0460     if (!m_d->model->colorSet()) return;
0461     if (!m_d->view) return;
0462     if (!m_d->view->document()) return;
0463 
0464     KoColorSetSP palette = m_d->model->colorSet();
0465     PaletteInfo &modified = m_d->modifiedPaletteInfo;
0466 
0467     if (m_d->isColumnCountModified) {
0468         m_d->model->setColumnCount(modified.columnCount);
0469     }
0470     if (m_d->isNameModified) {
0471         KisResourceUserOperations::renameResourceWithUserInput(m_d->view->mainWindowAsQWidget(), palette, m_d->modifiedPaletteInfo.name);
0472     }
0473     QString resourceLocation = m_d->model->colorSet()->storageLocation();
0474     if (resourceLocation != m_d->modifiedPaletteInfo.storageLocation) {
0475         // We need functionality for moving the resource to the new resource storage...
0476     }
0477 
0478     Q_FOREACH (const QString &groupName, palette->swatchGroupNames()) {
0479         if (!modified.groups.contains(groupName)) {
0480             m_d->model->removeGroup(groupName, m_d->keepColorGroups.contains(groupName));
0481         }
0482     }
0483     m_d->keepColorGroups.clear();
0484     Q_FOREACH (const QString &groupName, palette->swatchGroupNames()) {
0485         if (m_d->modifiedGroupNames.contains(groupName)) {
0486             m_d->model->setRowCountForGroup(groupName, modified.groups[groupName]->rowCount());
0487             if (groupName != modified.groups[groupName]->name()) {
0488                 m_d->model->changeGroupName(groupName, modified.groups[groupName]->name());
0489                 modified.groups[modified.groups[groupName]->name()] = modified.groups[groupName];
0490                 modified.groups.remove(groupName);
0491             }
0492         }
0493     }
0494     m_d->modifiedGroupNames.clear();
0495     Q_FOREACH (const QString &newGroupName, m_d->newGroupNames) {
0496         m_d->model->addGroup(newGroupName);
0497     }
0498     m_d->newGroupNames.clear();
0499 }
0500 
0501 void KisPaletteEditor::saveNewPaletteVersion()
0502 {
0503     if (!m_d->model || !m_d->model->colorSet()) { return; }
0504 
0505     QModelIndex index = m_d->rServer->resourceModel()->indexForResource(m_d->model->colorSet());
0506     bool isGlobal = false;
0507     if (index.isValid()) {
0508         bool ok = false;
0509         int storageId = m_d->rServer->resourceModel()->data(index, Qt::UserRole + KisAllResourcesModel::StorageId).toInt(&ok);
0510         if (ok) {
0511             KisStorageModel storageModel;
0512             KisResourceStorageSP storage = storageModel.storageForId(storageId);
0513             isGlobal = storage->type() != KisResourceStorage::StorageType::Memory;
0514         }
0515     }
0516     bool res = false;
0517     if (isGlobal) {
0518         if (m_d->view) {
0519             res = KisResourceUserOperations::updateResourceWithUserInput(m_d->view->mainWindowAsQWidget(), m_d->model->colorSet());
0520         } else if (m_d->model->colorSet()->version() >= 0) {
0521             //if the version is -1, then the resource should not be updated, because it was never saved to begin with...
0522             res = m_d->rServer->resourceModel()->updateResource(m_d->model->colorSet());
0523             dbgResources << Q_FUNC_INFO << "-- Updating resource without user input: " << m_d->model->colorSet()->name() << "Result:" << res;
0524         }
0525     }
0526 }
0527 
0528 void KisPaletteEditor::slotPaletteChanged()
0529 {
0530     Q_ASSERT(m_d->model);
0531     if (!m_d->model->colorSet()) { return; }
0532     KoColorSetSP palette = m_d->model->colorSet();
0533     m_d->modifiedPaletteInfo.groups.clear();
0534     m_d->keepColorGroups.clear();
0535     m_d->newGroupNames.clear();
0536     m_d->modifiedGroupNames.clear();
0537 
0538     m_d->modifiedPaletteInfo.name = palette->name();
0539     m_d->modifiedPaletteInfo.storageLocation = palette->storageLocation();
0540     m_d->modifiedPaletteInfo.columnCount = palette->columnCount();
0541 
0542     Q_FOREACH (const QString &groupName, palette->swatchGroupNames()) {
0543         KisSwatchGroupSP cs = palette->getGroup(groupName);
0544         m_d->modifiedPaletteInfo.groups[groupName].reset(new KisSwatchGroup(*cs.data()));
0545     }
0546 }
0547 
0548 QString KisPaletteEditor::newGroupName() const
0549 {
0550     int i = 1;
0551     QString groupname = i18nc("Default new group name", "New Group %1", QString::number(i));
0552     while (m_d->modifiedPaletteInfo.groups.contains(groupname)) {
0553         i++;
0554         groupname = i18nc("Default new group name", "New Group %1", QString::number(i));
0555     }
0556     return groupname;
0557 }
0558 
0559 QString KisPaletteEditor::filenameFromPath(const QString &path) const
0560 {
0561     return QDir::fromNativeSeparators(path).section('/', -1, -1);
0562 }