MauiKit Image Tools

code/modules/editor/src/controls/ImageEditor.qml
1import QtQuick
2import QtQuick.Controls
3import QtQuick.Layouts
4import QtQuick.Effects
5
6import org.mauikit.controls as Maui
7import org.mauikit.imagetools.editor as ITE
8
9import "private" as Private
10
11
12/**
13 * @inherit org::mauikit::controls::Page
14 * @brief A control with different tools for editingan image
15 *
16 */
17Maui.Page
19 id: control
20
21 property url url
22
23 readonly property bool ready : String(control.url).length
24
25 readonly property alias editor : imageDoc
26
27 headBar.visible: control.ready
28 headBar.background: null
29 headBar.leftContent: Button
30 {
31 icon.name: "edit-undo"
32 text: "Save"
33 enabled: imageDoc.edited
34 onClicked: imageDoc.undo()
35 }
36
37 headBar.rightContent: [
38
39 ToolButton
40 {
41 icon.name: "document-save-as"
42 enabled: imageDoc.edited
43 // onClicked: imageDoc.undo()
44 },
45
46 Button
47 {
48 Maui.Controls.status : Maui.Controls.Negative
49 text: i18n("Cancel")
50 }
51 ]
52
53 ITE.ImageItem
54 {
55 id: editImage
56 readonly property real ratioX: editImage.paintedWidth / editImage.nativeWidth;
57 readonly property real ratioY: editImage.paintedHeight / editImage.nativeHeight;
58
59 fillMode: Image.PreserveAspectFit
60 image: imageDoc.image
61 anchors.fill: parent
62 // anchors.margins: Maui.Style.space.medium
63 // anchors.bottomMargin: _editTools.height + Maui.Style.space.big*2
64
65 // rotation: _transBar.rotationSlider.value
66
67 ITE.ImageDocument
68 {
69 id: imageDoc
70 path: control.url
71 }
72
73 // KQuickImageEditor.SelectionTool
74 // {
75 // id: selectionTool
76 // visible: _transBar.cropButton.checked
77 // width: editImage.paintedWidth
78 // height: editImage.paintedHeight
79 // x: editImage.horizontalPadding
80 // y: editImage.verticalPadding
81
82 // KQuickImageEditor.CropBackground
83 // {
84 // anchors.fill: parent
85 // z: -1
86 // insideX: selectionTool.selectionX
87 // insideY: selectionTool.selectionY
88 // insideWidth: selectionTool.selectionWidth
89 // insideHeight: selectionTool.selectionHeight
90 // }
91 // Connections {
92 // target: selectionTool.selectionArea
93 // function onDoubleClicked() {
94 // control.crop()
95 // }
96 // }
97 // }
98
99 onImageChanged:
100 {
101 // selectionTool.selectionX = 0
102 // selectionTool.selectionY = 0
103 // selectionTool.selectionWidth = Qt.binding(() => selectionTool.width)
104 // selectionTool.selectionHeight = Qt.binding(() => selectionTool.height)
105 }
106
107
108 Canvas
109 {
110 visible: _transBar.rotationButton.checked
111 opacity: 0.15
112 anchors.fill : parent
113 property int wgrid: control.width / 20
114 onPaint: {
115 var ctx = getContext("2d")
116 ctx.lineWidth = 0.5
117 ctx.strokeStyle = Maui.Theme.textColor
118 ctx.beginPath()
119 var nrows = height/wgrid;
120 for(var i=0; i < nrows+1; i++){
121 ctx.moveTo(0, wgrid*i);
122 ctx.lineTo(width, wgrid*i);
123 }
124
125 var ncols = width/wgrid
126 for(var j=0; j < ncols+1; j++){
127 ctx.moveTo(wgrid*j, 0);
128 ctx.lineTo(wgrid*j, height);
129 }
130 ctx.closePath()
131 ctx.stroke()
132 }
133 }
134 }
135
136
137
138 Action
139 {
140 id: _colorsAction
141 icon.name: "color-mode-black-white"
142 text: i18nd("mauikitimagetools","Color")
143 checked: _actionsBarLoader.currentIndex === 0
144 onTriggered: _actionsBarLoader.currentIndex = 0
145 }
146
147 Action
148 {
149 id: _transfromAction
150 icon.name: "dialog-transform"
151 text: i18nd("mauikitimagetools","Transform")
152 checked: _actionsBarLoader.currentIndex === 1
153 onTriggered: _actionsBarLoader.currentIndex = 1
154 }
155
156 Action
157 {
158 id: _layerAction
159 icon.name: "layer-new"
160 text: i18nd("mauikitimagetools","Layer")
161 checked: _actionsBarLoader.currentIndex === 2
162 onTriggered: _actionsBarLoader.currentIndex = 2
163 }
164
165 Loader
166 {
167 id: _actionsBarLoader
168 property int currentIndex : -1
169 // active: settings.showActionsBar
170 visible: status == Loader.Ready
171 asynchronous: true
172 anchors.bottom: parent.bottom
173 anchors.horizontalCenter: parent.horizontalCenter
174 anchors.margins: Maui.Style.space.big
175
176 sourceComponent: Pane
177 {
178 id: _pane
179 Maui.Theme.colorSet: Maui.Theme.Complementary
180 Maui.Theme.inherit: false
181
182 // x: control.width - width - Maui.Style.space.big
183 // y: control.height - height - Maui.Style.space.big
184 background: Rectangle
185 {
186 radius: Maui.Style.radiusV
187 color: Maui.Theme.backgroundColor
188
189 layer.enabled: GraphicsInfo.api !== GraphicsInfo.Software
190 layer.effect: MultiEffect
191 {
192 autoPaddingEnabled: true
193 shadowEnabled: true
194 shadowColor: "#000000"
195 }
196 }
197
198 ScaleAnimator on scale
199 {
200 from: 0
201 to: 1
202 duration: Maui.Style.units.longDuration
203 running: visible
204 easing.type: Easing.OutInQuad
205 }
206
207 OpacityAnimator on opacity
208 {
209 from: 0
210 to: 1
211 duration: Maui.Style.units.longDuration
212 running: visible
213 }
214
215 contentItem: RowLayout
216 {
217 spacing: Maui.Style.defaultSpacing
218
219 ToolButton
220 {
221 icon.name: "edit-undo"
222 Layout.alignment: Qt.AlignVCenter
223 onClicked: imageDoc.undo()
224 checkable: false
225 enabled:imageDoc.edited
226 }
227
228 Item{}
229
230 Repeater
231 {
232
233 model: [_colorsAction, _transfromAction, _layerAction]
234
235 ToolButton
236 {
237 action: modelData
238 display: ToolButton.IconOnly
239 flat: false
240 }
241 }
242 Item{}
243
244 ToolButton
245 {
246 // text: i18nd("mauikitimagetools","Accept")
247 icon.name: "dialog-apply"
248 onClicked: imageDoc.applyChanges()
249 enabled: !imageDoc.changesApplied
250
251 }
252
253 }
254
255 DragHandler
256 {
257 target: _pane
258 // target: _actionsBarLoader
259 // grabPermissions: PointerHandler.TakeOverForbidden | PointerHandler.CanTakeOverFromAnything
260 xAxis.maximum: control.width - _pane.width
261 xAxis.minimum: 0
262
263 yAxis.enabled : false
264
265 onActiveChanged:
266 {
267 if(!active)
268 {
269 console.log(centroid.position, centroid.scenePosition, centroid.velocity.x)
270
271 let pos = centroid.velocity.x
272 _pane.x = Qt.binding(()=> { return pos < 0 ? Maui.Style.space.big : control.width - _pane.width - Maui.Style.space.big })
273 _pane.y = Qt.binding(()=> { return control.height - _pane.height - Maui.Style.space.big })
274 }
275 }
276 }
277 }
278 }
279
280
281
282 footBar.visible: false
283 footerColumn: [
284
285 Private.TransformationBar
286 {
287 id: _transBar
288 visible: _actionsBarLoader.currentIndex === 1 && control.ready
289 width: parent.width
290 },
291
292 Private.ColourBar
293 {
294 id: _colourBar
295 visible: _actionsBarLoader.currentIndex === 0 && control.ready
296 width: parent.width
297 }
298 ]
299
300
301 function crop() {
302 console.log("CROP")
303 imageDoc.crop(selectionTool.selectionX / editImage.ratioX,
304 selectionTool.selectionY / editImage.ratioY,
305 selectionTool.selectionWidth / editImage.ratioX,
306 selectionTool.selectionHeight / editImage.ratioY);
307 }
308}
bool visible
Q_SCRIPTABLE CaptureState status()
QString i18nd(const char *domain, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString path(const QString &relativePath)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 11 2025 11:57:09 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.