assetList.qml 15.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/***************************************************************************
 *   Copyright (C) 2017 by Nicolas Carion                                  *
 *   This file is part of Kdenlive. See www.kdenlive.org.                  *
 *                                                                         *
 *   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) version 3 or any later version accepted by the       *
 *   membership of KDE e.V. (or its successor approved  by the membership  *
 *   of KDE e.V.), which shall act as a proxy defined in Section 14 of     *
 *   version 3 of the license.                                             *
 *                                                                         *
 *   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, see <http://www.gnu.org/licenses/>. *
 ***************************************************************************/

22
import QtQuick 2.7
23
24
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.5
25
26
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.2
Nicolas Carion's avatar
Nicolas Carion committed
27
import QtQml.Models 2.2
28
29
30

Rectangle {
    id: listRoot
31
32
    SystemPalette { id: activePalette }
    color: activePalette.window
Nicolas Carion's avatar
Nicolas Carion committed
33
34

    function assetType(){
35
        return isEffectList ? i18n("effects") : i18n("compositions");
Nicolas Carion's avatar
Nicolas Carion committed
36
    }
37
38
39

    function expandNodes(indexes)  {
        for(var i = 0; i < indexes.length; i++) {
40
41
42
            if (indexes[i].valid) {
                treeView.expand(indexes[i]);
            }
43
44
        }
    }
45
46
47
48
49
50
51
52
53
54
55
56
    function rowPosition(model, index) {
        var pos = 0;
        for(var i = 0; i < index.parent.row; i++) {
            var catIndex = model.getCategory(i);
            if (treeView.isExpanded(catIndex)) {
                pos += model.rowCount(catIndex);
            }
            pos ++;
        }
        pos += index.row + 2;
        return pos;
    }
57

Nicolas Carion's avatar
Nicolas Carion committed
58
    ColumnLayout {
59
        anchors.fill: parent
60
        spacing: 0
Nicolas Carion's avatar
Nicolas Carion committed
61
62
63
        RowLayout {
            Layout.fillWidth: true
            Layout.fillHeight: false
64
            spacing: 4
Nicolas Carion's avatar
Nicolas Carion committed
65
            ExclusiveGroup { id: filterGroup}
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
66
67
68
69
70
71
72
73
74
75
76
77
78
79
            ToolButton {
                id: searchList
                iconName: "edit-find"
                checkable: true
                tooltip: isEffectList ? i18n('Find effect') : i18n('Find composition')
                onCheckedChanged: {
                    searchInput.visible = searchList.checked
                    searchInput.focus = searchList.checked
                    if (!searchList.checked) {
                        searchInput.text = ''
                        treeView.focus = true
                    }
                }
            }
Nicolas Carion's avatar
Nicolas Carion committed
80
81
82
83
84
            ToolButton {
                id: showAll
                iconName: "show-all-effects"
                checkable:true
                exclusiveGroup: filterGroup
85
                tooltip: i18n('Main %1', assetType())
86
                onClicked: {
Nicolas Carion's avatar
Nicolas Carion committed
87
                    assetlist.setFilterType("")
88
                }
89
            }
Nicolas Carion's avatar
Nicolas Carion committed
90
91
            ToolButton {
                id: showVideo
Nicolas Carion's avatar
Nicolas Carion committed
92
                visible: isEffectList
Nicolas Carion's avatar
Nicolas Carion committed
93
94
95
96
97
                iconName: "kdenlive-show-video"
                iconSource: 'qrc:///pics/kdenlive-show-video.svgz'
                checkable:true
                exclusiveGroup: filterGroup
                tooltip: i18n('Show all video effects')
98
                onClicked: {
Nicolas Carion's avatar
Nicolas Carion committed
99
                    assetlist.setFilterType("video")
100
                }
101
            }
Nicolas Carion's avatar
Nicolas Carion committed
102
103
            ToolButton {
                id: showAudio
Nicolas Carion's avatar
Nicolas Carion committed
104
                visible: isEffectList
Nicolas Carion's avatar
Nicolas Carion committed
105
106
107
108
109
                iconName: "kdenlive-show-audio"
                iconSource: 'qrc:///pics/kdenlive-show-audio.svgz'
                checkable:true
                exclusiveGroup: filterGroup
                tooltip: i18n('Show all audio effects')
110
                onClicked: {
Nicolas Carion's avatar
Nicolas Carion committed
111
                    assetlist.setFilterType("audio")
112
113
114
115
                }
            }
            ToolButton {
                id: showCustom
Nicolas Carion's avatar
Nicolas Carion committed
116
                visible: isEffectList
117
118
119
120
121
                iconName: "kdenlive-custom-effect"
                checkable:true
                exclusiveGroup: filterGroup
                tooltip: i18n('Show all custom effects')
                onClicked: {
Nicolas Carion's avatar
Nicolas Carion committed
122
                    assetlist.setFilterType("custom")
123
                }
Nicolas Carion's avatar
Nicolas Carion committed
124
            }
125
126
127
128
129
130
131
132
133
134
            ToolButton {
                id: showFavorites
                iconName: "favorite"
                checkable:true
                exclusiveGroup: filterGroup
                tooltip: i18n('Show favorite items')
                onClicked: {
                    assetlist.setFilterType("favorites")
                }
            }
135
136
137
138
139
140
141
142
143
            ToolButton {
                id: downloadTransitions
                visible: !isEffectList
                iconName: "edit-download"
                tooltip: i18n('Download New Wipes...')
                onClicked: {
                    assetlist.downloadNewLumas()
                }
            }
Nicolas Carion's avatar
Nicolas Carion committed
144
145
            Rectangle {
                //This is a spacer
146
                Layout.fillHeight: false
Nicolas Carion's avatar
Nicolas Carion committed
147
                Layout.fillWidth: true
148
                color: "transparent"
Nicolas Carion's avatar
Nicolas Carion committed
149
150
151
152
153
            }
            ToolButton {
                id: showDescription
                iconName: "help-about"
                checkable:true
Nicolas Carion's avatar
Nicolas Carion committed
154
                tooltip: i18n('Show/hide description of the ') + assetType()
155
                onCheckedChanged:{
156
                    assetlist.showDescription = checked
157
                }
158
                Component.onCompleted: checked = assetlist.showDescription
Nicolas Carion's avatar
Nicolas Carion committed
159
160
161
            }

        }
162
163
164
        TextField {
            id: searchInput
            Layout.fillWidth:true
165
            visible: false
Nicolas Carion's avatar
Nicolas Carion committed
166
167
            Image {
                id: clear
168
                source: 'image://icon/edit-clear'
169
170
                width: parent.height * 0.8
                height: width
Nicolas Carion's avatar
Nicolas Carion committed
171
172
173
174
                anchors { right: parent.right; rightMargin: 8; verticalCenter: parent.verticalCenter }
                opacity: 0
                MouseArea {
                    anchors.fill: parent
175
                    onClicked: { searchInput.text = ''; searchInput.focus = true; searchList.checked = false; }
Nicolas Carion's avatar
Nicolas Carion committed
176
177
178
                }
            }
            states: State {
179
                name: "hasText"; when: searchInput.text != ''
Nicolas Carion's avatar
Nicolas Carion committed
180
181
182
183
184
185
                PropertyChanges { target: clear; opacity: 1 }
            }

            transitions: [
                Transition {
                    from: ""; to: "hasText"
186
                    NumberAnimation { properties: "opacity" }
Nicolas Carion's avatar
Nicolas Carion committed
187
188
189
190
191
192
                },
                Transition {
                    from: "hasText"; to: ""
                    NumberAnimation { properties: "opacity" }
                }
            ]
Nicolas Carion's avatar
Nicolas Carion committed
193
            onTextChanged: {
194
                var current = sel.currentIndex
195
                var rowModelIndex = assetListModel.getModelIndex(sel.currentIndex);
Nicolas Carion's avatar
Nicolas Carion committed
196
                assetlist.setFilterName(text)
197
                if (text.length > 0) {
198
199
200
201
                    sel.setCurrentIndex(assetListModel.firstVisibleItem(current), ItemSelectionModel.ClearAndSelect)
                } else {
                    sel.clearCurrentIndex()
                    sel.setCurrentIndex(assetListModel.getProxyIndex(rowModelIndex), ItemSelectionModel.ClearAndSelect)
202
                }
203
204
                treeView.__listView.positionViewAtIndex(rowPosition(assetListModel, sel.currentIndex), ListView.Visible)
            }
205
            /*onEditingFinished: {
206
207
208
                if (!assetContextMenu.isDisplayed) {
                    searchList.checked = false
                }
209
            }*/
210
211
212
213
214
215
216
217
218
219
220
            Keys.onDownPressed: {
                sel.setCurrentIndex(assetListModel.getNextChild(sel.currentIndex), ItemSelectionModel.ClearAndSelect)
                treeView.expand(sel.currentIndex.parent)
                treeView.__listView.positionViewAtIndex(rowPosition(assetListModel, sel.currentIndex), ListView.Visible)
            }
            Keys.onUpPressed: {
                sel.setCurrentIndex(assetListModel.getPreviousChild(sel.currentIndex), ItemSelectionModel.ClearAndSelect)
                treeView.expand(sel.currentIndex.parent)
                treeView.__listView.positionViewAtIndex(rowPosition(assetListModel, sel.currentIndex), ListView.Visible)
            }
            Keys.onReturnPressed: {
221
222
223
224
                if (sel.hasSelection) {
                    assetlist.activate(sel.currentIndex)
                    searchList.checked = false
                }
Nicolas Carion's avatar
Nicolas Carion committed
225
226
227
228
            }
        }
        ItemSelectionModel {
            id: sel
Nicolas Carion's avatar
Nicolas Carion committed
229
            model: assetListModel
230
231
232
            onSelectionChanged: {
                assetDescription.text = assetlist.getDescription(sel.currentIndex)
            }
233
        }
234
235
236
237
        SplitView {
            orientation: Qt.Vertical
            Layout.fillHeight: true
            Layout.fillWidth: true
Nicolas Carion's avatar
Nicolas Carion committed
238
        TreeView {
239
            id: treeView
Nicolas Carion's avatar
Nicolas Carion committed
240
241
242
243
            Layout.fillHeight: true
            Layout.fillWidth: true
            alternatingRowColors: false
            headerVisible: false
244
245
246
            selection: sel
            selectionMode: SelectionMode.SingleSelection
            itemDelegate: Rectangle {
247
248
249
250
                id: assetDelegate
                // These anchors are important to allow "copy" dragging
                anchors.verticalCenter: parent ? parent.verticalCenter : undefined
                anchors.right: parent ? parent.right : undefined
251
                property bool isItem : styleData.value !== "root" && styleData.value !== ""
252
                property string mimeType : isItem ? assetlist.getMimeType(styleData.value) : ""
253
                height: assetText.implicitHeight
254
                color: dragArea.containsMouse ? activePalette.highlight : "transparent"
255
256
257
258

                Drag.active: isItem ? dragArea.drag.active : false
                Drag.dragType: Drag.Automatic
                Drag.supportedActions: Qt.CopyAction
259
260
261
262
                Drag.mimeData: isItem ? assetlist.getMimeData(styleData.value) : {}
                Drag.keys:[
                    isItem ? assetlist.getMimeType(styleData.value) : ""
                ]
263
264
265

                Row {
                    anchors.fill:parent
266
267
268
269
                    anchors.leftMargin: 1
                    anchors.topMargin: 1
                    anchors.bottomMargin: 1
                    spacing: 4
270
                    Image{
271
                        id: assetThumb
272
                        anchors.verticalCenter: parent.verticalCenter
273
                        visible: assetDelegate.isItem
274
                        property bool isFavorite: model == undefined || model.favorite === undefined ? false : model.favorite
275
                        height: parent.height * 0.8
276
                        width: height
277
278
279
                        source: 'image://asseticon/' + styleData.value
                    }
                    Label {
280
281
                        id: assetText
                        font.bold : assetThumb.isFavorite
282
283
                        text: assetlist.getName(styleData.index)
                    }
Nicolas Carion's avatar
Nicolas Carion committed
284
                }
285
286
                MouseArea {
                    id: dragArea
287
                    anchors.fill: assetDelegate
288
                    hoverEnabled: true
289
290
291
292
293
                    acceptedButtons: Qt.LeftButton | Qt.RightButton
                    drag.target: undefined
                    onReleased: {
                        drag.target = undefined
                    }
294
                    onPressed: {
295
296
                        if (assetDelegate.isItem) {
                            //sel.select(styleData.index, ItemSelectionModel.Select)
297
                            sel.setCurrentIndex(styleData.index, ItemSelectionModel.ClearAndSelect)
298
299
300
301
302
303
304
                            if (mouse.button === Qt.LeftButton) {
                                drag.target = parent
                                parent.grabToImage(function(result) {
                                    parent.Drag.imageSource = result.url
                                })
                            } else {
                                drag.target = undefined
305
                                assetContextMenu.isItemFavorite = assetThumb.isFavorite
306
                                assetContextMenu.popup()
307
                                mouse.accepted = false
308
                            }
309
                            console.log(parent.Drag.keys)
310
311
312
313
314
315
316
317
                        } else {
                            if (treeView.isExpanded(styleData.index)) {
                                treeView.collapse(styleData.index)
                            } else {
                                treeView.expand(styleData.index)
                            }

                        }
318
                        treeView.focus = true
319
                    }
320
321
322
323
324
                    onDoubleClicked: {
                        if (isItem) {
                            assetlist.activate(styleData.index)
                        }
                    }
Nicolas Carion's avatar
Nicolas Carion committed
325
326
                }
            }
327
328
            Menu {
                id: assetContextMenu
329
                property bool isItemFavorite
330
                property bool isDisplayed: false
331
332
                MenuItem {
                    id: favMenu
333
                    text: assetContextMenu.isItemFavorite ? "Remove from favorites" : "Add to favorites"
334
335
                    property url thumbSource
                    onTriggered: {
336
                        assetlist.setFavorite(sel.currentIndex, !assetContextMenu.isItemFavorite)
337
338
                    }
                }
339
340
341
342
343
344
                onAboutToShow: {
                    isDisplayed = true;
                }
                onAboutToHide: {
                    isDisplayed = false;
                }
345
            }
346

347
            TableViewColumn { role: "identifier"; title: "Name"; }
Nicolas Carion's avatar
Nicolas Carion committed
348
            model: assetListModel
349
350
351
352

            Keys.onDownPressed: {
                sel.setCurrentIndex(assetListModel.getNextChild(sel.currentIndex), ItemSelectionModel.ClearAndSelect)
                treeView.expand(sel.currentIndex.parent)
353
                treeView.__listView.positionViewAtIndex(rowPosition(assetListModel, sel.currentIndex), ListView.Visible)
354
355
356
357
            }
            Keys.onUpPressed: {
                sel.setCurrentIndex(assetListModel.getPreviousChild(sel.currentIndex), ItemSelectionModel.ClearAndSelect)
                treeView.expand(sel.currentIndex.parent)
358
                treeView.__listView.positionViewAtIndex(rowPosition(assetListModel, sel.currentIndex), ListView.Visible)
359
            }
360
361
362
363
364
            Keys.onReturnPressed: {
                if (sel.hasSelection) {
                    assetlist.activate(sel.currentIndex)
                }
            }
365

366
367
        }
        TextArea {
Nicolas Carion's avatar
Nicolas Carion committed
368
            id: assetDescription
369
            text: ""
370
            visible: showDescription.checked
371
            readOnly: true
372
373
            Layout.fillWidth: true
            states: State {
Nicolas Carion's avatar
Nicolas Carion committed
374
375
                name: "hasDescription"; when: assetDescription.text != '' && showDescription.checked
                PropertyChanges { target: assetDescription; visible: true}
376
            }
377
        }
378

379
380
381
        }
    }
}