11#include <QApplication>
17#include <QStandardPaths>
22#include <klocalizedstring.h>
170 connect(action, SIGNAL(triggered()),
this, SLOT(
trimToImage()));
172 action = actionManager->
createAction(
"purge_unused_image_data");
190 const bool isGroupLayer = layer && layer->inherits(
"KisGroupLayer");
192 QString mergeLayerText;
194 mergeLayerText = i18nc(
"@action:inmenu",
"Merge Selected Layers");
195 }
else if (isGroupLayer) {
196 mergeLayerText = i18nc(
"@action:inmenu",
"Merge Group");
198 mergeLayerText = i18nc(
"@action:inmenu",
"Merge with Layer Below");
215 if (!cropRect.isEmpty()) {
219 i18nc(
"floating message in layer manager",
255 const bool multipleLayersSelected = selectedNodes.size() > 1;
263 if (adjustmentLayer && !multipleLayersSelected) {
271 QString xmlBefore = configBefore->toXML();
273 if (dlg.exec() == QDialog::Accepted) {
277 Q_ASSERT(configAfter);
278 QString xmlAfter = configAfter->toXML();
280 if(xmlBefore != xmlAfter) {
283 configBefore->cloneWithResourcesSnapshot(),
284 configAfter->cloneWithResourcesSnapshot()));
287 if (adjustmentLayer->name() != dlg.
layerName()) {
290 adjustmentLayer->name(),
300 Q_ASSERT(configAfter);
301 QString xmlAfter = configAfter->toXML();
303 if(xmlBefore != xmlAfter) {
304 adjustmentLayer->setFilter(configBefore->cloneWithResourcesSnapshot());
305 adjustmentLayer->setDirty();
309 else if (fileLayer && !multipleLayersSelected){
311 QString fileNameOld = fileLayer->
fileName();
315 dlg.
setCaption(i18n(
"File Layer Properties"));
320 if (dlg.exec() == QDialog::Accepted) {
321 const QString fileNameNew = dlg.
fileName();
325 if(fileNameNew.isEmpty()){
326 QMessageBox::critical(
m_view->
mainWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"No file name specified"));
332 if (fileNameOld != fileNameNew || scalingMethodOld != scalingMethodNew
333 || scalingFilterOld != scalingFilterNew) {
357 QDialog* dlg =
nullptr;
359 if (generatorLayer && !multipleLayersSelected) {
361 Q_ASSERT(configBefore);
364 genDlg->setWindowTitle(i18n(
"Fill Layer Properties"));
365 genDlg->setConfiguration(configBefore.
data());
375 dlg->resize(dlg->minimumSizeHint());
376 dlg->setAttribute(Qt::WA_DeleteOnClose);
378 const Qt::WindowFlags flags = dlg->windowFlags();
381 dlg->setWindowFlags(flags | Qt::Dialog);
383 dlg->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
389 dlg->activateWindow();
401 if (selectedNodes.isEmpty()) {
407 Q_FOREACH (node, selectedNodes) {
410 cloneLayers << cloneLayer;
414 if (cloneLayers.isEmpty()) {
421 dialog->setCaption(i18n(
"Change Clone Layer"));
422 dialog->resize(dialog->minimumSizeHint());
423 dialog->setAttribute(Qt::WA_DeleteOnClose);
424 Qt::WindowFlags flags = dialog->windowFlags();
425 dialog->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
427 dialog->activateWindow();
445 if (!psdxml.isEmpty()) {
446 QMimeData *mimeData =
new QMimeData;
448 mimeData->setText(psdxml);
449 mimeData->setData(
"application/x-krita-layer-style", psdxml.toUtf8());
451 QGuiApplication::clipboard()->setMimeData(mimeData);
466 aslXml = QString::fromUtf8(QGuiApplication::clipboard()->mimeData()->data(
"application/x-krita-layer-style"));
468 aslXml = QGuiApplication::clipboard()->text();
471 if (aslXml.isEmpty())
return;
474 if (!aslDoc.setContent(aslXml))
return;
480 if (serializer.
styles().size() != 1)
return;
500 if (srcLayer && (srcLayer->inherits(
"KisGroupLayer") || srcLayer->
layerStyle() || srcLayer->
childCount() > 0)) {
511 if (targetGroup.
isNull()) {
514 if (!parent->parent())
return;
518 if (targetGroup.
isNull())
return;
553 QWidget *page =
new QWidget(&dlg);
555 QBoxLayout *layout =
new QVBoxLayout(page);
556 dlg.setWindowTitle(i18n(
"Save layers to..."));
557 QLabel *lbl =
new QLabel(i18n(
"Choose the location where the layer will be saved to. The new file layer will then reference this location."));
558 lbl->setWordWrap(
true);
559 layout->addWidget(lbl);
566 location.setFile(location.dir(), location.completeBaseName() +
"_" +
source->name() +
".png");
567 urlRequester->
setFileName(location.absoluteFilePath());
570 const QFileInfo location = QFileInfo(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
571 const QString proposedFileName = QDir(location.absoluteFilePath()).absoluteFilePath(
source->name() +
".png");
575 layout->addWidget(urlRequester);
576 if (!dlg.exec())
return;
578 QString path = urlRequester->
fileName();
580 if (path.isEmpty())
return;
585 if (mimeType.isEmpty()) {
586 mimeType =
"image/png";
600 doc->setFileBatchMode(
false);
601 doc->setCurrentImage(dst);
608 bool r = doc->exportDocumentSync(path, mimeType.toLatin1());
611 qWarning() <<
"Converting layer to file layer. path:"<< path <<
"gave errors" << doc->errorMessage();
614 QString relativePath = QDir(basePath).relativeFilePath(path);
625 doc->closePath(
false);
630 Q_ASSERT(activeNode);
633 above = parent->lastChild();
635 if (parent->inherits(
"KisGroupLayer") && parent->collapsed()) {
637 parent = parent->parent();
642 (!parent->allowAsChild(node) || !parent->isEditable(
false))) {
645 parent = parent->parent();
649 warnKrita <<
"KisLayerManager::adjustLayerPosition:"
650 <<
"No node accepted newly created node";
653 above = parent->lastChild();
665 if (layer->inherits(
"KisGroupLayer") || layer->inherits(
"KisPaintLayer")) {
668 if (layer->inherits(
"KisGroupLayer")) {
678 updateImage |= parentForceUpdate;
709 if (filteredNodes.isEmpty())
return KisNodeSP();
711 KisNodeSP newAbove = filteredNodes.last();
714 Q_FOREACH (node, filteredNodes) {
719 return lastClonedNode;
759 if (dlg.exec() != QDialog::Accepted || adjl->filter().isNull()) {
802 defaultConfig->setProperty(
"color", currentForeground);
805 if (dlg.exec() == QDialog::Accepted) {
827 i18nc(
"@title:window",
"Flatten Image"),
828 i18n(
"The image contains hidden layers that will be lost. Do you want to flatten the image?"),
829 QMessageBox::Yes | QMessageBox::No,
832 if (answer != QMessageBox::Yes) {
856 mergedNodes.append(currentNode);
857 mergedNodes.append(prevNode);
871 if (currentNode->inherits(
"KisGroupLayer")) {
895 bool hasEditableLayer =
false;
896 Q_FOREACH (
KisNodeSP node, selectedNodes) {
898 hasEditableLayer =
true;
903 if (!hasEditableLayer) {
905 i18ncp(
"floating message in layer manager",
906 "Layer is locked",
"Layers are locked", selectedNodes.size()),
911 if (selectedNodes.size() > 1) {
923 if (!prevLayer)
return;
927 i18nc(
"floating message in layer manager when previous layer is locked",
940 if (!strategy)
return;
944 i18nc(
"floating message in layer manager when trying to merge a non-animated layer into an animated one",
945 "Non-animated layer is merged into the current frame. To merge it into the whole clip, create at least one frame"),
983 QWidget *page =
new QWidget(&dlg);
985 QBoxLayout *layout =
new QVBoxLayout(page);
992 layout->addWidget(urlRequester);
994 QCheckBox *chkInvisible =
new QCheckBox(i18n(
"Convert Invisible Groups"), page);
995 chkInvisible->setChecked(
false);
996 layout->addWidget(chkInvisible);
997 QCheckBox *chkDepth =
new QCheckBox(i18n(
"Export Only Toplevel Groups"), page);
998 chkDepth->setChecked(
true);
999 layout->addWidget(chkDepth);
1001 if (!dlg.exec())
return;
1003 QString path = urlRequester->
fileName();
1005 if (path.isEmpty())
return;
1010 if (mimeType.isEmpty()) {
1011 mimeType =
"image/png";
1014 QString basename = f.completeBaseName();
1019 KisSaveGroupVisitor v(image, chkInvisible->isChecked(), chkDepth->isChecked(), f.absolutePath(), basename, extension, mimeType);
1033 basePath = QFileInfo(path).absolutePath();
1039 if (dlg.exec() == QDialog::Accepted) {
1043 if(fileName.isEmpty()){
1044 QMessageBox::critical(
m_view->
mainWindow(), i18nc(
"@title:window",
"Krita"), i18n(
"No file name specified"));
1060 dlg->
style()->cloneWithResourcesSnapshot(
1062 canvasResourcesInterface));
1085 canvasResourcesInterface);
1090 newStyle->setUuid(QUuid::createUuid());
1094 std::function<
void ()> updateCall(std::bind(
updateLayerStyles, layer, &dlg, canvasResourcesInterface));
1096 connect(&dlg, SIGNAL(configChanged()), &proxy, SLOT(start()));
1098 if (dlg.exec() == QDialog::Accepted) {
1101 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
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
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