diff --git a/libs/ui/canvas/kis_abstract_canvas_widget.h b/libs/ui/canvas/kis_abstract_canvas_widget.h index 15ef84ed3b..46e2cb4401 100644 --- a/libs/ui/canvas/kis_abstract_canvas_widget.h +++ b/libs/ui/canvas/kis_abstract_canvas_widget.h @@ -1,91 +1,92 @@ /* * Copyright (C) 2007 Boudewijn Rempt , (C) * Copyright (C) 2015 Michael Abrahams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_ABSTRACT_CANVAS_WIDGET_ #define _KIS_ABSTRACT_CANVAS_WIDGET_ class QWidget; class QRect; class QPainter; class QRect; class KoToolProxy; #include class KisDisplayFilter; class KisDisplayColorConverter; class QBitArray; #include "kis_types.h" #include "kis_ui_types.h" class KisAbstractCanvasWidget { public: KisAbstractCanvasWidget() {} virtual ~KisAbstractCanvasWidget() {} virtual QWidget * widget() = 0; virtual KoToolProxy * toolProxy() const = 0; /// Draw the specified decorations on the view. virtual void drawDecorations(QPainter & gc, const QRect &updateWidgetRect) const = 0; virtual void addDecoration(KisCanvasDecorationSP deco) = 0; + virtual void removeDecoration(const QString& id) = 0; virtual KisCanvasDecorationSP decoration(const QString& id) const = 0; virtual void setDecorations(const QList &) = 0; virtual QList decorations() const = 0; /// set the specified display filter on the canvas virtual void setDisplayFilter(QSharedPointer displayFilter) = 0; virtual void setWrapAroundViewingMode(bool value) = 0; // Called from KisCanvas2::channelSelectionChanged virtual void channelSelectionChanged(const QBitArray &channelFlags) = 0; // Called from KisCanvas2::slotSetDisplayProfile virtual void setDisplayProfile(KisDisplayColorConverter *colorConverter) = 0; // Called from KisCanvas2::finishResizingImage virtual void finishResizingImage(qint32 w, qint32 h) = 0; // Called from KisCanvas2::startUpdateProjection virtual KisUpdateInfoSP startUpdateCanvasProjection(const QRect & rc, const QBitArray &channelFlags) = 0; // Called from KisCanvas2::updateCanvasProjection virtual QRect updateCanvasProjection(KisUpdateInfoSP info) = 0; /** * Returns true if the asynchromous engine of the canvas * (e.g. openGL pipeline) is busy with processing of the previous * update events. This will make KisCanvas2 to postpone and * compress update events. */ virtual bool isBusy() const = 0; }; #endif // _KIS_ABSTRACT_CANVAS_WIDGET_ diff --git a/libs/ui/canvas/kis_canvas2.cpp b/libs/ui/canvas/kis_canvas2.cpp index d06f36791e..5e5289c40c 100644 --- a/libs/ui/canvas/kis_canvas2.cpp +++ b/libs/ui/canvas/kis_canvas2.cpp @@ -1,1014 +1,1033 @@ /* This file is part of the KDE project * * Copyright (C) 2006, 2010 Boudewijn Rempt * Copyright (C) Lukáš Tvrdý , (C) 2010 * Copyright (C) 2011 Silvio Heinrich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.. */ #include "kis_canvas2.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_tool_proxy.h" #include "kis_coordinates_converter.h" #include "kis_prescaled_projection.h" #include "kis_image.h" #include "kis_image_barrier_locker.h" #include "kis_undo_adapter.h" #include "KisDocument.h" #include "flake/kis_shape_layer.h" #include "kis_canvas_resource_provider.h" #include "KisViewManager.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_abstract_canvas_widget.h" #include "kis_qpainter_canvas.h" #include "kis_group_layer.h" #include "flake/kis_shape_controller.h" #include "kis_node_manager.h" #include "kis_selection.h" #include "kis_selection_component.h" #include "flake/kis_shape_selection.h" #include "kis_image_config.h" #include "kis_infinity_manager.h" #include "kis_signal_compressor.h" #include "kis_display_color_converter.h" #include "kis_exposure_gamma_correction_interface.h" #include "KisView.h" #include "kis_canvas_controller.h" #include "kis_grid_config.h" #include "kis_animation_player.h" #include "kis_animation_frame_cache.h" #include "opengl/kis_opengl_canvas2.h" #include "opengl/kis_opengl.h" #include "kis_fps_decoration.h" #include "KoColorConversionTransformation.h" #include "KisProofingConfiguration.h" #include #include #include "input/kis_input_manager.h" #include "kis_painting_assistants_decoration.h" #include "kis_canvas_updates_compressor.h" #include "KoZoomController.h" +#include +#include "opengl/kis_opengl_canvas_debugger.h" class Q_DECL_HIDDEN KisCanvas2::KisCanvas2Private { public: KisCanvas2Private(KoCanvasBase *parent, KisCoordinatesConverter* coordConverter, QPointer view, KoCanvasResourceManager* resourceManager) : coordinatesConverter(coordConverter) , view(view) , shapeManager(parent) , selectedShapesProxy(&shapeManager) , toolProxy(parent) , displayColorConverter(resourceManager, view) { } KisCoordinatesConverter *coordinatesConverter; QPointerview; KisAbstractCanvasWidget *canvasWidget = 0; KoShapeManager shapeManager; KisSelectedShapesProxy selectedShapesProxy; bool currentCanvasIsOpenGL; int openGLFilterMode; KisToolProxy toolProxy; KisPrescaledProjectionSP prescaledProjection; bool vastScrolling; KisSignalCompressor updateSignalCompressor; QRect savedUpdateRect; QBitArray channelFlags; KisProofingConfigurationSP proofingConfig; bool softProofing = false; bool gamutCheck = false; bool proofingConfigUpdated = false; KisPopupPalette *popupPalette = 0; KisDisplayColorConverter displayColorConverter; KisCanvasUpdatesCompressor projectionUpdatesCompressor; KisAnimationPlayer *animationPlayer; KisAnimationFrameCacheSP frameCache; bool lodAllowedInCanvas; bool bootstrapLodBlocked; QPointer currentlyActiveShapeManager; bool effectiveLodAllowedInCanvas() { return lodAllowedInCanvas && !bootstrapLodBlocked; } }; namespace { KoShapeManager* fetchShapeManagerFromNode(KisNodeSP node) { KoShapeManager *shapeManager = 0; KisLayer *layer = dynamic_cast(node.data()); if (layer) { KisShapeLayer *shapeLayer = dynamic_cast(layer); if (shapeLayer) { shapeManager = shapeLayer->shapeManager(); } else { KisSelectionSP selection = layer->selection(); if (selection && selection->hasShapeSelection()) { KisShapeSelection *shapeSelection = dynamic_cast(selection->shapeSelection()); KIS_ASSERT_RECOVER_RETURN_VALUE(shapeSelection, 0); shapeManager = shapeSelection->shapeManager(); } } } return shapeManager; } } KisCanvas2::KisCanvas2(KisCoordinatesConverter *coordConverter, KoCanvasResourceManager *resourceManager, KisView *view, KoShapeBasedDocumentBase *sc) : KoCanvasBase(sc, resourceManager) , m_d(new KisCanvas2Private(this, coordConverter, view, resourceManager)) { /** * While loading LoD should be blocked. Only when GUI has finished * loading and zoom level settled down, LoD is given a green * light. */ m_d->bootstrapLodBlocked = true; connect(view->mainWindow(), SIGNAL(guiLoadingFinished()), SLOT(bootstrapFinished())); m_d->updateSignalCompressor.setDelay(10); m_d->updateSignalCompressor.setMode(KisSignalCompressor::FIRST_ACTIVE); } void KisCanvas2::setup() { // a bit of duplication from slotConfigChanged() KisConfig cfg; m_d->vastScrolling = cfg.vastScrolling(); m_d->lodAllowedInCanvas = cfg.levelOfDetailEnabled(); createCanvas(cfg.useOpenGL()); setLodAllowedInCanvas(m_d->lodAllowedInCanvas); m_d->animationPlayer = new KisAnimationPlayer(this); connect(m_d->view->canvasController()->proxyObject, SIGNAL(moveDocumentOffset(QPoint)), SLOT(documentOffsetMoved(QPoint))); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged())); /** * We switch the shape manager every time vector layer or * shape selection is activated. Flake does not expect this * and connects all the signals of the global shape manager * to the clients in the constructor. To workaround this we * forward the signals of local shape managers stored in the * vector layers to the signals of global shape manager. So the * sequence of signal deliveries is the following: * * shapeLayer.m_d.canvas.m_shapeManager.selection() -> * shapeLayer -> * shapeController -> * globalShapeManager.selection() */ KisShapeController *kritaShapeController = static_cast(shapeController()->documentBase()); connect(kritaShapeController, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged())); connect(kritaShapeController, SIGNAL(selectionContentChanged()), globalShapeManager(), SIGNAL(selectionContentChanged())); connect(kritaShapeController, SIGNAL(currentLayerChanged(const KoShapeLayer*)), globalShapeManager()->selection(), SIGNAL(currentLayerChanged(const KoShapeLayer*))); connect(&m_d->updateSignalCompressor, SIGNAL(timeout()), SLOT(slotDoCanvasUpdate())); + + initializeFpsDecoration(); +} + +void KisCanvas2::initializeFpsDecoration() +{ + const bool shouldShowDebugOverlay = + (canvasIsOpenGL() && KisOpenglCanvasDebugger::instance()->showFpsOnCanvas()) || + KisStrokeSpeedMonitor::instance()->haveStrokeSpeedMeasurement(); + + if (shouldShowDebugOverlay && !decoration(KisFpsDecoration::idTag)) { + addDecoration(new KisFpsDecoration(imageView())); + + if (KisStrokeSpeedMonitor::instance()->haveStrokeSpeedMeasurement()) { + connect(KisStrokeSpeedMonitor::instance(), SIGNAL(sigStatsUpdated()), this, SLOT(updateCanvas())); + } + } else if (!shouldShowDebugOverlay && decoration(KisFpsDecoration::idTag)) { + m_d->canvasWidget->removeDecoration(KisFpsDecoration::idTag); + disconnect(KisStrokeSpeedMonitor::instance(), SIGNAL(sigStatsUpdated()), this, SLOT(updateCanvas())); + } } KisCanvas2::~KisCanvas2() { if (m_d->animationPlayer->isPlaying()) { m_d->animationPlayer->forcedStopOnExit(); } delete m_d; } void KisCanvas2::setCanvasWidget(QWidget * widget) { KisAbstractCanvasWidget *tmp = dynamic_cast(widget); Q_ASSERT_X(tmp, "setCanvasWidget", "Cannot cast the widget to a KisAbstractCanvasWidget"); if (m_d->popupPalette) { m_d->popupPalette->setParent(widget); } if(m_d->canvasWidget != 0) { tmp->setDecorations(m_d->canvasWidget->decorations()); // Redundant check for the constructor case, see below if(viewManager() != 0) viewManager()->inputManager()->removeTrackedCanvas(this); } m_d->canvasWidget = tmp; // Either tmp was null or we are being called by KisCanvas2 constructor that is called by KisView // constructor, so the view manager still doesn't exists. if(m_d->canvasWidget != 0 && viewManager() != 0) viewManager()->inputManager()->addTrackedCanvas(this); if (!m_d->canvasWidget->decoration(INFINITY_DECORATION_ID)) { KisInfinityManager *manager = new KisInfinityManager(m_d->view, this); manager->setVisible(true); m_d->canvasWidget->addDecoration(manager); } widget->setAutoFillBackground(false); widget->setAttribute(Qt::WA_OpaquePaintEvent); widget->setMouseTracking(true); widget->setAcceptDrops(true); KoCanvasControllerWidget *controller = dynamic_cast(canvasController()); if (controller) { Q_ASSERT(controller->canvas() == this); controller->changeCanvasWidget(widget); } } bool KisCanvas2::canvasIsOpenGL() const { return m_d->currentCanvasIsOpenGL; } KisOpenGL::FilterMode KisCanvas2::openGLFilterMode() const { return KisOpenGL::FilterMode(m_d->openGLFilterMode); } void KisCanvas2::gridSize(QPointF *offset, QSizeF *spacing) const { QTransform transform = coordinatesConverter()->imageToDocumentTransform(); const QPoint intSpacing = m_d->view->document()->gridConfig().spacing(); const QPoint intOffset = m_d->view->document()->gridConfig().offset(); QPointF size = transform.map(QPointF(intSpacing)); spacing->rwidth() = size.x(); spacing->rheight() = size.y(); *offset = transform.map(QPointF(intOffset)); } bool KisCanvas2::snapToGrid() const { return m_d->view->document()->gridConfig().snapToGrid(); } qreal KisCanvas2::rotationAngle() const { return m_d->coordinatesConverter->rotationAngle(); } bool KisCanvas2::xAxisMirrored() const { return m_d->coordinatesConverter->xAxisMirrored(); } bool KisCanvas2::yAxisMirrored() const { return m_d->coordinatesConverter->yAxisMirrored(); } void KisCanvas2::channelSelectionChanged() { KisImageSP image = this->image(); m_d->channelFlags = image->rootLayer()->channelFlags(); m_d->view->viewManager()->blockUntilOperationsFinishedForced(image); image->barrierLock(); m_d->canvasWidget->channelSelectionChanged(m_d->channelFlags); startUpdateInPatches(image->bounds()); image->unlock(); } void KisCanvas2::addCommand(KUndo2Command *command) { // This method exists to support flake-related operations m_d->view->document()->addCommand(command); } KoShapeManager* KisCanvas2::shapeManager() const { KisNodeSP node = m_d->view->currentNode(); KoShapeManager *localShapeManager = fetchShapeManagerFromNode(node); // sanity check for consistency of the local shape manager KIS_SAFE_ASSERT_RECOVER (localShapeManager == m_d->currentlyActiveShapeManager) { localShapeManager = globalShapeManager(); } return localShapeManager ? localShapeManager : globalShapeManager(); } KoSelectedShapesProxy* KisCanvas2::selectedShapesProxy() const { return &m_d->selectedShapesProxy; } KoShapeManager* KisCanvas2::globalShapeManager() const { return &m_d->shapeManager; } void KisCanvas2::updateInputMethodInfo() { // TODO call (the protected) QWidget::updateMicroFocus() on the proper canvas widget... } const KisCoordinatesConverter* KisCanvas2::coordinatesConverter() const { return m_d->coordinatesConverter; } KoViewConverter* KisCanvas2::viewConverter() const { return m_d->coordinatesConverter; } KisInputManager* KisCanvas2::globalInputManager() const { return m_d->view->globalInputManager(); } QWidget* KisCanvas2::canvasWidget() { return m_d->canvasWidget->widget(); } const QWidget* KisCanvas2::canvasWidget() const { return m_d->canvasWidget->widget(); } KoUnit KisCanvas2::unit() const { KoUnit unit(KoUnit::Pixel); KisImageWSP image = m_d->view->image(); if (image) { if (!qFuzzyCompare(image->xRes(), image->yRes())) { warnKrita << "WARNING: resolution of the image is anisotropic" << ppVar(image->xRes()) << ppVar(image->yRes()); } const qreal resolution = image->xRes(); unit.setFactor(resolution); } return unit; } KoToolProxy * KisCanvas2::toolProxy() const { return &m_d->toolProxy; } void KisCanvas2::createQPainterCanvas() { m_d->currentCanvasIsOpenGL = false; KisQPainterCanvas * canvasWidget = new KisQPainterCanvas(this, m_d->coordinatesConverter, m_d->view); m_d->prescaledProjection = new KisPrescaledProjection(); m_d->prescaledProjection->setCoordinatesConverter(m_d->coordinatesConverter); m_d->prescaledProjection->setMonitorProfile(m_d->displayColorConverter.monitorProfile(), m_d->displayColorConverter.renderingIntent(), m_d->displayColorConverter.conversionFlags()); m_d->prescaledProjection->setDisplayFilter(m_d->displayColorConverter.displayFilter()); canvasWidget->setPrescaledProjection(m_d->prescaledProjection); setCanvasWidget(canvasWidget); } void KisCanvas2::createOpenGLCanvas() { KisConfig cfg; m_d->openGLFilterMode = cfg.openGLFilteringMode(); m_d->currentCanvasIsOpenGL = true; KisOpenGLCanvas2 *canvasWidget = new KisOpenGLCanvas2(this, m_d->coordinatesConverter, 0, m_d->view->image(), &m_d->displayColorConverter); m_d->frameCache = KisAnimationFrameCache::getFrameCache(canvasWidget->openGLImageTextures()); setCanvasWidget(canvasWidget); - - if (canvasWidget->needsFpsDebugging() && !decoration(KisFpsDecoration::idTag)) { - addDecoration(new KisFpsDecoration(imageView())); - } } void KisCanvas2::createCanvas(bool useOpenGL) { // deinitialize previous canvas structures m_d->prescaledProjection = 0; m_d->frameCache = 0; KisConfig cfg; QDesktopWidget dw; const KoColorProfile *profile = cfg.displayProfile(dw.screenNumber(imageView())); m_d->displayColorConverter.setMonitorProfile(profile); if (useOpenGL) { if (KisOpenGL::hasOpenGL()) { createOpenGLCanvas(); if (cfg.canvasState() == "OPENGL_FAILED") { // Creating the opengl canvas failed, fall back warnKrita << "OpenGL Canvas initialization returned OPENGL_FAILED. Falling back to QPainter."; createQPainterCanvas(); } } else { warnKrita << "Tried to create OpenGL widget when system doesn't have OpenGL\n"; createQPainterCanvas(); } } else { createQPainterCanvas(); } if (m_d->popupPalette) { m_d->popupPalette->setParent(m_d->canvasWidget->widget()); } } void KisCanvas2::initializeImage() { KisImageSP image = m_d->view->image(); m_d->coordinatesConverter->setImage(image); m_d->toolProxy.initializeImage(image); connect(image, SIGNAL(sigImageUpdated(QRect)), SLOT(startUpdateCanvasProjection(QRect)), Qt::DirectConnection); connect(this, SIGNAL(sigCanvasCacheUpdated()), SLOT(updateCanvasProjection())); connect(image, SIGNAL(sigProofingConfigChanged()), SLOT(slotChangeProofingConfig())); connect(image, SIGNAL(sigSizeChanged(const QPointF&, const QPointF&)), SLOT(startResizingImage()), Qt::DirectConnection); connect(this, SIGNAL(sigContinueResizeImage(qint32,qint32)), SLOT(finishResizingImage(qint32,qint32))); connect(image->undoAdapter(), SIGNAL(selectionChanged()), SLOT(slotTrySwitchShapeManager())); connectCurrentCanvas(); } void KisCanvas2::connectCurrentCanvas() { KisImageWSP image = m_d->view->image(); if (!m_d->currentCanvasIsOpenGL) { Q_ASSERT(m_d->prescaledProjection); m_d->prescaledProjection->setImage(image); } startResizingImage(); emit imageChanged(image); setLodAllowedInCanvas(m_d->lodAllowedInCanvas); } void KisCanvas2::resetCanvas(bool useOpenGL) { // we cannot reset the canvas before it's created, but this method might be called, // for instance when setting the monitor profile. if (!m_d->canvasWidget) { return; } KisConfig cfg; bool needReset = (m_d->currentCanvasIsOpenGL != useOpenGL) || (m_d->currentCanvasIsOpenGL && m_d->openGLFilterMode != cfg.openGLFilteringMode()); if (needReset) { createCanvas(useOpenGL); connectCurrentCanvas(); notifyZoomChanged(); } updateCanvasWidgetImpl(); } void KisCanvas2::startUpdateInPatches(const QRect &imageRect) { if (m_d->currentCanvasIsOpenGL) { startUpdateCanvasProjection(imageRect); } else { KisImageConfig imageConfig; int patchWidth = imageConfig.updatePatchWidth(); int patchHeight = imageConfig.updatePatchHeight(); for (int y = 0; y < imageRect.height(); y += patchHeight) { for (int x = 0; x < imageRect.width(); x += patchWidth) { QRect patchRect(x, y, patchWidth, patchHeight); startUpdateCanvasProjection(patchRect); } } } } void KisCanvas2::setDisplayFilter(QSharedPointer displayFilter) { m_d->displayColorConverter.setDisplayFilter(displayFilter); KisImageSP image = this->image(); m_d->view->viewManager()->blockUntilOperationsFinishedForced(image); image->barrierLock(); m_d->canvasWidget->setDisplayFilter(displayFilter); image->unlock(); } QSharedPointer KisCanvas2::displayFilter() const { return m_d->displayColorConverter.displayFilter(); } KisDisplayColorConverter* KisCanvas2::displayColorConverter() const { return &m_d->displayColorConverter; } KisExposureGammaCorrectionInterface* KisCanvas2::exposureGammaCorrectionInterface() const { QSharedPointer displayFilter = m_d->displayColorConverter.displayFilter(); return displayFilter ? displayFilter->correctionInterface() : KisDumbExposureGammaCorrectionInterface::instance(); } void KisCanvas2::setProofingOptions(bool softProof, bool gamutCheck) { m_d->proofingConfig = this->image()->proofingConfiguration(); if (!m_d->proofingConfig) { qDebug()<<"Canvas: No proofing config found, generating one."; KisImageConfig cfg; m_d->proofingConfig = cfg.defaultProofingconfiguration(); } KoColorConversionTransformation::ConversionFlags conversionFlags = m_d->proofingConfig->conversionFlags; if (softProof && this->image()->colorSpace()->colorDepthId().id().contains("U")) { conversionFlags |= KoColorConversionTransformation::SoftProofing; } else { conversionFlags = conversionFlags & ~KoColorConversionTransformation::SoftProofing; } if (gamutCheck && softProof && this->image()->colorSpace()->colorDepthId().id().contains("U")) { conversionFlags |= KoColorConversionTransformation::GamutCheck; } else { conversionFlags = conversionFlags & ~KoColorConversionTransformation::GamutCheck; } m_d->proofingConfig->conversionFlags = conversionFlags; m_d->proofingConfigUpdated = true; startUpdateInPatches(this->image()->bounds()); } void KisCanvas2::slotSoftProofing(bool softProofing) { m_d->softProofing = softProofing; setProofingOptions(m_d->softProofing, m_d->gamutCheck); } void KisCanvas2::slotGamutCheck(bool gamutCheck) { m_d->gamutCheck = gamutCheck; setProofingOptions(m_d->softProofing, m_d->gamutCheck); } void KisCanvas2::slotChangeProofingConfig() { setProofingOptions(m_d->softProofing, m_d->gamutCheck); } void KisCanvas2::setProofingConfigUpdated(bool updated) { m_d->proofingConfigUpdated = updated; } bool KisCanvas2::proofingConfigUpdated() { return m_d->proofingConfigUpdated; } KisProofingConfigurationSP KisCanvas2::proofingConfiguration() const { if (!m_d->proofingConfig) { m_d->proofingConfig = this->image()->proofingConfiguration(); if (!m_d->proofingConfig) { qDebug()<<"Canvas: No proofing config found, generating one."; KisImageConfig cfg; m_d->proofingConfig = cfg.defaultProofingconfiguration(); } } return m_d->proofingConfig; } void KisCanvas2::startResizingImage() { KisImageWSP image = this->image(); qint32 w = image->width(); qint32 h = image->height(); emit sigContinueResizeImage(w, h); QRect imageBounds(0, 0, w, h); startUpdateInPatches(imageBounds); } void KisCanvas2::finishResizingImage(qint32 w, qint32 h) { m_d->canvasWidget->finishResizingImage(w, h); } void KisCanvas2::startUpdateCanvasProjection(const QRect & rc) { KisUpdateInfoSP info = m_d->canvasWidget->startUpdateCanvasProjection(rc, m_d->channelFlags); if (m_d->projectionUpdatesCompressor.putUpdateInfo(info)) { emit sigCanvasCacheUpdated(); } } void KisCanvas2::updateCanvasProjection() { while (KisUpdateInfoSP info = m_d->projectionUpdatesCompressor.takeUpdateInfo()) { QRect vRect = m_d->canvasWidget->updateCanvasProjection(info); if (!vRect.isEmpty()) { updateCanvasWidgetImpl(m_d->coordinatesConverter->viewportToWidget(vRect).toAlignedRect()); } } // TODO: Implement info->dirtyViewportRect() for KisOpenGLCanvas2 to avoid updating whole canvas if (m_d->currentCanvasIsOpenGL) { updateCanvasWidgetImpl(); } } void KisCanvas2::slotDoCanvasUpdate() { if (m_d->canvasWidget->isBusy()) { // just restarting the timer updateCanvasWidgetImpl(m_d->savedUpdateRect); return; } if (m_d->savedUpdateRect.isEmpty()) { m_d->canvasWidget->widget()->update(); emit updateCanvasRequested(m_d->canvasWidget->widget()->rect()); } else { emit updateCanvasRequested(m_d->savedUpdateRect); m_d->canvasWidget->widget()->update(m_d->savedUpdateRect); } m_d->savedUpdateRect = QRect(); } void KisCanvas2::updateCanvasWidgetImpl(const QRect &rc) { if (!m_d->updateSignalCompressor.isActive() || !m_d->savedUpdateRect.isEmpty()) { m_d->savedUpdateRect |= rc; } m_d->updateSignalCompressor.start(); } void KisCanvas2::updateCanvas() { updateCanvasWidgetImpl(); } void KisCanvas2::updateCanvas(const QRectF& documentRect) { if (m_d->currentCanvasIsOpenGL && m_d->canvasWidget->decorations().size() > 0) { updateCanvasWidgetImpl(); } else { // updateCanvas is called from tools, never from the projection // updates, so no need to prescale! QRect widgetRect = m_d->coordinatesConverter->documentToWidget(documentRect).toAlignedRect(); widgetRect.adjust(-2, -2, 2, 2); if (!widgetRect.isEmpty()) { updateCanvasWidgetImpl(widgetRect); } } } void KisCanvas2::disconnectCanvasObserver(QObject *object) { KoCanvasBase::disconnectCanvasObserver(object); m_d->view->disconnect(object); } void KisCanvas2::notifyZoomChanged() { if (!m_d->currentCanvasIsOpenGL) { Q_ASSERT(m_d->prescaledProjection); m_d->prescaledProjection->notifyZoomChanged(); } notifyLevelOfDetailChange(); updateCanvas(); // update the canvas, because that isn't done when zooming using KoZoomAction } void KisCanvas2::slotTrySwitchShapeManager() { QPointer oldManager = m_d->currentlyActiveShapeManager; KisNodeSP node = m_d->view->currentNode(); QPointer newManager; newManager = fetchShapeManagerFromNode(node); if (newManager != oldManager) { m_d->currentlyActiveShapeManager = newManager; m_d->selectedShapesProxy.setShapeManager(newManager); } } void KisCanvas2::notifyLevelOfDetailChange() { if (!m_d->effectiveLodAllowedInCanvas()) return; KisImageSP image = this->image(); const qreal effectiveZoom = m_d->coordinatesConverter->effectiveZoom(); KisConfig cfg; const int maxLod = cfg.numMipmapLevels(); int lod = KisLodTransform::scaleToLod(effectiveZoom, maxLod); image->setDesiredLevelOfDetail(lod); } const KoColorProfile * KisCanvas2::monitorProfile() { return m_d->displayColorConverter.monitorProfile(); } KisViewManager* KisCanvas2::viewManager() const { if (m_d->view) { return m_d->view->viewManager(); } return 0; } QPointerKisCanvas2::imageView() const { return m_d->view; } KisImageWSP KisCanvas2::image() const { return m_d->view->image(); } KisImageWSP KisCanvas2::currentImage() const { return m_d->view->image(); } void KisCanvas2::documentOffsetMoved(const QPoint &documentOffset) { QPointF offsetBefore = m_d->coordinatesConverter->imageRectInViewportPixels().topLeft(); m_d->coordinatesConverter->setDocumentOffset(documentOffset); QPointF offsetAfter = m_d->coordinatesConverter->imageRectInViewportPixels().topLeft(); QPointF moveOffset = offsetAfter - offsetBefore; if (!m_d->currentCanvasIsOpenGL) m_d->prescaledProjection->viewportMoved(moveOffset); emit documentOffsetUpdateFinished(); updateCanvas(); } void KisCanvas2::slotConfigChanged() { KisConfig cfg; m_d->vastScrolling = cfg.vastScrolling(); resetCanvas(cfg.useOpenGL()); slotSetDisplayProfile(cfg.displayProfile(QApplication::desktop()->screenNumber(this->canvasWidget()))); + initializeFpsDecoration(); } void KisCanvas2::refetchDataFromImage() { KisImageSP image = this->image(); KisImageBarrierLocker l(image); startUpdateInPatches(image->bounds()); } void KisCanvas2::slotSetDisplayProfile(const KoColorProfile *monitorProfile) { if (m_d->displayColorConverter.monitorProfile() == monitorProfile) return; m_d->displayColorConverter.setMonitorProfile(monitorProfile); { KisImageSP image = this->image(); KisImageBarrierLocker l(image); m_d->canvasWidget->setDisplayProfile(&m_d->displayColorConverter); } refetchDataFromImage(); } void KisCanvas2::addDecoration(KisCanvasDecorationSP deco) { m_d->canvasWidget->addDecoration(deco); } KisCanvasDecorationSP KisCanvas2::decoration(const QString& id) const { return m_d->canvasWidget->decoration(id); } QPoint KisCanvas2::documentOrigin() const { /** * In Krita we don't use document origin anymore. * All the centering when needed (vastScrolling < 0.5) is done * automatically by the KisCoordinatesConverter. */ return QPoint(); } QPoint KisCanvas2::documentOffset() const { return m_d->coordinatesConverter->documentOffset(); } void KisCanvas2::setFavoriteResourceManager(KisFavoriteResourceManager* favoriteResourceManager) { m_d->popupPalette = new KisPopupPalette(viewManager(), m_d->coordinatesConverter, favoriteResourceManager, displayColorConverter()->displayRendererInterface(), m_d->view->resourceProvider(), m_d->canvasWidget->widget()); connect(m_d->popupPalette, SIGNAL(zoomLevelChanged(int)), this, SLOT(slotZoomChanged(int))); connect(m_d->popupPalette, SIGNAL(sigUpdateCanvas()), this, SLOT(updateCanvas())); m_d->popupPalette->showPopupPalette(false); } void KisCanvas2::slotZoomChanged(int zoom ) { m_d->view->viewManager()->zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, (qreal)(zoom/100.0)); // 1.0 is 100% zoom notifyZoomChanged(); } void KisCanvas2::setCursor(const QCursor &cursor) { canvasWidget()->setCursor(cursor); } KisAnimationFrameCacheSP KisCanvas2::frameCache() const { return m_d->frameCache; } KisAnimationPlayer *KisCanvas2::animationPlayer() const { return m_d->animationPlayer; } void KisCanvas2::slotSelectionChanged() { KisShapeLayer* shapeLayer = dynamic_cast(viewManager()->activeLayer().data()); if (!shapeLayer) { return; } m_d->shapeManager.selection()->deselectAll(); Q_FOREACH (KoShape* shape, shapeLayer->shapeManager()->selection()->selectedShapes()) { m_d->shapeManager.selection()->select(shape); } } bool KisCanvas2::isPopupPaletteVisible() const { if (!m_d->popupPalette) { return false; } return m_d->popupPalette->isVisible(); } void KisCanvas2::setWrapAroundViewingMode(bool value) { KisCanvasDecorationSP infinityDecoration = m_d->canvasWidget->decoration(INFINITY_DECORATION_ID); if (infinityDecoration) { infinityDecoration->setVisible(!value); } m_d->canvasWidget->setWrapAroundViewingMode(value); } bool KisCanvas2::wrapAroundViewingMode() const { KisCanvasDecorationSP infinityDecoration = m_d->canvasWidget->decoration(INFINITY_DECORATION_ID); if (infinityDecoration) { return !(infinityDecoration->visible()); } return false; } void KisCanvas2::bootstrapFinished() { if (!m_d->bootstrapLodBlocked) return; m_d->bootstrapLodBlocked = false; setLodAllowedInCanvas(m_d->lodAllowedInCanvas); } void KisCanvas2::setLodAllowedInCanvas(bool value) { if (!KisOpenGL::supportsLoD()) { qWarning() << "WARNING: Level of Detail functionality is available only with openGL + GLSL 1.3 support"; } m_d->lodAllowedInCanvas = value && m_d->currentCanvasIsOpenGL && KisOpenGL::supportsLoD() && (m_d->openGLFilterMode == KisOpenGL::TrilinearFilterMode || m_d->openGLFilterMode == KisOpenGL::HighQualityFiltering); KisImageSP image = this->image(); if (m_d->effectiveLodAllowedInCanvas() != !image->levelOfDetailBlocked()) { image->setLevelOfDetailBlocked(!m_d->effectiveLodAllowedInCanvas()); notifyLevelOfDetailChange(); } KisConfig cfg; cfg.setLevelOfDetailEnabled(m_d->lodAllowedInCanvas); } bool KisCanvas2::lodAllowedInCanvas() const { return m_d->lodAllowedInCanvas; } void KisCanvas2::slotShowPopupPalette(const QPoint &p) { if (!m_d->popupPalette) { return; } m_d->popupPalette->showPopupPalette(p); } KisPaintingAssistantsDecorationSP KisCanvas2::paintingAssistantsDecoration() const { KisCanvasDecorationSP deco = decoration("paintingAssistantsDecoration"); return qobject_cast(deco.data()); } diff --git a/libs/ui/canvas/kis_canvas2.h b/libs/ui/canvas/kis_canvas2.h index 663c07c31e..ae8eebaa8d 100644 --- a/libs/ui/canvas/kis_canvas2.h +++ b/libs/ui/canvas/kis_canvas2.h @@ -1,303 +1,305 @@ /* This file is part of the KDE project * Copyright (C) 2006, 2010 Boudewijn Rempt * Copyright (C) 2011 Silvio Heinrich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CANVAS_H #define KIS_CANVAS_H #include #include #include #include #include #include #include #include #include #include #include "opengl/kis_opengl.h" #include "kis_ui_types.h" #include "kis_coordinates_converter.h" #include "kis_canvas_decoration.h" #include "kis_painting_assistants_decoration.h" class KoToolProxy; class KoColorProfile; class KisViewManager; class KisFavoriteResourceManager; class KisDisplayFilter; class KisDisplayColorConverter; struct KisExposureGammaCorrectionInterface; class KisView; class KisInputManager; class KisAnimationPlayer; class KisShapeController; class KisCoordinatesConverter; class KoViewConverter; /** * KisCanvas2 is not an actual widget class, but rather an adapter for * the widget it contains, which may be either a QPainter based * canvas, or an OpenGL based canvas: that are the real widgets. */ class KRITAUI_EXPORT KisCanvas2 : public KoCanvasBase { Q_OBJECT public: /** * Create a new canvas. The canvas manages a widget that will do * the actual painting: the canvas itself is not a widget. * * @param viewConverter the viewconverter for converting between * window and document coordinates. */ KisCanvas2(KisCoordinatesConverter *coordConverter, KoCanvasResourceManager *resourceManager, KisView *view, KoShapeBasedDocumentBase *sc); ~KisCanvas2() override; void notifyZoomChanged(); void disconnectCanvasObserver(QObject *object) override; public: // KoCanvasBase implementation bool canvasIsOpenGL() const override; KisOpenGL::FilterMode openGLFilterMode() const; void gridSize(QPointF *offset, QSizeF *spacing) const override; bool snapToGrid() const override; // This method only exists to support flake-related operations void addCommand(KUndo2Command *command) override; QPoint documentOrigin() const override; QPoint documentOffset() const; /** * Return the right shape manager for the current layer. That is * to say, if the current layer is a vector layer, return the shape * layer's canvas' shapemanager, else the shapemanager associated * with the global krita canvas. */ KoShapeManager * shapeManager() const override; /** * Since shapeManager() may change, we need a persistent object where we can * connect to and thack the selection. See more comments in KoCanvasBase. */ KoSelectedShapesProxy *selectedShapesProxy() const override; /** * Return the shape manager associated with this canvas */ KoShapeManager *globalShapeManager() const; void updateCanvas(const QRectF& rc) override; void updateInputMethodInfo() override; const KisCoordinatesConverter* coordinatesConverter() const; KoViewConverter *viewConverter() const override; QWidget* canvasWidget() override; const QWidget* canvasWidget() const override; KoUnit unit() const override; KoToolProxy* toolProxy() const override; const KoColorProfile* monitorProfile(); // FIXME: // Temporary! Either get the current layer and image from the // resource provider, or use this, which gets them from the // current shape selection. KisImageWSP currentImage() const; /** * Filters events and sends them to canvas actions. Shared * among all the views/canvases * * NOTE: May be null while initialization! */ KisInputManager* globalInputManager() const; KisPaintingAssistantsDecorationSP paintingAssistantsDecoration() const; public: // KisCanvas2 methods KisImageWSP image() const; KisViewManager* viewManager() const; QPointer imageView() const; /// @return true if the canvas image should be displayed in vertically mirrored mode void addDecoration(KisCanvasDecorationSP deco); KisCanvasDecorationSP decoration(const QString& id) const; void setDisplayFilter(QSharedPointer displayFilter); QSharedPointer displayFilter() const; KisDisplayColorConverter *displayColorConverter() const; KisExposureGammaCorrectionInterface* exposureGammaCorrectionInterface() const; /** * @brief setProofingOptions * set the options for softproofing, without affecting the proofing options as stored inside the image. */ void setProofingOptions(bool softProof, bool gamutCheck); KisProofingConfigurationSP proofingConfiguration() const; /** * @brief setProofingConfigUpdated This function is to set whether the proofing config is updated, * this is needed for determining whether or not to generate a new proofing transform. * @param updated whether it's updated. Just set it to false in normal usage. */ void setProofingConfigUpdated(bool updated); /** * @brief proofingConfigUpdated ask the canvas whether or not it updated the proofing config. * @return whether or not the proofing config is updated, if so, a new proofing transform needs to be made * in KisOpenGL canvas. */ bool proofingConfigUpdated(); void setCursor(const QCursor &cursor) override; KisAnimationFrameCacheSP frameCache() const; KisAnimationPlayer *animationPlayer() const; void refetchDataFromImage(); Q_SIGNALS: void imageChanged(KisImageWSP image); void sigCanvasCacheUpdated(); void sigContinueResizeImage(qint32 w, qint32 h); void documentOffsetUpdateFinished(); // emitted whenever the canvas widget thinks sketch should update void updateCanvasRequested(const QRect &rc); public Q_SLOTS: /// Update the entire canvas area void updateCanvas(); void startResizingImage(); void finishResizingImage(qint32 w, qint32 h); /// canvas rotation in degrees qreal rotationAngle() const; /// Bools indicating canvasmirroring. bool xAxisMirrored() const; bool yAxisMirrored() const; void slotSoftProofing(bool softProofing); void slotGamutCheck(bool gamutCheck); void slotChangeProofingConfig(); void slotZoomChanged(int zoom); void channelSelectionChanged(); /** * Called whenever the display monitor profile resource changes */ void slotSetDisplayProfile(const KoColorProfile *profile); void startUpdateInPatches(const QRect &imageRect); void slotTrySwitchShapeManager(); private Q_SLOTS: /// The image projection has changed, now start an update /// of the canvas representation. void startUpdateCanvasProjection(const QRect & rc); void updateCanvasProjection(); /** * Called whenever the view widget needs to show a different part of * the document * * @param documentOffset the offset in widget pixels */ void documentOffsetMoved(const QPoint &documentOffset); /** * Called whenever the configuration settings change. */ void slotConfigChanged(); void slotSelectionChanged(); void slotDoCanvasUpdate(); void bootstrapFinished(); public: bool isPopupPaletteVisible() const; void slotShowPopupPalette(const QPoint& = QPoint(0,0)); // interface for KisCanvasController only void setWrapAroundViewingMode(bool value); bool wrapAroundViewingMode() const; void setLodAllowedInCanvas(bool value); bool lodAllowedInCanvas() const; void initializeImage(); void setFavoriteResourceManager(KisFavoriteResourceManager* favoriteResourceManager); private: Q_DISABLE_COPY(KisCanvas2) void connectCurrentCanvas(); void createCanvas(bool useOpenGL); void createQPainterCanvas(); void createOpenGLCanvas(); void updateCanvasWidgetImpl(const QRect &rc = QRect()); void setCanvasWidget(QWidget *widget); void resetCanvas(bool useOpenGL); void notifyLevelOfDetailChange(); // Completes construction of canvas. // To be called by KisView in its constructor, once it has been setup enough // (to be defined what that means) for things KisCanvas2 expects from KisView // TODO: see to avoid that void setup(); + void initializeFpsDecoration(); + private: friend class KisView; // calls setup() class KisCanvas2Private; KisCanvas2Private * const m_d; }; #endif diff --git a/libs/ui/canvas/kis_canvas_widget_base.cpp b/libs/ui/canvas/kis_canvas_widget_base.cpp index 614dcb4467..482d63e034 100644 --- a/libs/ui/canvas/kis_canvas_widget_base.cpp +++ b/libs/ui/canvas/kis_canvas_widget_base.cpp @@ -1,248 +1,258 @@ /* * Copyright (C) 2007, 2010 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_canvas_widget_base.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_coordinates_converter.h" #include "kis_canvas_decoration.h" #include "kis_config.h" #include "kis_canvas2.h" #include "KisViewManager.h" #include "kis_selection_manager.h" #include "KisDocument.h" struct KisCanvasWidgetBase::Private { public: Private(KisCanvas2 *newCanvas, KisCoordinatesConverter *newCoordinatesConverter) : canvas(newCanvas) , coordinatesConverter(newCoordinatesConverter) , viewConverter(newCanvas->viewConverter()) , toolProxy(newCanvas->toolProxy()) , ignorenextMouseEventExceptRightMiddleClick(0) , borderColor(Qt::gray) {} QList decorations; KisCanvas2 * canvas; KisCoordinatesConverter *coordinatesConverter; const KoViewConverter * viewConverter; KoToolProxy * toolProxy; QTimer blockMouseEvent; bool ignorenextMouseEventExceptRightMiddleClick; // HACK work around Qt bug not sending tablet right/dblclick http://bugreports.qt.nokia.com/browse/QTBUG-8598 QColor borderColor; }; KisCanvasWidgetBase::KisCanvasWidgetBase(KisCanvas2 * canvas, KisCoordinatesConverter *coordinatesConverter) : m_d(new Private(canvas, coordinatesConverter)) { m_d->blockMouseEvent.setSingleShot(true); } KisCanvasWidgetBase::~KisCanvasWidgetBase() { /** * Clear all the attached decoration. Oherwise they might decide * to process some events or signals after the canvas has been * destroyed */ //5qDeleteAll(m_d->decorations); m_d->decorations.clear(); delete m_d; } void KisCanvasWidgetBase::drawDecorations(QPainter & gc, const QRect &updateWidgetRect) const { if (!m_d->canvas) { dbgFile<<"canvas doesn't exist, in canvas widget base!"; return; } gc.save(); // Setup the painter to take care of the offset; all that the // classes that do painting need to keep track of is resolution gc.setRenderHint(QPainter::Antialiasing); gc.setRenderHint(QPainter::TextAntialiasing); // This option does not do anything anymore with Qt4.6, so don't reenable it since it seems to break display // http://www.archivum.info/qt-interest@trolltech.com/2010-01/00481/Re:-(Qt-interest)-Is-QPainter::HighQualityAntialiasing-render-hint-broken-in-Qt-4.6.html // gc.setRenderHint(QPainter::HighQualityAntialiasing); gc.setRenderHint(QPainter::SmoothPixmapTransform); gc.save(); gc.setClipRect(updateWidgetRect); QTransform transform = m_d->coordinatesConverter->flakeToWidgetTransform(); gc.setTransform(transform); // Paint the shapes (other than the layers) m_d->canvas->globalShapeManager()->paint(gc, *m_d->viewConverter, false); // draw green selection outlines around text shapes that are edited, so the user sees where they end gc.save(); QTransform worldTransform = gc.worldTransform(); gc.setPen( Qt::green ); Q_FOREACH (KoShape *shape, canvas()->shapeManager()->selection()->selectedShapes()) { if (shape->shapeId() == "ArtisticText" || shape->shapeId() == "TextShapeID") { gc.setWorldTransform(shape->absoluteTransformation(m_d->viewConverter) * worldTransform); KoShape::applyConversion(gc, *m_d->viewConverter); gc.drawRect(QRectF(QPointF(), shape->size())); } } gc.restore(); // Draw text shape over canvas while editing it, that's needs to show the text selection correctly QString toolId = KoToolManager::instance()->activeToolId(); if (toolId == "ArtisticTextTool" || toolId == "TextTool") { gc.save(); gc.setPen(Qt::NoPen); gc.setBrush(Qt::NoBrush); Q_FOREACH (KoShape *shape, canvas()->shapeManager()->selection()->selectedShapes()) { if (shape->shapeId() == "ArtisticText" || shape->shapeId() == "TextShapeID") { KoShapePaintingContext paintContext(canvas(), false); gc.save(); gc.setTransform(shape->absoluteTransformation(m_d->viewConverter) * gc.transform()); canvas()->shapeManager()->paintShape(shape, gc, *m_d->viewConverter, paintContext); gc.restore(); } } gc.restore(); } // - some tools do not restore gc, but that is not important here // - we need to disable clipping to draw handles properly gc.setClipping(false); toolProxy()->paint(gc, *m_d->viewConverter); gc.restore(); // ask the decorations to paint themselves Q_FOREACH (KisCanvasDecorationSP deco, m_d->decorations) { deco->paint(gc, m_d->coordinatesConverter->widgetToDocument(updateWidgetRect), m_d->coordinatesConverter,m_d->canvas); } gc.restore(); } void KisCanvasWidgetBase::addDecoration(KisCanvasDecorationSP deco) { m_d->decorations.push_back(deco); } +void KisCanvasWidgetBase::removeDecoration(const QString &id) +{ + for (auto it = m_d->decorations.begin(); it != m_d->decorations.end(); ++it) { + if ((*it)->id() == id) { + it = m_d->decorations.erase(it); + break; + } + } +} + KisCanvasDecorationSP KisCanvasWidgetBase::decoration(const QString& id) const { Q_FOREACH (KisCanvasDecorationSP deco, m_d->decorations) { if (deco->id() == id) { return deco; } } return 0; } void KisCanvasWidgetBase::setDecorations(const QList &decorations) { m_d->decorations=decorations; } QList KisCanvasWidgetBase::decorations() const { return m_d->decorations; } void KisCanvasWidgetBase::setWrapAroundViewingMode(bool value) { Q_UNUSED(value); } QImage KisCanvasWidgetBase::createCheckersImage(qint32 checkSize) { KisConfig cfg; if(checkSize < 0) checkSize = cfg.checkSize(); QColor checkColor1 = cfg.checkersColor1(); QColor checkColor2 = cfg.checkersColor2(); QImage tile(checkSize * 2, checkSize * 2, QImage::Format_RGB32); QPainter pt(&tile); pt.fillRect(tile.rect(), checkColor2); pt.fillRect(0, 0, checkSize, checkSize, checkColor1); pt.fillRect(checkSize, checkSize, checkSize, checkSize, checkColor1); pt.end(); return tile; } void KisCanvasWidgetBase::notifyConfigChanged() { KisConfig cfg; m_d->borderColor = cfg.canvasBorderColor(); } QColor KisCanvasWidgetBase::borderColor() const { return m_d->borderColor; } KisCanvas2 *KisCanvasWidgetBase::canvas() const { return m_d->canvas; } KisCoordinatesConverter* KisCanvasWidgetBase::coordinatesConverter() const { return m_d->coordinatesConverter; } KoToolProxy *KisCanvasWidgetBase::toolProxy() const { return m_d->toolProxy; } QVariant KisCanvasWidgetBase::processInputMethodQuery(Qt::InputMethodQuery query) const { if (query == Qt::ImMicroFocus) { QRectF rect = m_d->toolProxy->inputMethodQuery(query, *m_d->viewConverter).toRectF(); return m_d->coordinatesConverter->flakeToWidget(rect); } return m_d->toolProxy->inputMethodQuery(query, *m_d->viewConverter); } void KisCanvasWidgetBase::processInputMethodEvent(QInputMethodEvent *event) { m_d->toolProxy->inputMethodEvent(event); } diff --git a/libs/ui/canvas/kis_canvas_widget_base.h b/libs/ui/canvas/kis_canvas_widget_base.h index a97be68e81..011e65e1be 100644 --- a/libs/ui/canvas/kis_canvas_widget_base.h +++ b/libs/ui/canvas/kis_canvas_widget_base.h @@ -1,102 +1,103 @@ /* * Copyright (C) 2007 Boudewijn Rempt , (C) * Copyright (C) 2010 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_CANVAS_WIDGET_BASE_ #define _KIS_CANVAS_WIDGET_BASE_ #include #include #include "kis_abstract_canvas_widget.h" class QColor; class QImage; class QInputMethodEvent; class QVariant; class KisCoordinatesConverter; class KisDisplayFilter; class KisCanvas2; #include "kritaui_export.h" class KRITAUI_EXPORT KisCanvasWidgetBase : public KisAbstractCanvasWidget { public: KisCanvasWidgetBase(KisCanvas2 * canvas, KisCoordinatesConverter *coordinatesConverter); ~KisCanvasWidgetBase() override; public: // KisAbstractCanvasWidget KoToolProxy *toolProxy() const override; /// set the specified display filter on the canvas void setDisplayFilter(QSharedPointer displayFilter) override = 0; /** * Draw the specified decorations on the view. */ void drawDecorations(QPainter & gc, const QRect &updateWidgetRect) const override; void addDecoration(KisCanvasDecorationSP deco) override; + void removeDecoration(const QString& id) override; KisCanvasDecorationSP decoration(const QString& id) const override; void setDecorations(const QList &) override; QList decorations() const override; void setWrapAroundViewingMode(bool value) override; /** * Returns the color of the border, i.e. the part of the canvas * outside the image contents. * */ QColor borderColor() const; /** * Returns one check of the background checkerboard pattern. */ static QImage createCheckersImage(qint32 checkSize = -1); KisCoordinatesConverter* coordinatesConverter() const; protected: KisCanvas2 *canvas() const; /** * Event handlers to be called by derived canvas event handlers. * All common event processing is carried out by these * functions. */ QVariant processInputMethodQuery(Qt::InputMethodQuery query) const; void processInputMethodEvent(QInputMethodEvent *event); void notifyConfigChanged(); /// To be implemented by the derived canvas virtual bool callFocusNextPrevChild(bool next) = 0; private: struct Private; Private * const m_d; }; #endif // _KIS_CANVAS_WIDGET_BASE_ diff --git a/libs/ui/dialogs/kis_dlg_preferences.cc b/libs/ui/dialogs/kis_dlg_preferences.cc index 7d4f811811..7767b01e8d 100644 --- a/libs/ui/dialogs/kis_dlg_preferences.cc +++ b/libs/ui/dialogs/kis_dlg_preferences.cc @@ -1,1260 +1,1262 @@ /* * preferencesdlg.cc - part of KImageShop * * Copyright (c) 1999 Michael Koch * Copyright (c) 2003-2011 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_dlg_preferences.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoID.h" #include #include #include #include #include #include "kis_action_registry.h" #include "widgets/squeezedcombobox.h" #include "kis_clipboard.h" #include "widgets/kis_cmb_idlist.h" #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "KoColorConversionTransformation.h" #include "kis_cursor.h" #include "kis_config.h" #include "kis_canvas_resource_provider.h" #include "kis_preference_set_registry.h" #include "kis_color_manager.h" #include "KisProofingConfiguration.h" #include "kis_image_config.h" #include "slider_and_spin_box_sync.h" // for the performance update #include #include #include "input/config/kis_input_configuration_page.h" #ifdef Q_OS_WIN # include #endif GeneralTab::GeneralTab(QWidget *_parent, const char *_name) : WdgGeneralSettings(_parent, _name) { KisConfig cfg; m_cmbCursorShape->addItem(i18n("No Cursor")); m_cmbCursorShape->addItem(i18n("Tool Icon")); m_cmbCursorShape->addItem(i18n("Arrow")); m_cmbCursorShape->addItem(i18n("Small Circle")); m_cmbCursorShape->addItem(i18n("Crosshair")); m_cmbCursorShape->addItem(i18n("Triangle Righthanded")); m_cmbCursorShape->addItem(i18n("Triangle Lefthanded")); m_cmbCursorShape->addItem(i18n("Black Pixel")); m_cmbCursorShape->addItem(i18n("White Pixel")); m_cmbOutlineShape->addItem(i18n("No Outline")); m_cmbOutlineShape->addItem(i18n("Circle Outline")); m_cmbOutlineShape->addItem(i18n("Preview Outline")); m_cmbOutlineShape->addItem(i18n("Tilt Outline")); m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle()); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle()); chkShowRootLayer->setChecked(cfg.showRootLayer()); int autosaveInterval = cfg.autoSaveInterval(); //convert to minutes m_autosaveSpinBox->setValue(autosaveInterval / 60); m_autosaveCheckBox->setChecked(autosaveInterval > 0); m_undoStackSize->setValue(cfg.undoStackLimit()); m_backupFileCheckBox->setChecked(cfg.backupFile()); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting()); m_hideSplashScreen->setChecked(cfg.hideSplashScreen()); KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs"); m_chkNativeFileDialog->setChecked(!group.readEntry("DontUseNativeFileDialog", true)); intMaxBrushSize->setValue(cfg.readEntry("maximumBrushSize", 1000)); m_cmbMDIType->setCurrentIndex(cfg.readEntry("mdi_viewmode", (int)QMdiArea::TabbedView)); m_chkRubberBand->setChecked(cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets()); KoColor mdiColor; mdiColor.fromQColor(cfg.getMDIBackgroundColor()); m_mdiColor->setColor(mdiColor); m_backgroundimage->setText(cfg.getMDIBackgroundImage()); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages()); m_chkCompressKra->setChecked(cfg.compressKra()); const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); m_chkHiDPI->setChecked(kritarc.value("EnableHiDPI", false).toBool()); m_chkSingleApplication->setChecked(kritarc.value("EnableSingleApplication", true).toBool()); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker()); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt()); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas()); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport()); m_chkCacheAnimatioInBackground->setChecked(cfg.calculateAnimationCacheInBackground()); KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8()); cursorColor.fromQColor(cfg.getCursorMainColor()); cursorColorBtutton->setColor(cursorColor); connect(m_bnFileName, SIGNAL(clicked()), SLOT(getBackgroundImage())); connect(clearBgImageButton, SIGNAL(clicked()), SLOT(clearBackgroundImage())); } void GeneralTab::setDefault() { KisConfig cfg; m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle(true)); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle(true)); chkShowRootLayer->setChecked(cfg.showRootLayer(true)); m_autosaveCheckBox->setChecked(cfg.autoSaveInterval(true) > 0); //convert to minutes m_autosaveSpinBox->setValue(cfg.autoSaveInterval(true) / 60); m_undoStackSize->setValue(cfg.undoStackLimit(true)); m_backupFileCheckBox->setChecked(cfg.backupFile(true)); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting(true)); m_hideSplashScreen->setChecked(cfg.hideSplashScreen(true)); m_chkNativeFileDialog->setChecked(false); intMaxBrushSize->setValue(1000); m_cmbMDIType->setCurrentIndex((int)QMdiArea::TabbedView); m_chkRubberBand->setChecked(cfg.useOpenGL(true)); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets(true)); KoColor mdiColor; mdiColor.fromQColor(cfg.getMDIBackgroundColor(true)); m_mdiColor->setColor(mdiColor); m_backgroundimage->setText(cfg.getMDIBackgroundImage(true)); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages(true)); m_chkCompressKra->setChecked(cfg.compressKra(true)); m_chkHiDPI->setChecked(false); m_chkSingleApplication->setChecked(true); m_chkHiDPI->setChecked(true); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true)); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt(true)); chkEnableTouch->setChecked(!cfg.disableTouchOnCanvas(true)); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport(true)); m_chkCacheAnimatioInBackground->setChecked(cfg.calculateAnimationCacheInBackground(true)); KoColor cursorColor(KoColorSpaceRegistry::instance()->rgb8()); cursorColor.fromQColor(cfg.getCursorMainColor(true)); cursorColorBtutton->setColor(cursorColor); } CursorStyle GeneralTab::cursorStyle() { return (CursorStyle)m_cmbCursorShape->currentIndex(); } OutlineStyle GeneralTab::outlineStyle() { return (OutlineStyle)m_cmbOutlineShape->currentIndex(); } bool GeneralTab::showRootLayer() { return chkShowRootLayer->isChecked(); } int GeneralTab::autoSaveInterval() { //convert to seconds return m_autosaveCheckBox->isChecked() ? m_autosaveSpinBox->value() * 60 : 0; } int GeneralTab::undoStackSize() { return m_undoStackSize->value(); } bool GeneralTab::showOutlineWhilePainting() { return m_showOutlinePainting->isChecked(); } bool GeneralTab::hideSplashScreen() { return m_hideSplashScreen->isChecked(); } int GeneralTab::mdiMode() { return m_cmbMDIType->currentIndex(); } int GeneralTab::favoritePresets() { return m_favoritePresetsSpinBox->value(); } bool GeneralTab::showCanvasMessages() { return m_chkCanvasMessages->isChecked(); } bool GeneralTab::compressKra() { return m_chkCompressKra->isChecked(); } bool GeneralTab::toolOptionsInDocker() { return m_radioToolOptionsInDocker->isChecked(); } bool GeneralTab::switchSelectionCtrlAlt() { return m_chkSwitchSelectionCtrlAlt->isChecked(); } bool GeneralTab::convertToImageColorspaceOnImport() { return m_chkConvertOnImport->isChecked(); } bool GeneralTab::calculateAnimationCacheInBackground() { return m_chkCacheAnimatioInBackground->isChecked(); } void GeneralTab::getBackgroundImage() { KoFileDialog dialog(this, KoFileDialog::OpenFile, "BackgroundImages"); dialog.setCaption(i18n("Select a Background Image")); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); dialog.setImageFilters(); QString fn = dialog.filename(); // dialog box was canceled or somehow no file was selected if (fn.isEmpty()) { return; } QImage image(fn); if (image.isNull()) { QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("%1 is not a valid image file!", fn)); } else { m_backgroundimage->setText(fn); } } void GeneralTab::clearBackgroundImage() { // clearing the background image text will implicitly make the background color be used m_backgroundimage->setText(""); } #include "kactioncollection.h" #include "KisActionsSnapshot.h" ShortcutSettingsTab::ShortcutSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgShortcutSettings(this); l->addWidget(m_page, 0, 0); m_snapshot.reset(new KisActionsSnapshot); KActionCollection *collection = KisPart::instance()->currentMainwindow()->actionCollection(); Q_FOREACH (QAction *action, collection->actions()) { m_snapshot->addAction(action->objectName(), action); } QMap sortedCollections = m_snapshot->actionCollections(); for (auto it = sortedCollections.constBegin(); it != sortedCollections.constEnd(); ++it) { m_page->addCollection(it.value(), it.key()); } } ShortcutSettingsTab::~ShortcutSettingsTab() { } void ShortcutSettingsTab::setDefault() { m_page->allDefault(); } void ShortcutSettingsTab::saveChanges() { m_page->save(); KisActionRegistry::instance()->settingsPageSaved(); } void ShortcutSettingsTab::cancelChanges() { m_page->undo(); } ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); // XXX: Make sure only profiles that fit the specified color model // are shown in the profile combos QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgColorSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg; m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile()); connect(m_page->chkUseSystemMonitorProfile, SIGNAL(toggled(bool)), this, SLOT(toggleAllowMonitorProfileSelection(bool))); m_page->cmbWorkingColorSpace->setIDList(KoColorSpaceRegistry::instance()->listKeys()); m_page->cmbWorkingColorSpace->setCurrent(cfg.workingColorSpace()); m_page->bnAddColorProfile->setIcon(KisIconUtils::loadIcon("document-open")); m_page->bnAddColorProfile->setToolTip( i18n("Open Color Profile") ); connect(m_page->bnAddColorProfile, SIGNAL(clicked()), SLOT(installProfile())); QFormLayout *monitorProfileGrid = new QFormLayout(m_page->monitorprofileholder); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { QLabel *lbl = new QLabel(i18nc("The number of the screen", "Screen %1:", i + 1)); m_monitorProfileLabels << lbl; SqueezedComboBox *cmb = new SqueezedComboBox(); cmb->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); monitorProfileGrid->addRow(lbl, cmb); m_monitorProfileWidgets << cmb; } refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation()); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization()); KisImageConfig cfgImage; KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(); m_page->sldAdaptationState->setMaximum(20); m_page->sldAdaptationState->setMinimum(0); m_page->sldAdaptationState->setValue((int)proofingConfig->adaptationState*20); //probably this should become the screenprofile? KoColor ga(KoColorSpaceRegistry::instance()->rgb8()); ga.fromKoColor(proofingConfig->warningColor); m_page->gamutAlarm->setColor(ga); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel, proofingConfig->proofingDepth, proofingConfig->proofingProfile); if (proofingSpace) { m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); } m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_pasteBehaviourGroup.addButton(m_page->radioPasteWeb, PASTE_ASSUME_WEB); m_pasteBehaviourGroup.addButton(m_page->radioPasteMonitor, PASTE_ASSUME_MONITOR); m_pasteBehaviourGroup.addButton(m_page->radioPasteAsk, PASTE_ASK); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour()); Q_ASSERT(button); if (button) { button->setChecked(true); } m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent()); toggleAllowMonitorProfileSelection(cfg.useSystemMonitorProfile()); } void ColorSettingsTab::installProfile() { KoFileDialog dialog(this, KoFileDialog::OpenFiles, "OpenDocumentICC"); dialog.setCaption(i18n("Install Color Profiles")); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); dialog.setMimeTypeFilters(QStringList() << "application/vnd.iccprofile", "application/vnd.iccprofile"); QStringList profileNames = dialog.filenames(); KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc"); Q_ASSERT(iccEngine); QString saveLocation = KoResourcePaths::saveLocation("icc_profiles"); Q_FOREACH (const QString &profileName, profileNames) { if (!QFile::copy(profileName, saveLocation + QFileInfo(profileName).fileName())) { qWarning() << "Could not install profile!" << saveLocation + QFileInfo(profileName).fileName(); continue; } iccEngine->addProfile(saveLocation + QFileInfo(profileName).fileName()); } KisConfig cfg; refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } void ColorSettingsTab::toggleAllowMonitorProfileSelection(bool useSystemProfile) { if (useSystemProfile) { KisConfig cfg; QStringList devices = KisColorManager::instance()->devices(); if (devices.size() == QApplication::desktop()->screenCount()) { for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); QString monitorForScreen = cfg.monitorForScreen(i, devices[i]); Q_FOREACH (const QString &device, devices) { m_monitorProfileLabels[i]->setText(i18nc("The display/screen we got from Qt", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->addSqueezedItem(KisColorManager::instance()->deviceName(device), device); if (devices[i] == monitorForScreen) { m_monitorProfileWidgets[i]->setCurrentIndex(i); } } } } } else { KisConfig cfg; refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } } void ColorSettingsTab::setDefault() { m_page->cmbWorkingColorSpace->setCurrent("RGBA"); refillMonitorProfiles(KoID("RGBA", "")); KisConfig cfg; KisImageConfig cfgImage; KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel,proofingConfig->proofingDepth,proofingConfig->proofingProfile); if (proofingSpace) { m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); } m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_page->sldAdaptationState->setValue(0); //probably this should become the screenprofile? KoColor ga(KoColorSpaceRegistry::instance()->rgb8()); ga.fromKoColor(proofingConfig->warningColor); m_page->gamutAlarm->setColor(ga); m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation(true)); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization(true)); m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent(true)); m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile(true)); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour(true)); Q_ASSERT(button); if (button) { button->setChecked(true); } } void ColorSettingsTab::refillMonitorProfiles(const KoID & colorSpaceId) { for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); } QMap profileList; Q_FOREACH(const KoColorProfile *profile, KoColorSpaceRegistry::instance()->profilesFor(colorSpaceId.id())) { profileList[profile->name()] = profile; } Q_FOREACH (const KoColorProfile *profile, profileList.values()) { //qDebug() << "Profile" << profile->name() << profile->isSuitableForDisplay() << csf->defaultProfile(); if (profile->isSuitableForDisplay()) { for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->addSqueezedItem(profile->name()); } } } for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileLabels[i]->setText(i18nc("The number of the screen", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->setCurrent(KoColorSpaceRegistry::instance()->defaultProfileForColorSpace(colorSpaceId.id())); } } //--------------------------------------------------------------------------------------------------- void TabletSettingsTab::setDefault() { KisCubicCurve curve; curve.fromString(DEFAULT_CURVE_STRING); m_page->pressureCurve->setCurve(curve); #ifdef Q_OS_WIN if (KisTabletSupportWin8::isAvailable()) { KisConfig cfg; m_page->radioWintab->setChecked(!cfg.useWin8PointerInput(true)); m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput(true)); } else { m_page->radioWintab->setChecked(true); m_page->radioWin8PointerInput->setChecked(false); } #endif } TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgTabletSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg; KisCubicCurve curve; curve.fromString( cfg.pressureTabletCurve() ); m_page->pressureCurve->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); m_page->pressureCurve->setCurve(curve); #ifdef Q_OS_WIN if (KisTabletSupportWin8::isAvailable()) { m_page->radioWintab->setChecked(!cfg.useWin8PointerInput()); m_page->radioWin8PointerInput->setChecked(cfg.useWin8PointerInput()); } else { m_page->radioWintab->setChecked(true); m_page->radioWin8PointerInput->setChecked(false); m_page->grpTabletApi->setVisible(false); } #else m_page->grpTabletApi->setVisible(false); #endif } //--------------------------------------------------------------------------------------------------- #include "kis_acyclic_signal_connector.h" int getTotalRAM() { KisImageConfig cfg; return cfg.totalRAM(); } int PerformanceTab::realTilesRAM() { return intMemoryLimit->value() - intPoolLimit->value(); } PerformanceTab::PerformanceTab(QWidget *parent, const char *name) : WdgPerformanceSettings(parent, name) { KisImageConfig cfg; const int totalRAM = cfg.totalRAM(); lblTotalMemory->setText(i18n("%1 MiB", totalRAM)); sliderMemoryLimit->setSuffix(i18n(" %")); sliderMemoryLimit->setRange(1, 100, 2); sliderMemoryLimit->setSingleStep(0.01); sliderPoolLimit->setSuffix(i18n(" %")); sliderPoolLimit->setRange(0, 20, 2); sliderMemoryLimit->setSingleStep(0.01); sliderUndoLimit->setSuffix(i18n(" %")); sliderUndoLimit->setRange(0, 50, 2); sliderMemoryLimit->setSingleStep(0.01); intMemoryLimit->setMinimumWidth(80); intPoolLimit->setMinimumWidth(80); intUndoLimit->setMinimumWidth(80); SliderAndSpinBoxSync *sync1 = new SliderAndSpinBoxSync(sliderMemoryLimit, intMemoryLimit, getTotalRAM); sync1->slotParentValueChanged(); m_syncs << sync1; SliderAndSpinBoxSync *sync2 = new SliderAndSpinBoxSync(sliderPoolLimit, intPoolLimit, std::bind(&KisIntParseSpinBox::value, intMemoryLimit)); connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync2, SLOT(slotParentValueChanged())); sync2->slotParentValueChanged(); m_syncs << sync2; SliderAndSpinBoxSync *sync3 = new SliderAndSpinBoxSync(sliderUndoLimit, intUndoLimit, std::bind(&PerformanceTab::realTilesRAM, this)); connect(intPoolLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged())); sync3->slotParentValueChanged(); m_syncs << sync3; sliderSwapSize->setSuffix(i18n(" GiB")); sliderSwapSize->setRange(1, 64); intSwapSize->setRange(1, 64); KisAcyclicSignalConnector *swapSizeConnector = new KisAcyclicSignalConnector(this); swapSizeConnector->connectForwardInt(sliderSwapSize, SIGNAL(valueChanged(int)), intSwapSize, SLOT(setValue(int))); swapSizeConnector->connectBackwardInt(intSwapSize, SIGNAL(valueChanged(int)), sliderSwapSize, SLOT(setValue(int))); lblSwapFileLocation->setText(cfg.swapDir()); connect(bnSwapFile, SIGNAL(clicked()), SLOT(selectSwapDir())); sliderThreadsLimit->setRange(1, QThread::idealThreadCount()); sliderFrameClonesLimit->setRange(1, QThread::idealThreadCount()); connect(sliderThreadsLimit, SIGNAL(valueChanged(int)), SLOT(slotThreadsLimitChanged(int))); connect(sliderFrameClonesLimit, SIGNAL(valueChanged(int)), SLOT(slotFrameClonesLimitChanged(int))); load(false); } PerformanceTab::~PerformanceTab() { qDeleteAll(m_syncs); } void PerformanceTab::load(bool requestDefault) { KisImageConfig cfg; sliderMemoryLimit->setValue(cfg.memoryHardLimitPercent(requestDefault)); sliderPoolLimit->setValue(cfg.memoryPoolLimitPercent(requestDefault)); sliderUndoLimit->setValue(cfg.memorySoftLimitPercent(requestDefault)); chkPerformanceLogging->setChecked(cfg.enablePerfLog(requestDefault)); chkProgressReporting->setChecked(cfg.enableProgressReporting(requestDefault)); sliderSwapSize->setValue(cfg.maxSwapSize(requestDefault) / 1024); lblSwapFileLocation->setText(cfg.swapDir(requestDefault)); m_lastUsedThreadsLimit = cfg.maxNumberOfThreads(requestDefault); m_lastUsedClonesLimit = cfg.frameRenderingClones(requestDefault); sliderThreadsLimit->setValue(m_lastUsedThreadsLimit); sliderFrameClonesLimit->setValue(m_lastUsedClonesLimit); { KisConfig cfg2; chkOpenGLFramerateLogging->setChecked(cfg2.enableOpenGLFramerateLogging(requestDefault)); + chkBrushSpeedLogging->setChecked(cfg2.enableBrushSpeedLogging(requestDefault)); chkDisableVectorOptimizations->setChecked(cfg2.enableAmdVectorizationWorkaround(requestDefault)); } } void PerformanceTab::save() { KisImageConfig cfg; cfg.setMemoryHardLimitPercent(sliderMemoryLimit->value()); cfg.setMemorySoftLimitPercent(sliderUndoLimit->value()); cfg.setMemoryPoolLimitPercent(sliderPoolLimit->value()); cfg.setEnablePerfLog(chkPerformanceLogging->isChecked()); cfg.setEnableProgressReporting(chkProgressReporting->isChecked()); cfg.setMaxSwapSize(sliderSwapSize->value() * 1024); cfg.setSwapDir(lblSwapFileLocation->text()); cfg.setMaxNumberOfThreads(sliderThreadsLimit->value()); cfg.setFrameRenderingClones(sliderFrameClonesLimit->value()); { KisConfig cfg2; cfg2.setEnableOpenGLFramerateLogging(chkOpenGLFramerateLogging->isChecked()); + cfg2.setEnableBrushSpeedLogging(chkBrushSpeedLogging->isChecked()); cfg2.setEnableAmdVectorizationWorkaround(chkDisableVectorOptimizations->isChecked()); } } void PerformanceTab::selectSwapDir() { KisImageConfig cfg; QString swapDir = cfg.swapDir(); swapDir = QFileDialog::getExistingDirectory(0, i18nc("@title:window", "Select a swap directory"), swapDir); if (swapDir.isEmpty()) { return; } lblSwapFileLocation->setText(swapDir); } void PerformanceTab::slotThreadsLimitChanged(int value) { KisSignalsBlocker b(sliderFrameClonesLimit); sliderFrameClonesLimit->setValue(qMin(m_lastUsedClonesLimit, value)); m_lastUsedThreadsLimit = value; } void PerformanceTab::slotFrameClonesLimitChanged(int value) { KisSignalsBlocker b(sliderThreadsLimit); sliderThreadsLimit->setValue(qMax(m_lastUsedThreadsLimit, value)); m_lastUsedClonesLimit = value; } //--------------------------------------------------------------------------------------------------- #include "KoColor.h" DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name) : WdgDisplaySettings(parent, name) { KisConfig cfg; const QString rendererOpenGLText = i18nc("canvas renderer", "OpenGL"); const QString rendererAngleText = i18nc("canvas renderer", "Direct3D 11 via ANGLE"); #ifdef Q_OS_WIN cmbRenderer->clear(); QString qtPreferredRendererText; if (KisOpenGL::getQtPreferredOpenGLRenderer() == KisOpenGL::RendererAngle) { qtPreferredRendererText = rendererAngleText; } else { qtPreferredRendererText = rendererOpenGLText; } cmbRenderer->addItem(i18nc("canvas renderer", "Auto (%1)", qtPreferredRendererText), KisOpenGL::RendererAuto); cmbRenderer->setCurrentIndex(0); if (KisOpenGL::getSupportedOpenGLRenderers() & KisOpenGL::RendererDesktopGL) { cmbRenderer->addItem(rendererOpenGLText, KisOpenGL::RendererDesktopGL); if (KisOpenGL::getNextUserOpenGLRendererConfig() == KisOpenGL::RendererDesktopGL) { cmbRenderer->setCurrentIndex(cmbRenderer->count() - 1); } } if (KisOpenGL::getSupportedOpenGLRenderers() & KisOpenGL::RendererAngle) { cmbRenderer->addItem(rendererAngleText, KisOpenGL::RendererAngle); if (KisOpenGL::getNextUserOpenGLRendererConfig() == KisOpenGL::RendererAngle) { cmbRenderer->setCurrentIndex(cmbRenderer->count() - 1); } } #else lblRenderer->setEnabled(false); cmbRenderer->setEnabled(false); cmbRenderer->clear(); cmbRenderer->addItem(rendererOpenGLText); cmbRenderer->setCurrentIndex(0); #endif #ifdef Q_OS_WIN if (!(KisOpenGL::getSupportedOpenGLRenderers() & (KisOpenGL::RendererDesktopGL | KisOpenGL::RendererAngle))) { #else if (!KisOpenGL::hasOpenGL()) { #endif grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL()); chkUseTextureBuffer->setEnabled(cfg.useOpenGL()); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer()); chkDisableVsync->setVisible(cfg.showAdvancedOpenGLSettings()); chkDisableVsync->setEnabled(cfg.useOpenGL()); chkDisableVsync->setChecked(cfg.disableVSync()); cmbFilterMode->setEnabled(cfg.useOpenGL()); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode()); // Don't show the high quality filtering mode if it's not available if (!KisOpenGL::supportsLoD()) { cmbFilterMode->removeItem(3); } } if (qApp->applicationName() == "kritasketch" || qApp->applicationName() == "kritagemini") { grpOpenGL->setVisible(false); grpOpenGL->setMaximumHeight(0); } KoColor c; c.fromQColor(cfg.selectionOverlayMaskColor()); c.setOpacity(1.0); btnSelectionOverlayColor->setColor(c); sldSelectionOverlayOpacity->setRange(0.0, 1.0, 2); sldSelectionOverlayOpacity->setSingleStep(0.05); sldSelectionOverlayOpacity->setValue(cfg.selectionOverlayMaskColor().alphaF()); intCheckSize->setValue(cfg.checkSize()); chkMoving->setChecked(cfg.scrollCheckers()); KoColor ck1(KoColorSpaceRegistry::instance()->rgb8()); ck1.fromQColor(cfg.checkersColor1()); colorChecks1->setColor(ck1); KoColor ck2(KoColorSpaceRegistry::instance()->rgb8()); ck2.fromQColor(cfg.checkersColor2()); colorChecks2->setColor(ck2); KoColor cb(KoColorSpaceRegistry::instance()->rgb8()); cb.fromQColor(cfg.canvasBorderColor()); canvasBorder->setColor(cb); hideScrollbars->setChecked(cfg.hideScrollbars()); chkCurveAntialiasing->setChecked(cfg.antialiasCurves()); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline()); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor()); chkHidePopups->setChecked(cfg.hidePopups()); connect(grpOpenGL, SIGNAL(toggled(bool)), SLOT(slotUseOpenGLToggled(bool))); KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8()); gridColor.fromQColor(cfg.getPixelGridColor()); pixelGridColorButton->setColor(gridColor); pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold() * 100); grpPixelGrid->setEnabled(true); grpPixelGrid->setChecked(cfg.pixelGridEnabled()); } void DisplaySettingsTab::setDefault() { KisConfig cfg; cmbRenderer->setCurrentIndex(0); #ifdef Q_OS_WIN if (!(KisOpenGL::getSupportedOpenGLRenderers() & (KisOpenGL::RendererDesktopGL | KisOpenGL::RendererAngle))) { #else if (!KisOpenGL::hasOpenGL()) { #endif grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL(true)); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer(true)); chkUseTextureBuffer->setEnabled(true); chkDisableVsync->setEnabled(true); chkDisableVsync->setChecked(cfg.disableVSync(true)); cmbFilterMode->setEnabled(true); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode(true)); } chkMoving->setChecked(cfg.scrollCheckers(true)); intCheckSize->setValue(cfg.checkSize(true)); KoColor ck1(KoColorSpaceRegistry::instance()->rgb8()); ck1.fromQColor(cfg.checkersColor1(true)); colorChecks1->setColor(ck1); KoColor ck2(KoColorSpaceRegistry::instance()->rgb8()); ck2.fromQColor(cfg.checkersColor2(true)); colorChecks2->setColor(ck2); KoColor cvb(KoColorSpaceRegistry::instance()->rgb8()); cvb.fromQColor(cfg.canvasBorderColor(true)); canvasBorder->setColor(cvb); hideScrollbars->setChecked(cfg.hideScrollbars(true)); chkCurveAntialiasing->setChecked(cfg.antialiasCurves(true)); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline(true)); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor(true)); chkHidePopups->setChecked(cfg.hidePopups(true)); KoColor gridColor(KoColorSpaceRegistry::instance()->rgb8()); gridColor.fromQColor(cfg.getPixelGridColor(true)); pixelGridColorButton->setColor(gridColor); pixelGridDrawingThresholdBox->setValue(cfg.getPixelGridDrawingThreshold(true) * 100); grpPixelGrid->setEnabled(true); grpPixelGrid->setChecked(cfg.pixelGridEnabled(true)); } void DisplaySettingsTab::slotUseOpenGLToggled(bool isChecked) { chkUseTextureBuffer->setEnabled(isChecked); chkDisableVsync->setEnabled(isChecked); cmbFilterMode->setEnabled(isChecked); } //--------------------------------------------------------------------------------------------------- FullscreenSettingsTab::FullscreenSettingsTab(QWidget* parent) : WdgFullscreenSettingsBase(parent) { KisConfig cfg; chkDockers->setChecked(cfg.hideDockersFullscreen()); chkMenu->setChecked(cfg.hideMenuFullscreen()); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen()); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen()); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen()); chkToolbar->setChecked(cfg.hideToolbarFullscreen()); } void FullscreenSettingsTab::setDefault() { KisConfig cfg; chkDockers->setChecked(cfg.hideDockersFullscreen(true)); chkMenu->setChecked(cfg.hideMenuFullscreen(true)); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen(true)); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen(true)); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen(true)); chkToolbar->setChecked(cfg.hideToolbarFullscreen(true)); } //--------------------------------------------------------------------------------------------------- KisDlgPreferences::KisDlgPreferences(QWidget* parent, const char* name) : KPageDialog(parent) { Q_UNUSED(name); setWindowTitle(i18n("Configure Krita")); setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults); button(QDialogButtonBox::Ok)->setDefault(true); setFaceType(KPageDialog::List); // General KoVBox *vbox = new KoVBox(); KPageWidgetItem *page = new KPageWidgetItem(vbox, i18n("General")); page->setObjectName("general"); page->setHeader(i18n("General")); page->setIcon(KisIconUtils::loadIcon("go-home")); addPage(page); m_general = new GeneralTab(vbox); // Shortcuts vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Keyboard Shortcuts")); page->setObjectName("shortcuts"); page->setHeader(i18n("Shortcuts")); page->setIcon(KisIconUtils::loadIcon("document-export")); addPage(page); m_shortcutSettings = new ShortcutSettingsTab(vbox); connect(this, SIGNAL(accepted()), m_shortcutSettings, SLOT(saveChanges())); connect(this, SIGNAL(rejected()), m_shortcutSettings, SLOT(cancelChanges())); // Canvas input settings m_inputConfiguration = new KisInputConfigurationPage(); page = addPage(m_inputConfiguration, i18n("Canvas Input Settings")); page->setHeader(i18n("Canvas Input")); page->setObjectName("canvasinput"); page->setIcon(KisIconUtils::loadIcon("configure")); // Display vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Display")); page->setObjectName("display"); page->setHeader(i18n("Display")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-display")); addPage(page); m_displaySettings = new DisplaySettingsTab(vbox); // Color vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Color Management")); page->setObjectName("colormanagement"); page->setHeader(i18n("Color")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-color")); addPage(page); m_colorSettings = new ColorSettingsTab(vbox); // Performance vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Performance")); page->setObjectName("performance"); page->setHeader(i18n("Performance")); page->setIcon(KisIconUtils::loadIcon("applications-system")); addPage(page); m_performanceSettings = new PerformanceTab(vbox); // Tablet vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Tablet settings")); page->setObjectName("tablet"); page->setHeader(i18n("Tablet")); page->setIcon(KisIconUtils::loadIcon("document-edit")); addPage(page); m_tabletSettings = new TabletSettingsTab(vbox); // full-screen mode vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Canvas-only settings")); page->setObjectName("canvasonly"); page->setHeader(i18n("Canvas-only")); page->setIcon(KisIconUtils::loadIcon("folder-pictures")); addPage(page); m_fullscreenSettings = new FullscreenSettingsTab(vbox); // Author profiles m_authorPage = new KoConfigAuthorPage(); page = addPage(m_authorPage, i18nc("@title:tab Author page", "Author" )); page->setObjectName("author"); page->setHeader(i18n("Author")); page->setIcon(KisIconUtils::loadIcon("im-user")); QPushButton *restoreDefaultsButton = button(QDialogButtonBox::RestoreDefaults); connect(this, SIGNAL(accepted()), m_inputConfiguration, SLOT(saveChanges())); connect(this, SIGNAL(rejected()), m_inputConfiguration, SLOT(revertChanges())); KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); Q_FOREACH (KisAbstractPreferenceSetFactory *preferenceSetFactory, preferenceSetRegistry->values()) { KisPreferenceSet* preferenceSet = preferenceSetFactory->createPreferenceSet(); vbox = new KoVBox(); page = new KPageWidgetItem(vbox, preferenceSet->name()); page->setHeader(preferenceSet->header()); page->setIcon(preferenceSet->icon()); addPage(page); preferenceSet->setParent(vbox); preferenceSet->loadPreferences(); connect(restoreDefaultsButton, SIGNAL(clicked(bool)), preferenceSet, SLOT(loadDefaultPreferences()), Qt::UniqueConnection); connect(this, SIGNAL(accepted()), preferenceSet, SLOT(savePreferences()), Qt::UniqueConnection); } connect(restoreDefaultsButton, SIGNAL(clicked(bool)), this, SLOT(slotDefault())); } KisDlgPreferences::~KisDlgPreferences() { } void KisDlgPreferences::slotDefault() { if (currentPage()->objectName() == "general") { m_general->setDefault(); } else if (currentPage()->objectName() == "shortcuts") { m_shortcutSettings->setDefault(); } else if (currentPage()->objectName() == "display") { m_displaySettings->setDefault(); } else if (currentPage()->objectName() == "colormanagement") { m_colorSettings->setDefault(); } else if (currentPage()->objectName() == "performance") { m_performanceSettings->load(true); } else if (currentPage()->objectName() == "tablet") { m_tabletSettings->setDefault(); } else if (currentPage()->objectName() == "canvasonly") { m_fullscreenSettings->setDefault(); } else if (currentPage()->objectName() == "canvasinput") { m_inputConfiguration->setDefaults(); } } bool KisDlgPreferences::editPreferences() { KisDlgPreferences* dialog; dialog = new KisDlgPreferences(); bool baccept = (dialog->exec() == Accepted); if (baccept) { // General settings KisConfig cfg; cfg.setNewCursorStyle(dialog->m_general->cursorStyle()); cfg.setNewOutlineStyle(dialog->m_general->outlineStyle()); cfg.setShowRootLayer(dialog->m_general->showRootLayer()); cfg.setShowOutlineWhilePainting(dialog->m_general->showOutlineWhilePainting()); cfg.setHideSplashScreen(dialog->m_general->hideSplashScreen()); cfg.setCalculateAnimationCacheInBackground(dialog->m_general->calculateAnimationCacheInBackground()); KConfigGroup group = KSharedConfig::openConfig()->group("File Dialogs"); group.writeEntry("DontUseNativeFileDialog", !dialog->m_general->m_chkNativeFileDialog->isChecked()); cfg.writeEntry("maximumBrushSize", dialog->m_general->intMaxBrushSize->value()); cfg.writeEntry("mdi_viewmode", dialog->m_general->mdiMode()); cfg.setMDIBackgroundColor(dialog->m_general->m_mdiColor->color().toQColor()); cfg.setMDIBackgroundImage(dialog->m_general->m_backgroundimage->text()); cfg.setAutoSaveInterval(dialog->m_general->autoSaveInterval()); cfg.setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked()); cfg.setShowCanvasMessages(dialog->m_general->showCanvasMessages()); cfg.setCompressKra(dialog->m_general->compressKra()); const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); kritarc.setValue("EnableHiDPI", dialog->m_general->m_chkHiDPI->isChecked()); kritarc.setValue("EnableSingleApplication", dialog->m_general->m_chkSingleApplication->isChecked()); cfg.setToolOptionsInDocker(dialog->m_general->toolOptionsInDocker()); cfg.setSwitchSelectionCtrlAlt(dialog->m_general->switchSelectionCtrlAlt()); cfg.setDisableTouchOnCanvas(!dialog->m_general->chkEnableTouch->isChecked()); cfg.setConvertToImageColorspaceOnImport(dialog->m_general->convertToImageColorspaceOnImport()); cfg.setUndoStackLimit(dialog->m_general->undoStackSize()); cfg.setFavoritePresets(dialog->m_general->favoritePresets()); // Color settings cfg.setUseSystemMonitorProfile(dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()) { int currentIndex = dialog->m_colorSettings->m_monitorProfileWidgets[i]->currentIndex(); QString monitorid = dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemData(currentIndex).toString(); cfg.setMonitorForScreen(i, monitorid); } else { cfg.setMonitorProfile(i, dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemHighlighted(), dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); } } cfg.setWorkingColorSpace(dialog->m_colorSettings->m_page->cmbWorkingColorSpace->currentItem().id()); KisImageConfig cfgImage; cfgImage.setDefaultProofingConfig(dialog->m_colorSettings->m_page->proofingSpaceSelector->currentColorSpace(), dialog->m_colorSettings->m_page->cmbProofingIntent->currentIndex(), dialog->m_colorSettings->m_page->ckbProofBlackPoint->isChecked(), dialog->m_colorSettings->m_page->gamutAlarm->color(), (double)dialog->m_colorSettings->m_page->sldAdaptationState->value()/20); cfg.setUseBlackPointCompensation(dialog->m_colorSettings->m_page->chkBlackpoint->isChecked()); cfg.setAllowLCMSOptimization(dialog->m_colorSettings->m_page->chkAllowLCMSOptimization->isChecked()); cfg.setPasteBehaviour(dialog->m_colorSettings->m_pasteBehaviourGroup.checkedId()); cfg.setRenderIntent(dialog->m_colorSettings->m_page->cmbMonitorIntent->currentIndex()); // Tablet settings cfg.setPressureTabletCurve( dialog->m_tabletSettings->m_page->pressureCurve->curve().toString() ); #ifdef Q_OS_WIN if (KisTabletSupportWin8::isAvailable()) { cfg.setUseWin8PointerInput(dialog->m_tabletSettings->m_page->radioWin8PointerInput->isChecked()); } #endif dialog->m_performanceSettings->save(); #ifdef Q_OS_WIN { KisOpenGL::OpenGLRenderer renderer = static_cast( dialog->m_displaySettings->cmbRenderer->itemData( dialog->m_displaySettings->cmbRenderer->currentIndex()).toInt()); KisOpenGL::setNextUserOpenGLRendererConfig(renderer); const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); kritarc.setValue("OpenGLRenderer", KisOpenGL::convertOpenGLRendererToConfig(renderer)); } #endif if (!cfg.useOpenGL() && dialog->m_displaySettings->grpOpenGL->isChecked()) cfg.setCanvasState("TRY_OPENGL"); cfg.setUseOpenGL(dialog->m_displaySettings->grpOpenGL->isChecked()); cfg.setUseOpenGLTextureBuffer(dialog->m_displaySettings->chkUseTextureBuffer->isChecked()); cfg.setOpenGLFilteringMode(dialog->m_displaySettings->cmbFilterMode->currentIndex()); cfg.setDisableVSync(dialog->m_displaySettings->chkDisableVsync->isChecked()); cfg.setCheckSize(dialog->m_displaySettings->intCheckSize->value()); cfg.setScrollingCheckers(dialog->m_displaySettings->chkMoving->isChecked()); cfg.setCheckersColor1(dialog->m_displaySettings->colorChecks1->color().toQColor()); cfg.setCheckersColor2(dialog->m_displaySettings->colorChecks2->color().toQColor()); cfg.setCanvasBorderColor(dialog->m_displaySettings->canvasBorder->color().toQColor()); cfg.setHideScrollbars(dialog->m_displaySettings->hideScrollbars->isChecked()); KoColor c = dialog->m_displaySettings->btnSelectionOverlayColor->color(); c.setOpacity(dialog->m_displaySettings->sldSelectionOverlayOpacity->value()); cfg.setSelectionOverlayMaskColor(c.toQColor()); cfg.setAntialiasCurves(dialog->m_displaySettings->chkCurveAntialiasing->isChecked()); cfg.setAntialiasSelectionOutline(dialog->m_displaySettings->chkSelectionOutlineAntialiasing->isChecked()); cfg.setShowSingleChannelAsColor(dialog->m_displaySettings->chkChannelsAsColor->isChecked()); cfg.setHidePopups(dialog->m_displaySettings->chkHidePopups->isChecked()); cfg.setHideDockersFullscreen(dialog->m_fullscreenSettings->chkDockers->checkState()); cfg.setHideMenuFullscreen(dialog->m_fullscreenSettings->chkMenu->checkState()); cfg.setHideScrollbarsFullscreen(dialog->m_fullscreenSettings->chkScrollbars->checkState()); cfg.setHideStatusbarFullscreen(dialog->m_fullscreenSettings->chkStatusbar->checkState()); cfg.setHideTitlebarFullscreen(dialog->m_fullscreenSettings->chkTitlebar->checkState()); cfg.setHideToolbarFullscreen(dialog->m_fullscreenSettings->chkToolbar->checkState()); cfg.setCursorMainColor(dialog->m_general->cursorColorBtutton->color().toQColor()); cfg.setPixelGridColor(dialog->m_displaySettings->pixelGridColorButton->color().toQColor()); cfg.setPixelGridDrawingThreshold(dialog->m_displaySettings->pixelGridDrawingThresholdBox->value() / 100); cfg.enablePixelGrid(dialog->m_displaySettings->grpPixelGrid->isChecked()); dialog->m_authorPage->apply(); } delete dialog; return baccept; } diff --git a/libs/ui/forms/wdgperformancesettings.ui b/libs/ui/forms/wdgperformancesettings.ui index d8012e7772..01672ff8a1 100644 --- a/libs/ui/forms/wdgperformancesettings.ui +++ b/libs/ui/forms/wdgperformancesettings.ui @@ -1,354 +1,361 @@ WdgPerformanceSettings 0 0 753 - 554 + 613 RAM (needs restarting Krita) Memory available: 0 0 XXX MiB Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Krita will not use more memory than this limit. Memory Limit: 0 0 Krita will not use more memory than this limit. MiB Internal Pool: 0 0 MiB When undo information reaches this limit, it will be stored in a temporary file and memory will be freed. Undo will be slower. Swap Undo After: 0 0 When undo information reaches this limit, it will be stored in a temporary file and memory will be freed. Undo will be slower. MiB Swap File Size (needs restarting Krita) The swap file will not be bigger than this limit. File Size Limit: 0 0 The swap file will not be bigger than this limit. GiB Swap File Location: 0 0 TextLabel Select the location where Krita writes its swap files. ... Multithreading CPU Limit: 0 0 <html><head/><body><p>Krita will not use more CPU cores than selected by this limit</p></body></html> Frame Rendering Clones Limit 0 0 <html><head/><body><p>When rendering animation frames (into files or during animation cache regeneration), Krita will make the specified number of copies of your image and will work on them in parallel. Each copy will demand more RAM for its storage (about 20% of the size of you image), so raise this limit only if you have enough RAM installed.</p><p><br/></p><p><span style=" font-weight:600;">Recommended value:</span> set Clones Limit to the number of <span style=" text-decoration: underline;">physical</span> (non-hyperthreaded) cores your CPU has</p></body></html> Advanced (needs restarting Krita) Enable progress reporting (might affect performance) Enable performance logging QFrame::NoFrame <html><head/><body><p>When performance logging is enabled Krita saves timing information into the '&lt;working_dir&gt;/log' folder. If you experience performance problems and want to help us, enable this option and add the contents of the directory to a bug report.</p></body></html> true Enable debug logging of OpenGL framerate + + + + Enable debug logging for brush rendering speed + + + Disable vector optimizations (for AMD CPUs) Qt::Vertical 20 40 KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc index 25fd4a81a4..01a1f4fe35 100644 --- a/libs/ui/kis_config.cc +++ b/libs/ui/kis_config.cc @@ -1,1903 +1,1913 @@ /* * Copyright (c) 2002 Patrick Julien * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_canvas_resource_provider.h" #include "kis_config_notifier.h" #include "kis_snap_config.h" #include #include KisConfig::KisConfig() : m_cfg( KSharedConfig::openConfig()->group("")) { } KisConfig::~KisConfig() { if (qApp->thread() != QThread::currentThread()) { //dbgKrita << "WARNING: KisConfig: requested config synchronization from nonGUI thread! Skipping..."; return; } m_cfg.sync(); } bool KisConfig::disableTouchOnCanvas(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("disableTouchOnCanvas", false)); } void KisConfig::setDisableTouchOnCanvas(bool value) const { m_cfg.writeEntry("disableTouchOnCanvas", value); } bool KisConfig::useProjections(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("useProjections", true)); } void KisConfig::setUseProjections(bool useProj) const { m_cfg.writeEntry("useProjections", useProj); } bool KisConfig::undoEnabled(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("undoEnabled", true)); } void KisConfig::setUndoEnabled(bool undo) const { m_cfg.writeEntry("undoEnabled", undo); } int KisConfig::undoStackLimit(bool defaultValue) const { return (defaultValue ? 30 : m_cfg.readEntry("undoStackLimit", 30)); } void KisConfig::setUndoStackLimit(int limit) const { m_cfg.writeEntry("undoStackLimit", limit); } bool KisConfig::useCumulativeUndoRedo(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useCumulativeUndoRedo",false)); } void KisConfig::setCumulativeUndoRedo(bool value) { m_cfg.writeEntry("useCumulativeUndoRedo", value); } qreal KisConfig::stackT1(bool defaultValue) const { return (defaultValue ? 5 : m_cfg.readEntry("stackT1",5)); } void KisConfig::setStackT1(int T1) { m_cfg.writeEntry("stackT1", T1); } qreal KisConfig::stackT2(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("stackT2",1)); } void KisConfig::setStackT2(int T2) { m_cfg.writeEntry("stackT2", T2); } int KisConfig::stackN(bool defaultValue) const { return (defaultValue ? 5 : m_cfg.readEntry("stackN",5)); } void KisConfig::setStackN(int N) { m_cfg.writeEntry("stackN", N); } qint32 KisConfig::defImageWidth(bool defaultValue) const { return (defaultValue ? 1600 : m_cfg.readEntry("imageWidthDef", 1600)); } qint32 KisConfig::defImageHeight(bool defaultValue) const { return (defaultValue ? 1200 : m_cfg.readEntry("imageHeightDef", 1200)); } qreal KisConfig::defImageResolution(bool defaultValue) const { return (defaultValue ? 100.0 : m_cfg.readEntry("imageResolutionDef", 100.0)) / 72.0; } QString KisConfig::defColorModel(bool defaultValue) const { return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->colorModelId().id() : m_cfg.readEntry("colorModelDef", KoColorSpaceRegistry::instance()->rgb8()->colorModelId().id())); } void KisConfig::defColorModel(const QString & model) const { m_cfg.writeEntry("colorModelDef", model); } QString KisConfig::defaultColorDepth(bool defaultValue) const { return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->colorDepthId().id() : m_cfg.readEntry("colorDepthDef", KoColorSpaceRegistry::instance()->rgb8()->colorDepthId().id())); } void KisConfig::setDefaultColorDepth(const QString & depth) const { m_cfg.writeEntry("colorDepthDef", depth); } QString KisConfig::defColorProfile(bool defaultValue) const { return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->profile()->name() : m_cfg.readEntry("colorProfileDef", KoColorSpaceRegistry::instance()->rgb8()->profile()->name())); } void KisConfig::defColorProfile(const QString & profile) const { m_cfg.writeEntry("colorProfileDef", profile); } void KisConfig::defImageWidth(qint32 width) const { m_cfg.writeEntry("imageWidthDef", width); } void KisConfig::defImageHeight(qint32 height) const { m_cfg.writeEntry("imageHeightDef", height); } void KisConfig::defImageResolution(qreal res) const { m_cfg.writeEntry("imageResolutionDef", res*72.0); } void cleanOldCursorStyleKeys(KConfigGroup &cfg) { if (cfg.hasKey("newCursorStyle") && cfg.hasKey("newOutlineStyle")) { cfg.deleteEntry("cursorStyleDef"); } } CursorStyle KisConfig::newCursorStyle(bool defaultValue) const { if (defaultValue) { return CURSOR_STYLE_NO_CURSOR; } int style = m_cfg.readEntry("newCursorStyle", int(-1)); if (style < 0) { // old style format style = m_cfg.readEntry("cursorStyleDef", int(OLD_CURSOR_STYLE_OUTLINE)); switch (style) { case OLD_CURSOR_STYLE_TOOLICON: style = CURSOR_STYLE_TOOLICON; break; case OLD_CURSOR_STYLE_CROSSHAIR: case OLD_CURSOR_STYLE_OUTLINE_CENTER_CROSS: style = CURSOR_STYLE_CROSSHAIR; break; case OLD_CURSOR_STYLE_POINTER: style = CURSOR_STYLE_POINTER; break; case OLD_CURSOR_STYLE_OUTLINE: case OLD_CURSOR_STYLE_NO_CURSOR: style = CURSOR_STYLE_NO_CURSOR; break; case OLD_CURSOR_STYLE_SMALL_ROUND: case OLD_CURSOR_STYLE_OUTLINE_CENTER_DOT: style = CURSOR_STYLE_SMALL_ROUND; break; case OLD_CURSOR_STYLE_TRIANGLE_RIGHTHANDED: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_RIGHTHANDED: style = CURSOR_STYLE_TRIANGLE_RIGHTHANDED; break; case OLD_CURSOR_STYLE_TRIANGLE_LEFTHANDED: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_LEFTHANDED: style = CURSOR_STYLE_TRIANGLE_LEFTHANDED; break; default: style = -1; } } cleanOldCursorStyleKeys(m_cfg); // compatibility with future versions if (style < 0 || style >= N_CURSOR_STYLE_SIZE) { style = CURSOR_STYLE_NO_CURSOR; } return (CursorStyle) style; } void KisConfig::setNewCursorStyle(CursorStyle style) { m_cfg.writeEntry("newCursorStyle", (int)style); } QColor KisConfig::getCursorMainColor(bool defaultValue) const { QColor col; col.setRgbF(0.501961, 1.0, 0.501961); return (defaultValue ? col : m_cfg.readEntry("cursorMaincColor", col)); } void KisConfig::setCursorMainColor(const QColor &v) const { m_cfg.writeEntry("cursorMaincColor", v); } OutlineStyle KisConfig::newOutlineStyle(bool defaultValue) const { if (defaultValue) { return OUTLINE_FULL; } int style = m_cfg.readEntry("newOutlineStyle", int(-1)); if (style < 0) { // old style format style = m_cfg.readEntry("cursorStyleDef", int(OLD_CURSOR_STYLE_OUTLINE)); switch (style) { case OLD_CURSOR_STYLE_TOOLICON: case OLD_CURSOR_STYLE_CROSSHAIR: case OLD_CURSOR_STYLE_POINTER: case OLD_CURSOR_STYLE_NO_CURSOR: case OLD_CURSOR_STYLE_SMALL_ROUND: case OLD_CURSOR_STYLE_TRIANGLE_RIGHTHANDED: case OLD_CURSOR_STYLE_TRIANGLE_LEFTHANDED: style = OUTLINE_NONE; break; case OLD_CURSOR_STYLE_OUTLINE: case OLD_CURSOR_STYLE_OUTLINE_CENTER_DOT: case OLD_CURSOR_STYLE_OUTLINE_CENTER_CROSS: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_RIGHTHANDED: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_LEFTHANDED: style = OUTLINE_FULL; break; default: style = -1; } } cleanOldCursorStyleKeys(m_cfg); // compatibility with future versions if (style < 0 || style >= N_OUTLINE_STYLE_SIZE) { style = OUTLINE_FULL; } return (OutlineStyle) style; } void KisConfig::setNewOutlineStyle(OutlineStyle style) { m_cfg.writeEntry("newOutlineStyle", (int)style); } QRect KisConfig::colorPreviewRect() const { return m_cfg.readEntry("colorPreviewRect", QVariant(QRect(32, 32, 48, 48))).toRect(); } void KisConfig::setColorPreviewRect(const QRect &rect) { m_cfg.writeEntry("colorPreviewRect", QVariant(rect)); } bool KisConfig::useDirtyPresets(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useDirtyPresets",false)); } void KisConfig::setUseDirtyPresets(bool value) { m_cfg.writeEntry("useDirtyPresets",value); KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::useEraserBrushSize(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useEraserBrushSize",false)); } void KisConfig::setUseEraserBrushSize(bool value) { m_cfg.writeEntry("useEraserBrushSize",value); KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::useEraserBrushOpacity(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useEraserBrushOpacity",false)); } void KisConfig::setUseEraserBrushOpacity(bool value) { m_cfg.writeEntry("useEraserBrushOpacity",value); KisConfigNotifier::instance()->notifyConfigChanged(); } QColor KisConfig::getMDIBackgroundColor(bool defaultValue) const { QColor col(77, 77, 77); return (defaultValue ? col : m_cfg.readEntry("mdiBackgroundColor", col)); } void KisConfig::setMDIBackgroundColor(const QColor &v) const { m_cfg.writeEntry("mdiBackgroundColor", v); } QString KisConfig::getMDIBackgroundImage(bool defaultValue) const { return (defaultValue ? "" : m_cfg.readEntry("mdiBackgroundImage", "")); } void KisConfig::setMDIBackgroundImage(const QString &filename) const { m_cfg.writeEntry("mdiBackgroundImage", filename); } QString KisConfig::monitorProfile(int screen) const { // Note: keep this in sync with the default profile for the RGB colorspaces! QString profile = m_cfg.readEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), "sRGB-elle-V2-srgbtrc.icc"); //dbgKrita << "KisConfig::monitorProfile()" << profile; return profile; } QString KisConfig::monitorForScreen(int screen, const QString &defaultMonitor, bool defaultValue) const { return (defaultValue ? defaultMonitor : m_cfg.readEntry(QString("monitor_for_screen_%1").arg(screen), defaultMonitor)); } void KisConfig::setMonitorForScreen(int screen, const QString& monitor) { m_cfg.writeEntry(QString("monitor_for_screen_%1").arg(screen), monitor); } void KisConfig::setMonitorProfile(int screen, const QString & monitorProfile, bool override) const { m_cfg.writeEntry("monitorProfile/OverrideX11", override); m_cfg.writeEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), monitorProfile); } const KoColorProfile *KisConfig::getScreenProfile(int screen) { if (screen < 0) return 0; KisConfig cfg; QString monitorId; if (KisColorManager::instance()->devices().size() > screen) { monitorId = cfg.monitorForScreen(screen, KisColorManager::instance()->devices()[screen]); } //dbgKrita << "getScreenProfile(). Screen" << screen << "monitor id" << monitorId; if (monitorId.isEmpty()) { return 0; } QByteArray bytes = KisColorManager::instance()->displayProfile(monitorId); //dbgKrita << "\tgetScreenProfile()" << bytes.size(); if (bytes.length() > 0) { const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(RGBAColorModelID.id(), Integer8BitsColorDepthID.id(), bytes); //dbgKrita << "\tKisConfig::getScreenProfile for screen" << screen << profile->name(); return profile; } else { //dbgKrita << "\tCould not get a system monitor profile"; return 0; } } const KoColorProfile *KisConfig::displayProfile(int screen) const { if (screen < 0) return 0; // if the user plays with the settings, they can override the display profile, in which case // we don't want the system setting. bool override = useSystemMonitorProfile(); //dbgKrita << "KisConfig::displayProfile(). Override X11:" << override; const KoColorProfile *profile = 0; if (override) { //dbgKrita << "\tGoing to get the screen profile"; profile = KisConfig::getScreenProfile(screen); } // if it fails. check the configuration if (!profile || !profile->isSuitableForDisplay()) { //dbgKrita << "\tGoing to get the monitor profile"; QString monitorProfileName = monitorProfile(screen); //dbgKrita << "\t\tmonitorProfileName:" << monitorProfileName; if (!monitorProfileName.isEmpty()) { profile = KoColorSpaceRegistry::instance()->profileByName(monitorProfileName); } if (profile) { //dbgKrita << "\t\tsuitable for display" << profile->isSuitableForDisplay(); } else { //dbgKrita << "\t\tstill no profile"; } } // if we still don't have a profile, or the profile isn't suitable for display, // we need to get a last-resort profile. the built-in sRGB is a good choice then. if (!profile || !profile->isSuitableForDisplay()) { //dbgKrita << "\tnothing worked, going to get sRGB built-in"; profile = KoColorSpaceRegistry::instance()->profileByName("sRGB Built-in"); } if (profile) { //dbgKrita << "\tKisConfig::displayProfile for screen" << screen << "is" << profile->name(); } else { //dbgKrita << "\tCouldn't get a display profile at all"; } return profile; } QString KisConfig::workingColorSpace(bool defaultValue) const { return (defaultValue ? "RGBA" : m_cfg.readEntry("workingColorSpace", "RGBA")); } void KisConfig::setWorkingColorSpace(const QString & workingColorSpace) const { m_cfg.writeEntry("workingColorSpace", workingColorSpace); } QString KisConfig::printerColorSpace(bool /*defaultValue*/) const { //TODO currently only rgb8 is supported //return (defaultValue ? "RGBA" : m_cfg.readEntry("printerColorSpace", "RGBA")); return QString("RGBA"); } void KisConfig::setPrinterColorSpace(const QString & printerColorSpace) const { m_cfg.writeEntry("printerColorSpace", printerColorSpace); } QString KisConfig::printerProfile(bool defaultValue) const { return (defaultValue ? "" : m_cfg.readEntry("printerProfile", "")); } void KisConfig::setPrinterProfile(const QString & printerProfile) const { m_cfg.writeEntry("printerProfile", printerProfile); } bool KisConfig::useBlackPointCompensation(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("useBlackPointCompensation", true)); } void KisConfig::setUseBlackPointCompensation(bool useBlackPointCompensation) const { m_cfg.writeEntry("useBlackPointCompensation", useBlackPointCompensation); } bool KisConfig::allowLCMSOptimization(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("allowLCMSOptimization", true)); } void KisConfig::setAllowLCMSOptimization(bool allowLCMSOptimization) { m_cfg.writeEntry("allowLCMSOptimization", allowLCMSOptimization); } bool KisConfig::showRulers(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showrulers", false)); } void KisConfig::setShowRulers(bool rulers) const { m_cfg.writeEntry("showrulers", rulers); } bool KisConfig::rulersTrackMouse(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("rulersTrackMouse", true)); } void KisConfig::setRulersTrackMouse(bool value) const { m_cfg.writeEntry("rulersTrackMouse", value); } qint32 KisConfig::pasteBehaviour(bool defaultValue) const { return (defaultValue ? 2 : m_cfg.readEntry("pasteBehaviour", 2)); } void KisConfig::setPasteBehaviour(qint32 renderIntent) const { m_cfg.writeEntry("pasteBehaviour", renderIntent); } qint32 KisConfig::monitorRenderIntent(bool defaultValue) const { qint32 intent = m_cfg.readEntry("renderIntent", INTENT_PERCEPTUAL); if (intent > 3) intent = 3; if (intent < 0) intent = 0; return (defaultValue ? INTENT_PERCEPTUAL : intent); } void KisConfig::setRenderIntent(qint32 renderIntent) const { if (renderIntent > 3) renderIntent = 3; if (renderIntent < 0) renderIntent = 0; m_cfg.writeEntry("renderIntent", renderIntent); } bool KisConfig::useOpenGL(bool defaultValue) const { if (defaultValue) { return true; } //dbgKrita << "use opengl" << m_cfg.readEntry("useOpenGL", true) << "success" << m_cfg.readEntry("canvasState", "OPENGL_SUCCESS"); QString cs = canvasState(); #ifdef Q_OS_WIN return (m_cfg.readEntry("useOpenGLWindows", true) && (cs == "OPENGL_SUCCESS" || cs == "TRY_OPENGL")); #else return (m_cfg.readEntry("useOpenGL", true) && (cs == "OPENGL_SUCCESS" || cs == "TRY_OPENGL")); #endif } void KisConfig::setUseOpenGL(bool useOpenGL) const { #ifdef Q_OS_WIN m_cfg.writeEntry("useOpenGLWindows", useOpenGL); #else m_cfg.writeEntry("useOpenGL", useOpenGL); #endif } int KisConfig::openGLFilteringMode(bool defaultValue) const { return (defaultValue ? 3 : m_cfg.readEntry("OpenGLFilterMode", 3)); } void KisConfig::setOpenGLFilteringMode(int filteringMode) { m_cfg.writeEntry("OpenGLFilterMode", filteringMode); } bool KisConfig::useOpenGLTextureBuffer(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("useOpenGLTextureBuffer", true)); } void KisConfig::setUseOpenGLTextureBuffer(bool useBuffer) { m_cfg.writeEntry("useOpenGLTextureBuffer", useBuffer); } int KisConfig::openGLTextureSize(bool defaultValue) const { return (defaultValue ? 256 : m_cfg.readEntry("textureSize", 256)); } bool KisConfig::disableVSync(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("disableVSync", true)); } void KisConfig::setDisableVSync(bool disableVSync) { m_cfg.writeEntry("disableVSync", disableVSync); } bool KisConfig::showAdvancedOpenGLSettings(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showAdvancedOpenGLSettings", false)); } bool KisConfig::forceOpenGLFenceWorkaround(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("forceOpenGLFenceWorkaround", false)); } int KisConfig::numMipmapLevels(bool defaultValue) const { return (defaultValue ? 4 : m_cfg.readEntry("numMipmapLevels", 4)); } int KisConfig::textureOverlapBorder() const { return 1 << qMax(0, numMipmapLevels()); } quint32 KisConfig::getGridMainStyle(bool defaultValue) const { int v = m_cfg.readEntry("gridmainstyle", 0); v = qBound(0, v, 2); return (defaultValue ? 0 : v); } void KisConfig::setGridMainStyle(quint32 v) const { m_cfg.writeEntry("gridmainstyle", v); } quint32 KisConfig::getGridSubdivisionStyle(bool defaultValue) const { quint32 v = m_cfg.readEntry("gridsubdivisionstyle", 1); if (v > 2) v = 2; return (defaultValue ? 1 : v); } void KisConfig::setGridSubdivisionStyle(quint32 v) const { m_cfg.writeEntry("gridsubdivisionstyle", v); } QColor KisConfig::getGridMainColor(bool defaultValue) const { QColor col(99, 99, 99); return (defaultValue ? col : m_cfg.readEntry("gridmaincolor", col)); } void KisConfig::setGridMainColor(const QColor & v) const { m_cfg.writeEntry("gridmaincolor", v); } QColor KisConfig::getGridSubdivisionColor(bool defaultValue) const { QColor col(150, 150, 150); return (defaultValue ? col : m_cfg.readEntry("gridsubdivisioncolor", col)); } void KisConfig::setGridSubdivisionColor(const QColor & v) const { m_cfg.writeEntry("gridsubdivisioncolor", v); } QColor KisConfig::getPixelGridColor(bool defaultValue) const { QColor col(255, 255, 255); return (defaultValue ? col : m_cfg.readEntry("pixelGridColor", col)); } void KisConfig::setPixelGridColor(const QColor & v) const { m_cfg.writeEntry("pixelGridColor", v); } qreal KisConfig::getPixelGridDrawingThreshold(bool defaultValue) const { qreal border = 8.0f; return (defaultValue ? border : m_cfg.readEntry("pixelGridDrawingThreshold", border)); } void KisConfig::setPixelGridDrawingThreshold(qreal v) const { m_cfg.writeEntry("pixelGridDrawingThreshold", v); } bool KisConfig::pixelGridEnabled(bool defaultValue) const { bool enabled = true; return (defaultValue ? enabled : m_cfg.readEntry("pixelGridEnabled", enabled)); } void KisConfig::enablePixelGrid(bool v) const { m_cfg.writeEntry("pixelGridEnabled", v); } quint32 KisConfig::guidesLineStyle(bool defaultValue) const { int v = m_cfg.readEntry("guidesLineStyle", 0); v = qBound(0, v, 2); return (defaultValue ? 0 : v); } void KisConfig::setGuidesLineStyle(quint32 v) const { m_cfg.writeEntry("guidesLineStyle", v); } QColor KisConfig::guidesColor(bool defaultValue) const { QColor col(99, 99, 99); return (defaultValue ? col : m_cfg.readEntry("guidesColor", col)); } void KisConfig::setGuidesColor(const QColor & v) const { m_cfg.writeEntry("guidesColor", v); } void KisConfig::loadSnapConfig(KisSnapConfig *config, bool defaultValue) const { KisSnapConfig defaultConfig(false); if (defaultValue) { *config = defaultConfig; return; } config->setOrthogonal(m_cfg.readEntry("globalSnapOrthogonal", defaultConfig.orthogonal())); config->setNode(m_cfg.readEntry("globalSnapNode", defaultConfig.node())); config->setExtension(m_cfg.readEntry("globalSnapExtension", defaultConfig.extension())); config->setIntersection(m_cfg.readEntry("globalSnapIntersection", defaultConfig.intersection())); config->setBoundingBox(m_cfg.readEntry("globalSnapBoundingBox", defaultConfig.boundingBox())); config->setImageBounds(m_cfg.readEntry("globalSnapImageBounds", defaultConfig.imageBounds())); config->setImageCenter(m_cfg.readEntry("globalSnapImageCenter", defaultConfig.imageCenter())); } void KisConfig::saveSnapConfig(const KisSnapConfig &config) { m_cfg.writeEntry("globalSnapOrthogonal", config.orthogonal()); m_cfg.writeEntry("globalSnapNode", config.node()); m_cfg.writeEntry("globalSnapExtension", config.extension()); m_cfg.writeEntry("globalSnapIntersection", config.intersection()); m_cfg.writeEntry("globalSnapBoundingBox", config.boundingBox()); m_cfg.writeEntry("globalSnapImageBounds", config.imageBounds()); m_cfg.writeEntry("globalSnapImageCenter", config.imageCenter()); } qint32 KisConfig::checkSize(bool defaultValue) const { return (defaultValue ? 32 : m_cfg.readEntry("checksize", 32)); } void KisConfig::setCheckSize(qint32 checksize) const { m_cfg.writeEntry("checksize", checksize); } bool KisConfig::scrollCheckers(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("scrollingcheckers", false)); } void KisConfig::setScrollingCheckers(bool sc) const { m_cfg.writeEntry("scrollingcheckers", sc); } QColor KisConfig::canvasBorderColor(bool defaultValue) const { QColor color(QColor(128,128,128)); return (defaultValue ? color : m_cfg.readEntry("canvasBorderColor", color)); } void KisConfig::setCanvasBorderColor(const QColor& color) const { m_cfg.writeEntry("canvasBorderColor", color); } bool KisConfig::hideScrollbars(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("hideScrollbars", false)); } void KisConfig::setHideScrollbars(bool value) const { m_cfg.writeEntry("hideScrollbars", value); } QColor KisConfig::checkersColor1(bool defaultValue) const { QColor col(220, 220, 220); return (defaultValue ? col : m_cfg.readEntry("checkerscolor", col)); } void KisConfig::setCheckersColor1(const QColor & v) const { m_cfg.writeEntry("checkerscolor", v); } QColor KisConfig::checkersColor2(bool defaultValue) const { return (defaultValue ? QColor(Qt::white) : m_cfg.readEntry("checkerscolor2", QColor(Qt::white))); } void KisConfig::setCheckersColor2(const QColor & v) const { m_cfg.writeEntry("checkerscolor2", v); } bool KisConfig::antialiasCurves(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("antialiascurves", true)); } void KisConfig::setAntialiasCurves(bool v) const { m_cfg.writeEntry("antialiascurves", v); } QColor KisConfig::selectionOverlayMaskColor(bool defaultValue) const { QColor def(255, 0, 0, 220); return (defaultValue ? def : m_cfg.readEntry("selectionOverlayMaskColor", def)); } void KisConfig::setSelectionOverlayMaskColor(const QColor &color) { m_cfg.writeEntry("selectionOverlayMaskColor", color); } bool KisConfig::antialiasSelectionOutline(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("AntialiasSelectionOutline", false)); } void KisConfig::setAntialiasSelectionOutline(bool v) const { m_cfg.writeEntry("AntialiasSelectionOutline", v); } bool KisConfig::showRootLayer(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ShowRootLayer", false)); } void KisConfig::setShowRootLayer(bool showRootLayer) const { m_cfg.writeEntry("ShowRootLayer", showRootLayer); } bool KisConfig::showGlobalSelection(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ShowGlobalSelection", false)); } void KisConfig::setShowGlobalSelection(bool showGlobalSelection) const { m_cfg.writeEntry("ShowGlobalSelection", showGlobalSelection); } bool KisConfig::showOutlineWhilePainting(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("ShowOutlineWhilePainting", true)); } void KisConfig::setShowOutlineWhilePainting(bool showOutlineWhilePainting) const { m_cfg.writeEntry("ShowOutlineWhilePainting", showOutlineWhilePainting); } bool KisConfig::hideSplashScreen(bool defaultValue) const { KConfigGroup cfg( KSharedConfig::openConfig(), "SplashScreen"); return (defaultValue ? true : cfg.readEntry("HideSplashAfterStartup", true)); } void KisConfig::setHideSplashScreen(bool hideSplashScreen) const { KConfigGroup cfg( KSharedConfig::openConfig(), "SplashScreen"); cfg.writeEntry("HideSplashAfterStartup", hideSplashScreen); } qreal KisConfig::outlineSizeMinimum(bool defaultValue) const { return (defaultValue ? 1.0 : m_cfg.readEntry("OutlineSizeMinimum", 1.0)); } void KisConfig::setOutlineSizeMinimum(qreal outlineSizeMinimum) const { m_cfg.writeEntry("OutlineSizeMinimum", outlineSizeMinimum); } qreal KisConfig::selectionViewSizeMinimum(bool defaultValue) const { return (defaultValue ? 5.0 : m_cfg.readEntry("SelectionViewSizeMinimum", 5.0)); } void KisConfig::setSelectionViewSizeMinimum(qreal outlineSizeMinimum) const { m_cfg.writeEntry("SelectionViewSizeMinimum", outlineSizeMinimum); } int KisConfig::autoSaveInterval(bool defaultValue) const { return (defaultValue ? 15 * 60 : m_cfg.readEntry("AutoSaveInterval", 15 * 60)); } void KisConfig::setAutoSaveInterval(int seconds) const { return m_cfg.writeEntry("AutoSaveInterval", seconds); } bool KisConfig::backupFile(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("CreateBackupFile", true)); } void KisConfig::setBackupFile(bool backupFile) const { m_cfg.writeEntry("CreateBackupFile", backupFile); } bool KisConfig::showFilterGallery(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showFilterGallery", false)); } void KisConfig::setShowFilterGallery(bool showFilterGallery) const { m_cfg.writeEntry("showFilterGallery", showFilterGallery); } bool KisConfig::showFilterGalleryLayerMaskDialog(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showFilterGalleryLayerMaskDialog", true)); } void KisConfig::setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const { m_cfg.writeEntry("setShowFilterGalleryLayerMaskDialog", showFilterGallery); } QString KisConfig::canvasState(bool defaultValue) const { const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); return (defaultValue ? "OPENGL_NOT_TRIED" : kritarc.value("canvasState", "OPENGL_NOT_TRIED").toString()); } void KisConfig::setCanvasState(const QString& state) const { static QStringList acceptableStates; if (acceptableStates.isEmpty()) { acceptableStates << "OPENGL_SUCCESS" << "TRY_OPENGL" << "OPENGL_NOT_TRIED" << "OPENGL_FAILED"; } if (acceptableStates.contains(state)) { const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat); kritarc.setValue("canvasState", state); } } bool KisConfig::toolOptionsPopupDetached(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ToolOptionsPopupDetached", false)); } void KisConfig::setToolOptionsPopupDetached(bool detached) const { m_cfg.writeEntry("ToolOptionsPopupDetached", detached); } bool KisConfig::paintopPopupDetached(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("PaintopPopupDetached", false)); } void KisConfig::setPaintopPopupDetached(bool detached) const { m_cfg.writeEntry("PaintopPopupDetached", detached); } QString KisConfig::pressureTabletCurve(bool defaultValue) const { return (defaultValue ? "0,0;1,1" : m_cfg.readEntry("tabletPressureCurve","0,0;1,1;")); } void KisConfig::setPressureTabletCurve(const QString& curveString) const { m_cfg.writeEntry("tabletPressureCurve", curveString); } bool KisConfig::useWin8PointerInput(bool defaultValue) const { #ifdef Q_OS_WIN return (defaultValue ? false : m_cfg.readEntry("useWin8PointerInput", false)); #else Q_UNUSED(defaultValue); return false; #endif } void KisConfig::setUseWin8PointerInput(bool value) const { #ifdef Q_OS_WIN // Special handling: Only set value if changed // I don't want it to be set if the user hasn't touched it if (useWin8PointerInput() != value) { m_cfg.writeEntry("useWin8PointerInput", value); } #else Q_UNUSED(value) #endif } qreal KisConfig::vastScrolling(bool defaultValue) const { return (defaultValue ? 0.9 : m_cfg.readEntry("vastScrolling", 0.9)); } void KisConfig::setVastScrolling(const qreal factor) const { m_cfg.writeEntry("vastScrolling", factor); } int KisConfig::presetChooserViewMode(bool defaultValue) const { return (defaultValue ? 0 : m_cfg.readEntry("presetChooserViewMode", 0)); } void KisConfig::setPresetChooserViewMode(const int mode) const { m_cfg.writeEntry("presetChooserViewMode", mode); } int KisConfig::presetIconSize(bool defaultValue) const { return (defaultValue ? 30 : m_cfg.readEntry("presetIconSize", 30)); } void KisConfig::setPresetIconSize(const int value) const { m_cfg.writeEntry("presetIconSize", value); } bool KisConfig::firstRun(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("firstRun", true)); } void KisConfig::setFirstRun(const bool first) const { m_cfg.writeEntry("firstRun", first); } int KisConfig::horizontalSplitLines(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("horizontalSplitLines", 1)); } void KisConfig::setHorizontalSplitLines(const int numberLines) const { m_cfg.writeEntry("horizontalSplitLines", numberLines); } int KisConfig::verticalSplitLines(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("verticalSplitLines", 1)); } void KisConfig::setVerticalSplitLines(const int numberLines) const { m_cfg.writeEntry("verticalSplitLines", numberLines); } bool KisConfig::clicklessSpacePan(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("clicklessSpacePan", true)); } void KisConfig::setClicklessSpacePan(const bool toggle) const { m_cfg.writeEntry("clicklessSpacePan", toggle); } bool KisConfig::hideDockersFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideDockersFullScreen", true)); } void KisConfig::setHideDockersFullscreen(const bool value) const { m_cfg.writeEntry("hideDockersFullScreen", value); } bool KisConfig::showDockerTitleBars(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showDockerTitleBars", true)); } void KisConfig::setShowDockerTitleBars(const bool value) const { m_cfg.writeEntry("showDockerTitleBars", value); } bool KisConfig::showDockers(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showDockers", true)); } void KisConfig::setShowDockers(const bool value) const { m_cfg.writeEntry("showDockers", value); } bool KisConfig::showStatusBar(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showStatusBar", true)); } void KisConfig::setShowStatusBar(const bool value) const { m_cfg.writeEntry("showStatusBar", value); } bool KisConfig::hideMenuFullscreen(bool defaultValue) const { return (defaultValue ? true: m_cfg.readEntry("hideMenuFullScreen", true)); } void KisConfig::setHideMenuFullscreen(const bool value) const { m_cfg.writeEntry("hideMenuFullScreen", value); } bool KisConfig::hideScrollbarsFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideScrollbarsFullScreen", true)); } void KisConfig::setHideScrollbarsFullscreen(const bool value) const { m_cfg.writeEntry("hideScrollbarsFullScreen", value); } bool KisConfig::hideStatusbarFullscreen(bool defaultValue) const { return (defaultValue ? true: m_cfg.readEntry("hideStatusbarFullScreen", true)); } void KisConfig::setHideStatusbarFullscreen(const bool value) const { m_cfg.writeEntry("hideStatusbarFullScreen", value); } bool KisConfig::hideTitlebarFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideTitleBarFullscreen", true)); } void KisConfig::setHideTitlebarFullscreen(const bool value) const { m_cfg.writeEntry("hideTitleBarFullscreen", value); } bool KisConfig::hideToolbarFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideToolbarFullscreen", true)); } void KisConfig::setHideToolbarFullscreen(const bool value) const { m_cfg.writeEntry("hideToolbarFullscreen", value); } bool KisConfig::fullscreenMode(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("fullscreenMode", true)); } void KisConfig::setFullscreenMode(const bool value) const { m_cfg.writeEntry("fullscreenMode", value); } QStringList KisConfig::favoriteCompositeOps(bool defaultValue) const { return (defaultValue ? QStringList() : m_cfg.readEntry("favoriteCompositeOps", QStringList())); } void KisConfig::setFavoriteCompositeOps(const QStringList& compositeOps) const { m_cfg.writeEntry("favoriteCompositeOps", compositeOps); } QString KisConfig::exportConfiguration(const QString &filterId, bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("ExportConfiguration-" + filterId, QString())); } void KisConfig::setExportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const { QString exportConfig = properties->toXML(); m_cfg.writeEntry("ExportConfiguration-" + filterId, exportConfig); } QString KisConfig::importConfiguration(const QString &filterId, bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("ImportConfiguration-" + filterId, QString())); } void KisConfig::setImportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const { QString importConfig = properties->toXML(); m_cfg.writeEntry("ImportConfiguration-" + filterId, importConfig); } bool KisConfig::useOcio(bool defaultValue) const { #ifdef HAVE_OCIO return (defaultValue ? false : m_cfg.readEntry("Krita/Ocio/UseOcio", false)); #else Q_UNUSED(defaultValue); return false; #endif } void KisConfig::setUseOcio(bool useOCIO) const { m_cfg.writeEntry("Krita/Ocio/UseOcio", useOCIO); } int KisConfig::favoritePresets(bool defaultValue) const { return (defaultValue ? 10 : m_cfg.readEntry("numFavoritePresets", 10)); } void KisConfig::setFavoritePresets(const int value) { m_cfg.writeEntry("numFavoritePresets", value); } bool KisConfig::levelOfDetailEnabled(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("levelOfDetailEnabled", false)); } void KisConfig::setLevelOfDetailEnabled(bool value) { m_cfg.writeEntry("levelOfDetailEnabled", value); } KisConfig::OcioColorManagementMode KisConfig::ocioColorManagementMode(bool defaultValue) const { return (OcioColorManagementMode)(defaultValue ? INTERNAL : m_cfg.readEntry("Krita/Ocio/OcioColorManagementMode", (int) INTERNAL)); } void KisConfig::setOcioColorManagementMode(OcioColorManagementMode mode) const { m_cfg.writeEntry("Krita/Ocio/OcioColorManagementMode", (int) mode); } QString KisConfig::ocioConfigurationPath(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("Krita/Ocio/OcioConfigPath", QString())); } void KisConfig::setOcioConfigurationPath(const QString &path) const { m_cfg.writeEntry("Krita/Ocio/OcioConfigPath", path); } QString KisConfig::ocioLutPath(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("Krita/Ocio/OcioLutPath", QString())); } void KisConfig::setOcioLutPath(const QString &path) const { m_cfg.writeEntry("Krita/Ocio/OcioLutPath", path); } int KisConfig::ocioLutEdgeSize(bool defaultValue) const { return (defaultValue ? 64 : m_cfg.readEntry("Krita/Ocio/LutEdgeSize", 64)); } void KisConfig::setOcioLutEdgeSize(int value) { m_cfg.writeEntry("Krita/Ocio/LutEdgeSize", value); } bool KisConfig::ocioLockColorVisualRepresentation(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("Krita/Ocio/OcioLockColorVisualRepresentation", false)); } void KisConfig::setOcioLockColorVisualRepresentation(bool value) { m_cfg.writeEntry("Krita/Ocio/OcioLockColorVisualRepresentation", value); } QString KisConfig::defaultPalette(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("defaultPalette", QString())); } void KisConfig::setDefaultPalette(const QString& name) const { m_cfg.writeEntry("defaultPalette", name); } QString KisConfig::toolbarSlider(int sliderNumber, bool defaultValue) const { QString def = "flow"; if (sliderNumber == 1) { def = "opacity"; } if (sliderNumber == 2) { def = "size"; } return (defaultValue ? def : m_cfg.readEntry(QString("toolbarslider_%1").arg(sliderNumber), def)); } void KisConfig::setToolbarSlider(int sliderNumber, const QString &slider) { m_cfg.writeEntry(QString("toolbarslider_%1").arg(sliderNumber), slider); } bool KisConfig::sliderLabels(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("sliderLabels", true)); } void KisConfig::setSliderLabels(bool enabled) { m_cfg.writeEntry("sliderLabels", enabled); } QString KisConfig::currentInputProfile(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("currentInputProfile", QString())); } void KisConfig::setCurrentInputProfile(const QString& name) { m_cfg.writeEntry("currentInputProfile", name); } bool KisConfig::useSystemMonitorProfile(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ColorManagement/UseSystemMonitorProfile", false)); } void KisConfig::setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const { m_cfg.writeEntry("ColorManagement/UseSystemMonitorProfile", _useSystemMonitorProfile); } bool KisConfig::presetStripVisible(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("presetStripVisible", true)); } void KisConfig::setPresetStripVisible(bool visible) { m_cfg.writeEntry("presetStripVisible", visible); } bool KisConfig::scratchpadVisible(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("scratchpadVisible", true)); } void KisConfig::setScratchpadVisible(bool visible) { m_cfg.writeEntry("scratchpadVisible", visible); } bool KisConfig::showSingleChannelAsColor(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showSingleChannelAsColor", false)); } void KisConfig::setShowSingleChannelAsColor(bool asColor) { m_cfg.writeEntry("showSingleChannelAsColor", asColor); } bool KisConfig::hidePopups(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("hidePopups", false)); } void KisConfig::setHidePopups(bool hidepopups) { m_cfg.writeEntry("hidePopups", hidepopups); } int KisConfig::numDefaultLayers(bool defaultValue) const { return (defaultValue ? 2 : m_cfg.readEntry("NumberOfLayersForNewImage", 2)); } void KisConfig::setNumDefaultLayers(int num) { m_cfg.writeEntry("NumberOfLayersForNewImage", num); } quint8 KisConfig::defaultBackgroundOpacity(bool defaultValue) const { return (defaultValue ? (int)OPACITY_OPAQUE_U8 : m_cfg.readEntry("BackgroundOpacityForNewImage", (int)OPACITY_OPAQUE_U8)); } void KisConfig::setDefaultBackgroundOpacity(quint8 value) { m_cfg.writeEntry("BackgroundOpacityForNewImage", (int)value); } QColor KisConfig::defaultBackgroundColor(bool defaultValue) const { return (defaultValue ? QColor(Qt::white) : m_cfg.readEntry("BackgroundColorForNewImage", QColor(Qt::white))); } void KisConfig::setDefaultBackgroundColor(QColor value) { m_cfg.writeEntry("BackgroundColorForNewImage", value); } KisConfig::BackgroundStyle KisConfig::defaultBackgroundStyle(bool defaultValue) const { return (KisConfig::BackgroundStyle)(defaultValue ? LAYER : m_cfg.readEntry("BackgroundStyleForNewImage", (int)LAYER)); } void KisConfig::setDefaultBackgroundStyle(KisConfig::BackgroundStyle value) { m_cfg.writeEntry("BackgroundStyleForNewImage", (int)value); } int KisConfig::lineSmoothingType(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("LineSmoothingType", 1)); } void KisConfig::setLineSmoothingType(int value) { m_cfg.writeEntry("LineSmoothingType", value); } qreal KisConfig::lineSmoothingDistance(bool defaultValue) const { return (defaultValue ? 50.0 : m_cfg.readEntry("LineSmoothingDistance", 50.0)); } void KisConfig::setLineSmoothingDistance(qreal value) { m_cfg.writeEntry("LineSmoothingDistance", value); } qreal KisConfig::lineSmoothingTailAggressiveness(bool defaultValue) const { return (defaultValue ? 0.15 : m_cfg.readEntry("LineSmoothingTailAggressiveness", 0.15)); } void KisConfig::setLineSmoothingTailAggressiveness(qreal value) { m_cfg.writeEntry("LineSmoothingTailAggressiveness", value); } bool KisConfig::lineSmoothingSmoothPressure(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("LineSmoothingSmoothPressure", false)); } void KisConfig::setLineSmoothingSmoothPressure(bool value) { m_cfg.writeEntry("LineSmoothingSmoothPressure", value); } bool KisConfig::lineSmoothingScalableDistance(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingScalableDistance", true)); } void KisConfig::setLineSmoothingScalableDistance(bool value) { m_cfg.writeEntry("LineSmoothingScalableDistance", value); } qreal KisConfig::lineSmoothingDelayDistance(bool defaultValue) const { return (defaultValue ? 50.0 : m_cfg.readEntry("LineSmoothingDelayDistance", 50.0)); } void KisConfig::setLineSmoothingDelayDistance(qreal value) { m_cfg.writeEntry("LineSmoothingDelayDistance", value); } bool KisConfig::lineSmoothingUseDelayDistance(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingUseDelayDistance", true)); } void KisConfig::setLineSmoothingUseDelayDistance(bool value) { m_cfg.writeEntry("LineSmoothingUseDelayDistance", value); } bool KisConfig::lineSmoothingFinishStabilizedCurve(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingFinishStabilizedCurve", true)); } void KisConfig::setLineSmoothingFinishStabilizedCurve(bool value) { m_cfg.writeEntry("LineSmoothingFinishStabilizedCurve", value); } bool KisConfig::lineSmoothingStabilizeSensors(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingStabilizeSensors", true)); } void KisConfig::setLineSmoothingStabilizeSensors(bool value) { m_cfg.writeEntry("LineSmoothingStabilizeSensors", value); } int KisConfig::paletteDockerPaletteViewSectionSize(bool defaultValue) const { return (defaultValue ? 12 : m_cfg.readEntry("paletteDockerPaletteViewSectionSize", 12)); } void KisConfig::setPaletteDockerPaletteViewSectionSize(int value) const { m_cfg.writeEntry("paletteDockerPaletteViewSectionSize", value); } int KisConfig::tabletEventsDelay(bool defaultValue) const { return (defaultValue ? 10 : m_cfg.readEntry("tabletEventsDelay", 10)); } void KisConfig::setTabletEventsDelay(int value) { m_cfg.writeEntry("tabletEventsDelay", value); } bool KisConfig::testingAcceptCompressedTabletEvents(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("testingAcceptCompressedTabletEvents", false)); } void KisConfig::setTestingAcceptCompressedTabletEvents(bool value) { m_cfg.writeEntry("testingAcceptCompressedTabletEvents", value); } bool KisConfig::shouldEatDriverShortcuts(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("shouldEatDriverShortcuts", false)); } bool KisConfig::testingCompressBrushEvents(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("testingCompressBrushEvents", false)); } void KisConfig::setTestingCompressBrushEvents(bool value) { m_cfg.writeEntry("testingCompressBrushEvents", value); } int KisConfig::workaroundX11SmoothPressureSteps(bool defaultValue) const { return (defaultValue ? 0 : m_cfg.readEntry("workaroundX11SmoothPressureSteps", 0)); } bool KisConfig::showCanvasMessages(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showOnCanvasMessages", true)); } void KisConfig::setShowCanvasMessages(bool show) { m_cfg.writeEntry("showOnCanvasMessages", show); } bool KisConfig::compressKra(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("compressLayersInKra", false)); } void KisConfig::setCompressKra(bool compress) { m_cfg.writeEntry("compressLayersInKra", compress); } bool KisConfig::toolOptionsInDocker(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("ToolOptionsInDocker", true)); } void KisConfig::setToolOptionsInDocker(bool inDocker) { m_cfg.writeEntry("ToolOptionsInDocker", inDocker); } const KoColorSpace* KisConfig::customColorSelectorColorSpace(bool defaultValue) const { const KoColorSpace *cs = 0; KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); if (defaultValue || cfg.readEntry("useCustomColorSpace", true)) { KoColorSpaceRegistry* csr = KoColorSpaceRegistry::instance(); QString modelID = cfg.readEntry("customColorSpaceModel", "RGBA"); QString depthID = cfg.readEntry("customColorSpaceDepthID", "U8"); QString profile = cfg.readEntry("customColorSpaceProfile", "sRGB built-in - (lcms internal)"); if (profile == "default") { // qDebug() << "Falling back to default color profile."; profile = "sRGB built-in - (lcms internal)"; } cs = csr->colorSpace(modelID, depthID, profile); } return cs; } void KisConfig::setCustomColorSelectorColorSpace(const KoColorSpace *cs) { KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); cfg.writeEntry("useCustomColorSpace", bool(cs)); if(cs) { cfg.writeEntry("customColorSpaceModel", cs->colorModelId().id()); cfg.writeEntry("customColorSpaceDepthID", cs->colorDepthId().id()); cfg.writeEntry("customColorSpaceProfile", cs->profile()->name()); } KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::enableOpenGLFramerateLogging(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("enableOpenGLFramerateLogging", false)); } void KisConfig::setEnableOpenGLFramerateLogging(bool value) const { m_cfg.writeEntry("enableOpenGLFramerateLogging", value); } +bool KisConfig::enableBrushSpeedLogging(bool defaultValue) const +{ + return (defaultValue ? false : m_cfg.readEntry("enableBrushSpeedLogging", false)); +} + +void KisConfig::setEnableBrushSpeedLogging(bool value) const +{ + m_cfg.writeEntry("enableBrushSpeedLogging", value); +} + void KisConfig::setEnableAmdVectorizationWorkaround(bool value) { m_cfg.writeEntry("amdDisableVectorWorkaround", value); } bool KisConfig::enableAmdVectorizationWorkaround(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("amdDisableVectorWorkaround", false)); } void KisConfig::setAnimationDropFrames(bool value) { bool oldValue = animationDropFrames(); if (value == oldValue) return; m_cfg.writeEntry("animationDropFrames", value); KisConfigNotifier::instance()->notifyDropFramesModeChanged(); } bool KisConfig::animationDropFrames(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("animationDropFrames", true)); } int KisConfig::scrubbingUpdatesDelay(bool defaultValue) const { return (defaultValue ? 30 : m_cfg.readEntry("scrubbingUpdatesDelay", 30)); } void KisConfig::setScrubbingUpdatesDelay(int value) { m_cfg.writeEntry("scrubbingUpdatesDelay", value); } int KisConfig::scrubbingAudioUpdatesDelay(bool defaultValue) const { return (defaultValue ? -1 : m_cfg.readEntry("scrubbingAudioUpdatesDelay", -1)); } void KisConfig::setScrubbingAudioUpdatesDelay(int value) { m_cfg.writeEntry("scrubbingAudioUpdatesDelay", value); } int KisConfig::audioOffsetTolerance(bool defaultValue) const { return (defaultValue ? -1 : m_cfg.readEntry("audioOffsetTolerance", -1)); } void KisConfig::setAudioOffsetTolerance(int value) { m_cfg.writeEntry("audioOffsetTolerance", value); } bool KisConfig::switchSelectionCtrlAlt(bool defaultValue) const { return defaultValue ? false : m_cfg.readEntry("switchSelectionCtrlAlt", false); } void KisConfig::setSwitchSelectionCtrlAlt(bool value) { m_cfg.writeEntry("switchSelectionCtrlAlt", value); KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::convertToImageColorspaceOnImport(bool defaultValue) const { return defaultValue ? false : m_cfg.readEntry("ConvertToImageColorSpaceOnImport", false); } void KisConfig::setConvertToImageColorspaceOnImport(bool value) { m_cfg.writeEntry("ConvertToImageColorSpaceOnImport", value); } int KisConfig::stabilizerSampleSize(bool defaultValue) const { #ifdef Q_OS_WIN const int defaultSampleSize = 50; #else const int defaultSampleSize = 15; #endif return defaultValue ? defaultSampleSize : m_cfg.readEntry("stabilizerSampleSize", defaultSampleSize); } void KisConfig::setStabilizerSampleSize(int value) { m_cfg.writeEntry("stabilizerSampleSize", value); } bool KisConfig::stabilizerDelayedPaint(bool defaultValue) const { const bool defaultEnabled = true; return defaultValue ? defaultEnabled : m_cfg.readEntry("stabilizerDelayedPaint", defaultEnabled); } void KisConfig::setStabilizerDelayedPaint(bool value) { m_cfg.writeEntry("stabilizerDelayedPaint", value); } QString KisConfig::customFFMpegPath(bool defaultValue) const { return defaultValue ? QString() : m_cfg.readEntry("ffmpegExecutablePath", QString()); } void KisConfig::setCustomFFMpegPath(const QString &value) const { m_cfg.writeEntry("ffmpegExecutablePath", value); } bool KisConfig::showBrushHud(bool defaultValue) const { return defaultValue ? false : m_cfg.readEntry("showBrushHud", false); } void KisConfig::setShowBrushHud(bool value) { m_cfg.writeEntry("showBrushHud", value); } QString KisConfig::brushHudSetting(bool defaultValue) const { QString defaultDoc = "\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n"; return defaultValue ? defaultDoc : m_cfg.readEntry("brushHudSettings", defaultDoc); } void KisConfig::setBrushHudSetting(const QString &value) const { m_cfg.writeEntry("brushHudSettings", value); } bool KisConfig::calculateAnimationCacheInBackground(bool defaultValue) const { return defaultValue ? true : m_cfg.readEntry("calculateAnimationCacheInBackground", true); } void KisConfig::setCalculateAnimationCacheInBackground(bool value) { m_cfg.writeEntry("calculateAnimationCacheInBackground", value); } #include #include void KisConfig::writeKoColor(const QString& name, const KoColor& color) const { QDomDocument doc = QDomDocument(name); QDomElement el = doc.createElement(name); doc.appendChild(el); color.toXML(doc, el); m_cfg.writeEntry(name, doc.toString()); } //ported from kispropertiesconfig. KoColor KisConfig::readKoColor(const QString& name, const KoColor& color) const { QDomDocument doc; if (!m_cfg.readEntry(name).isNull()) { doc.setContent(m_cfg.readEntry(name)); QDomElement e = doc.documentElement().firstChild().toElement(); return KoColor::fromXML(e, Integer16BitsColorDepthID.id()); } else { QString blackColor = "\n\n \n\n"; doc.setContent(blackColor); QDomElement e = doc.documentElement().firstChild().toElement(); return KoColor::fromXML(e, Integer16BitsColorDepthID.id()); } return color; } diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h index 210b00065a..8eb8eefb25 100644 --- a/libs/ui/kis_config.h +++ b/libs/ui/kis_config.h @@ -1,562 +1,565 @@ /* * Copyright (c) 2002 Patrick Julien * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CONFIG_H_ #define KIS_CONFIG_H_ #include #include #include #include #include #include #include "kis_global.h" #include "kis_properties_configuration.h" #include "kritaui_export.h" class KoColorProfile; class KoColorSpace; class KisSnapConfig; class KRITAUI_EXPORT KisConfig { public: KisConfig(); ~KisConfig(); bool disableTouchOnCanvas(bool defaultValue = false) const; void setDisableTouchOnCanvas(bool value) const; bool useProjections(bool defaultValue = false) const; void setUseProjections(bool useProj) const; bool undoEnabled(bool defaultValue = false) const; void setUndoEnabled(bool undo) const; int undoStackLimit(bool defaultValue = false) const; void setUndoStackLimit(int limit) const; bool useCumulativeUndoRedo(bool defaultValue = false) const; void setCumulativeUndoRedo(bool value); double stackT1(bool defaultValue = false) const; void setStackT1(int T1); double stackT2(bool defaultValue = false) const; void setStackT2(int T2); int stackN(bool defaultValue = false) const; void setStackN(int N); qint32 defImageWidth(bool defaultValue = false) const; void defImageWidth(qint32 width) const; qint32 defImageHeight(bool defaultValue = false) const; void defImageHeight(qint32 height) const; qreal defImageResolution(bool defaultValue = false) const; void defImageResolution(qreal res) const; /** * @return the id of the default color model used for creating new images. */ QString defColorModel(bool defaultValue = false) const; /** * set the id of the default color model used for creating new images. */ void defColorModel(const QString & model) const; /** * @return the id of the default color depth used for creating new images. */ QString defaultColorDepth(bool defaultValue = false) const; /** * set the id of the default color depth used for creating new images. */ void setDefaultColorDepth(const QString & depth) const; /** * @return the id of the default color profile used for creating new images. */ QString defColorProfile(bool defaultValue = false) const; /** * set the id of the default color profile used for creating new images. */ void defColorProfile(const QString & depth) const; CursorStyle newCursorStyle(bool defaultValue = false) const; void setNewCursorStyle(CursorStyle style); QColor getCursorMainColor(bool defaultValue = false) const; void setCursorMainColor(const QColor& v) const; OutlineStyle newOutlineStyle(bool defaultValue = false) const; void setNewOutlineStyle(OutlineStyle style); QRect colorPreviewRect() const; void setColorPreviewRect(const QRect &rect); /// get the profile the user has selected for the given screen QString monitorProfile(int screen) const; void setMonitorProfile(int screen, const QString & monitorProfile, bool override) const; QString monitorForScreen(int screen, const QString &defaultMonitor, bool defaultValue = true) const; void setMonitorForScreen(int screen, const QString& monitor); /// Get the actual profile to be used for the given screen, which is /// either the screen profile set by the color management system or /// the custom monitor profile set by the user, depending on the configuration const KoColorProfile *displayProfile(int screen) const; QString workingColorSpace(bool defaultValue = false) const; void setWorkingColorSpace(const QString & workingColorSpace) const; QString importProfile(bool defaultValue = false) const; void setImportProfile(const QString & importProfile) const; QString printerColorSpace(bool defaultValue = false) const; void setPrinterColorSpace(const QString & printerColorSpace) const; QString printerProfile(bool defaultValue = false) const; void setPrinterProfile(const QString & printerProfile) const; bool useBlackPointCompensation(bool defaultValue = false) const; void setUseBlackPointCompensation(bool useBlackPointCompensation) const; bool allowLCMSOptimization(bool defaultValue = false) const; void setAllowLCMSOptimization(bool allowLCMSOptimization); void writeKoColor(const QString& name, const KoColor& color) const; KoColor readKoColor(const QString& name, const KoColor& color = KoColor()) const; bool showRulers(bool defaultValue = false) const; void setShowRulers(bool rulers) const; bool rulersTrackMouse(bool defaultValue = false) const; void setRulersTrackMouse(bool value) const; qint32 pasteBehaviour(bool defaultValue = false) const; void setPasteBehaviour(qint32 behaviour) const; qint32 monitorRenderIntent(bool defaultValue = false) const; void setRenderIntent(qint32 monitorRenderIntent) const; bool useOpenGL(bool defaultValue = false) const; void setUseOpenGL(bool useOpenGL) const; int openGLFilteringMode(bool defaultValue = false) const; void setOpenGLFilteringMode(int filteringMode); bool useOpenGLTextureBuffer(bool defaultValue = false) const; void setUseOpenGLTextureBuffer(bool useBuffer); bool disableVSync(bool defaultValue = false) const; void setDisableVSync(bool disableVSync); bool showAdvancedOpenGLSettings(bool defaultValue = false) const; bool forceOpenGLFenceWorkaround(bool defaultValue = false) const; int numMipmapLevels(bool defaultValue = false) const; int openGLTextureSize(bool defaultValue = false) const; int textureOverlapBorder() const; quint32 getGridMainStyle(bool defaultValue = false) const; void setGridMainStyle(quint32 v) const; quint32 getGridSubdivisionStyle(bool defaultValue = false) const; void setGridSubdivisionStyle(quint32 v) const; QColor getGridMainColor(bool defaultValue = false) const; void setGridMainColor(const QColor & v) const; QColor getGridSubdivisionColor(bool defaultValue = false) const; void setGridSubdivisionColor(const QColor & v) const; QColor getPixelGridColor(bool defaultValue = false) const; void setPixelGridColor(const QColor & v) const; qreal getPixelGridDrawingThreshold(bool defaultValue = false) const; void setPixelGridDrawingThreshold(qreal v) const; bool pixelGridEnabled(bool defaultValue = false) const; void enablePixelGrid(bool v) const; quint32 guidesLineStyle(bool defaultValue = false) const; void setGuidesLineStyle(quint32 v) const; QColor guidesColor(bool defaultValue = false) const; void setGuidesColor(const QColor & v) const; void loadSnapConfig(KisSnapConfig *config, bool defaultValue = false) const; void saveSnapConfig(const KisSnapConfig &config); qint32 checkSize(bool defaultValue = false) const; void setCheckSize(qint32 checkSize) const; bool scrollCheckers(bool defaultValue = false) const; void setScrollingCheckers(bool scollCheckers) const; QColor checkersColor1(bool defaultValue = false) const; void setCheckersColor1(const QColor & v) const; QColor checkersColor2(bool defaultValue = false) const; void setCheckersColor2(const QColor & v) const; QColor canvasBorderColor(bool defaultValue = false) const; void setCanvasBorderColor(const QColor &color) const; bool hideScrollbars(bool defaultValue = false) const; void setHideScrollbars(bool value) const; bool antialiasCurves(bool defaultValue = false) const; void setAntialiasCurves(bool v) const; QColor selectionOverlayMaskColor(bool defaultValue = false) const; void setSelectionOverlayMaskColor(const QColor &color); bool antialiasSelectionOutline(bool defaultValue = false) const; void setAntialiasSelectionOutline(bool v) const; bool showRootLayer(bool defaultValue = false) const; void setShowRootLayer(bool showRootLayer) const; bool showGlobalSelection(bool defaultValue = false) const; void setShowGlobalSelection(bool showGlobalSelection) const; bool showOutlineWhilePainting(bool defaultValue = false) const; void setShowOutlineWhilePainting(bool showOutlineWhilePainting) const; bool hideSplashScreen(bool defaultValue = false) const; void setHideSplashScreen(bool hideSplashScreen) const; qreal outlineSizeMinimum(bool defaultValue = false) const; void setOutlineSizeMinimum(qreal outlineSizeMinimum) const; qreal selectionViewSizeMinimum(bool defaultValue = false) const; void setSelectionViewSizeMinimum(qreal outlineSizeMinimum) const; int autoSaveInterval(bool defaultValue = false) const; void setAutoSaveInterval(int seconds) const; bool backupFile(bool defaultValue = false) const; void setBackupFile(bool backupFile) const; bool showFilterGallery(bool defaultValue = false) const; void setShowFilterGallery(bool showFilterGallery) const; bool showFilterGalleryLayerMaskDialog(bool defaultValue = false) const; void setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const; // OPENGL_SUCCESS, TRY_OPENGL, OPENGL_NOT_TRIED, OPENGL_FAILED QString canvasState(bool defaultValue = false) const; void setCanvasState(const QString& state) const; bool toolOptionsPopupDetached(bool defaultValue = false) const; void setToolOptionsPopupDetached(bool detached) const; bool paintopPopupDetached(bool defaultValue = false) const; void setPaintopPopupDetached(bool detached) const; QString pressureTabletCurve(bool defaultValue = false) const; void setPressureTabletCurve(const QString& curveString) const; bool useWin8PointerInput(bool defaultValue = false) const; void setUseWin8PointerInput(bool value) const; qreal vastScrolling(bool defaultValue = false) const; void setVastScrolling(const qreal factor) const; int presetChooserViewMode(bool defaultValue = false) const; void setPresetChooserViewMode(const int mode) const; int presetIconSize(bool defaultValue = false) const; void setPresetIconSize(const int value) const; bool firstRun(bool defaultValue = false) const; void setFirstRun(const bool firstRun) const; bool clicklessSpacePan(bool defaultValue = false) const; void setClicklessSpacePan(const bool toggle) const; int horizontalSplitLines(bool defaultValue = false) const; void setHorizontalSplitLines(const int numberLines) const; int verticalSplitLines(bool defaultValue = false) const; void setVerticalSplitLines(const int numberLines) const; bool hideDockersFullscreen(bool defaultValue = false) const; void setHideDockersFullscreen(const bool value) const; bool showDockerTitleBars(bool defaultValue = false) const; void setShowDockerTitleBars(const bool value) const; bool showDockers(bool defaultValue = false) const; void setShowDockers(const bool value) const; bool showStatusBar(bool defaultValue = false) const; void setShowStatusBar(const bool value) const; bool hideMenuFullscreen(bool defaultValue = false) const; void setHideMenuFullscreen(const bool value) const; bool hideScrollbarsFullscreen(bool defaultValue = false) const; void setHideScrollbarsFullscreen(const bool value) const; bool hideStatusbarFullscreen(bool defaultValue = false) const; void setHideStatusbarFullscreen(const bool value) const; bool hideTitlebarFullscreen(bool defaultValue = false) const; void setHideTitlebarFullscreen(const bool value) const; bool hideToolbarFullscreen(bool defaultValue = false) const; void setHideToolbarFullscreen(const bool value) const; bool fullscreenMode(bool defaultValue = false) const; void setFullscreenMode(const bool value) const; QStringList favoriteCompositeOps(bool defaultValue = false) const; void setFavoriteCompositeOps(const QStringList& compositeOps) const; QString exportConfiguration(const QString &filterId, bool defaultValue = false) const; void setExportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const; QString importConfiguration(const QString &filterId, bool defaultValue = false) const; void setImportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const; bool useOcio(bool defaultValue = false) const; void setUseOcio(bool useOCIO) const; int favoritePresets(bool defaultValue = false) const; void setFavoritePresets(const int value); bool levelOfDetailEnabled(bool defaultValue = false) const; void setLevelOfDetailEnabled(bool value); enum OcioColorManagementMode { INTERNAL = 0, OCIO_CONFIG, OCIO_ENVIRONMENT }; OcioColorManagementMode ocioColorManagementMode(bool defaultValue = false) const; void setOcioColorManagementMode(OcioColorManagementMode mode) const; QString ocioConfigurationPath(bool defaultValue = false) const; void setOcioConfigurationPath(const QString &path) const; QString ocioLutPath(bool defaultValue = false) const; void setOcioLutPath(const QString &path) const; int ocioLutEdgeSize(bool defaultValue = false) const; void setOcioLutEdgeSize(int value); bool ocioLockColorVisualRepresentation(bool defaultValue = false) const; void setOcioLockColorVisualRepresentation(bool value); bool useSystemMonitorProfile(bool defaultValue = false) const; void setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const; QString defaultPalette(bool defaultValue = false) const; void setDefaultPalette(const QString& name) const; QString toolbarSlider(int sliderNumber, bool defaultValue = false) const; void setToolbarSlider(int sliderNumber, const QString &slider); bool sliderLabels(bool defaultValue = false) const; void setSliderLabels(bool enabled); QString currentInputProfile(bool defaultValue = false) const; void setCurrentInputProfile(const QString& name); bool presetStripVisible(bool defaultValue = false) const; void setPresetStripVisible(bool visible); bool scratchpadVisible(bool defaultValue = false) const; void setScratchpadVisible(bool visible); bool showSingleChannelAsColor(bool defaultValue = false) const; void setShowSingleChannelAsColor(bool asColor); bool hidePopups(bool defaultValue = false) const; void setHidePopups(bool hidepopups); int numDefaultLayers(bool defaultValue = false) const; void setNumDefaultLayers(int num); quint8 defaultBackgroundOpacity(bool defaultValue = false) const; void setDefaultBackgroundOpacity(quint8 value); QColor defaultBackgroundColor(bool defaultValue = false) const; void setDefaultBackgroundColor(QColor value); enum BackgroundStyle { LAYER = 0, PROJECTION = 1 }; BackgroundStyle defaultBackgroundStyle(bool defaultValue = false) const; void setDefaultBackgroundStyle(BackgroundStyle value); int lineSmoothingType(bool defaultValue = false) const; void setLineSmoothingType(int value); qreal lineSmoothingDistance(bool defaultValue = false) const; void setLineSmoothingDistance(qreal value); qreal lineSmoothingTailAggressiveness(bool defaultValue = false) const; void setLineSmoothingTailAggressiveness(qreal value); bool lineSmoothingSmoothPressure(bool defaultValue = false) const; void setLineSmoothingSmoothPressure(bool value); bool lineSmoothingScalableDistance(bool defaultValue = false) const; void setLineSmoothingScalableDistance(bool value); qreal lineSmoothingDelayDistance(bool defaultValue = false) const; void setLineSmoothingDelayDistance(qreal value); bool lineSmoothingUseDelayDistance(bool defaultValue = false) const; void setLineSmoothingUseDelayDistance(bool value); bool lineSmoothingFinishStabilizedCurve(bool defaultValue = false) const; void setLineSmoothingFinishStabilizedCurve(bool value); bool lineSmoothingStabilizeSensors(bool defaultValue = false) const; void setLineSmoothingStabilizeSensors(bool value); int paletteDockerPaletteViewSectionSize(bool defaultValue = false) const; void setPaletteDockerPaletteViewSectionSize(int value) const; int tabletEventsDelay(bool defaultValue = false) const; void setTabletEventsDelay(int value); bool testingAcceptCompressedTabletEvents(bool defaultValue = false) const; void setTestingAcceptCompressedTabletEvents(bool value); bool shouldEatDriverShortcuts(bool defaultValue = false) const; bool testingCompressBrushEvents(bool defaultValue = false) const; void setTestingCompressBrushEvents(bool value); const KoColorSpace* customColorSelectorColorSpace(bool defaultValue = false) const; void setCustomColorSelectorColorSpace(const KoColorSpace *cs); bool useDirtyPresets(bool defaultValue = false) const; void setUseDirtyPresets(bool value); bool useEraserBrushSize(bool defaultValue = false) const; void setUseEraserBrushSize(bool value); bool useEraserBrushOpacity(bool defaultValue = false) const; void setUseEraserBrushOpacity(bool value); QColor getMDIBackgroundColor(bool defaultValue = false) const; void setMDIBackgroundColor(const QColor & v) const; QString getMDIBackgroundImage(bool defaultValue = false) const; void setMDIBackgroundImage(const QString & fileName) const; int workaroundX11SmoothPressureSteps(bool defaultValue = false) const; bool showCanvasMessages(bool defaultValue = false) const; void setShowCanvasMessages(bool show); bool compressKra(bool defaultValue = false) const; void setCompressKra(bool compress); bool toolOptionsInDocker(bool defaultValue = false) const; void setToolOptionsInDocker(bool inDocker); void setEnableOpenGLFramerateLogging(bool value) const; bool enableOpenGLFramerateLogging(bool defaultValue = false) const; + void setEnableBrushSpeedLogging(bool value) const; + bool enableBrushSpeedLogging(bool defaultValue = false) const; + void setEnableAmdVectorizationWorkaround(bool value); bool enableAmdVectorizationWorkaround(bool defaultValue = false) const; bool animationDropFrames(bool defaultValue = false) const; void setAnimationDropFrames(bool value); int scrubbingUpdatesDelay(bool defaultValue = false) const; void setScrubbingUpdatesDelay(int value); int scrubbingAudioUpdatesDelay(bool defaultValue = false) const; void setScrubbingAudioUpdatesDelay(int value); int audioOffsetTolerance(bool defaultValue = false) const; void setAudioOffsetTolerance(int value); bool switchSelectionCtrlAlt(bool defaultValue = false) const; void setSwitchSelectionCtrlAlt(bool value); bool convertToImageColorspaceOnImport(bool defaultValue = false) const; void setConvertToImageColorspaceOnImport(bool value); int stabilizerSampleSize(bool defaultValue = false) const; void setStabilizerSampleSize(int value); bool stabilizerDelayedPaint(bool defaultValue = false) const; void setStabilizerDelayedPaint(bool value); QString customFFMpegPath(bool defaultValue = false) const; void setCustomFFMpegPath(const QString &value) const; bool showBrushHud(bool defaultValue = false) const; void setShowBrushHud(bool value); QString brushHudSetting(bool defaultValue = false) const; void setBrushHudSetting(const QString &value) const; bool calculateAnimationCacheInBackground(bool defaultValue = false) const; void setCalculateAnimationCacheInBackground(bool value); template void writeEntry(const QString& name, const T& value) { m_cfg.writeEntry(name, value); } template void writeList(const QString& name, const QList& value) { m_cfg.writeEntry(name, value); } template T readEntry(const QString& name, const T& defaultValue=T()) { return m_cfg.readEntry(name, defaultValue); } template QList readList(const QString& name, const QList& defaultValue=QList()) { return m_cfg.readEntry(name, defaultValue); } /// get the profile the color managment system has stored for the given screen static const KoColorProfile* getScreenProfile(int screen); private: KisConfig(const KisConfig&); KisConfig& operator=(const KisConfig&) const; private: mutable KConfigGroup m_cfg; }; #endif // KIS_CONFIG_H_ diff --git a/libs/ui/kis_fps_decoration.cpp b/libs/ui/kis_fps_decoration.cpp index e5a79baf39..8e6f465a68 100644 --- a/libs/ui/kis_fps_decoration.cpp +++ b/libs/ui/kis_fps_decoration.cpp @@ -1,64 +1,99 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_fps_decoration.h" #include #include "kis_canvas2.h" #include "kis_coordinates_converter.h" #include "opengl/kis_opengl_canvas_debugger.h" +#include const QString KisFpsDecoration::idTag = "fps_decoration"; KisFpsDecoration::KisFpsDecoration(QPointer view) : KisCanvasDecoration(idTag, view) { setVisible(true); } KisFpsDecoration::~KisFpsDecoration() { } void KisFpsDecoration::drawDecoration(QPainter& gc, const QRectF& /*updateRect*/, const KisCoordinatesConverter */*converter*/, KisCanvas2* /*canvas*/) { #ifdef Q_OS_OSX - QPixmap pixmap(256, 64); + QPixmap pixmap(320, 128); pixmap.fill(Qt::transparent); { QPainter painter(&pixmap); draw(painter); } gc.drawPixmap(0, 0, pixmap); #else draw(gc); #endif } + + void KisFpsDecoration::draw(QPainter& gc) { - const qreal value = KisOpenglCanvasDebugger::instance()->accumulatedFps(); - const QString text = QString("FPS: %1").arg(QString::number(value, 'f', 1)); + QStringList lines; + + if (KisOpenglCanvasDebugger::instance()->showFpsOnCanvas()) { + const qreal value = KisOpenglCanvasDebugger::instance()->accumulatedFps(); + lines << QString("Canvas FPS: %1").arg(QString::number(value, 'f', 1)); + } + + KisStrokeSpeedMonitor *monitor = KisStrokeSpeedMonitor::instance(); + + if (monitor->haveStrokeSpeedMeasurement()) { + lines << QString("Last cursor/brush speed (px/ms): %1/%2%3") + .arg(monitor->lastCursorSpeed(), 0, 'f', 1) + .arg(monitor->lastRenderingSpeed(), 0, 'f', 1) + .arg(monitor->lastStrokeSaturated() ? " (!)" : ""); + lines << QString("Last brush framerate: %1 fps") + .arg(monitor->lastFps(), 0, 'f', 1); + + lines << QString("Average cursor/brush speed (px/ms): %1/%2") + .arg(monitor->avgCursorSpeed(), 0, 'f', 1) + .arg(monitor->avgRenderingSpeed(), 0, 'f', 1); + lines << QString("Average brush framerate: %1 fps") + .arg(monitor->avgFps(), 0, 'f', 1); + } + + + QPoint startPoint(20,30); + const int lineSpacing = QFontMetrics(gc.font()).lineSpacing(); + gc.save(); - gc.setPen(QPen(Qt::white)); - gc.drawText(QPoint(21, 31), text); - gc.setPen(QPen(Qt::black)); - gc.drawText(QPoint(20, 30), text); + + Q_FOREACH (const QString &line, lines) { + gc.setPen(QPen(Qt::white)); + gc.drawText(startPoint + QPoint(1,1), line); + gc.setPen(QPen(Qt::black)); + gc.drawText(startPoint, line); + + startPoint += QPoint(0, lineSpacing); + } + gc.restore(); } diff --git a/libs/ui/opengl/kis_opengl_canvas2.cpp b/libs/ui/opengl/kis_opengl_canvas2.cpp index 0d72cbeb85..6174bfecfe 100644 --- a/libs/ui/opengl/kis_opengl_canvas2.cpp +++ b/libs/ui/opengl/kis_opengl_canvas2.cpp @@ -1,909 +1,904 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2006-2013 * Copyright (C) 2015 Michael Abrahams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #define GL_GLEXT_PROTOTYPES #include "opengl/kis_opengl_canvas2.h" #include "opengl/kis_opengl_canvas2_p.h" #include "opengl/kis_opengl_shader_loader.h" #include "opengl/kis_opengl_canvas_debugger.h" #include "canvas/kis_canvas2.h" #include "canvas/kis_coordinates_converter.h" #include "canvas/kis_display_filter.h" #include "canvas/kis_display_color_converter.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_debug.h" #include #include #include #include #include #include #include #include #include #include #include #ifndef Q_OS_OSX #include #endif #define NEAR_VAL -1000.0 #define FAR_VAL 1000.0 #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif #define PROGRAM_VERTEX_ATTRIBUTE 0 #define PROGRAM_TEXCOORD_ATTRIBUTE 1 static bool OPENGL_SUCCESS = false; struct KisOpenGLCanvas2::Private { public: ~Private() { delete displayShader; delete checkerShader; delete solidColorShader; Sync::deleteSync(glSyncObject); } bool canvasInitialized{false}; KisOpenGLImageTexturesSP openGLImageTextures; KisOpenGLShaderLoader shaderLoader; KisShaderProgram *displayShader{0}; KisShaderProgram *checkerShader{0}; KisShaderProgram *solidColorShader{0}; bool displayShaderCompiledWithDisplayFilterSupport{false}; GLfloat checkSizeScale; bool scrollCheckers; QSharedPointer displayFilter; KisOpenGL::FilterMode filterMode; bool proofingConfigIsUpdated=false; GLsync glSyncObject{0}; bool wrapAroundMode{false}; // Stores a quad for drawing the canvas QOpenGLVertexArrayObject quadVAO; QOpenGLBuffer quadBuffers[2]; // Stores data for drawing tool outlines QOpenGLVertexArrayObject outlineVAO; QOpenGLBuffer lineBuffer; QVector3D vertices[6]; QVector2D texCoords[6]; #ifndef Q_OS_OSX QOpenGLFunctions_2_1 *glFn201; #endif qreal pixelGridDrawingThreshold; bool pixelGridEnabled; QColor gridColor; int xToColWithWrapCompensation(int x, const QRect &imageRect) { int firstImageColumn = openGLImageTextures->xToCol(imageRect.left()); int lastImageColumn = openGLImageTextures->xToCol(imageRect.right()); int colsPerImage = lastImageColumn - firstImageColumn + 1; int numWraps = floor(qreal(x) / imageRect.width()); int remainder = x - imageRect.width() * numWraps; return colsPerImage * numWraps + openGLImageTextures->xToCol(remainder); } int yToRowWithWrapCompensation(int y, const QRect &imageRect) { int firstImageRow = openGLImageTextures->yToRow(imageRect.top()); int lastImageRow = openGLImageTextures->yToRow(imageRect.bottom()); int rowsPerImage = lastImageRow - firstImageRow + 1; int numWraps = floor(qreal(y) / imageRect.height()); int remainder = y - imageRect.height() * numWraps; return rowsPerImage * numWraps + openGLImageTextures->yToRow(remainder); } }; KisOpenGLCanvas2::KisOpenGLCanvas2(KisCanvas2 *canvas, KisCoordinatesConverter *coordinatesConverter, QWidget *parent, KisImageWSP image, KisDisplayColorConverter *colorConverter) : QOpenGLWidget(parent) , KisCanvasWidgetBase(canvas, coordinatesConverter) , d(new Private()) { KisConfig cfg; cfg.setCanvasState("OPENGL_STARTED"); d->openGLImageTextures = KisOpenGLImageTextures::getImageTextures(image, colorConverter->monitorProfile(), colorConverter->renderingIntent(), colorConverter->conversionFlags()); setAcceptDrops(true); setAutoFillBackground(false); setFocusPolicy(Qt::StrongFocus); setAttribute(Qt::WA_NoSystemBackground, true); #ifdef Q_OS_OSX setAttribute(Qt::WA_AcceptTouchEvents, false); #else setAttribute(Qt::WA_AcceptTouchEvents, true); #endif setAttribute(Qt::WA_InputMethodEnabled, true); setAttribute(Qt::WA_DontCreateNativeAncestors, true); setDisplayFilterImpl(colorConverter->displayFilter(), true); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged())); slotConfigChanged(); cfg.writeEntry("canvasState", "OPENGL_SUCCESS"); } KisOpenGLCanvas2::~KisOpenGLCanvas2() { delete d; } -bool KisOpenGLCanvas2::needsFpsDebugging() const -{ - return KisOpenglCanvasDebugger::instance()->showFpsOnCanvas(); -} - void KisOpenGLCanvas2::setDisplayFilter(QSharedPointer displayFilter) { setDisplayFilterImpl(displayFilter, false); } void KisOpenGLCanvas2::setDisplayFilterImpl(QSharedPointer displayFilter, bool initializing) { bool needsInternalColorManagement = !displayFilter || displayFilter->useInternalColorManagement(); bool needsFullRefresh = d->openGLImageTextures->setInternalColorManagementActive(needsInternalColorManagement); d->displayFilter = displayFilter; if (!initializing && needsFullRefresh) { canvas()->startUpdateInPatches(canvas()->image()->bounds()); } else if (!initializing) { canvas()->updateCanvas(); } } void KisOpenGLCanvas2::setWrapAroundViewingMode(bool value) { d->wrapAroundMode = value; update(); } inline void rectToVertices(QVector3D* vertices, const QRectF &rc) { vertices[0] = QVector3D(rc.left(), rc.bottom(), 0.f); vertices[1] = QVector3D(rc.left(), rc.top(), 0.f); vertices[2] = QVector3D(rc.right(), rc.bottom(), 0.f); vertices[3] = QVector3D(rc.left(), rc.top(), 0.f); vertices[4] = QVector3D(rc.right(), rc.top(), 0.f); vertices[5] = QVector3D(rc.right(), rc.bottom(), 0.f); } inline void rectToTexCoords(QVector2D* texCoords, const QRectF &rc) { texCoords[0] = QVector2D(rc.left(), rc.bottom()); texCoords[1] = QVector2D(rc.left(), rc.top()); texCoords[2] = QVector2D(rc.right(), rc.bottom()); texCoords[3] = QVector2D(rc.left(), rc.top()); texCoords[4] = QVector2D(rc.right(), rc.top()); texCoords[5] = QVector2D(rc.right(), rc.bottom()); } void KisOpenGLCanvas2::initializeGL() { KisOpenGL::initializeContext(context()); initializeOpenGLFunctions(); #ifndef Q_OS_OSX if (!KisOpenGL::hasOpenGLES()) { d->glFn201 = context()->versionFunctions(); if (!d->glFn201) { warnUI << "Cannot obtain QOpenGLFunctions_2_1, glLogicOp cannot be used"; } } else { d->glFn201 = nullptr; } #endif KisConfig cfg; d->openGLImageTextures->setProofingConfig(canvas()->proofingConfiguration()); d->openGLImageTextures->initGL(context()->functions()); d->openGLImageTextures->generateCheckerTexture(createCheckersImage(cfg.checkSize())); initializeShaders(); // If we support OpenGL 3.2, then prepare our VAOs and VBOs for drawing if (KisOpenGL::hasOpenGL3()) { d->quadVAO.create(); d->quadVAO.bind(); glEnableVertexAttribArray(PROGRAM_VERTEX_ATTRIBUTE); glEnableVertexAttribArray(PROGRAM_TEXCOORD_ATTRIBUTE); // Create the vertex buffer object, it has 6 vertices with 3 components d->quadBuffers[0].create(); d->quadBuffers[0].setUsagePattern(QOpenGLBuffer::StaticDraw); d->quadBuffers[0].bind(); d->quadBuffers[0].allocate(d->vertices, 6 * 3 * sizeof(float)); glVertexAttribPointer(PROGRAM_VERTEX_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, 0, 0); // Create the texture buffer object, it has 6 texture coordinates with 2 components d->quadBuffers[1].create(); d->quadBuffers[1].setUsagePattern(QOpenGLBuffer::StaticDraw); d->quadBuffers[1].bind(); d->quadBuffers[1].allocate(d->texCoords, 6 * 2 * sizeof(float)); glVertexAttribPointer(PROGRAM_TEXCOORD_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, 0, 0); // Create the outline buffer, this buffer will store the outlines of // tools and will frequently change data d->outlineVAO.create(); d->outlineVAO.bind(); glEnableVertexAttribArray(PROGRAM_VERTEX_ATTRIBUTE); // The outline buffer has a StreamDraw usage pattern, because it changes constantly d->lineBuffer.create(); d->lineBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); d->lineBuffer.bind(); glVertexAttribPointer(PROGRAM_VERTEX_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, 0, 0); } Sync::init(context()); d->canvasInitialized = true; } /** * Loads all shaders and reports compilation problems */ void KisOpenGLCanvas2::initializeShaders() { KIS_SAFE_ASSERT_RECOVER_RETURN(!d->canvasInitialized); delete d->checkerShader; delete d->solidColorShader; d->checkerShader = 0; d->solidColorShader = 0; try { d->checkerShader = d->shaderLoader.loadCheckerShader(); d->solidColorShader = d->shaderLoader.loadSolidColorShader(); } catch (const ShaderLoaderException &e) { reportFailedShaderCompilation(e.what()); } initializeDisplayShader(); } void KisOpenGLCanvas2::initializeDisplayShader() { KIS_SAFE_ASSERT_RECOVER_RETURN(!d->canvasInitialized); bool useHiQualityFiltering = d->filterMode == KisOpenGL::HighQualityFiltering; delete d->displayShader; d->displayShader = 0; try { d->displayShader = d->shaderLoader.loadDisplayShader(d->displayFilter, useHiQualityFiltering); d->displayShaderCompiledWithDisplayFilterSupport = d->displayFilter; } catch (const ShaderLoaderException &e) { reportFailedShaderCompilation(e.what()); } } /** * Displays a message box telling the user that * shader compilation failed and turns off OpenGL. */ void KisOpenGLCanvas2::reportFailedShaderCompilation(const QString &context) { KisConfig cfg; qDebug() << "Shader Compilation Failure: " << context; QMessageBox::critical(this, i18nc("@title:window", "Krita"), QString(i18n("Krita could not initialize the OpenGL canvas:\n\n%1\n\n Krita will disable OpenGL and close now.")).arg(context), QMessageBox::Close); cfg.setUseOpenGL(false); cfg.setCanvasState("OPENGL_FAILED"); } void KisOpenGLCanvas2::resizeGL(int width, int height) { coordinatesConverter()->setCanvasWidgetSize(QSize(width, height)); paintGL(); } void KisOpenGLCanvas2::paintGL() { if (!OPENGL_SUCCESS) { KisConfig cfg; cfg.writeEntry("canvasState", "OPENGL_PAINT_STARTED"); } KisOpenglCanvasDebugger::instance()->nofityPaintRequested(); renderCanvasGL(); if (d->glSyncObject) { Sync::deleteSync(d->glSyncObject); } d->glSyncObject = Sync::getSync(); QPainter gc(this); renderDecorations(&gc); gc.end(); if (!OPENGL_SUCCESS) { KisConfig cfg; cfg.writeEntry("canvasState", "OPENGL_SUCCESS"); OPENGL_SUCCESS = true; } } void KisOpenGLCanvas2::paintToolOutline(const QPainterPath &path) { if (!d->solidColorShader->bind()) { return; } // setup the mvp transformation QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(coordinatesConverter()->flakeToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->solidColorShader->setUniformValue(d->solidColorShader->location(Uniform::ModelViewProjection), modelMatrix); if (!KisOpenGL::hasOpenGLES()) { glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_COLOR_LOGIC_OP); #ifndef Q_OS_OSX if (d->glFn201) { d->glFn201->glLogicOp(GL_XOR); } #else glLogicOp(GL_XOR); #endif } else { glEnable(GL_BLEND); glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR, GL_ZERO, GL_ONE, GL_ONE); } KisConfig cfg; QColor cursorColor = cfg.getCursorMainColor(); d->solidColorShader->setUniformValue( d->solidColorShader->location(Uniform::FragmentColor), QVector4D(cursorColor.redF(), cursorColor.greenF(), cursorColor.blueF(), 1.0f)); // Paint the tool outline if (KisOpenGL::hasOpenGL3()) { d->outlineVAO.bind(); d->lineBuffer.bind(); } // Convert every disjointed subpath to a polygon and draw that polygon QList subPathPolygons = path.toSubpathPolygons(); for (int i = 0; i < subPathPolygons.size(); i++) { const QPolygonF& polygon = subPathPolygons.at(i); QVector vertices; vertices.resize(polygon.count()); for (int j = 0; j < polygon.count(); j++) { QPointF p = polygon.at(j); vertices[j].setX(p.x()); vertices[j].setY(p.y()); } if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.allocate(vertices.constData(), 3 * vertices.size() * sizeof(float)); } else { d->solidColorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->solidColorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, vertices.constData()); } glDrawArrays(GL_LINE_STRIP, 0, vertices.size()); } if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.release(); d->outlineVAO.release(); } if (!KisOpenGL::hasOpenGLES()) { glDisable(GL_COLOR_LOGIC_OP); } else { glDisable(GL_BLEND); } d->solidColorShader->release(); } bool KisOpenGLCanvas2::isBusy() const { const bool isBusyStatus = Sync::syncStatus(d->glSyncObject) == Sync::Unsignaled; KisOpenglCanvasDebugger::instance()->nofitySyncStatus(isBusyStatus); return isBusyStatus; } void KisOpenGLCanvas2::drawCheckers() { if (!d->checkerShader) { return; } KisCoordinatesConverter *converter = coordinatesConverter(); QTransform textureTransform; QTransform modelTransform; QRectF textureRect; QRectF modelRect; QRectF viewportRect = !d->wrapAroundMode ? converter->imageRectInViewportPixels() : converter->widgetToViewport(this->rect()); converter->getOpenGLCheckersInfo(viewportRect, &textureTransform, &modelTransform, &textureRect, &modelRect, d->scrollCheckers); textureTransform *= QTransform::fromScale(d->checkSizeScale / KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE, d->checkSizeScale / KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE); if (!d->checkerShader->bind()) { qWarning() << "Could not bind checker shader"; return; } QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(modelTransform); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->checkerShader->setUniformValue(d->checkerShader->location(Uniform::ModelViewProjection), modelMatrix); QMatrix4x4 textureMatrix(textureTransform); d->checkerShader->setUniformValue(d->checkerShader->location(Uniform::TextureMatrix), textureMatrix); //Setup the geometry for rendering if (KisOpenGL::hasOpenGL3()) { rectToVertices(d->vertices, modelRect); d->quadBuffers[0].bind(); d->quadBuffers[0].write(0, d->vertices, 3 * 6 * sizeof(float)); rectToTexCoords(d->texCoords, textureRect); d->quadBuffers[1].bind(); d->quadBuffers[1].write(0, d->texCoords, 2 * 6 * sizeof(float)); } else { rectToVertices(d->vertices, modelRect); d->checkerShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->checkerShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices); rectToTexCoords(d->texCoords, textureRect); d->checkerShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE); d->checkerShader->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, d->texCoords); } // render checkers glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, d->openGLImageTextures->checkerTexture()); glDrawArrays(GL_TRIANGLES, 0, 6); glBindTexture(GL_TEXTURE_2D, 0); d->checkerShader->release(); glBindBuffer(GL_ARRAY_BUFFER, 0); } void KisOpenGLCanvas2::drawGrid() { if (!d->solidColorShader->bind()) { return; } QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(coordinatesConverter()->imageToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->solidColorShader->setUniformValue(d->solidColorShader->location(Uniform::ModelViewProjection), modelMatrix); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); d->solidColorShader->setUniformValue( d->solidColorShader->location(Uniform::FragmentColor), QVector4D(d->gridColor.redF(), d->gridColor.greenF(), d->gridColor.blueF(), 0.5f)); if (KisOpenGL::hasOpenGL3()) { d->outlineVAO.bind(); d->lineBuffer.bind(); } QRectF widgetRect(0,0, width(), height()); QRectF widgetRectInImagePixels = coordinatesConverter()->documentToImage(coordinatesConverter()->widgetToDocument(widgetRect)); QRect wr = widgetRectInImagePixels.toAlignedRect(); if (!d->wrapAroundMode) { wr &= d->openGLImageTextures->storedImageBounds(); } QPoint topLeftCorner = wr.topLeft(); QPoint bottomRightCorner = wr.bottomRight() + QPoint(1, 1); QVector grid; for (int i = topLeftCorner.x(); i <= bottomRightCorner.x(); ++i) { grid.append(QVector3D(i, topLeftCorner.y(), 0)); grid.append(QVector3D(i, bottomRightCorner.y(), 0)); } for (int i = topLeftCorner.y(); i <= bottomRightCorner.y(); ++i) { grid.append(QVector3D(topLeftCorner.x(), i, 0)); grid.append(QVector3D(bottomRightCorner.x(), i, 0)); } if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.allocate(grid.constData(), 3 * grid.size() * sizeof(float)); } else { d->solidColorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->solidColorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, grid.constData()); } glDrawArrays(GL_LINES, 0, grid.size()); if (KisOpenGL::hasOpenGL3()) { d->lineBuffer.release(); d->outlineVAO.release(); } d->solidColorShader->release(); glDisable(GL_BLEND); } void KisOpenGLCanvas2::drawImage() { if (!d->displayShader) { return; } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); KisCoordinatesConverter *converter = coordinatesConverter(); d->displayShader->bind(); QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(converter->imageToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->displayShader->setUniformValue(d->displayShader->location(Uniform::ModelViewProjection), modelMatrix); QMatrix4x4 textureMatrix; textureMatrix.setToIdentity(); d->displayShader->setUniformValue(d->displayShader->location(Uniform::TextureMatrix), textureMatrix); QRectF widgetRect(0,0, width(), height()); QRectF widgetRectInImagePixels = converter->documentToImage(converter->widgetToDocument(widgetRect)); qreal scaleX, scaleY; converter->imageScale(&scaleX, &scaleY); d->displayShader->setUniformValue(d->displayShader->location(Uniform::ViewportScale), (GLfloat) scaleX); d->displayShader->setUniformValue(d->displayShader->location(Uniform::TexelSize), (GLfloat) d->openGLImageTextures->texelSize()); QRect ir = d->openGLImageTextures->storedImageBounds(); QRect wr = widgetRectInImagePixels.toAlignedRect(); if (!d->wrapAroundMode) { // if we don't want to paint wrapping images, just limit the // processing area, and the code will handle all the rest wr &= ir; } int firstColumn = d->xToColWithWrapCompensation(wr.left(), ir); int lastColumn = d->xToColWithWrapCompensation(wr.right(), ir); int firstRow = d->yToRowWithWrapCompensation(wr.top(), ir); int lastRow = d->yToRowWithWrapCompensation(wr.bottom(), ir); int minColumn = d->openGLImageTextures->xToCol(ir.left()); int maxColumn = d->openGLImageTextures->xToCol(ir.right()); int minRow = d->openGLImageTextures->yToRow(ir.top()); int maxRow = d->openGLImageTextures->yToRow(ir.bottom()); int imageColumns = maxColumn - minColumn + 1; int imageRows = maxRow - minRow + 1; for (int col = firstColumn; col <= lastColumn; col++) { for (int row = firstRow; row <= lastRow; row++) { int effectiveCol = col; int effectiveRow = row; QPointF tileWrappingTranslation; if (effectiveCol > maxColumn || effectiveCol < minColumn) { int translationStep = floor(qreal(col) / imageColumns); int originCol = translationStep * imageColumns; effectiveCol = col - originCol; tileWrappingTranslation.rx() = translationStep * ir.width(); } if (effectiveRow > maxRow || effectiveRow < minRow) { int translationStep = floor(qreal(row) / imageRows); int originRow = translationStep * imageRows; effectiveRow = row - originRow; tileWrappingTranslation.ry() = translationStep * ir.height(); } KisTextureTile *tile = d->openGLImageTextures->getTextureTileCR(effectiveCol, effectiveRow); if (!tile) { warnUI << "OpenGL: Trying to paint texture tile but it has not been created yet."; continue; } /* * We create a float rect here to workaround Qt's * "history reasons" in calculation of right() * and bottom() coordinates of integer rects. */ QRectF textureRect(tile->tileRectInTexturePixels()); QRectF modelRect(tile->tileRectInImagePixels().translated(tileWrappingTranslation.x(), tileWrappingTranslation.y())); //Setup the geometry for rendering if (KisOpenGL::hasOpenGL3()) { rectToVertices(d->vertices, modelRect); d->quadBuffers[0].bind(); d->quadBuffers[0].write(0, d->vertices, 3 * 6 * sizeof(float)); rectToTexCoords(d->texCoords, textureRect); d->quadBuffers[1].bind(); d->quadBuffers[1].write(0, d->texCoords, 2 * 6 * sizeof(float)); } else { rectToVertices(d->vertices, modelRect); d->displayShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->displayShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices); rectToTexCoords(d->texCoords, textureRect); d->displayShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE); d->displayShader->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, d->texCoords); } if (d->displayFilter) { glActiveTexture(GL_TEXTURE0 + 1); glBindTexture(GL_TEXTURE_3D, d->displayFilter->lutTexture()); d->displayShader->setUniformValue(d->displayShader->location(Uniform::Texture1), 1); } int currentLodPlane = tile->currentLodPlane(); if (d->displayShader->location(Uniform::FixedLodLevel) >= 0) { d->displayShader->setUniformValue(d->displayShader->location(Uniform::FixedLodLevel), (GLfloat) currentLodPlane); } glActiveTexture(GL_TEXTURE0); tile->bindToActiveTexture(); if (currentLodPlane > 0) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else if (SCALE_MORE_OR_EQUAL_TO(scaleX, scaleY, 2.0)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); switch(d->filterMode) { case KisOpenGL::NearestFilterMode: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); break; case KisOpenGL::BilinearFilterMode: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); break; case KisOpenGL::TrilinearFilterMode: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); break; case KisOpenGL::HighQualityFiltering: if (SCALE_LESS_THAN(scaleX, scaleY, 0.5)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } break; } } glDrawArrays(GL_TRIANGLES, 0, 6); } } glBindTexture(GL_TEXTURE_2D, 0); d->displayShader->release(); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_BLEND); } void KisOpenGLCanvas2::slotConfigChanged() { KisConfig cfg; d->checkSizeScale = KisOpenGLImageTextures::BACKGROUND_TEXTURE_CHECK_SIZE / static_cast(cfg.checkSize()); d->scrollCheckers = cfg.scrollCheckers(); d->openGLImageTextures->generateCheckerTexture(createCheckersImage(cfg.checkSize())); d->openGLImageTextures->updateConfig(cfg.useOpenGLTextureBuffer(), cfg.numMipmapLevels()); d->filterMode = (KisOpenGL::FilterMode) cfg.openGLFilteringMode(); d->pixelGridDrawingThreshold = cfg.getPixelGridDrawingThreshold(); d->pixelGridEnabled = cfg.pixelGridEnabled(); d->gridColor = cfg.getPixelGridColor(); notifyConfigChanged(); } QVariant KisOpenGLCanvas2::inputMethodQuery(Qt::InputMethodQuery query) const { return processInputMethodQuery(query); } void KisOpenGLCanvas2::inputMethodEvent(QInputMethodEvent *event) { processInputMethodEvent(event); } void KisOpenGLCanvas2::renderCanvasGL() { // Draw the border (that is, clear the whole widget to the border color) QColor widgetBackgroundColor = borderColor(); glClearColor(widgetBackgroundColor.redF(), widgetBackgroundColor.greenF(), widgetBackgroundColor.blueF(), 1.0); glClear(GL_COLOR_BUFFER_BIT); if ((d->displayFilter && d->displayFilter->updateShader()) || (bool(d->displayFilter) != d->displayShaderCompiledWithDisplayFilterSupport)) { KIS_SAFE_ASSERT_RECOVER_NOOP(d->canvasInitialized); d->canvasInitialized = false; // TODO: check if actually needed? initializeDisplayShader(); d->canvasInitialized = true; } if (KisOpenGL::hasOpenGL3()) { d->quadVAO.bind(); } drawCheckers(); drawImage(); if ((coordinatesConverter()->effectiveZoom() > d->pixelGridDrawingThreshold - 0.00001) && d->pixelGridEnabled) { drawGrid(); } if (KisOpenGL::hasOpenGL3()) { d->quadVAO.release(); } } void KisOpenGLCanvas2::renderDecorations(QPainter *painter) { QRect boundingRect = coordinatesConverter()->imageRectInWidgetPixels().toAlignedRect(); drawDecorations(*painter, boundingRect); } void KisOpenGLCanvas2::setDisplayProfile(KisDisplayColorConverter *colorConverter) { d->openGLImageTextures->setMonitorProfile(colorConverter->monitorProfile(), colorConverter->renderingIntent(), colorConverter->conversionFlags()); } void KisOpenGLCanvas2::channelSelectionChanged(const QBitArray &channelFlags) { d->openGLImageTextures->setChannelFlags(channelFlags); } void KisOpenGLCanvas2::finishResizingImage(qint32 w, qint32 h) { if (d->canvasInitialized) { d->openGLImageTextures->slotImageSizeChanged(w, h); } } KisUpdateInfoSP KisOpenGLCanvas2::startUpdateCanvasProjection(const QRect & rc, const QBitArray &channelFlags) { d->openGLImageTextures->setChannelFlags(channelFlags); if (canvas()->proofingConfigUpdated()) { d->openGLImageTextures->setProofingConfig(canvas()->proofingConfiguration()); canvas()->setProofingConfigUpdated(false); } return d->openGLImageTextures->updateCache(rc, d->openGLImageTextures->image()); } QRect KisOpenGLCanvas2::updateCanvasProjection(KisUpdateInfoSP info) { // See KisQPainterCanvas::updateCanvasProjection for more info bool isOpenGLUpdateInfo = dynamic_cast(info.data()); if (isOpenGLUpdateInfo) { d->openGLImageTextures->recalculateCache(info); } #ifdef Q_OS_OSX /** * There is a bug on OSX: if we issue frame redraw before the tiles finished * uploading, the tiles will become corrupted. Depending on the GPU/driver * version either the tile itself, or its mipmaps will become totally * transparent. */ glFinish(); #endif return QRect(); // FIXME: Implement dirty rect for OpenGL } bool KisOpenGLCanvas2::callFocusNextPrevChild(bool next) { return focusNextPrevChild(next); } KisOpenGLImageTexturesSP KisOpenGLCanvas2::openGLImageTextures() const { return d->openGLImageTextures; } diff --git a/libs/ui/opengl/kis_opengl_canvas2.h b/libs/ui/opengl/kis_opengl_canvas2.h index 4cb092c0db..283fa00ddf 100644 --- a/libs/ui/opengl/kis_opengl_canvas2.h +++ b/libs/ui/opengl/kis_opengl_canvas2.h @@ -1,127 +1,125 @@ /* * Copyright (C) Boudewijn Rempt , (C) 2006 * Copyright (C) Michael Abrahams , (C) 2015 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_OPENGL_CANVAS_2_H #define KIS_OPENGL_CANVAS_2_H #include #ifndef Q_OS_OSX #include #else #include #endif #include "canvas/kis_canvas_widget_base.h" #include "opengl/kis_opengl_image_textures.h" #include "kritaui_export.h" #include "kis_ui_types.h" class KisCanvas2; class KisDisplayColorConverter; class QOpenGLShaderProgram; class QPainterPath; #ifndef Q_MOC_RUN #ifndef Q_OS_OSX #define GLFunctions QOpenGLFunctions #else #define GLFunctions QOpenGLFunctions_3_2_Core #endif #endif /** * KisOpenGLCanvas is the widget that shows the actual image using OpenGL * * NOTE: if you change something in the event handling here, also change it * in the qpainter canvas. * */ class KRITAUI_EXPORT KisOpenGLCanvas2 : public QOpenGLWidget #ifndef Q_MOC_RUN , protected GLFunctions #endif , public KisCanvasWidgetBase { Q_OBJECT public: KisOpenGLCanvas2(KisCanvas2 *canvas, KisCoordinatesConverter *coordinatesConverter, QWidget *parent, KisImageWSP image, KisDisplayColorConverter *colorConverter); ~KisOpenGLCanvas2() override; public: // QOpenGLWidget void resizeGL(int width, int height) override; void initializeGL() override; void paintGL() override; QVariant inputMethodQuery(Qt::InputMethodQuery query) const override; void inputMethodEvent(QInputMethodEvent *event) override; public: void renderCanvasGL(); void renderDecorations(QPainter *painter); void paintToolOutline(const QPainterPath &path); - bool needsFpsDebugging() const; - public: // Implement kis_abstract_canvas_widget interface void setDisplayFilter(QSharedPointer displayFilter) override; void setWrapAroundViewingMode(bool value) override; void channelSelectionChanged(const QBitArray &channelFlags) override; void setDisplayProfile(KisDisplayColorConverter *colorConverter) override; void finishResizingImage(qint32 w, qint32 h) override; KisUpdateInfoSP startUpdateCanvasProjection(const QRect & rc, const QBitArray &channelFlags) override; QRect updateCanvasProjection(KisUpdateInfoSP info) override; QWidget *widget() override { return this; } bool isBusy() const override; void setDisplayFilterImpl(QSharedPointer displayFilter, bool initializing); KisOpenGLImageTexturesSP openGLImageTextures() const; private Q_SLOTS: void slotConfigChanged(); protected: // KisCanvasWidgetBase bool callFocusNextPrevChild(bool next) override; private: void initializeShaders(); void initializeDisplayShader(); void reportFailedShaderCompilation(const QString &context); void drawImage(); void drawCheckers(); void drawGrid(); private: struct Private; Private * const d; }; #endif // KIS_OPENGL_CANVAS_2_H diff --git a/libs/ui/opengl/kis_opengl_canvas_debugger.cpp b/libs/ui/opengl/kis_opengl_canvas_debugger.cpp index 3e13bb3842..86df5a0bf9 100644 --- a/libs/ui/opengl/kis_opengl_canvas_debugger.cpp +++ b/libs/ui/opengl/kis_opengl_canvas_debugger.cpp @@ -1,115 +1,121 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_opengl_canvas_debugger.h" #include #include #include #include "kis_config.h" - +#include struct KisOpenglCanvasDebugger::Private { Private() : fpsCounter(0), fpsSum(0), syncFlaggedCounter(0), syncFlaggedSum(0), isEnabled(true) {} QElapsedTimer time; int fpsCounter; int fpsSum; int syncFlaggedCounter; int syncFlaggedSum; bool isEnabled; }; Q_GLOBAL_STATIC(KisOpenglCanvasDebugger, s_instance) KisOpenglCanvasDebugger::KisOpenglCanvasDebugger() : m_d(new Private) { - KisConfig cfg; - m_d->isEnabled = cfg.enableOpenGLFramerateLogging(); - - if (m_d->isEnabled) { - m_d->time.start(); - } + connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged())); + slotConfigChanged(); } KisOpenglCanvasDebugger::~KisOpenglCanvasDebugger() { } KisOpenglCanvasDebugger* KisOpenglCanvasDebugger::instance() { return s_instance; } bool KisOpenglCanvasDebugger::showFpsOnCanvas() const { return m_d->isEnabled; } qreal KisOpenglCanvasDebugger::accumulatedFps() { qreal value = 0; if (m_d->fpsSum > 0) { value = qreal(m_d->fpsCounter) / m_d->fpsSum * 1000.0; } return value; } +void KisOpenglCanvasDebugger::slotConfigChanged() +{ + KisConfig cfg; + m_d->isEnabled = cfg.enableOpenGLFramerateLogging(); + + if (m_d->isEnabled) { + m_d->time.start(); + } +} + void KisOpenglCanvasDebugger::nofityPaintRequested() { if (!m_d->isEnabled) return; m_d->fpsSum += m_d->time.restart(); m_d->fpsCounter++; if (m_d->fpsCounter > 100 && m_d->fpsSum > 0) { qDebug() << "Requested FPS:" << qreal(m_d->fpsCounter) / m_d->fpsSum * 1000.0; m_d->fpsSum = 0; m_d->fpsCounter = 0; } } void KisOpenglCanvasDebugger::nofitySyncStatus(bool isBusy) { if (!m_d->isEnabled) return; m_d->syncFlaggedSum += isBusy; m_d->syncFlaggedCounter++; if (m_d->syncFlaggedCounter > 500 && m_d->syncFlaggedSum > 0) { qDebug() << "glSync effectiveness:" << qreal(m_d->syncFlaggedSum) / m_d->syncFlaggedCounter; m_d->syncFlaggedSum = 0; m_d->syncFlaggedCounter = 0; } } diff --git a/libs/ui/opengl/kis_opengl_canvas_debugger.h b/libs/ui/opengl/kis_opengl_canvas_debugger.h index 8d7e605e96..293128e860 100644 --- a/libs/ui/opengl/kis_opengl_canvas_debugger.h +++ b/libs/ui/opengl/kis_opengl_canvas_debugger.h @@ -1,45 +1,49 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_OPENGL_CANVAS_DEBUGGER_H #define __KIS_OPENGL_CANVAS_DEBUGGER_H #include +#include - -class KisOpenglCanvasDebugger +class KisOpenglCanvasDebugger : public QObject { + Q_OBJECT public: KisOpenglCanvasDebugger(); ~KisOpenglCanvasDebugger(); static KisOpenglCanvasDebugger* instance(); bool showFpsOnCanvas() const; void nofityPaintRequested(); void nofitySyncStatus(bool value); qreal accumulatedFps(); +private Q_SLOTS: + void slotConfigChanged(); + private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_OPENGL_CANVAS_DEBUGGER_H */ diff --git a/libs/ui/tool/KisStrokeSpeedMonitor.cpp b/libs/ui/tool/KisStrokeSpeedMonitor.cpp index 7c18c2646a..4dccf85d83 100644 --- a/libs/ui/tool/KisStrokeSpeedMonitor.cpp +++ b/libs/ui/tool/KisStrokeSpeedMonitor.cpp @@ -1,131 +1,210 @@ /* * Copyright (c) 2017 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisStrokeSpeedMonitor.h" #include #include #include #include #include "kis_paintop_preset.h" #include "kis_paintop_settings.h" +#include "kis_config.h" +#include "kis_config_notifier.h" +#include "KisUpdateSchedulerConfigNotifier.h" + + Q_GLOBAL_STATIC(KisStrokeSpeedMonitor, s_instance) struct KisStrokeSpeedMonitor::Private { static const int averageWindow = 10; Private() : avgCursorSpeed(averageWindow), avgRenderingSpeed(averageWindow), avgFps(averageWindow) { } KisRollingMeanAccumulatorWrapper avgCursorSpeed; KisRollingMeanAccumulatorWrapper avgRenderingSpeed; KisRollingMeanAccumulatorWrapper avgFps; + qreal cachedAvgCursorSpeed = 0; + qreal cachedAvgRenderingSpeed = 0; + qreal cachedAvgFps = 0; + qreal lastCursorSpeed = 0; qreal lastRenderingSpeed = 0; qreal lastFps = 0; + bool lastStrokeSaturated = false; QByteArray lastPresetMd5; QString lastPresetName; qreal lastPresetSize = 0; - bool haveStrokeSpeedMeasurement = false; + bool haveStrokeSpeedMeasurement = true; QMutex mutex; }; KisStrokeSpeedMonitor::KisStrokeSpeedMonitor() : m_d(new Private()) { + connect(KisUpdateSchedulerConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(resetAccumulatedValues())); + connect(KisUpdateSchedulerConfigNotifier::instance(), SIGNAL(configChanged()), SIGNAL(sigStatsUpdated())); + connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged())); + + slotConfigChanged(); } KisStrokeSpeedMonitor::~KisStrokeSpeedMonitor() { } KisStrokeSpeedMonitor *KisStrokeSpeedMonitor::instance() { return s_instance; } bool KisStrokeSpeedMonitor::haveStrokeSpeedMeasurement() const { return m_d->haveStrokeSpeedMeasurement; } void KisStrokeSpeedMonitor::setHaveStrokeSpeedMeasurement(bool value) { m_d->haveStrokeSpeedMeasurement = value; } +void KisStrokeSpeedMonitor::resetAccumulatedValues() +{ + m_d->avgCursorSpeed.reset(m_d->averageWindow); + m_d->avgRenderingSpeed.reset(m_d->averageWindow); + m_d->avgFps.reset(m_d->averageWindow); +} + +void KisStrokeSpeedMonitor::slotConfigChanged() +{ + KisConfig cfg; + m_d->haveStrokeSpeedMeasurement = cfg.enableBrushSpeedLogging(); + resetAccumulatedValues(); + emit sigStatsUpdated(); +} + void KisStrokeSpeedMonitor::notifyStrokeFinished(qreal cursorSpeed, qreal renderingSpeed, qreal fps, KisPaintOpPresetSP preset) { if (qFuzzyCompare(cursorSpeed, 0.0) || qFuzzyCompare(renderingSpeed, 0.0)) return; QMutexLocker locker(&m_d->mutex); const bool isSamePreset = m_d->lastPresetName == preset->name() && qFuzzyCompare(m_d->lastPresetSize, preset->settings()->paintOpSize()); ENTER_FUNCTION() << ppVar(isSamePreset); if (!isSamePreset) { - m_d->avgCursorSpeed.reset(m_d->averageWindow); - m_d->avgRenderingSpeed.reset(m_d->averageWindow); - m_d->avgFps.reset(m_d->averageWindow); + resetAccumulatedValues(); m_d->lastPresetName = preset->name(); m_d->lastPresetSize = preset->settings()->paintOpSize(); } m_d->lastCursorSpeed = cursorSpeed; m_d->lastRenderingSpeed = renderingSpeed; m_d->lastFps = fps; static const qreal saturationSpeedThreshold = 0.30; // cursor speed should be at least 30% higher - const bool isStrokeSturated = cursorSpeed / renderingSpeed > (1.0 + saturationSpeedThreshold); + m_d->lastStrokeSaturated = cursorSpeed / renderingSpeed > (1.0 + saturationSpeedThreshold); - if (isStrokeSturated) { + if (m_d->lastStrokeSaturated) { m_d->avgCursorSpeed(cursorSpeed); m_d->avgRenderingSpeed(renderingSpeed); m_d->avgFps(fps); + + m_d->cachedAvgCursorSpeed = m_d->avgCursorSpeed.rollingMean(); + m_d->cachedAvgRenderingSpeed = m_d->avgRenderingSpeed.rollingMean(); + m_d->cachedAvgFps = m_d->avgFps.rollingMean(); } + emit sigStatsUpdated(); + ENTER_FUNCTION() << QString(" CS: %1 RS: %2 FPS: %3 %4") .arg(m_d->lastCursorSpeed, 5) .arg(m_d->lastRenderingSpeed, 5) .arg(m_d->lastFps, 5) - .arg(isStrokeSturated ? "(saturated)" : ""); + .arg(m_d->lastStrokeSaturated ? "(saturated)" : ""); ENTER_FUNCTION() << QString("ACS: %1 ARS: %2 AFPS: %3") - .arg(m_d->avgCursorSpeed.rollingMean(), 5) - .arg(m_d->avgRenderingSpeed.rollingMean(), 5) - .arg(m_d->avgFps.rollingMean(), 5); + .arg(m_d->cachedAvgCursorSpeed, 5) + .arg(m_d->cachedAvgRenderingSpeed, 5) + .arg(m_d->cachedAvgFps, 5); +} + +QString KisStrokeSpeedMonitor::lastPresetName() const +{ + return m_d->lastPresetName; +} + +qreal KisStrokeSpeedMonitor::lastPresetSize() const +{ + return m_d->lastPresetSize; +} + +qreal KisStrokeSpeedMonitor::lastCursorSpeed() const +{ + return m_d->lastCursorSpeed; +} + +qreal KisStrokeSpeedMonitor::lastRenderingSpeed() const +{ + return m_d->lastRenderingSpeed; +} + +qreal KisStrokeSpeedMonitor::lastFps() const +{ + return m_d->lastFps; +} + +bool KisStrokeSpeedMonitor::lastStrokeSaturated() const +{ + return m_d->lastStrokeSaturated; +} + +qreal KisStrokeSpeedMonitor::avgCursorSpeed() const +{ + return m_d->cachedAvgCursorSpeed; +} + +qreal KisStrokeSpeedMonitor::avgRenderingSpeed() const +{ + return m_d->cachedAvgRenderingSpeed; +} + +qreal KisStrokeSpeedMonitor::avgFps() const +{ + return m_d->cachedAvgFps; } diff --git a/libs/ui/tool/KisStrokeSpeedMonitor.h b/libs/ui/tool/KisStrokeSpeedMonitor.h index 44a4707423..51536ed1b6 100644 --- a/libs/ui/tool/KisStrokeSpeedMonitor.h +++ b/libs/ui/tool/KisStrokeSpeedMonitor.h @@ -1,46 +1,83 @@ /* * Copyright (c) 2017 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISSTROKESPEEDMONITOR_H #define KISSTROKESPEEDMONITOR_H #include #include "kis_types.h" +#include "kritaui_export.h" -class KisStrokeSpeedMonitor : public QObject +class KRITAUI_EXPORT KisStrokeSpeedMonitor : public QObject { + Q_OBJECT + + Q_PROPERTY(QString lastPresetName READ lastPresetName NOTIFY sigStatsUpdated) + Q_PROPERTY(qreal lastPresetSize READ lastPresetSize NOTIFY sigStatsUpdated) + + Q_PROPERTY(qreal lastCursorSpeed READ lastCursorSpeed NOTIFY sigStatsUpdated) + Q_PROPERTY(qreal lastRenderingSpeed READ lastRenderingSpeed NOTIFY sigStatsUpdated) + Q_PROPERTY(qreal lastFps READ lastFps NOTIFY sigStatsUpdated) + + Q_PROPERTY(bool lastStrokeSaturated READ lastCursorSpeed NOTIFY sigStatsUpdated) + + Q_PROPERTY(qreal avgCursorSpeed READ avgCursorSpeed NOTIFY sigStatsUpdated) + Q_PROPERTY(qreal avgRenderingSpeed READ avgRenderingSpeed NOTIFY sigStatsUpdated) + Q_PROPERTY(qreal avgFps READ avgFps NOTIFY sigStatsUpdated) + public: KisStrokeSpeedMonitor(); ~KisStrokeSpeedMonitor(); static KisStrokeSpeedMonitor* instance(); bool haveStrokeSpeedMeasurement() const; void notifyStrokeFinished(qreal cursorSpeed, qreal renderingSpeed, qreal fps, KisPaintOpPresetSP preset); + + QString lastPresetName() const; + qreal lastPresetSize() const; + + qreal lastCursorSpeed() const; + qreal lastRenderingSpeed() const; + qreal lastFps() const; + bool lastStrokeSaturated() const; + + qreal avgCursorSpeed() const; + qreal avgRenderingSpeed() const; + qreal avgFps() const; + + +Q_SIGNALS: + void sigStatsUpdated(); + public Q_SLOTS: void setHaveStrokeSpeedMeasurement(bool value); +private Q_SLOTS: + void resetAccumulatedValues(); + void slotConfigChanged(); + private: struct Private; const QScopedPointer m_d; }; #endif // KISSTROKESPEEDMONITOR_H