File indexing completed on 2024-05-19 04:28:56
0001 /* 0002 * SPDX-FileCopyrightText: 2006 Bart Coppens <kde@bartcoppens.be> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_custom_pattern.h" 0008 0009 #include <KoResourceServerProvider.h> 0010 #include <resources/KoPattern.h> 0011 0012 #include <QLabel> 0013 #include <QImage> 0014 #include <QPushButton> 0015 #include <QComboBox> 0016 #include <QPixmap> 0017 #include <QShowEvent> 0018 #include <QSharedPointer> 0019 #include <QFileInfo> 0020 #include <KoFileDialog.h> 0021 #include <QMessageBox> 0022 0023 #include "KisDocument.h" 0024 #include "KisViewManager.h" 0025 #include "kis_image.h" 0026 #include "kis_layer.h" 0027 #include "kis_paint_device.h" 0028 #include "kis_selection.h" 0029 #include "kis_painter.h" 0030 0031 #include <kis_debug.h> 0032 #include "KisResourceServerProvider.h" 0033 #include <KisResourceLoaderRegistry.h> 0034 #include "kis_paint_layer.h" 0035 #include <KisResourceUserOperations.h> 0036 0037 0038 KisCustomPattern::KisCustomPattern(QWidget *parent, const char* name, const QString& caption, KisViewManager* view) 0039 : KisWdgCustomPattern(parent, name) 0040 , m_view(view) 0041 { 0042 Q_ASSERT(m_view); 0043 setWindowTitle(caption); 0044 0045 m_pattern = 0; 0046 0047 preview->setScaledContents(true); 0048 0049 m_rServer = KoResourceServerProvider::instance()->patternServer(); 0050 0051 connect(addButton, SIGNAL(pressed()), this, SLOT(slotAddPredefined())); 0052 connect(patternButton, SIGNAL(pressed()), this, SLOT(slotUsePattern())); 0053 connect(updateButton, SIGNAL(pressed()), this, SLOT(slotUpdateCurrentPattern())); 0054 connect(cmbSource, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateCurrentPattern())); 0055 0056 lblWarning->setVisible(false); 0057 slotUpdateCurrentPattern(); 0058 } 0059 0060 KisCustomPattern::~KisCustomPattern() 0061 { 0062 m_pattern.clear(); 0063 } 0064 0065 void KisCustomPattern::slotUpdateCurrentPattern() 0066 { 0067 m_pattern.clear(); 0068 if (m_view && m_view->image()) { 0069 createPattern(); 0070 if (m_pattern) { 0071 const qint32 maxSize = 150; 0072 if ((m_pattern->width() > maxSize) || (m_pattern->height() > maxSize)) { 0073 float aspectRatio = (float)m_pattern->width() / m_pattern->height(); 0074 qint32 scaledWidth, scaledHeight; 0075 0076 if (m_pattern->width() > m_pattern->height()) { 0077 scaledWidth = maxSize; 0078 scaledHeight = maxSize / aspectRatio; 0079 } else { 0080 scaledWidth = maxSize * aspectRatio; 0081 scaledHeight = maxSize; 0082 } 0083 0084 if (scaledWidth == 0) scaledWidth++; 0085 if (scaledHeight == 0) scaledHeight++; 0086 0087 QPixmap scaledPixmap = QPixmap::fromImage(m_pattern->pattern()); 0088 preview->setPixmap(scaledPixmap.scaled(scaledWidth, scaledHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation)); 0089 } else { 0090 preview->setPixmap(QPixmap::fromImage(m_pattern->pattern())); 0091 } 0092 } 0093 } 0094 0095 } 0096 0097 void KisCustomPattern::slotAddPredefined() 0098 { 0099 if (!m_pattern) return; 0100 0101 // Save in the directory that is likely to be: ~/.kde/share/apps/krita/patterns 0102 // a unique file with this pattern name 0103 QString dir = KoResourceServerProvider::instance()->patternServer()->saveLocation(); 0104 0105 KoFileDialog dlg(this, KoFileDialog::SaveFile, "KisCustomPattern::slotAddPredefined"); 0106 dlg.setDefaultDir(dir + "/" + m_pattern->name() + ".pat"); 0107 dlg.setMimeTypeFilters(KisResourceLoaderRegistry::instance()->mimeTypes(ResourceType::Patterns)); 0108 dlg.setCaption(i18n("Add to Predefined Patterns")); 0109 0110 QString filename = dlg.filename(); 0111 0112 if (filename == "") { 0113 // dialog was cancelled 0114 return; 0115 } 0116 bool hadToChangeFilename = false; 0117 0118 QFileInfo fi(filename); 0119 if (fi.suffix().isEmpty()) { 0120 fi.setFile(fi.baseName() + m_pattern->defaultFileExtension()); 0121 hadToChangeFilename = true; 0122 } 0123 0124 if (fi.baseName() != m_pattern->name()) { 0125 m_pattern->setName(fi.baseName()); 0126 } 0127 0128 bool overwrite = false; 0129 if (fi.exists()) { 0130 if (hadToChangeFilename) { // if not, the File Dialog would show the warning 0131 if (QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("This pattern already exists. Do you want to overwrite it?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { 0132 overwrite = true; 0133 } 0134 } else { // the File Dialog showed the warning and the user said "yeah fine" 0135 overwrite = true; 0136 } 0137 } 0138 0139 if (!filename.isEmpty()) { 0140 m_pattern->setFilename(fi.fileName()); // to make sure we include the suffix added earlier 0141 if (!fi.exists()) { 0142 if (!KisResourceUserOperations::addResourceWithUserInput(this, m_pattern->clone().dynamicCast<KoPattern>())) { 0143 qWarning() << "Could not add pattern with filename" << filename; 0144 } 0145 else { 0146 emit patternAdded(m_pattern); 0147 } 0148 } 0149 else if (overwrite) { 0150 if (!KisResourceUserOperations::updateResourceWithUserInput(this, m_pattern->clone().dynamicCast<KoPattern>())) { 0151 qWarning() << "Could not add pattern with filename" << filename; 0152 } 0153 else { 0154 emit patternUpdated(m_pattern); 0155 } 0156 } 0157 } 0158 } 0159 0160 void KisCustomPattern::slotUsePattern() 0161 { 0162 if (!m_pattern) 0163 return; 0164 KoPatternSP copy = m_pattern->clone().dynamicCast<KoPattern>(); 0165 emit(activatedResource(copy)); 0166 } 0167 0168 void KisCustomPattern::createPattern() 0169 { 0170 if (!m_view) return; 0171 0172 KisPaintDeviceSP dev; 0173 KisPaintDeviceSP cache; 0174 QString name; 0175 KisImageWSP image = m_view->image(); 0176 if (!image) return; 0177 QRect rc = image->bounds(); 0178 0179 if (cmbSource->currentIndex() == 0) { 0180 dev = m_view->activeNode()->projection(); 0181 name = m_view->activeNode()->name(); 0182 QRect rc2 = dev->exactBounds(); 0183 rc = rc.intersected(rc2); 0184 } 0185 else { 0186 image->barrierLock(); 0187 dev = image->projection(); 0188 image->unlock(); 0189 name = image->objectName(); 0190 } 0191 if (!dev) return; 0192 0193 if(m_view->selection()) { 0194 KisSelectionSP selection = m_view->selection(); 0195 QRect selectionRect = selection->selectedExactRect(); 0196 cache = dev->createCompositionSourceDevice(); 0197 KisPainter gc(cache); 0198 gc.setSelection(selection); 0199 gc.bitBlt(selectionRect.topLeft(), dev, selectionRect); 0200 rc = selectionRect; 0201 } else { 0202 cache = dev; 0203 } 0204 if (!cache) return; 0205 0206 0207 // warn when creating large patterns 0208 0209 QSize size = rc.size(); 0210 if (size.height() > 1000 || size.width() > 1000) { 0211 lblWarning->setVisible(true); 0212 size.scale(1000, 1000, Qt::KeepAspectRatio); 0213 } 0214 else { 0215 lblWarning->setVisible(false); 0216 } 0217 0218 QString dir = KoResourceServerProvider::instance()->patternServer()->saveLocation(); 0219 m_pattern = KoPatternSP(new KoPattern(cache->createThumbnail(size.width(), size.height(), rc, /*oversample*/ 1, 0220 KoColorConversionTransformation::internalRenderingIntent(), 0221 KoColorConversionTransformation::internalConversionFlags()), name, dir)); 0222 } 0223 0224