Krita

Document.cpp
1 /*
2  * SPDX-FileCopyrightText: 2016 Boudewijn Rempt <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.0-or-later
5  */
6 #include "Document.h"
7 #include <QPointer>
8 #include <QUrl>
9 #include <QDomDocument>
10 
11 #include <KoColorSpaceConstants.h>
12 #include <KisDocument.h>
13 #include <kis_image.h>
14 #include <KisPart.h>
15 #include <kis_paint_device.h>
16 #include <KisMainWindow.h>
17 #include <kis_node_manager.h>
18 #include <kis_node_selection_adapter.h>
19 #include <KisViewManager.h>
20 #include <kis_file_layer.h>
21 #include <kis_adjustment_layer.h>
22 #include <kis_mask.h>
23 #include <kis_clone_layer.h>
24 #include <kis_group_layer.h>
25 #include <kis_filter_mask.h>
26 #include <kis_transform_mask.h>
27 #include <kis_transparency_mask.h>
28 #include <kis_selection_mask.h>
29 #include <lazybrush/kis_colorize_mask.h>
30 #include <kis_effect_mask.h>
31 #include <kis_paint_layer.h>
32 #include <kis_generator_layer.h>
33 #include <kis_generator_registry.h>
34 #include <kis_shape_layer.h>
35 #include <kis_filter_configuration.h>
36 #include <kis_filter_registry.h>
37 #include <kis_selection.h>
38 #include <KisMimeDatabase.h>
39 #include <kis_filter_strategy.h>
40 #include <kis_guides_config.h>
41 #include <kis_coordinates_converter.h>
42 #include <kis_time_span.h>
43 #include <KisImportExportErrorCode.h>
44 #include <kis_types.h>
45 #include <kis_annotation.h>
46 
47 #include <KoColor.h>
48 #include <KoColorSpace.h>
49 #include <KoColorProfile.h>
50 #include <KoColorSpaceRegistry.h>
51 #include <KoColorConversionTransformation.h>
52 #include <KoDocumentInfo.h>
53 #include <KisGlobalResourcesInterface.h>
54 
55 #include <InfoObject.h>
56 #include <Node.h>
57 #include <Selection.h>
58 #include <LibKisUtils.h>
59 
60 #include "kis_animation_importer.h"
61 #include <kis_canvas2.h>
62 #include <KoUpdater.h>
63 #include <QMessageBox>
64 
65 #include <kis_image_animation_interface.h>
66 #include <kis_layer_utils.h>
67 
68 struct Document::Private {
69  Private() {}
70  QPointer<KisDocument> document;
71  bool ownsDocument {false};
72 };
73 
74 Document::Document(KisDocument *document, bool ownsDocument, QObject *parent)
75  : QObject(parent)
76  , d(new Private)
77 {
78  d->document = document;
79  d->ownsDocument = ownsDocument;
80 }
81 
82 Document::~Document()
83 {
84  if (d->ownsDocument && d->document) {
85  KisPart::instance()->removeDocument(d->document);
86  delete d->document;
87  }
88  delete d;
89 }
90 
91 bool Document::operator==(const Document &other) const
92 {
93  return (d->document == other.d->document);
94 }
95 
96 bool Document::operator!=(const Document &other) const
97 {
98  return !(operator==(other));
99 }
100 
102 {
103  if (!d->document) return false;
104  return d->document->fileBatchMode();
105 }
106 
107 void Document::setBatchmode(bool value)
108 {
109  if (!d->document) return;
110  d->document->setFileBatchMode(value);
111 }
112 
114 {
115  QList<KisNodeSP> activeNodes;
116  Q_FOREACH(QPointer<KisView> view, KisPart::instance()->views()) {
117  if (view && view->document() == d->document) {
118  activeNodes << view->currentNode();
119 
120  }
121  }
122  if (activeNodes.size() > 0) {
123  QList<Node*> nodes = LibKisUtils::createNodeList(activeNodes, d->document->image());
124  return nodes.first();
125  }
126 
127  return 0;
128 }
129 
131 {
132  if (!value) return;
133  if (!value->node()) return;
134  KisMainWindow *mainWin = KisPart::instance()->currentMainwindow();
135  if (!mainWin) return;
136  KisViewManager *viewManager = mainWin->viewManager();
137  if (!viewManager) return;
138  if (viewManager->document() != d->document) return;
139  KisNodeManager *nodeManager = viewManager->nodeManager();
140  if (!nodeManager) return;
141  KisNodeSelectionAdapter *selectionAdapter = nodeManager->nodeSelectionAdapter();
142  if (!selectionAdapter) return;
143  selectionAdapter->setActiveNode(value->node());
144 
145 }
146 
148 {
149  if (!d->document) return QList<Node *>();
150  Node n(d->document->image(), d->document->image()->rootLayer());
151  return n.childNodes();
152 }
153 
154 
155 Node *Document::nodeByName(const QString &name) const
156 {
157  if (!d->document) return 0;
158  KisNodeSP node = KisLayerUtils::findNodeByName(d->document->image()->rootLayer(),name);
159 
160  if (node.isNull()) return 0;
161 
162  return Node::createNode(d->document->image(), node);
163 }
164 
166 {
167  if (!d->document) return 0;
168 
169  KisNodeSP node = KisLayerUtils::findNodeByUuid(d->document->image()->rootLayer(), id);
170 
171  if (node.isNull()) return 0;
172  return Node::createNode(d->document->image(), node);
173 }
174 
175 
177 {
178  if (!d->document) return "";
179  return d->document->image()->colorSpace()->colorDepthId().id();
180 }
181 
183 {
184  if (!d->document) return "";
185  return d->document->image()->colorSpace()->colorModelId().id();
186 }
187 
189 {
190  if (!d->document) return "";
191  return d->document->image()->colorSpace()->profile()->name();
192 }
193 
195 {
196  if (!d->document) return false;
197  if (!d->document->image()) return false;
198  const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(value);
199  if (!profile) return false;
200  bool retval = d->document->image()->assignImageProfile(profile);
201  d->document->image()->waitForDone();
202  return retval;
203 }
204 
205 bool Document::setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile)
206 {
207  if (!d->document) return false;
208  if (!d->document->image()) return false;
209  const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(colorModel, colorDepth, colorProfile);
210  if (!colorSpace) return false;
211 
212  d->document->image()->convertImageColorSpace(colorSpace,
213  KoColorConversionTransformation::IntentPerceptual,
214  KoColorConversionTransformation::HighQuality | KoColorConversionTransformation::NoOptimization);
215 
216  d->document->image()->waitForDone();
217  return true;
218 }
219 
221 {
222  if (!d->document) return QColor();
223  if (!d->document->image()) return QColor();
224 
225  const KoColor color = d->document->image()->defaultProjectionColor();
226  return color.toQColor();
227 }
228 
230 {
231  if (!d->document) return false;
232  if (!d->document->image()) return false;
233 
234  KoColor background = KoColor(color, d->document->image()->colorSpace());
235  d->document->image()->setDefaultProjectionColor(background);
236 
237  d->document->image()->setModifiedWithoutUndo();
238  d->document->image()->initialRefreshGraph();
239 
240  return true;
241 }
242 
244 {
245  QDomDocument doc = KisDocument::createDomDocument("document-info"
246  /*DTD name*/, "document-info" /*tag name*/, "1.1");
247  doc = d->document->documentInfo()->save(doc);
248  return doc.toString();
249 }
250 
251 void Document::setDocumentInfo(const QString &document)
252 {
253  QDomDocument doc;
254  QString errorMsg;
255  int errorLine, errorColumn;
256  doc.setContent(document, &errorMsg, &errorLine, &errorColumn);
257  d->document->documentInfo()->load(doc);
258 }
259 
260 
262 {
263  if (!d->document) return QString();
264  return d->document->path();
265 }
266 
268 {
269  if (!d->document) return;
270  QString mimeType = KisMimeDatabase::mimeTypeForFile(value, false);
271  d->document->setMimeType(mimeType.toLatin1());
272  d->document->setPath(value);
273 }
274 
275 int Document::height() const
276 {
277  if (!d->document) return 0;
278  KisImageSP image = d->document->image();
279  if (!image) return 0;
280  return image->height();
281 }
282 
283 void Document::setHeight(int value)
284 {
285  if (!d->document) return;
286  if (!d->document->image()) return;
287  resizeImage(d->document->image()->bounds().x(),
288  d->document->image()->bounds().y(),
289  d->document->image()->width(),
290  value);
291 }
292 
293 
295 {
296  if (!d->document) return "";
297  return d->document->documentInfo()->aboutInfo("title");
298 }
299 
301 {
302  if (!d->document) return;
303  d->document->documentInfo()->setAboutInfo("title", value);
304 }
305 
306 
308 {
309  if (!d->document) return 0;
310  KisImageSP image = d->document->image();
311  if (!image) return 0;
312 
313  return qRound(d->document->image()->xRes() * 72);
314 }
315 
316 void Document::setResolution(int value)
317 {
318  if (!d->document) return;
319  KisImageSP image = d->document->image();
320  if (!image) return;
321 
322  KisFilterStrategy *strategy = KisFilterStrategyRegistry::instance()->get("Bicubic");
323  KIS_SAFE_ASSERT_RECOVER_RETURN(strategy);
324 
325  image->scaleImage(image->size(), value / 72.0, value / 72.0, strategy);
326  image->waitForDone();
327 }
328 
329 
331 {
332  if (!d->document) return 0;
333  KisImageSP image = d->document->image();
334  if (!image) return 0;
335 
336  return Node::createNode(image, image->root());
337 }
338 
340 {
341  if (!d->document) return 0;
342  if (!d->document->image()) return 0;
343  if (!d->document->image()->globalSelection()) return 0;
344  return new Selection(d->document->image()->globalSelection());
345 }
346 
348 {
349  if (!d->document) return;
350  if (!d->document->image()) return;
351  if (value) {
352  d->document->image()->setGlobalSelection(value->selection());
353  }
354  else {
355  d->document->image()->setGlobalSelection(0);
356  }
357 }
358 
359 
360 int Document::width() const
361 {
362  if (!d->document) return 0;
363  KisImageSP image = d->document->image();
364  if (!image) return 0;
365  return image->width();
366 }
367 
368 void Document::setWidth(int value)
369 {
370  if (!d->document) return;
371  if (!d->document->image()) return;
372  resizeImage(d->document->image()->bounds().x(),
373  d->document->image()->bounds().y(),
374  value,
375  d->document->image()->height());
376 }
377 
378 
379 int Document::xOffset() const
380 {
381  if (!d->document) return 0;
382  KisImageSP image = d->document->image();
383  if (!image) return 0;
384  return image->bounds().x();
385 }
386 
388 {
389  if (!d->document) return;
390  if (!d->document->image()) return;
391  resizeImage(x,
392  d->document->image()->bounds().y(),
393  d->document->image()->width(),
394  d->document->image()->height());
395 }
396 
397 
398 int Document::yOffset() const
399 {
400  if (!d->document) return 0;
401  KisImageSP image = d->document->image();
402  if (!image) return 0;
403  return image->bounds().y();
404 }
405 
407 {
408  if (!d->document) return;
409  if (!d->document->image()) return;
410  resizeImage(d->document->image()->bounds().x(),
411  y,
412  d->document->image()->width(),
413  d->document->image()->height());
414 }
415 
416 
417 double Document::xRes() const
418 {
419  if (!d->document) return 0.0;
420  if (!d->document->image()) return 0.0;
421  return d->document->image()->xRes()*72.0;
422 }
423 
424 void Document::setXRes(double xRes) const
425 {
426  if (!d->document) return;
427  KisImageSP image = d->document->image();
428  if (!image) return;
429 
430  KisFilterStrategy *strategy = KisFilterStrategyRegistry::instance()->get("Bicubic");
431  KIS_SAFE_ASSERT_RECOVER_RETURN(strategy);
432 
433  image->scaleImage(image->size(), xRes / 72.0, image->yRes(), strategy);
434  image->waitForDone();
435 }
436 
437 double Document::yRes() const
438 {
439  if (!d->document) return 0.0;
440  if (!d->document->image()) return 0.0;
441  return d->document->image()->yRes()*72.0;
442 }
443 
444 void Document::setYRes(double yRes) const
445 {
446  if (!d->document) return;
447  KisImageSP image = d->document->image();
448  if (!image) return;
449 
450  KisFilterStrategy *strategy = KisFilterStrategyRegistry::instance()->get("Bicubic");
451  KIS_SAFE_ASSERT_RECOVER_RETURN(strategy);
452 
453  image->scaleImage(image->size(), image->xRes(), yRes / 72.0, strategy);
454  image->waitForDone();
455 }
456 
457 
458 QByteArray Document::pixelData(int x, int y, int w, int h) const
459 {
460  QByteArray ba;
461 
462  if (!d->document) return ba;
463  KisImageSP image = d->document->image();
464  if (!image) return ba;
465 
466  KisPaintDeviceSP dev = image->projection();
467  ba.resize(w * h * dev->pixelSize());
468  dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
469  return ba;
470 }
471 
473 {
474  bool retval = d->document->closePath(false);
475 
476  Q_FOREACH(KisView *view, KisPart::instance()->views()) {
477  if (view->document() == d->document) {
478  view->close();
479  view->closeView();
480  view->deleteLater();
481  }
482  }
483 
484  KisPart::instance()->removeDocument(d->document, !d->ownsDocument);
485 
486  if (d->ownsDocument) {
487 
488  delete d->document;
489  }
490 
491  d->document = 0;
492  return retval;
493 }
494 
495 void Document::crop(int x, int y, int w, int h)
496 {
497  if (!d->document) return;
498  KisImageSP image = d->document->image();
499  if (!image) return;
500  QRect rc(x, y, w, h);
501  image->cropImage(rc);
502  image->waitForDone();
503 }
504 
505 bool Document::exportImage(const QString &filename, const InfoObject &exportConfiguration)
506 {
507  if (!d->document) return false;
508 
509  const QString outputFormatString = KisMimeDatabase::mimeTypeForFile(filename, false);
510  const QByteArray outputFormat = outputFormatString.toLatin1();
511 
512  return d->document->exportDocumentSync(filename, outputFormat, exportConfiguration.configuration());
513 }
514 
516 {
517  if (!d->document) return;
518  if (!d->document->image()) return;
519  d->document->image()->flatten(0);
520  d->document->image()->waitForDone();
521 }
522 
523 void Document::resizeImage(int x, int y, int w, int h)
524 {
525  if (!d->document) return;
526  KisImageSP image = d->document->image();
527  if (!image) return;
528  QRect rc;
529  rc.setX(x);
530  rc.setY(y);
531  rc.setWidth(w);
532  rc.setHeight(h);
533 
534  image->resizeImage(rc);
535  image->waitForDone();
536 }
537 
538 void Document::scaleImage(int w, int h, int xres, int yres, QString strategy)
539 {
540  if (!d->document) return;
541  KisImageSP image = d->document->image();
542  if (!image) return;
543  QRect rc = image->bounds();
544  rc.setWidth(w);
545  rc.setHeight(h);
546 
547  KisFilterStrategy *actualStrategy = KisFilterStrategyRegistry::instance()->get(strategy);
548  if (!actualStrategy) actualStrategy = KisFilterStrategyRegistry::instance()->get("Bicubic");
549 
550  image->scaleImage(rc.size(), xres/72, yres/72, actualStrategy);
551  image->waitForDone();
552 }
553 
554 void Document::rotateImage(double radians)
555 {
556  if (!d->document) return;
557  KisImageSP image = d->document->image();
558  if (!image) return;
559  image->rotateImage(radians);
560  image->waitForDone();
561 }
562 
563 void Document::shearImage(double angleX, double angleY)
564 {
565  if (!d->document) return;
566  KisImageSP image = d->document->image();
567  if (!image) return;
568  image->shear(angleX, angleY);
569  image->waitForDone();
570 }
571 
573 {
574  if (!d->document) return false;
575  if (d->document->path().isEmpty()) return false;
576 
577  bool retval = d->document->save(true, 0);
578  d->document->waitForSavingToComplete();
579 
580  return retval;
581 }
582 
583 bool Document::saveAs(const QString &filename)
584 {
585  if (!d->document) return false;
586 
587  setFileName(filename);
588  const QString outputFormatString = KisMimeDatabase::mimeTypeForFile(filename, false);
589  const QByteArray outputFormat = outputFormatString.toLatin1();
590  QString oldPath = d->document->path();
591  d->document->setPath(filename);
592  bool retval = d->document->saveAs(filename, outputFormat, true);
593  d->document->waitForSavingToComplete();
594  d->document->setPath(oldPath);
595 
596  return retval;
597 }
598 
599 Node* Document::createNode(const QString &name, const QString &nodeType)
600 {
601  if (!d->document) return 0;
602  if (!d->document->image()) return 0;
603  KisImageSP image = d->document->image();
604 
605  Node *node = 0;
606 
607  if (nodeType.toLower()== "paintlayer") {
608  node = new Node(image, new KisPaintLayer(image, name, OPACITY_OPAQUE_U8));
609  }
610  else if (nodeType.toLower() == "grouplayer") {
611  node = new Node(image, new KisGroupLayer(image, name, OPACITY_OPAQUE_U8));
612  }
613  else if (nodeType.toLower() == "filelayer") {
614  node = new Node(image, new KisFileLayer(image, name, OPACITY_OPAQUE_U8));
615  }
616  else if (nodeType.toLower() == "filterlayer") {
617  node = new Node(image, new KisAdjustmentLayer(image, name, 0, 0));
618  }
619  else if (nodeType.toLower() == "filllayer") {
620  node = new Node(image, new KisGeneratorLayer(image, name, 0, 0));
621  }
622  else if (nodeType.toLower() == "clonelayer") {
623  node = new Node(image, new KisCloneLayer(0, image, name, OPACITY_OPAQUE_U8));
624  }
625  else if (nodeType.toLower() == "vectorlayer") {
626  node = new Node(image, new KisShapeLayer(d->document->shapeController(), image, name, OPACITY_OPAQUE_U8));
627  }
628  else if (nodeType.toLower() == "transparencymask") {
629  node = new Node(image, new KisTransparencyMask(image, name));
630  }
631  else if (nodeType.toLower() == "filtermask") {
632  node = new Node(image, new KisFilterMask(image, name));
633  }
634  else if (nodeType.toLower() == "transformmask") {
635  node = new Node(image, new KisTransformMask(image, name));
636  }
637  else if (nodeType.toLower() == "selectionmask") {
638  node = new Node(image, new KisSelectionMask(image, name));
639  }
640  else if (nodeType.toLower() == "colorizemask") {
641  node = new Node(image, new KisColorizeMask(image, name));
642  }
643 
644  return node;
645 }
646 
648 {
649  if (!d->document) return 0;
650  if (!d->document->image()) return 0;
651  KisImageSP image = d->document->image();
652 
653  return new GroupLayer(image, name);
654 }
655 
656 FileLayer *Document::createFileLayer(const QString &name, const QString fileName, const QString scalingMethod, const QString scalingFilter)
657 {
658  if (!d->document) return 0;
659  if (!d->document->image()) return 0;
660  KisImageSP image = d->document->image();
661 
662  return new FileLayer(image, name, this->fileName(), fileName, scalingMethod, scalingFilter);
663 }
664 
666 {
667  if (!d->document) return 0;
668  if (!d->document->image()) return 0;
669  KisImageSP image = d->document->image();
670 
671  return new FilterLayer(image, name, filter, selection);
672 }
673 
674 FillLayer *Document::createFillLayer(const QString &name, const QString generatorName, InfoObject &configuration, Selection &selection)
675 {
676  if (!d->document) return 0;
677  if (!d->document->image()) return 0;
678  KisImageSP image = d->document->image();
679 
680  KisGeneratorSP generator = KisGeneratorRegistry::instance()->value(generatorName);
681  if (generator) {
682 
683  KisFilterConfigurationSP config = generator->factoryConfiguration(KisGlobalResourcesInterface::instance());
684  Q_FOREACH(const QString property, configuration.properties().keys()) {
685  config->setProperty(property, configuration.property(property));
686  }
687 
688  return new FillLayer(image, name, config, selection);
689  }
690  return 0;
691 }
692 
693 CloneLayer *Document::createCloneLayer(const QString &name, const Node *source)
694 {
695  if (!d->document) return 0;
696  if (!d->document->image()) return 0;
697  KisImageSP image = d->document->image();
698  KisLayerSP layer = qobject_cast<KisLayer*>(source->node().data());
699 
700  return new CloneLayer(image, name, layer);
701 }
702 
704 {
705  if (!d->document) return 0;
706  if (!d->document->image()) return 0;
707  KisImageSP image = d->document->image();
708 
709  return new VectorLayer(d->document->shapeController(), image, name);
710 }
711 
712 FilterMask *Document::createFilterMask(const QString &name, Filter &filter, const Node *selection_source)
713 {
714  if (!d->document)
715  return 0;
716 
717  if (!d->document->image())
718  return 0;
719 
720  if(!selection_source)
721  return 0;
722 
723  KisLayerSP layer = qobject_cast<KisLayer*>(selection_source->node().data());
724  if(layer.isNull())
725  return 0;
726 
727  KisImageSP image = d->document->image();
728  FilterMask* mask = new FilterMask(image, name, filter);
729  qobject_cast<KisMask*>(mask->node().data())->initSelection(layer);
730 
731  return mask;
732 }
733 
735 {
736  if (!d->document)
737  return 0;
738 
739  if (!d->document->image())
740  return 0;
741 
742  KisImageSP image = d->document->image();
743  FilterMask* mask = new FilterMask(image, name, filter);
744  qobject_cast<KisMask*>(mask->node().data())->setSelection(selection.selection());
745 
746  return mask;
747 }
748 
750 {
751  if (!d->document) return 0;
752  if (!d->document->image()) return 0;
753  KisImageSP image = d->document->image();
754 
755  return new SelectionMask(image, name);
756 }
757 
759 {
760  if (!d->document) return 0;
761  if (!d->document->image()) return 0;
762  KisImageSP image = d->document->image();
763 
764  return new TransparencyMask(image, name);
765 }
766 
768 {
769  if (!d->document) return 0;
770  if (!d->document->image()) return 0;
771  KisImageSP image = d->document->image();
772 
773  return new TransformMask(image, name);
774 }
775 
777 {
778  if (!d->document) return 0;
779  if (!d->document->image()) return 0;
780  KisImageSP image = d->document->image();
781 
782  return new ColorizeMask(image, name);
783 }
784 
785 QImage Document::projection(int x, int y, int w, int h) const
786 {
787  if (!d->document || !d->document->image()) return QImage();
788  return d->document->image()->convertToQImage(x, y, w, h, 0);
789 }
790 
791 QImage Document::thumbnail(int w, int h) const
792 {
793  if (!d->document || !d->document->image()) return QImage();
794  return d->document->generatePreview(QSize(w, h)).toImage();
795 }
796 
797 
799 {
800  if (!d->document || !d->document->image()) return;
801  d->document->image()->barrierLock();
802 }
803 
805 {
806  if (!d->document || !d->document->image()) return;
807  d->document->image()->unlock();
808 }
809 
811 {
812  if (!d->document || !d->document->image()) return;
813  d->document->image()->waitForDone();
814 }
815 
817 {
818  if (!d->document || !d->document->image()) return false;
819  return d->document->image()->tryBarrierLock();
820 }
821 
823 {
824  if (!d->document || !d->document->image()) return;
825  d->document->image()->refreshGraph();
826 }
827 
829 {
830  QList<qreal> lines;
831  if (!d->document || !d->document->image()) return lines;
832  KisCoordinatesConverter converter;
833  converter.setImage(d->document->image());
834  QTransform transform = converter.imageToDocumentTransform().inverted();
835  QList<qreal> untransformedLines = d->document->guidesConfig().horizontalGuideLines();
836  for (int i = 0; i< untransformedLines.size(); i++) {
837  qreal line = untransformedLines[i];
838  lines.append(transform.map(QPointF(line, line)).x());
839  }
840  return lines;
841 }
842 
844 {
845  QList<qreal> lines;
846  if (!d->document || !d->document->image()) return lines;
847  KisCoordinatesConverter converter;
848  converter.setImage(d->document->image());
849  QTransform transform = converter.imageToDocumentTransform().inverted();
850  QList<qreal> untransformedLines = d->document->guidesConfig().verticalGuideLines();
851  for (int i = 0; i< untransformedLines.size(); i++) {
852  qreal line = untransformedLines[i];
853  lines.append(transform.map(QPointF(line, line)).y());
854  }
855  return lines;
856 }
857 
859 {
860  return d->document->guidesConfig().showGuides();
861 }
862 
864 {
865  return d->document->guidesConfig().lockGuides();
866 }
867 
869 {
870  if (!d->document) return 0;
871  QPointer<KisDocument> clone = d->document->clone();
872 
873  /// We set ownsDocument to true, it will be reset
874  /// automatically as soon as we create the first
875  /// view for the document
876  Document * newDocument = new Document(clone, true);
877  return newDocument;
878 }
879 
881 {
882  if (!d->document) return;
883  KisGuidesConfig config = d->document->guidesConfig();
884  KisCoordinatesConverter converter;
885  converter.setImage(d->document->image());
886  QTransform transform = converter.imageToDocumentTransform();
887  QList<qreal> transformedLines;
888  for (int i = 0; i< lines.size(); i++) {
889  qreal line = lines[i];
890  transformedLines.append(transform.map(QPointF(line, line)).x());
891  }
892  config.setHorizontalGuideLines(transformedLines);
893  d->document->setGuidesConfig(config);
894 }
895 
897 {
898  if (!d->document) return;
899  KisGuidesConfig config = d->document->guidesConfig();
900  KisCoordinatesConverter converter;
901  converter.setImage(d->document->image());
902  QTransform transform = converter.imageToDocumentTransform();
903  QList<qreal> transformedLines;
904  for (int i = 0; i< lines.size(); i++) {
905  qreal line = lines[i];
906  transformedLines.append(transform.map(QPointF(line, line)).y());
907  }
908  config.setVerticalGuideLines(transformedLines);
909  d->document->setGuidesConfig(config);
910 }
911 
912 void Document::setGuidesVisible(bool visible)
913 {
914  if (!d->document) return;
915  KisGuidesConfig config = d->document->guidesConfig();
916  config.setShowGuides(visible);
917  d->document->setGuidesConfig(config);
918 }
919 
920 void Document::setGuidesLocked(bool locked)
921 {
922  if (!d->document) return;
923  KisGuidesConfig config = d->document->guidesConfig();
924  config.setLockGuides(locked);
925  d->document->setGuidesConfig(config);
926 }
927 
928 bool Document::modified() const
929 {
930  if (!d->document) return false;
931  return d->document->isModified();
932 }
933 
934 void Document::setModified(bool modified)
935 {
936  if (!d->document) return;
937  d->document->setModified(modified);
938 }
939 
941 {
942  if (!d->document) return QRect();
943  return d->document->image()->bounds();
944 }
945 
946 QPointer<KisDocument> Document::document() const
947 {
948  return d->document;
949 }
950 
951 void Document::setOwnsDocument(bool ownsDocument)
952 {
953  d->ownsDocument = ownsDocument;
954 }
955 
956 /* Animation related function */
957 
958 bool Document::importAnimation(const QList<QString> &files, int firstFrame, int step)
959 {
960  KisView *activeView = KisPart::instance()->currentMainwindow()->activeView();
961 
962  KoUpdaterPtr updater = 0;
963  if (activeView && d->document->fileBatchMode()) {
964  updater = activeView->viewManager()->createUnthreadedUpdater(i18n("Import frames"));
965  }
966 
967  KisAnimationImporter importer(d->document->image(), updater);
968  KisImportExportErrorCode status = importer.import(files, firstFrame, step);
969 
970  return status.isOk();
971 }
972 
974 {
975  if (!d->document) return false;
976  if (!d->document->image()) return false;
977 
978  return d->document->image()->animationInterface()->framerate();
979 }
980 
982 {
983  if (!d->document) return;
984  if (!d->document->image()) return;
985 
986  d->document->image()->animationInterface()->setFramerate(fps);
987 }
988 
990 {
991  if (!d->document) return;
992  if (!d->document->image()) return;
993 
994  d->document->image()->animationInterface()->setDocumentRangeStartFrame(startTime);
995 }
996 
997 
999 {
1000  if (!d->document) return false;
1001  if (!d->document->image()) return false;
1002 
1003  return d->document->image()->animationInterface()->documentPlaybackRange().start();
1004 }
1005 
1006 
1008 {
1009  if (!d->document) return;
1010  if (!d->document->image()) return;
1011 
1012  d->document->image()->animationInterface()->setDocumentRangeEndFrame(endTime);
1013 }
1014 
1015 
1017 {
1018  if (!d->document) return false;
1019  if (!d->document->image()) return false;
1020 
1021  return d->document->image()->animationInterface()->documentPlaybackRange().end();
1022 }
1023 
1025 {
1026  if (!d->document) return false;
1027  if (!d->document->image()) return false;
1028 
1029  return d->document->image()->animationInterface()->totalLength();
1030 }
1031 
1033 {
1034  if (!d->document) return;
1035  if (!d->document->image()) return;
1036 
1037  const KisTimeSpan newTimeRange = KisTimeSpan::fromTimeWithDuration(start, (stop-start));
1038  d->document->image()->animationInterface()->setActivePlaybackRange(newTimeRange);
1039 }
1040 
1042 {
1043  if (!d->document) return false;
1044  if (!d->document->image()) return false;
1045 
1046  return d->document->image()->animationInterface()->activePlaybackRange().start();
1047 }
1048 
1050 {
1051  if (!d->document) return false;
1052  if (!d->document->image()) return false;
1053 
1054  return d->document->image()->animationInterface()->activePlaybackRange().end();
1055 }
1056 
1058 {
1059  if (!d->document) return false;
1060  if (!d->document->image()) return false;
1061 
1062  return d->document->image()->animationInterface()->currentTime();
1063 }
1064 
1066 {
1067  if (!d->document) return;
1068  if (!d->document->image()) return;
1069 
1070  return d->document->image()->animationInterface()->requestTimeSwitchWithUndo(time);
1071 }
1072 
1074 {
1075  if (!d->document) return QStringList();
1076 
1077  QStringList types;
1078 
1079  KisImageSP image = d->document->image().toStrongRef();
1080 
1081  if (!image) return QStringList();
1082 
1083  vKisAnnotationSP_it beginIt = image->beginAnnotations();
1084  vKisAnnotationSP_it endIt = image->endAnnotations();
1085 
1086  vKisAnnotationSP_it it = beginIt;
1087  while (it != endIt) {
1088  if (!(*it) || (*it)->type().isEmpty()) {
1089  qWarning() << "Warning: empty annotation";
1090  it++;
1091  continue;
1092  }
1093  types << (*it)->type();
1094 
1095  it++;
1096  }
1097  return types;
1098 }
1099 
1101 {
1102  KisImageSP image = d->document->image().toStrongRef();
1103  KisAnnotationSP annotation = image->annotation(type);
1104  return annotation->description();
1105 }
1106 
1108 {
1109  KisImageSP image = d->document->image().toStrongRef();
1110  KisAnnotationSP annotation = image->annotation(type);
1111  if (annotation) {
1112  return annotation->annotation();
1113  }
1114  else {
1115  return QByteArray();
1116  }
1117 }
1118 
1119 void Document::setAnnotation(const QString &key, const QString &description, const QByteArray &annotation)
1120 {
1121  KisAnnotation *a = new KisAnnotation(key, description, annotation);
1122  KisImageSP image = d->document->image().toStrongRef();
1123  image->addAnnotation(a);
1124 
1125 }
1126 
1128 {
1129  KisImageSP image = d->document->image().toStrongRef();
1130  image->removeAnnotation(type);
1131 }
void append(const T &value)
T & first()
int fullClipRangeEndTime()
get the full clip range end time
Definition: Document.cpp:1016
QString toString(int indent) const const
QByteArray annotation(const QString &type)
annotation the actual data for the annotation for this type.
Definition: Document.cpp:1107
QList< qreal > verticalGuides() const
verticalGuides The vertical guide lines.
Definition: Document.cpp:843
void setWidth(int width)
int playBackEndTime()
get end time of current playback
Definition: Document.cpp:1049
void unlock()
Unlocks the image and starts/resumes all the pending internal jobs.
Definition: Document.cpp:804
void rotateImage(double radians)
rotateImage Rotate the image by the given radians.
Definition: Document.cpp:554
QRect bounds() const
bounds return the bounds of the image
Definition: Document.cpp:940
void setFullClipRangeStartTime(int startTime)
set start time of animation
Definition: Document.cpp:989
InfoObject wrap a properties map.
Definition: InfoObject.h:19
int height() const
Definition: Document.cpp:275
void setYOffset(int y)
setYOffset sets the top edge of the canvas to y.
Definition: Document.cpp:406
QSize size() const const
bool save()
save the image to its currently set path.
Definition: Document.cpp:572
bool batchmode() const
Batchmode means that no actions on the document should show dialogs or popups.
Definition: Document.cpp:101
bool setColorProfile(const QString &colorProfile)
setColorProfile set the color profile of the image to the given profile.
Definition: Document.cpp:194
void stop(Ekos::AlignState mode)
bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile)
setColorSpace convert the nodes and the image to the given colorspace.
Definition: Document.cpp:205
int playBackStartTime()
get start time of current playback
Definition: Document.cpp:1041
Node * nodeByUniqueID(const QUuid &id) const
nodeByUniqueID searches the node tree for a node with the given name and returns it.
Definition: Document.cpp:165
FilterMask * createFilterMask(const QString &name, Filter &filter, Selection &selection)
createFilterMask Creates a filter mask object that much like a filterlayer can apply a filter non-des...
Definition: Document.cpp:734
void scaleImage(int w, int h, int xres, int yres, QString strategy)
scaleImage
Definition: Document.cpp:538
FilterLayer * createFilterLayer(const QString &name, Filter &filter, Selection &selection)
createFilterLayer creates a filter layer, which is a layer that represents a filter applied non-destr...
Definition: Document.cpp:665
The ColorizeMask class A colorize mask is a mask type node that can be used to color in line art.
Definition: ColorizeMask.h:59
void setVerticalGuides(const QList< qreal > &lines)
setVerticalGuides replace all existing horizontal guides with the entries in the list.
Definition: Document.cpp:896
FileLayer * createFileLayer(const QString &name, const QString fileName, const QString scalingMethod, const QString scalingFilter="Bicubic")
createFileLayer returns a layer that shows an external image.
Definition: Document.cpp:656
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QByteArray toLatin1() const const
QList< Node * > childNodes() const
childNodes
Definition: Node.cpp:205
VectorLayer * createVectorLayer(const QString &name)
createVectorLayer Creates a vector layer that can contain vector shapes.
Definition: Document.cpp:703
The GroupLayer class A group layer is a layer that can contain other layers.
Definition: GroupLayer.h:29
Node * activeNode() const
activeNode retrieve the node that is currently active in the currently active window
Definition: Document.cpp:113
QByteArray pixelData(int x, int y, int w, int h) const
pixelData reads the given rectangle from the image projection and returns it as a byte array.
Definition: Document.cpp:458
The Document class encapsulates a Krita Document/Image.
Definition: Document.h:33
QList< qreal > horizontalGuides() const
horizontalGuides The horizontal guides.
Definition: Document.cpp:828
TransformMask * createTransformMask(const QString &name)
createTransformMask Creates a transform mask, which can be used to apply a transformation non-destruc...
Definition: Document.cpp:767
int resolution() const
Definition: Document.cpp:307
SelectionMask * createSelectionMask(const QString &name)
createSelectionMask Creates a selection mask, which can be used to store selections.
Definition: Document.cpp:749
QVariant property(const QString &key)
return the value for the property identified by key, or None if there is no such key.
Definition: InfoObject.cpp:72
GroupLayer * createGroupLayer(const QString &name)
createGroupLayer Returns a grouplayer object.
Definition: Document.cpp:647
Selection represents a selection on Krita.
Definition: Selection.h:30
The TransformMask class A transform mask is a mask type node that can be used to store transformation...
Definition: TransformMask.h:22
QColor backgroundColor()
backgroundColor returns the current background color of the document.
Definition: Document.cpp:220
void flatten()
flatten all layers in the image
Definition: Document.cpp:515
int fullClipRangeStartTime()
get the full clip range start time
Definition: Document.cpp:998
The SelectionMask class A selection mask is a mask type node that can be used to store selections.
Definition: SelectionMask.h:26
int size() const const
void crop(int x, int y, int w, int h)
crop the image to rectangle described by x, y, w and h
Definition: Document.cpp:495
Q_SCRIPTABLE Q_NOREPLY void start()
int currentTime()
get current frame selected of animation
Definition: Document.cpp:1057
QString i18n(const char *text, const TYPE &arg...)
void setXRes(double xRes) const
setXRes set the horizontal resolution of the image to xRes in pixels per inch
Definition: Document.cpp:424
void shearImage(double angleX, double angleY)
shearImage shear the whole image.
Definition: Document.cpp:563
void setGuidesVisible(bool visible)
setGuidesVisible set guides visible on this document.
Definition: Document.cpp:912
The CloneLayer class A clone layer is a layer that takes a reference inside the image and shows the e...
Definition: CloneLayer.h:25
void refreshProjection()
Starts a synchronous recomposition of the projection: everything will wait until the image is fully r...
Definition: Document.cpp:822
void setHeight(int height)
int framesPerSecond()
frames per second of document
Definition: Document.cpp:973
Filter: represents a filter and its configuration.
Definition: Filter.h:30
bool guidesLocked() const
guidesLocked Returns guide lockedness.
Definition: Document.cpp:863
QString name() const
Definition: Document.cpp:294
void setDocumentInfo(const QString &document)
setDocumentInfo set the Document information to the information contained in document
Definition: Document.cpp:251
bool saveAs(const QString &filename)
saveAs save the document under the filename.
Definition: Document.cpp:583
bool importAnimation(const QList< QString > &files, int firstFrame, int step)
Import an image sequence of files from a directory.
Definition: Document.cpp:958
void removeAnnotation(const QString &type)
removeAnnotation remove the specified annotation from the image
Definition: Document.cpp:1127
The TransparencyMask class A transparency mask is a mask type node that can be used to show and hide ...
Q_SCRIPTABLE CaptureState status()
QString colorDepth() const
colorDepth A string describing the color depth of the image:
Definition: Document.cpp:176
void setWidth(int value)
setWidth resize the document to
Definition: Document.cpp:368
QString fileName() const
Definition: Document.cpp:261
The FillLayer class A fill layer is much like a filter layer in that it takes a name and filter.
Definition: FillLayer.h:24
void setAnnotation(const QString &type, const QString &description, const QByteArray &annotation)
setAnnotation Add the given annotation to the document
Definition: Document.cpp:1119
void setSelection(Selection *value)
setSelection set or replace the global selection
Definition: Document.cpp:347
QString annotationDescription(const QString &type) const
annotationDescription gets the pretty description for the current annotation
Definition: Document.cpp:1100
The FileLayer class A file layer is a layer that can reference an external image and show said refere...
Definition: FileLayer.h:26
void setXOffset(int x)
setXOffset sets the left edge of the canvas to x.
Definition: Document.cpp:387
void setActiveNode(Node *value)
setActiveNode make the given node active in the currently active view and window
Definition: Document.cpp:130
Selection * selection() const
selection Create a Selection object around the global selection, if there is one.
Definition: Document.cpp:339
KSharedConfigPtr config()
TransparencyMask * createTransparencyMask(const QString &name)
createTransparencyMask Creates a transparency mask, which can be used to assign transparency to regio...
Definition: Document.cpp:758
QString colorModel() const
colorModel retrieve the current color model of this document:
Definition: Document.cpp:182
int width() const
Definition: Document.cpp:360
QImage thumbnail(int w, int h) const
thumbnail create a thumbnail of the given dimensions.
Definition: Document.cpp:791
void setGuidesLocked(bool locked)
setGuidesLocked set guides locked on this document
Definition: Document.cpp:920
void setHorizontalGuides(const QList< qreal > &lines)
setHorizontalGuides replace all existing horizontal guides with the entries in the list.
Definition: Document.cpp:880
double yRes() const
Definition: Document.cpp:437
QString toLower() const const
int xOffset() const
Definition: Document.cpp:379
bool modified() const
modified returns true if the document has unsaved modifications.
Definition: Document.cpp:928
Node represents a layer or mask in a Krita image's Node hierarchy.
Definition: Node.h:21
void resize(int size)
Node * rootNode() const
rootNode the root node is the invisible group layer that contains the entire node hierarchy.
Definition: Document.cpp:330
void setFileName(QString value)
setFileName set the full path of the document to
Definition: Document.cpp:267
QMap< QString, QVariant > properties() const
Return all properties this InfoObject manages.
Definition: InfoObject.cpp:45
Node * nodeByName(const QString &name) const
nodeByName searches the node tree for a node with the given name and returns it
Definition: Document.cpp:155
int yOffset() const
Definition: Document.cpp:398
QList< Node * > topLevelNodes() const
toplevelNodes return a list with all top level nodes in the image graph
Definition: Document.cpp:147
void setModified(bool modified)
setModified sets the modified status of the document
Definition: Document.cpp:934
bool exportImage(const QString &filename, const InfoObject &exportConfiguration)
exportImage export the image, without changing its URL to the given path.
Definition: Document.cpp:505
void setResolution(int value)
setResolution set the resolution of the image; this does not scale the image
Definition: Document.cpp:316
double xRes() const
Definition: Document.cpp:417
The VectorLayer class A vector layer is a special layer that stores and shows vector shapes.
Definition: VectorLayer.h:31
void setX(int x)
void setY(int y)
void setFramesPerSecond(int fps)
set frames per second of document
Definition: Document.cpp:981
bool tryBarrierLock()
Tries to lock the image without waiting for the jobs to finish.
Definition: Document.cpp:816
QString documentInfo() const
documentInfo creates and XML document representing document and author information.
Definition: Document.cpp:243
QString colorProfile() const
Definition: Document.cpp:188
void resizeImage(int x, int y, int w, int h)
resizeImage resizes the canvas to the given left edge, top edge, width and height.
Definition: Document.cpp:523
void setCurrentTime(int time)
set current time of document's animation
Definition: Document.cpp:1065
int animationLength()
get total frame range for animation
Definition: Document.cpp:1024
void setBatchmode(bool value)
Set batchmode to value.
Definition: Document.cpp:107
void setPlayBackRange(int start, int stop)
set temporary playback range of document
Definition: Document.cpp:1032
void setFullClipRangeEndTime(int endTime)
set full clip range end time
Definition: Document.cpp:1007
bool guidesVisible() const
guidesVisible Returns guide visibility.
Definition: Document.cpp:858
void waitForDone()
Wait for all the internal image jobs to complete and return without locking the image.
Definition: Document.cpp:810
CloneLayer * createCloneLayer(const QString &name, const Node *source)
createCloneLayer
Definition: Document.cpp:693
The FilterMask class A filter mask, unlike a filter layer, will add a non-destructive filter to the c...
Definition: FilterMask.h:28
FillLayer * createFillLayer(const QString &name, const QString generatorName, InfoObject &configuration, Selection &selection)
createFillLayer creates a fill layer object, which is a layer
Definition: Document.cpp:674
void setHeight(int value)
setHeight resize the document to
Definition: Document.cpp:283
void lock()
[low-level] Lock the image without waiting for all the internal job queues are processed
Definition: Document.cpp:798
void setYRes(double yRes) const
setYRes set the vertical resolution of the image to yRes in pixels per inch
Definition: Document.cpp:444
Node * createNode(const QString &name, const QString &nodeType)
Definition: Document.cpp:599
QImage projection(int x=0, int y=0, int w=0, int h=0) const
projection creates a QImage from the rendered image or a cutout rectangle.
Definition: Document.cpp:785
Document * clone() const
clone create a shallow clone of this document.
Definition: Document.cpp:868
ColorizeMask * createColorizeMask(const QString &name)
createColorizeMask Creates a colorize mask, which can be used to color fill via keystrokes.
Definition: Document.cpp:776
void setName(QString value)
setName sets the name of the document to value.
Definition: Document.cpp:300
char * data()
bool setBackgroundColor(const QColor &color)
setBackgroundColor sets the background color of the document.
Definition: Document.cpp:229
bool close()
close Close the document: remove it from Krita's internal list of documents and close all views.
Definition: Document.cpp:472
The FilterLayer class A filter layer will, when compositing, take the composited image up to the poin...
Definition: FilterLayer.h:33
QVariant property(const char *name) const const
QStringList annotationTypes() const
annotationTypes returns the list of annotations present in the document.
Definition: Document.cpp:1073
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Fri Sep 22 2023 04:09:51 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.