11#include <QApplication>
17#include <QStandardPaths>
22#include <klocalizedstring.h>
169 connect(action, SIGNAL(triggered()),
this, SLOT(
trimToImage()));
171 action = actionManager->
createAction(
"purge_unused_image_data");
189 const bool isGroupLayer = layer && layer->inherits(
"KisGroupLayer");
191 QString mergeLayerText;
193 mergeLayerText = i18nc(
"@action:inmenu",
"Merge Selected Layers");
194 }
else if (isGroupLayer) {
195 mergeLayerText = i18nc(
"@action:inmenu",
"Merge Group");
197 mergeLayerText = i18nc(
"@action:inmenu",
"Merge with Layer Below");
214 if (!cropRect.isEmpty()) {
218 i18nc(
"floating message in layer manager",
254 const bool multipleLayersSelected = selectedNodes.size() > 1;
262 if (adjustmentLayer && !multipleLayersSelected) {
266 adjustmentLayer->name(), i18n(
"Filter Layer Properties"),
272 QString xmlBefore = configBefore->toXML();
274 if (dlg.exec() == QDialog::Accepted) {
278 Q_ASSERT(configAfter);
279 QString xmlAfter = configAfter->toXML();
281 if(xmlBefore != xmlAfter) {
284 configBefore->cloneWithResourcesSnapshot(),
285 configAfter->cloneWithResourcesSnapshot()));
288 if (adjustmentLayer->name() != dlg.
layerName()) {
291 adjustmentLayer->name(),
301 Q_ASSERT(configAfter);
302 QString xmlAfter = configAfter->toXML();
304 if(xmlBefore != xmlAfter) {
305 adjustmentLayer->setFilter(configBefore->cloneWithResourcesSnapshot());
306 adjustmentLayer->setDirty();
310 else if (fileLayer && !multipleLayersSelected){
312 QString fileNameOld = fileLayer->
fileName();
316 dlg.
setCaption(i18n(
"File Layer Properties"));
321 if (dlg.exec() == QDialog::Accepted) {
322 const QString fileNameNew = dlg.
fileName();
326 if(fileNameNew.isEmpty()){
327 QMessageBox::critical(
m_view->
mainWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"No file name specified"));
333 if (fileNameOld != fileNameNew || scalingMethodOld != scalingMethodNew
334 || scalingFilterOld != scalingFilterNew) {
358 QDialog* dlg =
nullptr;
360 if (generatorLayer && !multipleLayersSelected) {
362 Q_ASSERT(configBefore);
365 genDlg->setWindowTitle(i18n(
"Fill Layer Properties"));
366 genDlg->setConfiguration(configBefore.
data());
376 dlg->resize(dlg->minimumSizeHint());
377 dlg->setAttribute(Qt::WA_DeleteOnClose);
379 const Qt::WindowFlags flags = dlg->windowFlags();
382 dlg->setWindowFlags(flags | Qt::Dialog);
384 dlg->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
390 dlg->activateWindow();
402 if (selectedNodes.isEmpty()) {
408 Q_FOREACH (node, selectedNodes) {
411 cloneLayers << cloneLayer;
415 if (cloneLayers.isEmpty()) {
422 dialog->setCaption(i18n(
"Change Clone Layer"));
423 dialog->resize(dialog->minimumSizeHint());
424 dialog->setAttribute(Qt::WA_DeleteOnClose);
425 Qt::WindowFlags flags = dialog->windowFlags();
426 dialog->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
428 dialog->activateWindow();
446 if (!psdxml.isEmpty()) {
447 QMimeData *mimeData =
new QMimeData;
449 mimeData->setText(psdxml);
450 mimeData->setData(
"application/x-krita-layer-style", psdxml.toUtf8());
452 QGuiApplication::clipboard()->setMimeData(mimeData);
467 aslXml = QString::fromUtf8(QGuiApplication::clipboard()->mimeData()->data(
"application/x-krita-layer-style"));
469 aslXml = QGuiApplication::clipboard()->text();
472 if (aslXml.isEmpty())
return;
475 if (!aslDoc.setContent(aslXml))
return;
481 if (serializer.
styles().size() != 1)
return;
501 if (srcLayer && (srcLayer->inherits(
"KisGroupLayer") || srcLayer->
layerStyle() || srcLayer->
childCount() > 0)) {
512 if (targetGroup.
isNull()) {
515 if (!parent->parent())
return;
519 if (targetGroup.
isNull())
return;
554 QWidget *page =
new QWidget(&dlg);
556 QBoxLayout *layout =
new QVBoxLayout(page);
557 dlg.setWindowTitle(i18n(
"Save layers to..."));
558 QLabel *lbl =
new QLabel(i18n(
"Choose the location where the layer will be saved to. The new file layer will then reference this location."));
559 lbl->setWordWrap(
true);
560 layout->addWidget(lbl);
567 location.setFile(location.dir(), location.completeBaseName() +
"_" +
source->name() +
".png");
568 urlRequester->
setFileName(location.absoluteFilePath());
571 const QFileInfo location = QFileInfo(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
572 const QString proposedFileName = QDir(location.absoluteFilePath()).absoluteFilePath(
source->name() +
".png");
576 layout->addWidget(urlRequester);
577 if (!dlg.exec())
return;
579 QString path = urlRequester->
fileName();
581 if (path.isEmpty())
return;
586 if (mimeType.isEmpty()) {
587 mimeType =
"image/png";
601 doc->setFileBatchMode(
false);
602 doc->setCurrentImage(dst);
609 bool r = doc->exportDocumentSync(path, mimeType.toLatin1());
612 qWarning() <<
"Converting layer to file layer. path:"<< path <<
"gave errors" << doc->errorMessage();
615 QString relativePath = QDir(basePath).relativeFilePath(path);
626 doc->closePath(
false);
631 Q_ASSERT(activeNode);
634 above = parent->lastChild();
636 if (parent->inherits(
"KisGroupLayer") && parent->collapsed()) {
638 parent = parent->parent();
643 (!parent->allowAsChild(node) || !parent->isEditable(
false))) {
646 parent = parent->parent();
650 warnKrita <<
"KisLayerManager::adjustLayerPosition:"
651 <<
"No node accepted newly created node";
654 above = parent->lastChild();
666 if (layer->inherits(
"KisGroupLayer") || layer->inherits(
"KisPaintLayer")) {
669 if (layer->inherits(
"KisGroupLayer")) {
679 updateImage |= parentForceUpdate;
710 if (filteredNodes.isEmpty())
return KisNodeSP();
712 KisNodeSP newAbove = filteredNodes.last();
715 Q_FOREACH (node, filteredNodes) {
720 return lastClonedNode;
760 if (dlg.exec() != QDialog::Accepted || adjl->filter().isNull()) {
803 defaultConfig->setProperty(
"color", currentForeground);
806 if (dlg.exec() == QDialog::Accepted) {
828 i18nc(
"@title:window",
"Flatten Image"),
829 i18n(
"The image contains hidden layers that will be lost. Do you want to flatten the image?"),
830 QMessageBox::Yes | QMessageBox::No,
833 if (answer != QMessageBox::Yes) {
857 mergedNodes.append(currentNode);
858 mergedNodes.append(prevNode);
872 if (currentNode->inherits(
"KisGroupLayer")) {
896 bool hasEditableLayer =
false;
897 Q_FOREACH (
KisNodeSP node, selectedNodes) {
899 hasEditableLayer =
true;
904 if (!hasEditableLayer) {
906 i18ncp(
"floating message in layer manager",
907 "Layer is locked",
"Layers are locked", selectedNodes.size()),
912 if (selectedNodes.size() > 1) {
924 if (!prevLayer)
return;
928 i18nc(
"floating message in layer manager when previous layer is locked",
941 if (!strategy)
return;
945 i18nc(
"floating message in layer manager when trying to merge a non-animated layer into an animated one",
946 "Non-animated layer is merged into the current frame. To merge it into the whole clip, create at least one frame"),
984 QWidget *page =
new QWidget(&dlg);
986 QBoxLayout *layout =
new QVBoxLayout(page);
993 layout->addWidget(urlRequester);
995 QCheckBox *chkInvisible =
new QCheckBox(i18n(
"Convert Invisible Groups"), page);
996 chkInvisible->setChecked(
false);
997 layout->addWidget(chkInvisible);
998 QCheckBox *chkDepth =
new QCheckBox(i18n(
"Export Only Toplevel Groups"), page);
999 chkDepth->setChecked(
true);
1000 layout->addWidget(chkDepth);
1002 if (!dlg.exec())
return;
1004 QString path = urlRequester->
fileName();
1006 if (path.isEmpty())
return;
1011 if (mimeType.isEmpty()) {
1012 mimeType =
"image/png";
1015 QString basename = f.completeBaseName();
1020 KisSaveGroupVisitor v(image, chkInvisible->isChecked(), chkDepth->isChecked(), f.absolutePath(), basename, extension, mimeType);
1034 basePath = QFileInfo(path).absolutePath();
1040 if (dlg.exec() == QDialog::Accepted) {
1044 if(fileName.isEmpty()){
1045 QMessageBox::critical(
m_view->
mainWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"No file name specified"));
1061 dlg->
style()->cloneWithResourcesSnapshot(
1063 canvasResourcesInterface));
1086 canvasResourcesInterface);
1091 newStyle->setUuid(QUuid::createUuid());
1095 std::function<
void ()> updateCall(std::bind(
updateLayerStyles, layer, &dlg, canvasResourcesInterface));
1097 connect(&dlg, SIGNAL(configChanged()), &proxy, SLOT(start()));
1099 if (dlg.exec() == QDialog::Accepted) {
1102 canvasResourcesInterface);
QVector< KisImageSignalType > KisImageSignalVector
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
const quint8 OPACITY_OPAQUE_U8
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
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
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
void purgeUnusedData(bool isCancellable)
purge all pixels that have default pixel to free up memory
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 purgeUnusedImageData()
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)
KUndo2Command * composeCommands(KUndo2Command *parent, KUndo2Command *cmd)
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)
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