11#include <QApplication>
17#include <QStandardPaths>
22#include <klocalizedstring.h>
187 const bool isGroupLayer = layer && layer->inherits(
"KisGroupLayer");
189 QString mergeLayerText;
191 mergeLayerText = i18nc(
"@action:inmenu",
"Merge Selected Layers");
192 }
else if (isGroupLayer) {
193 mergeLayerText = i18nc(
"@action:inmenu",
"Merge Group");
195 mergeLayerText = i18nc(
"@action:inmenu",
"Merge with Layer Below");
212 if (!cropRect.isEmpty()) {
216 i18nc(
"floating message in layer manager",
244 const bool multipleLayersSelected = selectedNodes.size() > 1;
252 if (adjustmentLayer && !multipleLayersSelected) {
262 QString xmlBefore = configBefore->toXML();
265 if (dlg.exec() == QDialog::Accepted) {
267 adjustmentLayer->setName(dlg.
layerName());
270 Q_ASSERT(configAfter);
271 QString xmlAfter = configAfter->toXML();
273 if(xmlBefore != xmlAfter) {
276 configBefore->cloneWithResourcesSnapshot(),
277 configAfter->cloneWithResourcesSnapshot());
286 Q_ASSERT(configAfter);
287 QString xmlAfter = configAfter->toXML();
289 if(xmlBefore != xmlAfter) {
290 adjustmentLayer->setFilter(configBefore->cloneWithResourcesSnapshot());
291 adjustmentLayer->setDirty();
295 else if (fileLayer && !multipleLayersSelected){
297 QString fileNameOld = fileLayer->
fileName();
301 dlg.
setCaption(i18n(
"File Layer Properties"));
306 if (dlg.exec() == QDialog::Accepted) {
307 const QString fileNameNew = dlg.
fileName();
311 if(fileNameNew.isEmpty()){
312 QMessageBox::critical(
m_view->
mainWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"No file name specified"));
317 if (fileNameOld!= fileNameNew || scalingMethodOld != scalingMethodNew || scalingFilterOld != scalingFilterNew) {
332 QDialog* dlg =
nullptr;
334 if (generatorLayer && !multipleLayersSelected) {
336 Q_ASSERT(configBefore);
339 genDlg->setWindowTitle(i18n(
"Fill Layer Properties"));
340 genDlg->setConfiguration(configBefore.
data());
350 dlg->resize(dlg->minimumSizeHint());
351 dlg->setAttribute(Qt::WA_DeleteOnClose);
353 const Qt::WindowFlags flags = dlg->windowFlags();
356 dlg->setWindowFlags(flags | Qt::Dialog);
358 dlg->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
364 dlg->activateWindow();
376 if (selectedNodes.isEmpty()) {
382 Q_FOREACH (node, selectedNodes) {
385 cloneLayers << cloneLayer;
389 if (cloneLayers.isEmpty()) {
396 dialog->setCaption(i18n(
"Change Clone Layer"));
397 dialog->resize(dialog->minimumSizeHint());
398 dialog->setAttribute(Qt::WA_DeleteOnClose);
399 Qt::WindowFlags flags = dialog->windowFlags();
400 dialog->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
402 dialog->activateWindow();
420 if (!psdxml.isEmpty()) {
421 QMimeData *mimeData =
new QMimeData;
423 mimeData->setText(psdxml);
424 mimeData->setData(
"application/x-krita-layer-style", psdxml.toUtf8());
426 QGuiApplication::clipboard()->setMimeData(mimeData);
441 aslXml = QString::fromUtf8(QGuiApplication::clipboard()->mimeData()->data(
"application/x-krita-layer-style"));
443 aslXml = QGuiApplication::clipboard()->text();
446 if (aslXml.isEmpty())
return;
449 if (!aslDoc.setContent(aslXml))
return;
455 if (serializer.
styles().size() != 1)
return;
475 if (srcLayer && (srcLayer->inherits(
"KisGroupLayer") || srcLayer->
layerStyle() || srcLayer->
childCount() > 0)) {
486 if (targetGroup.
isNull()) {
489 if (!parent->parent())
return;
493 if (targetGroup.
isNull())
return;
528 QWidget *page =
new QWidget(&dlg);
530 QBoxLayout *layout =
new QVBoxLayout(page);
531 dlg.setWindowTitle(i18n(
"Save layers to..."));
532 QLabel *lbl =
new QLabel(i18n(
"Choose the location where the layer will be saved to. The new file layer will then reference this location."));
533 lbl->setWordWrap(
true);
534 layout->addWidget(lbl);
541 location.setFile(location.dir(), location.completeBaseName() +
"_" +
source->name() +
".png");
542 urlRequester->
setFileName(location.absoluteFilePath());
545 const QFileInfo location = QFileInfo(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
546 const QString proposedFileName = QDir(location.absoluteFilePath()).absoluteFilePath(
source->name() +
".png");
550 layout->addWidget(urlRequester);
551 if (!dlg.exec())
return;
553 QString path = urlRequester->
fileName();
555 if (path.isEmpty())
return;
560 if (mimeType.isEmpty()) {
561 mimeType =
"image/png";
575 doc->setFileBatchMode(
false);
576 doc->setCurrentImage(dst);
583 bool r = doc->exportDocumentSync(path, mimeType.toLatin1());
586 qWarning() <<
"Converting layer to file layer. path:"<< path <<
"gave errors" << doc->errorMessage();
589 QString relativePath = QDir(basePath).relativeFilePath(path);
600 doc->closePath(
false);
605 Q_ASSERT(activeNode);
608 above = parent->lastChild();
610 if (parent->inherits(
"KisGroupLayer") && parent->collapsed()) {
612 parent = parent->parent();
617 (!parent->allowAsChild(node) || !parent->isEditable(
false))) {
620 parent = parent->parent();
624 warnKrita <<
"KisLayerManager::adjustLayerPosition:"
625 <<
"No node accepted newly created node";
628 above = parent->lastChild();
640 if (layer->inherits(
"KisGroupLayer") || layer->inherits(
"KisPaintLayer")) {
643 if (layer->inherits(
"KisGroupLayer")) {
653 updateImage |= parentForceUpdate;
684 if (filteredNodes.isEmpty())
return KisNodeSP();
686 KisNodeSP newAbove = filteredNodes.last();
689 Q_FOREACH (node, filteredNodes) {
694 return lastClonedNode;
732 if (dlg.exec() != QDialog::Accepted || adjl->filter().isNull()) {
776 defaultConfig->setProperty(
"color", currentForeground);
779 if (dlg.exec() == QDialog::Accepted) {
801 i18nc(
"@title:window",
"Flatten Image"),
802 i18n(
"The image contains hidden layers that will be lost. Do you want to flatten the image?"),
803 QMessageBox::Yes | QMessageBox::No,
806 if (answer != QMessageBox::Yes) {
830 mergedNodes.append(currentNode);
831 mergedNodes.append(prevNode);
845 if (currentNode->inherits(
"KisGroupLayer")) {
869 bool hasEditableLayer =
false;
870 Q_FOREACH (
KisNodeSP node, selectedNodes) {
872 hasEditableLayer =
true;
877 if (!hasEditableLayer) {
879 i18ncp(
"floating message in layer manager",
880 "Layer is locked",
"Layers are locked", selectedNodes.size()),
885 if (selectedNodes.size() > 1) {
897 if (!prevLayer)
return;
901 i18nc(
"floating message in layer manager when previous layer is locked",
914 if (!strategy)
return;
918 i18nc(
"floating message in layer manager when trying to merge a non-animated layer into an animated one",
919 "Non-animated layer is merged into the current frame. To merge it into the whole clip, create at least one frame"),
957 QWidget *page =
new QWidget(&dlg);
959 QBoxLayout *layout =
new QVBoxLayout(page);
966 layout->addWidget(urlRequester);
968 QCheckBox *chkInvisible =
new QCheckBox(i18n(
"Convert Invisible Groups"), page);
969 chkInvisible->setChecked(
false);
970 layout->addWidget(chkInvisible);
971 QCheckBox *chkDepth =
new QCheckBox(i18n(
"Export Only Toplevel Groups"), page);
972 chkDepth->setChecked(
true);
973 layout->addWidget(chkDepth);
975 if (!dlg.exec())
return;
977 QString path = urlRequester->
fileName();
979 if (path.isEmpty())
return;
984 if (mimeType.isEmpty()) {
985 mimeType =
"image/png";
988 QString basename = f.completeBaseName();
993 KisSaveGroupVisitor v(image, chkInvisible->isChecked(), chkDepth->isChecked(), f.absolutePath(), basename, extension, mimeType);
1007 basePath = QFileInfo(path).absolutePath();
1013 if (dlg.exec() == QDialog::Accepted) {
1017 if(fileName.isEmpty()){
1018 QMessageBox::critical(
m_view->
mainWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"No file name specified"));
1034 dlg->
style()->cloneWithResourcesSnapshot(
1036 canvasResourcesInterface));
1059 canvasResourcesInterface);
1064 newStyle->setUuid(QUuid::createUuid());
1069 std::function<
void ()> updateCall(std::bind(
updateLayerStyles, layer, &dlg, canvasResourcesInterface));
1071 connect(&dlg, SIGNAL(configChanged()), &proxy, SLOT(start()));
1073 if (dlg.exec() == QDialog::Accepted) {
1076 canvasResourcesInterface);
QVector< KisImageSignalType > KisImageSignalVector
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
const quint8 OPACITY_OPAQUE_U8
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
A KisActionManager class keeps track of KisActions. These actions are always associated with the GUI....
KisAction * createAction(const QString &name)
QVector< KisPSDLayerStyleSP > styles() const
void readFromPSDXML(const QDomDocument &doc)
void registerPSDPattern(const QDomDocument &doc)
QDomDocument formPsdXmlDocument() const
void setStyles(const QVector< KisPSDLayerStyleSP > &styles)
void slotNodeActivated(const KisNodeSP node)
static KisClipboard * instance()
bool autoPinLayersToTimeline(bool defaultValue=false) const
QString layerName() const
KisFilterConfigurationSP filterConfiguration() const
QString layerName() const
void setScalingFilter(QString filter)
QString layerName() const
void setFileName(QString fileName)
KisFileLayer::ScalingMethod scaleToImageResolution() const
QString scalingFilter() const
void setScalingMethod(KisFileLayer::ScalingMethod method)
KisFilterConfigurationSP configuration() const
void setConfiguration(const KisFilterConfigurationSP config)
QString layerName() const
KisPSDLayerStyleSP style() const
KisShapeController * shapeController
void setModified(bool _mod)
The KisFileLayer class loads a particular file as a layer into the layer stack.
ScalingMethod scalingMethod() const
QString scalingFilter() const
void setStartDir(const QString &path)
void setMimeTypeFilters(const QStringList &filterList, QString defaultFilter=QString())
void setMode(KoFileDialog::DialogType mode)
void setFileName(const QString &path)
static KisResourcesInterfaceSP instance()
KisGroupLayerSP rootLayer() const
const KoColorSpace * colorSpace() const
QString nextLayerName(const QString &baseName="") const
void flattenLayer(KisLayerSP layer)
void flatten(KisNodeSP activeNode)
KisPaintDeviceSP projection() const
KisPostExecutionUndoAdapter * postExecutionUndoAdapter() const override
qint32 nHiddenLayers() const
void cropImage(const QRect &newRect)
start asynchronous operation on cropping the image
void initialRefreshGraph()
void mergeMultipleLayers(QList< KisNodeSP > mergedLayers, KisNodeSP putAfter)
void mergeDown(KisLayerSP l, const KisMetaData::MergeStrategy *strategy)
QRect bounds() const override
void setResolution(double xres, double yres)
static QStringList supportedMimeTypes(Direction direction)
void addLayerCommon(KisNodeSP activeNode, KisNodeSP layer, bool updateImage=true, KisProcessingApplicator *applicator=0)
KisNodeSP addShapeLayer(KisNodeSP activeNode)
KisNodeSP addGeneratorLayer(KisNodeSP activeNode)
void imageResizeToActiveLayer()
void setView(QPointer< KisView >view)
KisNodeSP addFileLayer(KisNodeSP activeNode)
KisAction * m_imageResizeToLayer
void activateLayer(KisLayerSP layer)
KisLayerManager(KisViewManager *view)
void adjustLayerPosition(KisNodeSP node, KisNodeSP activeNode, KisNodeSP &parent, KisNodeSP &above)
KisPaintDeviceSP activeDevice()
void convertGroupToAnimated()
KisAction * m_copyLayerStyle
bool activeLayerHasSelection()
void setup(KisActionManager *actionManager)
void convertLayerToFileLayer(KisNodeSP source)
KisLayerSP addPaintLayer(KisNodeSP activeNode)
KisAction * m_flattenLayer
KisAction * m_convertGroupAnimated
KisNodeSP addGroupLayer(KisNodeSP activeNode)
KisNodeSP addCloneLayer(KisNodeList nodes)
KisAction * m_imageFlatten
bool m_layerPropertiesDialogActive
QPointer< KisView > m_imageView
void convertNodeToPaintLayer(KisNodeSP source)
KisAction * m_pasteLayerStyle
KisAction * m_imageMergeLayer
KisAction * m_groupLayersSave
~KisLayerManager() override
void layerPropertiesDialogClosed()
KisNodeSP addAdjustmentLayer(KisNodeSP activeNode)
KisNodeCommandsAdapter * m_commandsAdapter
static QStringList suffixesForMimeType(const QString &mimeType)
static QString mimeTypeForFile(const QString &file, bool checkExistingFiles=true)
Find the mimetype for the given filename. The filename must include a suffix.
void addNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis, KisImageLayerAddCommand::Flags flags=KisImageLayerAddCommand::DoRedoUpdates|KisImageLayerAddCommand::DoUndoUpdates)
void removeNode(KisNodeSP node)
void addNodeAsync(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis, bool doRedoUpdates=true, bool doUndoUpdates=true, KisProcessingApplicator *applicator=0)
void beginMacro(const KUndo2MagicString ¯oName)
virtual KisFilterConfigurationSP filter() const
KisNodeList selectedNodes()
bool canModifyLayers(KisNodeList nodes, bool showWarning=true)
bool canModifyLayer(KisNodeSP node, bool showWarning=true)
The command for setting the node's name.
QRect nonDefaultPixelArea() const
virtual const KoColorSpace * compositionSourceColorSpace() const
void convertTo(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags(), KUndo2Command *parentCommand=nullptr, KoUpdater *progressUpdater=nullptr)
static KisPart * instance()
void addCommand(KUndo2CommandSP command)
static void runSingleCommandStroke(KisImageSP image, KUndo2Command *cmd, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
runSingleCommandStroke creates a stroke and runs cmd in it. The text() field of cmd is used as a titl...
const KisStrokeId getStroke() const
void applyCommand(KUndo2Command *command, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
The KisRasterKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisRas...
void importFrame(int time, KisPaintDeviceSP sourceDevice, KUndo2Command *parentCommand)
The KisSaveGroupVisitor class saves the groups in a Krita image to separate images.
static void updateLayerStyle(KisLayerSP layer, KisPSDLayerStyleSP style)
void setProfile(KisImageWSP image)
virtual void addCommand(KUndo2Command *cmd)=0
bool blockUntilOperationsFinished(KisImageSP image)
blockUntilOperationsFinished blocks the GUI of the application until execution of actions on image is...
KisMainWindow * mainWindow() const
KisDocument * document() const
KisCanvas2 * canvasBase() const
Return the canvas base class.
KisUndoAdapter * undoAdapter()
The undo adapter is used to add commands to the undo stack.
KisSelectionSP selection()
QWidget * canvas() const
Return the actual widget that is displaying the current image.
KisNodeManager * nodeManager() const
The node manager handles everything about nodes.
KisImageWSP image() const
Return the image this view is displaying.
KisCanvasResourceProvider * canvasResourceProvider()
KisStatusBar * statusBar() const
Return the wrapper class around the statusbar.
void showFloatingMessage(const QString &message, const QIcon &icon, int timeout=4500, KisFloatingMessage::Priority priority=KisFloatingMessage::Medium, int alignment=Qt::AlignCenter|Qt::TextWordWrap)
shows a floating message in the top right corner of the canvas
QPointer< KoCanvasResourceProvider > resourceManager
void toQColor(QColor *c) const
a convenience method for the above.
A dialog base class with standard buttons and predefined layouts.
void setMainWidget(QWidget *widget)
virtual void setCaption(const QString &caption)
QSize minimumSizeHint() const override
T get(const QString &id) const
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_ASSERT_RECOVER_RETURN(cond)
bool isSelectionMask(KisNodeSP node)
void updateLayerStyles(KisLayerSP layer, KisDlgLayerStyle *dlg, KoCanvasResourcesInterfaceSP canvasResourcesInterface)
bool tryMergeSelectionMasks(KisNodeSP currentNode, KisImageSP image)
bool tryFlattenGroupLayer(KisNodeSP currentNode, KisImageSP image)
KisDocument * createDocument(QList< KisNodeSP > nodes, KisImageSP srcImage, const QRect &copiedBounds)
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
QSharedPointer< T > toQShared(T *ptr)
KisSharedPtr< KisFileLayer > KisFileLayerSP
KisSharedPtr< KisAdjustmentLayer > KisAdjustmentLayerSP
KisSharedPtr< KisGeneratorLayer > KisGeneratorLayerSP
KisSharedPtr< KisNode > KisNodeSP
KUndo2MagicString kundo2_i18n(const char *text)
KisNodeList sortAndFilterMergeableInternalNodes(KisNodeList nodes, bool allowMasks)
std::future< KisNodeSP > convertToPaintLayer(KisImageSP image, KisNodeSP src)
void setPinnedToTimeline(bool pinned)
virtual KisPaintDeviceSP projection() const =0
bool isEditable(bool checkVisibility=true) const
KisKeyframeChannel * getKeyframeChannel(const QString &id, bool create)
void setName(const QString &name)
virtual KisPaintDeviceSP paintDevice() const =0
bool projectionIsValid() const
const KoColorSpace * colorSpace() const override
bool accept(KisNodeVisitor &v) override
void resetCache(const KoColorSpace *colorSpace)
KisPaintDeviceSP projection() const override
KisMetaData::Store * metaData()
KisPSDLayerStyleSP layerStyle
void setX(qint32 x) override
void setY(qint32 y) override
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)
KisNodeSP prevSibling() const
KisNodeSP firstChild() const
quint32 childCount() const
KisNodeSP nextSibling() const
The KisPSDLayerStyle class implements loading, saving and applying the PSD layer effects.
KisPaintDeviceSP paintDevice