Krita Source Code Documentation
Loading...
Searching...
No Matches
KisView.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2014 Boudewijn Rempt <boud@valdyas.org>
3 * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy@amyspark.me>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8#include "KisView.h"
9
10#include "KisView_p.h"
11
12#include <KoDockFactoryBase.h>
13#include <KoDockRegistry.h>
14#include <KoDocumentInfo.h>
15#include <KoToolManager.h>
16
17#include <kis_icon.h>
18
19#include <kactioncollection.h>
20#include <klocalizedstring.h>
21#include <kis_debug.h>
22#include <kselectaction.h>
23#include <kconfiggroup.h>
24
25#include <QMessageBox>
26#include <QUrl>
27#include <QTemporaryFile>
28#include <QApplication>
29#include <QScreen>
30#include <QDragEnterEvent>
31#include <QDropEvent>
32#include <QList>
33#include <QPrintDialog>
34#include <QToolBar>
35#include <QStatusBar>
36#include <QMoveEvent>
37#include <QMdiSubWindow>
38#include <QFileInfo>
39#include <QScreen>
40
41#include <kis_image.h>
42#include <kis_node.h>
43
44#include <kis_group_layer.h>
45#include <kis_layer.h>
46#include <kis_mask.h>
47#include <kis_selection.h>
48
49#include "KisDocument.h"
51#include "KisMainWindow.h"
52#include "KisMimeDatabase.h"
53#include "KisPart.h"
57#include "KisViewManager.h"
59#include "kis_canvas2.h"
62#include "kis_clipboard.h"
63#include "kis_config.h"
64#include "kis_file_layer.h"
65#include "kis_fill_painter.h"
66#include "kis_filter_manager.h"
67#include "kis_image_manager.h"
68#include "kis_import_catcher.h"
69#include "kis_mimedata.h"
71#include "kis_node_manager.h"
72#include "kis_paint_layer.h"
78#include "kis_zoom_manager.h"
79#include "krita_utils.h"
86#include <kis_command_utils.h>
89#include "kformat.h"
90
91
92//static
94{
95 static int s_viewIFNumber = 0;
96 QString name; name.setNum(s_viewIFNumber++); name.prepend("view_");
97 return name;
98}
99
100bool KisView::s_firstView = true;
101
102class Q_DECL_HIDDEN KisView::Private
103{
104public:
106 KisDocument *document,
107 KisViewManager *viewManager)
108 : actionCollection(viewManager->actionCollection())
109 , viewConverter()
110 , canvasController(_q, viewManager->mainWindow(), viewManager->actionCollection())
111 , canvas(&viewConverter, viewManager->canvasResourceProvider()->resourceManager(), viewManager->mainWindow(), _q, document->shapeController())
112 , zoomManager(_q, &this->viewConverter, &this->canvasController)
113 , viewManager(viewManager)
114 , floatingMessageCompressor(100, KisSignalCompressor::POSTPONE)
115 , screenMigrationTracker(_q)
116 {
117 }
118
119 bool inOperation {false}; //in the middle of an operation (no screen refreshing)?
120
121 QPointer<KisDocument> document; // our KisDocument
122 QWidget *tempActiveWidget {nullptr};
123
124 KisKActionCollection* actionCollection {nullptr};
129 KisViewManager *viewManager {nullptr};
133 bool isCurrent {false};
134 bool showFloatingMessage {true};
137 QMdiSubWindow *subWindow {nullptr};
138
139 bool softProofing {false};
140 bool gamutCheck {false};
141
144
146
147 // Hmm sorry for polluting the private class with such a big inner class.
148 // At the beginning it was a little struct :)
149 class StatusBarItem : public boost::equality_comparable<StatusBarItem>
150 {
151 public:
152
153 StatusBarItem(QWidget * widget, int stretch, bool permanent)
154 : m_widget(widget),
155 m_stretch(stretch),
156 m_permanent(permanent),
157 m_connected(false),
158 m_hidden(false) {}
159
160 bool operator==(const StatusBarItem& rhs) {
161 return m_widget == rhs.m_widget;
162 }
163
164 QWidget * widget() const {
165 return m_widget;
166 }
167
168 void ensureItemShown(QStatusBar * sb) {
169 Q_ASSERT(m_widget);
170 if (!m_connected) {
171 if (m_permanent)
172 sb->addPermanentWidget(m_widget, m_stretch);
173 else
174 sb->addWidget(m_widget, m_stretch);
175
176 if(!m_hidden)
177 m_widget->show();
178
179 m_connected = true;
180 }
181 }
182 void ensureItemHidden(QStatusBar * sb) {
183 if (m_connected) {
184 m_hidden = m_widget->isHidden();
185 sb->removeWidget(m_widget);
186 m_widget->hide();
187 m_connected = false;
188 }
189 }
190
191 private:
192 QWidget * m_widget = 0;
195 bool m_connected = false;
196 bool m_hidden = false;
197
198 };
199
200};
201
202KisView::KisView(KisDocument *document, KisViewManager *viewManager, QWidget *parent)
203 : QWidget(parent)
204 , d(new Private(this, document, viewManager))
205{
206 Q_ASSERT(document);
207 setObjectName(newObjectName());
208
209 d->document = document;
210
211 setFocusPolicy(Qt::StrongFocus);
212
213 QStatusBar * sb = statusBar();
214 if (sb) { // No statusbar in e.g. konqueror
215 connect(d->document, SIGNAL(statusBarMessage(QString,int)),
216 this, SLOT(slotSavingStatusMessage(QString,int)));
217 connect(d->document, SIGNAL(clearStatusBarMessage()),
218 this, SLOT(slotClearStatusText()));
219 }
220
221 d->canvas.setup();
222
223 KisConfig cfg(false);
224
225 d->canvasController.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
226 d->canvasController.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
227 d->canvasController.setCanvas(&d->canvas);
228
229 d->zoomManager.setup(d->actionCollection);
230
231 setAcceptDrops(true);
232
233 connect(d->document, SIGNAL(sigLoadingFinished()), this, SLOT(slotLoadingFinished()));
234
235 d->referenceImagesDecoration = new KisReferenceImagesDecoration(this, document, /* viewReady = */ false);
236 d->canvas.addDecoration(d->referenceImagesDecoration);
237 d->referenceImagesDecoration->setVisible(true);
238
239 d->paintingAssistantsDecoration = new KisPaintingAssistantsDecoration(this);
240 d->canvas.addDecoration(d->paintingAssistantsDecoration);
241 d->paintingAssistantsDecoration->setVisible(true);
242
243 d->showFloatingMessage = cfg.showCanvasMessages();
245
246 connect(document, SIGNAL(sigReadWriteChanged(bool)), this, SLOT(slotUpdateDocumentTitle()));
247 connect(document, SIGNAL(sigRecoveredChanged(bool)), this, SLOT(slotUpdateDocumentTitle()));
248 connect(document, SIGNAL(sigPathChanged(QString)), this, SLOT(slotUpdateDocumentTitle()));
250 SIGNAL(sigUpdateMemoryStatistics()),
252 connect(document, SIGNAL(modified(bool)), this, SLOT(setWindowModified(bool)));
254 setWindowModified(document->isModified());
255}
256
258{
259 if (d->viewManager) {
260 if (d->viewManager->filterManager()->isStrokeRunning()) {
261 d->viewManager->filterManager()->cancelDialog();
262 }
263
264 d->viewManager->mainWindow()->notifyChildViewDestroyed(this);
265 }
266
268
274
275 KoToolManager::instance()->removeCanvasController(&d->canvasController);
276 d->canvasController.setCanvas(0);
277
279 delete d;
280}
281
283{
284 d->isCurrent = isCurrent;
285
286 if (!d->isCurrent && d->savedFloatingMessage) {
287 d->savedFloatingMessage->removeMessage();
288 }
289
290 KisInputManager *inputManager = globalInputManager();
291 if (d->isCurrent) {
292 inputManager->attachPriorityEventFilter(&d->canvasController);
293 } else {
294 inputManager->detachPriorityEventFilter(&d->canvasController);
295 }
296
302}
303
304bool KisView::isCurrent() const
305{
306 return d->isCurrent;
307}
308
310{
311 d->showFloatingMessage = show;
312}
313
314void KisView::showFloatingMessage(const QString &message, const QIcon& icon, int timeout, KisFloatingMessage::Priority priority, int alignment)
315{
316 if (!d->viewManager) return;
317
318 if(d->isCurrent && d->showFloatingMessage && d->viewManager->qtMainWindow()) {
319 if (d->savedFloatingMessage) {
320 d->savedFloatingMessage->tryOverrideMessage(message, icon, timeout, priority, alignment);
321 } else {
322 d->savedFloatingMessage = new KisFloatingMessage(message, this->canvasBase()->canvasWidget(), false, timeout, priority, alignment);
323 d->savedFloatingMessage->setShowOverParent(true);
324 d->savedFloatingMessage->setIcon(icon);
325
326 connect(&d->floatingMessageCompressor, SIGNAL(timeout()), d->savedFloatingMessage, SLOT(showMessage()));
327 d->floatingMessageCompressor.start();
328 }
329 }
330}
331
333{
334 return d->canvas.xAxisMirrored() || d->canvas.yAxisMirrored();
335}
336
338{
339 d->viewManager = view;
340
341 KoToolManager::instance()->addController(&d->canvasController);
342 KisShapeController* shapeController = dynamic_cast<KisShapeController*>(d->document->shapeController());
343 shapeController->setInitialShapeForCanvas(&d->canvas);
344
345 if (d->viewManager && d->viewManager->nodeManager()) {
346 d->viewManager->nodeManager()->nodesUpdated();
347 }
348
349 connect(image(), SIGNAL(sigSizeChanged(QPointF,QPointF)), this, SLOT(slotImageSizeChanged(QPointF,QPointF)));
350 connect(image(), SIGNAL(sigResolutionChanged(double,double)), this, SLOT(slotImageResolutionChanged()));
351
352 d->addNodeConnection.connectSync(image(), &KisImage::sigNodeAddedAsync,
354
355 // executed in a context of an image thread
356 connect(image(), SIGNAL(sigRemoveNodeAsync(KisNodeSP)),
358 Qt::DirectConnection);
359
360 d->removeNodeConnection.connectOutputSlot(this, &KisView::slotContinueRemoveNode);
361
362 d->viewManager->updateGUI();
363
364 KoToolManager::instance()->switchToolRequested("KritaShape/KisToolBrush");
365}
366
368{
369 return d->viewManager;
370}
371
372void KisView::slotContinueAddNode(KisNodeSP newActiveNode, KisNodeAdditionFlags flags)
373{
374 Q_UNUSED(flags)
375
376
384 if (!d->isCurrent &&
385 (!d->currentNode || !d->currentNode->parent())) {
386
387 d->currentNode = newActiveNode;
388 }
389}
390
391
393{
394 d->removeNodeConnection.start(KritaUtils::nearestNodeAfterRemoval(node));
395}
396
398{
399 if (!d->isCurrent) {
400 d->currentNode = newActiveNode;
401 }
402}
403
405{
406 return &d->zoomManager;
407}
408
410{
411 return &d->canvasController;
412}
413
415{
416 if (d->viewManager) {
417 return d->viewManager->canvasResourceProvider();
418 }
419 return 0;
420}
421
423{
424 return d->viewManager ? d->viewManager->inputManager() : 0;
425}
426
428{
429 return &d->canvas;
430}
431
433{
434 if (d->document) {
435 return d->document->image();
436 }
437 return 0;
438}
439
440
442{
443 return &d->viewConverter;
444}
445
446void KisView::dragEnterEvent(QDragEnterEvent *event)
447{
448 dbgUI << Q_FUNC_INFO
449 << "Formats: " << event->mimeData()->formats()
450 << "Urls: " << event->mimeData()->urls()
451 << "Has images: " << event->mimeData()->hasImage();
452 if (event->mimeData()->hasImage()
453 || event->mimeData()->hasUrls()
454 || event->mimeData()->hasFormat("application/x-krita-node-internal-pointer")
455 || event->mimeData()->hasFormat("krita/x-colorsetentry")
456 || event->mimeData()->hasColor()) {
457 event->accept();
458
459 // activate view if it should accept the drop
460 this->setFocus();
461 } else {
462 event->ignore();
463 }
464}
465
466void KisView::dropEvent(QDropEvent *event)
467{
468 KisImageWSP kisimage = image();
469 Q_ASSERT(kisimage);
470
471 QPoint imgCursorPos = canvasBase()->coordinatesConverter()->widgetToImage(event->pos()).toPoint();
472 QRect imageBounds = kisimage->bounds();
473 boost::optional<QPoint> forcedCenter;
474
475 if (event->keyboardModifiers() & Qt::ShiftModifier && imageBounds.contains(imgCursorPos)) {
476 forcedCenter = imgCursorPos;
477 }
478
479 dbgUI << Q_FUNC_INFO;
480 dbgUI << "\t Formats: " << event->mimeData()->formats();
481 dbgUI << "\t Urls: " << event->mimeData()->urls();
482 dbgUI << "\t Has images: " << event->mimeData()->hasImage();
483
484 if (event->mimeData()->hasFormat("application/x-krita-node-internal-pointer")) {
485 KisShapeController *kritaShapeController =
486 dynamic_cast<KisShapeController*>(d->document->shapeController());
487
488 bool copyNode = true;
489 QList<KisNodeSP> nodes;
490
491 if (forcedCenter) {
492 nodes = KisMimeData::loadNodesFastAndRecenter(*forcedCenter, event->mimeData(), kisimage, kritaShapeController, copyNode);
493 } else {
494 nodes = KisMimeData::loadNodesFast(event->mimeData(), kisimage, kritaShapeController, copyNode);
495 }
496
497 Q_FOREACH (KisNodeSP node, nodes) {
498 if (node) {
500 if (!viewManager()->nodeManager()->activeLayer()) {
501 adapter.addNode(node, kisimage->rootLayer() , 0);
502 } else {
503 adapter.addNode(node,
504 viewManager()->nodeManager()->activeLayer()->parent(),
505 viewManager()->nodeManager()->activeLayer());
506 }
507 }
508 }
509 } else if (event->mimeData()->hasImage() || event->mimeData()->hasUrls()) {
510 const auto *data = event->mimeData();
511
512 KisCanvasDrop dlgAction;
513
514 const auto callPos = QCursor::pos();
515
516 const KisCanvasDrop::Action action = dlgAction.dropAs(*data, callPos);
517
519 const QPair<bool, KisClipboard::PasteFormatBehaviour> source =
521
522 if (!source.first) {
523 dbgUI << "Paste event cancelled";
524 return;
525 }
526
528 const QList<QUrl> &urls = data->urls();
529 const auto url = std::find_if(
530 urls.constBegin(),
531 urls.constEnd(),
532 [&](const QUrl &url) {
533 if (source.second
534 == KisClipboard::PASTE_FORMAT_DOWNLOAD) {
535 return !url.isLocalFile();
536 } else if (source.second
538 return url.isLocalFile();
539 } else {
540 return false;
541 }
542 });
543
544 if (url != urls.constEnd()) {
545 QScopedPointer<QTemporaryFile> tmp(new QTemporaryFile());
546 tmp->setAutoRemove(true);
547
548 const QUrl localUrl = [&]() -> QUrl {
549 if (!url->isLocalFile()) {
550 // download the file and substitute the url
551 KisRemoteFileFetcher fetcher;
552 tmp->setFileName(url->fileName());
553
554 if (!fetcher.fetchFile(*url, tmp.data())) {
555 warnUI << "Fetching" << *url << "failed";
556 return {};
557 }
558 return QUrl::fromLocalFile(tmp->fileName());
559 }
560 return *url;
561 }();
562
563 if (localUrl.isLocalFile()) {
564 this->mainWindow()
565 ->viewManager()
566 ->imageManager()
567 ->importImage(localUrl);
568 this->activateWindow();
569 return;
570 }
571 }
572 }
573
574 KisPaintDeviceSP clip =
576 QRect(),
577 true,
578 -1,
579 false,
580 source);
581 if (clip) {
582 const auto pos = this->viewConverter()
583 ->imageToDocument(imgCursorPos)
584 .toPoint();
585
586 clip->moveTo(pos.x(), pos.y());
587
589 this->image());
590
591 KisPaintLayerSP layer = new KisPaintLayer(
592 this->image(),
593 this->image()->nextLayerName() + " " + i18n("(pasted)"),
595 clip);
597 this->mainWindow()->viewManager());
598 adapter.addNode(
599 layer,
600 this->mainWindow()->viewManager()->activeNode()->parent(),
601 this->mainWindow()->viewManager()->activeNode());
602 this->activateWindow();
603 return;
604 }
605 } else if (action == KisCanvasDrop::INSERT_AS_REFERENCE_IMAGE) {
606 KisPaintDeviceSP clip =
607 KisClipboard::instance()->clipFromMimeData(data, QRect(), true);
608 if (clip) {
610 this->image());
611
612 auto *reference =
614 *this->viewConverter(),
615 this);
616
617 if (reference) {
618 if (data->hasUrls()) {
619 const auto &urls = data->urls();
620 const auto url = std::find_if(urls.constBegin(), urls.constEnd(), std::mem_fn(&QUrl::isLocalFile));
621 if (url != urls.constEnd()) {
622 reference->setFilename((*url).toLocalFile());
623 }
624 }
625 const auto pos = this->canvasBase()
627 ->widgetToImage(event->pos());
628 reference->setPosition(
629 (*this->viewConverter()).imageToDocument(pos));
630 this->canvasBase()
632 ->addReferenceImage(reference);
634 "ToolReferenceImages");
635 return;
636 }
637 }
638 } else if (action != KisCanvasDrop::NONE) {
639 // multiple URLs detected OR about to open a document
640
641 for (QUrl url : data->urls()) { // do copy it
642 QScopedPointer<QTemporaryFile> tmp(new QTemporaryFile());
643 tmp->setAutoRemove(true);
644
645 if (!url.isLocalFile()) {
646 // download the file and substitute the url
647 KisRemoteFileFetcher fetcher;
648 tmp->setFileName(url.fileName());
649
650 if (!fetcher.fetchFile(url, tmp.data())) {
651 qWarning() << "Fetching" << url << "failed";
652 continue;
653 }
654 url = QUrl::fromLocalFile(tmp->fileName());
655 }
656
657 if (url.isLocalFile()) {
658 if (action == KisCanvasDrop::INSERT_MANY_LAYERS) {
659 this->mainWindow()
660 ->viewManager()
661 ->imageManager()
662 ->importImage(url);
663 this->activateWindow();
664 } else if (action == KisCanvasDrop::INSERT_MANY_FILE_LAYERS
665 || action
668 this->mainWindow()->viewManager());
669 QFileInfo fileInfo(url.toLocalFile());
670
671 QString type =
672 KisMimeDatabase::mimeTypeForFile(url.toLocalFile());
673 QStringList mimes =
676
677 if (!mimes.contains(type)) {
678 QString msg =
681 .errorMessage();
682 QMessageBox::warning(
683 this,
684 i18nc("@title:window", "Krita"),
685 i18n("Could not open %2.\nReason: %1.",
686 msg,
687 url.toDisplayString()));
688 continue;
689 }
690
691 KisFileLayer *fileLayer =
692 new KisFileLayer(this->image(),
693 "",
694 url.toLocalFile(),
696 "Bicubic",
697 fileInfo.fileName(),
699
700 KisLayerSP above =
701 this->mainWindow()->viewManager()->activeLayer();
702 KisNodeSP parent = above ? above->parent()
703 : this->mainWindow()
704 ->viewManager()
705 ->image()
706 ->root();
707
708 adapter.addNode(fileLayer, parent, above);
709 } else if (action == KisCanvasDrop::OPEN_IN_NEW_DOCUMENT
710 || action
712 if (this->mainWindow()) {
713 this->mainWindow()->openDocument(
714 url.toLocalFile(),
716 }
717 } else if (action
719 || action
720 == KisCanvasDrop::
721 INSERT_AS_REFERENCE_IMAGE) {
722 auto *reference =
723 KisReferenceImage::fromFile(url.toLocalFile(),
724 *this->viewConverter(),
725 this);
726
727 if (reference) {
728 const auto pos = this->canvasBase()
730 ->widgetToImage(event->pos());
731 reference->setPosition(
732 (*this->viewConverter()).imageToDocument(pos));
733 this->canvasBase()
735 ->addReferenceImage(reference);
736
738 "ToolReferenceImages");
739 }
740 }
741 }
742 }
743 }
744 } else if (event->mimeData()->hasColor() || event->mimeData()->hasFormat("krita/x-colorsetentry")) {
745 if (!image()) {
746 return;
747 }
748
749 // Cannot fill on non-painting layers (vector layer, clone layer, file layer, group layer)
750 if (d->viewManager->activeNode().isNull() ||
751 d->viewManager->activeNode()->inherits("KisShapeLayer") ||
752 d->viewManager->activeNode()->inherits("KisCloneLayer") ||
753 !d->viewManager->activeDevice()) {
754 showFloatingMessage(i18n("You cannot drag and drop colors on the selected layer type."), QIcon());
755 return;
756 }
757
758 // Cannot fill if the layer is not editable
759 if (!d->viewManager->activeNode()->isEditable()) {
760 QString message;
761 if (!d->viewManager->activeNode()->visible() && d->viewManager->activeNode()->userLocked()) {
762 message = i18n("Layer is locked and invisible.");
763 } else if (d->viewManager->activeNode()->userLocked()) {
764 message = i18n("Layer is locked.");
765 } else if(!d->viewManager->activeNode()->visible()) {
766 message = i18n("Layer is invisible.");
767 }
768 showFloatingMessage(message, KisIconUtils::loadIcon("object-locked"));
769 return;
770 }
771
772 // The cursor is outside the image
773 if (!image()->wrapAroundModePermitted() && !image()->bounds().contains(imgCursorPos)) {
774 return;
775 }
776
779 kundo2_i18n("Flood Fill Layer"), false, image().data()
780 );
781 strategy->setSupportsWrapAroundMode(true);
782 KisStrokeId fillStrokeId = image()->startStroke(strategy);
783 KIS_SAFE_ASSERT_RECOVER_RETURN(fillStrokeId);
784
785 QSharedPointer<QRect> dirtyRect = QSharedPointer<QRect>(new QRect);
786
787 KisResourcesSnapshotSP resources =
788 new KisResourcesSnapshot(image(), d->viewManager->activeNode(), d->viewManager->canvasResourceProvider()->resourceManager());
789
790 if (event->mimeData()->hasColor()) {
791 resources->setFGColorOverride(KoColor(event->mimeData()->colorData().value<QColor>(), image()->colorSpace()));
792 } else {
793 QByteArray byteData = event->mimeData()->data("krita/x-colorsetentry");
795 resources->setFGColorOverride(s.color());
796 }
797
798 // Use same options as the fill tool
799 KConfigGroup configGroup = KSharedConfig::openConfig()->group("KritaFill/KisToolFill");
800 QString fillMode = configGroup.readEntry<QString>("whatToFill", "");
801 if (fillMode.isEmpty()) {
802 if (configGroup.readEntry<bool>("fillSelection", false)) {
803 fillMode = "fillSelection";
804 } else {
805 fillMode = "fillContiguousRegion";
806 }
807 }
808 const bool useCustomBlendingOptions = configGroup.readEntry<bool>("useCustomBlendingOptions", false);
809 const qreal customOpacity =
810 qBound(0, configGroup.readEntry<int>("customOpacity", 100), 100) / 100.0;
811 QString customCompositeOp = configGroup.readEntry<QString>("customCompositeOp", COMPOSITE_OVER);
812 if (KoCompositeOpRegistry::instance().getKoID(customCompositeOp).id().isNull()) {
813 customCompositeOp = COMPOSITE_OVER;
814 }
815
816 if (event->keyboardModifiers() == Qt::ShiftModifier) {
817 if (fillMode == "fillSimilarRegions") {
818 fillMode = "fillSelection";
819 } else {
820 fillMode = "fillSimilarRegions";
821 }
822 } else if (event->keyboardModifiers() == Qt::AltModifier) {
823 if (fillMode == "fillContiguousRegion") {
824 fillMode = "fillSelection";
825 } else {
826 fillMode = "fillContiguousRegion";
827 }
828 }
829
830 if (fillMode == "fillSelection") {
831 FillProcessingVisitor *visitor = new FillProcessingVisitor(nullptr,
832 selection(),
833 resources);
834 visitor->setSeedPoint(imgCursorPos);
835 visitor->setSelectionOnly(true);
836 visitor->setUseCustomBlendingOptions(useCustomBlendingOptions);
837 if (useCustomBlendingOptions) {
838 visitor->setCustomOpacity(customOpacity);
839 visitor->setCustomCompositeOp(customCompositeOp);
840 }
841 visitor->setOutDirtyRect(dirtyRect);
842
843 image()->addJob(
844 fillStrokeId,
846 KUndo2CommandSP(new KisProcessingCommand(visitor, d->viewManager->activeNode())),
847 false,
850 )
851 );
852 } else {
853 const int threshold = configGroup.readEntry("thresholdAmount", 8);
854 const int opacitySpread = configGroup.readEntry("opacitySpread", 100);
855 const bool antiAlias = configGroup.readEntry("antiAlias", true);
856 const int grow = configGroup.readEntry("growSelection", 0);
857 const bool stopGrowingAtDarkestPixel = configGroup.readEntry<bool>("stopGrowingAtDarkestPixel", false);
858 const int feather = configGroup.readEntry("featherAmount", 0);
859 const int closeGap = configGroup.readEntry("closeGapAmount", 0);
860 QString sampleLayersMode = configGroup.readEntry("sampleLayersMode", "");
861 if (sampleLayersMode.isEmpty()) {
862 if (configGroup.readEntry("sampleMerged", false)) {
863 sampleLayersMode = "allLayers";
864 } else {
865 sampleLayersMode = "currentLayer";
866 }
867 }
868 QList<int> colorLabels;
869 {
870 const QStringList colorLabelsStr = configGroup.readEntry<QString>("colorLabels", "").split(',', Qt::SkipEmptyParts);
871
872 for (const QString &colorLabelStr : colorLabelsStr) {
873 bool ok;
874 const int colorLabel = colorLabelStr.toInt(&ok);
875 if (ok) {
876 colorLabels << colorLabel;
877 }
878 }
879 }
880
881 KisPaintDeviceSP referencePaintDevice = nullptr;
882 if (sampleLayersMode == "allLayers") {
883 referencePaintDevice = image()->projection();
884 } else if (sampleLayersMode == "currentLayer") {
885 referencePaintDevice = d->viewManager->activeNode()->paintDevice();
886 } else if (sampleLayersMode == "colorLabeledLayers") {
887 referencePaintDevice = KisMergeLabeledLayersCommand::createRefPaintDevice(image(), "Fill Tool Reference Result Paint Device");
888 image()->addJob(
889 fillStrokeId,
892 referencePaintDevice,
893 colorLabels,
895 false,
898 )
899 );
900 }
901
902 QSharedPointer<KoColor> referenceColor(new KoColor);
903 if (sampleLayersMode == "colorLabeledLayers") {
904 // We need to obtain the reference color from the reference paint
905 // device, but it is produced in a stroke, so we must get the color
906 // after the device is ready. So we get it in the stroke
907 image()->addJob(
908 fillStrokeId,
911 [referenceColor, referencePaintDevice, imgCursorPos]() -> KUndo2Command*
912 {
913 *referenceColor = referencePaintDevice->pixel(imgCursorPos);
914 return 0;
915 }
916 )),
917 false,
920 )
921 );
922 } else {
923 // Here the reference device is already ready, so we obtain the
924 // reference color directly
925 *referenceColor = referencePaintDevice->pixel(imgCursorPos);
926 }
927
928 if (fillMode == "fillContiguousRegion") {
929 const KisFillPainter::RegionFillingMode regionFillingMode =
930 configGroup.readEntry("contiguousFillMode", "") == "boundaryFill"
933 KoColor regionFillingBoundaryColor;
934 if (regionFillingMode == KisFillPainter::RegionFillingMode_BoundaryFill) {
935 const QString xmlColor = configGroup.readEntry("contiguousFillBoundaryColor", QString());
936 QDomDocument doc;
937 if (doc.setContent(xmlColor)) {
938 QDomElement e = doc.documentElement().firstChild().toElement();
939 QString channelDepthID = doc.documentElement().attribute("channeldepth", Integer16BitsColorDepthID.id());
940 bool ok;
941 if (e.hasAttribute("space") || e.tagName().toLower() == "srgb") {
942 regionFillingBoundaryColor = KoColor::fromXML(e, channelDepthID, &ok);
943 } else if (doc.documentElement().hasAttribute("space") || doc.documentElement().tagName().toLower() == "srgb"){
944 regionFillingBoundaryColor = KoColor::fromXML(doc.documentElement(), channelDepthID, &ok);
945 }
946 }
947 }
948 const bool useSelectionAsBoundary = configGroup.readEntry("useSelectionAsBoundary", false);
949 const bool blendingOptionsAreNoOp = useCustomBlendingOptions
950 ? (qFuzzyCompare(customOpacity, OPACITY_OPAQUE_F) &&
951 customCompositeOp == COMPOSITE_OVER)
952 : (qFuzzyCompare(resources->opacity(), OPACITY_OPAQUE_F) &&
953 resources->compositeOpId() == COMPOSITE_OVER);
954 const bool useFastMode = !resources->activeSelection() &&
955 blendingOptionsAreNoOp &&
956 opacitySpread == 100 &&
957 useSelectionAsBoundary == false &&
958 !antiAlias && grow == 0 && feather == 0 &&
959 closeGap == 0 &&
960 sampleLayersMode == "currentLayer";
961
962 FillProcessingVisitor *visitor = new FillProcessingVisitor(referencePaintDevice,
963 selection(),
964 resources);
965 visitor->setSeedPoint(imgCursorPos);
966 visitor->setUseFastMode(useFastMode);
967 visitor->setUseSelectionAsBoundary(useSelectionAsBoundary);
968 visitor->setFeather(feather);
969 visitor->setSizeMod(grow);
970 visitor->setStopGrowingAtDarkestPixel(stopGrowingAtDarkestPixel);
971 visitor->setRegionFillingMode(regionFillingMode);
972 if (regionFillingMode == KisFillPainter::RegionFillingMode_BoundaryFill) {
973 visitor->setRegionFillingBoundaryColor(regionFillingBoundaryColor);
974 }
975 visitor->setFillThreshold(threshold);
976 visitor->setOpacitySpread(opacitySpread);
977 visitor->setCloseGap(closeGap);
978 visitor->setAntiAlias(antiAlias);
979 visitor->setUseCustomBlendingOptions(useCustomBlendingOptions);
980 if (useCustomBlendingOptions) {
981 visitor->setCustomOpacity(customOpacity);
982 visitor->setCustomCompositeOp(customCompositeOp);
983 }
984 visitor->setOutDirtyRect(dirtyRect);
985
986 image()->addJob(
987 fillStrokeId,
989 KUndo2CommandSP(new KisProcessingCommand(visitor, d->viewManager->activeNode())),
990 false,
993 )
994 );
995 } else {
996 KisSelectionSP fillMask = new KisSelection;
998 progressHelper(new KisProcessingVisitor::ProgressHelper(currentNode()));
999
1000 {
1001 KisSelectionSP selection = this->selection();
1002 KisFillPainter painter;
1003 QRect bounds = image()->bounds();
1004 if (selection) {
1005 bounds = bounds.intersected(selection->projection()->selectedRect());
1006 }
1007
1008 painter.setFillThreshold(threshold);
1009 painter.setOpacitySpread(opacitySpread);
1010 painter.setAntiAlias(antiAlias);
1011 painter.setSizemod(grow);
1012 painter.setStopGrowingAtDarkestPixel(stopGrowingAtDarkestPixel);
1013 painter.setFeather(feather);
1014
1017 fillMask->pixelSelection(), referenceColor, referencePaintDevice,
1018 bounds, selection ? selection->projection() : nullptr, progressHelper
1019 );
1020
1021 for (KisStrokeJobData *job : jobs) {
1022 image()->addJob(fillStrokeId, job);
1023 }
1024 }
1025
1026 {
1027 FillProcessingVisitor *visitor = new FillProcessingVisitor(nullptr,
1028 fillMask,
1029 resources);
1030
1031 visitor->setSeedPoint(imgCursorPos);
1032 visitor->setSelectionOnly(true);
1033 visitor->setProgressHelper(progressHelper);
1034 visitor->setOutDirtyRect(dirtyRect);
1035
1036 image()->addJob(
1037 fillStrokeId,
1039 KUndo2CommandSP(new KisProcessingCommand(visitor, currentNode())),
1040 false,
1043 )
1044 );
1045 }
1046 }
1047 }
1048
1049 image()->addJob(
1050 fillStrokeId,
1052 KUndo2CommandSP(new KisUpdateCommand(d->viewManager->activeNode(), dirtyRect, image().data())),
1053 false,
1056 )
1057 );
1058
1059 image()->endStroke(fillStrokeId);
1060 }
1061}
1062
1063void KisView::dragMoveEvent(QDragMoveEvent *event)
1064{
1065 dbgUI << Q_FUNC_INFO
1066 << "Formats: " << event->mimeData()->formats()
1067 << "Urls: " << event->mimeData()->urls()
1068 << "Has images: " << event->mimeData()->hasImage();
1069 if (event->mimeData()->hasImage()
1070 || event->mimeData()->hasUrls()
1071 || event->mimeData()->hasFormat("application/x-krita-node-internal-pointer")
1072 || event->mimeData()->hasFormat("krita/x-colorsetentry")
1073 || event->mimeData()->hasColor()) {
1074 return event->accept();
1075 }
1076
1077 return event->ignore();
1078}
1079
1081{
1082 return d->document;
1083}
1084
1086{
1087 KisMainWindow *window = mainWindow();
1088 QMdiSubWindow *subWindow = d->subWindow;
1089 delete this;
1090 return window->newView(document, subWindow);
1091}
1092
1094{
1095 return d->viewManager->mainWindow();
1096}
1097
1098void KisView::setSubWindow(QMdiSubWindow *subWindow)
1099{
1100 d->subWindow = subWindow;
1101}
1102
1103QStatusBar * KisView::statusBar() const
1104{
1105 KisMainWindow *mw = mainWindow();
1106 return mw ? mw->statusBar() : 0;
1107}
1108
1109void KisView::slotSavingStatusMessage(const QString &text, int timeout, bool isAutoSaving)
1110{
1111 QStatusBar *sb = statusBar();
1112 if (sb) {
1113 sb->showMessage(text, timeout);
1114 }
1115
1116 KisConfig cfg(true);
1117
1118 if (!sb || sb->isHidden() ||
1119 (!isAutoSaving && cfg.forceShowSaveMessages()) ||
1120 (cfg.forceShowAutosaveMessages() && isAutoSaving)) {
1121
1122 viewManager()->showFloatingMessage(text, QIcon());
1123 }
1124}
1125
1127{
1128 QStatusBar *sb = statusBar();
1129 if (sb) {
1130 sb->clearMessage();
1131 }
1132}
1133
1135{
1136 UnitActionGroup* unitActions = new UnitActionGroup(d->document, addPixelUnit, this);
1137 return unitActions->actions();
1138}
1139
1140void KisView::closeEvent(QCloseEvent *event)
1141{
1142 // Check whether we're the last view
1143 int viewCount = KisPart::instance()->viewCount(document());
1144 if (viewCount > 1) {
1145 // there are others still, so don't bother the user
1146 event->accept();
1147 return;
1148 }
1149
1150 if (queryClose()) {
1151 event->accept();
1152 return;
1153 }
1154
1155 event->ignore();
1156
1157}
1158
1160{
1161 if (!document())
1162 return true;
1163
1164 document()->waitForSavingToComplete();
1165
1166 if (document()->isModified()) {
1167 QString name;
1168 name = QFileInfo(document()->path()).fileName();
1169
1170 if (name.isEmpty())
1171 name = i18n("Untitled");
1172
1173 int res = QMessageBox::warning(this,
1174 i18nc("@title:window", "Krita"),
1175 i18n("<p>The document <b>'%1'</b> has been modified.</p><p>Do you want to save it?</p>", name),
1176 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes);
1177
1178 switch (res) {
1179 case QMessageBox::Yes : {
1180 bool isNative = (document()->mimeType() == document()->nativeFormatMimeType());
1181 if (!viewManager()->mainWindow()->saveDocument(document(), !isNative, false))
1182 return false;
1183 break;
1184 }
1185 case QMessageBox::No : {
1186 KisImageSP image = document()->image();
1189
1190 document()->removeAutoSaveFiles(document()->localFilePath(), document()->isRecovered());
1191 document()->setModified(false); // Now when queryClose() is called by closeEvent it won't do anything.
1192 break;
1193 }
1194 default : // case QMessageBox::Cancel :
1195 return false;
1196 }
1197 }
1198
1199 return true;
1200
1201}
1202
1204{
1205 d->canvas.slotScreenChanged(screen);
1206}
1207
1209{
1214 d->canvasController.updateScreenResolution(this);
1215
1216 if (d->canvas.resourceManager() && d->screenMigrationTracker.currentScreen()) {
1217 int penWidth = qRound(d->screenMigrationTracker.currentScreen()->devicePixelRatio());
1218 d->canvas.resourceManager()->setDecorationThickness(qMax(penWidth, 1));
1219 }
1220}
1221
1223{
1224 return d->screenMigrationTracker.currentScreen();
1225}
1226
1228{
1229 this->setPalette(pal);
1230 for (int i=0; i<this->children().size();i++) {
1231 QWidget *w = qobject_cast<QWidget*> ( this->children().at(i));
1232 if (w) {
1233 w->setPalette(pal);
1234 }
1235 }
1236 if (canvasBase()) {
1237 canvasBase()->canvasWidget()->setPalette(pal);
1238 }
1239 if (canvasController()) {
1240 canvasController()->setPalette(pal);
1241 }
1242}
1243
1245{
1246 QString title = d->document->caption();
1247
1248 if (!d->document->isReadWrite()) {
1249 title += " " + i18n("Write Protected");
1250 }
1251
1252 if (d->document->isRecovered()) {
1253 title += " " + i18n("Recovered");
1254 }
1255
1256 // show the file size for the document
1258
1259 if (fileSizeStats.imageSize) {
1260 title += QString(" (").append( KFormat().formatByteSize(qreal(fileSizeStats.imageSize))).append( ") ");
1261 }
1262
1263 title += "[*]";
1264
1265 this->setWindowTitle(title);
1266}
1267
1269{
1270 KisDocument *doc = document();
1271 if (doc) {
1272 doc->setPreActivatedNode(d->currentNode);
1273 }
1274}
1275
1277{
1278 config.setProperty("file", d->document->path());
1279 config.setProperty("window", mainWindow()->windowStateConfig().name());
1280
1281 if (d->subWindow) {
1282 config.setProperty("geometry", d->subWindow->saveGeometry().toBase64());
1283 }
1284
1285 const KoZoomState zoomState = d->canvasController.zoomState();
1286
1287 config.setProperty("zoomMode", zoomState.mode);
1288 config.setProperty("zoom", zoomState.zoom);
1289
1290 d->canvasController.saveCanvasState(config);
1291}
1292
1294{
1295 if (d->subWindow) {
1296 QByteArray geometry = QByteArray::fromBase64(config.getString("geometry", "").toLatin1());
1297 d->subWindow->restoreGeometry(QByteArray::fromBase64(geometry));
1298 }
1299
1300 qreal zoom = config.getFloat("zoom", 1.0f);
1301 int zoomMode = config.getInt("zoomMode", (int)KoZoomMode::ZOOM_PAGE);
1302 d->canvasController.setZoom((KoZoomMode::Mode)zoomMode, zoom);
1303 d->canvasController.restoreCanvasState(config);
1304}
1305
1307{
1308 d->currentNode = node;
1310
1312}
1313
1315{
1316 return d->currentNode;
1317}
1318
1320{
1321 KisNodeSP node;
1322 KisMaskSP mask = currentMask();
1323 if (mask) {
1324 node = mask->parent();
1325 }
1326 else {
1327 node = d->currentNode;
1328 }
1329 return qobject_cast<KisLayer*>(node.data());
1330}
1331
1333{
1334 return dynamic_cast<KisMask*>(d->currentNode.data());
1335}
1336
1338{
1339 KisLayerSP layer = currentLayer();
1340 if (layer)
1341 return layer->selection(); // falls through to the global
1342 // selection, or 0 in the end
1343 if (image()) {
1344 return image()->globalSelection();
1345 }
1346 return 0;
1347}
1348
1349void KisView::slotSoftProofing(bool softProofing)
1350{
1351 d->softProofing = softProofing;
1352 QString message;
1353 if (canvasBase()->image()->colorSpace()->colorDepthId().id().contains("F"))
1354 {
1355 message = i18n("Soft Proofing doesn't work in floating point.");
1356 viewManager()->showFloatingMessage(message,QIcon());
1357 return;
1358 }
1359 if (softProofing){
1360 message = i18n("Soft Proofing turned on.");
1361 } else {
1362 message = i18n("Soft Proofing turned off.");
1363 }
1364 viewManager()->showFloatingMessage(message,QIcon());
1366}
1367
1368void KisView::slotGamutCheck(bool gamutCheck)
1369{
1370 d->gamutCheck = gamutCheck;
1371 QString message;
1372 if (canvasBase()->image()->colorSpace()->colorDepthId().id().contains("F"))
1373 {
1374 message = i18n("Gamut Warnings don't work in floating point.");
1375 viewManager()->showFloatingMessage(message,QIcon());
1376 return;
1377 }
1378
1379 if (gamutCheck){
1380 message = i18n("Gamut Warnings turned on.");
1381 if (!d->softProofing){
1382 message += "\n "+i18n("But Soft Proofing is still off.");
1383 }
1384 } else {
1385 message = i18n("Gamut Warnings turned off.");
1386 }
1387 viewManager()->showFloatingMessage(message,QIcon());
1389}
1390
1392{
1393 return d->softProofing;
1394}
1395
1397{
1398 return d->gamutCheck;
1399}
1400
1402{
1403 if (!document()) return;
1404
1409
1410 if (image()->locked()) {
1411 // If this is the first view on the image, the image will have been locked
1412 // so unlock it.
1413 image()->blockSignals(false);
1414 image()->unlock();
1415 }
1416
1418
1419 connect(image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), this, SIGNAL(sigColorSpaceChanged(const KoColorSpace*)));
1420 connect(image(), SIGNAL(sigProfileChanged(const KoColorProfile*)), this, SIGNAL(sigProfileChanged(const KoColorProfile*)));
1421 connect(image(), SIGNAL(sigSizeChanged(QPointF,QPointF)), this, SIGNAL(sigSizeChanged(QPointF,QPointF)));
1422
1423 connect(&d->screenMigrationTracker, SIGNAL(sigScreenChanged(QScreen*)), this, SLOT(slotMigratedToScreen(QScreen*)));
1424 connect(&d->screenMigrationTracker, SIGNAL(sigScreenOrResolutionChanged(QScreen*)), this, SLOT(slotScreenOrResolutionChanged()));
1426}
1427
1429{
1430 d->canvasController.syncOnImageResolutionChange();
1431 d->zoomManager.syncOnImageResolutionChange();
1433}
1434
1435void KisView::slotImageSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint)
1436{
1437 d->canvasController.syncOnImageSizeChange(oldStillPoint, newStillPoint);
1439}
1440
1442{
1443 d->subWindow->close();
1444}
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const qreal OPACITY_OPAQUE_F
const quint8 OPACITY_OPAQUE_U8
const QString COMPOSITE_OVER
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void setOutDirtyRect(QSharedPointer< QRect > outDirtyRect)
void setStopGrowingAtDarkestPixel(bool stopGrowingAtDarkestPixel)
void setUseFastMode(bool useFastMode)
void setUseCustomBlendingOptions(bool useCustomBlendingOptions)
void setSeedPoint(const QPoint &seedPoint)
void setCustomCompositeOp(const QString &customCompositeOp)
void setProgressHelper(QSharedPointer< ProgressHelper > progressHelper)
void setOpacitySpread(int opacitySpread)
void setAntiAlias(bool antiAlias)
void setSelectionOnly(bool selectionOnly)
void setFillThreshold(int fillThreshold)
void setRegionFillingBoundaryColor(const KoColor &regionFillingBoundaryColor)
void setCustomOpacity(qreal customOpacity)
void setRegionFillingMode(KisFillPainter::RegionFillingMode regionFillingMode)
void setUseSelectionAsBoundary(bool useSelectionAsBoundary)
KisReferenceImagesDecorationSP referenceImagesDecoration() const
void slotScreenChanged(QScreen *screen)
void slotGamutCheck()
bool xAxisMirrored() const
Bools indicating canvasmirroring.
KisCoordinatesConverter * coordinatesConverter
void initializeImage()
void addDecoration(KisCanvasDecorationSP deco)
KisAbstractCanvasWidget * canvasWidget
void disconnectImage()
void slotSoftProofing()
bool yAxisMirrored() const
void slotTrySwitchShapeManager()
Action dropAs(const QMimeData &data, QPoint pos)
static KisClipboard * instance()
QPair< bool, PasteFormatBehaviour > askUserForSource(const QMimeData *data, bool useClipboardFallback=false) const
KisPaintDeviceSP clipFromMimeData(const QMimeData *data, const QRect &imageBounds, bool showPopup, int overridePasteBehaviour=-1, KisTimeSpan *clipRange=nullptr, bool useClipboardFallback=false) const
KisPaintDeviceSP clipFromBoardContents(const QMimeData *data, const QRect &imageBounds, bool showPopup, int overridePasteBehaviour=-1, bool useClipboardFallback=false, QPair< bool, PasteFormatBehaviour > source={ false, PasteFormatBehaviour::PASTE_FORMAT_ASK}) const
bool forceShowSaveMessages(bool defaultValue=true) const
bool showCanvasMessages(bool defaultValue=false) const
bool forceShowAutosaveMessages(bool defaultValue=true) const
_Private::Traits< T >::Result widgetToImage(const T &obj) const
_Private::Traits< T >::Result imageToDocument(const T &obj) const
void setPreActivatedNode(KisNodeSP activatedNode)
The KisFileLayer class loads a particular file as a layer into the layer stack.
void setSizemod(int sizemod)
void setFillThreshold(int threshold)
void setFeather(int feather)
QVector< KisStrokeJobData * > createSimilarColorsSelectionJobs(KisPixelSelectionSP outSelection, const QSharedPointer< KoColor > referenceColor, KisPaintDeviceSP referenceDevice, const QRect &rect, KisPixelSelectionSP mask, QSharedPointer< KisProcessingVisitor::ProgressHelper > progressHelper=nullptr)
void setAntiAlias(bool antiAlias)
void setStopGrowingAtDarkestPixel(bool stopGrowingAtDarkestPixel)
void setOpacitySpread(int opacitySpread)
The KisFloatingMessage class shows the given message in a semi-transparent bubble that doesn't take f...
qint32 importImage(const QUrl &url, const QString &layerType="KisPaintLayer")
KisGroupLayerSP rootLayer() const
void unlock()
Definition kis_image.cc:805
void requestStrokeCancellation()
KisSelectionSP globalSelection() const
Definition kis_image.cc:695
QRect bounds() const override
void sigNodeAddedAsync(KisNodeSP node, KisNodeAdditionFlags flags)
static void adaptClipToImageColorSpace(KisPaintDeviceSP dev, KisImageSP image)
static QStringList supportedMimeTypes(Direction direction)
Central object to manage canvas input.
void detachPriorityEventFilter(QObject *filter)
detachPriorityEventFilter
void attachPriorityEventFilter(QObject *filter, int priority=0)
attachPriorityEventFilter
A container for a set of QAction objects.
Main window for Krita.
KisView * newView(QObject *document, QMdiSubWindow *subWindow=0)
bool openDocument(const QString &path, OpenFlags flags)
bool saveDocument(KisDocument *document, bool saveas, bool isExporting, bool isAdvancedExporting=false)
KisViewManager * viewManager
static KisPaintDeviceSP createRefPaintDevice(KisImageSP originalImage, QString name="Merge Labeled Layers Reference Paint Device")
@ GroupSelectionPolicy_SelectIfColorLabeled
Groups will be taken into account only if they have set an explicit color label. This ignores groups ...
static KisNodeList loadNodesFastAndRecenter(const QPoint &preferredCenter, const QMimeData *data, KisImageSP image, KisShapeController *shapeController, bool &copyNode)
static KisNodeList loadNodesFast(const QMimeData *data, KisImageSP image, KisShapeController *shapeController, bool &copyNode)
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)
bool pixel(qint32 x, qint32 y, QColor *c) const
void moveTo(qint32 x, qint32 y)
static KisPart * instance()
Definition KisPart.cpp:131
void removeView(KisView *view)
Definition KisPart.cpp:344
int viewCount(KisDocument *doc) const
Definition KisPart.cpp:380
static KisReferenceImage * fromFile(const QString &filename, const KisCoordinatesConverter &converter, QWidget *parent)
static KisReferenceImage * fromPaintDevice(KisPaintDeviceSP src, const KisCoordinatesConverter &converter, QWidget *parent)
The KisReferenceImagesDecoration class draws the reference images on the canvas. The document stores ...
void addReferenceImage(KisReferenceImage *referenceImage)
The KisRemoteFileFetcher class can fetch a remote file and blocks until the file is downloaded.
bool fetchFile(const QUrl &remote, QIODevice *io)
fetch the image. Shows a progress dialog
The KisResourcesSnapshot class takes a snapshot of the various resources like colors and settings use...
void setFGColorOverride(const KoColor &color)
KisSelectionSP activeSelection() const
void setInitialShapeForCanvas(KisCanvas2 *canvas)
KoColor color() const
Definition KisSwatch.h:30
static KisSwatch fromByteArray(QByteArray &data, QString &groupName, int &originalRow, int &originalColumn)
Definition KisSwatch.cpp:57
KisMainWindow * mainWindow() const
KisImageManager * imageManager()
KisLayerSP activeLayer()
Convenience method to get at the active layer.
void blockUntilOperationsFinishedForced(KisImageSP image)
blockUntilOperationsFinished blocks the GUI of the application until execution of actions on image is...
KisSelectionManager * selectionManager()
KisImageWSP image() const
Return the image this view is displaying.
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
bool operator==(const StatusBarItem &rhs)
Definition KisView.cpp:160
StatusBarItem(QWidget *widget, int stretch, bool permanent)
Definition KisView.cpp:153
void ensureItemHidden(QStatusBar *sb)
Definition KisView.cpp:182
void ensureItemShown(QStatusBar *sb)
Definition KisView.cpp:168
QWidget * widget() const
Definition KisView.cpp:164
~KisView() override
Definition KisView.cpp:257
QScreen * currentScreen() const
Definition KisView.cpp:1222
KisView(KisDocument *document, KisViewManager *viewManager, QWidget *parent=0)
Definition KisView.cpp:202
KisCanvas2 * canvasBase() const
Definition KisView.cpp:427
void slotGamutCheck(bool gamutCheck)
slotGamutCheck set whether or not we're gamutchecking in this view. Will be setting the same in the v...
Definition KisView.cpp:1368
Private(KisView *_q, KisDocument *document, KisViewManager *viewManager)
Definition KisView.cpp:105
bool canvasIsMirrored() const
Definition KisView.cpp:332
void slotThemeChanged(QPalette pal)
Definition KisView.cpp:1227
static bool s_firstView
Definition KisView.h:265
QString newObjectName()
Definition KisView.cpp:93
void dropEvent(QDropEvent *event) override
Definition KisView.cpp:466
KisMainWindow * mainWindow() const
Definition KisView.cpp:1093
void syncLastActiveNodeToDocument()
Definition KisView.cpp:1268
void notifyCurrentStateChanged(bool isCurrent)
Definition KisView.cpp:282
bool gamutCheck
Definition KisView.cpp:140
void restoreViewState(const KisPropertiesConfiguration &config)
Definition KisView.cpp:1293
void slotClearStatusText()
Definition KisView.cpp:1126
void closeView()
Definition KisView.cpp:1441
KisInputManager * globalInputManager() const
Definition KisView.cpp:422
bool showFloatingMessage
Definition KisView.cpp:134
QList< QAction * > createChangeUnitActions(bool addPixelUnit=false)
create a list of actions that when activated will change the unit on the document.
Definition KisView.cpp:1134
KisCanvasController canvasController
Definition KisView.cpp:126
Private *const d
Definition KisView.h:263
QMdiSubWindow * subWindow
Definition KisView.cpp:137
void slotScreenOrResolutionChanged()
Definition KisView.cpp:1208
bool softProofing
Definition KisView.cpp:139
KisCoordinatesConverter viewConverter
Definition KisView.cpp:125
void setSubWindow(QMdiSubWindow *subWindow)
Definition KisView.cpp:1098
void sigColorSpaceChanged(const KoColorSpace *cs)
QStatusBar * statusBar() const
Definition KisView.cpp:1103
void dragMoveEvent(QDragMoveEvent *event) override
Definition KisView.cpp:1063
KisMaskSP currentMask() const
Definition KisView.cpp:1332
KisScreenMigrationTracker screenMigrationTracker
Definition KisView.cpp:145
void dragEnterEvent(QDragEnterEvent *event) override
Definition KisView.cpp:446
KisReferenceImagesDecorationSP referenceImagesDecoration
Definition KisView.cpp:132
KisViewManager * viewManager
Definition KisView.cpp:129
KisSignalCompressor floatingMessageCompressor
Definition KisView.cpp:136
KisImageWSP image() const
Definition KisView.cpp:432
void setShowFloatingMessage(bool show)
Definition KisView.cpp:309
void slotContinueRemoveNode(KisNodeSP newActiveNode)
Definition KisView.cpp:397
void slotSavingStatusMessage(const QString &text, int timeout, bool isAutoSaving=false)
Definition KisView.cpp:1109
KisView * replaceBy(KisDocument *document)
Definition KisView.cpp:1085
KisCanvasResourceProvider * resourceProvider() const
Definition KisView.cpp:414
void slotContinueAddNode(KisNodeSP newActiveNode, KisNodeAdditionFlags flags)
Definition KisView.cpp:372
void slotMigratedToScreen(QScreen *screen)
Definition KisView.cpp:1203
void closeEvent(QCloseEvent *event) override
Definition KisView.cpp:1140
QPointer< KisDocument > document
Definition KisView.cpp:121
void slotLoadingFinished()
Definition KisView.cpp:1401
void slotImageNodeRemoved(KisNodeSP node)
Definition KisView.cpp:392
void setViewManager(KisViewManager *view)
Definition KisView.cpp:337
void saveViewState(KisPropertiesConfiguration &config) const
Definition KisView.cpp:1276
void slotUpdateDocumentTitle()
Definition KisView.cpp:1244
bool queryClose()
Definition KisView.cpp:1159
void slotSoftProofing(bool softProofing)
slotSoftProofing set whether or not we're softproofing in this view. Will be setting the same in the ...
Definition KisView.cpp:1349
KisNodeSP currentNode
Definition KisView.cpp:130
void slotImageResolutionChanged()
Definition KisView.cpp:1428
KisSelectionSP selection()
Definition KisView.cpp:1337
KisSynchronizedConnection< KisNodeSP > removeNodeConnection
Definition KisView.cpp:143
void slotImageSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint)
Definition KisView.cpp:1435
KisLayerSP currentLayer() const
Definition KisView.cpp:1319
void setCurrentNode(KisNodeSP node)
Definition KisView.cpp:1306
KisPaintingAssistantsDecorationSP paintingAssistantsDecoration
Definition KisView.cpp:131
QPointer< KisFloatingMessage > savedFloatingMessage
Definition KisView.cpp:135
KisSynchronizedConnection< KisNodeSP, KisNodeAdditionFlags > addNodeConnection
Definition KisView.cpp:142
bool isCurrent
Definition KisView.cpp:133
KisZoomManager zoomManager
Definition KisView.cpp:128
void sigProfileChanged(const KoColorProfile *profile)
KisCanvas2 canvas
Definition KisView.cpp:127
void sigSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint)
void updateImageBoundsSnapping()
QPointer< KoCanvasResourceProvider > resourceManager
static KoColor fromXML(const QDomElement &elt, const QString &channelDepthId)
Definition KoColor.cpp:350
static const KoCompositeOpRegistry & instance()
KoID getKoID(const QString &compositeOpID) const
QString id() const
Definition KoID.cpp:63
void switchToolRequested(const QString &id)
void removeCanvasController(KoCanvasController *controller)
void addController(KoCanvasController *controller)
static KoToolManager * instance()
Return the toolmanager singleton.
@ ZOOM_PAGE
zoom page
Definition KoZoomMode.h:25
KoZoomMode::Mode mode
Definition KoZoomState.h:24
static bool qFuzzyCompare(half p1, half p2)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define bounds(x, a, b)
#define dbgUI
Definition kis_debug.h:52
#define warnUI
Definition kis_debug.h:94
QSharedPointer< KUndo2Command > KUndo2CommandSP
Definition kis_types.h:262
KUndo2MagicString kundo2_i18n(const char *text)
QList< KoSubpath * > split(const KoPathShape &path)
QIcon loadIcon(const QString &name)
KisNodeSP nearestNodeAfterRemoval(KisNodeSP node)
The LambdaCommand struct is a shorthand for creation of AggregateCommand commands using C++ lambda fe...
virtual KisSelectionSP selection() const
Definition kis_layer.cc:503
Statistics fetchMemoryStatistics(KisImageSP image) const
static KisMemoryStatisticsServer * instance()
KisNodeWSP parent
Definition kis_node.cpp:86
QString getString(const QString &name, const QString &def=QString()) const
virtual void setProperty(const QString &name, const QVariant &value)
int getInt(const QString &name, int def=0) const
float getFloat(const QString &name, float def=0.0) const
KisPixelSelectionSP projection() const
KisPixelSelectionSP pixelSelection
KisCanvas2 * canvas