diff --git a/config-oiio.h.cmake b/config-oiio.h.cmake
deleted file mode 100644
index ac4ea698e7..0000000000
--- a/config-oiio.h.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-/* config-ocio.h. Generated by cmake from config-ocio.h.cmake */
-
-/* Define if you have ocio, the OpenColorIO Library */
-#cmakedefine HAVE_OCIO 1
-
-
-
diff --git a/krita/data/symbols/CMakeLists.txt b/krita/data/symbols/CMakeLists.txt
index 483d7399e5..889d695435 100644
--- a/krita/data/symbols/CMakeLists.txt
+++ b/krita/data/symbols/CMakeLists.txt
@@ -1,6 +1,7 @@
install( FILES
BalloonSymbols.svg
pepper_carrot_speech_bubbles.svg
+ preset_icons.svg
DESTINATION ${DATA_INSTALL_DIR}/krita/symbols)
diff --git a/krita/data/symbols/preset_icons.svg b/krita/data/symbols/preset_icons.svg
new file mode 100644
index 0000000000..1c29478ddb
--- /dev/null
+++ b/krita/data/symbols/preset_icons.svg
@@ -0,0 +1,2281 @@
+
+
diff --git a/krita/data/templates/animation/.directory b/krita/data/templates/animation/.directory
index 41c05f1fe8..2a56c5142c 100644
--- a/krita/data/templates/animation/.directory
+++ b/krita/data/templates/animation/.directory
@@ -1,19 +1,20 @@
[Desktop Entry]
Name=Animation Templates
Name[ca]=Plantilles d'animació
Name[ca@valencia]=Plantilles d'animació
Name[cs]=Šablony animací:
Name[de]=Animations-Vorlagen
Name[en_GB]=Animation Templates
Name[es]=Plantillas de animación
Name[gl]=Modelos de animación
Name[it]=Modelli di animazioni
Name[nl]=Animatiesjablonen
Name[pl]=Szablony animacji
Name[pt]=Modelos de Animações
Name[pt_BR]=Modelos de animação
Name[sv]=Animeringsmallar
Name[tr]=Canlandırma Şablonları
Name[uk]=Шаблони анімацій
Name[x-test]=xxAnimation Templatesxx
+Name[zh_CN]=动画模板
X-KDE-DefaultTab=true
diff --git a/krita/krita.action b/krita/krita.action
index 86690ca6eb..d105555fd8 100644
--- a/krita/krita.action
+++ b/krita/krita.action
@@ -1,3114 +1,3114 @@
General
Open Resources Folder
Opens a file browser at the location Krita saves resources such as brushes to.
Opens a file browser at the location Krita saves resources such as brushes to.
Open Resources Folder
0
0
false
Cleanup removed files...
Cleanup removed files
Cleanup removed files
0
0
false
C&ascade
Cascade
Cascade
10
0
false
&Tile
Tile
Tile
10
0
false
Create Resource Bundle...
Create Resource Bundle
Create Resource Bundle
0
0
false
Show File Toolbar
Show File Toolbar
Show File Toolbar
false
Show color selector
Show color selector
Show color selector
Shift+I
false
Show MyPaint shade selector
Show MyPaint shade selector
Show MyPaint shade selector
Shift+M
false
Show minimal shade selector
Show minimal shade selector
Show minimal shade selector
Shift+N
false
Show color history
Show color history
Show color history
H
false
Show common colors
Show common colors
Show common colors
U
false
Show Tool Options
Show Tool Options
Show Tool Options
\
false
Show Brush Editor
Show Brush Editor
Show Brush Editor
F5
false
Show Brush Presets
Show Brush Presets
Show Brush Presets
F6
false
Toggle Tablet Debugger
Toggle Tablet Debugger
Toggle Tablet Debugger
0
0
Ctrl+Shift+T
false
Show system information for bug reports.
Show system information for bug reports.
Show system information for bug reports.
- /
+
false
Rename Composition...
Rename Composition
Rename Composition
0
0
false
Update Composition
Update Composition
Update Composition
0
0
false
Painting
Make brush color lighter
Make brush color lighter
Make brush color lighter
0
0
L
false
Make brush color darker
Make brush color darker
Make brush color darker
0
0
K
false
Make brush color more saturated
Make brush color more saturated
Make brush color more saturated
false
Make brush color more desaturated
Make brush color more desaturated
Make brush color more desaturated
false
Shift brush color hue clockwise
Shift brush color hue clockwise
Shift brush color hue clockwise
false
Shift brush color hue counter-clockwise
Shift brush color hue counter-clockwise
Shift brush color hue counter-clockwise
false
Make brush color more red
Make brush color more red
Make brush color more red
false
Make brush color more green
Make brush color more green
Make brush color more green
false
Make brush color more blue
Make brush color more blue
Make brush color more blue
false
Make brush color more yellow
Make brush color more yellow
Make brush color more yellow
false
Increase opacity
Increase opacity
Increase opacity
0
0
O
false
Decrease opacity
Decrease opacity
Decrease opacity
0
0
I
false
draw-eraser
Set eraser mode
Set eraser mode
Set eraser mode
10000
0
E
true
view-refresh
Reload Original Preset
Reload Original Preset
Reload Original Preset
10000
false
transparency-unlocked
Preserve Alpha
Preserve Alpha
Preserve Alpha
10000
true
transform_icons_penPressure
Use Pen Pressure
Use Pen Pressure
Use Pen Pressure
10000
true
symmetry-horizontal
Horizontal Mirror Tool
Horizontal Mirror Tool
Horizontal Mirror Tool
10000
true
symmetry-vertical
Vertical Mirror Tool
Vertical Mirror Tool
Vertical Mirror Tool
10000
true
Hide Mirror X Line
Hide Mirror X Line
Hide Mirror X Line
10000
true
Hide Mirror Y Line
Hide Mirror Y Line
Hide Mirror Y Line
10000
true
Lock
Lock X Line
Lock X Line
10000
true
Lock Y Line
Lock Y Line
Lock Y Line
10000
true
Move to Canvas Center
Move to Canvas Center X
Move to Canvas Center X
10000
false
Move to Canvas Center Y
Move to Canvas Center Y
Move to Canvas Center Y
10000
false
&Invert Selection
Invert current selection
Invert Selection
10000000000
100
Ctrl+Shift+I
false
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
&Toggle Selection Display Mode
Toggle Selection Display Mode
Toggle Selection Display Mode
0
0
false
Next Favourite Preset
Next Favourite Preset
Next Favourite Preset
,
false
Previous Favourite Preset
Previous Favourite Preset
Previous Favourite Preset
.
false
preset-switcher
Switch to Previous Preset
Switch to Previous Preset
Switch to Previous Preset
/
false
Hide Brushes and Stuff Toolbar
Hide Brushes and Stuff Toolbar
Hide Brushes and Stuff Toolbar
true
Reset Foreground and Background Color
Reset Foreground and Background Color
Reset Foreground and Background Color
D
false
Swap Foreground and Background Color
Swap Foreground and Background Color
Swap Foreground and Background Color
X
false
smoothing-weighted
Brush Smoothing: Weighted
Brush Smoothing: Weighted
Brush Smoothing: Weighted
false
smoothing-no
Brush Smoothing: Disabled
Brush Smoothing: Disabled
Brush Smoothing: Disabled
false
smoothing-stabilizer
Brush Smoothing: Stabilizer
Brush Smoothing: Stabilizer
Brush Smoothing: Stabilizer
false
Decrease Brush Size
Decrease Brush Size
Decrease Brush Size
0
0
[
false
smoothing-basic
Brush Smoothing: Basic
Brush Smoothing: Basic
Brush Smoothing: Basic
false
Increase Brush Size
Increase Brush Size
Increase Brush Size
0
0
]
false
Toggle Assistant
Toggle Assistant
ToggleAssistant
Ctrl+Shift+L
true
Undo Polygon Selection Points
Undo Polygon Selection Points
Undo Polygon Selection Points
Shift+Z
false
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
Convert &to Shape
Convert to Shape
Convert to Shape
10000000000
0
false
&Select Opaque
Select Opaque
Select Opaque
100000
100
false
&Show Global Selection Mask
Shows global selection as a usual selection mask in <interface>Layers</interface> docker
Show Global Selection Mask
100000
100
true
Filters
color-to-alpha
&Color to Alpha...
Color to Alpha
Color to Alpha
10000
0
false
&Top Edge Detection
Top Edge Detection
Top Edge Detection
10000
0
false
&Index Colors...
Index Colors
Index Colors
10000
0
false
Emboss Horizontal &Only
Emboss Horizontal Only
Emboss Horizontal Only
10000
0
false
D&odge
Dodge
Dodge
10000
0
false
&Sharpen
Sharpen
Sharpen
10000
0
false
B&urn
Burn
Burn
10000
0
false
&Mean Removal
Mean Removal
Mean Removal
10000
0
false
&Gaussian Blur...
Gaussian Blur
Gaussian Blur
10000
0
false
Emboss &in All Directions
Emboss in All Directions
Emboss in All Directions
10000
0
false
&Small Tiles...
Small Tiles
Small Tiles
10000
0
false
&Levels...
Levels
Levels
10000
0
Ctrl+L
false
&Sobel...
Sobel
Sobel
10000
0
false
&Wave...
Wave
Wave
10000
0
false
&Motion Blur...
Motion Blur
Motion Blur
10000
0
false
&Color Adjustment curves...
Color Adjustment curves
Color Adjustment curves
10000
0
Ctrl+M
false
Pi&xelize...
Pixelize
Pixelize
10000
0
false
Emboss (&Laplacian)
Emboss (Laplacian)
Emboss (Laplacian)
10000
0
false
&Left Edge Detection
Left Edge Detection
Left Edge Detection
10000
0
false
&Blur...
Blur
Blur
10000
0
false
&Raindrops...
Raindrops
Raindrops
10000
0
false
&Bottom Edge Detection
Bottom Edge Detection
Bottom Edge Detection
10000
0
false
&Random Noise...
Random Noise
Random Noise
10000
0
false
&Brightness/Contrast curve...
Brightness/Contrast curve
Brightness/Contrast curve
10000
0
false
Colo&r Balance..
Color Balance..
Color Balance..
10000
0
Ctrl+B
false
&Phong Bumpmap...
Phong Bumpmap
Phong Bumpmap
10000
0
false
&Desaturate
Desaturate
Desaturate
10000
0
Ctrl+Shift+U
false
Color &Transfer...
Color Transfer
Color Transfer
10000
0
false
Emboss &Vertical Only
Emboss Vertical Only
Emboss Vertical Only
10000
0
false
&Lens Blur...
Lens Blur
Lens Blur
10000
0
false
M&inimize Channel
Minimize Channel
Minimize Channel
10000
0
false
M&aximize Channel
Maximize Channel
Maximize Channel
10000
0
false
&Oilpaint...
Oilpaint
Oilpaint
10000
0
false
&Right Edge Detection
Right Edge Detection
Right Edge Detection
10000
0
false
&Auto Contrast
Auto Contrast
Auto Contrast
10000
0
false
&Round Corners...
Round Corners
Round Corners
10000
0
false
&Unsharp Mask...
Unsharp Mask
Unsharp Mask
10000
0
false
&Emboss with Variable Depth...
Emboss with Variable Depth
Emboss with Variable Depth
10000
0
false
Emboss &Horizontal && Vertical
Emboss Horizontal & Vertical
Emboss Horizontal & Vertical
10000
0
false
Random &Pick...
Random Pick
Random Pick
10000
0
false
&Gaussian Noise Reduction...
Gaussian Noise Reduction
Gaussian Noise Reduction
10000
0
false
&Posterize...
Posterize
Posterize
10000
0
false
&Wavelet Noise Reducer...
Wavelet Noise Reducer
Wavelet Noise Reducer
10000
0
false
&HSV Adjustment...
HSV Adjustment
HSV Adjustment
10000
0
Ctrl+U
false
Tool Shortcuts
Dynamic Brush Tool
Dynamic Brush Tool
Dynamic Brush Tool
false
Crop Tool
Crop the image to an area
Crop the image to an area
C
false
Polygon Tool
Polygon Tool. Shift-mouseclick ends the polygon.
Polygon Tool. Shift-mouseclick ends the polygon.
false
References
References
References
false
Rectangle Tool
Rectangle Tool
Rectangle Tool
false
Multibrush Tool
Multibrush Tool
Multibrush Tool
Q
false
Lazy Brush Tool
Lazy Brush Tool
Lazy Brush Tool
Smart Patch Tool
Smart Patch Tool
Smart Patch Tool
Pan Tool
Pan Tool
Pan Tool
Shape Manipulation Tool
Shape Manipulation Tool
Shape Manipulation Tool
false
Color Picker
Select a color from the image or current layer
Select a color from the image or current layer
P
false
Text Editing Tool
Text editing
Text editing
false
Outline Selection Tool
Outline Selection Tool
Outline Selection Tool
false
Artistic Text Tool
Artistic text editing
Artistic text editing
false
Bezier Curve Selection Tool
Select a
Bezier Curve Selection Tool
false
Similar Color Selection Tool
Select a
Similar Color Selection Tool
false
Fill Tool
Fill a contiguous area of color with a color, or fill a selection.
Fill a contiguous area of color with a color, or fill a selection.
F
false
Line Tool
Line Tool
Line Tool
false
Freehand Path Tool
Freehand Path Tool
Freehand Path Tool
false
Bezier Curve Tool
Bezier Curve Tool. Shift-mouseclick ends the curve.
Bezier Curve Tool. Shift-mouseclick ends the curve.
false
Ellipse Tool
Ellipse Tool
Ellipse Tool
false
Freehand Brush Tool
Freehand Brush Tool
Freehand Brush Tool
B
false
Create object
Create object
Create object
false
Elliptical Selection Tool
Elliptical Selection Tool
Elliptical Selection Tool
J
false
Contiguous Selection Tool
Contiguous Selection Tool
Contiguous Selection Tool
false
Pattern editing
Pattern editing
Pattern editing
false
Review
Review
Review
false
Draw a gradient.
Draw a gradient.
Draw a gradient.
G
false
Polygonal Selection Tool
Polygonal Selection Tool
Polygonal Selection Tool
false
Measurement Tool
Measure the distance between two points
Measure the distance between two points
false
Rectangular Selection Tool
Rectangular Selection Tool
Rectangular Selection Tool
Ctrl+R
false
Move Tool
Move a layer
Move a layer
T
false
Vector Image Tool
Vector Image (EMF/WMF/SVM/SVG) tool
Vector Image (EMF/WMF/SVM/SVG) tool
false
Calligraphy
Calligraphy
Calligraphy
false
Path editing
Path editing
Path editing
false
Zoom Tool
Zoom Tool
Zoom Tool
false
Polyline Tool
Polyline Tool. Shift-mouseclick ends the polyline.
Polyline Tool. Shift-mouseclick ends the polyline.
false
Transform Tool
Transform a layer or a selection
Transform a layer or a selection
Ctrl+T
false
Ruler assistant editor tool
Ruler assistant editor tool
Ruler assistant editor tool
false
Text tool
Text tool
Text tool
false
Gradient Editing Tool
Gradient editing
Gradient editing
false
Blending Modes
Select Normal Blending Mode
Select Normal Blending Mode
Select Normal Blending Mode
0
0
Alt+Shift+N
false
Select Dissolve Blending Mode
Select Dissolve Blending Mode
Select Dissolve Blending Mode
0
0
Alt+Shift+I
false
Select Behind Blending Mode
Select Behind Blending Mode
Select Behind Blending Mode
0
0
Alt+Shift+Q
false
Select Clear Blending Mode
Select Clear Blending Mode
Select Clear Blending Mode
0
0
Alt+Shift+R
false
Select Darken Blending Mode
Select Darken Blending Mode
Select Darken Blending Mode
0
0
Alt+Shift+K
false
Select Multiply Blending Mode
Select Multiply Blending Mode
Select Multiply Blending Mode
0
0
Alt+Shift+M
false
Select Color Burn Blending Mode
Select Color Burn Blending Mode
Select Color Burn Blending Mode
0
0
Alt+Shift+B
false
Select Linear Burn Blending Mode
Select Linear Burn Blending Mode
Select Linear Burn Blending Mode
0
0
Alt+Shift+A
false
Select Lighten Blending Mode
Select Lighten Blending Mode
Select Lighten Blending Mode
0
0
Alt+Shift+G
false
Select Screen Blending Mode
Select Screen Blending Mode
Select Screen Blending Mode
0
0
Alt+Shift+S
false
Select Color Dodge Blending Mode
Select Color Dodge Blending Mode
Select Color Dodge Blending Mode
0
0
Alt+Shift+D
false
Select Linear Dodge Blending Mode
Select Linear Dodge Blending Mode
Select Linear Dodge Blending Mode
0
0
Alt+Shift+W
false
Select Overlay Blending Mode
Select Overlay Blending Mode
Select Overlay Blending Mode
0
0
Alt+Shift+O
false
Select Hard Overlay Blending Mode
Select Hard Overlay Blending Mode
Select Hard Overlay Blending Mode
0
0
Alt+Shift+P
false
Select Soft Light Blending Mode
Select Soft Light Blending Mode
Select Soft Light Blending Mode
0
0
Alt+Shift+F
false
Select Hard Light Blending Mode
Select Hard Light Blending Mode
Select Hard Light Blending Mode
0
0
Alt+Shift+H
false
Select Vivid Light Blending Mode
Select Vivid Light Blending Mode
Select Vivid Light Blending Mode
0
0
Alt+Shift+V
false
Select Linear Light Blending Mode
Select Linear Light Blending Mode
Select Linear Light Blending Mode
0
0
Alt+Shift+J
false
Select Pin Light Blending Mode
Select Pin Light Blending Mode
Select Pin Light Blending Mode
0
0
Alt+Shift+Z
false
Select Hard Mix Blending Mode
Select Hard Mix Blending Mode
Select Hard Mix Blending Mode
0
0
Alt+Shift+L
false
Select Difference Blending Mode
Select Difference Blending Mode
Select Difference Blending Mode
0
0
Alt+Shift+E
false
Select Exclusion Blending Mode
Select Exclusion Blending Mode
Select Exclusion Blending Mode
0
0
Alt+Shift+X
false
Select Hue Blending Mode
Select Hue Blending Mode
Select Hue Blending Mode
0
0
Alt+Shift+U
false
Select Saturation Blending Mode
Select Saturation Blending Mode
Select Saturation Blending Mode
0
0
Alt+Shift+T
false
Select Color Blending Mode
Select Color Blending Mode
Select Color Blending Mode
0
0
Alt+Shift+C
false
Select Luminosity Blending Mode
Select Luminosity Blending Mode
Select Luminosity Blending Mode
0
0
Alt+Shift+Y
false
Animation
Previous frame
Move to previous frame
Move to previous frame
1
0
false
Next frame
Move to next frame
Move to next frame
1
0
false
Play / pause animation
Play / pause animation
Play / pause animation
1
0
false
Add blank frame
Add blank frame
Add blank frame
100000
0
false
Copy Frame
Add duplicate frame
Add duplicate frame
100000
0
false
Toggle onion skin
Toggle onion skin
Toggle onion skin
100000
0
false
Previous Keyframe
false
Next Keyframe
false
First Frame
false
Last Frame
false
Auto Frame Mode
true
true
Add blank frame
Add blank frame
Add blank frame
100000
0
false
Show in Timeline
true
Layers
Activate next layer
Activate next layer
Activate next layer
1000
0
PgUp
false
Activate previous layer
Activate previous layer
Activate previous layer
1000
0
PgDown
false
Activate previously selected layer
Activate previously selected layer
Activate previously selected layer
1000
0
;
false
groupLayer
&Group Layer
Group Layer
Group Layer
1000
0
false
cloneLayer
&Clone Layer
Clone Layer
Clone Layer
1000
0
false
vectorLayer
&Vector Layer
Vector Layer
Vector Layer
1000
0
false
filterLayer
&Filter Layer...
Filter Layer
Filter Layer
1000
0
false
fillLayer
&Fill Layer...
Fill Layer
Fill Layer
1000
0
false
fileLayer
&File Layer...
File Layer
File Layer
1000
0
false
transparencyMask
&Transparency Mask
Transparency Mask
Transparency Mask
100000
0
false
filterMask
&Filter Mask...
Filter Mask
Filter Mask
100000
0
false
filterMask
&Colorize Mask
Colorize Mask
Colorize Mask
100000
0
false
transformMask
&Transform Mask...
Transform Mask
Transform Mask
100000
0
false
selectionMask
&Local Selection
Local Selection
Local Selection
100000
0
false
view-filter
&Isolate Layer
Isolate Layer
Isolate Layer
1000
0
true
layer-locked
&Toggle layer lock
Toggle layer lock
Toggle layer lock
1000
0
false
visible
Toggle layer &visibility
Toggle layer visibility
Toggle layer visibility
1000
0
false
transparency-locked
Toggle layer &alpha
Toggle layer alpha
Toggle layer alpha
1000
0
false
transparency-enabled
Toggle layer alpha &inheritance
Toggle layer alpha inheritance
Toggle layer alpha inheritance
1000
0
false
paintLayer
&Paint Layer
Paint Layer
Paint Layer
1000
0
Insert
false
&New Layer From Visible
New layer from visible
New layer from visible
1000
0
false
duplicatelayer
&Duplicate Layer or Mask
Duplicate Layer or Mask
Duplicate Layer or Mask
1000
0
Ctrl+J
false
&Cut Selection to New Layer
Cut Selection to New Layer
Cut Selection to New Layer
100000000
1
Ctrl+Shift+J
false
Copy &Selection to New Layer
Copy Selection to New Layer
Copy Selection to New Layer
100000000
0
Ctrl+Alt+J
false
Copy Layer
Copy layer to clipboard
Copy layer to clipboard
10000
0
false
Cut Layer
Cut layer to clipboard
Cut layer to clipboard
10000
0
false
Paste Layer
Paste layer from clipboard
Paste layer from clipboard
10000
0
false
Quick Group
Create a group layer containing selected layers
Quick Group
100000
0
Ctrl+G
false
Quick Ungroup
Remove grouping of the layers or remove one layer out of the group
Quick Ungroup
100000
0
Ctrl+Alt+G
false
Quick Clipping Group
Group selected layers and add a layer with clipped alpha channel
Quick Clipping Group
100000
0
Ctrl+Shift+G
false
All Layers
Select all layers
Select all layers
10000
0
false
Visible Layers
Select all visible layers
Select all visible layers
10000
0
false
Locked Layers
Select all locked layers
Select all locked layers
10000
0
false
Invisible Layers
Select all invisible layers
Select all invisible layers
10000
0
false
Unlocked Layers
Select all unlocked layers
Select all unlocked layers
10000
0
false
document-save
&Save Layer/Mask...
Save Layer/Mask
Save Layer/Mask
1000
0
false
document-save
Save &Group Layers...
Save Group Layers
Save Group Layers
100000
0
false
Convert group to &animated layer
Convert child layers into animation frames
Convert child layers into animation frames
100000
0
false
I&mport Layer...
Import Layer
Import Layer
100000
0
false
paintLayer
&as Paint Layer...
as Paint Layer
as Paint Layer
1000
0
false
transparencyMask
as &Transparency Mask...
as Transparency Mask
as Transparency Mask
1000
0
false
filterMask
as &Filter Mask...
as Filter Mask
as Filter Mask
1000
0
false
selectionMask
as &Selection Mask...
as Selection Mask
as Selection Mask
1000
0
false
paintLayer
to &Paint Layer
to Paint Layer
to Paint Layer
1000
0
false
transparencyMask
to &Transparency Mask
to Transparency Mask
to Transparency Mask
1000
0
false
filterMask
to &Filter Mask...
to Filter Mask
to Filter Mask
1000
0
false
selectionMask
to &Selection Mask
to Selection Mask
to Selection Mask
1000
0
false
transparencyMask
&Alpha into Mask
Alpha into Mask
Alpha into Mask
100000
10
false
transparency-enabled
&Write as Alpha
Write as Alpha
Write as Alpha
1000000
1
false
document-save
&Save Merged...
Save Merged
Save Merged
1000000
0
false
split-layer
Split Layer...
Split Layer
Split Layer
1000
0
false
Wavelet Decompose ...
Wavelet Decompose
Wavelet Decompose
1000
1
false
symmetry-horizontal
Mirror Layer Hori&zontally
Mirror Layer Horizontally
Mirror Layer Horizontally
1000
1
false
symmetry-vertical
Mirror Layer &Vertically
Mirror Layer Vertically
Mirror Layer Vertically
1000
1
false
&Rotate Layer...
Rotate Layer
Rotate Layer
1000
1
false
object-rotate-right
Rotate &Layer 90° to the Right
Rotate Layer 90° to the Right
Rotate Layer 90° to the Right
1000
1
false
object-rotate-left
Rotate Layer &90° to the Left
Rotate Layer 90° to the Left
Rotate Layer 90° to the Left
1000
1
false
Rotate Layer &180°
Rotate Layer 180°
Rotate Layer 180°
1000
1
false
Scale &Layer to new Size...
Scale Layer to new Size
Scale Layer to new Size
100000
1
false
&Shear Layer...
Shear Layer
Shear Layer
1000
1
false
&Offset Layer...
Offset Layer
Offset Layer
100000
1
false
Clones &Array...
Clones Array
Clones Array
100000
0
false
&Edit metadata...
Edit metadata
Edit metadata
100000
1
false
&Histogram...
Histogram
Histogram
100000
0
false
&Convert Layer Color Space...
Convert Layer Color Space
Convert Layer Color Space
100000
1
false
merge-layer-below
&Merge with Layer Below
Merge with Layer Below
Merge with Layer Below
100000
0
Ctrl+E
false
&Flatten Layer
Flatten Layer
Flatten Layer
100000
0
false
Ras&terize Layer
Rasterize Layer
Rasterize Layer
10000000
1
false
Flatten ima&ge
Flatten image
Flatten image
100000
0
Ctrl+Shift+E
false
La&yer Style...
Layer Style
Layer Style
100000
1
false
Move into previous group
Move into previous group
Move into previous group
0
0
false
Move into next group
Move into next group
Move into next group
0
0
false
Rename current layer
Rename current layer
Rename current layer
100000
0
F2
false
deletelayer
&Remove Layer
Remove Layer
Remove Layer
1000
1
Shift+Delete
false
arrowupblr
Move Layer or Mask Up
Move Layer or Mask Up
Ctrl+PgUp
false
arrowdown
Move Layer or Mask Down
Move Layer or Mask Down
Ctrl+PgDown
false
properties
&Properties...
Properties
Properties
1000
1
F3
false
diff --git a/krita/main.cc b/krita/main.cc
index c23b3c579c..5c8d0750d2 100644
--- a/krita/main.cc
+++ b/krita/main.cc
@@ -1,289 +1,311 @@
/*
* Copyright (c) 1999 Matthias Elter
* Copyright (c) 2002 Patrick Julien
* Copyright (c) 2015 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "data/splash/splash_screen.xpm"
#include "data/splash/splash_holidays.xpm"
#include "KisDocument.h"
#include "kis_splash_screen.h"
#include "KisPart.h"
#include "KisApplicationArguments.h"
#include
#include "input/KisQtWidgetsTweaker.h"
#if defined Q_OS_WIN
#include
#include
#include
+#include
+#include
#elif defined HAVE_X11
#include
#include
#endif
#if defined HAVE_KCRASH
#include
#elif defined USE_DRMINGW
namespace
{
void tryInitDrMingw()
{
wchar_t path[MAX_PATH];
QString pathStr = QCoreApplication::applicationDirPath().replace(L'/', L'\\') + QStringLiteral("\\exchndl.dll");
if (pathStr.size() > MAX_PATH - 1) {
return;
}
int pathLen = pathStr.toWCharArray(path);
path[pathLen] = L'\0'; // toWCharArray doesn't add NULL terminator
HMODULE hMod = LoadLibraryW(path);
if (!hMod) {
return;
}
// No need to call ExcHndlInit since the crash handler is installed on DllMain
auto myExcHndlSetLogFileNameA = reinterpret_cast(GetProcAddress(hMod, "ExcHndlSetLogFileNameA"));
if (!myExcHndlSetLogFileNameA) {
return;
}
// Set the log file path to %LocalAppData%\kritacrash.log
QString logFile = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation).replace(L'/', L'\\') + QStringLiteral("\\kritacrash.log");
myExcHndlSetLogFileNameA(logFile.toLocal8Bit());
}
} // namespace
#endif
extern "C" int main(int argc, char **argv)
{
// The global initialization of the random generator
qsrand(time(0));
bool runningInKDE = !qgetenv("KDE_FULL_SESSION").isEmpty();
#if defined HAVE_X11
qputenv("QT_QPA_PLATFORM", "xcb");
#endif
KisLoggingManager::initialize();
// A per-user unique string, without /, because QLocalServer cannot use names with a / in it
QString key = "Krita3" + QDesktopServices::storageLocation(QDesktopServices::HomeLocation).replace("/", "_");
key = key.replace(":", "_").replace("\\","_");
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
bool singleApplication = true;
bool enableOpenGLDebug = false;
bool openGLDebugSynchronous = false;
{
QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
singleApplication = kritarc.value("EnableSingleApplication", true).toBool();
#if QT_VERSION >= 0x050600
if (kritarc.value("EnableHiDPI", false).toBool()) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
}
if (!qgetenv("KRITA_HIDPI").isEmpty()) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
}
#endif
if (!qgetenv("KRITA_OPENGL_DEBUG").isEmpty()) {
enableOpenGLDebug = true;
} else {
enableOpenGLDebug = kritarc.value("EnableOpenGLDebug", false).toBool();
}
if (enableOpenGLDebug && (qgetenv("KRITA_OPENGL_DEBUG") == "sync" || kritarc.value("OpenGLDebugSynchronous", false).toBool())) {
openGLDebugSynchronous = true;
}
}
KisOpenGL::setDefaultFormat(enableOpenGLDebug, openGLDebugSynchronous);
#ifdef Q_OS_WIN
// Force ANGLE to use Direct3D11. D3D9 doesn't support OpenGL ES 3 and WARP
// might get weird crashes atm.
qputenv("QT_ANGLE_PLATFORM", "d3d11");
// Probe QPA auto OpenGL detection
KisOpenGL::probeWindowsQpaOpenGL(argc, argv);
#endif
KLocalizedString::setApplicationDomain("krita");
// first create the application so we can create a pixmap
KisApplication app(key, argc, argv);
#ifdef Q_OS_LINUX
qputenv("XDG_DATA_DIRS", QFile::encodeName(KoResourcePaths::getApplicationRoot() + "share") + ":" + qgetenv("XDG_DATA_DIRS"));
#else
qputenv("XDG_DATA_DIRS", QFile::encodeName(KoResourcePaths::getApplicationRoot() + "share"));
#endif
qDebug() << "Setting XDG_DATA_DIRS" << qgetenv("XDG_DATA_DIRS");
qDebug() << "Available translations" << KLocalizedString::availableApplicationTranslations();
qDebug() << "Available domain translations" << KLocalizedString::availableDomainTranslations("krita");
// Now that the paths are set, set the language. First check the override from the langage
// selection dialog.
{
QSettings languageoverride(configPath + QStringLiteral("/klanguageoverridesrc"), QSettings::IniFormat);
languageoverride.beginGroup(QStringLiteral("Language"));
QString language = languageoverride.value(qAppName(), "").toString();
qDebug() << "Override language:" << language;
if (!language.isEmpty()) {
KLocalizedString::setLanguages(language.split(":"));
// And override Qt's locale, too
qputenv("LANG", language.split(":").first().toUtf8());
QLocale locale(language.split(":").first());
QLocale::setDefault(locale);
qDebug() << "Qt ui languages" << locale.uiLanguages();
}
else {
// And if there isn't one, check the one set by the system.
// XXX: This doesn't work, for some !@#$% reason.
QLocale locale = QLocale::system();
if (locale.bcp47Name() != QStringLiteral("en")) {
qputenv("LANG", locale.bcp47Name().toLatin1());
KLocalizedString::setLanguages(QStringList() << locale.bcp47Name());
}
}
}
#ifdef Q_OS_WIN
QDir appdir(KoResourcePaths::getApplicationRoot());
QString path = qgetenv("PATH");
qputenv("PATH", QFile::encodeName(appdir.absolutePath() + "/bin" + ";"
+ appdir.absolutePath() + "/lib" + ";"
+ appdir.absolutePath() + "/Frameworks" + ";"
+ appdir.absolutePath() + ";"
+ path));
qDebug() << "PATH" << qgetenv("PATH");
#endif
if (qApp->applicationDirPath().contains(KRITA_BUILD_DIR)) {
qFatal("FATAL: You're trying to run krita from the build location. You can only run Krita from the installation location.");
}
#if defined HAVE_KCRASH
KCrash::initialize();
#elif defined USE_DRMINGW
tryInitDrMingw();
#endif
// If we should clear the config, it has to be done as soon as possible after
// KisApplication has been created. Otherwise the config file may have been read
// and stored in a KConfig object we have no control over.
app.askClearConfig();
KisApplicationArguments args(app);
if (singleApplication && app.isRunning()) {
// only pass arguments to main instance if they are not for batch processing
// any batch processing would be done in this separate instance
const bool batchRun = (args.print() || args.exportAs() || args.exportAsPdf());
if (!batchRun) {
QByteArray ba = args.serialize();
if (app.sendMessage(ba)) {
return 0;
}
}
}
if (!runningInKDE) {
// Icons in menus are ugly and distracting
app.setAttribute(Qt::AA_DontShowIconsInMenus);
}
#if defined HAVE_X11
app.installNativeEventFilter(KisXi2EventFilter::instance());
#endif
app.installEventFilter(KisQtWidgetsTweaker::instance());
- // then create the pixmap from an xpm: we cannot get the
- // location of our datadir before we've started our components,
- // so use an xpm.
- QDate currentDate = QDate::currentDate();
- QWidget *splash = 0;
- if (currentDate > QDate(currentDate.year(), 12, 4) ||
- currentDate < QDate(currentDate.year(), 1, 9)) {
- splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_holidays_xpm));
- }
- else {
- splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_screen_xpm));
- }
+ if (!args.noSplash()) {
+ // then create the pixmap from an xpm: we cannot get the
+ // location of our datadir before we've started our components,
+ // so use an xpm.
+ QDate currentDate = QDate::currentDate();
+ QWidget *splash = 0;
+ if (currentDate > QDate(currentDate.year(), 12, 4) ||
+ currentDate < QDate(currentDate.year(), 1, 9)) {
+ splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_holidays_xpm));
+ }
+ else {
+ splash = new KisSplashScreen(app.applicationVersion(), QPixmap(splash_screen_xpm));
+ }
- app.setSplashScreen(splash);
+ app.setSplashScreen(splash);
+ }
#if defined Q_OS_WIN
- KisTabletSupportWin::init();
- // app.installNativeEventFilter(new KisTabletSupportWin());
+ {
+ KisConfig cfg;
+ bool isUsingWin8PointerInput = false;
+ if (cfg.useWin8PointerInput()) {
+ KisTabletSupportWin8 *penFilter = new KisTabletSupportWin8();
+ if (penFilter->init()) {
+ // penFilter.registerPointerDeviceNotifications();
+ app.installNativeEventFilter(penFilter);
+ isUsingWin8PointerInput = true;
+ qDebug() << "Using Win8 Pointer Input for tablet support";
+ } else {
+ qDebug() << "No Win8 Pointer Input available";
+ delete penFilter;
+ }
+ }
+ if (!isUsingWin8PointerInput) {
+ KisTabletSupportWin::init();
+ // app.installNativeEventFilter(new KisTabletSupportWin());
+ }
+ }
#endif
if (!app.start(args)) {
return 1;
}
#if QT_VERSION >= 0x050700
app.setAttribute(Qt::AA_CompressHighFrequencyEvents, false);
#endif
// Set up remote arguments.
QObject::connect(&app, SIGNAL(messageReceived(QByteArray,QObject*)),
&app, SLOT(remoteArguments(QByteArray,QObject*)));
QObject::connect(&app, SIGNAL(fileOpenRequest(QString)),
&app, SLOT(fileOpenRequested(QString)));
int state = app.exec();
{
QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
kritarc.setValue("canvasState", "OPENGL_SUCCESS");
}
return state;
}
diff --git a/libs/libkis/Action.cpp b/libs/libkis/Action.cpp
index 152a47ac05..75005dce79 100644
--- a/libs/libkis/Action.cpp
+++ b/libs/libkis/Action.cpp
@@ -1,164 +1,169 @@
/*
* Copyright (c) 2016 Boudewijn Rempt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser 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 "Action.h"
struct Action::Private {
Private() {}
QAction *action {0};
};
Action::Action(QObject *parent)
: QObject(parent)
, d(new Private)
{
d->action = new KisAction(this);
connect(d->action, SIGNAL(triggered(bool)), SIGNAL(triggered(bool)));
}
Action::Action(const QString &name, QAction *action, QObject *parent)
: QObject(parent)
, d(new Private)
{
d->action = action;
d->action->setObjectName(name);
connect(d->action, SIGNAL(triggered(bool)), SIGNAL(triggered(bool)));
}
Action::~Action()
{
delete d;
}
bool Action::operator==(const Action &other) const
{
return (d->action == other.d->action);
}
bool Action::operator!=(const Action &other) const
{
return !(operator==(other));
}
QString Action::text() const
{
if (!d->action) return "";
return d->action->text();
}
void Action::setText(QString text)
{
if (!d->action) return;
d->action->setText(text);
}
QString Action::name() const
{
if (!d->action) return "";
return d->action->objectName();
}
void Action::setName(QString name)
{
if (!d->action) return;
d->action->setObjectName(name);
}
bool Action::isCheckable() const
{
if (!d->action) return false;
return d->action->isCheckable();
}
void Action::setCheckable(bool value)
{
if (!d->action) return;
d->action->setCheckable(value);
}
bool Action::isChecked() const
{
if (!d->action) return false;
return d->action->isChecked();
}
void Action::setChecked(bool value)
{
if (!d->action) return;
d->action->setChecked(value);
}
QString Action::shortcut() const
{
if (!d->action) return QString();
return d->action->shortcut().toString();
}
void Action::setShortcut(QString value)
{
if (!d->action) return;
d->action->setShortcut(QKeySequence::fromString(value));
}
bool Action::isVisible() const
{
if (!d->action) return false;
return d->action->isVisible();
}
void Action::setVisible(bool value)
{
if (!d->action) return;
d->action->setVisible(value);
}
bool Action::isEnabled() const
{
if (!d->action) return false;
return d->action->isEnabled();
}
void Action::setEnabled(bool value)
{
if (!d->action) return;
d->action->setEnabled(value);
}
void Action::setToolTip(QString tooltip)
{
if (!d->action) return;
d->action->setToolTip(tooltip);
}
+QString Action::tooltip() const
+{
+ return d->action->toolTip();
+}
+
void Action::trigger()
{
d->action->trigger();
}
void Action::setMenu(const QString menu)
{
d->action->setProperty("menu", menu);
}
QString Action::menu() const
{
return d->action->property("menu").toString();
}
diff --git a/libs/libkis/Action.h b/libs/libkis/Action.h
index 66ed921131..3d8b470013 100644
--- a/libs/libkis/Action.h
+++ b/libs/libkis/Action.h
@@ -1,160 +1,165 @@
/*
* Copyright (c) 2016 Boudewijn Rempt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser 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 LIBKIS_ACTION_H
#define LIBKIS_ACTION_H
#include
#include "kritalibkis_export.h"
#include "libkis.h"
/**
* Action encapsulates a KisAction. By default, actions are put in the Tools/Scripts menu.
*/
class KRITALIBKIS_EXPORT Action : public QObject
{
Q_OBJECT
public:
/**
* @brief Action Create a new action object
* @param parent the parent if it's in a QObject hierarchy
*/
explicit Action(QObject *parent = 0);
/**
* @brief Action Create a new action object
* @param name the name of the action
* @param action the QAction it wraps
* @param parent the parent if it's in a QObject hierarchy
*/
Action(const QString &name, QAction *action, QObject *parent = 0);
~Action() override;
bool operator==(const Action &other) const;
bool operator!=(const Action &other) const;
public Q_SLOTS:
/**
* @return the user-visible text of the action.
*/
QString text() const;
/**
* set the user-visible text of the action to @param text.
*/
void setText(QString text);
/**
* @return the internal name of the action.
*/
QString name() const;
/**
* set the name of the action to @param name. This is not the user-visible name, but the internal one
*/
void setName(QString name);
/**
* @return true if the action is checkable, false if it isn't*
*/
bool isCheckable() const;
/**
* Set the action action checkable if @param value is true, unchecked if it's false
*/
void setCheckable(bool value);
/**
* @return true if the action is checked, false if it isn't
*/
bool isChecked() const;
/**
* Set the action checked if @param value is true, unchecked if it's false
*/
void setChecked(bool value);
/**
* Return the action's shortcut as a string
*/
QString shortcut() const;
/**
* set the action's shortcut to the given string.
* @code
* action.setShortcut("CTRL+SHIFT+S")
* @endcode
*/
void setShortcut(QString value);
bool isVisible() const;
/**
* @brief setVisible determines whether the action will be visible in the scripting menu.
* @param value true if the action is to be shown in the menu, false otherwise
*/
void setVisible(bool value);
/**
* @return true if the action is enabled, false if not
*/
bool isEnabled() const;
/**
* Set the action enabled or disabled according to @param value
*/
void setEnabled(bool value);
/**
* Set the tooltip to the given @param tooltip
*/
void setToolTip(QString tooltip);
+ /**
+ * @return the tooltip text
+ */
+ QString tooltip() const;
+
/**
* Trigger this action
*/
void trigger();
/**
* @brief setMenu determines in which menu the action will be placed. The default is tools/scripts
* @param menu the menu where the action should go, / -separated to drill down the hierarchy
*/
void setMenu(const QString menu);
/**
* @return the menu in which this action is to be placed.
*/
QString menu() const;
Q_SIGNALS:
/**
* Emitted whenever the action is triggered.
*/
void triggered(bool);
private:
struct Private;
Private *const d;
};
#endif // LIBKIS_ACTION_H
diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt
index f24b3547e2..5fb191cbd3 100644
--- a/libs/ui/CMakeLists.txt
+++ b/libs/ui/CMakeLists.txt
@@ -1,558 +1,559 @@
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile
${EXIV2_INCLUDE_DIR}
)
include_directories(SYSTEM
${EIGEN3_INCLUDE_DIR}
${OCIO_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
)
add_subdirectory( tests )
if (APPLE)
find_library(FOUNDATION_LIBRARY Foundation)
endif ()
set(kritaui_LIB_SRCS
canvas/kis_canvas_widget_base.cpp
canvas/kis_canvas2.cpp
canvas/kis_canvas_updates_compressor.cpp
canvas/kis_canvas_controller.cpp
canvas/kis_paintop_transformation_connector.cpp
canvas/kis_display_color_converter.cpp
canvas/kis_display_filter.cpp
canvas/kis_exposure_gamma_correction_interface.cpp
canvas/kis_tool_proxy.cpp
canvas/kis_canvas_decoration.cc
canvas/kis_coordinates_converter.cpp
canvas/kis_grid_manager.cpp
canvas/kis_grid_decoration.cpp
canvas/kis_grid_config.cpp
canvas/kis_prescaled_projection.cpp
canvas/kis_qpainter_canvas.cpp
canvas/kis_projection_backend.cpp
canvas/kis_update_info.cpp
canvas/kis_image_patch.cpp
canvas/kis_image_pyramid.cpp
canvas/kis_infinity_manager.cpp
canvas/kis_change_guides_command.cpp
canvas/kis_guides_decoration.cpp
canvas/kis_guides_manager.cpp
canvas/kis_guides_config.cpp
canvas/kis_snap_config.cpp
canvas/kis_snap_line_strategy.cpp
canvas/KisSnapPointStrategy.cpp
dialogs/kis_about_application.cpp
dialogs/kis_dlg_adj_layer_props.cc
dialogs/kis_dlg_adjustment_layer.cc
dialogs/kis_dlg_filter.cpp
dialogs/kis_dlg_generator_layer.cpp
dialogs/kis_dlg_file_layer.cpp
dialogs/kis_dlg_filter.cpp
dialogs/kis_dlg_stroke_selection_properties.cpp
dialogs/kis_dlg_image_properties.cc
dialogs/kis_dlg_layer_properties.cc
dialogs/kis_dlg_preferences.cc
dialogs/slider_and_spin_box_sync.cpp
dialogs/kis_dlg_blacklist_cleanup.cpp
dialogs/kis_dlg_layer_style.cpp
dialogs/kis_dlg_png_import.cpp
dialogs/kis_dlg_import_image_sequence.cpp
dialogs/kis_delayed_save_dialog.cpp
dialogs/kis_dlg_internal_color_selector.cpp
flake/kis_node_dummies_graph.cpp
flake/kis_dummies_facade_base.cpp
flake/kis_dummies_facade.cpp
flake/kis_node_shapes_graph.cpp
flake/kis_node_shape.cpp
flake/kis_shape_controller.cpp
flake/kis_shape_layer.cc
flake/kis_shape_layer_canvas.cpp
flake/kis_shape_selection.cpp
flake/kis_shape_selection_canvas.cpp
flake/kis_shape_selection_model.cpp
flake/kis_take_all_shapes_command.cpp
brushhud/kis_uniform_paintop_property_widget.cpp
brushhud/kis_brush_hud.cpp
brushhud/kis_round_hud_button.cpp
brushhud/kis_dlg_brush_hud_config.cpp
brushhud/kis_brush_hud_properties_list.cpp
brushhud/kis_brush_hud_properties_config.cpp
kis_aspect_ratio_locker.cpp
kis_autogradient.cc
kis_bookmarked_configurations_editor.cc
kis_bookmarked_configurations_model.cc
kis_bookmarked_filter_configurations_model.cc
kis_base_option.cpp
kis_canvas_resource_provider.cpp
kis_derived_resources.cpp
kis_categories_mapper.cpp
kis_categorized_list_model.cpp
kis_categorized_item_delegate.cpp
kis_clipboard.cc
kis_config.cc
kis_config_notifier.cpp
kis_control_frame.cpp
kis_composite_ops_model.cc
kis_paint_ops_model.cpp
kis_cursor.cc
kis_cursor_cache.cpp
kis_custom_pattern.cc
kis_file_layer.cpp
kis_safe_document_loader.cpp
kis_splash_screen.cpp
kis_filter_manager.cc
kis_filters_model.cc
kis_histogram_view.cc
KisImageBarrierLockerWithFeedback.cpp
kis_image_manager.cc
kis_image_view_converter.cpp
kis_import_catcher.cc
kis_layer_manager.cc
kis_mask_manager.cc
kis_mimedata.cpp
kis_node_commands_adapter.cpp
kis_node_manager.cpp
kis_node_juggler_compressed.cpp
kis_node_selection_adapter.cpp
kis_node_insertion_adapter.cpp
kis_node_model.cpp
kis_node_filter_proxy_model.cpp
kis_model_index_converter_base.cpp
kis_model_index_converter.cpp
kis_model_index_converter_show_all.cpp
kis_painting_assistant.cc
kis_painting_assistants_decoration.cpp
kis_painting_assistants_manager.cpp
kis_paintop_box.cc
kis_paintop_option.cpp
kis_paintop_options_model.cpp
kis_paintop_settings_widget.cpp
kis_popup_palette.cpp
kis_png_converter.cpp
kis_preference_set_registry.cpp
kis_script_manager.cpp
kis_resource_server_provider.cpp
KisSelectedShapesProxy.cpp
kis_selection_decoration.cc
kis_selection_manager.cc
kis_statusbar.cc
kis_zoom_manager.cc
kis_favorite_resource_manager.cpp
kis_workspace_resource.cpp
kis_action.cpp
kis_action_manager.cpp
kis_view_plugin.cpp
kis_canvas_controls_manager.cpp
kis_tooltip_manager.cpp
kis_multinode_property.cpp
kis_stopgradient_editor.cpp
kisexiv2/kis_exif_io.cpp
kisexiv2/kis_exiv2.cpp
kisexiv2/kis_iptc_io.cpp
kisexiv2/kis_xmp_io.cpp
opengl/kis_opengl.cpp
opengl/kis_opengl_canvas2.cpp
opengl/kis_opengl_canvas_debugger.cpp
opengl/kis_opengl_image_textures.cpp
opengl/kis_texture_tile.cpp
opengl/kis_opengl_shader_loader.cpp
kis_fps_decoration.cpp
recorder/kis_node_query_path_editor.cc
recorder/kis_recorded_action_creator.cc
recorder/kis_recorded_action_creator_factory.cc
recorder/kis_recorded_action_creator_factory_registry.cc
recorder/kis_recorded_action_editor_factory.cc
recorder/kis_recorded_action_editor_factory_registry.cc
recorder/kis_recorded_filter_action_editor.cc
recorder/kis_recorded_filter_action_creator.cpp
recorder/kis_recorded_paint_action_editor.cc
tool/kis_selection_tool_helper.cpp
tool/kis_selection_tool_config_widget_helper.cpp
tool/kis_rectangle_constraint_widget.cpp
tool/kis_shape_tool_helper.cpp
tool/kis_tool.cc
tool/kis_delegated_tool_policies.cpp
tool/kis_tool_freehand.cc
tool/kis_speed_smoother.cpp
tool/kis_painting_information_builder.cpp
tool/kis_stabilized_events_sampler.cpp
tool/kis_tool_freehand_helper.cpp
tool/kis_tool_multihand_helper.cpp
tool/kis_figure_painting_tool_helper.cpp
tool/kis_recording_adapter.cpp
tool/kis_tool_paint.cc
tool/kis_tool_shape.cc
tool/kis_tool_ellipse_base.cpp
tool/kis_tool_rectangle_base.cpp
tool/kis_tool_polyline_base.cpp
tool/kis_tool_utils.cpp
tool/kis_resources_snapshot.cpp
tool/kis_smoothing_options.cpp
tool/KisStabilizerDelayedPaintHelper.cpp
tool/strokes/freehand_stroke.cpp
tool/strokes/kis_painter_based_stroke_strategy.cpp
tool/strokes/kis_filter_stroke_strategy.cpp
tool/strokes/kis_color_picker_stroke_strategy.cpp
widgets/kis_cmb_composite.cc
widgets/kis_cmb_contour.cpp
widgets/kis_cmb_gradient.cpp
widgets/kis_paintop_list_widget.cpp
widgets/kis_cmb_idlist.cc
widgets/kis_color_space_selector.cc
widgets/kis_advanced_color_space_selector.cc
widgets/kis_cie_tongue_widget.cpp
widgets/kis_tone_curve_widget.cpp
widgets/kis_curve_widget.cpp
widgets/kis_custom_image_widget.cc
widgets/kis_image_from_clipboard_widget.cpp
widgets/kis_double_widget.cc
widgets/kis_filter_selector_widget.cc
widgets/kis_gradient_chooser.cc
widgets/kis_gradient_slider_widget.cc
widgets/kis_gradient_slider.cpp
widgets/kis_iconwidget.cc
widgets/kis_mask_widgets.cpp
widgets/kis_meta_data_merge_strategy_chooser_widget.cc
widgets/kis_multi_bool_filter_widget.cc
widgets/kis_multi_double_filter_widget.cc
widgets/kis_multi_integer_filter_widget.cc
widgets/kis_multipliers_double_slider_spinbox.cpp
widgets/kis_paintop_presets_popup.cpp
widgets/kis_tool_options_popup.cpp
widgets/kis_paintop_presets_chooser_popup.cpp
widgets/kis_paintop_presets_save.cpp
widgets/kis_pattern_chooser.cc
widgets/kis_popup_button.cc
widgets/kis_preset_chooser.cpp
widgets/kis_progress_widget.cpp
widgets/kis_selection_options.cc
widgets/kis_scratch_pad.cpp
widgets/kis_scratch_pad_event_filter.cpp
widgets/kis_preset_selector_strip.cpp
widgets/kis_slider_spin_box.cpp
widgets/kis_size_group.cpp
widgets/kis_size_group_p.cpp
widgets/kis_wdg_generator.cpp
widgets/kis_workspace_chooser.cpp
widgets/squeezedcombobox.cpp
widgets/kis_categorized_list_view.cpp
widgets/kis_widget_chooser.cpp
widgets/kis_tool_button.cpp
widgets/kis_floating_message.cpp
widgets/kis_lod_availability_widget.cpp
widgets/kis_color_label_selector_widget.cpp
widgets/kis_color_filter_combo.cpp
widgets/kis_elided_label.cpp
widgets/kis_stopgradient_slider_widget.cpp
widgets/kis_spinbox_color_selector.cpp
widgets/kis_screen_color_picker.cpp
widgets/KoDualColorButton.cpp
widgets/kis_color_input.cpp
widgets/kis_color_button.cpp
widgets/KisVisualColorSelector.cpp
widgets/KisVisualColorSelectorShape.cpp
widgets/KisVisualEllipticalSelectorShape.cpp
widgets/KisVisualRectangleSelectorShape.cpp
widgets/KisVisualTriangleSelectorShape.cpp
widgets/KoStrokeConfigWidget.cpp
widgets/KoFillConfigWidget.cpp
widgets/KoShapeFillWrapper.cpp
utils/kis_document_aware_spin_box_unit_manager.cpp
input/kis_input_manager.cpp
input/kis_input_manager_p.cpp
input/kis_extended_modifiers_mapper.cpp
input/kis_abstract_input_action.cpp
input/kis_tool_invocation_action.cpp
input/kis_pan_action.cpp
input/kis_alternate_invocation_action.cpp
input/kis_rotate_canvas_action.cpp
input/kis_zoom_action.cpp
input/kis_change_frame_action.cpp
input/kis_gamma_exposure_action.cpp
input/kis_show_palette_action.cpp
input/kis_change_primary_setting_action.cpp
input/kis_abstract_shortcut.cpp
input/kis_single_action_shortcut.cpp
input/kis_stroke_shortcut.cpp
input/kis_shortcut_matcher.cpp
input/kis_select_layer_action.cpp
input/KisQtWidgetsTweaker.cpp
operations/kis_operation.cpp
operations/kis_operation_configuration.cpp
operations/kis_operation_registry.cpp
operations/kis_operation_ui_factory.cpp
operations/kis_operation_ui_widget.cpp
operations/kis_filter_selection_operation.cpp
actions/kis_selection_action_factories.cpp
actions/KisPasteActionFactory.cpp
input/kis_touch_shortcut.cpp
kis_document_undo_store.cpp
kis_transaction_based_command.cpp
kis_gui_context_command.cpp
kis_gui_context_command_p.cpp
input/kis_tablet_debugger.cpp
input/kis_input_profile_manager.cpp
input/kis_input_profile.cpp
input/kis_shortcut_configuration.cpp
input/config/kis_input_configuration_page.cpp
input/config/kis_edit_profiles_dialog.cpp
input/config/kis_input_profile_model.cpp
input/config/kis_input_configuration_page_item.cpp
input/config/kis_action_shortcuts_model.cpp
input/config/kis_input_type_delegate.cpp
input/config/kis_input_mode_delegate.cpp
input/config/kis_input_button.cpp
input/config/kis_input_editor_delegate.cpp
input/config/kis_mouse_input_editor.cpp
input/config/kis_wheel_input_editor.cpp
input/config/kis_key_input_editor.cpp
processing/fill_processing_visitor.cpp
kis_asl_layer_style_serializer.cpp
kis_psd_layer_style_resource.cpp
canvas/kis_mirror_axis.cpp
kis_abstract_perspective_grid.cpp
-
+
KisApplication.cpp
KisAutoSaveRecoveryDialog.cpp
KisDetailsPane.cpp
KisDocument.cpp
KisNodeDelegate.cpp
kis_node_view_visibility_delegate.cpp
KisNodeToolTip.cpp
KisNodeView.cpp
kis_node_view_color_scheme.cpp
KisImportExportFilter.cpp
KisFilterEntry.cpp
KisImportExportManager.cpp
KisImportExportUtils.cpp
kis_async_action_feedback.cpp
KisMainWindow.cpp
KisOpenPane.cpp
KisPart.cpp
KisPrintJob.cpp
KisTemplate.cpp
KisTemplateCreateDia.cpp
KisTemplateGroup.cpp
KisTemplates.cpp
KisTemplatesPane.cpp
KisTemplateTree.cpp
KisUndoStackAction.cpp
KisView.cpp
thememanager.cpp
kis_mainwindow_observer.cpp
KisViewManager.cpp
kis_mirror_manager.cpp
qtlockedfile/qtlockedfile.cpp
qtsingleapplication/qtlocalpeer.cpp
qtsingleapplication/qtsingleapplication.cpp
KisResourceBundle.cpp
KisResourceBundleManifest.cpp
kis_md5_generator.cpp
KisApplicationArguments.cpp
KisNetworkAccessManager.cpp
KisMultiFeedRSSModel.cpp
KisRemoteFileFetcher.cpp
KisPaletteModel.cpp
kis_palette_delegate.cpp
kis_palette_view.cpp
KisColorsetChooser.cpp
KisSaveGroupVisitor.cpp
)
if(WIN32)
if (NOT Qt5Gui_PRIVATE_INCLUDE_DIRS)
message(FATAL_ERROR "Qt5Gui Private header are missing!")
endif()
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
input/kis_tablet_event.cpp
input/wintab/kis_tablet_support_win.cpp
input/wintab/kis_screen_size_choice_dialog.cpp
qtlockedfile/qtlockedfile_win.cpp
+ input/wintab/kis_tablet_support_win8.cpp
)
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
endif()
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
kis_animation_frame_cache.cpp
kis_animation_cache_populator.cpp
KisAnimationCacheRegenerator.cpp
dialogs/KisAnimationCacheUpdateProgressDialog.cpp
canvas/kis_animation_player.cpp
kis_animation_exporter.cpp
kis_animation_importer.cpp
KisSyncedAudioPlayback.cpp
)
if(UNIX)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
input/kis_tablet_event.cpp
input/wintab/kis_tablet_support.cpp
qtlockedfile/qtlockedfile_unix.cpp
)
if(NOT APPLE)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
input/wintab/kis_tablet_support_x11.cpp
input/wintab/qxcbconnection_xi2.cpp
input/wintab/qxcbconnection.cpp
input/wintab/kis_xi2_event_filter.cpp
)
endif()
endif()
ki18n_wrap_ui(kritaui_LIB_SRCS
widgets/KoFillConfigWidget.ui
widgets/KoStrokeConfigWidget.ui
forms/wdgdlgpngimport.ui
forms/wdgfullscreensettings.ui
forms/wdgautogradient.ui
forms/wdggeneralsettings.ui
forms/wdgperformancesettings.ui
forms/wdggenerators.ui
forms/wdgbookmarkedconfigurationseditor.ui
forms/wdgapplyprofile.ui
forms/wdgcustompattern.ui
forms/wdglayerproperties.ui
forms/wdgcolorsettings.ui
forms/wdgtabletsettings.ui
forms/wdgcolorspaceselector.ui
forms/wdgcolorspaceselectoradvanced.ui
forms/wdgdisplaysettings.ui
forms/kis_previewwidgetbase.ui
forms/kis_matrix_widget.ui
forms/wdgselectionoptions.ui
forms/wdggeometryoptions.ui
forms/wdgnewimage.ui
forms/wdgimageproperties.ui
forms/wdgmaskfromselection.ui
forms/wdgmasksource.ui
forms/wdgfilterdialog.ui
forms/wdgmetadatamergestrategychooser.ui
forms/wdgpaintoppresets.ui
forms/wdgpaintopsettings.ui
forms/wdgdlggeneratorlayer.ui
forms/wdgdlgfilelayer.ui
forms/wdgfilterselector.ui
forms/wdgfilternodecreation.ui
forms/wdgpaintactioneditor.ui
forms/wdgmultipliersdoublesliderspinbox.ui
forms/wdgnodequerypatheditor.ui
forms/wdgpresetselectorstrip.ui
forms/wdgsavebrushpreset.ui
forms/wdgdlgblacklistcleanup.ui
forms/wdgrectangleconstraints.ui
forms/wdgimportimagesequence.ui
forms/wdgstrokeselectionproperties.ui
forms/KisDetailsPaneBase.ui
forms/KisOpenPaneBase.ui
forms/wdgstopgradienteditor.ui
brushhud/kis_dlg_brush_hud_config.ui
forms/wdgdlginternalcolorselector.ui
dialogs/kis_delayed_save_dialog.ui
input/config/kis_input_configuration_page.ui
input/config/kis_edit_profiles_dialog.ui
input/config/kis_input_configuration_page_item.ui
input/config/kis_mouse_input_editor.ui
input/config/kis_wheel_input_editor.ui
input/config/kis_key_input_editor.ui
layerstyles/wdgBevelAndEmboss.ui
layerstyles/wdgblendingoptions.ui
layerstyles/WdgColorOverlay.ui
layerstyles/wdgContour.ui
layerstyles/wdgdropshadow.ui
layerstyles/WdgGradientOverlay.ui
layerstyles/wdgInnerGlow.ui
layerstyles/wdglayerstyles.ui
layerstyles/WdgPatternOverlay.ui
layerstyles/WdgSatin.ui
layerstyles/WdgStroke.ui
layerstyles/wdgstylesselector.ui
layerstyles/wdgTexture.ui
wdgsplash.ui
input/wintab/kis_screen_size_choice_dialog.ui
)
QT5_WRAP_CPP(kritaui_HEADERS_MOC KisNodePropertyAction_p.h)
add_library(kritaui SHARED ${kritaui_HEADERS_MOC} ${kritaui_LIB_SRCS} )
generate_export_header(kritaui BASE_NAME kritaui)
target_link_libraries(kritaui KF5::CoreAddons KF5::Completion KF5::I18n KF5::ItemViews Qt5::Network
kritaimpex kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES}
)
if (HAVE_QT_MULTIMEDIA)
target_link_libraries(kritaui Qt5::Multimedia)
endif()
if (HAVE_KIO)
target_link_libraries(kritaui KF5::KIOCore)
endif()
if (NOT WIN32 AND NOT APPLE)
target_link_libraries(kritaui ${X11_X11_LIB}
${X11_Xinput_LIB}
${XCB_LIBRARIES})
endif()
if(APPLE)
target_link_libraries(kritaui ${FOUNDATION_LIBRARY})
endif ()
target_link_libraries(kritaui ${OPENEXR_LIBRARIES})
# Add VSync disable workaround
if(NOT WIN32 AND NOT APPLE)
target_link_libraries(kritaui ${CMAKE_DL_LIBS} Qt5::X11Extras)
endif()
if(X11_FOUND)
target_link_libraries(kritaui Qt5::X11Extras ${X11_LIBRARIES})
endif()
target_include_directories(kritaui
PUBLIC
$
$
$
$
$
$
$
)
set_target_properties(kritaui
PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION}
)
install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS})
if (APPLE)
install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita)
endif ()
diff --git a/libs/ui/KisApplication.cpp b/libs/ui/KisApplication.cpp
index d9de4c0c80..fc743809ae 100644
--- a/libs/ui/KisApplication.cpp
+++ b/libs/ui/KisApplication.cpp
@@ -1,769 +1,783 @@
/* This file is part of the KDE project
Copyright (C) 1998, 1999 Torben Weis
Copyright (C) 2009 Thomas Zander
Copyright (C) 2012 Boudewijn Rempt
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "KisApplication.h"
#include
#ifdef Q_OS_WIN
#include
#include
#endif
#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 "KoGlobal.h"
#include "KoConfig.h"
#include
#include
#include
#include "thememanager.h"
#include "KisPrintJob.h"
#include "KisDocument.h"
#include "KisMainWindow.h"
#include "KisAutoSaveRecoveryDialog.h"
#include "KisPart.h"
#include
#include "kis_md5_generator.h"
#include "kis_splash_screen.h"
#include "kis_config.h"
#include "flake/kis_shape_selection.h"
#include
#include
#include
#include
#include
#include
#include
#include "kisexiv2/kis_exiv2.h"
#include "KisApplicationArguments.h"
#include
#include "kis_action_registry.h"
#include
#include
#include
#include "kis_image_barrier_locker.h"
#include "opengl/kis_opengl.h"
#include "kis_spin_box_unit_manager.h"
#include "kis_document_aware_spin_box_unit_manager.h"
+#include "KisViewManager.h"
+#include "kis_workspace_resource.h"
#include
namespace {
const QTime appStartTime(QTime::currentTime());
}
class KisApplicationPrivate
{
public:
KisApplicationPrivate()
: splashScreen(0)
{}
QPointer splashScreen;
};
class KisApplication::ResetStarting
{
public:
ResetStarting(KisSplashScreen *splash, int fileCount)
: m_splash(splash)
, m_fileCount(fileCount)
{
}
~ResetStarting() {
if (m_splash) {
KConfigGroup cfg( KSharedConfig::openConfig(), "SplashScreen");
bool hideSplash = cfg.readEntry("HideSplashAfterStartup", false);
if (m_fileCount > 0 || hideSplash) {
m_splash->hide();
}
else {
m_splash->setWindowFlags(Qt::Dialog);
QRect r(QPoint(), m_splash->size());
m_splash->move(QApplication::desktop()->availableGeometry().center() - r.center());
m_splash->setWindowTitle(qAppName());
m_splash->setParent(0);
Q_FOREACH (QObject *o, m_splash->children()) {
QWidget *w = qobject_cast(o);
if (w && w->isHidden()) {
w->setVisible(true);
}
}
m_splash->show();
m_splash->activateWindow();
}
}
}
QPointer m_splash;
int m_fileCount;
};
KisApplication::KisApplication(const QString &key, int &argc, char **argv)
: QtSingleApplication(key, argc, argv)
, d(new KisApplicationPrivate)
, m_autosaveDialog(0)
, m_mainWindow(0)
, m_batchRun(false)
{
QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath());
setApplicationDisplayName("Krita");
setApplicationName("krita");
// Note: Qt docs suggest we set this, but if we do, we get resource paths of the form of krita/krita, which is weird.
// setOrganizationName("krita");
setOrganizationDomain("krita.org");
QString version = KritaVersionWrapper::versionString(true);
setApplicationVersion(version);
setWindowIcon(KisIconUtils::loadIcon("calligrakrita"));
if (qgetenv("KRITA_NO_STYLE_OVERRIDE").isEmpty()) {
QStringList styles = QStringList() << "breeze" << "fusion" << "plastique";
if (!styles.contains(style()->objectName().toLower())) {
Q_FOREACH (const QString & style, styles) {
if (!setStyle(style)) {
qDebug() << "No" << style << "available.";
}
else {
qDebug() << "Set style" << style;
break;
}
}
}
}
else {
qDebug() << "Style override disabled, using" << style()->objectName();
}
KisOpenGL::initialize();
qDebug() << "krita has opengl" << KisOpenGL::hasOpenGL();
}
#if defined(Q_OS_WIN) && defined(ENV32BIT)
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process;
BOOL isWow64()
{
BOOL bIsWow64 = FALSE;
//IsWow64Process is not available on all supported versions of Windows.
//Use GetModuleHandle to get a handle to the DLL that contains the function
//and GetProcAddress to get a pointer to the function if available.
fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
if(0 != fnIsWow64Process)
{
if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
{
//handle error
}
}
return bIsWow64;
}
#endif
void KisApplication::initializeGlobals(const KisApplicationArguments &args)
{
int dpiX = args.dpiX();
int dpiY = args.dpiY();
if (dpiX > 0 && dpiY > 0) {
KoDpi::setDPI(dpiX, dpiY);
}
}
void KisApplication::addResourceTypes()
{
// All Krita's resource types
KoResourcePaths::addResourceType("kis_pics", "data", "/pics/");
KoResourcePaths::addResourceType("kis_images", "data", "/images/");
KoResourcePaths::addResourceType("icc_profiles", "data", "/profiles/");
KoResourcePaths::addResourceType("metadata_schema", "data", "/metadata/schemas/");
KoResourcePaths::addResourceType("kis_brushes", "data", "/brushes/");
KoResourcePaths::addResourceType("kis_taskset", "data", "/taskset/");
KoResourcePaths::addResourceType("kis_taskset", "data", "/taskset/");
KoResourcePaths::addResourceType("gmic_definitions", "data", "/gmic/");
KoResourcePaths::addResourceType("kis_resourcebundles", "data", "/bundles/");
KoResourcePaths::addResourceType("kis_defaultpresets", "data", "/defaultpresets/");
KoResourcePaths::addResourceType("kis_paintoppresets", "data", "/paintoppresets/");
KoResourcePaths::addResourceType("kis_workspaces", "data", "/workspaces/");
KoResourcePaths::addResourceType("psd_layer_style_collections", "data", "/asl");
KoResourcePaths::addResourceType("ko_patterns", "data", "/patterns/", true);
KoResourcePaths::addResourceType("ko_gradients", "data", "/gradients/");
KoResourcePaths::addResourceType("ko_gradients", "data", "/gradients/", true);
KoResourcePaths::addResourceType("ko_palettes", "data", "/palettes/", true);
KoResourcePaths::addResourceType("kis_shortcuts", "data", "/shortcuts/");
KoResourcePaths::addResourceType("kis_actions", "data", "/actions");
KoResourcePaths::addResourceType("icc_profiles", "data", "/color/icc");
KoResourcePaths::addResourceType("ko_effects", "data", "/effects/");
KoResourcePaths::addResourceType("tags", "data", "/tags/");
KoResourcePaths::addResourceType("templates", "data", "/templates");
KoResourcePaths::addResourceType("pythonscripts", "data", "/pykrita");
KoResourcePaths::addResourceType("symbols", "data", "/symbols");
// // Extra directories to look for create resources. (Does anyone actually use that anymore?)
// KoResourcePaths::addResourceDir("ko_gradients", "/usr/share/create/gradients/gimp");
// KoResourcePaths::addResourceDir("ko_gradients", QDir::homePath() + QString("/.create/gradients/gimp"));
// KoResourcePaths::addResourceDir("ko_patterns", "/usr/share/create/patterns/gimp");
// KoResourcePaths::addResourceDir("ko_patterns", QDir::homePath() + QString("/.create/patterns/gimp"));
// KoResourcePaths::addResourceDir("kis_brushes", "/usr/share/create/brushes/gimp");
// KoResourcePaths::addResourceDir("kis_brushes", QDir::homePath() + QString("/.create/brushes/gimp"));
// KoResourcePaths::addResourceDir("ko_palettes", "/usr/share/create/swatches");
// KoResourcePaths::addResourceDir("ko_palettes", QDir::homePath() + QString("/.create/swatches"));
// Make directories for all resources we can save, and tags
QDir d;
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/tags/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/asl/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/bundles/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/gradients/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/paintoppresets/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/palettes/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/patterns/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/taskset/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/workspaces/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/input/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/pykrita/");
d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/symbols/");
}
void KisApplication::loadResources()
{
setSplashScreenLoadingText(i18n("Loading Gradients..."));
processEvents();
KoResourceServerProvider::instance()->gradientServer(true);
// Load base resources
setSplashScreenLoadingText(i18n("Loading Patterns..."));
processEvents();
KoResourceServerProvider::instance()->patternServer(true);
setSplashScreenLoadingText(i18n("Loading Palettes..."));
processEvents();
KoResourceServerProvider::instance()->paletteServer(false);
setSplashScreenLoadingText(i18n("Loading Brushes..."));
processEvents();
KisBrushServer::instance()->brushServer(true);
// load paintop presets
setSplashScreenLoadingText(i18n("Loading Paint Operations..."));
processEvents();
KisResourceServerProvider::instance()->paintOpPresetServer(true);
// load symbols
setSplashScreenLoadingText(i18n("Loading SVG Symbol Collections..."));
processEvents();
KoResourceServerProvider::instance()->svgSymbolCollectionServer(true);
setSplashScreenLoadingText(i18n("Loading Resource Bundles..."));
processEvents();
KisResourceServerProvider::instance()->resourceBundleServer();
}
void KisApplication::loadPlugins()
{
KoShapeRegistry* r = KoShapeRegistry::instance();
r->add(new KisShapeSelectionFactory());
KisActionRegistry::instance();
KisFilterRegistry::instance();
KisGeneratorRegistry::instance();
KisPaintOpRegistry::instance();
KoColorSpaceRegistry::instance();
// Load the krita-specific tools
setSplashScreenLoadingText(i18n("Loading Plugins for Krita/Tool..."));
processEvents();
KoPluginLoader::instance()->load(QString::fromLatin1("Krita/Tool"),
QString::fromLatin1("[X-Krita-Version] == 28"));
// Load dockers
setSplashScreenLoadingText(i18n("Loading Plugins for Krita/Dock..."));
processEvents();
KoPluginLoader::instance()->load(QString::fromLatin1("Krita/Dock"),
QString::fromLatin1("[X-Krita-Version] == 28"));
// XXX_EXIV: make the exiv io backends real plugins
setSplashScreenLoadingText(i18n("Loading Plugins Exiv/IO..."));
processEvents();
KisExiv2::initialize();
}
bool KisApplication::start(const KisApplicationArguments &args)
{
KisConfig cfg;
#if defined(Q_OS_WIN)
#ifdef ENV32BIT
if (isWow64() && !cfg.readEntry("WarnedAbout32Bits", false)) {
QMessageBox::information(0,
i18nc("@title:window", "Krita: Warning"),
i18n("You are running a 32 bits build on a 64 bits Windows.\n"
"This is not recommended.\n"
"Please download and install the x64 build instead."));
cfg.writeEntry("WarnedAbout32Bits", true);
}
#endif
#endif
QString opengl = cfg.canvasState();
if (opengl == "OPENGL_NOT_TRIED" ) {
cfg.setCanvasState("TRY_OPENGL");
}
else if (opengl != "OPENGL_SUCCESS") {
cfg.setCanvasState("OPENGL_FAILED");
}
setSplashScreenLoadingText(i18n("Initializing Globals"));
processEvents();
initializeGlobals(args);
const bool doTemplate = args.doTemplate();
const bool print = args.print();
const bool exportAs = args.exportAs();
const bool exportAsPdf = args.exportAsPdf();
const QString exportFileName = args.exportFileName();
m_batchRun = (print || exportAs || exportAsPdf || !exportFileName.isEmpty());
// print & exportAsPdf do user interaction ATM
const bool needsMainWindow = !exportAs;
// only show the mainWindow when no command-line mode option is passed
// TODO: fix print & exportAsPdf to work without mainwindow shown
const bool showmainWindow = !exportAs; // would be !batchRun;
const bool showSplashScreen = !m_batchRun && qEnvironmentVariableIsEmpty("NOSPLASH");// && qgetenv("XDG_CURRENT_DESKTOP") != "GNOME";
if (showSplashScreen && d->splashScreen) {
d->splashScreen->show();
d->splashScreen->repaint();
processEvents();
}
KoHashGeneratorProvider::instance()->setGenerator("MD5", new KisMD5Generator());
// Initialize all Krita directories etc.
KoGlobal::initialize();
KConfigGroup group(KSharedConfig::openConfig(), "theme");
Digikam::ThemeManager themeManager;
themeManager.setCurrentTheme(group.readEntry("Theme", "Krita dark"));
-
ResetStarting resetStarting(d->splashScreen, args.filenames().count()); // remove the splash when done
Q_UNUSED(resetStarting);
// Make sure we can save resources and tags
setSplashScreenLoadingText(i18n("Adding resource types"));
processEvents();
addResourceTypes();
// Load all resources and tags before the plugins do that
loadResources();
// Load the plugins
loadPlugins();
if (needsMainWindow) {
// show a mainWindow asap, if we want that
setSplashScreenLoadingText(i18n("Loading Main Window..."));
processEvents();
m_mainWindow = KisPart::instance()->createMainWindow();
if (showmainWindow) {
m_mainWindow->initializeGeometry();
+
+ if (!args.workspace().isEmpty()) {
+ KoResourceServer * rserver = KisResourceServerProvider::instance()->workspaceServer();
+ KisWorkspaceResource* workspace = rserver->resourceByName(args.workspace());
+ if (workspace) {
+ m_mainWindow->restoreWorkspace(workspace->dockerState());
+ }
+ }
+
+ if (args.canvasOnly()) {
+ m_mainWindow->viewManager()->switchCanvasOnly(true);
+ }
+
m_mainWindow->show();
}
}
short int numberOfOpenDocuments = 0; // number of documents open
// Check for autosave files that can be restored, if we're not running a batchrun (test, print, export to pdf)
if (!m_batchRun) {
checkAutosaveFiles();
}
setSplashScreenLoadingText(QString()); // done loading, so clear out label
processEvents();
//configure the unit manager
KisSpinBoxUnitManagerFactory::setDefaultUnitManagerBuilder(new KisDocumentAwareSpinBoxUnitManagerBuilder());
connect(this, &KisApplication::aboutToQuit, &KisSpinBoxUnitManagerFactory::clearUnitManagerBuilder); //ensure the builder is destroyed when the application leave.
//the new syntax slot syntax allow to connect to a non q_object static method.
// Get the command line arguments which we have to parse
int argsCount = args.filenames().count();
if (argsCount > 0) {
// Loop through arguments
short int nPrinted = 0;
for (int argNumber = 0; argNumber < argsCount; argNumber++) {
QString fileName = args.filenames().at(argNumber);
// are we just trying to open a template?
if (doTemplate) {
// called in mix with batch options? ignore and silently skip
if (m_batchRun) {
continue;
}
if (createNewDocFromTemplate(fileName, m_mainWindow)) {
++numberOfOpenDocuments;
}
// now try to load
}
else {
if (exportAs) {
QString outputMimetype = KisMimeDatabase::mimeTypeForFile(exportFileName);
if (outputMimetype == "application/octetstream") {
dbgKrita << i18n("Mimetype not found, try using the -mimetype option") << endl;
return 1;
}
KisDocument *doc = KisPart::instance()->createDocument();
doc->setFileBatchMode(m_batchRun);
doc->openUrl(QUrl::fromLocalFile(fileName));
qApp->processEvents(); // For vector layers to be updated
doc->setFileBatchMode(true);
if (!doc->exportDocumentSync(QUrl::fromLocalFile(exportFileName), outputMimetype.toLatin1())) {
dbgKrita << "Could not export " << fileName << "to" << exportFileName << ":" << doc->errorMessage();
}
nPrinted++;
QTimer::singleShot(0, this, SLOT(quit()));
}
else if (m_mainWindow) {
KisMainWindow::OpenFlags flags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
if (m_mainWindow->openDocument(QUrl::fromLocalFile(fileName), flags)) {
if (print) {
m_mainWindow->slotFilePrint();
nPrinted++;
// TODO: trigger closing of app once printing is done
}
else if (exportAsPdf) {
KisPrintJob *job = m_mainWindow->exportToPdf(exportFileName);
if (job)
connect (job, SIGNAL(destroyed(QObject*)), m_mainWindow,
SLOT(slotFileQuit()), Qt::QueuedConnection);
nPrinted++;
} else {
// Normal case, success
numberOfOpenDocuments++;
}
} else {
// .... if failed
// delete doc; done by openDocument
}
}
}
}
if (m_batchRun) {
return nPrinted > 0;
}
}
// fixes BUG:369308 - Krita crashing on splash screen when loading.
// trying to open a file before Krita has loaded can cause it to hang and crash
if (d->splashScreen) {
d->splashScreen->displayLinks();
d->splashScreen->displayRecentFiles();
}
// not calling this before since the program will quit there.
return true;
}
KisApplication::~KisApplication()
{
delete d;
}
void KisApplication::setSplashScreen(QWidget *splashScreen)
{
d->splashScreen = qobject_cast(splashScreen);
}
void KisApplication::setSplashScreenLoadingText(QString textToLoad)
{
if (d->splashScreen) {
d->splashScreen->loadingLabel->setText(textToLoad);
d->splashScreen->repaint();
}
}
void KisApplication::hideSplashScreen()
{
if (d->splashScreen) {
// hide the splashscreen to see the dialog
d->splashScreen->hide();
}
}
bool KisApplication::notify(QObject *receiver, QEvent *event)
{
try {
return QApplication::notify(receiver, event);
} catch (std::exception &e) {
qWarning("Error %s sending event %i to object %s",
e.what(), event->type(), qPrintable(receiver->objectName()));
} catch (...) {
qWarning("Error sending event %i to object %s",
event->type(), qPrintable(receiver->objectName()));
}
return false;
}
void KisApplication::remoteArguments(QByteArray message, QObject *socket)
{
Q_UNUSED(socket);
// check if we have any mainwindow
KisMainWindow *mw = qobject_cast(qApp->activeWindow());
if (!mw) {
mw = KisPart::instance()->mainWindows().first();
}
if (!mw) {
return;
}
KisApplicationArguments args = KisApplicationArguments::deserialize(message);
const bool doTemplate = args.doTemplate();
const int argsCount = args.filenames().count();
if (argsCount > 0) {
// Loop through arguments
for (int argNumber = 0; argNumber < argsCount; ++argNumber) {
QString filename = args.filenames().at(argNumber);
// are we just trying to open a template?
if (doTemplate) {
createNewDocFromTemplate(filename, mw);
}
else if (QFile(filename).exists()) {
KisMainWindow::OpenFlags flags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
mw->openDocument(QUrl::fromLocalFile(filename), flags);
}
}
}
}
void KisApplication::fileOpenRequested(const QString &url)
{
KisMainWindow *mainWindow = KisPart::instance()->mainWindows().first();
if (mainWindow) {
KisMainWindow::OpenFlags flags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
mainWindow->openDocument(QUrl::fromLocalFile(url), flags);
}
}
void KisApplication::checkAutosaveFiles()
{
if (m_batchRun) return;
// Check for autosave files from a previous run. There can be several, and
// we want to offer a restore for every one. Including a nice thumbnail!
QStringList filters;
filters << QString(".krita-*-*-autosave.kra");
#ifdef Q_OS_WIN
QDir dir = QDir::temp();
#else
QDir dir = QDir::home();
#endif
// all autosave files for our application
QStringList autosaveFiles = dir.entryList(filters, QDir::Files | QDir::Hidden);
// Allow the user to make their selection
if (autosaveFiles.size() > 0) {
if (d->splashScreen) {
// hide the splashscreen to see the dialog
d->splashScreen->hide();
}
m_autosaveDialog = new KisAutoSaveRecoveryDialog(autosaveFiles, activeWindow());
QDialog::DialogCode result = (QDialog::DialogCode) m_autosaveDialog->exec();
if (result == QDialog::Accepted) {
QStringList filesToRecover = m_autosaveDialog->recoverableFiles();
Q_FOREACH (const QString &autosaveFile, autosaveFiles) {
if (!filesToRecover.contains(autosaveFile)) {
QFile::remove(dir.absolutePath() + "/" + autosaveFile);
}
}
autosaveFiles = filesToRecover;
} else {
autosaveFiles.clear();
}
if (autosaveFiles.size() > 0) {
QList autosaveUrls;
Q_FOREACH (const QString &autoSaveFile, autosaveFiles) {
const QUrl url = QUrl::fromLocalFile(dir.absolutePath() + QLatin1Char('/') + autoSaveFile);
autosaveUrls << url;
}
if (m_mainWindow) {
Q_FOREACH (const QUrl &url, autosaveUrls) {
KisMainWindow::OpenFlags flags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
m_mainWindow->openDocument(url, flags | KisMainWindow::RecoveryFile);
}
}
}
// cleanup
delete m_autosaveDialog;
m_autosaveDialog = nullptr;
}
}
bool KisApplication::createNewDocFromTemplate(const QString &fileName, KisMainWindow *mainWindow)
{
QString templatePath;
const QUrl templateUrl = QUrl::fromLocalFile(fileName);
if (QFile::exists(fileName)) {
templatePath = templateUrl.toLocalFile();
dbgUI << "using full path...";
}
else {
QString desktopName(fileName);
const QString templatesResourcePath = QStringLiteral("templates/");
QStringList paths = KoResourcePaths::findAllResources("data", templatesResourcePath + "*/" + desktopName);
if (paths.isEmpty()) {
paths = KoResourcePaths::findAllResources("data", templatesResourcePath + desktopName);
}
if (paths.isEmpty()) {
QMessageBox::critical(0, i18nc("@title:window", "Krita"),
i18n("No template found for: %1", desktopName));
} else if (paths.count() > 1) {
QMessageBox::critical(0, i18nc("@title:window", "Krita"),
i18n("Too many templates found for: %1", desktopName));
} else {
templatePath = paths.at(0);
}
}
if (!templatePath.isEmpty()) {
QUrl templateBase;
templateBase.setPath(templatePath);
KDesktopFile templateInfo(templatePath);
QString templateName = templateInfo.readUrl();
QUrl templateURL;
templateURL.setPath(templateBase.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash).path() + '/' + templateName);
KisMainWindow::OpenFlags batchFlags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None;
if (mainWindow->openDocument(templateURL, KisMainWindow::Import | batchFlags)) {
dbgUI << "Template loaded...";
return true;
}
else {
QMessageBox::critical(0, i18nc("@title:window", "Krita"),
i18n("Template %1 failed to load.", templateURL.toDisplayString()));
}
}
return false;
}
void KisApplication::clearConfig()
{
KIS_ASSERT_RECOVER_RETURN(qApp->thread() == QThread::currentThread());
KSharedConfigPtr config = KSharedConfig::openConfig();
// find user settings file
bool createDir = false;
QString kritarcPath = KoResourcePaths::locateLocal("config", "kritarc", createDir);
QFile configFile(kritarcPath);
if (configFile.exists()) {
// clear file
if (configFile.open(QFile::WriteOnly)) {
configFile.close();
}
else {
QMessageBox::warning(0,
i18nc("@title:window", "Krita"),
i18n("Failed to clear %1\n\n"
"Please make sure no other program is using the file and try again.",
kritarcPath),
QMessageBox::Ok, QMessageBox::Ok);
}
}
// reload from disk; with the user file settings cleared,
// this should load any default configuration files shipping with the program
config->reparseConfiguration();
config->sync();
}
void KisApplication::askClearConfig()
{
Qt::KeyboardModifiers mods = QApplication::queryKeyboardModifiers();
bool askClearConfig = (mods & Qt::ControlModifier) && (mods & Qt::ShiftModifier) && (mods & Qt::AltModifier);
if (askClearConfig) {
bool ok = QMessageBox::question(0,
i18nc("@title:window", "Krita"),
i18n("Do you want to clear the settings file?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes;
if (ok) {
clearConfig();
}
}
}
diff --git a/libs/ui/KisApplicationArguments.cpp b/libs/ui/KisApplicationArguments.cpp
index 6b6f462f16..94ee37756b 100644
--- a/libs/ui/KisApplicationArguments.cpp
+++ b/libs/ui/KisApplicationArguments.cpp
@@ -1,222 +1,268 @@
/*
* Copyright (c) 2015 Boudewijn Rempt
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "KisApplicationArguments.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct Q_DECL_HIDDEN KisApplicationArguments::Private
{
Private()
- : dpiX(0)
- , dpiY(0)
- , doTemplate(false)
- , print(false)
- , exportAs(false)
- , exportAsPdf(false)
{
}
QStringList filenames;
- int dpiX;
- int dpiY;
- bool doTemplate;
- bool print;
- bool exportAs;
- bool exportAsPdf;
+ int dpiX {72};
+ int dpiY {72};
+ bool doTemplate {false};
+ bool print {false};
+ bool exportAs {false};
+ bool exportAsPdf {false};
QString exportFileName;
+ QString workspace;
+ bool canvasOnly {false};
+ bool noSplash {false};
+ bool fullScreen {false};
};
+
+KisApplicationArguments::KisApplicationArguments()
+ : d(new Private)
+{
+}
+
+
+KisApplicationArguments::~KisApplicationArguments()
+{
+}
+
KisApplicationArguments::KisApplicationArguments(const QApplication &app)
: d(new Private)
{
QCommandLineParser parser;
parser.addVersionOption();
parser.addHelpOption();
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("print"), i18n("Only print and exit")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("template"), i18n("Open a new document with a template")));
+ parser.addOption(QCommandLineOption(QStringList() << QLatin1String("workspace"), i18n("The name of the workspace to open Krita with"), QLatin1String("workspace")));
+ parser.addOption(QCommandLineOption(QStringList() << QLatin1String("canvasonly"), i18n("Start Krita in canvas-only mode")));
+ parser.addOption(QCommandLineOption(QStringList() << QLatin1String("nosplash"), i18n("Do not show the splash screen")));
+ parser.addOption(QCommandLineOption(QStringList() << QLatin1String("fullscreen"), i18n("Start Krita in full-screen mode")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("dpi"), i18n("Override display DPI"), QLatin1String("dpiX,dpiY")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export-pdf"), i18n("Only export to PDF and exit")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export"), i18n("Export to the given filename and exit")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export-filename"), i18n("Filename for export/export-pdf"), QLatin1String("filename")));
parser.addPositionalArgument(QLatin1String("[file(s)]"), i18n("File(s) or URL(s) to open"));
parser.process(app);
- const QDir currentDir = QDir::current();
- Q_FOREACH (const QString &filename, parser.positionalArguments()) {
- d->filenames << currentDir.absoluteFilePath(filename);
- }
-
QString dpiValues = parser.value("dpi");
if (!dpiValues.isEmpty()) {
int sep = dpiValues.indexOf(QRegExp("[x, ]"));
bool ok = true;
if (sep != -1) {
d->dpiY = dpiValues.mid(sep + 1).toInt(&ok);
dpiValues.truncate(sep);
}
if (ok) {
d->dpiX = dpiValues.toInt(&ok);
if (ok) {
if (!d->dpiY)
d->dpiY = d->dpiX;
}
}
}
+
+ d->exportFileName = parser.value("export-filename");
+ d->workspace = parser.value("workspace");
+
d->doTemplate = parser.isSet("template");
d->print = parser.isSet("print");
d->exportAs = parser.isSet("export");
d->exportAsPdf = parser.isSet("export-pdf");
- d->exportFileName = parser.value("export-filename");
+ d->canvasOnly = parser.isSet("canvasonly");
+ d->noSplash = parser.isSet("nosplash");
+ d->fullScreen = parser.isSet("fullscreen");
+
+ const QDir currentDir = QDir::current();
+ Q_FOREACH (const QString &filename, parser.positionalArguments()) {
+ d->filenames << currentDir.absoluteFilePath(filename);
+ }
}
KisApplicationArguments::KisApplicationArguments(const KisApplicationArguments &rhs)
: d(new Private)
{
d->filenames = rhs.filenames();
d->dpiX = rhs.dpiX();
d->dpiY = rhs.dpiY();
d->doTemplate = rhs.doTemplate();
d->print = rhs.print();
d->exportAs = rhs.exportAs();
d->exportAsPdf = rhs.exportAsPdf();
d->exportFileName = rhs.exportFileName();
-}
-
-KisApplicationArguments::~KisApplicationArguments()
-{
+ d->canvasOnly = rhs.canvasOnly();
+ d->workspace = rhs.workspace();
+ d->noSplash = rhs.noSplash();
+ d->fullScreen = rhs.fullScreen();
}
void KisApplicationArguments::operator=(const KisApplicationArguments &rhs)
{
d->filenames = rhs.filenames();
d->dpiX = rhs.dpiX();
d->dpiY = rhs.dpiY();
d->doTemplate = rhs.doTemplate();
d->print = rhs.print();
d->exportAs = rhs.exportAs();
d->exportAsPdf = rhs.exportAsPdf();
d->exportFileName = rhs.exportFileName();
+ d->canvasOnly = rhs.canvasOnly();
+ d->workspace = rhs.workspace();
+ d->noSplash = rhs.noSplash();
+ d->fullScreen = rhs.fullScreen();
}
QByteArray KisApplicationArguments::serialize()
{
QByteArray ba;
QBuffer buf(&ba);
buf.open(QIODevice::WriteOnly);
QDataStream ds(&buf);
ds.setVersion(QDataStream::Qt_5_0);
ds << d->filenames.count();
Q_FOREACH (const QString &filename, d->filenames) {
ds << filename;
}
ds << d->dpiX;
ds << d->dpiY;
ds << d->doTemplate;
ds << d->print;
ds << d->exportAs;
ds << d->exportAsPdf;
ds << d->exportFileName;
+ ds << d->workspace;
+ ds << d->canvasOnly;
+ ds << d->noSplash;
+ ds << d->fullScreen;
buf.close();
return ba;
}
KisApplicationArguments KisApplicationArguments::deserialize(QByteArray &serialized)
{
KisApplicationArguments args;
QBuffer buf(&serialized);
buf.open(QIODevice::ReadOnly);
QDataStream ds(&buf);
ds.setVersion(QDataStream::Qt_5_0);
int count;
ds >> count;
for(int i = 0; i < count; ++i) {
QString s;
ds >> s;
args.d->filenames << s;
}
ds >> args.d->dpiX;
ds >> args.d->dpiY;
ds >> args.d->doTemplate;
ds >> args.d->print;
ds >> args.d->exportAs;
ds >> args.d->exportAsPdf;
ds >> args.d->exportFileName;
+ ds >> args.d->workspace;
+ ds >> args.d->canvasOnly;
+ ds >> args.d->noSplash;
+ ds >> args.d->fullScreen;
buf.close();
return args;
}
QStringList KisApplicationArguments::filenames() const
{
return d->filenames;
}
int KisApplicationArguments::dpiX() const
{
return d->dpiX;
}
int KisApplicationArguments::dpiY() const
{
return d->dpiY;
}
bool KisApplicationArguments::doTemplate() const
{
return d->doTemplate;
}
bool KisApplicationArguments::print() const
{
return d->print;
}
bool KisApplicationArguments::exportAs() const
{
return d->exportAs;
}
bool KisApplicationArguments::exportAsPdf() const
{
return d->exportAsPdf;
}
QString KisApplicationArguments::exportFileName() const
{
return d->exportFileName;
}
-KisApplicationArguments::KisApplicationArguments()
- : d(new Private)
+QString KisApplicationArguments::workspace() const
+{
+ return d->workspace;
+}
+
+bool KisApplicationArguments::canvasOnly() const
+{
+ return d->canvasOnly;
+}
+
+bool KisApplicationArguments::noSplash() const
+{
+ return d->noSplash;
+}
+
+bool KisApplicationArguments::fullScreen() const
{
+ return d->fullScreen;
}
diff --git a/libs/ui/KisApplicationArguments.h b/libs/ui/KisApplicationArguments.h
index 753be67f5b..b3ae335f25 100644
--- a/libs/ui/KisApplicationArguments.h
+++ b/libs/ui/KisApplicationArguments.h
@@ -1,60 +1,64 @@
/*
* Copyright (c) 2015 Boudewijn Rempt
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KISAPPLICATIONARGUMENTS_H
#define KISAPPLICATIONARGUMENTS_H
#include
class QApplication;
class QByteArray;
class QStringList;
#include "kritaui_export.h"
class KRITAUI_EXPORT KisApplicationArguments
{
public:
KisApplicationArguments(const QApplication &app);
KisApplicationArguments(const KisApplicationArguments &rhs);
~KisApplicationArguments();
void operator=(const KisApplicationArguments& rhs);
QByteArray serialize();
static KisApplicationArguments deserialize(QByteArray &serialized);
QStringList filenames() const;
int dpiX() const;
int dpiY() const;
bool doTemplate() const;
bool print() const;
bool exportAs() const;
bool exportAsPdf() const;
QString exportFileName() const;
+ QString workspace() const;
+ bool canvasOnly() const;
+ bool noSplash() const;
+ bool fullScreen() const;
private:
KisApplicationArguments();
struct Private;
const QScopedPointer d;
};
#endif // KISAPPLICATIONARGUMENTS_H
diff --git a/libs/ui/KisNodeDelegate.cpp b/libs/ui/KisNodeDelegate.cpp
index 19fae61fb7..49b8838d6e 100644
--- a/libs/ui/KisNodeDelegate.cpp
+++ b/libs/ui/KisNodeDelegate.cpp
@@ -1,883 +1,895 @@
/*
Copyright (c) 2006 Gábor Lehel
Copyright (c) 2008 Cyrille Berger
Copyright (c) 2011 José Luis Vergara
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kis_config.h"
#include "KisNodeDelegate.h"
#include "kis_node_model.h"
#include "KisNodeToolTip.h"
#include "KisNodeView.h"
#include "KisPart.h"
#include "input/kis_input_manager.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_node_view_color_scheme.h"
#include "kis_icon_utils.h"
#include "kis_layer_properties_icons.h"
#include "krita_utils.h"
+#include "kis_config_notifier.h"
typedef KisBaseNode::Property* OptionalProperty;
#include
class KisNodeDelegate::Private
{
public:
Private() : view(0), edit(0) { }
KisNodeView *view;
QPointer edit;
KisNodeToolTip tip;
+ QColor checkersColor1;
+ QColor checkersColor2;
+
QList rightmostProperties(const KisBaseNode::PropertyList &props) const;
int numProperties(const QModelIndex &index) const;
OptionalProperty findProperty(KisBaseNode::PropertyList &props, const OptionalProperty &refProp) const;
OptionalProperty findVisibilityProperty(KisBaseNode::PropertyList &props) const;
void toggleProperty(KisBaseNode::PropertyList &props, OptionalProperty prop, bool controlPressed, const QModelIndex &index);
};
KisNodeDelegate::KisNodeDelegate(KisNodeView *view, QObject *parent)
: QAbstractItemDelegate(parent)
, d(new Private)
{
d->view = view;
QApplication::instance()->installEventFilter(this);
+ connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
+ slotConfigChanged();
}
KisNodeDelegate::~KisNodeDelegate()
{
delete d;
}
QSize KisNodeDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
KisNodeViewColorScheme scm;
return QSize(option.rect.width(), scm.rowHeight());
}
void KisNodeDelegate::paint(QPainter *p, const QStyleOptionViewItem &o, const QModelIndex &index) const
{
p->save();
{
QStyleOptionViewItem option = getOptions(o, index);
QStyle *style = option.widget ? option.widget->style() : QApplication::style();
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, p, option.widget);
bool shouldGrayOut = index.data(KisNodeModel::ShouldGrayOutRole).toBool();
if (shouldGrayOut) {
option.state &= ~QStyle::State_Enabled;
}
p->setFont(option.font);
drawColorLabel(p, option, index);
drawFrame(p, option, index);
drawThumbnail(p, option, index);
drawText(p, option, index);
drawIcons(p, option, index);
drawVisibilityIconHijack(p, option, index);
drawDecoration(p, option, index);
drawExpandButton(p, option, index);
drawBranch(p, option, index);
drawProgressBar(p, option, index);
}
p->restore();
}
void KisNodeDelegate::drawBranch(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const {
Q_UNUSED(index);
KisNodeViewColorScheme scm;
const QPoint base = scm.relThumbnailRect().translated(option.rect.topLeft()).topLeft() - QPoint( scm.indentation(), 0);
// there is no indention if we are starting negative, so don't draw a branch
if (base.x() < 0) {
return;
}
QPen oldPen = p->pen();
const qreal oldOpacity = p->opacity(); // remember previous opacity
p->setOpacity(1.0);
QColor color = scm.gridColor(option, d->view);
QColor bgColor = option.state & QStyle::State_Selected ?
qApp->palette().color(QPalette::Base) :
qApp->palette().color(QPalette::Text);
color = KritaUtils::blendColors(color, bgColor, 0.9);
// TODO: if we are a mask type, use dotted lines for the branch style
// p->setPen(QPen(p->pen().color(), 2, Qt::DashLine, Qt::RoundCap, Qt::RoundJoin));
p->setPen(QPen(color, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
QPoint p2 = base + QPoint(scm.iconSize() - scm.decorationMargin()*2, scm.iconSize()*0.45);
QPoint p3 = base + QPoint(scm.iconSize() - scm.decorationMargin()*2, scm.iconSize());
QPoint p4 = base + QPoint(scm.iconSize()*1.4, scm.iconSize());
p->drawLine(p2, p3);
p->drawLine(p3, p4);
// draw parent lines (keep drawing until x position is less than 0
QPoint p5 = p2 - QPoint(scm.indentation(), 0);
QPoint p6 = p3 - QPoint(scm.indentation(), 0);
QPoint parentBase1 = p5;
QPoint parentBase2 = p6;
// indent lines needs to be very subtle to avoid making the docker busy looking
color = KritaUtils::blendColors(color, bgColor, 0.9); // makes it a little lighter than L lines
p->setPen(QPen(color, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
while (parentBase1.x() > scm.visibilityColumnWidth()) {
p->drawLine(parentBase1, parentBase2);
parentBase1 = parentBase1 - QPoint(scm.indentation(), 0);
parentBase2 = parentBase2 - QPoint(scm.indentation(), 0);
}
p->setPen(oldPen);
p->setOpacity(oldOpacity);
}
void KisNodeDelegate::drawColorLabel(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
const int label = index.data(KisNodeModel::ColorLabelIndexRole).toInt();
QColor color = scm.colorLabel(label);
if (color.alpha() <= 0) return;
QColor bgColor = qApp->palette().color(QPalette::Base);
color = KritaUtils::blendColors(color, bgColor, 0.3);
const QRect rect = option.state & QStyle::State_Selected ?
iconsRect(option, index) :
option.rect.adjusted(-scm.indentation(), 0, 0, 0);
p->fillRect(rect, color);
}
void KisNodeDelegate::drawFrame(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
QPen oldPen = p->pen();
p->setPen(scm.gridColor(option, d->view));
const QPoint base = option.rect.topLeft();
QPoint p2 = base + QPoint(-scm.indentation() - 1, 0);
QPoint p3 = base + QPoint(2 * scm.decorationMargin() + scm.decorationSize(), 0);
QPoint p4 = base + QPoint(-1, 0);
QPoint p5(iconsRect(option,
index).left() - 1, base.y());
QPoint p6(option.rect.right(), base.y());
QPoint v(0, option.rect.height());
// draw a line that goes the length of the entire frame. one for the
// top, and one for the bottom
QPoint pTopLeft(0, option.rect.topLeft().y());
QPoint pTopRight(option.rect.bottomRight().x(),option.rect.topLeft().y() );
p->drawLine(pTopLeft, pTopRight);
QPoint pBottomLeft(0, option.rect.topLeft().y() + scm.rowHeight());
QPoint pBottomRight(option.rect.bottomRight().x(),option.rect.topLeft().y() + scm.rowHeight() );
p->drawLine(pBottomLeft, pBottomRight);
const bool paintForParent =
index.parent().isValid() &&
!index.row();
if (paintForParent) {
QPoint p1(-2 * scm.indentation() - 1, 0);
p1 += base;
p->drawLine(p1, p2);
}
QPoint k0(0, base.y());
QPoint k1(1 * scm.border() + 2 * scm.visibilityMargin() + scm.visibilitySize(), base.y());
p->drawLine(k0, k1);
p->drawLine(k0 + v, k1 + v);
p->drawLine(k0, k0 + v);
p->drawLine(k1, k1 + v);
p->drawLine(p2, p6);
p->drawLine(p2 + v, p6 + v);
p->drawLine(p2, p2 + v);
p->drawLine(p3, p3 + v);
p->drawLine(p4, p4 + v);
p->drawLine(p5, p5 + v);
p->drawLine(p6, p6 + v);
//// For debugging purposes only
//p->setPen(Qt::blue);
//KritaUtils::renderExactRect(p, iconsRect(option, index));
//KritaUtils::renderExactRect(p, textRect(option, index));
//KritaUtils::renderExactRect(p, scm.relThumbnailRect().translated(option.rect.topLeft()));
p->setPen(oldPen);
}
void KisNodeDelegate::drawThumbnail(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
const int thumbSize = scm.thumbnailSize();
const qreal oldOpacity = p->opacity(); // remember previous opacity
QImage img = index.data(int(KisNodeModel::BeginThumbnailRole) + thumbSize).value();
if (!(option.state & QStyle::State_Enabled)) {
p->setOpacity(0.35);
}
QRect fitRect = scm.relThumbnailRect().translated(option.rect.topLeft());
QPoint offset;
offset.setX((fitRect.width() - img.width()) / 2);
offset.setY((fitRect.height() - img.height()) / 2);
offset += fitRect.topLeft();
- KisConfig cfg;
-
// paint in a checkerboard pattern behind the layer contents to represent transparent
const int step = scm.thumbnailSize() / 6;
QImage checkers(2 * step, 2 * step, QImage::Format_ARGB32);
QPainter gc(&checkers);
- gc.fillRect(QRect(0, 0, step, step), cfg.checkersColor1());
- gc.fillRect(QRect(step, 0, step, step), cfg.checkersColor2());
- gc.fillRect(QRect(step, step, step, step), cfg.checkersColor1());
- gc.fillRect(QRect(0, step, step, step), cfg.checkersColor2());
+ gc.fillRect(QRect(0, 0, step, step), d->checkersColor1);
+ gc.fillRect(QRect(step, 0, step, step), d->checkersColor2);
+ gc.fillRect(QRect(step, step, step, step), d->checkersColor1);
+ gc.fillRect(QRect(0, step, step, step), d->checkersColor2);
QBrush brush(checkers);
p->setBrushOrigin(offset);
p->fillRect(img.rect().translated(offset), brush);
p->drawImage(offset, img);
p->setOpacity(oldOpacity); // restore old opacity
QRect borderRect = kisGrowRect(img.rect(), 1).translated(offset);
KritaUtils::renderExactRect(p, borderRect, scm.gridColor(option, d->view));
}
QRect KisNodeDelegate::iconsRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
int propCount = d->numProperties(index);
const int iconsWidth =
propCount * (scm.iconSize() + 2 * scm.iconMargin()) +
(propCount - 1) * scm.border();
const int x = option.rect.x() + option.rect.width()
- (iconsWidth + scm.border());
const int y = option.rect.y() + scm.border();
return QRect(x, y,
iconsWidth,
scm.rowHeight() - scm.border());
}
QRect KisNodeDelegate::textRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
static QFont f;
static int minbearing = 1337 + 666; //can be 0 or negative, 2003 is less likely
if (minbearing == 2003 || f != option.font) {
f = option.font; //getting your bearings can be expensive, so we cache them
minbearing = option.fontMetrics.minLeftBearing() + option.fontMetrics.minRightBearing();
}
const int decorationOffset =
2 * scm.border() +
2 * scm.decorationMargin() +
scm.decorationSize();
const int width =
iconsRect(option, index).left() - option.rect.x() -
scm.border() + minbearing - decorationOffset;
return QRect(option.rect.x() - minbearing + decorationOffset,
option.rect.y() + scm.border(),
width,
scm.rowHeight() - scm.border());
}
void KisNodeDelegate::drawText(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
const QRect rc = textRect(option, index)
.adjusted(scm.textMargin(), 0, -scm.textMargin(), 0);
QPen oldPen = p->pen();
const qreal oldOpacity = p->opacity(); // remember previous opacity
p->setPen(option.palette.color(QPalette::Active,QPalette::Text ));
if (!(option.state & QStyle::State_Enabled)) {
p->setOpacity(0.55);
}
const QString text = index.data(Qt::DisplayRole).toString();
const QString elided = elidedText(p->fontMetrics(), rc.width(), Qt::ElideRight, text);
p->drawText(rc, Qt::AlignLeft | Qt::AlignVCenter, elided);
p->setPen(oldPen); // restore pen settings
p->setOpacity(oldOpacity);
}
QList KisNodeDelegate::Private::rightmostProperties(const KisBaseNode::PropertyList &props) const
{
QList list;
QList prependList;
list << OptionalProperty(0);
list << OptionalProperty(0);
list << OptionalProperty(0);
KisBaseNode::PropertyList::const_iterator it = props.constBegin();
KisBaseNode::PropertyList::const_iterator end = props.constEnd();
for (; it != end; ++it) {
if (!it->isMutable) continue;
if (it->id == KisLayerPropertiesIcons::visible.id()) {
// noop...
} else if (it->id == KisLayerPropertiesIcons::locked.id()) {
list[0] = OptionalProperty(&(*it));
} else if (it->id == KisLayerPropertiesIcons::inheritAlpha.id()) {
list[1] = OptionalProperty(&(*it));
} else if (it->id == KisLayerPropertiesIcons::alphaLocked.id()) {
list[2] = OptionalProperty(&(*it));
} else {
prependList.prepend(OptionalProperty(&(*it)));
}
}
{
QMutableListIterator i(prependList);
i.toBack();
while (i.hasPrevious()) {
OptionalProperty val = i.previous();
int emptyIndex = list.lastIndexOf(0);
if (emptyIndex < 0) break;
list[emptyIndex] = val;
i.remove();
}
}
return prependList + list;
}
int KisNodeDelegate::Private::numProperties(const QModelIndex &index) const
{
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
QList realProps = rightmostProperties(props);
return realProps.size();
}
OptionalProperty KisNodeDelegate::Private::findProperty(KisBaseNode::PropertyList &props, const OptionalProperty &refProp) const
{
KisBaseNode::PropertyList::iterator it = props.begin();
KisBaseNode::PropertyList::iterator end = props.end();
for (; it != end; ++it) {
if (it->id == refProp->id) {
return &(*it);
}
}
return 0;
}
OptionalProperty KisNodeDelegate::Private::findVisibilityProperty(KisBaseNode::PropertyList &props) const
{
KisBaseNode::PropertyList::iterator it = props.begin();
KisBaseNode::PropertyList::iterator end = props.end();
for (; it != end; ++it) {
if (it->id == KisLayerPropertiesIcons::visible.id()) {
return &(*it);
}
}
return 0;
}
void KisNodeDelegate::drawIcons(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
const QRect r = iconsRect(option, index);
QTransform oldTransform = p->transform();
QPen oldPen = p->pen();
p->setTransform(QTransform::fromTranslate(r.x(), r.y()));
p->setPen(scm.gridColor(option, d->view));
int x = 0;
const int y = (scm.rowHeight() - scm.border() - scm.iconSize()) / 2;
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
QList realProps = d->rightmostProperties(props);
Q_FOREACH (OptionalProperty prop, realProps) {
x += scm.iconMargin();
if (prop) {
QIcon icon = prop->state.toBool() ? prop->onIcon : prop->offIcon;
bool fullColor = prop->state.toBool() && option.state & QStyle::State_Enabled;
const qreal oldOpacity = p->opacity(); // remember previous opacity
if (fullColor) {
p->setOpacity(1.0);
}
else {
p->setOpacity(0.35);
}
p->drawPixmap(x, y, icon.pixmap(scm.iconSize(), QIcon::Normal));
p->setOpacity(oldOpacity); // restore old opacity
}
x += scm.iconSize() + scm.iconMargin();
p->drawLine(x, 0, x, scm.rowHeight() - scm.border());
x += scm.border();
}
p->setTransform(oldTransform);
p->setPen(oldPen);
}
QRect KisNodeDelegate::visibilityClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
KisNodeViewColorScheme scm;
return QRect(scm.border(), scm.border() + option.rect.top(),
2 * scm.visibilityMargin() + scm.visibilitySize(),
scm.rowHeight() - scm.border());
}
QRect KisNodeDelegate::decorationClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option);
Q_UNUSED(index);
KisNodeViewColorScheme scm;
QRect realVisualRect = d->view->originalVisualRect(index);
return QRect(realVisualRect.left(), scm.border() + realVisualRect.top(),
2 * scm.decorationMargin() + scm.decorationSize(),
scm.rowHeight() - scm.border());
}
void KisNodeDelegate::drawVisibilityIconHijack(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
/**
* Small hack Alert:
*
* Here wepaint over the area that sits basically outside our layer's
* row. Anyway, just update it later...
*/
KisNodeViewColorScheme scm;
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
OptionalProperty prop = d->findVisibilityProperty(props);
if (!prop) return;
const int x = scm.border() + scm.visibilityMargin();
const int y = option.rect.top() + (scm.rowHeight() - scm.border() - scm.visibilitySize()) / 2;
QIcon icon = prop->state.toBool() ? prop->onIcon : prop->offIcon;
p->setOpacity(1.0);
p->drawPixmap(x, y, icon.pixmap(scm.visibilitySize(), QIcon::Normal));
//// For debugging purposes only
// p->save();
// p->setPen(Qt::blue);
// KritaUtils::renderExactRect(p, visibilityClickRect(option, index));
// p->restore();
}
void KisNodeDelegate::drawDecoration(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
QIcon icon = index.data(Qt::DecorationRole).value();
if (!icon.isNull()) {
QPixmap pixmap =
icon.pixmap(scm.decorationSize(),
(option.state & QStyle::State_Enabled) ?
QIcon::Normal : QIcon::Disabled);
const QRect rc = scm.relDecorationRect().translated(option.rect.topLeft());
const qreal oldOpacity = p->opacity(); // remember previous opacity
if (!(option.state & QStyle::State_Enabled)) {
p->setOpacity(0.35);
}
p->drawPixmap(rc.topLeft(), pixmap);
p->setOpacity(oldOpacity); // restore old opacity
}
}
void KisNodeDelegate::drawExpandButton(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
KisNodeViewColorScheme scm;
QRect rc = scm.relExpandButtonRect().translated(option.rect.topLeft());
rc = kisGrowRect(rc, 0);
if (!(option.state & QStyle::State_Children)) {
return;
}
QString iconName = option.state & QStyle::State_Open ? "arrow-down" : "arrow-right";
QIcon icon = KisIconUtils::loadIcon(iconName);
QPixmap pixmap = icon.pixmap(rc.width(),
(option.state & QStyle::State_Enabled) ?
QIcon::Normal : QIcon::Disabled);
p->drawPixmap(rc.topLeft(), pixmap);
}
void KisNodeDelegate::Private::toggleProperty(KisBaseNode::PropertyList &props, OptionalProperty clickedProperty, bool controlPressed, const QModelIndex &index)
{
QAbstractItemModel *model = view->model();
// Using Ctrl+click to enter stasis
if (controlPressed && clickedProperty->canHaveStasis) {
// STEP 0: Prepare to Enter or Leave control key stasis
quint16 numberOfLeaves = model->rowCount(index.parent());
QModelIndex eachItem;
// STEP 1: Go.
if (clickedProperty->isInStasis == false) { // Enter
/* Make every leaf of this node go State = False, saving the old property value to stateInStasis */
for (quint16 i = 0; i < numberOfLeaves; ++i) { // Foreach leaf in the node (index.parent())
eachItem = model->index(i, 1, index.parent());
// The entire property list has to be altered because model->setData cannot set individual properties
KisBaseNode::PropertyList eachPropertyList = eachItem.data(KisNodeModel::PropertiesRole).value();
OptionalProperty prop = findProperty(eachPropertyList, clickedProperty);
if (!prop) continue;
prop->stateInStasis = prop->state.toBool();
prop->state = eachItem == index;
prop->isInStasis = true;
model->setData(eachItem, QVariant::fromValue(eachPropertyList), KisNodeModel::PropertiesRole);
}
for (quint16 i = 0; i < numberOfLeaves; ++i) { // Foreach leaf in the node (index.parent())
eachItem = model->index(i, 1, index.parent());
KisBaseNode::PropertyList eachPropertyList = eachItem.data(KisNodeModel::PropertiesRole).value();
OptionalProperty prop = findProperty(eachPropertyList, clickedProperty);
if (!prop) continue;
}
} else { // Leave
/* Make every leaf of this node go State = stateInStasis */
for (quint16 i = 0; i < numberOfLeaves; ++i) {
eachItem = model->index(i, 1, index.parent());
// The entire property list has to be altered because model->setData cannot set individual properties
KisBaseNode::PropertyList eachPropertyList = eachItem.data(KisNodeModel::PropertiesRole).value();
OptionalProperty prop = findProperty(eachPropertyList, clickedProperty);
if (!prop) continue;
prop->state = prop->stateInStasis;
prop->isInStasis = false;
model->setData(eachItem, QVariant::fromValue(eachPropertyList), KisNodeModel::PropertiesRole);
}
}
} else {
clickedProperty->state = !clickedProperty->state.toBool();
model->setData(index, QVariant::fromValue(props), KisNodeModel::PropertiesRole);
}
}
bool KisNodeDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
KisNodeViewColorScheme scm;
if ((event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick)
&& (index.flags() & Qt::ItemIsEnabled))
{
QMouseEvent *mouseEvent = static_cast(event);
/**
* Small hack Alert:
*
* Here we handle clicking even when it happened outside
* the rectangle of the current index. The point is, we
* use some virtual scroling offset to move the tree to the
* right of the visibility icon. So the icon itself is placed
* in an empty area that doesn't belong to any index. But we still
* handle it.
*/
const QRect iconsRect = this->iconsRect(option, index);
const bool iconsClicked = iconsRect.isValid() &&
iconsRect.contains(mouseEvent->pos());
const QRect visibilityRect = visibilityClickRect(option, index);
const bool visibilityClicked = visibilityRect.isValid() &&
visibilityRect.contains(mouseEvent->pos());
const QRect decorationRect = decorationClickRect(option, index);
const bool decorationClicked = decorationRect.isValid() &&
decorationRect.contains(mouseEvent->pos());
const bool leftButton = mouseEvent->buttons() & Qt::LeftButton;
if (leftButton && iconsClicked) {
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
QList realProps = d->rightmostProperties(props);
const int numProps = realProps.size();
const int iconWidth = scm.iconSize() + 2 * scm.iconMargin() + scm.border();
const int xPos = mouseEvent->pos().x() - iconsRect.left();
const int clickedIcon = xPos / iconWidth;
const int distToBorder = qMin(xPos % iconWidth, iconWidth - xPos % iconWidth);
if (iconsClicked &&
clickedIcon >= 0 &&
clickedIcon < numProps &&
distToBorder > scm.iconMargin()) {
OptionalProperty clickedProperty = realProps[clickedIcon];
if (!clickedProperty) return false;
d->toggleProperty(props, clickedProperty, mouseEvent->modifiers() == Qt::ControlModifier, index);
return true;
}
} else if (leftButton && visibilityClicked) {
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
OptionalProperty clickedProperty = d->findVisibilityProperty(props);
if (!clickedProperty) return false;
d->toggleProperty(props, clickedProperty, mouseEvent->modifiers() == Qt::ControlModifier, index);
return true;
} else if (leftButton && decorationClicked) {
bool isExpandable = model->hasChildren(index);
if (isExpandable) {
bool isExpanded = d->view->isExpanded(index);
d->view->setExpanded(index, !isExpanded);
return true;
}
}
if (mouseEvent->button() == Qt::LeftButton &&
mouseEvent->modifiers() == Qt::AltModifier) {
d->view->setCurrentIndex(index);
model->setData(index, true, KisNodeModel::AlternateActiveRole);
return true;
}
}
else if (event->type() == QEvent::ToolTip) {
if (!KisConfig().hidePopups()) {
QHelpEvent *helpEvent = static_cast(event);
d->tip.showTip(d->view, helpEvent->pos(), option, index);
}
return true;
} else if (event->type() == QEvent::Leave) {
d->tip.hide();
}
return false;
}
QWidget *KisNodeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex&) const
{
d->edit = new QLineEdit(parent);
d->edit->installEventFilter(const_cast(this)); //hack?
return d->edit;
}
void KisNodeDelegate::setEditorData(QWidget *widget, const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast(widget);
Q_ASSERT(edit);
edit->setText(index.data(Qt::DisplayRole).toString());
}
void KisNodeDelegate::setModelData(QWidget *widget, QAbstractItemModel *model, const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast(widget);
Q_ASSERT(edit);
model->setData(index, edit->text(), Qt::DisplayRole);
}
void KisNodeDelegate::updateEditorGeometry(QWidget *widget, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
widget->setGeometry(option.rect);
}
// PROTECTED
bool KisNodeDelegate::eventFilter(QObject *object, QEvent *event)
{
switch (event->type()) {
case QEvent::MouseButtonPress: {
if (d->edit) {
QMouseEvent *me = static_cast(event);
if (!QRect(d->edit->mapToGlobal(QPoint()), d->edit->size()).contains(me->globalPos())) {
emit commitData(d->edit);
emit closeEditor(d->edit);
}
}
} break;
case QEvent::KeyPress: {
QLineEdit *edit = qobject_cast(object);
if (edit && edit == d->edit) {
QKeyEvent *ke = static_cast(event);
switch (ke->key()) {
case Qt::Key_Escape:
emit closeEditor(edit);
return true;
case Qt::Key_Tab:
emit commitData(edit);
emit closeEditor(edit,EditNextItem);
return true;
case Qt::Key_Backtab:
emit commitData(edit);
emit closeEditor(edit, EditPreviousItem);
return true;
case Qt::Key_Return:
case Qt::Key_Enter:
emit commitData(edit);
emit closeEditor(edit);
return true;
default: break;
}
}
} break;
case QEvent::ShortcutOverride : {
QLineEdit *edit = qobject_cast(object);
if (edit && edit == d->edit){
auto* key = static_cast(event);
if (key->modifiers() == Qt::NoModifier){
switch (key->key()){
case Qt::Key_Escape:
case Qt::Key_Tab:
case Qt::Key_Backtab:
case Qt::Key_Return:
case Qt::Key_Enter:
event->accept();
return true;
default: break;
}
}
}
} break;
case QEvent::FocusOut : {
QLineEdit *edit = qobject_cast(object);
if (edit && edit == d->edit) {
emit commitData(edit);
emit closeEditor(edit);
}
}
default: break;
}
return QAbstractItemDelegate::eventFilter(object, event);
}
// PRIVATE
QStyleOptionViewItem KisNodeDelegate::getOptions(const QStyleOptionViewItem &o, const QModelIndex &index)
{
QStyleOptionViewItem option = o;
QVariant v = index.data(Qt::FontRole);
if (v.isValid()) {
option.font = v.value();
option.fontMetrics = QFontMetrics(option.font);
}
v = index.data(Qt::TextAlignmentRole);
if (v.isValid())
option.displayAlignment = QFlag(v.toInt());
v = index.data(Qt::TextColorRole);
if (v.isValid())
option.palette.setColor(QPalette::Text, v.value());
v = index.data(Qt::BackgroundColorRole);
if (v.isValid())
option.palette.setColor(QPalette::Window, v.value());
return option;
}
QRect KisNodeDelegate::progressBarRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return iconsRect(option, index);
}
void KisNodeDelegate::drawProgressBar(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QVariant value = index.data(KisNodeModel::ProgressRole);
if (!value.isNull() && (value.toInt() >= 0 && value.toInt() <= 100)) {
const QRect r = progressBarRect(option, index);
p->save();
{
p->setClipRect(r);
QStyle* style = QApplication::style();
QStyleOptionProgressBar opt;
opt.minimum = 0;
opt.maximum = 100;
opt.progress = value.toInt();
opt.textVisible = true;
opt.textAlignment = Qt::AlignHCenter;
opt.text = i18n("%1 %", opt.progress);
opt.rect = r;
opt.orientation = Qt::Horizontal;
opt.state = option.state;
style->drawControl(QStyle::CE_ProgressBar, &opt, p, 0);
}
p->restore();
}
}
+
+void KisNodeDelegate::slotConfigChanged()
+{
+ KisConfig cfg;
+
+ d->checkersColor1 = cfg.checkersColor1();
+ d->checkersColor2 = cfg.checkersColor2();
+}
diff --git a/libs/ui/KisNodeDelegate.h b/libs/ui/KisNodeDelegate.h
index 9ccd9a693f..1cd0606c0a 100644
--- a/libs/ui/KisNodeDelegate.h
+++ b/libs/ui/KisNodeDelegate.h
@@ -1,82 +1,85 @@
/*
Copyright (c) 2006 Gábor Lehel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KIS_DOCUMENT_SECTION_DELEGATE_H
#define KIS_DOCUMENT_SECTION_DELEGATE_H
#include
class KisNodeView;
class KisNodeModel;
/**
* See KisNodeModel and KisNodeView.
*
* A delegate provides the gui machinery, using Qt's model/view terminology.
* This class is owned by KisNodeView to do the work of generating the
* graphical representation of each item.
*/
class KisNodeDelegate: public QAbstractItemDelegate
{
Q_OBJECT
public:
explicit KisNodeDelegate(KisNodeView *view, QObject *parent = 0);
~KisNodeDelegate() override;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex& index) const override;
protected:
bool eventFilter(QObject *object, QEvent *event) override;
private:
typedef KisNodeModel Model;
typedef KisNodeView View;
class Private;
Private* const d;
static QStyleOptionViewItem getOptions(const QStyleOptionViewItem &option, const QModelIndex &index);
QRect progressBarRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawProgressBar(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawBranch(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawColorLabel(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawFrame(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawThumbnail(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QRect iconsRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
QRect textRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawText(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawIcons(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QRect visibilityClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
QRect decorationClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawVisibilityIconHijack(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawDecoration(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawExpandButton(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+private Q_SLOTS:
+ void slotConfigChanged();
};
#endif
diff --git a/libs/ui/actions/kis_selection_action_factories.cpp b/libs/ui/actions/kis_selection_action_factories.cpp
index e11d6124cb..fed059d12a 100644
--- a/libs/ui/actions/kis_selection_action_factories.cpp
+++ b/libs/ui/actions/kis_selection_action_factories.cpp
@@ -1,579 +1,580 @@
/*
* Copyright (c) 2012 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_selection_action_factories.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "KisViewManager.h"
#include "kis_canvas_resource_provider.h"
#include "kis_clipboard.h"
#include "kis_pixel_selection.h"
#include "kis_paint_layer.h"
#include "kis_image.h"
#include "kis_image_barrier_locker.h"
#include "kis_fill_painter.h"
#include "kis_transaction.h"
#include "kis_iterator_ng.h"
#include "kis_processing_applicator.h"
#include "kis_group_layer.h"
#include "commands/kis_selection_commands.h"
#include "commands/kis_image_layer_add_command.h"
#include "kis_tool_proxy.h"
#include "kis_canvas2.h"
#include "kis_canvas_controller.h"
#include "kis_selection_manager.h"
#include "kis_transaction_based_command.h"
#include "kis_selection_filters.h"
#include "kis_shape_selection.h"
#include "KisPart.h"
#include "kis_shape_layer.h"
#include
#include
#include
#include "kis_canvas_resource_provider.h"
#include "kis_figure_painting_tool_helper.h"
namespace ActionHelper {
void copyFromDevice(KisViewManager *view, KisPaintDeviceSP device, bool makeSharpClip = false)
{
KisImageWSP image = view->image();
if (!image) return;
KisSelectionSP selection = view->selection();
QRect rc = (selection) ? selection->selectedExactRect() : image->bounds();
KisPaintDeviceSP clip = new KisPaintDevice(device->colorSpace());
Q_CHECK_PTR(clip);
const KoColorSpace *cs = clip->colorSpace();
// TODO if the source is linked... copy from all linked layers?!?
// Copy image data
KisPainter::copyAreaOptimized(QPoint(), device, clip, rc);
if (selection) {
// Apply selection mask.
KisPaintDeviceSP selectionProjection = selection->projection();
KisHLineIteratorSP layerIt = clip->createHLineIteratorNG(0, 0, rc.width());
KisHLineConstIteratorSP selectionIt = selectionProjection->createHLineIteratorNG(rc.x(), rc.y(), rc.width());
const KoColorSpace *selCs = selection->projection()->colorSpace();
for (qint32 y = 0; y < rc.height(); y++) {
for (qint32 x = 0; x < rc.width(); x++) {
/**
* Sharp method is an exact reverse of COMPOSITE_OVER
* so if you cover the cut/copied piece over its source
* you get an exactly the same image without any seams
*/
if (makeSharpClip) {
qreal dstAlpha = cs->opacityF(layerIt->rawData());
qreal sel = selCs->opacityF(selectionIt->oldRawData());
qreal newAlpha = sel * dstAlpha / (1.0 - dstAlpha + sel * dstAlpha);
float mask = newAlpha / dstAlpha;
cs->applyAlphaNormedFloatMask(layerIt->rawData(), &mask, 1);
} else {
cs->applyAlphaU8Mask(layerIt->rawData(), selectionIt->oldRawData(), 1);
}
layerIt->nextPixel();
selectionIt->nextPixel();
}
layerIt->nextRow();
selectionIt->nextRow();
}
}
KisClipboard::instance()->setClip(clip, rc.topLeft());
}
}
void KisSelectAllActionFactory::run(KisViewManager *view)
{
KisImageWSP image = view->image();
if (!image) return;
KisProcessingApplicator *ap = beginAction(view, kundo2_i18n("Select All"));
if (!image->globalSelection()) {
ap->applyCommand(new KisSetEmptyGlobalSelectionCommand(image),
KisStrokeJobData::SEQUENTIAL,
KisStrokeJobData::EXCLUSIVE);
}
struct SelectAll : public KisTransactionBasedCommand {
SelectAll(KisImageSP image) : m_image(image) {}
KisImageSP m_image;
KUndo2Command* paint() override {
KisSelectionSP selection = m_image->globalSelection();
KisSelectionTransaction transaction(selection->pixelSelection());
+ selection->pixelSelection()->clear();
selection->pixelSelection()->select(m_image->bounds());
return transaction.endAndTake();
}
};
ap->applyCommand(new SelectAll(image),
KisStrokeJobData::SEQUENTIAL,
KisStrokeJobData::EXCLUSIVE);
endAction(ap, KisOperationConfiguration(id()).toXML());
}
void KisDeselectActionFactory::run(KisViewManager *view)
{
KisImageWSP image = view->image();
if (!image) return;
KUndo2Command *cmd = new KisDeselectGlobalSelectionCommand(image);
KisProcessingApplicator *ap = beginAction(view, cmd->text());
ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE);
endAction(ap, KisOperationConfiguration(id()).toXML());
}
void KisReselectActionFactory::run(KisViewManager *view)
{
KisImageWSP image = view->image();
if (!image) return;
KUndo2Command *cmd = new KisReselectGlobalSelectionCommand(image);
KisProcessingApplicator *ap = beginAction(view, cmd->text());
ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE);
endAction(ap, KisOperationConfiguration(id()).toXML());
}
void KisFillActionFactory::run(const QString &fillSource, KisViewManager *view)
{
KisNodeSP node = view->activeNode();
if (!node || !node->hasEditablePaintDevice()) return;
KisSelectionSP selection = view->selection();
QRect selectedRect = selection ?
selection->selectedRect() : view->image()->bounds();
Q_UNUSED(selectedRect);
KisPaintDeviceSP filled = node->paintDevice()->createCompositionSourceDevice();
Q_UNUSED(filled);
bool usePattern = false;
bool useBgColor = false;
if (fillSource.contains("pattern")) {
usePattern = true;
} else if (fillSource.contains("bg")) {
useBgColor = true;
}
KisProcessingApplicator applicator(view->image(), node,
KisProcessingApplicator::NONE,
KisImageSignalVector() << ModifiedSignal,
kundo2_i18n("Flood Fill Layer"));
KisResourcesSnapshotSP resources =
new KisResourcesSnapshot(view->image(), node, view->resourceProvider()->resourceManager());
if (!fillSource.contains("opacity")) {
resources->setOpacity(1.0);
}
KisProcessingVisitorSP visitor =
new FillProcessingVisitor(QPoint(0, 0), // start position
selection,
resources,
false, // fast mode
usePattern,
true, // fill only selection,
0, // feathering radius
0, // sizemod
80, // threshold,
false, // unmerged
useBgColor);
applicator.applyVisitor(visitor,
KisStrokeJobData::SEQUENTIAL,
KisStrokeJobData::EXCLUSIVE);
applicator.end();
}
void KisClearActionFactory::run(KisViewManager *view)
{
// XXX: "Add saving of XML data for Clear action"
view->canvasBase()->toolProxy()->deleteSelection();
}
void KisImageResizeToSelectionActionFactory::run(KisViewManager *view)
{
// XXX: "Add saving of XML data for Image Resize To Selection action"
KisSelectionSP selection = view->selection();
if (!selection) return;
view->image()->cropImage(selection->selectedExactRect());
}
void KisCutCopyActionFactory::run(bool willCut, bool makeSharpClip, KisViewManager *view)
{
KisImageSP image = view->image();
if (!image) return;
bool haveShapesSelected = view->selectionManager()->haveShapesSelected();
if (haveShapesSelected) {
// XXX: "Add saving of XML data for Cut/Copy of shapes"
KisImageBarrierLocker locker(image);
if (willCut) {
view->canvasBase()->toolProxy()->cut();
} else {
view->canvasBase()->toolProxy()->copy();
}
} else {
KisNodeSP node = view->activeNode();
if (!node) return;
KisSelectionSP selection = view->selection();
if (selection.isNull()) return;
{
KisImageBarrierLocker locker(image);
KisPaintDeviceSP dev = node->paintDevice();
if (!dev) {
dev = node->projection();
}
if (!dev) {
view->showFloatingMessage(
i18nc("floating message when cannot copy from a node",
"Cannot copy pixels from this type of layer "),
QIcon(), 3000, KisFloatingMessage::Medium);
return;
}
if (dev->exactBounds().isEmpty()) {
view->showFloatingMessage(
i18nc("floating message when copying empty selection",
"Selection is empty: no pixels were copied "),
QIcon(), 3000, KisFloatingMessage::Medium);
return;
}
ActionHelper::copyFromDevice(view, dev, makeSharpClip);
}
if (willCut) {
KUndo2Command *command = 0;
if (node->hasEditablePaintDevice()) {
struct ClearSelection : public KisTransactionBasedCommand {
ClearSelection(KisNodeSP node, KisSelectionSP sel)
: m_node(node), m_sel(sel) {}
KisNodeSP m_node;
KisSelectionSP m_sel;
KUndo2Command* paint() override {
KisSelectionSP cutSelection = m_sel;
// Shrinking the cutting area was previously used
// for getting seamless cut-paste. Now we use makeSharpClip
// instead.
// QRect originalRect = cutSelection->selectedExactRect();
// static const int preciseSelectionThreshold = 16;
//
// if (originalRect.width() > preciseSelectionThreshold ||
// originalRect.height() > preciseSelectionThreshold) {
// cutSelection = new KisSelection(*m_sel);
// delete cutSelection->flatten();
//
// KisSelectionFilter* filter = new KisShrinkSelectionFilter(1, 1, false);
//
// QRect processingRect = filter->changeRect(originalRect);
// filter->process(cutSelection->pixelSelection(), processingRect);
// }
KisTransaction transaction(m_node->paintDevice());
m_node->paintDevice()->clearSelection(cutSelection);
m_node->setDirty(cutSelection->selectedRect());
return transaction.endAndTake();
}
};
command = new ClearSelection(node, selection);
}
KUndo2MagicString actionName = willCut ?
kundo2_i18n("Cut") :
kundo2_i18n("Copy");
KisProcessingApplicator *ap = beginAction(view, actionName);
if (command) {
ap->applyCommand(command,
KisStrokeJobData::SEQUENTIAL,
KisStrokeJobData::NORMAL);
}
KisOperationConfiguration config(id());
config.setProperty("will-cut", willCut);
endAction(ap, config.toXML());
}
}
}
void KisCopyMergedActionFactory::run(KisViewManager *view)
{
KisImageWSP image = view->image();
if (!image) return;
if (!view->blockUntilOperationsFinished(image)) return;
image->barrierLock();
KisPaintDeviceSP dev = image->root()->projection();
ActionHelper::copyFromDevice(view, dev);
image->unlock();
KisProcessingApplicator *ap = beginAction(view, kundo2_i18n("Copy Merged"));
endAction(ap, KisOperationConfiguration(id()).toXML());
}
void KisPasteNewActionFactory::run(KisViewManager *viewManager)
{
Q_UNUSED(viewManager);
KisPaintDeviceSP clip = KisClipboard::instance()->clip(QRect(), true);
if (!clip) return;
QRect rect = clip->exactBounds();
if (rect.isEmpty()) return;
KisDocument *doc = KisPart::instance()->createDocument();
KisImageSP image = new KisImage(doc->createUndoStore(),
rect.width(),
rect.height(),
clip->colorSpace(),
i18n("Pasted"));
KisPaintLayerSP layer =
new KisPaintLayer(image.data(), image->nextLayerName() + i18n("(pasted)"),
OPACITY_OPAQUE_U8, clip->colorSpace());
KisPainter::copyAreaOptimized(QPoint(), clip, layer->paintDevice(), rect);
image->addNode(layer.data(), image->rootLayer());
doc->setCurrentImage(image);
KisPart::instance()->addDocument(doc);
KisMainWindow *win = viewManager->mainWindow();
win->addViewAndNotifyLoadingCompleted(doc);
}
void KisInvertSelectionOperation::runFromXML(KisViewManager* view, const KisOperationConfiguration& config)
{
KisSelectionFilter* filter = new KisInvertSelectionFilter();
runFilter(filter, view, config);
}
void KisSelectionToVectorActionFactory::run(KisViewManager *view)
{
KisSelectionSP selection = view->selection();
if (selection->hasShapeSelection() ||
!selection->outlineCacheValid()) {
return;
}
QPainterPath selectionOutline = selection->outlineCache();
QTransform transform = view->canvasBase()->coordinatesConverter()->imageToDocumentTransform();
KoShape *shape = KoPathShape::createShapeFromPainterPath(transform.map(selectionOutline));
shape->setShapeId(KoPathShapeId);
/**
* Mark a shape that it belongs to a shape selection
*/
if(!shape->userData()) {
shape->setUserData(new KisShapeSelectionMarker);
}
KisProcessingApplicator *ap = beginAction(view, kundo2_i18n("Convert to Vector Selection"));
ap->applyCommand(view->canvasBase()->shapeController()->addShape(shape),
KisStrokeJobData::SEQUENTIAL,
KisStrokeJobData::EXCLUSIVE);
endAction(ap, KisOperationConfiguration(id()).toXML());
}
void KisShapesToVectorSelectionActionFactory::run(KisViewManager* view)
{
const QList originalShapes = view->canvasBase()->shapeManager()->selection()->selectedShapes();
QList clonedShapes;
Q_FOREACH (KoShape *shape, originalShapes) {
clonedShapes << shape->cloneShape();
}
KisSelectionToolHelper helper(view->canvasBase(), kundo2_i18n("Convert shapes to vector selection"));
helper.addSelectionShapes(clonedShapes);
}
void KisSelectionToShapeActionFactory::run(KisViewManager *view)
{
KisSelectionSP selection = view->selection();
if (!selection->outlineCacheValid()) {
return;
}
QPainterPath selectionOutline = selection->outlineCache();
QTransform transform = view->canvasBase()->coordinatesConverter()->imageToDocumentTransform();
KoShape *shape = KoPathShape::createShapeFromPainterPath(transform.map(selectionOutline));
shape->setShapeId(KoPathShapeId);
KoColor fgColor = view->canvasBase()->resourceManager()->resource(KoCanvasResourceManager::ForegroundColor).value();
KoShapeStrokeSP border(new KoShapeStroke(1.0, fgColor.toQColor()));
shape->setStroke(border);
view->document()->shapeController()->addShape(shape);
}
void KisStrokeSelectionActionFactory::run(KisViewManager *view, StrokeSelectionOptions params)
{
KisImageWSP image = view->image();
if (!image) {
return;
}
KisSelectionSP selection = view->selection();
if (!selection) {
return;
}
int size = params.lineSize;
KisPixelSelectionSP pixelSelection = selection->projection();
if (!pixelSelection->outlineCacheValid()) {
pixelSelection->recalculateOutlineCache();
}
QPainterPath outline = pixelSelection->outlineCache();
QColor color = params.color.toQColor();
KisNodeSP currentNode = view->resourceProvider()->resourceManager()->resource(KisCanvasResourceProvider::CurrentKritaNode).value();
if (!currentNode->inherits("KisShapeLayer") && currentNode->childCount() == 0) {
KoCanvasResourceManager * rManager = view->resourceProvider()->resourceManager();
KisPainter::StrokeStyle strokeStyle = KisPainter::StrokeStyleBrush;
KisPainter::FillStyle fillStyle = params.fillStyle();
KisFigurePaintingToolHelper helper(kundo2_i18n("Draw Polyline"),
image,
currentNode,
rManager ,
strokeStyle,
fillStyle);
helper.setFGColorOverride(params.color);
helper.setSelectionOverride(0);
QPen pen(Qt::red, size);
pen.setJoinStyle(Qt::RoundJoin);
if (fillStyle != KisPainter::FillStyleNone) {
helper.paintPainterPathQPenFill(outline, pen, params.fillColor);
}
else {
helper.paintPainterPathQPen(outline, pen, params.fillColor);
}
}
else {
QTransform transform = view->canvasBase()->coordinatesConverter()->imageToDocumentTransform();
KoShape *shape = KoPathShape::createShapeFromPainterPath(transform.map(outline));
shape->setShapeId(KoPathShapeId);
KoShapeStrokeSP border(new KoShapeStroke(size, color));
shape->setStroke(border);
view->document()->shapeController()->addShape(shape);
}
image->setModified();
}
void KisStrokeBrushSelectionActionFactory::run(KisViewManager *view, StrokeSelectionOptions params)
{
KisImageWSP image = view->image();
if (!image) {
return;
}
KisSelectionSP selection = view->selection();
if (!selection) {
return;
}
KisPixelSelectionSP pixelSelection = selection->projection();
if (!pixelSelection->outlineCacheValid()) {
pixelSelection->recalculateOutlineCache();
}
KisNodeSP currentNode = view->resourceProvider()->resourceManager()->resource(KisCanvasResourceProvider::CurrentKritaNode).value();
if (!currentNode->inherits("KisShapeLayer") && currentNode->childCount() == 0)
{
KoCanvasResourceManager * rManager = view->resourceProvider()->resourceManager();
QPainterPath outline = pixelSelection->outlineCache();
KisPainter::StrokeStyle strokeStyle = KisPainter::StrokeStyleBrush;
KisPainter::FillStyle fillStyle = KisPainter::FillStyleNone;
KoColor color = params.color;
KisFigurePaintingToolHelper helper(kundo2_i18n("Draw Polyline"),
image,
currentNode,
rManager ,
strokeStyle,
fillStyle);
helper.setFGColorOverride(color);
helper.setSelectionOverride(0);
helper.paintPainterPath(outline);
image->setModified();
}
}
diff --git a/libs/ui/brushhud/kis_brush_hud.cpp b/libs/ui/brushhud/kis_brush_hud.cpp
index 94a87b37ed..d0265c2186 100644
--- a/libs/ui/brushhud/kis_brush_hud.cpp
+++ b/libs/ui/brushhud/kis_brush_hud.cpp
@@ -1,270 +1,275 @@
/*
* 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_brush_hud.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_uniform_paintop_property.h"
#include "kis_slider_based_paintop_property.h"
#include "kis_uniform_paintop_property_widget.h"
#include "kis_canvas_resource_provider.h"
#include "kis_paintop_preset.h"
#include "kis_paintop_settings.h"
#include "kis_signal_auto_connection.h"
#include "kis_paintop_settings_update_proxy.h"
#include "kis_icon_utils.h"
#include "kis_dlg_brush_hud_config.h"
#include "kis_brush_hud_properties_config.h"
#include "kis_elided_label.h"
#include "kis_debug.h"
struct KisBrushHud::Private
{
QPointer lblPresetName;
QPointer lblPresetIcon;
QPointer wdgProperties;
QPointer wdgPropertiesArea;
QPointer propertiesLayout;
QPointer btnConfigure;
KisCanvasResourceProvider *provider;
KisSignalAutoConnectionsStore connections;
KisSignalAutoConnectionsStore presetConnections;
KisPaintOpPresetSP currentPreset;
};
KisBrushHud::KisBrushHud(KisCanvasResourceProvider *provider, QWidget *parent)
: QWidget(parent, Qt::FramelessWindowHint),
m_d(new Private)
{
m_d->provider = provider;
QVBoxLayout *layout = new QVBoxLayout();
QHBoxLayout *labelLayout = new QHBoxLayout();
m_d->lblPresetIcon = new QLabel(this);
const QSize iconSize = QSize(22,22) * qApp->devicePixelRatio();
m_d->lblPresetIcon->setMinimumSize(iconSize);
m_d->lblPresetIcon->setMaximumSize(iconSize);
m_d->lblPresetIcon->setScaledContents(true);
m_d->lblPresetName = new KisElidedLabel("", Qt::ElideMiddle, this);
m_d->btnConfigure = new QToolButton(this);
m_d->btnConfigure->setAutoRaise(true);
m_d->btnConfigure->setIcon(KisIconUtils::loadIcon("applications-system"));
connect(m_d->btnConfigure, SIGNAL(clicked()), SLOT(slotConfigBrushHud()));
labelLayout->addWidget(m_d->lblPresetIcon);
labelLayout->addWidget(m_d->lblPresetName);
labelLayout->addWidget(m_d->btnConfigure);
layout->addLayout(labelLayout);
m_d->wdgPropertiesArea = new QScrollArea(this);
m_d->wdgPropertiesArea->setAlignment(Qt::AlignLeft | Qt::AlignTop);
m_d->wdgPropertiesArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_d->wdgPropertiesArea->setWidgetResizable(true);
m_d->wdgProperties = new QWidget(this);
m_d->propertiesLayout = new QVBoxLayout(this);
m_d->propertiesLayout->setSpacing(0);
m_d->propertiesLayout->setContentsMargins(0, 0, 22, 0);
m_d->propertiesLayout->setSizeConstraint(QLayout::SetMinimumSize);
// not adding any widgets until explicitly requested
m_d->wdgProperties->setLayout(m_d->propertiesLayout);
m_d->wdgPropertiesArea->setWidget(m_d->wdgProperties);
layout->addWidget(m_d->wdgPropertiesArea);
setLayout(layout);
setCursor(Qt::ArrowCursor);
+
+ // Prevent tablet events from being captured by the canvas
+ setAttribute(Qt::WA_NoMousePropagation, true);
}
KisBrushHud::~KisBrushHud()
{
}
QSize KisBrushHud::sizeHint() const
{
QSize size = QWidget::sizeHint();
return QSize(size.width(), parentWidget()->height());
}
void KisBrushHud::slotReloadProperties()
{
m_d->presetConnections.clear();
clearProperties();
updateProperties();
}
void KisBrushHud::clearProperties() const
{
while (m_d->propertiesLayout->count()) {
QLayoutItem *item = m_d->propertiesLayout->takeAt(0);
QWidget *w = item->widget();
if (w) {
w->deleteLater();
}
delete item;
}
m_d->currentPreset.clear();
}
void KisBrushHud::updateProperties()
{
KisPaintOpPresetSP preset = m_d->provider->currentPreset();
if (preset == m_d->currentPreset) return;
m_d->presetConnections.clear();
clearProperties();
m_d->currentPreset = preset;
m_d->presetConnections.addConnection(
m_d->currentPreset->updateProxy(), SIGNAL(sigUniformPropertiesChanged()),
this, SLOT(slotReloadProperties()));
m_d->lblPresetIcon->setPixmap(QPixmap::fromImage(preset->image()));
m_d->lblPresetName->setLongText(preset->name());
QList properties;
{
QList allProperties = preset->uniformProperties();
QList discardedProperties;
KisBrushHudPropertiesConfig cfg;
cfg.filterProperties(preset->paintOp().id(),
allProperties,
&properties,
&discardedProperties);
}
Q_FOREACH(auto property, properties) {
QWidget *w = 0;
if (!property->isVisible()) continue;
if (property->type() == KisUniformPaintOpProperty::Int) {
w = new KisUniformPaintOpPropertyIntSlider(property, m_d->wdgProperties);
} else if (property->type() == KisUniformPaintOpProperty::Double) {
w = new KisUniformPaintOpPropertyDoubleSlider(property, m_d->wdgProperties);
} else if (property->type() == KisUniformPaintOpProperty::Bool) {
w = new KisUniformPaintOpPropertyCheckBox(property, m_d->wdgProperties);
} else if (property->type() == KisUniformPaintOpProperty::Combo) {
w = new KisUniformPaintOpPropertyComboBox(property, m_d->wdgProperties);
}
if (w) {
w->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
m_d->propertiesLayout->addWidget(w);
}
}
m_d->propertiesLayout->addStretch();
}
void KisBrushHud::showEvent(QShowEvent *event)
{
m_d->connections.clear();
m_d->connections.addUniqueConnection(
m_d->provider->resourceManager(), SIGNAL(canvasResourceChanged(int, QVariant)),
this, SLOT(slotCanvasResourceChanged(int, QVariant)));
updateProperties();
QWidget::showEvent(event);
}
void KisBrushHud::hideEvent(QHideEvent *event)
{
m_d->connections.clear();
QWidget::hideEvent(event);
clearProperties();
}
void KisBrushHud::slotCanvasResourceChanged(int key, const QVariant &resource)
{
Q_UNUSED(resource);
if (key == KisCanvasResourceProvider::CurrentPaintOpPreset) {
updateProperties();
}
}
void KisBrushHud::paintEvent(QPaintEvent *event)
{
QColor bgColor = palette().color(QPalette::Window);
QPainter painter(this);
painter.fillRect(rect() & event->rect(), bgColor);
painter.end();
QWidget::paintEvent(event);
}
bool KisBrushHud::event(QEvent *event)
{
switch (event->type()) {
case QEvent::TabletPress:
case QEvent::TabletMove:
case QEvent::TabletRelease:
+ // Allow the tablet event to be translated to a mouse event on certain platforms
+ break;
case QEvent::MouseButtonPress:
case QEvent::MouseMove:
case QEvent::MouseButtonRelease:
case QEvent::Wheel:
event->accept();
return true;
default:
break;
}
return QWidget::event(event);
}
void KisBrushHud::slotConfigBrushHud()
{
if (!m_d->currentPreset) return;
KisDlgConfigureBrushHud dlg(m_d->currentPreset);
dlg.exec();
slotReloadProperties();
}
diff --git a/libs/ui/canvas/kis_coordinates_converter.cpp b/libs/ui/canvas/kis_coordinates_converter.cpp
index b8329a97a6..36f6aa4805 100644
--- a/libs/ui/canvas/kis_coordinates_converter.cpp
+++ b/libs/ui/canvas/kis_coordinates_converter.cpp
@@ -1,441 +1,441 @@
/*
* Copyright (c) 2010 Dmitry Kazakov
* Copyright (c) 2011 Silvio Heinrich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include "kis_coordinates_converter.h"
#include
#include
#include
#include
struct KisCoordinatesConverter::Private {
Private():
isXAxisMirrored(false), isYAxisMirrored(false), rotationAngle(0.0) { }
KisImageWSP image;
bool isXAxisMirrored;
bool isYAxisMirrored;
qreal rotationAngle;
QSizeF canvasWidgetSize;
QPointF documentOffset;
QTransform flakeToWidget;
QTransform imageToDocument;
QTransform documentToFlake;
QTransform widgetToViewport;
};
/**
* When vastScrolling value is less than 0.5 it is possible
* that the whole scrolling area (viewport) will be smaller than
* the size of the widget. In such cases the image should be
* centered in the widget. Previously we used a special parameter
* documentOrigin for this purpose, now the value for this
* centering is calculated dynamically, helping the offset to
* center the image inside the widget
*
* Note that the correction is null when the size of the document
* plus vast scrolling reserve is larger than the widget. This
* is always true for vastScrolling parameter > 0.5.
*/
QPointF KisCoordinatesConverter::centeringCorrection() const
{
KisConfig cfg;
QSize documentSize = imageRectInWidgetPixels().toAlignedRect().size();
QPointF dPoint(documentSize.width(), documentSize.height());
QPointF wPoint(m_d->canvasWidgetSize.width(), m_d->canvasWidgetSize.height());
QPointF minOffset = -cfg.vastScrolling() * wPoint;
QPointF maxOffset = dPoint - wPoint + cfg.vastScrolling() * wPoint;
QPointF range = maxOffset - minOffset;
range.rx() = qMin(range.x(), (qreal)0.0);
range.ry() = qMin(range.y(), (qreal)0.0);
range /= 2;
return -range;
}
/**
* The document offset and the position of the top left corner of the
* image must always coincide, that is why we need to correct them to
* and fro.
*
* When we change zoom level, the calculation of the new offset is
* done by KoCanvasControllerWidget, that is why we just passively fix
* the flakeToWidget transform to conform the offset and wait until
* the canvas controller will recenter us.
*
* But when we do our own transformations of the canvas, like rotation
* and mirroring, we cannot rely on the centering of the canvas
* controller and we do it ourselves. Then we just set new offset and
* return its value to be set in the canvas controller explicitly.
*/
void KisCoordinatesConverter::correctOffsetToTransformation()
{
m_d->documentOffset = -(imageRectInWidgetPixels().topLeft() -
centeringCorrection()).toPoint();
}
void KisCoordinatesConverter::correctTransformationToOffset()
{
QPointF topLeft = imageRectInWidgetPixels().topLeft();
QPointF diff = (-topLeft) - m_d->documentOffset;
diff += centeringCorrection();
m_d->flakeToWidget *= QTransform::fromTranslate(diff.x(), diff.y());
}
void KisCoordinatesConverter::recalculateTransformations()
{
if(!m_d->image) return;
m_d->imageToDocument = QTransform::fromScale(1 / m_d->image->xRes(),
1 / m_d->image->yRes());
qreal zoomX, zoomY;
KoZoomHandler::zoom(&zoomX, &zoomY);
m_d->documentToFlake = QTransform::fromScale(zoomX, zoomY);
correctTransformationToOffset();
QRectF irect = imageRectInWidgetPixels();
QRectF wrect = QRectF(QPoint(0,0), m_d->canvasWidgetSize);
QRectF rrect = irect & wrect;
QTransform reversedTransform = flakeToWidgetTransform().inverted();
QRectF canvasBounds = reversedTransform.mapRect(rrect);
QPointF offset = canvasBounds.topLeft();
m_d->widgetToViewport = reversedTransform * QTransform::fromTranslate(-offset.x(), -offset.y());
}
KisCoordinatesConverter::KisCoordinatesConverter()
: m_d(new Private) { }
KisCoordinatesConverter::~KisCoordinatesConverter()
{
delete m_d;
}
void KisCoordinatesConverter::setCanvasWidgetSize(QSize size)
{
m_d->canvasWidgetSize = size;
recalculateTransformations();
}
void KisCoordinatesConverter::setImage(KisImageWSP image)
{
m_d->image = image;
recalculateTransformations();
}
void KisCoordinatesConverter::setDocumentOffset(const QPoint& offset)
{
QPointF diff = m_d->documentOffset - offset;
m_d->documentOffset = offset;
m_d->flakeToWidget *= QTransform::fromTranslate(diff.x(), diff.y());
recalculateTransformations();
}
QPoint KisCoordinatesConverter::documentOffset() const
{
return QPoint(int(m_d->documentOffset.x()), int(m_d->documentOffset.y()));
}
qreal KisCoordinatesConverter::rotationAngle() const
{
return m_d->rotationAngle;
}
void KisCoordinatesConverter::setZoom(qreal zoom)
{
KoZoomHandler::setZoom(zoom);
recalculateTransformations();
}
qreal KisCoordinatesConverter::effectiveZoom() const
{
qreal scaleX, scaleY;
this->imageScale(&scaleX, &scaleY);
if (scaleX != scaleY) {
qWarning() << "WARNING: Zoom is not isotropic!" << ppVar(scaleX) << ppVar(scaleY) << ppVar(qFuzzyCompare(scaleX, scaleY));
}
// zoom by average of x and y
return 0.5 * (scaleX + scaleY);
}
QPoint KisCoordinatesConverter::rotate(QPointF center, qreal angle)
{
QTransform rot;
rot.rotate(angle);
m_d->flakeToWidget *= QTransform::fromTranslate(-center.x(),-center.y());
m_d->flakeToWidget *= rot;
m_d->flakeToWidget *= QTransform::fromTranslate(center.x(), center.y());
m_d->rotationAngle = std::fmod(m_d->rotationAngle + angle, 360.0);
correctOffsetToTransformation();
recalculateTransformations();
return m_d->documentOffset.toPoint();
}
QPoint KisCoordinatesConverter::mirror(QPointF center, bool mirrorXAxis, bool mirrorYAxis)
{
bool keepOrientation = false; // XXX: Keep here for now, maybe some day we can restore the parameter again.
bool doXMirroring = m_d->isXAxisMirrored ^ mirrorXAxis;
bool doYMirroring = m_d->isYAxisMirrored ^ mirrorYAxis;
qreal scaleX = doXMirroring ? -1.0 : 1.0;
qreal scaleY = doYMirroring ? -1.0 : 1.0;
QTransform mirror = QTransform::fromScale(scaleX, scaleY);
QTransform rot;
rot.rotate(m_d->rotationAngle);
m_d->flakeToWidget *= QTransform::fromTranslate(-center.x(),-center.y());
if (keepOrientation) {
m_d->flakeToWidget *= rot.inverted();
}
m_d->flakeToWidget *= mirror;
if (keepOrientation) {
m_d->flakeToWidget *= rot;
}
m_d->flakeToWidget *= QTransform::fromTranslate(center.x(),center.y());
if (!keepOrientation && (doXMirroring ^ doYMirroring)) {
m_d->rotationAngle = -m_d->rotationAngle;
}
m_d->isXAxisMirrored = mirrorXAxis;
m_d->isYAxisMirrored = mirrorYAxis;
correctOffsetToTransformation();
recalculateTransformations();
return m_d->documentOffset.toPoint();
}
bool KisCoordinatesConverter::xAxisMirrored() const
{
return m_d->isXAxisMirrored;
}
bool KisCoordinatesConverter::yAxisMirrored() const
{
return m_d->isYAxisMirrored;
}
QPoint KisCoordinatesConverter::resetRotation(QPointF center)
{
QTransform rot;
rot.rotate(-m_d->rotationAngle);
m_d->flakeToWidget *= QTransform::fromTranslate(-center.x(), -center.y());
m_d->flakeToWidget *= rot;
m_d->flakeToWidget *= QTransform::fromTranslate(center.x(), center.y());
m_d->rotationAngle = 0.0;
correctOffsetToTransformation();
recalculateTransformations();
return m_d->documentOffset.toPoint();
}
QTransform KisCoordinatesConverter::imageToWidgetTransform() const{
return m_d->imageToDocument * m_d->documentToFlake * m_d->flakeToWidget;
}
QTransform KisCoordinatesConverter::imageToDocumentTransform() const {
return m_d->imageToDocument;
}
QTransform KisCoordinatesConverter::documentToFlakeTransform() const {
return m_d->documentToFlake;
}
QTransform KisCoordinatesConverter::flakeToWidgetTransform() const {
return m_d->flakeToWidget;
}
QTransform KisCoordinatesConverter::documentToWidgetTransform() const
{
return m_d->documentToFlake * m_d->flakeToWidget;
}
QTransform KisCoordinatesConverter::viewportToWidgetTransform() const {
return m_d->widgetToViewport.inverted();
}
QTransform KisCoordinatesConverter::imageToViewportTransform() const {
return m_d->imageToDocument * m_d->documentToFlake * m_d->flakeToWidget * m_d->widgetToViewport;
}
void KisCoordinatesConverter::getQPainterCheckersInfo(QTransform *transform,
QPointF *brushOrigin,
- QPolygonF *polygon) const
+ QPolygonF *polygon,
+ const bool scrollCheckers) const
{
/**
* Qt has different rounding for QPainter::drawRect/drawImage.
* The image is rounded mathematically, while rect in aligned
* to the next integer. That causes transparent line appear on
* the canvas.
*
* See: https://bugreports.qt.nokia.com/browse/QTBUG-22827
*/
QRectF imageRect = imageRectInViewportPixels();
imageRect.adjust(0,0,-0.5,-0.5);
- KisConfig cfg;
- if (cfg.scrollCheckers()) {
+ if (scrollCheckers) {
*transform = viewportToWidgetTransform();
*polygon = imageRect;
*brushOrigin = imageToViewport(QPointF(0,0));
}
else {
*transform = QTransform();
*polygon = viewportToWidgetTransform().map(imageRect);
*brushOrigin = QPoint(0,0);
}
}
void KisCoordinatesConverter::getOpenGLCheckersInfo(const QRectF &viewportRect,
QTransform *textureTransform,
QTransform *modelTransform,
QRectF *textureRect,
QRectF *modelRect,
const bool scrollCheckers) const
{
if(scrollCheckers) {
*textureTransform = QTransform();
*textureRect = QRectF(0, 0, viewportRect.width(),viewportRect.height());
}
else {
*textureTransform = viewportToWidgetTransform();
*textureRect = viewportRect;
}
*modelTransform = viewportToWidgetTransform();
*modelRect = viewportRect;
}
QPointF KisCoordinatesConverter::imageCenterInWidgetPixel() const
{
if(!m_d->image)
return QPointF();
QPolygonF poly = imageToWidget(QPolygon(m_d->image->bounds()));
return (poly[0] + poly[1] + poly[2] + poly[3]) / 4.0;
}
// these functions return a bounding rect if the canvas is rotated
QRectF KisCoordinatesConverter::imageRectInWidgetPixels() const
{
if(!m_d->image) return QRectF();
return imageToWidget(m_d->image->bounds());
}
QRectF KisCoordinatesConverter::imageRectInViewportPixels() const
{
if(!m_d->image) return QRectF();
return imageToViewport(m_d->image->bounds());
}
QRect KisCoordinatesConverter::imageRectInImagePixels() const
{
if(!m_d->image) return QRect();
return m_d->image->bounds();
}
QRectF KisCoordinatesConverter::imageRectInDocumentPixels() const
{
if(!m_d->image) return QRectF();
return imageToDocument(m_d->image->bounds());
}
QSizeF KisCoordinatesConverter::imageSizeInFlakePixels() const
{
if(!m_d->image) return QSizeF();
qreal scaleX, scaleY;
imageScale(&scaleX, &scaleY);
QSize imageSize = m_d->image->size();
return QSizeF(imageSize.width() * scaleX, imageSize.height() * scaleY);
}
QRectF KisCoordinatesConverter::widgetRectInFlakePixels() const
{
return widgetToFlake(QRectF(QPoint(0,0), m_d->canvasWidgetSize));
}
QPointF KisCoordinatesConverter::flakeCenterPoint() const
{
QRectF widgetRect = widgetRectInFlakePixels();
return QPointF(widgetRect.left() + widgetRect.width() / 2,
widgetRect.top() + widgetRect.height() / 2);
}
QPointF KisCoordinatesConverter::widgetCenterPoint() const
{
return QPointF(m_d->canvasWidgetSize.width() / 2.0, m_d->canvasWidgetSize.height() / 2.0);
}
void KisCoordinatesConverter::imageScale(qreal *scaleX, qreal *scaleY) const
{
if(!m_d->image) {
*scaleX = 1.0;
*scaleY = 1.0;
return;
}
// get the x and y zoom level of the canvas
qreal zoomX, zoomY;
KoZoomHandler::zoom(&zoomX, &zoomY);
// Get the KisImage resolution
qreal resX = m_d->image->xRes();
qreal resY = m_d->image->yRes();
// Compute the scale factors
*scaleX = zoomX / resX;
*scaleY = zoomY / resY;
}
diff --git a/libs/ui/canvas/kis_coordinates_converter.h b/libs/ui/canvas/kis_coordinates_converter.h
index 803a5d94bd..e7ce76b2c9 100644
--- a/libs/ui/canvas/kis_coordinates_converter.h
+++ b/libs/ui/canvas/kis_coordinates_converter.h
@@ -1,162 +1,163 @@
/*
* Copyright (c) 2010 Dmitry Kazakov
* Copyright (c) 2011 Silvio Heinrich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef KIS_COORDINATES_CONVERTER_H
#define KIS_COORDINATES_CONVERTER_H
#include
#include
#include "kritaui_export.h"
#include "kis_types.h"
#define EPSILON 1e-6
#define SCALE_LESS_THAN(scX, scY, value) \
(scX < (value) - EPSILON && scY < (value) - EPSILON)
#define SCALE_MORE_OR_EQUAL_TO(scX, scY, value) \
(scX > (value) - EPSILON && scY > (value) - EPSILON)
namespace _Private
{
template struct Traits
{
typedef T Result;
static T map(const QTransform& transform, const T& obj) { return transform.map(obj); }
};
template<> struct Traits
{
typedef QRectF Result;
static QRectF map(const QTransform& transform, const QRectF& rc) { return transform.mapRect(rc); }
};
template<> struct Traits: public Traits { };
template<> struct Traits: public Traits { };
template<> struct Traits: public Traits { };
template<> struct Traits: public Traits { };
}
class KRITAUI_EXPORT KisCoordinatesConverter: public KoZoomHandler
{
public:
KisCoordinatesConverter();
~KisCoordinatesConverter() override;
void setCanvasWidgetSize(QSize size);
void setImage(KisImageWSP image);
void setDocumentOffset(const QPoint &offset);
QPoint documentOffset() const;
qreal rotationAngle() const;
QPoint rotate(QPointF center, qreal angle);
QPoint mirror(QPointF center, bool mirrorXAxis, bool mirrorYAxis);
bool xAxisMirrored() const;
bool yAxisMirrored() const;
QPoint resetRotation(QPointF center);
void setZoom(qreal zoom) override;
/**
* A composition of to scale methods: zoom level + image resolution
*/
qreal effectiveZoom() const;
template typename _Private::Traits::Result
imageToViewport(const T& obj) const { return _Private::Traits::map(imageToViewportTransform(), obj); }
template typename _Private::Traits::Result
viewportToImage(const T& obj) const { return _Private::Traits::map(imageToViewportTransform().inverted(), obj); }
template typename _Private::Traits::Result
flakeToWidget(const T& obj) const { return _Private::Traits::map(flakeToWidgetTransform(), obj); }
template typename _Private::Traits::Result
widgetToFlake(const T& obj) const { return _Private::Traits::map(flakeToWidgetTransform().inverted(), obj); }
template typename _Private::Traits::Result
widgetToViewport(const T& obj) const { return _Private::Traits::map(viewportToWidgetTransform().inverted(), obj); }
template typename _Private::Traits::Result
viewportToWidget(const T& obj) const { return _Private::Traits::map(viewportToWidgetTransform(), obj); }
template typename _Private::Traits::Result
documentToWidget(const T& obj) const { return _Private::Traits::map(documentToWidgetTransform(), obj); }
template typename _Private::Traits::Result
widgetToDocument(const T& obj) const { return _Private::Traits::map(documentToWidgetTransform().inverted(), obj); }
template typename _Private::Traits::Result
imageToDocument(const T& obj) const { return _Private::Traits::map(imageToDocumentTransform(), obj); }
template typename _Private::Traits::Result
documentToImage(const T& obj) const { return _Private::Traits::map(imageToDocumentTransform().inverted(), obj); }
template typename _Private::Traits