Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_custom_pattern.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006 Bart Coppens <kde@bartcoppens.be>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
10#include <resources/KoPattern.h>
11
12#include <QPixmap>
13#include <QShowEvent>
14#include <QFileInfo>
15#include <KoFileDialog.h>
16#include <QMessageBox>
17
18#include "KisDocument.h"
19#include "KisViewManager.h"
20#include "kis_image.h"
21#include "kis_layer.h"
22#include "kis_paint_device.h"
23#include "kis_selection.h"
24#include "kis_painter.h"
25
26#include <kis_debug.h>
29#include "kis_paint_layer.h"
31
32
33KisCustomPattern::KisCustomPattern(QWidget *parent, const char* name, const QString& caption, KisViewManager* view)
34 : KisWdgCustomPattern(parent, name)
35 , m_view(view)
36{
37 Q_ASSERT(m_view);
38 setWindowTitle(caption);
39
40 m_pattern = 0;
41
42 preview->setScaledContents(true);
43
45
46 connect(addButton, SIGNAL(pressed()), this, SLOT(slotAddPredefined()));
47 connect(patternButton, SIGNAL(pressed()), this, SLOT(slotUsePattern()));
48 connect(updateButton, SIGNAL(pressed()), this, SLOT(slotUpdateCurrentPattern()));
49 connect(cmbSource, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateCurrentPattern()));
50
51 lblWarning->setVisible(false);
53}
54
59
61{
62 m_pattern.clear();
63 if (m_view && m_view->image()) {
65 if (m_pattern) {
66 const qint32 maxSize = 150;
67 if ((m_pattern->width() > maxSize) || (m_pattern->height() > maxSize)) {
68 float aspectRatio = (float)m_pattern->width() / m_pattern->height();
69 qint32 scaledWidth, scaledHeight;
70
71 if (m_pattern->width() > m_pattern->height()) {
72 scaledWidth = maxSize;
73 scaledHeight = maxSize / aspectRatio;
74 } else {
75 scaledWidth = maxSize * aspectRatio;
76 scaledHeight = maxSize;
77 }
78
79 if (scaledWidth == 0) scaledWidth++;
80 if (scaledHeight == 0) scaledHeight++;
81
82 QPixmap scaledPixmap = QPixmap::fromImage(m_pattern->pattern());
83 preview->setPixmap(scaledPixmap.scaled(scaledWidth, scaledHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation));
84 } else {
85 preview->setPixmap(QPixmap::fromImage(m_pattern->pattern()));
86 }
87 }
88 }
89
90}
91
93{
94 if (!m_pattern) return;
95
96 // Save in the directory that is likely to be: ~/.kde/share/apps/krita/patterns
97 // a unique file with this pattern name
99
100 KoFileDialog dlg(this, KoFileDialog::SaveFile, "KisCustomPattern::slotAddPredefined");
101 dlg.setDefaultDir(dir + "/" + m_pattern->name() + ".pat");
103 dlg.setCaption(i18n("Add to Predefined Patterns"));
104
105 QString filename = dlg.filename();
106
107 if (filename == "") {
108 // dialog was cancelled
109 return;
110 }
111 bool hadToChangeFilename = false;
112
113 QFileInfo fi(filename);
114 if (fi.suffix().isEmpty()) {
115 fi.setFile(fi.baseName() + m_pattern->defaultFileExtension());
116 hadToChangeFilename = true;
117 }
118
119 if (fi.baseName() != m_pattern->name()) {
120 m_pattern->setName(fi.baseName());
121 }
122
123 bool overwrite = false;
124 if (fi.exists()) {
125 if (hadToChangeFilename) { // if not, the File Dialog would show the warning
126 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) {
127 overwrite = true;
128 }
129 } else { // the File Dialog showed the warning and the user said "yeah fine"
130 overwrite = true;
131 }
132 }
133
134 if (!filename.isEmpty()) {
135 m_pattern->setFilename(fi.fileName()); // to make sure we include the suffix added earlier
136 if (!fi.exists()) {
137 if (!KisResourceUserOperations::addResourceWithUserInput(this, m_pattern->clone().dynamicCast<KoPattern>())) {
138 qWarning() << "Could not add pattern with filename" << filename;
139 }
140 else {
141 Q_EMIT patternAdded(m_pattern);
142 }
143 }
144 else if (overwrite) {
146 qWarning() << "Could not add pattern with filename" << filename;
147 }
148 else {
150 }
151 }
152 }
153}
154
156{
157 if (!m_pattern)
158 return;
159 KoPatternSP copy = m_pattern->clone().dynamicCast<KoPattern>();
160 emit(activatedResource(copy));
161}
162
164{
165 if (!m_view) return;
166
168 KisPaintDeviceSP cache;
169 QString name;
170 KisImageWSP image = m_view->image();
171 if (!image) return;
172 QRect rc = image->bounds();
173
174 if (cmbSource->currentIndex() == 0) {
175 dev = m_view->activeNode()->projection();
176 name = m_view->activeNode()->name();
177 QRect rc2 = dev->exactBounds();
178 rc = rc.intersected(rc2);
179 }
180 else {
181 image->barrierLock();
182 dev = image->projection();
183 image->unlock();
184 name = image->objectName();
185 }
186 if (!dev) return;
187
188 if(m_view->selection()) {
189 KisSelectionSP selection = m_view->selection();
190 QRect selectionRect = selection->selectedExactRect();
191 cache = dev->createCompositionSourceDevice();
192 KisPainter gc(cache);
193 gc.setSelection(selection);
194 gc.bitBlt(selectionRect.topLeft(), dev, selectionRect);
195 rc = selectionRect;
196 } else {
197 cache = dev;
198 }
199 if (!cache) return;
200
201
202 // warn when creating large patterns
203
204 QSize size = rc.size();
205 if (size.height() > 1000 || size.width() > 1000) {
206 lblWarning->setVisible(true);
207 size.scale(1000, 1000, Qt::KeepAspectRatio);
208 }
209 else {
210 lblWarning->setVisible(false);
211 }
212
214 m_pattern = KoPatternSP(new KoPattern(cache->createThumbnail(size.width(), size.height(), rc, /*oversample*/ 1,
217}
218
219
QSharedPointer< KoPattern > KoPatternSP
Definition KoPattern.h:16
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void patternAdded(KoResourceSP)
void activatedResource(KoResourceSP)
KisCustomPattern(QWidget *parent, const char *name, const QString &caption, KisViewManager *view)
void patternUpdated(KoResourceSP)
KisViewManager * m_view
KoResourceServer< KoPattern > * m_rServer
void unlock()
Definition kis_image.cc:805
void barrierLock(bool readOnly=false)
Wait until all the queued background jobs are completed and lock the image.
Definition kis_image.cc:756
KisPaintDeviceSP projection() const
QRect bounds() const override
KisPaintDeviceSP createCompositionSourceDevice() const
QImage createThumbnail(qint32 maxw, qint32 maxh, QRect rect, qreal oversample=1, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags())
QRect exactBounds() const
void setSelection(KisSelectionSP selection)
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
static KisResourceLoaderRegistry * instance()
static bool addResourceWithUserInput(QWidget *widgetParent, KoResourceSP resource, QString storageLocation="")
static bool updateResourceWithUserInput(QWidget *widgetParent, KoResourceSP resource)
KisNodeSP activeNode()
KisSelectionSP selection()
KisImageWSP image() const
Return the image this view is displaying.
QString filename()
Get the file name the user selected in the file dialog.
void setDefaultDir(const QString &defaultDir, bool force=false)
setDefaultDir set the default directory to defaultDir.
void setCaption(const QString &caption)
void setMimeTypeFilters(const QStringList &mimeTypeList, QString defaultMimeType=QString())
setMimeTypeFilters Update the list of file filters from mime types.
Write API docs here.
Definition KoPattern.h:21
QString saveLocation()
Returns path where to save user defined and imported resources to.
const QString Patterns
virtual KisPaintDeviceSP projection() const =0
QString name() const
QRect selectedExactRect() const
Slow, but exact way of determining the rectangle that encloses the selection.
static KoResourceServerProvider * instance()
KoResourceServer< KoPattern > * patternServer