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
453 if (shouldAcceptDrag(event)) {
454 event->accept();
455 setFocus(); // activate view if it should accept the drop
456 } else {
457 event->ignore();
458 }
459}
460
461void KisView::dropEvent(QDropEvent *event)
462{
463 dbgUI << Q_FUNC_INFO;
464 dbgUI << "\t Formats: " << event->mimeData()->formats();
465 dbgUI << "\t Urls: " << event->mimeData()->urls();
466 dbgUI << "\t Has images: " << event->mimeData()->hasImage();
467
468 if (!shouldAcceptDrag(event)) {
469 return;
470 }
471
472 KisImageWSP kisimage = image();
473 Q_ASSERT(kisimage);
474
475 QPoint imgCursorPos = canvasBase()->coordinatesConverter()->widgetToImage(event->pos()).toPoint();
476 QRect imageBounds = kisimage->bounds();
477 boost::optional<QPoint> forcedCenter;
478
479 if (event->keyboardModifiers() & Qt::ShiftModifier && imageBounds.contains(imgCursorPos)) {
480 forcedCenter = imgCursorPos;
481 }
482
483 if (event->mimeData()->hasFormat("application/x-krita-node-internal-pointer")) {
484 KisShapeController *kritaShapeController =
485 dynamic_cast<KisShapeController*>(d->document->shapeController());
486
487 bool copyNode = true;
488 QList<KisNodeSP> nodes;
489
490 if (forcedCenter) {
491 nodes = KisMimeData::loadNodesFastAndRecenter(*forcedCenter, event->mimeData(), kisimage, kritaShapeController, copyNode);
492 } else {
493 nodes = KisMimeData::loadNodesFast(event->mimeData(), kisimage, kritaShapeController, copyNode);
494 }
495
496 Q_FOREACH (KisNodeSP node, nodes) {
497 if (node) {
499 if (!viewManager()->nodeManager()->activeLayer()) {
500 adapter.addNode(node, kisimage->rootLayer() , 0);
501 } else {
502 adapter.addNode(node,
503 viewManager()->nodeManager()->activeLayer()->parent(),
504 viewManager()->nodeManager()->activeLayer());
505 }
506 }
507 }
508 } else if (event->mimeData()->hasImage() || event->mimeData()->hasUrls()) {
509 const auto *data = event->mimeData();
510
511 KisCanvasDrop dlgAction;
512
513 const auto callPos = QCursor::pos();
514
515 const KisCanvasDrop::Action action = dlgAction.dropAs(*data, callPos);
516
518 const QPair<bool, KisClipboard::PasteFormatBehaviour> source =
520
521 if (!source.first) {
522 dbgUI << "Paste event cancelled";
523 return;
524 }
525
527 const QList<QUrl> &urls = data->urls();
528 const auto url = std::find_if(
529 urls.constBegin(),
530 urls.constEnd(),
531 [&](const QUrl &url) {
532 if (source.second
533 == KisClipboard::PASTE_FORMAT_DOWNLOAD) {
534 return !url.isLocalFile();
535 } else if (source.second
537 return url.isLocalFile();
538 } else {
539 return false;
540 }
541 });
542
543 if (url != urls.constEnd()) {
544 QScopedPointer<QTemporaryFile> tmp(new QTemporaryFile());
545 tmp->setAutoRemove(true);
546
547 const QUrl localUrl = [&]() -> QUrl {
548 if (!url->isLocalFile()) {
549 // download the file and substitute the url
550 KisRemoteFileFetcher fetcher;
551 tmp->setFileName(url->fileName());
552
553 if (!fetcher.fetchFile(*url, tmp.data())) {
554 warnUI << "Fetching" << *url << "failed";
555 return {};
556 }
557 return QUrl::fromLocalFile(tmp->fileName());
558 }
559 return *url;
560 }();
561
562 if (localUrl.isLocalFile()) {
563 this->mainWindow()
564 ->viewManager()
565 ->imageManager()
566 ->importImage(localUrl);
567 this->activateWindow();
568 return;
569 }
570 }
571 }
572
573 KisPaintDeviceSP clip =
575 QRect(),
576 true,
577 -1,
578 false,
579 source);
580 if (clip) {
581 const auto pos = this->viewConverter()
582 ->imageToDocument(imgCursorPos)
583 .toPoint();
584
585 clip->moveTo(pos.x(), pos.y());
586
588 this->image());
589
590 KisPaintLayerSP layer = new KisPaintLayer(
591 this->image(),
592 this->image()->nextLayerName() + " " + i18n("(pasted)"),
594 clip);
596 this->mainWindow()->viewManager());
597 adapter.addNode(
598 layer,
599 this->mainWindow()->viewManager()->activeNode()->parent(),
600 this->mainWindow()->viewManager()->activeNode());
601 this->activateWindow();
602 return;
603 }
604 } else if (action == KisCanvasDrop::INSERT_AS_REFERENCE_IMAGE) {
605 KisPaintDeviceSP clip =
606 KisClipboard::instance()->clipFromMimeData(data, QRect(), true);
607 if (clip) {
609 this->image());
610
611 auto *reference =
613 *this->viewConverter(),
614 this);
615
616 if (reference) {
617 if (data->hasUrls()) {
618 const auto &urls = data->urls();
619 const auto url = std::find_if(urls.constBegin(), urls.constEnd(), std::mem_fn(&QUrl::isLocalFile));
620 if (url != urls.constEnd()) {
621 reference->setFilename((*url).toLocalFile());
622 }
623 }
624 const auto pos = this->canvasBase()
626 ->widgetToImage(event->pos());
627 reference->setPosition(
628 (*this->viewConverter()).imageToDocument(pos));
629 this->canvasBase()
631 ->addReferenceImage(reference);
633 "ToolReferenceImages");
634 return;
635 }
636 }
637 } else if (action != KisCanvasDrop::NONE) {
638 // multiple URLs detected OR about to open a document
639
640 for (QUrl url : data->urls()) { // do copy it
641 QScopedPointer<QTemporaryFile> tmp(new QTemporaryFile());
642 tmp->setAutoRemove(true);
643
644 if (!url.isLocalFile()) {
645 // download the file and substitute the url
646 KisRemoteFileFetcher fetcher;
647 tmp->setFileName(url.fileName());
648
649 if (!fetcher.fetchFile(url, tmp.data())) {
650 qWarning() << "Fetching" << url << "failed";
651 continue;
652 }
653 url = QUrl::fromLocalFile(tmp->fileName());
654 }
655
656 if (url.isLocalFile()) {
657 if (action == KisCanvasDrop::INSERT_MANY_LAYERS) {
658 this->mainWindow()
659 ->viewManager()
660 ->imageManager()
661 ->importImage(url);
662 this->activateWindow();
663 } else if (action == KisCanvasDrop::INSERT_MANY_FILE_LAYERS
664 || action
667 this->mainWindow()->viewManager());
668 QFileInfo fileInfo(url.toLocalFile());
669
670 QString type =
671 KisMimeDatabase::mimeTypeForFile(url.toLocalFile());
672 QStringList mimes =
675
676 if (!mimes.contains(type)) {
677 QString msg =
680 .errorMessage();
681 QMessageBox::warning(
682 this,
683 i18nc("@title:window", "Krita"),
684 i18n("Could not open %2.\nReason: %1.",
685 msg,
686 url.toDisplayString()));
687 continue;
688 }
689
690 KisFileLayer *fileLayer =
691 new KisFileLayer(this->image(),
692 "",
693 url.toLocalFile(),
695 "Bicubic",
696 fileInfo.fileName(),
698
699 KisLayerSP above =
700 this->mainWindow()->viewManager()->activeLayer();
701 KisNodeSP parent = above ? above->parent()
702 : this->mainWindow()
703 ->viewManager()
704 ->image()
705 ->root();
706
707 adapter.addNode(fileLayer, parent, above);
708 } else if (action == KisCanvasDrop::OPEN_IN_NEW_DOCUMENT
709 || action
711 if (this->mainWindow()) {
712 this->mainWindow()->openDocument(
713 url.toLocalFile(),
715 }
716 } else if (action
718 || action
719 == KisCanvasDrop::
720 INSERT_AS_REFERENCE_IMAGE) {
721 auto *reference =
722 KisReferenceImage::fromFile(url.toLocalFile(),
723 *this->viewConverter(),
724 this);
725
726 if (reference) {
727 const auto pos = this->canvasBase()
729 ->widgetToImage(event->pos());
730 reference->setPosition(
731 (*this->viewConverter()).imageToDocument(pos));
732 this->canvasBase()
734 ->addReferenceImage(reference);
735
737 "ToolReferenceImages");
738 }
739 }
740 }
741 }
742 }
743 } else if (event->mimeData()->hasColor() || event->mimeData()->hasFormat("krita/x-colorsetentry")) {
744 if (!image()) {
745 return;
746 }
747
748 // Cannot fill on non-painting layers (vector layer, clone layer, file layer, group layer)
749 if (d->viewManager->activeNode().isNull() ||
750 d->viewManager->activeNode()->inherits("KisShapeLayer") ||
751 d->viewManager->activeNode()->inherits("KisCloneLayer") ||
752 !d->viewManager->activeDevice()) {
753 showFloatingMessage(i18n("You cannot drag and drop colors on the selected layer type."), QIcon());
754 return;
755 }
756
757 // Cannot fill if the layer is not editable
758 if (!d->viewManager->activeNode()->isEditable()) {
759 QString message;
760 if (!d->viewManager->activeNode()->visible() && d->viewManager->activeNode()->userLocked()) {
761 message = i18n("Layer is locked and invisible.");
762 } else if (d->viewManager->activeNode()->userLocked()) {
763 message = i18n("Layer is locked.");
764 } else if(!d->viewManager->activeNode()->visible()) {
765 message = i18n("Layer is invisible.");
766 }
767 showFloatingMessage(message, KisIconUtils::loadIcon("object-locked"));
768 return;
769 }
770
771 // The cursor is outside the image
772 if (!image()->wrapAroundModePermitted() && !image()->bounds().contains(imgCursorPos)) {
773 return;
774 }
775
778 kundo2_i18n("Flood Fill Layer"), false, image().data()
779 );
780 strategy->setSupportsWrapAroundMode(true);
781 KisStrokeId fillStrokeId = image()->startStroke(strategy);
782 KIS_SAFE_ASSERT_RECOVER_RETURN(fillStrokeId);
783
784 QSharedPointer<QRect> dirtyRect = QSharedPointer<QRect>(new QRect);
785
786 KisResourcesSnapshotSP resources =
787 new KisResourcesSnapshot(image(), d->viewManager->activeNode(), d->viewManager->canvasResourceProvider()->resourceManager());
788
789 if (event->mimeData()->hasColor()) {
790 resources->setFGColorOverride(KoColor(event->mimeData()->colorData().value<QColor>(), image()->colorSpace()));
791 } else {
792 QByteArray byteData = event->mimeData()->data("krita/x-colorsetentry");
794 resources->setFGColorOverride(s.color());
795 }
796
797 // Use same options as the fill tool
798 KConfigGroup configGroup = KSharedConfig::openConfig()->group("KritaFill/KisToolFill");
799 QString fillMode = configGroup.readEntry<QString>("whatToFill", "");
800 if (fillMode.isEmpty()) {
801 if (configGroup.readEntry<bool>("fillSelection", false)) {
802 fillMode = "fillSelection";
803 } else {
804 fillMode = "fillContiguousRegion";
805 }
806 }
807 const bool useCustomBlendingOptions = configGroup.readEntry<bool>("useCustomBlendingOptions", false);
808 const qreal customOpacity =
809 qBound(0, configGroup.readEntry<int>("customOpacity", 100), 100) / 100.0;
810 QString customCompositeOp = configGroup.readEntry<QString>("customCompositeOp", COMPOSITE_OVER);
811 if (KoCompositeOpRegistry::instance().getKoID(customCompositeOp).id().isNull()) {
812 customCompositeOp = COMPOSITE_OVER;
813 }
814
815 if (event->keyboardModifiers() == Qt::ShiftModifier) {
816 if (fillMode == "fillSimilarRegions") {
817 fillMode = "fillSelection";
818 } else {
819 fillMode = "fillSimilarRegions";
820 }
821 } else if (event->keyboardModifiers() == Qt::AltModifier) {
822 if (fillMode == "fillContiguousRegion") {
823 fillMode = "fillSelection";
824 } else {
825 fillMode = "fillContiguousRegion";
826 }
827 }
828
829 if (fillMode == "fillSelection") {
830 FillProcessingVisitor *visitor = new FillProcessingVisitor(nullptr,
831 selection(),
832 resources);
833 visitor->setSeedPoint(imgCursorPos);
834 visitor->setSelectionOnly(true);
835 visitor->setUseCustomBlendingOptions(useCustomBlendingOptions);
836 if (useCustomBlendingOptions) {
837 visitor->setCustomOpacity(customOpacity);
838 visitor->setCustomCompositeOp(customCompositeOp);
839 }
840 visitor->setOutDirtyRect(dirtyRect);
841
842 image()->addJob(
843 fillStrokeId,
845 KUndo2CommandSP(new KisProcessingCommand(visitor, d->viewManager->activeNode())),
846 false,
849 )
850 );
851 } else {
852 const int threshold = configGroup.readEntry("thresholdAmount", 8);
853 const int opacitySpread = configGroup.readEntry("opacitySpread", 100);
854 const bool antiAlias = configGroup.readEntry("antiAlias", true);
855 const int grow = configGroup.readEntry("growSelection", 0);
856 const bool stopGrowingAtDarkestPixel = configGroup.readEntry<bool>("stopGrowingAtDarkestPixel", false);
857 const int feather = configGroup.readEntry("featherAmount", 0);
858 const int closeGap = configGroup.readEntry("closeGapAmount", 0);
859 QString sampleLayersMode = configGroup.readEntry("sampleLayersMode", "");
860 if (sampleLayersMode.isEmpty()) {
861 if (configGroup.readEntry("sampleMerged", false)) {
862 sampleLayersMode = "allLayers";
863 } else {
864 sampleLayersMode = "currentLayer";
865 }
866 }
867 QList<int> colorLabels;
868 {
869 const QStringList colorLabelsStr = configGroup.readEntry<QString>("colorLabels", "").split(',', Qt::SkipEmptyParts);
870
871 for (const QString &colorLabelStr : colorLabelsStr) {
872 bool ok;
873 const int colorLabel = colorLabelStr.toInt(&ok);
874 if (ok) {
875 colorLabels << colorLabel;
876 }
877 }
878 }
879
880 KisPaintDeviceSP referencePaintDevice = nullptr;
881 if (sampleLayersMode == "allLayers") {
882 referencePaintDevice = image()->projection();
883 } else if (sampleLayersMode == "currentLayer") {
884 referencePaintDevice = d->viewManager->activeNode()->paintDevice();
885 } else if (sampleLayersMode == "colorLabeledLayers") {
886 referencePaintDevice = KisMergeLabeledLayersCommand::createRefPaintDevice(image(), "Fill Tool Reference Result Paint Device");
887 image()->addJob(
888 fillStrokeId,
891 referencePaintDevice,
892 colorLabels,
894 false,
897 )
898 );
899 }
900
901 QSharedPointer<KoColor> referenceColor(new KoColor);
902 if (sampleLayersMode == "colorLabeledLayers") {
903 // We need to obtain the reference color from the reference paint
904 // device, but it is produced in a stroke, so we must get the color
905 // after the device is ready. So we get it in the stroke
906 image()->addJob(
907 fillStrokeId,
910 [referenceColor, referencePaintDevice, imgCursorPos]() -> KUndo2Command*
911 {
912 *referenceColor = referencePaintDevice->pixel(imgCursorPos);
913 return 0;
914 }
915 )),
916 false,
919 )
920 );
921 } else {
922 // Here the reference device is already ready, so we obtain the
923 // reference color directly
924 *referenceColor = referencePaintDevice->pixel(imgCursorPos);
925 }
926
927 if (fillMode == "fillContiguousRegion") {
928 const KisFillPainter::RegionFillingMode regionFillingMode =
929 configGroup.readEntry("contiguousFillMode", "") == "boundaryFill"
932 KoColor regionFillingBoundaryColor;
933 if (regionFillingMode == KisFillPainter::RegionFillingMode_BoundaryFill) {
934 const QString xmlColor = configGroup.readEntry("contiguousFillBoundaryColor", QString());
935 QDomDocument doc;
936 if (doc.setContent(xmlColor)) {
937 QDomElement e = doc.documentElement().firstChild().toElement();
938 QString channelDepthID = doc.documentElement().attribute("channeldepth", Integer16BitsColorDepthID.id());
939 bool ok;
940 if (e.hasAttribute("space") || e.tagName().toLower() == "srgb") {
941 regionFillingBoundaryColor = KoColor::fromXML(e, channelDepthID, &ok);
942 } else if (doc.documentElement().hasAttribute("space") || doc.documentElement().tagName().toLower() == "srgb"){
943 regionFillingBoundaryColor = KoColor::fromXML(doc.documentElement(), channelDepthID, &ok);
944 }
945 }
946 }
947 const bool useSelectionAsBoundary = configGroup.readEntry("useSelectionAsBoundary", false);
948 const bool blendingOptionsAreNoOp = useCustomBlendingOptions
949 ? (qFuzzyCompare(customOpacity, OPACITY_OPAQUE_F) &&
950 customCompositeOp == COMPOSITE_OVER)
951 : (qFuzzyCompare(resources->opacity(), OPACITY_OPAQUE_F) &&
952 resources->compositeOpId() == COMPOSITE_OVER);
953 const bool useFastMode = !resources->activeSelection() &&
954 blendingOptionsAreNoOp &&
955 opacitySpread == 100 &&
956 useSelectionAsBoundary == false &&
957 !antiAlias && grow == 0 && feather == 0 &&
958 closeGap == 0 &&
959 sampleLayersMode == "currentLayer";
960
961 FillProcessingVisitor *visitor = new FillProcessingVisitor(referencePaintDevice,
962 selection(),
963 resources);
964 visitor->setSeedPoint(imgCursorPos);
965 visitor->setUseFastMode(useFastMode);
966 visitor->setUseSelectionAsBoundary(useSelectionAsBoundary);
967 visitor->setFeather(feather);
968 visitor->setSizeMod(grow);
969 visitor->setStopGrowingAtDarkestPixel(stopGrowingAtDarkestPixel);
970 visitor->setRegionFillingMode(regionFillingMode);
971 if (regionFillingMode == KisFillPainter::RegionFillingMode_BoundaryFill) {
972 visitor->setRegionFillingBoundaryColor(regionFillingBoundaryColor);
973 }
974 visitor->setFillThreshold(threshold);
975 visitor->setOpacitySpread(opacitySpread);
976 visitor->setCloseGap(closeGap);
977 visitor->setAntiAlias(antiAlias);
978 visitor->setUseCustomBlendingOptions(useCustomBlendingOptions);
979 if (useCustomBlendingOptions) {
980 visitor->setCustomOpacity(customOpacity);
981 visitor->setCustomCompositeOp(customCompositeOp);
982 }
983 visitor->setOutDirtyRect(dirtyRect);
984
985 image()->addJob(
986 fillStrokeId,
988 KUndo2CommandSP(new KisProcessingCommand(visitor, d->viewManager->activeNode())),
989 false,
992 )
993 );
994 } else {
995 KisSelectionSP fillMask = new KisSelection;
997 progressHelper(new KisProcessingVisitor::ProgressHelper(currentNode()));
998
999 {
1000 KisSelectionSP selection = this->selection();
1001 KisFillPainter painter;
1002 QRect bounds = image()->bounds();
1003 if (selection) {
1004 bounds = bounds.intersected(selection->projection()->selectedRect());
1005 }
1006
1007 painter.setFillThreshold(threshold);
1008 painter.setOpacitySpread(opacitySpread);
1009 painter.setAntiAlias(antiAlias);
1010 painter.setSizemod(grow);
1011 painter.setStopGrowingAtDarkestPixel(stopGrowingAtDarkestPixel);
1012 painter.setFeather(feather);
1013
1016 fillMask->pixelSelection(), referenceColor, referencePaintDevice,
1017 bounds, selection ? selection->projection() : nullptr, progressHelper
1018 );
1019
1020 for (KisStrokeJobData *job : jobs) {
1021 image()->addJob(fillStrokeId, job);
1022 }
1023 }
1024
1025 {
1026 FillProcessingVisitor *visitor = new FillProcessingVisitor(nullptr,
1027 fillMask,
1028 resources);
1029
1030 visitor->setSeedPoint(imgCursorPos);
1031 visitor->setSelectionOnly(true);
1032 visitor->setProgressHelper(progressHelper);
1033 visitor->setOutDirtyRect(dirtyRect);
1034
1035 image()->addJob(
1036 fillStrokeId,
1038 KUndo2CommandSP(new KisProcessingCommand(visitor, currentNode())),
1039 false,
1042 )
1043 );
1044 }
1045 }
1046 }
1047
1048 image()->addJob(
1049 fillStrokeId,
1051 KUndo2CommandSP(new KisUpdateCommand(d->viewManager->activeNode(), dirtyRect, image().data())),
1052 false,
1055 )
1056 );
1057
1058 image()->endStroke(fillStrokeId);
1059 }
1060}
1061
1062void KisView::dragMoveEvent(QDragMoveEvent *event)
1063{
1064 dbgUI << Q_FUNC_INFO
1065 << "Formats: " << event->mimeData()->formats()
1066 << "Urls: " << event->mimeData()->urls()
1067 << "Has images: " << event->mimeData()->hasImage();
1068
1069 if (shouldAcceptDrag(event)) {
1070 event->accept();
1071 } else {
1072 event->ignore();
1073 }
1074}
1075
1077{
1078 return d->document;
1079}
1080
1082{
1083 KisMainWindow *window = mainWindow();
1084 QMdiSubWindow *subWindow = d->subWindow;
1085 delete this;
1086 return window->newView(document, subWindow);
1087}
1088
1090{
1091 return d->viewManager->mainWindow();
1092}
1093
1094void KisView::setSubWindow(QMdiSubWindow *subWindow)
1095{
1096 d->subWindow = subWindow;
1097}
1098
1099QStatusBar * KisView::statusBar() const
1100{
1101 KisMainWindow *mw = mainWindow();
1102 return mw ? mw->statusBar() : 0;
1103}
1104
1105void KisView::slotSavingStatusMessage(const QString &text, int timeout, bool isAutoSaving)
1106{
1107 QStatusBar *sb = statusBar();
1108 if (sb) {
1109 sb->showMessage(text, timeout);
1110 }
1111
1112 KisConfig cfg(true);
1113
1114 if (!sb || sb->isHidden() ||
1115 (!isAutoSaving && cfg.forceShowSaveMessages()) ||
1116 (cfg.forceShowAutosaveMessages() && isAutoSaving)) {
1117
1118 viewManager()->showFloatingMessage(text, QIcon());
1119 }
1120}
1121
1123{
1124 QStatusBar *sb = statusBar();
1125 if (sb) {
1126 sb->clearMessage();
1127 }
1128}
1129
1131{
1132 UnitActionGroup* unitActions = new UnitActionGroup(d->document, addPixelUnit, this);
1133 return unitActions->actions();
1134}
1135
1136void KisView::closeEvent(QCloseEvent *event)
1137{
1138 // Check whether we're the last view
1139 int viewCount = KisPart::instance()->viewCount(document());
1140 if (viewCount > 1) {
1141 // there are others still, so don't bother the user
1142 event->accept();
1143 return;
1144 }
1145
1146 if (queryClose()) {
1147 event->accept();
1148 return;
1149 }
1150
1151 event->ignore();
1152
1153}
1154
1156{
1157 if (!document())
1158 return true;
1159
1160 document()->waitForSavingToComplete();
1161
1162 if (document()->isModified()) {
1163 QString name;
1164 name = QFileInfo(document()->path()).fileName();
1165
1166 if (name.isEmpty())
1167 name = i18n("Untitled");
1168
1169 int res = QMessageBox::warning(this,
1170 i18nc("@title:window", "Krita"),
1171 i18n("<p>The document <b>'%1'</b> has been modified.</p><p>Do you want to save it?</p>", name),
1172 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes);
1173
1174 switch (res) {
1175 case QMessageBox::Yes : {
1176 bool isNative = (document()->mimeType() == document()->nativeFormatMimeType());
1177 if (!viewManager()->mainWindow()->saveDocument(document(), !isNative, false))
1178 return false;
1179 break;
1180 }
1181 case QMessageBox::No : {
1182 KisImageSP image = document()->image();
1185
1186 document()->removeAutoSaveFiles(document()->localFilePath(), document()->isRecovered());
1187 document()->setModified(false); // Now when queryClose() is called by closeEvent it won't do anything.
1188 break;
1189 }
1190 default : // case QMessageBox::Cancel :
1191 return false;
1192 }
1193 }
1194
1195 return true;
1196
1197}
1198
1200{
1201 d->canvas.slotScreenChanged(screen);
1202}
1203
1205{
1210 d->canvasController.updateScreenResolution(this);
1211
1212 if (d->canvas.resourceManager() && d->screenMigrationTracker.currentScreen()) {
1213 int penWidth = qRound(d->screenMigrationTracker.currentScreen()->devicePixelRatio());
1214 d->canvas.resourceManager()->setDecorationThickness(qMax(penWidth, 1));
1215 }
1216}
1217
1219{
1220 return d->screenMigrationTracker.currentScreen();
1221}
1222
1224{
1225 this->setPalette(pal);
1226 for (int i=0; i<this->children().size();i++) {
1227 QWidget *w = qobject_cast<QWidget*> ( this->children().at(i));
1228 if (w) {
1229 w->setPalette(pal);
1230 }
1231 }
1232 if (canvasBase()) {
1233 canvasBase()->canvasWidget()->setPalette(pal);
1234 }
1235 if (canvasController()) {
1236 canvasController()->setPalette(pal);
1237 }
1238}
1239
1241{
1242 QString title = d->document->caption();
1243
1244 if (!d->document->isReadWrite()) {
1245 title += " " + i18n("Write Protected");
1246 }
1247
1248 if (d->document->isRecovered()) {
1249 title += " " + i18n("Recovered");
1250 }
1251
1252 // show the file size for the document
1254
1255 if (fileSizeStats.imageSize) {
1256 title += QString(" (").append( KFormat().formatByteSize(qreal(fileSizeStats.imageSize))).append( ") ");
1257 }
1258
1259 title += "[*]";
1260
1261 this->setWindowTitle(title);
1262}
1263
1265{
1266 KisDocument *doc = document();
1267 if (doc) {
1268 doc->setPreActivatedNode(d->currentNode);
1269 }
1270}
1271
1273{
1274 config.setProperty("file", d->document->path());
1275 config.setProperty("window", mainWindow()->windowStateConfig().name());
1276
1277 if (d->subWindow) {
1278 config.setProperty("geometry", d->subWindow->saveGeometry().toBase64());
1279 }
1280
1281 const KoZoomState zoomState = d->canvasController.zoomState();
1282
1283 config.setProperty("zoomMode", zoomState.mode);
1284 config.setProperty("zoom", zoomState.zoom);
1285
1286 d->canvasController.saveCanvasState(config);
1287}
1288
1290{
1291 if (d->subWindow) {
1292 QByteArray geometry = QByteArray::fromBase64(config.getString("geometry", "").toLatin1());
1293 d->subWindow->restoreGeometry(QByteArray::fromBase64(geometry));
1294 }
1295
1296 qreal zoom = config.getFloat("zoom", 1.0f);
1297 int zoomMode = config.getInt("zoomMode", (int)KoZoomMode::ZOOM_PAGE);
1298 d->canvasController.setZoom((KoZoomMode::Mode)zoomMode, zoom);
1299 d->canvasController.restoreCanvasState(config);
1300}
1301
1303{
1304 d->currentNode = node;
1306
1308}
1309
1311{
1312 return d->currentNode;
1313}
1314
1316{
1317 KisNodeSP node;
1318 KisMaskSP mask = currentMask();
1319 if (mask) {
1320 node = mask->parent();
1321 }
1322 else {
1323 node = d->currentNode;
1324 }
1325 return qobject_cast<KisLayer*>(node.data());
1326}
1327
1329{
1330 return dynamic_cast<KisMask*>(d->currentNode.data());
1331}
1332
1334{
1335 KisLayerSP layer = currentLayer();
1336 if (layer)
1337 return layer->selection(); // falls through to the global
1338 // selection, or 0 in the end
1339 if (image()) {
1340 return image()->globalSelection();
1341 }
1342 return 0;
1343}
1344
1345void KisView::slotSoftProofing(bool softProofing)
1346{
1347 d->softProofing = softProofing;
1348 QString message;
1349 if (canvasBase()->image()->colorSpace()->colorDepthId().id().contains("F"))
1350 {
1351 message = i18n("Soft Proofing doesn't work in floating point.");
1352 viewManager()->showFloatingMessage(message,QIcon());
1353 return;
1354 }
1355 if (softProofing){
1356 message = i18n("Soft Proofing turned on.");
1357 } else {
1358 message = i18n("Soft Proofing turned off.");
1359 }
1360 viewManager()->showFloatingMessage(message,QIcon());
1362}
1363
1364void KisView::slotGamutCheck(bool gamutCheck)
1365{
1366 d->gamutCheck = gamutCheck;
1367 QString message;
1368 if (canvasBase()->image()->colorSpace()->colorDepthId().id().contains("F"))
1369 {
1370 message = i18n("Gamut Warnings don't work in floating point.");
1371 viewManager()->showFloatingMessage(message,QIcon());
1372 return;
1373 }
1374
1375 if (gamutCheck){
1376 message = i18n("Gamut Warnings turned on.");
1377 if (!d->softProofing){
1378 message += "\n "+i18n("But Soft Proofing is still off.");
1379 }
1380 } else {
1381 message = i18n("Gamut Warnings turned off.");
1382 }
1383 viewManager()->showFloatingMessage(message,QIcon());
1385}
1386
1388{
1389 return d->softProofing;
1390}
1391
1393{
1394 return d->gamutCheck;
1395}
1396
1398{
1399 if (!document()) return;
1400
1405
1406 if (image()->locked()) {
1407 // If this is the first view on the image, the image will have been locked
1408 // so unlock it.
1409 image()->blockSignals(false);
1410 image()->unlock();
1411 }
1412
1414
1415 connect(image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), this, SIGNAL(sigColorSpaceChanged(const KoColorSpace*)));
1416 connect(image(), SIGNAL(sigProfileChanged(const KoColorProfile*)), this, SIGNAL(sigProfileChanged(const KoColorProfile*)));
1417 connect(image(), SIGNAL(sigSizeChanged(QPointF,QPointF)), this, SIGNAL(sigSizeChanged(QPointF,QPointF)));
1418
1419 connect(&d->screenMigrationTracker, SIGNAL(sigScreenChanged(QScreen*)), this, SLOT(slotMigratedToScreen(QScreen*)));
1420 connect(&d->screenMigrationTracker, SIGNAL(sigScreenOrResolutionChanged(QScreen*)), this, SLOT(slotScreenOrResolutionChanged()));
1422}
1423
1425{
1426 d->canvasController.syncOnImageResolutionChange();
1427 d->zoomManager.syncOnImageResolutionChange();
1429}
1430
1431void KisView::slotImageSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint)
1432{
1433 d->canvasController.syncOnImageSizeChange(oldStillPoint, newStillPoint);
1435}
1436
1438{
1439 d->subWindow->close();
1440}
1441
1442bool KisView::shouldAcceptDrag(const QDropEvent *event) const
1443{
1444 const QMimeData *data = event->mimeData();
1445 if (data->hasFormat(QStringLiteral("application/x-krita-node-internal-pointer"))) {
1446 // Don't allow dragging layers onto their own canvas, that really only
1447 // gets triggered accidentally if you're a bit sloppy about selecting
1448 // or reordering layers and then you're left confused about the layer
1449 // duplicates that seem to show up at random. The user can override
1450 // this by explicitly holding down Ctrl if necessary. We always accept
1451 // the enter event so that this works properly, otherwise we don't get
1452 // any further drag events unless Ctrl was held to begin with.
1453 return event->type() == QEvent::DragEnter
1454 || event->keyboardModifiers().testFlag(Qt::ControlModifier)
1456 } else {
1457 return data->hasImage()
1458 || data->hasUrls()
1459 || data->hasFormat("krita/x-colorsetentry")
1460 || data->hasColor();
1461 }
1462}
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
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 bool isNodeMimeDataFromSameImage(const QMimeData *data, KisImageSP image)
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:320
int viewCount(KisDocument *doc) const
Definition KisPart.cpp:356
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:1218
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:1364
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:1223
static bool s_firstView
Definition KisView.h:266
QString newObjectName()
Definition KisView.cpp:93
void dropEvent(QDropEvent *event) override
Definition KisView.cpp:461
KisMainWindow * mainWindow() const
Definition KisView.cpp:1089
void syncLastActiveNodeToDocument()
Definition KisView.cpp:1264
void notifyCurrentStateChanged(bool isCurrent)
Definition KisView.cpp:282
bool gamutCheck
Definition KisView.cpp:140
void restoreViewState(const KisPropertiesConfiguration &config)
Definition KisView.cpp:1289
void slotClearStatusText()
Definition KisView.cpp:1122
void closeView()
Definition KisView.cpp:1437
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:1130
KisCanvasController canvasController
Definition KisView.cpp:126
Private *const d
Definition KisView.h:264
QMdiSubWindow * subWindow
Definition KisView.cpp:137
void slotScreenOrResolutionChanged()
Definition KisView.cpp:1204
bool softProofing
Definition KisView.cpp:139
KisCoordinatesConverter viewConverter
Definition KisView.cpp:125
void setSubWindow(QMdiSubWindow *subWindow)
Definition KisView.cpp:1094
void sigColorSpaceChanged(const KoColorSpace *cs)
QStatusBar * statusBar() const
Definition KisView.cpp:1099
void dragMoveEvent(QDragMoveEvent *event) override
Definition KisView.cpp:1062
KisMaskSP currentMask() const
Definition KisView.cpp:1328
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:1105
KisView * replaceBy(KisDocument *document)
Definition KisView.cpp:1081
KisCanvasResourceProvider * resourceProvider() const
Definition KisView.cpp:414
void slotContinueAddNode(KisNodeSP newActiveNode, KisNodeAdditionFlags flags)
Definition KisView.cpp:372
void slotMigratedToScreen(QScreen *screen)
Definition KisView.cpp:1199
void closeEvent(QCloseEvent *event) override
Definition KisView.cpp:1136
QPointer< KisDocument > document
Definition KisView.cpp:121
void slotLoadingFinished()
Definition KisView.cpp:1397
void slotImageNodeRemoved(KisNodeSP node)
Definition KisView.cpp:392
void setViewManager(KisViewManager *view)
Definition KisView.cpp:337
bool shouldAcceptDrag(const QDropEvent *event) const
Definition KisView.cpp:1442
void saveViewState(KisPropertiesConfiguration &config) const
Definition KisView.cpp:1272
void slotUpdateDocumentTitle()
Definition KisView.cpp:1240
bool queryClose()
Definition KisView.cpp:1155
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:1345
KisNodeSP currentNode
Definition KisView.cpp:130
void slotImageResolutionChanged()
Definition KisView.cpp:1424
KisSelectionSP selection()
Definition KisView.cpp:1333
KisSynchronizedConnection< KisNodeSP > removeNodeConnection
Definition KisView.cpp:143
void slotImageSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint)
Definition KisView.cpp:1431
KisLayerSP currentLayer() const
Definition KisView.cpp:1315
void setCurrentNode(KisNodeSP node)
Definition KisView.cpp:1302
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