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

KDE's Doxygen guidelines are available online.