diff --git a/krita/kritamenu.action b/krita/kritamenu.action
index 89bfefbb47..c37dbcf969 100644
--- a/krita/kritamenu.action
+++ b/krita/kritamenu.action
@@ -1,1851 +1,1861 @@
File
document-new
&New...
Create new document
New
0
0
Ctrl+N
false
document-open
&Open...
Open an existing document
Open
0
0
Ctrl+O
false
document-open-recent
Open &Recent
Open a document which was recently opened
Open Recent
1
0
false
document-save
&Save
Save
Save
1
0
Ctrl+S
false
document-save-as
Save &As...
Save document under a new name
Save As
1
0
Ctrl+Shift+S
false
Sessions...
Open session manager
Sessions
0
0
false
document-import
Open ex&isting Document as Untitled Document...
Open existing Document as Untitled Document
Open existing Document as Untitled Document
0
0
false
document-export
E&xport...
Export
Export
1
0
false
Import animation frames...
Import animation frames
Import animation frames
1
0
false
&Render Animation...
Render Animation to GIF, Image Sequence or Video
Render Animation
1000
0
false
&Render Animation Again
Render Animation Again
Render Animation
1000
0
false
Save Incremental &Version
Save Incremental Version
Save Incremental Version
1
0
Ctrl+Alt+S
false
Save Incremental &Backup
Save Incremental Backup
Save Incremental Backup
1
0
F4
false
&Create Template From Image...
Create Template From Image
Create Template From Image
1
0
false
Create Copy &From Current Image
Create Copy From Current Image
Create Copy From Current Image
1
0
false
document-print
&Print...
Print document
Print
1
0
Ctrl+P
false
document-print-preview
Print Previe&w
Show a print preview of document
Print Preview
1
0
false
configure
&Document Information
Document Information
Document Information
1
0
false
&Close All
Close All
Close All
1
0
Ctrl+Shift+W
false
C&lose
Close
Close
1
0
Ctrl+W
false
&Quit
Quit application
Quit
0
0
Ctrl+Q
false
Edit
edit-undo
Undo
Undo last action
Undo
1
0
Ctrl+Z
false
edit-redo
Redo
Redo last undone action
Redo
1
0
Ctrl+Shift+Z
false
edit-cut
Cu&t
Cut selection to clipboard
Cut
0
0
Ctrl+X
false
edit-copy
&Copy
Copy selection to clipboard
Copy
0
0
Ctrl+C
false
C&opy (sharp)
Copy (sharp)
Copy (sharp)
100000000
0
false
Cut (&sharp)
Cut (sharp)
Cut (sharp)
100000000
0
false
Copy &merged
Copy merged
Copy merged
100000000
0
Ctrl+Shift+C
false
edit-paste
&Paste
Paste clipboard content
Paste
0
0
Ctrl+V
false
Paste at Cursor
Paste at cursor
Paste at cursor
0
0
Ctrl+Alt+V
false
Paste into &New Image
Paste into New Image
Paste into New Image
0
0
Ctrl+Shift+N
false
Paste as R&eference Image
Paste as Reference Image
Paste as Reference Image
1
0
Ctrl+Shift+R
false
edit-clear
C&lear
Clear
Clear
1
0
Del
false
&Fill with Foreground Color
Fill with Foreground Color
Fill with Foreground Color
10000
1
Shift+Backspace
false
Fill &with Background Color
Fill with Background Color
Fill with Background Color
10000
1
Backspace
false
F&ill with Pattern
Fill with Pattern
Fill with Pattern
10000
1
false
Fill Special
Fill with Foreground Color (Opacity)
Fill with Foreground Color (Opacity)
Fill with Foreground Color (Opacity)
10000
1
Ctrl+Shift+Backspace
false
Fill with Background Color (Opacity)
Fill with Background Color (Opacity)
Fill with Background Color (Opacity)
10000
1
Ctrl+Backspace
false
Fill with Pattern (Opacity)
Fill with Pattern (Opacity)
Fill with Pattern (Opacity)
10000
1
false
Stro&ke selected shapes
Stroke selected shapes
Stroke selected shapes
1000000000
0
false
Stroke Selec&tion...
Stroke selection
Stroke selection
10000000000
0
false
Delete keyframe
Delete keyframe
Delete keyframe
100000
0
false
Window
window-new
&New Window
New Window
New Window
0
0
false
N&ext
Next
Next
10
0
false
Previous
Previous
Previous
false
View
document-new
&Show Canvas Only
Show just the canvas or the whole window
Show Canvas Only
0
0
Tab
true
view-fullscreen
F&ull Screen Mode
Display the window in full screen
Full Screen Mode
0
0
Ctrl+Shift+F
true
Detach canvas
Show the canvas on a separate window
Detach canvas
0
0
true
&Wrap Around Mode
Wrap Around Mode
Wrap Around Mode
1
0
true
&Instant Preview Mode
Instant Preview Mode
Instant Preview Mode
1
0
Shift+L
true
Soft Proofing
Turns on Soft Proofing
Turns on Soft Proofing
Ctrl+Y
true
Out of Gamut Warnings
Turns on warnings for colors out of proofed gamut, needs soft proofing to be turned on.
Turns on warnings for colors out of proofed gamut, needs soft proofing to be turned on.
Ctrl+Shift+Y
true
mirror-view
Mirror View
Mirror View
Mirror View
M
false
zoom-original
&Reset zoom
Reset zoom
Reset zoom
1
0
Ctrl+0
false
zoom-in
Zoom &In
Zoom In
0
0
Ctrl++
false
zoom-out
Zoom &Out
Zoom Out
0
0
Ctrl+-
false
rotate-canvas-right
Rotate &Canvas Right
Rotate Canvas Right
Rotate Canvas Right
1
0
Ctrl+]
false
rotate-canvas-left
Rotate Canvas &Left
Rotate Canvas Left
Rotate Canvas Left
1
0
Ctrl+[
false
rotation-reset
Reset Canvas Rotation
Reset Canvas Rotation
Reset Canvas Rotation
1
0
false
Show &Rulers
The rulers show the horizontal and vertical positions of the mouse on the image and can be used to position your mouse at the right place on the canvas. <p>Uncheck this to hide the rulers.</p>
Show Rulers
Show Rulers
1
0
true
Rulers Track Pointer
The rulers will track current mouse position and show it on screen. It can cause suptle performance slowdown
Rulers Track Pointer
Rulers Track Pointer
1
0
true
Show Guides
Show or hide guides
Show Guides
1
0
true
Lock Guides
Lock or unlock guides
Lock Guides
1
0
true
Snap to Guides
Snap cursor to guides position
Snap to Guides
1
0
true
Show Status &Bar
Show or hide the status bar
Show Status Bar
0
0
true
Show Pixel Grid
Show Pixel Grid
Show Pixel Grid
1000
1000
true
view-grid
Show &Grid
Show Grid
Show Grid
1000
0
Ctrl+Shift+'
true
Snap To Grid
Snap To Grid
Snap To Grid
1000
Ctrl+Shift+;
true
Show Snap Options Popup
Show Snap Options Popup
Show Snap Options Popup
1000
Shift+s
false
Snap Orthogonal
Snap Orthogonal
Snap Orthogonal
1000
true
Snap Node
Snap Node
Snap Node
1000
true
Snap Extension
Snap Extension
Snap Extension
1000
true
Snap Pixel
Snap Pixel
Snap Pixel
1000
true
Snap Intersection
Snap Intersection
Snap Intersection
1000
true
Snap Bounding Box
Snap Bounding Box
Snap Bounding Box
1000
true
Snap Image Bounds
Snap Image Bounds
Snap Image Bounds
1000
true
Snap Image Center
Snap Image Center
Snap Image Center
1000
true
S&how Painting Assistants
Show Painting Assistants
Show Painting Assistants
1000
0
true
Show &Assistant Previews
Show Assistant Previews
Show Assistant Previews
1000
0
true
S&how Reference Images
Show Reference Images
Show Reference Images
1000
0
true
Image
document-properties
&Properties...
Properties
Properties
1000
0
false
format-stroke-color
&Image Background Color and Transparency...
Change the background color of the image
Image Background Color and Transparency
1000
0
false
&Convert Image Color Space...
Convert Image Color Space
Convert Image Color Space
1000
0
false
trim-to-image
&Trim to Image Size
Trim to Image Size
Trim to Image Size
1
0
false
Trim to Current &Layer
Trim to Current Layer
Trim to Current Layer
100000
0
false
Trim to S&election
Trim to Selection
Trim to Selection
100000000
0
false
&Rotate Image...
Rotate Image
Rotate Image
1000
0
false
object-rotate-right
Rotate &Image 90° to the Right
Rotate Image 90° to the Right
Rotate Image 90° to the Right
1000
0
false
object-rotate-left
Rotate Image &90° to the Left
Rotate Image 90° to the Left
Rotate Image 90° to the Left
1000
0
false
Rotate Image &180°
Rotate Image 180°
Rotate Image 180°
1000
0
false
&Shear Image...
Shear Image
Shear Image
1000
0
false
symmetry-horizontal
&Mirror Image Horizontally
Mirror Image Horizontally
Mirror Image Horizontally
1000
0
false
symmetry-vertical
Mirror Image &Vertically
Mirror Image Vertically
Mirror Image Vertically
1000
0
false
Scale Image To &New Size...
Scale Image To New Size
Scale Image To New Size
1000
0
Ctrl+Alt+I
false
&Offset Image...
Offset Image
Offset Image
1000
0
false
R&esize Canvas...
Resize Canvas
Resize Canvas
1000
0
Ctrl+Alt+C
false
Im&age Split
Image Split
Image Split
1000
0
false
Separate Ima&ge...
Separate Image
Separate Image
1000
0
false
Select
edit-select-all
Select &All
Select All
Select All
0
0
Ctrl+A
false
edit-select-none
&Deselect
Deselect
Deselect
1100000000
0
Ctrl+Shift+A
false
&Reselect
Reselect
Reselect
0
0
Ctrl+Shift+D
false
&Convert to Vector Selection
Convert to Vector Selection
Convert to Vector Selection
100000000000000000
0
false
&Convert to Raster Selection
Convert to Raster Selection
Convert to Raster Selection
10000000000000000
0
false
Edit Selection
Edit Selection
Edit Selection
10000000000
100
false
Convert Shapes to &Vector Selection
Convert Shapes to Vector Selection
Convert Shapes to Vector Selection
1000000000
0
false
&Feather Selection...
Feather Selection
Feather Selection
10000000000
100
Shift+F6
false
Dis&play Selection
Display Selection
Display Selection
1000
0
Ctrl+H
true
Sca&le...
Scale
Scale
100000000
100
false
S&elect from Color Range...
Select from Color Range
Select from Color Range
10000
100
false
Select &Opaque (Replace)
Select Opaque
Select Opaque
1
100
false
Select Opaque (&Add)
Select Opaque (Add)
Select Opaque (Add)
1
100
false
Select Opaque (&Subtract)
Select Opaque (Subtract)
Select Opaque (Subtract)
1
100
false
Select Opaque (&Intersect)
Select Opaque (Intersect)
Select Opaque (Intersect)
1
100
false
&Grow Selection...
Grow Selection
Grow Selection
10000000000
100
false
S&hrink Selection...
Shrink Selection
Shrink Selection
10000000000
100
false
&Border Selection...
Border Selection
Border Selection
10000000000
100
false
S&mooth
Smooth
Smooth
10000000000
100
false
Filter
&Apply Filter Again
Apply Filter Again
Apply Filter Again
0
0
Ctrl+F
false
Adjust
Adjust
Adjust
false
Artistic
Artistic
Artistic
false
Blur
Blur
Blur
false
Colors
Colors
Colors
false
Edge Detection
Edge Detection
Edge Detection
false
Enhance
Enhance
Enhance
false
Emboss
Emboss
Emboss
false
Map
Map
Map
false
Other
Other
Other
false
gmic
Start G'MIC-Qt
Start G'Mic-Qt
Start G'Mic-Qt
false
gmic
Re-apply the last G'MIC filter
Apply the last G'Mic-Qt action again
Apply the last G'Mic-Qt action again
false
Settings
configure
&Configure Krita...
Configure Krita
Configure Krita
0
0
false
&Manage Resources...
Manage Resources
Manage Resources
0
0
false
preferences-desktop-locale
Switch Application &Language...
Switch Application Language
Switch Application Language
false
&Show Dockers
Show Dockers
Show Dockers
0
0
true
configure
Configure Tool&bars...
Configure Toolbars
Configure Toolbars
0
0
false
Dockers
Dockers
Dockers
false
&Themes
Themes
Themes
false
im-user
Active Author Profile
Active Author Profile
Active Author Profile
Reset Krita Configurations
Reset Krita Configurations
Reset Krita Configurations
false
configure-shortcuts
Configure S&hortcuts...
Configure Shortcuts
Configure Shortcuts
0
0
false
&Window
Window
Window
false
Help
help-contents
Krita &Handbook
Krita Handbook
Krita Handbook
F1
false
tools-report-bug
&Report Bug...
Report Bug
Report Bug
false
krita
&About Krita
About Krita
About Krita
false
kde
About &KDE
About KDE
About KDE
false
Brushes and Stuff
&Gradients
Gradients
Gradients
false
&Patterns
Patterns
Patterns
false
&Color
Color
Color
false
&Painter's Tools
Painter's Tools
Painter's Tools
false
Brush composite
Brush composite
Brush composite
false
Brush option slider 1
Brush option slider 1
Brush option slider 1
false
Brush option slider 2
Brush option slider 2
Brush option slider 2
false
Brush option slider 3
Brush option slider 3
Brush option slider 3
false
+
+
+
+ Brush option slider 4
+
+ Brush option slider 4
+ Brush option slider 4
+
+ false
+
Mirror
Mirror
Mirror
false
Layouts
Select layout
false
Workspaces
Workspaces
Workspaces
false
diff --git a/libs/image/brushengine/kis_paintop_settings.cpp b/libs/image/brushengine/kis_paintop_settings.cpp
index 0e43fc9eeb..ac185cb47e 100644
--- a/libs/image/brushengine/kis_paintop_settings.cpp
+++ b/libs/image/brushengine/kis_paintop_settings.cpp
@@ -1,514 +1,529 @@
/*
* Copyright (c) 2007 Boudewijn Rempt
* Copyright (c) 2008 Lukáš Tvrdý
* Copyright (c) 2014 Mohit Goyal
* 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
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_paint_layer.h"
#include "kis_image.h"
#include "kis_painter.h"
#include "kis_paint_device.h"
#include "kis_paintop_registry.h"
#include "kis_timing_information.h"
#include
#include "kis_paintop_config_widget.h"
#include
#include "kis_paintop_settings_update_proxy.h"
#include
#include
#include
#include
#include
#include "KisPaintopSettingsIds.h"
#include "kis_algebra_2d.h"
struct Q_DECL_HIDDEN KisPaintOpSettings::Private {
Private()
: disableDirtyNotifications(false)
{}
QPointer settingsWidget;
QString modelName;
KisPaintOpPresetWSP preset;
QList uniformProperties;
bool disableDirtyNotifications;
class DirtyNotificationsLocker {
public:
DirtyNotificationsLocker(KisPaintOpSettings::Private *d)
: m_d(d),
m_oldNotificationsState(d->disableDirtyNotifications)
{
m_d->disableDirtyNotifications = true;
}
~DirtyNotificationsLocker() {
m_d->disableDirtyNotifications = m_oldNotificationsState;
}
private:
KisPaintOpSettings::Private *m_d;
bool m_oldNotificationsState;
Q_DISABLE_COPY(DirtyNotificationsLocker)
};
KisPaintopSettingsUpdateProxy* updateProxyNoCreate() const {
auto presetSP = preset.toStrongRef();
return presetSP ? presetSP->updateProxyNoCreate() : 0;
}
KisPaintopSettingsUpdateProxy* updateProxyCreate() const {
auto presetSP = preset.toStrongRef();
return presetSP ? presetSP->updateProxy() : 0;
}
};
KisPaintOpSettings::KisPaintOpSettings()
: d(new Private)
{
d->preset = 0;
}
KisPaintOpSettings::~KisPaintOpSettings()
{
}
KisPaintOpSettings::KisPaintOpSettings(const KisPaintOpSettings &rhs)
: KisPropertiesConfiguration(rhs)
, d(new Private)
{
d->settingsWidget = 0;
d->preset = rhs.preset();
d->modelName = rhs.modelName();
}
void KisPaintOpSettings::setOptionsWidget(KisPaintOpConfigWidget* widget)
{
d->settingsWidget = widget;
}
void KisPaintOpSettings::setPreset(KisPaintOpPresetWSP preset)
{
d->preset = preset;
}
KisPaintOpPresetWSP KisPaintOpSettings::preset() const
{
return d->preset;
}
bool KisPaintOpSettings::mousePressEvent(const KisPaintInformation &paintInformation, Qt::KeyboardModifiers modifiers, KisNodeWSP currentNode)
{
Q_UNUSED(modifiers);
Q_UNUSED(currentNode);
setRandomOffset(paintInformation);
return true; // ignore the event by default
}
bool KisPaintOpSettings::mouseReleaseEvent()
{
return true; // ignore the event by default
}
void KisPaintOpSettings::setRandomOffset(const KisPaintInformation &paintInformation)
{
bool disableDirtyBefore = d->disableDirtyNotifications;
d->disableDirtyNotifications = true;
if (getBool("Texture/Pattern/Enabled")) {
if (getBool("Texture/Pattern/isRandomOffsetX")) {
setProperty("Texture/Pattern/OffsetX",
paintInformation.randomSource()->generate(0, KisPropertiesConfiguration::getInt("Texture/Pattern/MaximumOffsetX")));
}
if (getBool("Texture/Pattern/isRandomOffsetY")) {
setProperty("Texture/Pattern/OffsetY",
paintInformation.randomSource()->generate(0, KisPropertiesConfiguration::getInt("Texture/Pattern/MaximumOffsetY")));
}
}
d->disableDirtyNotifications = disableDirtyBefore;
}
bool KisPaintOpSettings::hasMaskingSettings() const
{
return getBool(KisPaintOpUtils::MaskingBrushEnabledTag, false);
}
KisPaintOpSettingsSP KisPaintOpSettings::createMaskingSettings() const
{
if (!hasMaskingSettings()) return KisPaintOpSettingsSP();
const KoID pixelBrushId(KisPaintOpUtils::MaskingBrushPaintOpId, QString());
KisPaintOpSettingsSP maskingSettings = KisPaintOpRegistry::instance()->settings(pixelBrushId);
this->getPrefixedProperties(KisPaintOpUtils::MaskingBrushPresetPrefix, maskingSettings);
const bool useMasterSize = this->getBool(KisPaintOpUtils::MaskingBrushUseMasterSizeTag, true);
if (useMasterSize) {
const qreal masterSizeCoeff = getDouble(KisPaintOpUtils::MaskingBrushMasterSizeCoeffTag, 1.0);
maskingSettings->setPaintOpSize(masterSizeCoeff * paintOpSize());
}
return maskingSettings;
}
+bool KisPaintOpSettings::hasPatternSettings() const
+{
+ return false;
+}
+
QString KisPaintOpSettings::maskingBrushCompositeOp() const
{
return getString(KisPaintOpUtils::MaskingBrushCompositeOpTag, COMPOSITE_MULT);
}
+
+
KisPaintOpSettingsSP KisPaintOpSettings::clone() const
{
QString paintopID = getString("paintop");
if (paintopID.isEmpty())
return 0;
KisPaintOpSettingsSP settings = KisPaintOpRegistry::instance()->settings(KoID(paintopID));
QMapIterator i(getProperties());
while (i.hasNext()) {
i.next();
settings->setProperty(i.key(), QVariant(i.value()));
}
settings->setPreset(this->preset());
return settings;
}
void KisPaintOpSettings::resetSettings(const QStringList &preserveProperties)
{
QStringList allKeys = preserveProperties;
allKeys << "paintop";
QHash preserved;
Q_FOREACH (const QString &key, allKeys) {
if (hasProperty(key)) {
preserved[key] = getProperty(key);
}
}
clearProperties();
for (auto it = preserved.constBegin(); it != preserved.constEnd(); ++it) {
setProperty(it.key(), it.value());
}
}
void KisPaintOpSettings::activate()
{
}
void KisPaintOpSettings::setPaintOpOpacity(qreal value)
{
KisLockedPropertiesProxySP proxy(
KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(this));
proxy->setProperty("OpacityValue", value);
}
void KisPaintOpSettings::setPaintOpFlow(qreal value)
{
KisLockedPropertiesProxySP proxy(
KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(this));
proxy->setProperty("FlowValue", value);
}
void KisPaintOpSettings::setPaintOpCompositeOp(const QString &value)
{
KisLockedPropertiesProxySP proxy(
KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(this));
proxy->setProperty("CompositeOp", value);
}
qreal KisPaintOpSettings::paintOpOpacity()
{
KisLockedPropertiesProxySP proxy = KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(this);
return proxy->getDouble("OpacityValue", 1.0);
}
qreal KisPaintOpSettings::paintOpFlow()
{
KisLockedPropertiesProxySP proxy(
KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(this));
return proxy->getDouble("FlowValue", 1.0);
}
+qreal KisPaintOpSettings::paintOpPatternSize()
+{
+ KisLockedPropertiesProxySP proxy(
+ KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(this));
+
+ return proxy->getDouble("Texture/Pattern/Scale", 0.5);
+}
+
QString KisPaintOpSettings::paintOpCompositeOp()
{
KisLockedPropertiesProxySP proxy(
KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(this));
return proxy->getString("CompositeOp", COMPOSITE_OVER);
}
void KisPaintOpSettings::setEraserMode(bool value)
{
KisLockedPropertiesProxySP proxy(
KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(this));
proxy->setProperty("EraserMode", value);
}
bool KisPaintOpSettings::eraserMode()
{
KisLockedPropertiesProxySP proxy(
KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(this));
return proxy->getBool("EraserMode", false);
}
QString KisPaintOpSettings::effectivePaintOpCompositeOp()
{
return !eraserMode() ? paintOpCompositeOp() : COMPOSITE_ERASE;
}
qreal KisPaintOpSettings::savedEraserSize() const
{
return getDouble("SavedEraserSize", 0.0);
}
void KisPaintOpSettings::setSavedEraserSize(qreal value)
{
setProperty("SavedEraserSize", value);
setPropertyNotSaved("SavedEraserSize");
}
qreal KisPaintOpSettings::savedBrushSize() const
{
return getDouble("SavedBrushSize", 0.0);
}
void KisPaintOpSettings::setSavedBrushSize(qreal value)
{
setProperty("SavedBrushSize", value);
setPropertyNotSaved("SavedBrushSize");
}
qreal KisPaintOpSettings::savedEraserOpacity() const
{
return getDouble("SavedEraserOpacity", 0.0);
}
void KisPaintOpSettings::setSavedEraserOpacity(qreal value)
{
setProperty("SavedEraserOpacity", value);
setPropertyNotSaved("SavedEraserOpacity");
}
qreal KisPaintOpSettings::savedBrushOpacity() const
{
return getDouble("SavedBrushOpacity", 0.0);
}
void KisPaintOpSettings::setSavedBrushOpacity(qreal value)
{
setProperty("SavedBrushOpacity", value);
setPropertyNotSaved("SavedBrushOpacity");
}
QString KisPaintOpSettings::modelName() const
{
return d->modelName;
}
void KisPaintOpSettings::setModelName(const QString & modelName)
{
d->modelName = modelName;
}
KisPaintOpConfigWidget* KisPaintOpSettings::optionsWidget() const
{
if (d->settingsWidget.isNull())
return 0;
return d->settingsWidget.data();
}
bool KisPaintOpSettings::isValid() const
{
return true;
}
bool KisPaintOpSettings::isLoadable()
{
return isValid();
}
QString KisPaintOpSettings::indirectPaintingCompositeOp() const
{
return COMPOSITE_ALPHA_DARKEN;
}
bool KisPaintOpSettings::isAirbrushing() const
{
return getBool(AIRBRUSH_ENABLED, false);
}
qreal KisPaintOpSettings::airbrushInterval() const
{
qreal rate = getDouble(AIRBRUSH_RATE, 1.0);
if (rate == 0.0) {
return LONG_TIME;
}
else {
return 1000.0 / rate;
}
}
bool KisPaintOpSettings::useSpacingUpdates() const
{
return getBool(SPACING_USE_UPDATES, false);
}
bool KisPaintOpSettings::needsAsynchronousUpdates() const
{
return false;
}
QPainterPath KisPaintOpSettings::brushOutline(const KisPaintInformation &info, const OutlineMode &mode, qreal alignForZoom)
{
QPainterPath path;
if (mode.isVisible) {
path = ellipseOutline(10, 10, 1.0, 0);
if (mode.showTiltDecoration) {
path.addPath(makeTiltIndicator(info, QPointF(0.0, 0.0), 0.0, 2.0));
}
path.translate(KisAlgebra2D::alignForZoom(info.pos(), alignForZoom));
}
return path;
}
QPainterPath KisPaintOpSettings::ellipseOutline(qreal width, qreal height, qreal scale, qreal rotation)
{
QPainterPath path;
QRectF ellipse(0, 0, width * scale, height * scale);
ellipse.translate(-ellipse.center());
path.addEllipse(ellipse);
QTransform m;
m.reset();
m.rotate(rotation);
path = m.map(path);
return path;
}
QPainterPath KisPaintOpSettings::makeTiltIndicator(KisPaintInformation const& info,
QPointF const& start, qreal maxLength, qreal angle)
{
if (maxLength == 0.0) maxLength = 50.0;
maxLength = qMax(maxLength, 50.0);
qreal const length = maxLength * (1 - info.tiltElevation(info, 60.0, 60.0, true));
qreal const baseAngle = 360.0 - fmod(KisPaintInformation::tiltDirection(info, true) * 360.0 + 270.0, 360.0);
QLineF guideLine = QLineF::fromPolar(length, baseAngle + angle);
guideLine.translate(start);
QPainterPath ret;
ret.moveTo(guideLine.p1());
ret.lineTo(guideLine.p2());
guideLine.setAngle(baseAngle - angle);
ret.lineTo(guideLine.p2());
ret.lineTo(guideLine.p1());
return ret;
}
void KisPaintOpSettings::setProperty(const QString & name, const QVariant & value)
{
if (value != KisPropertiesConfiguration::getProperty(name) &&
!d->disableDirtyNotifications) {
KisPaintOpPresetSP presetSP = preset().toStrongRef();
if (presetSP) {
presetSP->setDirty(true);
}
}
KisPropertiesConfiguration::setProperty(name, value);
onPropertyChanged();
}
void KisPaintOpSettings::onPropertyChanged()
{
KisPaintopSettingsUpdateProxy *proxy = d->updateProxyNoCreate();
if (proxy) {
proxy->notifySettingsChanged();
}
}
bool KisPaintOpSettings::isLodUserAllowed(const KisPropertiesConfigurationSP config)
{
return config->getBool("lodUserAllowed", true);
}
void KisPaintOpSettings::setLodUserAllowed(KisPropertiesConfigurationSP config, bool value)
{
config->setProperty("lodUserAllowed", value);
}
bool KisPaintOpSettings::lodSizeThresholdSupported() const
{
return true;
}
qreal KisPaintOpSettings::lodSizeThreshold() const
{
return getDouble("lodSizeThreshold", 100.0);
}
void KisPaintOpSettings::setLodSizeThreshold(qreal value)
{
setProperty("lodSizeThreshold", value);
}
#include "kis_standard_uniform_properties_factory.h"
QList KisPaintOpSettings::uniformProperties(KisPaintOpSettingsSP settings)
{
QList props =
listWeakToStrong(d->uniformProperties);
if (props.isEmpty()) {
using namespace KisStandardUniformPropertiesFactory;
props.append(createProperty(opacity, settings, d->updateProxyCreate()));
props.append(createProperty(size, settings, d->updateProxyCreate()));
props.append(createProperty(flow, settings, d->updateProxyCreate()));
d->uniformProperties = listStrongToWeak(props);
}
return props;
}
diff --git a/libs/image/brushengine/kis_paintop_settings.h b/libs/image/brushengine/kis_paintop_settings.h
index e47b8781bf..3527d28aef 100644
--- a/libs/image/brushengine/kis_paintop_settings.h
+++ b/libs/image/brushengine/kis_paintop_settings.h
@@ -1,349 +1,356 @@
/*
* Copyright (c) 2007 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.
*/
#ifndef KIS_PAINTOP_SETTINGS_H_
#define KIS_PAINTOP_SETTINGS_H_
#include "kis_types.h"
#include "kritaimage_export.h"
#include
#include
#include "kis_properties_configuration.h"
#include
#include
class KisPaintOpConfigWidget;
class KisPaintopSettingsUpdateProxy;
/**
* Configuration property used to control whether airbrushing is enabled.
*/
const QString AIRBRUSH_ENABLED = "PaintOpSettings/isAirbrushing";
/**
* Configuration property used to control airbrushing rate. The value should be in dabs per second.
*/
const QString AIRBRUSH_RATE = "PaintOpSettings/rate";
/**
* Configuration property used to control whether airbrushing is configured to ignore distance-based
* spacing.
*/
const QString AIRBRUSH_IGNORE_SPACING = "PaintOpSettings/ignoreSpacing";
/**
* Configuration property used to control whether the spacing settings can be updated between
* painted dabs.
*/
const QString SPACING_USE_UPDATES = "PaintOpSettings/updateSpacingBetweenDabs";
/**
* This class is used to cache the settings for a paintop
* between two creations. There is one KisPaintOpSettings per input device (mouse, tablet,
* etc...).
*
* The settings may be stored in a preset. Note that if your
* paintop's settings subclass has data that is not stored as a property, that data is not
* saved and restored.
*
* The object also contains a pointer to its parent KisPaintOpPreset object.This is to control the DirtyPreset
* property of KisPaintOpPreset. Whenever the settings are changed/modified from the original -- the preset is
* set to dirty.
*/
class KRITAIMAGE_EXPORT KisPaintOpSettings : public KisPropertiesConfiguration
{
public:
KisPaintOpSettings();
~KisPaintOpSettings() override;
KisPaintOpSettings(const KisPaintOpSettings &rhs);
/**
*
*/
void setOptionsWidget(KisPaintOpConfigWidget* widget);
/**
* This function is called by a tool when the mouse is pressed. It's useful if
* the paintop needs mouse interaction for instance in the case of the clone op.
* If the tool is supposed to ignore the event, the paint op should return true
* and if the tool is supposed to use the event, return false.
* See kis_tool_freehand:tryPickByPaintOp()
*/
virtual bool mousePressEvent(const KisPaintInformation &paintInformation, Qt::KeyboardModifiers modifiers, KisNodeWSP currentNode);
/**
* This function is called by a tool when the mouse is released. It's useful if
* the paintop needs mouse interaction for instance in the case of the clone op.
* If the tool is supposed to ignore the event, the paint op should return true
* and if the tool is supposed to use the event, return false.
*/
virtual bool mouseReleaseEvent();
/**
* Clone the current settings object. Override this if your settings instance doesn't
* store everything as properties.
*/
virtual KisPaintOpSettingsSP clone() const;
/**
* Removes all the settings from the object while keeping the paintop id,
* which is loaded to the object by the factory
*/
void resetSettings(const QStringList &preserveProperties = QStringList());
/**
* @return the node the paintop is working on.
*/
KisNodeSP node() const;
/**
* Call this function when the paint op is selected or the tool is activated
*/
virtual void activate();
/**
* XXX: Remove this after 2.0, when the paint operation (incremental/non incremental) will
* be completely handled in the paintop, not in the tool. This is a filthy hack to move
* the option to the right place, at least.
* @return true if we paint incrementally, false if we paint like Photoshop. By default, paintops
* do not support non-incremental.
*/
virtual bool paintIncremental() {
return true;
}
/**
* @return the composite op it to which the indirect painting device
* should be initialized to. This is used by clone op to reset
* the composite op to COMPOSITE_COPY
*/
virtual QString indirectPaintingCompositeOp() const;
/**
* Whether this paintop wants to deposit paint even when not moving, i.e. the tool needs to
* activate its timer. If this is true, painting updates need to be generated at regular
* intervals even in the absence of input device events, e.g. when the cursor is not moving.
*
* The default implementation checks the property AIRBRUSH_ENABLED, defaulting to false if the
* property is not found. This should be suitable for most paintops.
*/
virtual bool isAirbrushing() const;
/**
* Indicates the minimum time interval that might be needed between airbrush dabs, in
* milliseconds. A lower value means painting updates need to happen more frequently. This value
* should be ignored if isAirbrushing() is false.
*
* The default implementation uses the property AIRBRUSH_RATE, defaulting to an interval of
* one second if the property is not found. This should be suitable for most paintops.
*/
virtual qreal airbrushInterval() const;
/**
* Indicates whether this configuration allows spacing information to be updated between painted
* dabs during a stroke.
*/
virtual bool useSpacingUpdates() const;
/**
* Indicates if the tool should call paintOp->doAsynchronousUpdate() inbetween
* paintAt() calls to do the asynchronous rendering
*/
virtual bool needsAsynchronousUpdates() const;
/**
* This structure defines the current mode for painting an outline.
*/
struct OutlineMode {
bool isVisible = false;
bool forceCircle = false;
bool showTiltDecoration = false;
bool forceFullSize = false;
};
/**
* Returns the brush outline in pixel coordinates. Tool is responsible for conversion into view coordinates.
* Outline mode has to be passed to the paintop which builds the outline as some paintops have to paint outline
* always like clone paintop indicating the duplicate position
*/
virtual QPainterPath brushOutline(const KisPaintInformation &info, const OutlineMode &mode, qreal alignForZoom);
/**
* Helpers for drawing the brush outline
*/
static QPainterPath ellipseOutline(qreal width, qreal height, qreal scale, qreal rotation);
/**
* Helper for drawing a triangle representing the tilt of the stylus.
*
* @param start is the offset from the brush's outline's bounding box
* @param lengthScale is used for deciding the size of the triangle.
* Brush diameter or width are common choices for this.
* @param angle is the angle between the two sides of the triangle.
*/
static QPainterPath makeTiltIndicator(KisPaintInformation const& info,
QPointF const& start, qreal lengthScale, qreal angle);
/**
* Set paintop opacity directly in the properties
*/
void setPaintOpOpacity(qreal value);
/**
* Set paintop flow directly in the properties
*/
void setPaintOpFlow(qreal value);
/**
* Set paintop composite mode directly in the properties
*/
void setPaintOpCompositeOp(const QString &value);
/**
* @return opacity saved in the properties
*/
qreal paintOpOpacity();
/**
* @return flow saved in the properties
*/
qreal paintOpFlow();
/**
* @return composite mode saved in the properties
*/
QString paintOpCompositeOp();
/**
* Set paintop size directly in the properties
*/
virtual void setPaintOpSize(qreal value) = 0;
/**
* @return size saved in the properties
*/
virtual qreal paintOpSize() const = 0;
+ /**
+ * @return pattern size saved in the properties
+ */
+ virtual qreal paintOpPatternSize();
+
void setEraserMode(bool value);
bool eraserMode();
qreal savedEraserSize() const;
void setSavedEraserSize(qreal value);
qreal savedBrushSize() const;
void setSavedBrushSize(qreal value);
qreal savedEraserOpacity() const;
void setSavedEraserOpacity(qreal value);
qreal savedBrushOpacity() const;
void setSavedBrushOpacity(qreal value);
QString effectivePaintOpCompositeOp();
void setPreset(KisPaintOpPresetWSP preset);
KisPaintOpPresetWSP preset() const;
/**
* @return filename of the 3D brush model, empty if no brush is set
*/
virtual QString modelName() const;
/**
* Set filename of 3D brush model. By default no brush is set
*/
void setModelName(const QString & modelName);
/// Check if the settings are valid, setting might be invalid through missing brushes etc
/// Overwrite if the settings of a paintop can be invalid
/// @return state of the settings, default implementation is true
virtual bool isValid() const;
/// Check if the settings are loadable, that might the case if we can fallback to something
/// Overwrite if the settings can do some kind of fallback
/// @return loadable state of the settings, by default implementation return the same as isValid()
virtual bool isLoadable();
/**
* Overrides the method in KisPropertiesCofiguration to allow
* onPropertyChanged() callback
*/
void setProperty(const QString & name, const QVariant & value) override;
virtual QList uniformProperties(KisPaintOpSettingsSP settings);
static bool isLodUserAllowed(const KisPropertiesConfigurationSP config);
static void setLodUserAllowed(KisPropertiesConfigurationSP config, bool value);
virtual bool lodSizeThresholdSupported() const;
qreal lodSizeThreshold() const;
void setLodSizeThreshold(qreal value);
/**
* @return the option widget of the paintop (can be 0 is no option widgets is set)
*/
KisPaintOpConfigWidget* optionsWidget() const;
/**
* This function is called to set random offsets to the brush whenever the mouse is clicked. It is
* specific to when the pattern option is set.
*
*/
virtual void setRandomOffset(const KisPaintInformation &paintInformation);
/**
* @return true if this preset demands a secondary masked brush running
* alongside it
*/
bool hasMaskingSettings() const;
/**
* @return a newly created settings object representing a preset of the masking
* brush that should be run alongside the current brush
*/
KisPaintOpSettingsSP createMaskingSettings() const;
/**
* @return a composite op id of the masked brush rendering algorithm.
*
* Please take into account that the brush itself always paints in alpha-
* darken mode, but the final result is combined with this composite op.
*/
QString maskingBrushCompositeOp() const;
+ virtual bool hasPatternSettings() const;
+
protected:
/**
* The callback is called every time when a property changes
*/
virtual void onPropertyChanged();
private:
struct Private;
const QScopedPointer d;
};
#endif
diff --git a/libs/ui/KisViewManager.cpp b/libs/ui/KisViewManager.cpp
index 5826eac557..017e9c095e 100644
--- a/libs/ui/KisViewManager.cpp
+++ b/libs/ui/KisViewManager.cpp
@@ -1,1459 +1,1460 @@
/*
* This file is part of KimageShop^WKrayon^WKrita
*
* Copyright (c) 1999 Matthias Elter
* 1999 Michael Koch
* 1999 Carsten Pfeiffer
* 2002 Patrick Julien
* 2003-2011 Boudewijn Rempt
* 2004 Clarence Dang
* 2011 José Luis Vergara
* 2017 L. E. Segovia
*
* 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
#include "KisViewManager.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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "input/kis_input_manager.h"
#include "canvas/kis_canvas2.h"
#include "canvas/kis_canvas_controller.h"
#include "canvas/kis_grid_manager.h"
#include "dialogs/kis_dlg_blacklist_cleanup.h"
#include "input/kis_input_profile_manager.h"
#include "kis_action_manager.h"
#include "kis_action.h"
#include "kis_canvas_controls_manager.h"
#include "kis_canvas_resource_provider.h"
#include "kis_composite_progress_proxy.h"
#include
#include "kis_config.h"
#include "kis_config_notifier.h"
#include "kis_control_frame.h"
#include "kis_coordinates_converter.h"
#include "KisDocument.h"
#include "kis_favorite_resource_manager.h"
#include "kis_filter_manager.h"
#include "kis_group_layer.h"
#include
#include
#include "kis_image_manager.h"
#include
#include "kis_mainwindow_observer.h"
#include "kis_mask_manager.h"
#include "kis_mimedata.h"
#include "kis_mirror_manager.h"
#include "kis_node_commands_adapter.h"
#include "kis_node.h"
#include "kis_node_manager.h"
#include "KisDecorationsManager.h"
#include
#include "kis_paintop_box.h"
#include
#include "KisPart.h"
#include "KisPrintJob.h"
#include
#include "KisResourceServerProvider.h"
#include "kis_selection.h"
#include "kis_selection_mask.h"
#include "kis_selection_manager.h"
#include "kis_shape_controller.h"
#include "kis_shape_layer.h"
#include
#include "kis_statusbar.h"
#include
#include
#include "kis_tooltip_manager.h"
#include
#include "KisView.h"
#include "kis_zoom_manager.h"
#include "widgets/kis_floating_message.h"
#include "kis_signal_auto_connection.h"
#include "kis_icon_utils.h"
#include "kis_guides_manager.h"
#include "kis_derived_resources.h"
#include "dialogs/kis_delayed_save_dialog.h"
#include
#include "kis_signals_blocker.h"
class BlockingUserInputEventFilter : public QObject
{
bool eventFilter(QObject *watched, QEvent *event) override
{
Q_UNUSED(watched);
if(dynamic_cast(event)
|| dynamic_cast(event)
|| dynamic_cast(event)) {
return true;
}
else {
return false;
}
}
};
class KisViewManager::KisViewManagerPrivate
{
public:
KisViewManagerPrivate(KisViewManager *_q, KActionCollection *_actionCollection, QWidget *_q_parent)
: filterManager(_q)
, createTemplate(0)
, saveIncremental(0)
, saveIncrementalBackup(0)
, openResourcesDirectory(0)
, rotateCanvasRight(0)
, rotateCanvasLeft(0)
, resetCanvasRotation(0)
, wrapAroundAction(0)
, levelOfDetailAction(0)
, showRulersAction(0)
, rulersTrackMouseAction(0)
, zoomTo100pct(0)
, zoomIn(0)
, zoomOut(0)
, selectionManager(_q)
, statusBar(_q)
, controlFrame(_q, _q_parent)
, nodeManager(_q)
, imageManager(_q)
, gridManager(_q)
, canvasControlsManager(_q)
, paintingAssistantsManager(_q)
, actionManager(_q, _actionCollection)
, mainWindow(0)
, showFloatingMessage(true)
, currentImageView(0)
, canvasResourceProvider(_q)
, canvasResourceManager()
, guiUpdateCompressor(30, KisSignalCompressor::POSTPONE, _q)
, actionCollection(_actionCollection)
, mirrorManager(_q)
, inputManager(_q)
, actionAuthor(0)
, showPixelGrid(0)
{
KisViewManager::initializeResourceManager(&canvasResourceManager);
}
public:
KisFilterManager filterManager;
KisAction *createTemplate;
KisAction *createCopy;
KisAction *saveIncremental;
KisAction *saveIncrementalBackup;
KisAction *openResourcesDirectory;
KisAction *rotateCanvasRight;
KisAction *rotateCanvasLeft;
KisAction *resetCanvasRotation;
KisAction *wrapAroundAction;
KisAction *levelOfDetailAction;
KisAction *showRulersAction;
KisAction *rulersTrackMouseAction;
KisAction *zoomTo100pct;
KisAction *zoomIn;
KisAction *zoomOut;
KisAction *softProof;
KisAction *gamutCheck;
KisAction *toggleFgBg;
KisAction *resetFgBg;
KisSelectionManager selectionManager;
KisGuidesManager guidesManager;
KisStatusBar statusBar;
QPointer persistentImageProgressUpdater;
QScopedPointer persistentUnthreadedProgressUpdaterRouter;
QPointer persistentUnthreadedProgressUpdater;
KisControlFrame controlFrame;
KisNodeManager nodeManager;
KisImageManager imageManager;
KisGridManager gridManager;
KisCanvasControlsManager canvasControlsManager;
KisDecorationsManager paintingAssistantsManager;
BlockingUserInputEventFilter blockingEventFilter;
KisActionManager actionManager;
QMainWindow* mainWindow;
QPointer savedFloatingMessage;
bool showFloatingMessage;
QPointer currentImageView;
KisCanvasResourceProvider canvasResourceProvider;
KoCanvasResourceProvider canvasResourceManager;
KisSignalCompressor guiUpdateCompressor;
KActionCollection *actionCollection;
KisMirrorManager mirrorManager;
KisInputManager inputManager;
KisSignalAutoConnectionsStore viewConnections;
KSelectAction *actionAuthor; // Select action for author profile.
KisAction *showPixelGrid;
QByteArray canvasState;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
QFlags windowFlags;
#endif
bool blockUntilOperationsFinishedImpl(KisImageSP image, bool force);
};
KisViewManager::KisViewManager(QWidget *parent, KActionCollection *_actionCollection)
: d(new KisViewManagerPrivate(this, _actionCollection, parent))
{
d->actionCollection = _actionCollection;
d->mainWindow = dynamic_cast(parent);
d->canvasResourceProvider.setResourceManager(&d->canvasResourceManager);
connect(&d->guiUpdateCompressor, SIGNAL(timeout()), this, SLOT(guiUpdateTimeout()));
createActions();
setupManagers();
// These initialization functions must wait until KisViewManager ctor is complete.
d->statusBar.setup();
d->persistentImageProgressUpdater =
d->statusBar.progressUpdater()->startSubtask(1, "", true);
// reset state to "completed"
d->persistentImageProgressUpdater->setRange(0,100);
d->persistentImageProgressUpdater->setValue(100);
d->persistentUnthreadedProgressUpdater =
d->statusBar.progressUpdater()->startSubtask(1, "", true);
// reset state to "completed"
d->persistentUnthreadedProgressUpdater->setRange(0,100);
d->persistentUnthreadedProgressUpdater->setValue(100);
d->persistentUnthreadedProgressUpdaterRouter.reset(
new KoProgressUpdater(d->persistentUnthreadedProgressUpdater,
KoProgressUpdater::Unthreaded));
d->persistentUnthreadedProgressUpdaterRouter->setAutoNestNames(true);
d->controlFrame.setup(parent);
//Check to draw scrollbars after "Canvas only mode" toggle is created.
this->showHideScrollbars();
QScopedPointer dummy(new KoDummyCanvasController(actionCollection()));
KoToolManager::instance()->registerToolActions(actionCollection(), dummy.data());
QTimer::singleShot(0, this, SLOT(initializeStatusBarVisibility()));
connect(KoToolManager::instance(), SIGNAL(inputDeviceChanged(KoInputDevice)),
d->controlFrame.paintopBox(), SLOT(slotInputDeviceChanged(KoInputDevice)));
connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)),
d->controlFrame.paintopBox(), SLOT(slotToolChanged(KoCanvasController*,int)));
connect(&d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)),
canvasResourceProvider(), SLOT(slotNodeActivated(KisNodeSP)));
connect(KisPart::instance(), SIGNAL(sigViewAdded(KisView*)), SLOT(slotViewAdded(KisView*)));
connect(KisPart::instance(), SIGNAL(sigViewRemoved(KisView*)), SLOT(slotViewRemoved(KisView*)));
connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotUpdateAuthorProfileActions()));
connect(KisConfigNotifier::instance(), SIGNAL(pixelGridModeChanged()), SLOT(slotUpdatePixelGridAction()));
KisInputProfileManager::instance()->loadProfiles();
KisConfig cfg(true);
d->showFloatingMessage = cfg.showCanvasMessages();
const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
KoColor foreground(Qt::black, cs);
d->canvasResourceProvider.setFGColor(cfg.readKoColor("LastForeGroundColor",foreground));
KoColor background(Qt::white, cs);
d->canvasResourceProvider.setBGColor(cfg.readKoColor("LastBackGroundColor",background));
}
KisViewManager::~KisViewManager()
{
KisConfig cfg(false);
if (canvasResourceProvider() && canvasResourceProvider()->currentPreset()) {
cfg.writeKoColor("LastForeGroundColor",canvasResourceProvider()->fgColor());
cfg.writeKoColor("LastBackGroundColor",canvasResourceProvider()->bgColor());
}
cfg.writeEntry("baseLength", KoResourceItemChooserSync::instance()->baseLength());
cfg.writeEntry("CanvasOnlyActive", false); // We never restart in CavnasOnlyMode
delete d;
}
void KisViewManager::initializeResourceManager(KoCanvasResourceProvider *resourceManager)
{
resourceManager->addDerivedResourceConverter(toQShared(new KisCompositeOpResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisEffectiveCompositeOpResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisOpacityResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisFlowResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisSizeResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisLodAvailabilityResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisLodSizeThresholdResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisLodSizeThresholdSupportedResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisEraserModeResourceConverter));
+ resourceManager->addDerivedResourceConverter(toQShared(new KisPatternSizeResourceConverter));
resourceManager->addResourceUpdateMediator(toQShared(new KisPresetUpdateMediator));
}
KActionCollection *KisViewManager::actionCollection() const
{
return d->actionCollection;
}
void KisViewManager::slotViewAdded(KisView *view)
{
// WARNING: this slot is called even when a view from another main windows is added!
// Don't expect \p view be a child of this view manager!
Q_UNUSED(view);
if (viewCount() == 0) {
d->statusBar.showAllStatusBarItems();
}
}
void KisViewManager::slotViewRemoved(KisView *view)
{
// WARNING: this slot is called even when a view from another main windows is removed!
// Don't expect \p view be a child of this view manager!
Q_UNUSED(view);
if (viewCount() == 0) {
d->statusBar.hideAllStatusBarItems();
}
KisConfig cfg(false);
if (canvasResourceProvider() && canvasResourceProvider()->currentPreset()) {
cfg.writeEntry("LastPreset", canvasResourceProvider()->currentPreset()->name());
}
}
void KisViewManager::setCurrentView(KisView *view)
{
bool first = true;
if (d->currentImageView) {
d->currentImageView->notifyCurrentStateChanged(false);
d->currentImageView->canvasBase()->setCursor(QCursor(Qt::ArrowCursor));
first = false;
KisDocument* doc = d->currentImageView->document();
if (doc) {
doc->image()->compositeProgressProxy()->removeProxy(d->persistentImageProgressUpdater);
doc->disconnect(this);
}
d->currentImageView->canvasController()->proxyObject->disconnect(&d->statusBar);
d->viewConnections.clear();
}
QPointer imageView = qobject_cast(view);
d->currentImageView = imageView;
if (imageView) {
d->softProof->setChecked(imageView->softProofing());
d->gamutCheck->setChecked(imageView->gamutCheck());
// Wait for the async image to have loaded
KisDocument* doc = imageView->document();
if (KisConfig(true).readEntry("EnablePositionLabel", false)) {
connect(d->currentImageView->canvasController()->proxyObject,
SIGNAL(documentMousePositionChanged(QPointF)),
&d->statusBar,
SLOT(documentMousePositionChanged(QPointF)));
}
// Restore the last used brush preset, color and background color.
if (first) {
KisPaintOpPresetResourceServer * rserver = KisResourceServerProvider::instance()->paintOpPresetServer();
QString defaultPresetName = "basic_tip_default";
bool foundTip = false;
for (int i=0; iresourceCount(); i++) {
KisPaintOpPresetSP resource = rserver->resources().at(i);
if (resource->name().toLower().contains("basic_tip_default")) {
defaultPresetName = resource->name();
foundTip = true;
} else if (foundTip == false && (resource->name().toLower().contains("default") ||
resource->filename().toLower().contains("default"))) {
defaultPresetName = resource->name();
foundTip = true;
}
}
KisConfig cfg(true);
QString lastPreset = cfg.readEntry("LastPreset", defaultPresetName);
KisPaintOpPresetSP preset = rserver->resourceByName(lastPreset);
if (!preset) {
preset = rserver->resourceByName(defaultPresetName);
}
if (!preset && !rserver->resources().isEmpty()) {
preset = rserver->resources().first();
}
if (preset) {
paintOpBox()->restoreResource(preset.data());
canvasResourceProvider()->setCurrentCompositeOp(preset->settings()->paintOpCompositeOp());
}
}
KisCanvasController *canvasController = dynamic_cast(d->currentImageView->canvasController());
d->viewConnections.addUniqueConnection(&d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)), doc->image(), SLOT(requestStrokeEndActiveNode()));
d->viewConnections.addUniqueConnection(d->rotateCanvasRight, SIGNAL(triggered()), canvasController, SLOT(rotateCanvasRight15()));
d->viewConnections.addUniqueConnection(d->rotateCanvasLeft, SIGNAL(triggered()),canvasController, SLOT(rotateCanvasLeft15()));
d->viewConnections.addUniqueConnection(d->resetCanvasRotation, SIGNAL(triggered()),canvasController, SLOT(resetCanvasRotation()));
d->viewConnections.addUniqueConnection(d->wrapAroundAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleWrapAroundMode(bool)));
d->wrapAroundAction->setChecked(canvasController->wrapAroundMode());
d->viewConnections.addUniqueConnection(d->levelOfDetailAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleLevelOfDetailMode(bool)));
d->levelOfDetailAction->setChecked(canvasController->levelOfDetailMode());
d->viewConnections.addUniqueConnection(d->currentImageView->image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), d->controlFrame.paintopBox(), SLOT(slotColorSpaceChanged(const KoColorSpace*)));
d->viewConnections.addUniqueConnection(d->showRulersAction, SIGNAL(toggled(bool)), imageView->zoomManager(), SLOT(setShowRulers(bool)));
d->viewConnections.addUniqueConnection(d->rulersTrackMouseAction, SIGNAL(toggled(bool)), imageView->zoomManager(), SLOT(setRulersTrackMouse(bool)));
d->viewConnections.addUniqueConnection(d->zoomTo100pct, SIGNAL(triggered()), imageView->zoomManager(), SLOT(zoomTo100()));
d->viewConnections.addUniqueConnection(d->zoomIn, SIGNAL(triggered()), imageView->zoomController()->zoomAction(), SLOT(zoomIn()));
d->viewConnections.addUniqueConnection(d->zoomOut, SIGNAL(triggered()), imageView->zoomController()->zoomAction(), SLOT(zoomOut()));
d->viewConnections.addUniqueConnection(d->softProof, SIGNAL(toggled(bool)), view, SLOT(slotSoftProofing(bool)) );
d->viewConnections.addUniqueConnection(d->gamutCheck, SIGNAL(toggled(bool)), view, SLOT(slotGamutCheck(bool)) );
// set up progrress reporting
doc->image()->compositeProgressProxy()->addProxy(d->persistentImageProgressUpdater);
d->viewConnections.addUniqueConnection(&d->statusBar, SIGNAL(sigCancellationRequested()), doc->image(), SLOT(requestStrokeCancellation()));
d->viewConnections.addUniqueConnection(d->showPixelGrid, SIGNAL(toggled(bool)), canvasController, SLOT(slotTogglePixelGrid(bool)));
imageView->zoomManager()->setShowRulers(d->showRulersAction->isChecked());
imageView->zoomManager()->setRulersTrackMouse(d->rulersTrackMouseAction->isChecked());
showHideScrollbars();
}
d->filterManager.setView(imageView);
d->selectionManager.setView(imageView);
d->guidesManager.setView(imageView);
d->nodeManager.setView(imageView);
d->imageManager.setView(imageView);
d->canvasControlsManager.setView(imageView);
d->actionManager.setView(imageView);
d->gridManager.setView(imageView);
d->statusBar.setView(imageView);
d->paintingAssistantsManager.setView(imageView);
d->mirrorManager.setView(imageView);
if (d->currentImageView) {
d->currentImageView->notifyCurrentStateChanged(true);
d->currentImageView->canvasController()->activate();
d->currentImageView->canvasController()->setFocus();
d->viewConnections.addUniqueConnection(
image(), SIGNAL(sigSizeChanged(QPointF,QPointF)),
canvasResourceProvider(), SLOT(slotImageSizeChanged()));
d->viewConnections.addUniqueConnection(
image(), SIGNAL(sigResolutionChanged(double,double)),
canvasResourceProvider(), SLOT(slotOnScreenResolutionChanged()));
d->viewConnections.addUniqueConnection(
image(), SIGNAL(sigNodeChanged(KisNodeSP)),
this, SLOT(updateGUI()));
d->viewConnections.addUniqueConnection(
d->currentImageView->zoomManager()->zoomController(),
SIGNAL(zoomChanged(KoZoomMode::Mode,qreal)),
canvasResourceProvider(), SLOT(slotOnScreenResolutionChanged()));
}
d->actionManager.updateGUI();
canvasResourceProvider()->slotImageSizeChanged();
canvasResourceProvider()->slotOnScreenResolutionChanged();
Q_EMIT viewChanged();
}
KoZoomController *KisViewManager::zoomController() const
{
if (d->currentImageView) {
return d->currentImageView->zoomController();
}
return 0;
}
KisImageWSP KisViewManager::image() const
{
if (document()) {
return document()->image();
}
return 0;
}
KisCanvasResourceProvider * KisViewManager::canvasResourceProvider()
{
return &d->canvasResourceProvider;
}
KisCanvas2 * KisViewManager::canvasBase() const
{
if (d && d->currentImageView) {
return d->currentImageView->canvasBase();
}
return 0;
}
QWidget* KisViewManager::canvas() const
{
if (d && d->currentImageView && d->currentImageView->canvasBase()->canvasWidget()) {
return d->currentImageView->canvasBase()->canvasWidget();
}
return 0;
}
KisStatusBar * KisViewManager::statusBar() const
{
return &d->statusBar;
}
KisPaintopBox* KisViewManager::paintOpBox() const
{
return d->controlFrame.paintopBox();
}
QPointer KisViewManager::createUnthreadedUpdater(const QString &name)
{
return d->persistentUnthreadedProgressUpdaterRouter->startSubtask(1, name, false);
}
QPointer KisViewManager::createThreadedUpdater(const QString &name)
{
return d->statusBar.progressUpdater()->startSubtask(1, name, false);
}
KisSelectionManager * KisViewManager::selectionManager()
{
return &d->selectionManager;
}
KisNodeSP KisViewManager::activeNode()
{
return d->nodeManager.activeNode();
}
KisLayerSP KisViewManager::activeLayer()
{
return d->nodeManager.activeLayer();
}
KisPaintDeviceSP KisViewManager::activeDevice()
{
return d->nodeManager.activePaintDevice();
}
KisZoomManager * KisViewManager::zoomManager()
{
if (d->currentImageView) {
return d->currentImageView->zoomManager();
}
return 0;
}
KisFilterManager * KisViewManager::filterManager()
{
return &d->filterManager;
}
KisImageManager * KisViewManager::imageManager()
{
return &d->imageManager;
}
KisInputManager* KisViewManager::inputManager() const
{
return &d->inputManager;
}
KisSelectionSP KisViewManager::selection()
{
if (d->currentImageView) {
return d->currentImageView->selection();
}
return 0;
}
bool KisViewManager::selectionEditable()
{
KisLayerSP layer = activeLayer();
if (layer) {
KisSelectionMaskSP mask = layer->selectionMask();
if (mask) {
return mask->isEditable();
}
}
// global selection is always editable
return true;
}
KisUndoAdapter * KisViewManager::undoAdapter()
{
if (!document()) return 0;
KisImageWSP image = document()->image();
Q_ASSERT(image);
return image->undoAdapter();
}
void KisViewManager::createActions()
{
KisConfig cfg(true);
d->saveIncremental = actionManager()->createAction("save_incremental_version");
connect(d->saveIncremental, SIGNAL(triggered()), this, SLOT(slotSaveIncremental()));
d->saveIncrementalBackup = actionManager()->createAction("save_incremental_backup");
connect(d->saveIncrementalBackup, SIGNAL(triggered()), this, SLOT(slotSaveIncrementalBackup()));
connect(mainWindow(), SIGNAL(documentSaved()), this, SLOT(slotDocumentSaved()));
d->saveIncremental->setEnabled(false);
d->saveIncrementalBackup->setEnabled(false);
KisAction *tabletDebugger = actionManager()->createAction("tablet_debugger");
connect(tabletDebugger, SIGNAL(triggered()), this, SLOT(toggleTabletLogger()));
d->createTemplate = actionManager()->createAction("create_template");
connect(d->createTemplate, SIGNAL(triggered()), this, SLOT(slotCreateTemplate()));
d->createCopy = actionManager()->createAction("create_copy");
connect(d->createCopy, SIGNAL(triggered()), this, SLOT(slotCreateCopy()));
d->openResourcesDirectory = actionManager()->createAction("open_resources_directory");
connect(d->openResourcesDirectory, SIGNAL(triggered()), SLOT(openResourcesDirectory()));
d->rotateCanvasRight = actionManager()->createAction("rotate_canvas_right");
d->rotateCanvasLeft = actionManager()->createAction("rotate_canvas_left");
d->resetCanvasRotation = actionManager()->createAction("reset_canvas_rotation");
d->wrapAroundAction = actionManager()->createAction("wrap_around_mode");
d->levelOfDetailAction = actionManager()->createAction("level_of_detail_mode");
d->softProof = actionManager()->createAction("softProof");
d->gamutCheck = actionManager()->createAction("gamutCheck");
KisAction *tAction = actionManager()->createAction("showStatusBar");
tAction->setChecked(cfg.showStatusBar());
connect(tAction, SIGNAL(toggled(bool)), this, SLOT(showStatusBar(bool)));
tAction = actionManager()->createAction("view_show_canvas_only");
tAction->setChecked(false);
connect(tAction, SIGNAL(toggled(bool)), this, SLOT(switchCanvasOnly(bool)));
//Workaround, by default has the same shortcut as mirrorCanvas
KisAction *a = dynamic_cast(actionCollection()->action("format_italic"));
if (a) {
a->setDefaultShortcut(QKeySequence());
}
a = actionManager()->createAction("edit_blacklist_cleanup");
connect(a, SIGNAL(triggered()), this, SLOT(slotBlacklistCleanup()));
actionManager()->createAction("ruler_pixel_multiple2");
d->showRulersAction = actionManager()->createAction("view_ruler");
d->showRulersAction->setChecked(cfg.showRulers());
connect(d->showRulersAction, SIGNAL(toggled(bool)), SLOT(slotSaveShowRulersState(bool)));
d->rulersTrackMouseAction = actionManager()->createAction("rulers_track_mouse");
d->rulersTrackMouseAction->setChecked(cfg.rulersTrackMouse());
connect(d->rulersTrackMouseAction, SIGNAL(toggled(bool)), SLOT(slotSaveRulersTrackMouseState(bool)));
d->zoomTo100pct = actionManager()->createAction("zoom_to_100pct");
d->zoomIn = actionManager()->createStandardAction(KStandardAction::ZoomIn, 0, "");
d->zoomOut = actionManager()->createStandardAction(KStandardAction::ZoomOut, 0, "");
d->actionAuthor = new KSelectAction(KisIconUtils::loadIcon("im-user"), i18n("Active Author Profile"), this);
connect(d->actionAuthor, SIGNAL(triggered(QString)), this, SLOT(changeAuthorProfile(QString)));
actionCollection()->addAction("settings_active_author", d->actionAuthor);
slotUpdateAuthorProfileActions();
d->showPixelGrid = actionManager()->createAction("view_pixel_grid");
slotUpdatePixelGridAction();
d->toggleFgBg = actionManager()->createAction("toggle_fg_bg");
connect(d->toggleFgBg, SIGNAL(triggered(bool)), this, SLOT(slotToggleFgBg()));
d->resetFgBg = actionManager()->createAction("reset_fg_bg");
connect(d->resetFgBg, SIGNAL(triggered(bool)), this, SLOT(slotResetFgBg()));
}
void KisViewManager::setupManagers()
{
// Create the managers for filters, selections, layers etc.
// XXX: When the currentlayer changes, call updateGUI on all
// managers
d->filterManager.setup(actionCollection(), actionManager());
d->selectionManager.setup(actionManager());
d->guidesManager.setup(actionManager());
d->nodeManager.setup(actionCollection(), actionManager());
d->imageManager.setup(actionManager());
d->gridManager.setup(actionManager());
d->paintingAssistantsManager.setup(actionManager());
d->canvasControlsManager.setup(actionManager());
d->mirrorManager.setup(actionCollection());
}
void KisViewManager::updateGUI()
{
d->guiUpdateCompressor.start();
}
void KisViewManager::slotBlacklistCleanup()
{
KisDlgBlacklistCleanup dialog;
dialog.exec();
}
KisNodeManager * KisViewManager::nodeManager() const
{
return &d->nodeManager;
}
KisActionManager* KisViewManager::actionManager() const
{
return &d->actionManager;
}
KisGridManager * KisViewManager::gridManager() const
{
return &d->gridManager;
}
KisGuidesManager * KisViewManager::guidesManager() const
{
return &d->guidesManager;
}
KisDocument *KisViewManager::document() const
{
if (d->currentImageView && d->currentImageView->document()) {
return d->currentImageView->document();
}
return 0;
}
int KisViewManager::viewCount() const
{
KisMainWindow *mw = qobject_cast(d->mainWindow);
if (mw) {
return mw->viewCount();
}
return 0;
}
bool KisViewManager::KisViewManagerPrivate::blockUntilOperationsFinishedImpl(KisImageSP image, bool force)
{
const int busyWaitDelay = 1000;
KisDelayedSaveDialog dialog(image, !force ? KisDelayedSaveDialog::GeneralDialog : KisDelayedSaveDialog::ForcedDialog, busyWaitDelay, mainWindow);
dialog.blockIfImageIsBusy();
return dialog.result() == QDialog::Accepted;
}
bool KisViewManager::blockUntilOperationsFinished(KisImageSP image)
{
return d->blockUntilOperationsFinishedImpl(image, false);
}
void KisViewManager::blockUntilOperationsFinishedForced(KisImageSP image)
{
d->blockUntilOperationsFinishedImpl(image, true);
}
void KisViewManager::slotCreateTemplate()
{
if (!document()) return;
KisTemplateCreateDia::createTemplate( QStringLiteral("templates/"), ".kra", document(), mainWindow());
}
void KisViewManager::slotCreateCopy()
{
KisDocument *srcDoc = document();
if (!srcDoc) return;
if (!this->blockUntilOperationsFinished(srcDoc->image())) return;
KisDocument *doc = 0;
{
KisImageBarrierLocker l(srcDoc->image());
doc = srcDoc->clone();
}
KIS_SAFE_ASSERT_RECOVER_RETURN(doc);
QString name = srcDoc->documentInfo()->aboutInfo("name");
if (name.isEmpty()) {
name = document()->url().toLocalFile();
}
name = i18n("%1 (Copy)", name);
doc->documentInfo()->setAboutInfo("title", name);
KisPart::instance()->addDocument(doc);
KisMainWindow *mw = qobject_cast(d->mainWindow);
mw->addViewAndNotifyLoadingCompleted(doc);
}
QMainWindow* KisViewManager::qtMainWindow() const
{
if (d->mainWindow)
return d->mainWindow;
//Fallback for when we have not yet set the main window.
QMainWindow* w = qobject_cast(qApp->activeWindow());
if(w)
return w;
return mainWindow();
}
void KisViewManager::setQtMainWindow(QMainWindow* newMainWindow)
{
d->mainWindow = newMainWindow;
}
void KisViewManager::slotDocumentSaved()
{
d->saveIncremental->setEnabled(true);
d->saveIncrementalBackup->setEnabled(true);
}
void KisViewManager::slotSaveIncremental()
{
if (!document()) return;
if (document()->url().isEmpty()) {
KisMainWindow *mw = qobject_cast(d->mainWindow);
mw->saveDocument(document(), true, false);
return;
}
bool foundVersion;
bool fileAlreadyExists;
bool isBackup;
QString version = "000";
QString newVersion;
QString letter;
QString path = QFileInfo(document()->localFilePath()).canonicalPath();
QString fileName = QFileInfo(document()->localFilePath()).fileName();
// Find current version filenames
// v v Regexp to find incremental versions in the filename, taking our backup scheme into account as well
// Considering our incremental version and backup scheme, format is filename_001~001.ext
QRegExp regex("_\\d{1,4}[.]|_\\d{1,4}[a-z][.]|_\\d{1,4}[~]|_\\d{1,4}[a-z][~]");
regex.indexIn(fileName); // Perform the search
QStringList matches = regex.capturedTexts();
foundVersion = matches.at(0).isEmpty() ? false : true;
// Ensure compatibility with Save Incremental Backup
// If this regex is not kept separate, the entire algorithm needs modification;
// It's simpler to just add this.
QRegExp regexAux("_\\d{1,4}[~]|_\\d{1,4}[a-z][~]");
regexAux.indexIn(fileName); // Perform the search
QStringList matchesAux = regexAux.capturedTexts();
isBackup = matchesAux.at(0).isEmpty() ? false : true;
// If the filename has a version, prepare it for incrementation
if (foundVersion) {
version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches
if (version.contains(QRegExp("[a-z]"))) {
version.chop(1); // Trim "."
letter = version.right(1); // Save letter
version.chop(1); // Trim letter
} else {
version.chop(1); // Trim "."
}
version.remove(0, 1); // Trim "_"
} else {
// TODO: this will not work with files extensions like jp2
// ...else, simply add a version to it so the next loop works
QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension
regex2.indexIn(fileName);
QStringList matches2 = regex2.capturedTexts();
QString extensionPlusVersion = matches2.at(0);
extensionPlusVersion.prepend(version);
extensionPlusVersion.prepend("_");
fileName.replace(regex2, extensionPlusVersion);
}
// Prepare the base for new version filename
int intVersion = version.toInt(0);
++intVersion;
QString baseNewVersion = QString::number(intVersion);
while (baseNewVersion.length() < version.length()) {
baseNewVersion.prepend("0");
}
// Check if the file exists under the new name and search until options are exhausted (test appending a to z)
do {
newVersion = baseNewVersion;
newVersion.prepend("_");
if (!letter.isNull()) newVersion.append(letter);
if (isBackup) {
newVersion.append("~");
} else {
newVersion.append(".");
}
fileName.replace(regex, newVersion);
fileAlreadyExists = QFileInfo(path + '/' + fileName).exists();
if (fileAlreadyExists) {
if (!letter.isNull()) {
char letterCh = letter.at(0).toLatin1();
++letterCh;
letter = QString(QChar(letterCh));
} else {
letter = 'a';
}
}
} while (fileAlreadyExists && letter != "{"); // x, y, z, {...
if (letter == "{") {
QMessageBox::critical(mainWindow(), i18nc("@title:window", "Couldn't save incremental version"), i18n("Alternative names exhausted, try manually saving with a higher number"));
return;
}
QUrl newUrl = QUrl::fromUserInput(path + '/' + fileName);
document()->setFileBatchMode(true);
document()->saveAs(newUrl, document()->mimeType(), true);
document()->setFileBatchMode(false);
KisPart::instance()->addRecentURLToAllMainWindows(newUrl, document()->url());
if (mainWindow()) {
mainWindow()->updateCaption();
}
}
void KisViewManager::slotSaveIncrementalBackup()
{
if (!document()) return;
if (document()->url().isEmpty()) {
KisMainWindow *mw = qobject_cast(d->mainWindow);
mw->saveDocument(document(), true, false);
return;
}
bool workingOnBackup;
bool fileAlreadyExists;
QString version = "000";
QString newVersion;
QString letter;
QString path = QFileInfo(document()->localFilePath()).canonicalPath();
QString fileName = QFileInfo(document()->localFilePath()).fileName();
// First, discover if working on a backup file, or a normal file
QRegExp regex("~\\d{1,4}[.]|~\\d{1,4}[a-z][.]");
regex.indexIn(fileName); // Perform the search
QStringList matches = regex.capturedTexts();
workingOnBackup = matches.at(0).isEmpty() ? false : true;
if (workingOnBackup) {
// Try to save incremental version (of backup), use letter for alt versions
version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches
if (version.contains(QRegExp("[a-z]"))) {
version.chop(1); // Trim "."
letter = version.right(1); // Save letter
version.chop(1); // Trim letter
} else {
version.chop(1); // Trim "."
}
version.remove(0, 1); // Trim "~"
// Prepare the base for new version filename
int intVersion = version.toInt(0);
++intVersion;
QString baseNewVersion = QString::number(intVersion);
QString backupFileName = document()->localFilePath();
while (baseNewVersion.length() < version.length()) {
baseNewVersion.prepend("0");
}
// Check if the file exists under the new name and search until options are exhausted (test appending a to z)
do {
newVersion = baseNewVersion;
newVersion.prepend("~");
if (!letter.isNull()) newVersion.append(letter);
newVersion.append(".");
backupFileName.replace(regex, newVersion);
fileAlreadyExists = QFile(backupFileName).exists();
if (fileAlreadyExists) {
if (!letter.isNull()) {
char letterCh = letter.at(0).toLatin1();
++letterCh;
letter = QString(QChar(letterCh));
} else {
letter = 'a';
}
}
} while (fileAlreadyExists && letter != "{"); // x, y, z, {...
if (letter == "{") {
QMessageBox::critical(mainWindow(), i18nc("@title:window", "Couldn't save incremental backup"), i18n("Alternative names exhausted, try manually saving with a higher number"));
return;
}
QFile::copy(path + '/' + fileName, path + '/' + backupFileName);
document()->saveAs(QUrl::fromUserInput(path + '/' + fileName), document()->mimeType(), true);
if (mainWindow()) mainWindow()->updateCaption();
}
else { // if NOT working on a backup...
// Navigate directory searching for latest backup version, ignore letters
const quint8 HARDCODED_DIGIT_COUNT = 3;
QString baseNewVersion = "000";
QString backupFileName = QFileInfo(document()->localFilePath()).fileName();
QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension
regex2.indexIn(backupFileName);
QStringList matches2 = regex2.capturedTexts();
QString extensionPlusVersion = matches2.at(0);
extensionPlusVersion.prepend(baseNewVersion);
extensionPlusVersion.prepend("~");
backupFileName.replace(regex2, extensionPlusVersion);
// Save version with 1 number higher than the highest version found ignoring letters
do {
newVersion = baseNewVersion;
newVersion.prepend("~");
newVersion.append(".");
backupFileName.replace(regex, newVersion);
fileAlreadyExists = QFile(backupFileName).exists();
if (fileAlreadyExists) {
// Prepare the base for new version filename, increment by 1
int intVersion = baseNewVersion.toInt(0);
++intVersion;
baseNewVersion = QString::number(intVersion);
while (baseNewVersion.length() < HARDCODED_DIGIT_COUNT) {
baseNewVersion.prepend("0");
}
}
} while (fileAlreadyExists);
// Save both as backup and on current file for interapplication workflow
document()->setFileBatchMode(true);
QFile::copy(path + '/' + fileName, path + '/' + backupFileName);
document()->saveAs(QUrl::fromUserInput(path + '/' + fileName), document()->mimeType(), true);
document()->setFileBatchMode(false);
if (mainWindow()) mainWindow()->updateCaption();
}
}
void KisViewManager::disableControls()
{
// prevents possible crashes, if somebody changes the paintop during dragging by using the mousewheel
// this is for Bug 250944
// the solution blocks all wheel, mouse and key event, while dragging with the freehand tool
// see KisToolFreehand::initPaint() and endPaint()
d->controlFrame.paintopBox()->installEventFilter(&d->blockingEventFilter);
Q_FOREACH (QObject* child, d->controlFrame.paintopBox()->children()) {
child->installEventFilter(&d->blockingEventFilter);
}
}
void KisViewManager::enableControls()
{
d->controlFrame.paintopBox()->removeEventFilter(&d->blockingEventFilter);
Q_FOREACH (QObject* child, d->controlFrame.paintopBox()->children()) {
child->removeEventFilter(&d->blockingEventFilter);
}
}
void KisViewManager::showStatusBar(bool toggled)
{
KisMainWindow *mw = mainWindow();
if(mw && mw->statusBar()) {
mw->statusBar()->setVisible(toggled);
KisConfig cfg(false);
cfg.setShowStatusBar(toggled);
}
}
void KisViewManager::switchCanvasOnly(bool toggled)
{
KisConfig cfg(false);
KisMainWindow *main = mainWindow();
if(!main) {
dbgUI << "Unable to switch to canvas-only mode, main window not found";
return;
}
cfg.writeEntry("CanvasOnlyActive", toggled);
if (toggled) {
d->canvasState = qtMainWindow()->saveState();
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
d->windowFlags = main->windowState();
#endif
}
if (cfg.hideStatusbarFullscreen()) {
if (main->statusBar()) {
if (!toggled) {
if (main->statusBar()->dynamicPropertyNames().contains("wasvisible")) {
if (main->statusBar()->property("wasvisible").toBool()) {
main->statusBar()->setVisible(true);
}
}
}
else {
main->statusBar()->setProperty("wasvisible", main->statusBar()->isVisible());
main->statusBar()->setVisible(false);
}
}
}
if (cfg.hideDockersFullscreen()) {
KisAction* action = qobject_cast(main->actionCollection()->action("view_toggledockers"));
if (action) {
action->setCheckable(true);
if (toggled) {
if (action->isChecked()) {
cfg.setShowDockers(action->isChecked());
action->setChecked(false);
} else {
cfg.setShowDockers(false);
}
} else {
action->setChecked(cfg.showDockers());
}
}
}
// QT in windows does not return to maximized upon 4th tab in a row
// https://bugreports.qt.io/browse/QTBUG-57882, https://bugreports.qt.io/browse/QTBUG-52555, https://codereview.qt-project.org/#/c/185016/
if (cfg.hideTitlebarFullscreen() && !cfg.fullscreenMode()) {
if(toggled) {
main->setWindowState( main->windowState() | Qt::WindowFullScreen);
} else {
main->setWindowState( main->windowState() & ~Qt::WindowFullScreen);
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
// If window was maximized prior to fullscreen, restore that
if (d->windowFlags & Qt::WindowMaximized) {
main->setWindowState( main->windowState() | Qt::WindowMaximized);
}
#endif
}
}
if (cfg.hideMenuFullscreen()) {
if (!toggled) {
if (main->menuBar()->dynamicPropertyNames().contains("wasvisible")) {
if (main->menuBar()->property("wasvisible").toBool()) {
main->menuBar()->setVisible(true);
}
}
}
else {
main->menuBar()->setProperty("wasvisible", main->menuBar()->isVisible());
main->menuBar()->setVisible(false);
}
}
if (cfg.hideToolbarFullscreen()) {
QList toolBars = main->findChildren();
Q_FOREACH (QToolBar* toolbar, toolBars) {
if (!toggled) {
if (toolbar->dynamicPropertyNames().contains("wasvisible")) {
if (toolbar->property("wasvisible").toBool()) {
toolbar->setVisible(true);
}
}
}
else {
toolbar->setProperty("wasvisible", toolbar->isVisible());
toolbar->setVisible(false);
}
}
}
showHideScrollbars();
if (toggled) {
// show a fading heads-up display about the shortcut to go back
showFloatingMessage(i18n("Going into Canvas-Only mode.\nPress %1 to go back.",
actionCollection()->action("view_show_canvas_only")->shortcut().toString()), QIcon());
}
else {
main->restoreState(d->canvasState);
}
}
void KisViewManager::toggleTabletLogger()
{
d->inputManager.toggleTabletLogger();
}
void KisViewManager::openResourcesDirectory()
{
QString dir = KoResourcePaths::locateLocal("data", "");
QDesktopServices::openUrl(QUrl::fromLocalFile(dir));
}
void KisViewManager::updateIcons()
{
if (mainWindow()) {
QList dockers = mainWindow()->dockWidgets();
Q_FOREACH (QDockWidget* dock, dockers) {
QObjectList objects;
objects.append(dock);
while (!objects.isEmpty()) {
QObject* object = objects.takeFirst();
objects.append(object->children());
KisIconUtils::updateIconCommon(object);
}
}
}
}
void KisViewManager::initializeStatusBarVisibility()
{
KisConfig cfg(true);
d->mainWindow->statusBar()->setVisible(cfg.showStatusBar());
}
void KisViewManager::guiUpdateTimeout()
{
d->nodeManager.updateGUI();
d->selectionManager.updateGUI();
d->filterManager.updateGUI();
if (zoomManager()) {
zoomManager()->updateGuiAfterDocumentSize();
}
d->gridManager.updateGUI();
d->actionManager.updateGUI();
}
void KisViewManager::showFloatingMessage(const QString &message, const QIcon& icon, int timeout, KisFloatingMessage::Priority priority, int alignment)
{
if (!d->currentImageView) return;
d->currentImageView->showFloatingMessage(message, icon, timeout, priority, alignment);
emit floatingMessageRequested(message, icon.name());
}
KisMainWindow *KisViewManager::mainWindow() const
{
return qobject_cast(d->mainWindow);
}
void KisViewManager::showHideScrollbars()
{
if (!d->currentImageView) return;
if (!d->currentImageView->canvasController()) return;
KisConfig cfg(true);
bool toggled = actionCollection()->action("view_show_canvas_only")->isChecked();
if ( (toggled && cfg.hideScrollbarsFullscreen()) || (!toggled && cfg.hideScrollbars()) ) {
d->currentImageView->canvasController()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
d->currentImageView->canvasController()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
} else {
d->currentImageView->canvasController()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
d->currentImageView->canvasController()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
}
}
void KisViewManager::slotSaveShowRulersState(bool value)
{
KisConfig cfg(false);
cfg.setShowRulers(value);
}
void KisViewManager::slotSaveRulersTrackMouseState(bool value)
{
KisConfig cfg(false);
cfg.setRulersTrackMouse(value);
}
void KisViewManager::setShowFloatingMessage(bool show)
{
d->showFloatingMessage = show;
}
void KisViewManager::changeAuthorProfile(const QString &profileName)
{
KConfigGroup appAuthorGroup(KSharedConfig::openConfig(), "Author");
if (profileName.isEmpty() || profileName == i18nc("choice for author profile", "Anonymous")) {
appAuthorGroup.writeEntry("active-profile", "");
} else {
appAuthorGroup.writeEntry("active-profile", profileName);
}
appAuthorGroup.sync();
Q_FOREACH (KisDocument *doc, KisPart::instance()->documents()) {
doc->documentInfo()->updateParameters();
}
}
void KisViewManager::slotUpdateAuthorProfileActions()
{
Q_ASSERT(d->actionAuthor);
if (!d->actionAuthor) {
return;
}
d->actionAuthor->clear();
d->actionAuthor->addAction(i18nc("choice for author profile", "Anonymous"));
KConfigGroup authorGroup(KSharedConfig::openConfig(), "Author");
QStringList profiles = authorGroup.readEntry("profile-names", QStringList());
QString authorInfo = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/authorinfo/";
QStringList filters = QStringList() << "*.authorinfo";
QDir dir(authorInfo);
Q_FOREACH(QString entry, dir.entryList(filters)) {
int ln = QString(".authorinfo").size();
entry.chop(ln);
if (!profiles.contains(entry)) {
profiles.append(entry);
}
}
Q_FOREACH (const QString &profile , profiles) {
d->actionAuthor->addAction(profile);
}
KConfigGroup appAuthorGroup(KSharedConfig::openConfig(), "Author");
QString profileName = appAuthorGroup.readEntry("active-profile", "");
if (profileName == "anonymous" || profileName.isEmpty()) {
d->actionAuthor->setCurrentItem(0);
} else if (profiles.contains(profileName)) {
d->actionAuthor->setCurrentAction(profileName);
}
}
void KisViewManager::slotUpdatePixelGridAction()
{
KIS_SAFE_ASSERT_RECOVER_RETURN(d->showPixelGrid);
KisSignalsBlocker b(d->showPixelGrid);
KisConfig cfg(true);
d->showPixelGrid->setChecked(cfg.pixelGridEnabled() && cfg.useOpenGL());
}
void KisViewManager::slotActivateTransformTool()
{
if(KoToolManager::instance()->activeToolId() == "KisToolTransform") {
KoToolBase* tool = KoToolManager::instance()->toolById(canvasBase(), "KisToolTransform");
QSet dummy;
// Start a new stroke
tool->deactivate();
tool->activate(KoToolBase::DefaultActivation, dummy);
}
KoToolManager::instance()->switchToolRequested("KisToolTransform");
}
void KisViewManager::slotToggleFgBg()
{
KoColor newFg = d->canvasResourceManager.backgroundColor();
KoColor newBg = d->canvasResourceManager.foregroundColor();
/**
* NOTE: Some of color selectors do not differentiate foreground
* and background colors, so if one wants them to end up
* being set up to foreground color, it should be set the
* last.
*/
d->canvasResourceManager.setBackgroundColor(newBg);
d->canvasResourceManager.setForegroundColor(newFg);
}
void KisViewManager::slotResetFgBg()
{
// see a comment in slotToggleFgBg()
d->canvasResourceManager.setBackgroundColor(KoColor(Qt::white, KoColorSpaceRegistry::instance()->rgb8()));
d->canvasResourceManager.setForegroundColor(KoColor(Qt::black, KoColorSpaceRegistry::instance()->rgb8()));
}
void KisViewManager::slotResetRotation()
{
KisCanvasController *canvasController = d->currentImageView->canvasController();
canvasController->resetCanvasRotation();
}
void KisViewManager::slotToggleFullscreen()
{
KisConfig cfg(false);
KisMainWindow *main = mainWindow();
main->viewFullscreen(!main->isFullScreen());
cfg.fullscreenMode(main->isFullScreen());
}
diff --git a/libs/ui/forms/wdgmultipliersdoublesliderspinbox.ui b/libs/ui/forms/wdgmultipliersdoublesliderspinbox.ui
index d943fa96ce..ea47b46eb2 100644
--- a/libs/ui/forms/wdgmultipliersdoublesliderspinbox.ui
+++ b/libs/ui/forms/wdgmultipliersdoublesliderspinbox.ui
@@ -1,58 +1,70 @@
WdgMultipliersDoubleSliderSpinBox
0
0
395
25
-
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
0
-
-
+
-
+
0
0
-
-
+
0
0
52
16777215
QComboBox::InsertAlphabetically
KisDoubleSliderSpinBox
QWidget
1
diff --git a/libs/ui/kis_canvas_resource_provider.cpp b/libs/ui/kis_canvas_resource_provider.cpp
index 806dbf6698..df5f283528 100644
--- a/libs/ui/kis_canvas_resource_provider.cpp
+++ b/libs/ui/kis_canvas_resource_provider.cpp
@@ -1,557 +1,567 @@
/*
* Copyright (c) 2006 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_canvas_resource_provider.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_favorite_resource_manager.h"
#include "kis_config.h"
#include "KisViewManager.h"
#include "canvas/kis_canvas2.h"
KisCanvasResourceProvider::KisCanvasResourceProvider(KisViewManager * view)
: m_view(view)
{
m_fGChanged = true;
}
KisCanvasResourceProvider::~KisCanvasResourceProvider()
{
disconnect(); // in case Qt gets confused
}
KoCanvasResourceProvider* KisCanvasResourceProvider::resourceManager()
{
return m_resourceManager;
}
void KisCanvasResourceProvider::setResourceManager(KoCanvasResourceProvider *resourceManager)
{
m_resourceManager = resourceManager;
QVariant v;
v.setValue(KoColor(Qt::black, KoColorSpaceRegistry::instance()->rgb8()));
m_resourceManager->setResource(KoCanvasResourceProvider::ForegroundColor, v);
v.setValue(KoColor(Qt::white, KoColorSpaceRegistry::instance()->rgb8()));
m_resourceManager->setResource(KoCanvasResourceProvider::BackgroundColor, v);
setCurrentCompositeOp(COMPOSITE_OVER);
setMirrorHorizontal(false);
setMirrorVertical(false);
m_resourceManager->setResource(HdrExposure, 0.0);
m_resourceManager->setResource(HdrGamma, 1.0);
m_resourceManager->setResource(EffectiveZoom, 1.0);
connect(m_resourceManager, SIGNAL(canvasResourceChanged(int,QVariant)),
this, SLOT(slotCanvasResourceChanged(int,QVariant)));
m_resourceManager->setResource(KoCanvasResourceProvider::ApplicationSpeciality, KoCanvasResourceProvider::NoAdvancedText);
m_resourceManager->setResource(GamutMaskActive, false);
}
KoCanvasBase * KisCanvasResourceProvider::canvas() const
{
return m_view->canvasBase();
}
KoColor KisCanvasResourceProvider::bgColor() const
{
return m_resourceManager->resource(KoCanvasResourceProvider::BackgroundColor).value();
}
KoColor KisCanvasResourceProvider::fgColor() const
{
return m_resourceManager->resource(KoCanvasResourceProvider::ForegroundColor).value();
}
float KisCanvasResourceProvider::HDRExposure() const
{
return static_cast(m_resourceManager->resource(HdrExposure).toDouble());
}
void KisCanvasResourceProvider::setHDRExposure(float exposure)
{
m_resourceManager->setResource(HdrExposure, static_cast(exposure));
}
float KisCanvasResourceProvider::HDRGamma() const
{
return static_cast(m_resourceManager->resource(HdrGamma).toDouble());
}
void KisCanvasResourceProvider::setHDRGamma(float gamma)
{
m_resourceManager->setResource(HdrGamma, static_cast(gamma));
}
KoPattern * KisCanvasResourceProvider::currentPattern() const
{
if (m_resourceManager->hasResource(CurrentPattern)) {
return m_resourceManager->resource(CurrentPattern).value();
}
else {
return 0;
}
}
KoAbstractGradient* KisCanvasResourceProvider::currentGradient() const
{
if (m_resourceManager->hasResource(CurrentGradient)) {
return m_resourceManager->resource(CurrentGradient).value();
}
else {
return 0;
}
}
KisImageWSP KisCanvasResourceProvider::currentImage() const
{
return m_view->image();
}
KisNodeSP KisCanvasResourceProvider::currentNode() const
{
return m_view->activeNode();
}
KoGamutMask *KisCanvasResourceProvider::currentGamutMask() const
{
if (m_resourceManager->hasResource(CurrentGamutMask)) {
return m_resourceManager->resource(CurrentGamutMask).value();
}
else {
return nullptr;
}
}
bool KisCanvasResourceProvider::gamutMaskActive() const
{
return m_resourceManager->resource(GamutMaskActive).toBool();
}
KisPaintOpPresetSP KisCanvasResourceProvider::currentPreset() const
{
KisPaintOpPresetSP preset = m_resourceManager->resource(CurrentPaintOpPreset).value();
return preset;
}
void KisCanvasResourceProvider::setPaintOpPreset(const KisPaintOpPresetSP preset)
{
Q_ASSERT(preset->valid());
Q_ASSERT(!preset->paintOp().id().isEmpty());
Q_ASSERT(preset->settings());
if (!preset) return;
dbgUI << "setPaintOpPreset" << preset->paintOp();
QVariant v;
v.setValue(preset);
m_resourceManager->setResource(CurrentPaintOpPreset, v);
}
KisPaintOpPresetSP KisCanvasResourceProvider::previousPreset() const
{
KisPaintOpPresetSP preset = m_resourceManager->resource(PreviousPaintOpPreset).value();
return preset;
}
void KisCanvasResourceProvider::setPreviousPaintOpPreset(const KisPaintOpPresetSP preset)
{
Q_ASSERT(preset->valid());
Q_ASSERT(!preset->paintOp().id().isEmpty());
Q_ASSERT(preset->settings());
if (!preset) return;
dbgUI << "setPreviousPaintOpPreset" << preset->paintOp();
QVariant v;
v.setValue(preset);
m_resourceManager->setResource(PreviousPaintOpPreset, v);
}
void KisCanvasResourceProvider::slotPatternActivated(KoResource * res)
{
KoPattern *pattern = dynamic_cast(res);
QVariant v;
v.setValue(pattern);
m_resourceManager->setResource(CurrentPattern, v);
emit sigPatternChanged(pattern);
}
void KisCanvasResourceProvider::slotGradientActivated(KoResource *res)
{
KoAbstractGradient * gradient = dynamic_cast(res);
QVariant v;
v.setValue(gradient);
m_resourceManager->setResource(CurrentGradient, v);
emit sigGradientChanged(gradient);
}
void KisCanvasResourceProvider::setBGColor(const KoColor& c)
{
QVariant v;
v.setValue(c);
m_resourceManager->setResource(KoCanvasResourceProvider::BackgroundColor, v);
emit sigBGColorChanged(c);
}
void KisCanvasResourceProvider::setFGColor(const KoColor& c)
{
m_fGChanged = true;
QVariant v;
v.setValue(c);
m_resourceManager->setResource(KoCanvasResourceProvider::ForegroundColor, v);
emit sigFGColorChanged(c);
}
void KisCanvasResourceProvider::slotSetFGColor(const KoColor& c)
{
setFGColor(c);
}
void KisCanvasResourceProvider::slotSetBGColor(const KoColor& c)
{
setBGColor(c);
}
void KisCanvasResourceProvider::slotNodeActivated(const KisNodeSP node)
{
QVariant v;
v.setValue(KisNodeWSP(node));
m_resourceManager->setResource(CurrentKritaNode, v);
emit sigNodeChanged(currentNode());
}
void KisCanvasResourceProvider::slotImageSizeChanged()
{
if (KisImageWSP image = m_view->image()) {
float fw = image->width() / image->xRes();
float fh = image->height() / image->yRes();
QSizeF postscriptSize(fw, fh);
m_resourceManager->setResource(KoCanvasResourceProvider::PageSize, postscriptSize);
}
}
void KisCanvasResourceProvider::slotOnScreenResolutionChanged()
{
KisImageWSP image = m_view->image();
KisCanvas2 *canvas = m_view->canvasBase();
if(!image || !canvas) return;
qreal zoomX, zoomY;
canvas->coordinatesConverter()->zoom(&zoomX, &zoomY);
qreal scaleX = zoomX / image->xRes();
qreal scaleY = zoomY / image->yRes();
emit sigOnScreenResolutionChanged(scaleX, scaleY);
}
void KisCanvasResourceProvider::slotCanvasResourceChanged(int key, const QVariant & res)
{
if(key == KoCanvasResourceProvider::ForegroundColor || key == KoCanvasResourceProvider::BackgroundColor) {
KoAbstractGradient* resource = KoResourceServerProvider::instance()->gradientServer()->resources()[0];
KoStopGradient* stopGradient = dynamic_cast(resource);
if(stopGradient) {
QList stops;
stops << KoGradientStop(0.0, fgColor()) << KoGradientStop(1.0, KoColor(QColor(0, 0, 0, 0), fgColor().colorSpace()));
stopGradient->setStops(stops);
KoResourceServerProvider::instance()->gradientServer()->updateResource(resource);
}
resource = KoResourceServerProvider::instance()->gradientServer()->resources()[1];
stopGradient = dynamic_cast(resource);
if(stopGradient) {
QList stops;
stops << KoGradientStop(0.0, fgColor()) << KoGradientStop(1.0, bgColor());
stopGradient->setStops(stops);
KoResourceServerProvider::instance()->gradientServer()->updateResource(resource);
}
}
switch (key) {
case(KoCanvasResourceProvider::ForegroundColor):
m_fGChanged = true;
emit sigFGColorChanged(res.value());
break;
case(KoCanvasResourceProvider::BackgroundColor):
emit sigBGColorChanged(res.value());
break;
case(CurrentPattern):
emit sigPatternChanged(static_cast(res.value()));
break;
case(CurrentGradient):
emit sigGradientChanged(static_cast(res.value()));
break;
case(CurrentKritaNode) :
emit sigNodeChanged(currentNode());
break;
case (Opacity):
{
emit sigOpacityChanged(res.toDouble());
}
default:
;
// Do nothing
};
}
void KisCanvasResourceProvider::setCurrentCompositeOp(const QString& compositeOp)
{
m_resourceManager->setResource(CurrentCompositeOp,
QVariant::fromValue(compositeOp));
}
QString KisCanvasResourceProvider::currentCompositeOp() const
{
return m_resourceManager->resource(CurrentCompositeOp).value();
}
bool KisCanvasResourceProvider::eraserMode() const
{
return m_resourceManager->resource(EraserMode).toBool();
}
void KisCanvasResourceProvider::setEraserMode(bool value)
{
m_resourceManager->setResource(EraserMode,
QVariant::fromValue(value));
}
void KisCanvasResourceProvider::slotPainting()
{
if (m_fGChanged) {
emit sigFGColorUsed(fgColor());
m_fGChanged = false;
}
}
void KisCanvasResourceProvider::slotGamutMaskActivated(KoGamutMask *mask)
{
QVariant v;
v.setValue(mask);
m_resourceManager->setResource(CurrentGamutMask, v);
m_resourceManager->setResource(GamutMaskActive, QVariant::fromValue(true));
emit sigGamutMaskChanged(mask);
}
void KisCanvasResourceProvider::slotGamutMaskUnset()
{
m_resourceManager->setResource(GamutMaskActive, QVariant::fromValue(false));
m_resourceManager->clearResource(CurrentGamutMask);
emit sigGamutMaskUnset();
}
void KisCanvasResourceProvider::slotGamutMaskPreviewUpdate()
{
emit sigGamutMaskPreviewUpdate();
}
void KisCanvasResourceProvider::slotGamutMaskDeactivate()
{
m_resourceManager->setResource(GamutMaskActive, QVariant::fromValue(false));
emit sigGamutMaskDeactivated();
}
QList > KisCanvasResourceProvider::perspectiveGrids() const
{
return m_perspectiveGrids;
}
void KisCanvasResourceProvider::addPerspectiveGrid(KisAbstractPerspectiveGrid* grid)
{
m_perspectiveGrids.append(grid);
}
void KisCanvasResourceProvider::removePerspectiveGrid(KisAbstractPerspectiveGrid* grid)
{
m_perspectiveGrids.removeOne(grid);
}
void KisCanvasResourceProvider::clearPerspectiveGrids()
{
m_perspectiveGrids.clear();
}
void KisCanvasResourceProvider::setMirrorHorizontal(bool mirrorHorizontal)
{
m_resourceManager->setResource(MirrorHorizontal, mirrorHorizontal);
emit mirrorModeChanged();
}
bool KisCanvasResourceProvider::mirrorHorizontal() const
{
return m_resourceManager->resource(MirrorHorizontal).toBool();
}
void KisCanvasResourceProvider::setMirrorVertical(bool mirrorVertical)
{
m_resourceManager->setResource(MirrorVertical, mirrorVertical);
emit mirrorModeChanged();
}
bool KisCanvasResourceProvider::mirrorVertical() const
{
return m_resourceManager->resource(MirrorVertical).toBool();
}
void KisCanvasResourceProvider::setMirrorHorizontalLock(bool isLocked)
{
m_resourceManager->setResource(MirrorHorizontalLock, isLocked);
emit mirrorModeChanged();
}
bool KisCanvasResourceProvider::mirrorHorizontalLock() {
return m_resourceManager->resource(MirrorHorizontalLock).toBool();
}
void KisCanvasResourceProvider::setMirrorVerticalLock(bool isLocked)
{
m_resourceManager->setResource(MirrorVerticalLock, isLocked);
emit mirrorModeChanged();
}
bool KisCanvasResourceProvider::mirrorVerticalHideDecorations() {
return m_resourceManager->resource(MirrorVerticalHideDecorations).toBool();
}
void KisCanvasResourceProvider::setMirrorVerticalHideDecorations(bool hide)
{
m_resourceManager->setResource(MirrorVerticalHideDecorations, hide);
emit mirrorModeChanged();
}
bool KisCanvasResourceProvider::mirrorHorizontalHideDecorations() {
return m_resourceManager->resource(MirrorHorizontalHideDecorations).toBool();
}
void KisCanvasResourceProvider::setMirrorHorizontalHideDecorations(bool hide)
{
m_resourceManager->setResource(MirrorHorizontalHideDecorations, hide);
emit mirrorModeChanged();
}
bool KisCanvasResourceProvider::mirrorVerticalLock() {
return m_resourceManager->resource(MirrorVerticalLock).toBool();
}
void KisCanvasResourceProvider::mirrorVerticalMoveCanvasToCenter() {
emit moveMirrorVerticalCenter();
}
void KisCanvasResourceProvider::mirrorHorizontalMoveCanvasToCenter() {
emit moveMirrorHorizontalCenter();
}
void KisCanvasResourceProvider::setOpacity(qreal opacity)
{
m_resourceManager->setResource(Opacity, opacity);
}
qreal KisCanvasResourceProvider::opacity() const
{
return m_resourceManager->resource(Opacity).toReal();
}
void KisCanvasResourceProvider::setFlow(qreal flow)
{
m_resourceManager->setResource(Flow, flow);
}
qreal KisCanvasResourceProvider::flow() const
{
return m_resourceManager->resource(Flow).toReal();
}
void KisCanvasResourceProvider::setSize(qreal size)
{
m_resourceManager->setResource(Size, size);
}
qreal KisCanvasResourceProvider::size() const
{
return m_resourceManager->resource(Size).toReal();
}
+void KisCanvasResourceProvider::setPatternSize(qreal size)
+{
+ m_resourceManager->setResource(PatternSize, size);
+}
+
+qreal KisCanvasResourceProvider::patternSize() const
+{
+ return m_resourceManager->resource(PatternSize).toReal();
+}
+
void KisCanvasResourceProvider::setGlobalAlphaLock(bool lock)
{
m_resourceManager->setResource(GlobalAlphaLock, lock);
}
bool KisCanvasResourceProvider::globalAlphaLock() const
{
return m_resourceManager->resource(GlobalAlphaLock).toBool();
}
void KisCanvasResourceProvider::setDisablePressure(bool value)
{
m_resourceManager->setResource(DisablePressure, value);
}
bool KisCanvasResourceProvider::disablePressure() const
{
return m_resourceManager->resource(DisablePressure).toBool();
}
void KisCanvasResourceProvider::notifyLoadingWorkspace(KisWorkspaceResource* workspace)
{
emit sigLoadingWorkspace(workspace);
}
void KisCanvasResourceProvider::notifySavingWorkspace(KisWorkspaceResource* workspace)
{
emit sigSavingWorkspace(workspace);
}
diff --git a/libs/ui/kis_canvas_resource_provider.h b/libs/ui/kis_canvas_resource_provider.h
index 5ca69579d5..60c70adeae 100644
--- a/libs/ui/kis_canvas_resource_provider.h
+++ b/libs/ui/kis_canvas_resource_provider.h
@@ -1,235 +1,239 @@
/*
* Copyright (c) 2006 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.
*/
#ifndef KIS_CANVAS_RESOURCE_PROVIDER_H_
#define KIS_CANVAS_RESOURCE_PROVIDER_H_
#include
#include
#include
#include
#include "kis_types.h"
#include "kritaui_export.h"
class KisWorkspaceResource;
class KoColorProfile;
class KoAbstractGradient;
class KoResource;
class KoCanvasBase;
class KisViewManager;
class KoPattern;
class KoGamutMask;
class KisFilterConfiguration;
#include
/**
* KisCanvasResourceProvider contains the per-window current settings that
* influence painting, like paintop, color, gradients and so on.
*/
class KRITAUI_EXPORT KisCanvasResourceProvider : public QObject
{
Q_OBJECT
public:
enum Resources {
HdrExposure = KoCanvasResourceProvider::KritaStart + 1,
CurrentPattern,
CurrentGamutMask,
GamutMaskActive,
CurrentGradient,
CurrentDisplayProfile,
CurrentKritaNode,
CurrentPaintOpPreset,
CurrentGeneratorConfiguration,
CurrentCompositeOp,
CurrentEffectiveCompositeOp,
LodAvailability, ///<-user choice
LodSizeThreshold, ///<-user choice
LodSizeThresholdSupported, ///<-paintop property
EffectiveLodAvailablility, ///<- a superposition of user choice, threshold and paintop traits
EraserMode,
MirrorHorizontal,
MirrorVertical,
MirrorHorizontalLock,
MirrorVerticalLock,
MirrorVerticalHideDecorations,
MirrorHorizontalHideDecorations,
Opacity,
Flow,
Size,
HdrGamma,
GlobalAlphaLock,
DisablePressure,
PreviousPaintOpPreset,
- EffectiveZoom ///<-Used only by painting tools for non-displaying purposes
+ EffectiveZoom, ///<-Used only by painting tools for non-displaying purposes
+ PatternSize
};
KisCanvasResourceProvider(KisViewManager * view);
~KisCanvasResourceProvider() override;
void setResourceManager(KoCanvasResourceProvider *resourceManager);
KoCanvasResourceProvider* resourceManager();
KoCanvasBase * canvas() const;
KoColor bgColor() const;
void setBGColor(const KoColor& c);
KoColor fgColor() const;
void setFGColor(const KoColor& c);
float HDRExposure() const;
void setHDRExposure(float exposure);
float HDRGamma() const;
void setHDRGamma(float gamma);
bool eraserMode() const;
void setEraserMode(bool value);
KoPattern *currentPattern() const;
KoAbstractGradient *currentGradient() const;
KisImageWSP currentImage() const;
KisNodeSP currentNode() const;
KoGamutMask* currentGamutMask() const;
bool gamutMaskActive() const;
KisPaintOpPresetSP currentPreset() const;
void setPaintOpPreset(const KisPaintOpPresetSP preset);
KisPaintOpPresetSP previousPreset() const;
void setPreviousPaintOpPreset(const KisPaintOpPresetSP preset);
void setCurrentCompositeOp(const QString& compositeOp);
QString currentCompositeOp() const;
QList > perspectiveGrids() const;
void addPerspectiveGrid(KisAbstractPerspectiveGrid*);
void removePerspectiveGrid(KisAbstractPerspectiveGrid*);
void clearPerspectiveGrids();
void setMirrorHorizontal(bool mirrorHorizontal);
bool mirrorHorizontal() const;
void setMirrorVertical(bool mirrorVertical);
bool mirrorVertical() const;
// options for horizontal and vertical mirror toolbar
void setMirrorHorizontalLock(bool isLocked);
bool mirrorHorizontalLock();
void setMirrorVerticalLock(bool isLocked);
bool mirrorVerticalLock();
void setMirrorVerticalHideDecorations(bool hide);
bool mirrorVerticalHideDecorations();
void setMirrorHorizontalHideDecorations(bool hide);
bool mirrorHorizontalHideDecorations();
void mirrorVerticalMoveCanvasToCenter();
void mirrorHorizontalMoveCanvasToCenter();
void setOpacity(qreal opacity);
qreal opacity() const;
void setFlow(qreal opacity);
qreal flow() const;
void setSize(qreal size);
qreal size() const;
+ void setPatternSize(qreal size);
+ qreal patternSize() const;
+
void setGlobalAlphaLock(bool lock);
bool globalAlphaLock() const;
void setDisablePressure(bool value);
bool disablePressure() const;
///Notify that the workspace is saved and settings should be saved to it
void notifySavingWorkspace(KisWorkspaceResource* workspace);
///Notify that the workspace is loaded and settings can be read
void notifyLoadingWorkspace(KisWorkspaceResource* workspace);
public Q_SLOTS:
void slotSetFGColor(const KoColor& c);
void slotSetBGColor(const KoColor& c);
void slotPatternActivated(KoResource *pattern);
void slotGradientActivated(KoResource *gradient);
void slotNodeActivated(const KisNodeSP node);
void slotPainting();
void slotGamutMaskActivated(KoGamutMask* mask);
void slotGamutMaskUnset();
void slotGamutMaskPreviewUpdate();
void slotGamutMaskDeactivate();
/**
* Set the image size in pixels. The resource provider will store
* the image size in postscript points.
*/
// FIXME: this slot doesn't catch the case when image resolution is changed
void slotImageSizeChanged();
void slotOnScreenResolutionChanged();
private Q_SLOTS:
void slotCanvasResourceChanged(int key, const QVariant & res);
Q_SIGNALS:
void sigFGColorChanged(const KoColor &);
void sigBGColorChanged(const KoColor &);
void sigGradientChanged(KoAbstractGradient *);
void sigPatternChanged(KoPattern *);
void sigNodeChanged(const KisNodeSP);
void sigDisplayProfileChanged(const KoColorProfile *);
void sigFGColorUsed(const KoColor&);
void sigOnScreenResolutionChanged(qreal scaleX, qreal scaleY);
void sigOpacityChanged(qreal);
void sigSavingWorkspace(KisWorkspaceResource* workspace);
void sigLoadingWorkspace(KisWorkspaceResource* workspace);
void mirrorModeChanged();
void moveMirrorVerticalCenter();
void moveMirrorHorizontalCenter();
void sigGamutMaskChanged(KoGamutMask* mask);
void sigGamutMaskUnset();
void sigGamutMaskPreviewUpdate();
void sigGamutMaskDeactivated();
private:
KisViewManager * m_view;
KoCanvasResourceProvider *m_resourceManager;
bool m_fGChanged;
QList > m_perspectiveGrids;
};
#endif
diff --git a/libs/ui/kis_derived_resources.cpp b/libs/ui/kis_derived_resources.cpp
index 36c810ed95..e8ec75e8d7 100644
--- a/libs/ui/kis_derived_resources.cpp
+++ b/libs/ui/kis_derived_resources.cpp
@@ -1,288 +1,316 @@
/*
* Copyright (c) 2016 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_derived_resources.h"
#include "kis_signal_auto_connection.h"
#include "kis_canvas_resource_provider.h"
#include "kis_paintop_preset.h"
#include "kis_paintop_settings.h"
#include "kis_paintop_settings_update_proxy.h"
struct KisPresetUpdateMediator::Private
{
KisSignalAutoConnectionsStore connections;
};
KisPresetUpdateMediator::KisPresetUpdateMediator()
: KoResourceUpdateMediator(KisCanvasResourceProvider::CurrentPaintOpPreset),
m_d(new Private)
{
}
KisPresetUpdateMediator::~KisPresetUpdateMediator()
{
}
void KisPresetUpdateMediator::connectResource(QVariant sourceResource)
{
KisPaintOpPresetSP preset = sourceResource.value();
if (!preset) return;
m_d->connections.clear();
m_d->connections.addUniqueConnection(
preset->updateProxy(),
SIGNAL(sigSettingsChanged()),
this,
SLOT(slotSettingsChanged()));
}
void KisPresetUpdateMediator::slotSettingsChanged()
{
emit sigResourceChanged(key());
}
/*********************************************************************/
/* KisCompositeOpResourceConverter */
/*********************************************************************/
KisCompositeOpResourceConverter::KisCompositeOpResourceConverter()
: KoDerivedResourceConverter(KisCanvasResourceProvider::CurrentCompositeOp,
KisCanvasResourceProvider::CurrentPaintOpPreset)
{
}
QVariant KisCompositeOpResourceConverter::fromSource(const QVariant &value)
{
KisPaintOpPresetSP preset = value.value();
return preset ? preset->settings()->paintOpCompositeOp() : QVariant();
}
QVariant KisCompositeOpResourceConverter::toSource(const QVariant &value, const QVariant &sourceValue)
{
KisPaintOpPresetSP preset = sourceValue.value();
if (!preset) return sourceValue;
preset->settings()->setPaintOpCompositeOp(value.toString());
return QVariant::fromValue(preset);
}
/*********************************************************************/
/* KisEffectiveCompositeOpResourceConverter */
/*********************************************************************/
KisEffectiveCompositeOpResourceConverter::KisEffectiveCompositeOpResourceConverter()
: KoDerivedResourceConverter(KisCanvasResourceProvider::CurrentEffectiveCompositeOp,
KisCanvasResourceProvider::CurrentPaintOpPreset)
{
}
QVariant KisEffectiveCompositeOpResourceConverter::fromSource(const QVariant &value)
{
KisPaintOpPresetSP preset = value.value();
return preset ? preset->settings()->effectivePaintOpCompositeOp() : QVariant();
}
QVariant KisEffectiveCompositeOpResourceConverter::toSource(const QVariant &value, const QVariant &sourceValue)
{
Q_UNUSED(value);
// WARNING: we don't save that!
KisPaintOpPresetSP preset = sourceValue.value();
if (!preset) return sourceValue;
return QVariant::fromValue(preset);
}
/*********************************************************************/
/* KisOpacityResourceConverter */
/*********************************************************************/
KisOpacityResourceConverter::KisOpacityResourceConverter()
: KoDerivedResourceConverter(KisCanvasResourceProvider::Opacity,
KisCanvasResourceProvider::CurrentPaintOpPreset)
{
}
QVariant KisOpacityResourceConverter::fromSource(const QVariant &value)
{
KisPaintOpPresetSP preset = value.value();
return preset ? preset->settings()->paintOpOpacity() : QVariant(1.0);
}
QVariant KisOpacityResourceConverter::toSource(const QVariant &value, const QVariant &sourceValue)
{
KisPaintOpPresetSP preset = sourceValue.value();
if (!preset) return sourceValue;
preset->settings()->setPaintOpOpacity(value.toReal());
return QVariant::fromValue(preset);
}
/*********************************************************************/
/* KisFlowResourceConverter */
/*********************************************************************/
KisFlowResourceConverter::KisFlowResourceConverter()
: KoDerivedResourceConverter(KisCanvasResourceProvider::Flow,
KisCanvasResourceProvider::CurrentPaintOpPreset)
{
}
QVariant KisFlowResourceConverter::fromSource(const QVariant &value)
{
KisPaintOpPresetSP preset = value.value();
return preset ? preset->settings()->paintOpFlow() : QVariant();
}
QVariant KisFlowResourceConverter::toSource(const QVariant &value, const QVariant &sourceValue)
{
KisPaintOpPresetSP preset = sourceValue.value();
if (!preset) return sourceValue;
preset->settings()->setPaintOpFlow(value.toReal());
return QVariant::fromValue(preset);
}
/*********************************************************************/
/* KisSizeResourceConverter */
/*********************************************************************/
KisSizeResourceConverter::KisSizeResourceConverter()
: KoDerivedResourceConverter(KisCanvasResourceProvider::Size,
KisCanvasResourceProvider::CurrentPaintOpPreset)
{
}
QVariant KisSizeResourceConverter::fromSource(const QVariant &value)
{
KisPaintOpPresetSP preset = value.value();
return preset ? preset->settings()->paintOpSize() : QVariant();
}
QVariant KisSizeResourceConverter::toSource(const QVariant &value, const QVariant &sourceValue)
{
KisPaintOpPresetSP preset = sourceValue.value();
if (!preset) return sourceValue;
preset->settings()->setPaintOpSize(value.toReal());
return QVariant::fromValue(preset);
}
+///*********************************************************************/
+///* KisPatternSizeResourceConverter */
+///*********************************************************************/
+//
+KisPatternSizeResourceConverter::KisPatternSizeResourceConverter()
+ : KoDerivedResourceConverter(KisCanvasResourceProvider::Size,
+ KisCanvasResourceProvider::CurrentPaintOpPreset)
+{
+}
+
+QVariant KisPatternSizeResourceConverter::fromSource(const QVariant& value)
+{
+ KisPaintOpPresetSP preset = value.value();
+ return preset && preset->settings()->hasPatternSettings() ? preset->settings()->paintOpPatternSize() : QVariant::fromValue(1.0);
+}
+
+QVariant KisPatternSizeResourceConverter::toSource(const QVariant& value, const QVariant& sourceValue)
+{
+ KisPaintOpPresetSP preset = sourceValue.value();
+ if (!preset) return sourceValue;
+
+ if (preset->settings()->hasPatternSettings()) {
+ preset->settings()->setProperty("Texture/Pattern/Scale", value.toReal());
+ }
+
+ return QVariant::fromValue(preset);
+}
+
/*********************************************************************/
/* KisLodAvailabilityResourceConverter */
/*********************************************************************/
KisLodAvailabilityResourceConverter::KisLodAvailabilityResourceConverter()
: KoDerivedResourceConverter(KisCanvasResourceProvider::LodAvailability,
KisCanvasResourceProvider::CurrentPaintOpPreset)
{
}
QVariant KisLodAvailabilityResourceConverter::fromSource(const QVariant &value)
{
KisPaintOpPresetSP preset = value.value();
return preset ? KisPaintOpSettings::isLodUserAllowed(preset->settings()) : QVariant();
}
QVariant KisLodAvailabilityResourceConverter::toSource(const QVariant &value, const QVariant &sourceValue)
{
KisPaintOpPresetSP preset = sourceValue.value();
if (!preset) return sourceValue;
KisPaintOpSettings::setLodUserAllowed(preset->settings().data(), value.toBool());
return QVariant::fromValue(preset);
}
/*********************************************************************/
/* KisLodSizeThresholdResourceConverter */
/*********************************************************************/
KisLodSizeThresholdResourceConverter::KisLodSizeThresholdResourceConverter()
: KoDerivedResourceConverter(KisCanvasResourceProvider::LodSizeThreshold,
KisCanvasResourceProvider::CurrentPaintOpPreset)
{
}
QVariant KisLodSizeThresholdResourceConverter::fromSource(const QVariant &value)
{
KisPaintOpPresetSP preset = value.value();
return preset ? preset->settings()->lodSizeThreshold() : QVariant();
}
QVariant KisLodSizeThresholdResourceConverter::toSource(const QVariant &value, const QVariant &sourceValue)
{
KisPaintOpPresetSP preset = sourceValue.value();
if (!preset) return sourceValue;
preset->settings()->setLodSizeThreshold(value.toDouble());
return QVariant::fromValue(preset);
}
/*********************************************************************/
/* KisLodSizeThresholdSupportedResourceConverter */
/*********************************************************************/
KisLodSizeThresholdSupportedResourceConverter::KisLodSizeThresholdSupportedResourceConverter()
: KoDerivedResourceConverter(KisCanvasResourceProvider::LodSizeThresholdSupported,
KisCanvasResourceProvider::CurrentPaintOpPreset)
{
}
QVariant KisLodSizeThresholdSupportedResourceConverter::fromSource(const QVariant &value)
{
KisPaintOpPresetSP preset = value.value();
return preset ? preset->settings()->lodSizeThresholdSupported() : QVariant();
}
QVariant KisLodSizeThresholdSupportedResourceConverter::toSource(const QVariant &value, const QVariant &sourceValue)
{
// this property of the preset is immutable
Q_UNUSED(value);
return sourceValue;
}
/*********************************************************************/
/* KisEraserModeResourceConverter */
/*********************************************************************/
KisEraserModeResourceConverter::KisEraserModeResourceConverter()
: KoDerivedResourceConverter(KisCanvasResourceProvider::EraserMode,
KisCanvasResourceProvider::CurrentPaintOpPreset)
{
}
QVariant KisEraserModeResourceConverter::fromSource(const QVariant &value)
{
KisPaintOpPresetSP preset = value.value();
return preset ? preset->settings()->eraserMode() : QVariant();
}
QVariant KisEraserModeResourceConverter::toSource(const QVariant &value, const QVariant &sourceValue)
{
KisPaintOpPresetSP preset = sourceValue.value();
if (!preset) return sourceValue;
preset->settings()->setEraserMode(value.toBool());
return QVariant::fromValue(preset);
}
diff --git a/libs/ui/kis_derived_resources.h b/libs/ui/kis_derived_resources.h
index e3d113f74a..4031838ea8 100644
--- a/libs/ui/kis_derived_resources.h
+++ b/libs/ui/kis_derived_resources.h
@@ -1,125 +1,134 @@
/*
* Copyright (c) 2016 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_DERIVED_RESOURCES_H
#define __KIS_DERIVED_RESOURCES_H
#include "KoDerivedResourceConverter.h"
#include "KoResourceUpdateMediator.h"
#include
class KisPresetUpdateMediator : public KoResourceUpdateMediator
{
Q_OBJECT
public:
KisPresetUpdateMediator();
~KisPresetUpdateMediator() override;
void connectResource(QVariant sourceResource) override;
private Q_SLOTS:
void slotSettingsChanged();
private:
struct Private;
const QScopedPointer m_d;
};
class KisCompositeOpResourceConverter : public KoDerivedResourceConverter
{
public:
KisCompositeOpResourceConverter();
QVariant fromSource(const QVariant &value) override;
QVariant toSource(const QVariant &value, const QVariant &sourceValue) override;
};
class KisEffectiveCompositeOpResourceConverter : public KoDerivedResourceConverter
{
public:
KisEffectiveCompositeOpResourceConverter();
QVariant fromSource(const QVariant &value) override;
QVariant toSource(const QVariant &value, const QVariant &sourceValue) override;
};
class KisOpacityResourceConverter : public KoDerivedResourceConverter, public QObject
{
public:
KisOpacityResourceConverter();
QVariant fromSource(const QVariant &value) override;
QVariant toSource(const QVariant &value, const QVariant &sourceValue) override;
};
class KisFlowResourceConverter : public KoDerivedResourceConverter, public QObject
{
public:
KisFlowResourceConverter();
QVariant fromSource(const QVariant &value) override;
QVariant toSource(const QVariant &value, const QVariant &sourceValue) override;
};
class KisSizeResourceConverter : public KoDerivedResourceConverter, public QObject
{
public:
KisSizeResourceConverter();
QVariant fromSource(const QVariant &value) override;
QVariant toSource(const QVariant &value, const QVariant &sourceValue) override;
};
+class KisPatternSizeResourceConverter : public KoDerivedResourceConverter, public QObject
+{
+public:
+ KisPatternSizeResourceConverter();
+
+ QVariant fromSource(const QVariant& value) override;
+ QVariant toSource(const QVariant& value, const QVariant& sourceValue) override;
+};
+
class KisLodAvailabilityResourceConverter : public KoDerivedResourceConverter
{
public:
KisLodAvailabilityResourceConverter();
QVariant fromSource(const QVariant &value) override;
QVariant toSource(const QVariant &value, const QVariant &sourceValue) override;
};
class KisLodSizeThresholdResourceConverter : public KoDerivedResourceConverter
{
public:
KisLodSizeThresholdResourceConverter();
QVariant fromSource(const QVariant &value) override;
QVariant toSource(const QVariant &value, const QVariant &sourceValue) override;
};
class KisLodSizeThresholdSupportedResourceConverter : public KoDerivedResourceConverter
{
public:
KisLodSizeThresholdSupportedResourceConverter();
QVariant fromSource(const QVariant &value) override;
QVariant toSource(const QVariant &value, const QVariant &sourceValue) override;
};
class KisEraserModeResourceConverter : public KoDerivedResourceConverter
{
public:
KisEraserModeResourceConverter();
QVariant fromSource(const QVariant &value) override;
QVariant toSource(const QVariant &value, const QVariant &sourceValue) override;
};
#endif /* __KIS_DERIVED_RESOURCES_H */
diff --git a/libs/ui/kis_paintop_box.cc b/libs/ui/kis_paintop_box.cc
index 0b38df2885..d94dc04da7 100644
--- a/libs/ui/kis_paintop_box.cc
+++ b/libs/ui/kis_paintop_box.cc
@@ -1,1383 +1,1451 @@
/*
* kis_paintop_box.cc - part of KImageShop/Krayon/Krita
*
* Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
* Copyright (c) 2009-2011 Sven Langkamp (sven.langkamp@gmail.com)
* Copyright (c) 2010 Lukáš Tvrdý
* Copyright (C) 2011 Silvio Heinrich
* Copyright (C) 2011 Srikanth Tiyyagura
* Copyright (c) 2014 Mohit Goyal
*
* 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_paintop_box.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 "kis_canvas2.h"
#include "kis_node_manager.h"
#include "KisViewManager.h"
#include "kis_canvas_resource_provider.h"
#include "KisResourceServerProvider.h"
#include "kis_favorite_resource_manager.h"
#include "kis_config.h"
#include "kis_popup_button.h"
#include "widgets/kis_iconwidget.h"
#include "widgets/kis_tool_options_popup.h"
#include "widgets/kis_paintop_presets_popup.h"
#include "widgets/kis_paintop_presets_chooser_popup.h"
#include "widgets/kis_workspace_chooser.h"
#include "widgets/kis_paintop_list_widget.h"
#include "kis_slider_spin_box.h"
+#include "widgets/kis_multipliers_double_slider_spinbox.h"
#include "widgets/kis_cmb_composite.h"
#include "widgets/kis_widget_chooser.h"
#include "tool/kis_tool.h"
#include "kis_signals_blocker.h"
#include "kis_action_manager.h"
#include "KisHighlightedToolButton.h"
typedef KoResourceServerSimpleConstruction > KisPaintOpPresetResourceServer;
typedef KoResourceServerAdapter > KisPaintOpPresetResourceServerAdapter;
KisPaintopBox::KisPaintopBox(KisViewManager *view, QWidget *parent, const char *name)
: QWidget(parent)
, m_resourceProvider(view->canvasResourceProvider())
, m_optionWidget(0)
, m_toolOptionsPopupButton(0)
, m_brushEditorPopupButton(0)
, m_presetSelectorPopupButton(0)
, m_toolOptionsPopup(0)
, m_viewManager(view)
, m_previousNode(0)
, m_currTabletToolID(KoInputDevice::invalid())
, m_presetsEnabled(true)
, m_blockUpdate(false)
, m_dirtyPresetsEnabled(false)
, m_eraserBrushSizeEnabled(false)
, m_eraserBrushOpacityEnabled(false)
{
Q_ASSERT(view != 0);
setObjectName(name);
KisConfig cfg(true);
m_dirtyPresetsEnabled = cfg.useDirtyPresets();
m_eraserBrushSizeEnabled = cfg.useEraserBrushSize();
m_eraserBrushOpacityEnabled = cfg.useEraserBrushOpacity();
KAcceleratorManager::setNoAccel(this);
setWindowTitle(i18n("Painter's Toolchest"));
m_favoriteResourceManager = new KisFavoriteResourceManager(this);
KConfigGroup grp = KSharedConfig::openConfig()->group("krita").group("Toolbar BrushesAndStuff");
int iconsize = grp.readEntry("IconSize", 32);
if (!cfg.toolOptionsInDocker()) {
m_toolOptionsPopupButton = new KisPopupButton(this);
m_toolOptionsPopupButton->setIcon(KisIconUtils::loadIcon("configure"));
m_toolOptionsPopupButton->setToolTip(i18n("Tool Settings"));
m_toolOptionsPopupButton->setFixedSize(iconsize, iconsize);
}
m_brushEditorPopupButton = new KisIconWidget(this);
m_brushEditorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_02"));
m_brushEditorPopupButton->setToolTip(i18n("Edit brush settings"));
m_brushEditorPopupButton->setFixedSize(iconsize, iconsize);
m_presetSelectorPopupButton = new KisPopupButton(this);
m_presetSelectorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_01"));
m_presetSelectorPopupButton->setToolTip(i18n("Choose brush preset"));
m_presetSelectorPopupButton->setFixedSize(iconsize, iconsize);
m_eraseModeButton = new KisHighlightedToolButton(this);
m_eraseModeButton->setFixedSize(iconsize, iconsize);
m_eraseModeButton->setCheckable(true);
m_eraseAction = m_viewManager->actionManager()->createAction("erase_action");
m_eraseModeButton->setDefaultAction(m_eraseAction);
m_reloadButton = new QToolButton(this);
m_reloadButton->setFixedSize(iconsize, iconsize);
m_reloadAction = m_viewManager->actionManager()->createAction("reload_preset_action");
m_reloadButton->setDefaultAction(m_reloadAction);
m_alphaLockButton = new KisHighlightedToolButton(this);
m_alphaLockButton->setFixedSize(iconsize, iconsize);
m_alphaLockButton->setCheckable(true);
KisAction* alphaLockAction = m_viewManager->actionManager()->createAction("preserve_alpha");
m_alphaLockButton->setDefaultAction(alphaLockAction);
// horizontal and vertical mirror toolbar buttons
// mirror tool options for the X Mirror
QMenu *toolbarMenuXMirror = new QMenu();
hideCanvasDecorationsX = m_viewManager->actionManager()->createAction("mirrorX-hideDecorations");
toolbarMenuXMirror->addAction(hideCanvasDecorationsX);
lockActionX = m_viewManager->actionManager()->createAction("mirrorX-lock");
toolbarMenuXMirror->addAction(lockActionX);
moveToCenterActionX = m_viewManager->actionManager()->createAction("mirrorX-moveToCenter");
toolbarMenuXMirror->addAction(moveToCenterActionX);
// mirror tool options for the Y Mirror
QMenu *toolbarMenuYMirror = new QMenu();
hideCanvasDecorationsY = m_viewManager->actionManager()->createAction("mirrorY-hideDecorations");
toolbarMenuYMirror->addAction(hideCanvasDecorationsY);
lockActionY = m_viewManager->actionManager()->createAction("mirrorY-lock");
toolbarMenuYMirror->addAction(lockActionY);
moveToCenterActionY = m_viewManager->actionManager()->createAction("mirrorY-moveToCenter");
toolbarMenuYMirror->addAction(moveToCenterActionY);
// create horizontal and vertical mirror buttons
m_hMirrorButton = new KisHighlightedToolButton(this);
int menuPadding = 10;
m_hMirrorButton->setFixedSize(iconsize + menuPadding, iconsize);
m_hMirrorButton->setCheckable(true);
m_hMirrorAction = m_viewManager->actionManager()->createAction("hmirror_action");
m_hMirrorButton->setDefaultAction(m_hMirrorAction);
m_hMirrorButton->setMenu(toolbarMenuXMirror);
m_hMirrorButton->setPopupMode(QToolButton::MenuButtonPopup);
m_vMirrorButton = new KisHighlightedToolButton(this);
m_vMirrorButton->setFixedSize(iconsize + menuPadding, iconsize);
m_vMirrorButton->setCheckable(true);
m_vMirrorAction = m_viewManager->actionManager()->createAction("vmirror_action");
m_vMirrorButton->setDefaultAction(m_vMirrorAction);
m_vMirrorButton->setMenu(toolbarMenuYMirror);
m_vMirrorButton->setPopupMode(QToolButton::MenuButtonPopup);
// add connections for horizontal and mirrror buttons
connect(lockActionX, SIGNAL(toggled(bool)), this, SLOT(slotLockXMirrorToggle(bool)));
connect(lockActionY, SIGNAL(toggled(bool)), this, SLOT(slotLockYMirrorToggle(bool)));
connect(moveToCenterActionX, SIGNAL(triggered(bool)), this, SLOT(slotMoveToCenterMirrorX()));
connect(moveToCenterActionY, SIGNAL(triggered(bool)), this, SLOT(slotMoveToCenterMirrorY()));
connect(hideCanvasDecorationsX, SIGNAL(toggled(bool)), this, SLOT(slotHideDecorationMirrorX(bool)));
connect(hideCanvasDecorationsY, SIGNAL(toggled(bool)), this, SLOT(slotHideDecorationMirrorY(bool)));
const bool sliderLabels = cfg.sliderLabels();
int sliderWidth;
if (sliderLabels) {
sliderWidth = 150 * logicalDpiX() / 96;
}
else {
sliderWidth = 120 * logicalDpiX() / 96;
}
- for (int i = 0; i < 3; ++i) {
+ for (int i = 0; i < 4; ++i) {
m_sliderChooser[i] = new KisWidgetChooser(i + 1);
KisDoubleSliderSpinBox* slOpacity;
KisDoubleSliderSpinBox* slFlow;
KisDoubleSliderSpinBox* slSize;
+ KisMultipliersDoubleSliderSpinBox* slPatternSize;
if (sliderLabels) {
- slOpacity = m_sliderChooser[i]->addWidget("opacity");
- slFlow = m_sliderChooser[i]->addWidget("flow");
- slSize = m_sliderChooser[i]->addWidget("size");
+ slOpacity = m_sliderChooser[i]->addWidget("opacity");
+ slFlow = m_sliderChooser[i]->addWidget("flow");
+ slSize = m_sliderChooser[i]->addWidget("size");
+ slPatternSize = m_sliderChooser[i]->addWidget("patternsize");
slOpacity->setPrefix(QString("%1 ").arg(i18n("Opacity:")));
slFlow->setPrefix(QString("%1 ").arg(i18n("Flow:")));
slSize->setPrefix(QString("%1 ").arg(i18n("Size:")));
+ slPatternSize->setPrefix(QString("%1 ").arg(i18n("Pattern Scale:")));
}
else {
slOpacity = m_sliderChooser[i]->addWidget("opacity", i18n("Opacity:"));
slFlow = m_sliderChooser[i]->addWidget("flow", i18n("Flow:"));
slSize = m_sliderChooser[i]->addWidget("size", i18n("Size:"));
+ slPatternSize = m_sliderChooser[i]->addWidget("patternsize", i18n("Pattern Scale:"));
}
slOpacity->setRange(0, 100, 0);
slOpacity->setValue(100);
slOpacity->setSingleStep(5);
slOpacity->setSuffix(i18n("%"));
slOpacity->setMinimumWidth(qMax(sliderWidth, slOpacity->sizeHint().width()));
slOpacity->setFixedHeight(iconsize);
slOpacity->setBlockUpdateSignalOnDrag(true);
slFlow->setRange(0, 100, 0);
slFlow->setValue(100);
slFlow->setSingleStep(5);
slFlow->setSuffix(i18n("%"));
slFlow->setMinimumWidth(qMax(sliderWidth, slFlow->sizeHint().width()));
slFlow->setFixedHeight(iconsize);
slFlow->setBlockUpdateSignalOnDrag(true);
slSize->setRange(0.01, cfg.readEntry("maximumBrushSize", 1000), 2);
slSize->setValue(100);
slSize->setSingleStep(1);
slSize->setExponentRatio(3.0);
slSize->setSuffix(i18n(" px"));
slSize->setMinimumWidth(qMax(sliderWidth, slSize->sizeHint().width()));
slSize->setFixedHeight(iconsize);
slSize->setBlockUpdateSignalOnDrag(true);
+ slPatternSize->setRange(0.0, 2.0, 2);
+ slPatternSize->setValue(1.0);
+ slPatternSize->addMultiplier(0.1);
+ slPatternSize->addMultiplier(2);
+ slPatternSize->addMultiplier(10);
+
+ slPatternSize->setSingleStep(.01);
+ slPatternSize->setSuffix(i18n("x"));
+ slPatternSize->setMinimumWidth(qMax(sliderWidth, slPatternSize->sizeHint().width()));
+ slPatternSize->setFixedHeight(iconsize);
+ slPatternSize->setBlockUpdateSignalOnDrag(true);
+
+ m_sliderChooser[i]->setMinimumWidth(qMax(sliderWidth, slPatternSize->sizeHint().width()));
+
m_sliderChooser[i]->chooseWidget(cfg.toolbarSlider(i + 1));
}
m_cmbCompositeOp = new KisCompositeOpComboBox();
m_cmbCompositeOp->setFixedHeight(iconsize);
Q_FOREACH (KisAction * a, m_cmbCompositeOp->createBlendmodeActions()) {
m_viewManager->actionManager()->addAction(a->text(), a);
}
m_workspaceWidget = new KisPopupButton(this);
m_workspaceWidget->setIcon(KisIconUtils::loadIcon("view-choose"));
m_workspaceWidget->setToolTip(i18n("Choose workspace"));
m_workspaceWidget->setFixedSize(iconsize, iconsize);
m_workspaceWidget->setPopupWidget(new KisWorkspaceChooser(view));
QHBoxLayout* baseLayout = new QHBoxLayout(this);
m_paintopWidget = new QWidget(this);
baseLayout->addWidget(m_paintopWidget);
baseLayout->setSpacing(4);
baseLayout->setContentsMargins(0, 0, 0, 0);
m_layout = new QHBoxLayout(m_paintopWidget);
if (!cfg.toolOptionsInDocker()) {
m_layout->addWidget(m_toolOptionsPopupButton);
}
m_layout->addWidget(m_brushEditorPopupButton);
m_layout->addWidget(m_presetSelectorPopupButton);
m_layout->setSpacing(4);
m_layout->setContentsMargins(0, 0, 0, 0);
QWidget* compositeActions = new QWidget(this);
QHBoxLayout* compositeLayout = new QHBoxLayout(compositeActions);
compositeLayout->addWidget(m_cmbCompositeOp);
compositeLayout->addWidget(m_eraseModeButton);
compositeLayout->addWidget(m_alphaLockButton);
compositeLayout->setSpacing(4);
compositeLayout->setContentsMargins(0, 0, 0, 0);
compositeLayout->addWidget(m_reloadButton);
QWidgetAction * action;
action = new QWidgetAction(this);
view->actionCollection()->addAction("composite_actions", action);
action->setText(i18n("Brush composite"));
action->setDefaultWidget(compositeActions);
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("brushslider1", action);
view->actionCollection()->addAction("brushslider1", action);
action->setDefaultWidget(m_sliderChooser[0]);
connect(action, SIGNAL(triggered()), m_sliderChooser[0], SLOT(showPopupWidget()));
connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[0], SLOT(updateThemedIcons()));
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("brushslider2", action);
view->actionCollection()->addAction("brushslider2", action);
action->setDefaultWidget(m_sliderChooser[1]);
connect(action, SIGNAL(triggered()), m_sliderChooser[1], SLOT(showPopupWidget()));
connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[1], SLOT(updateThemedIcons()));
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("brushslider3", action);
view->actionCollection()->addAction("brushslider3", action);
action->setDefaultWidget(m_sliderChooser[2]);
connect(action, SIGNAL(triggered()), m_sliderChooser[2], SLOT(showPopupWidget()));
- connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[2], SLOT(updateThemedIcons()));
+ connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[2], SLOT(updateThemedIcons()));
+
+ action = new QWidgetAction(this);
+ KisActionRegistry::instance()->propertizeAction("brushslider4", action);
+ view->actionCollection()->addAction("brushslider4", action);
+ action->setDefaultWidget(m_sliderChooser[3]);
+ connect(action, SIGNAL(triggered()), m_sliderChooser[3], SLOT(showPopupWidget()));
+ connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_sliderChooser[3], SLOT(updateThemedIcons()));
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("next_favorite_preset", action);
view->actionCollection()->addAction("next_favorite_preset", action);
connect(action, SIGNAL(triggered()), this, SLOT(slotNextFavoritePreset()));
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("previous_favorite_preset", action);
view->actionCollection()->addAction("previous_favorite_preset", action);
connect(action, SIGNAL(triggered()), this, SLOT(slotPreviousFavoritePreset()));
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("previous_preset", action);
view->actionCollection()->addAction("previous_preset", action);
connect(action, SIGNAL(triggered()), this, SLOT(slotSwitchToPreviousPreset()));
if (!cfg.toolOptionsInDocker()) {
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("show_tool_options", action);
view->actionCollection()->addAction("show_tool_options", action);
connect(action, SIGNAL(triggered()), m_toolOptionsPopupButton, SLOT(showPopupWidget()));
}
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("show_brush_editor", action);
view->actionCollection()->addAction("show_brush_editor", action);
connect(action, SIGNAL(triggered()), m_brushEditorPopupButton, SLOT(showPopupWidget()));
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("show_brush_presets", action);
view->actionCollection()->addAction("show_brush_presets", action);
connect(action, SIGNAL(triggered()), m_presetSelectorPopupButton, SLOT(showPopupWidget()));
QWidget* mirrorActions = new QWidget(this);
QHBoxLayout* mirrorLayout = new QHBoxLayout(mirrorActions);
mirrorLayout->addWidget(m_hMirrorButton);
mirrorLayout->addWidget(m_vMirrorButton);
mirrorLayout->setSpacing(4);
mirrorLayout->setContentsMargins(0, 0, 0, 0);
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("mirror_actions", action);
action->setDefaultWidget(mirrorActions);
view->actionCollection()->addAction("mirror_actions", action);
action = new QWidgetAction(this);
KisActionRegistry::instance()->propertizeAction("workspaces", action);
view->actionCollection()->addAction("workspaces", action);
action->setDefaultWidget(m_workspaceWidget);
if (!cfg.toolOptionsInDocker()) {
m_toolOptionsPopup = new KisToolOptionsPopup();
m_toolOptionsPopupButton->setPopupWidget(m_toolOptionsPopup);
m_toolOptionsPopup->switchDetached(false);
}
m_savePresetWidget = new KisPresetSaveWidget(this);
m_presetsPopup = new KisPaintOpPresetsPopup(m_resourceProvider, m_favoriteResourceManager, m_savePresetWidget);
m_brushEditorPopupButton->setPopupWidget(m_presetsPopup);
m_presetsPopup->parentWidget()->setWindowTitle(i18n("Brush Editor"));
connect(m_presetsPopup, SIGNAL(brushEditorShown()), SLOT(slotUpdateOptionsWidgetPopup()));
connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), m_presetsPopup, SLOT(updateThemedIcons()));
m_presetsChooserPopup = new KisPaintOpPresetsChooserPopup();
m_presetsChooserPopup->setMinimumHeight(550);
m_presetsChooserPopup->setMinimumWidth(450);
m_presetSelectorPopupButton->setPopupWidget(m_presetsChooserPopup);
m_currCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id();
slotNodeChanged(view->activeNode());
// Get all the paintops
QList keys = KisPaintOpRegistry::instance()->keys();
QList factoryList;
Q_FOREACH (const QString & paintopId, keys) {
factoryList.append(KisPaintOpRegistry::instance()->get(paintopId));
}
m_presetsPopup->setPaintOpList(factoryList);
connect(m_presetsPopup , SIGNAL(paintopActivated(QString)) , SLOT(slotSetPaintop(QString)));
connect(m_presetsPopup , SIGNAL(defaultPresetClicked()) , SLOT(slotSetupDefaultPreset()));
connect(m_presetsPopup , SIGNAL(signalResourceSelected(KoResource*)), SLOT(resourceSelected(KoResource*)));
connect(m_presetsPopup , SIGNAL(reloadPresetClicked()) , SLOT(slotReloadPreset()));
connect(m_presetsPopup , SIGNAL(dirtyPresetToggled(bool)) , SLOT(slotDirtyPresetToggled(bool)));
connect(m_presetsPopup , SIGNAL(eraserBrushSizeToggled(bool)) , SLOT(slotEraserBrushSizeToggled(bool)));
connect(m_presetsPopup , SIGNAL(eraserBrushOpacityToggled(bool)) , SLOT(slotEraserBrushOpacityToggled(bool)));
connect(m_presetsPopup, SIGNAL(createPresetFromScratch(QString)), this, SLOT(slotCreatePresetFromScratch(QString)));
connect(m_presetsChooserPopup, SIGNAL(resourceSelected(KoResource*)) , SLOT(resourceSelected(KoResource*)));
connect(m_presetsChooserPopup, SIGNAL(resourceClicked(KoResource*)) , SLOT(resourceSelected(KoResource*)));
connect(m_resourceProvider , SIGNAL(sigNodeChanged(KisNodeSP)) , SLOT(slotNodeChanged(KisNodeSP)));
connect(m_cmbCompositeOp , SIGNAL(currentIndexChanged(int)) , SLOT(slotSetCompositeMode(int)));
connect(m_eraseAction , SIGNAL(toggled(bool)) , SLOT(slotToggleEraseMode(bool)));
connect(alphaLockAction , SIGNAL(toggled(bool)) , SLOT(slotToggleAlphaLockMode(bool)));
m_disablePressureAction = m_viewManager->actionManager()->createAction("disable_pressure");
connect(m_disablePressureAction , SIGNAL(toggled(bool)) , SLOT(slotDisablePressureMode(bool)));
m_disablePressureAction->setChecked(true);
connect(m_hMirrorAction , SIGNAL(toggled(bool)) , SLOT(slotHorizontalMirrorChanged(bool)));
connect(m_vMirrorAction , SIGNAL(toggled(bool)) , SLOT(slotVerticalMirrorChanged(bool)));
connect(m_reloadAction , SIGNAL(triggered()) , SLOT(slotReloadPreset()));
- connect(m_sliderChooser[0]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed()));
- connect(m_sliderChooser[0]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed()));
- connect(m_sliderChooser[0]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed()));
- connect(m_sliderChooser[1]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed()));
- connect(m_sliderChooser[1]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed()));
- connect(m_sliderChooser[1]->getWidget