Merge lp:~jonas-drange/ubuntu-settings-components/filepicker into lp:ubuntu-settings-components

Proposed by Jonas G. Drange on 2016-07-15
Status: Approved
Approved by: Ken VanDine on 2017-01-31
Approved revision: 167
Proposed branch: lp:~jonas-drange/ubuntu-settings-components/filepicker
Merge into: lp:ubuntu-settings-components
Diff against target: 1665 lines (+1174/-226)
27 files modified
debian/changelog (+6/-0)
debian/control (+1/-0)
examples/FilePickerComponent.qml (+91/-0)
plugins/Ubuntu/Settings/Components/CMakeLists.txt (+7/-0)
plugins/Ubuntu/Settings/Components/FilePicker.qml (+197/-0)
plugins/Ubuntu/Settings/Components/FilePickerProperties.qml (+22/-0)
plugins/Ubuntu/Settings/Components/filepickerhelper.cpp (+59/-0)
plugins/Ubuntu/Settings/Components/filepickerhelper.h (+36/-0)
plugins/Ubuntu/Settings/Components/plugin.cpp (+7/-0)
plugins/Ubuntu/Settings/Components/qmldir (+3/-0)
plugins/Ubuntu/Settings/Vpn/DialogFile.qml (+0/-176)
plugins/Ubuntu/Settings/Vpn/DialogFileProperties.qml (+0/-22)
plugins/Ubuntu/Settings/Vpn/FileSelector.qml (+7/-1)
plugins/Ubuntu/Settings/Vpn/VpnEditor.qml (+0/-7)
plugins/Ubuntu/Settings/Vpn/qmldir (+0/-4)
po/ubuntu-settings-components.pot (+28/-16)
tests/qmltests/CMakeLists.txt (+1/-0)
tests/qmltests/Components/tst_FilePicker.qml (+215/-0)
tests/qmltests/mocks/CMakeLists.txt (+1/-0)
tests/qmltests/mocks/Qt/CMakeLists.txt (+1/-0)
tests/qmltests/mocks/Qt/labs/CMakeLists.txt (+1/-0)
tests/qmltests/mocks/Qt/labs/folderlistmodel/CMakeLists.txt (+20/-0)
tests/qmltests/mocks/Qt/labs/folderlistmodel/MockFolderListModel.cpp (+241/-0)
tests/qmltests/mocks/Qt/labs/folderlistmodel/MockFolderListModel.h (+171/-0)
tests/qmltests/mocks/Qt/labs/folderlistmodel/plugin.cpp (+26/-0)
tests/qmltests/mocks/Qt/labs/folderlistmodel/plugin.h (+31/-0)
tests/qmltests/mocks/Qt/labs/folderlistmodel/qmldir (+2/-0)
To merge this branch: bzr merge lp:~jonas-drange/ubuntu-settings-components/filepicker
Reviewer Review Type Date Requested Status
Ken VanDine 2016-07-15 Approve on 2017-01-31
Lukáš Tinkl (community) Needs Information on 2016-07-18
PS Jenkins bot continuous-integration Pending
Review via email: mp+300180@code.launchpad.net

Commit Message

create file picker component for export

To post a comment you must log in.
Ken VanDine (ken-vandine) wrote :

One copyright question inline

review: Needs Information
Lukáš Tinkl (lukas-kde) wrote :

Two other minor points inline

review: Needs Information
Ken VanDine (ken-vandine) wrote :

Looks fine to me

review: Approve
Marco Trevisan (Treviño) (3v1n0) wrote :

Is this something we still want to land?

Jonas G. Drange (jonas-drange) wrote :

It's scheduled to land after silo 2078.

On 27 October 2016 at 18:16, Marco Trevisan (Treviño) <mail@3v1n0.net>
wrote:

> Is this something we still want to land?
> --
> https://code.launchpad.net/~jonas-drange/ubuntu-settings-
> components/filepicker/+merge/300180
> You are the owner of lp:~jonas-drange/ubuntu-settings-components/
> filepicker.
>

166. By Jonas G. Drange on 2017-01-24

bumps filepicker change

167. By Jonas G. Drange on 2017-01-25

syncs with trunk

Ken VanDine (ken-vandine) wrote :

I'll reviewed the commits since my last approval, looks fine.

review: Approve

Unmerged revisions

167. By Jonas G. Drange on 2017-01-25

syncs with trunk

166. By Jonas G. Drange on 2017-01-24

bumps filepicker change

165. By Jonas G. Drange on 2017-01-24

sync with trunk

164. By Jonas G. Drange on 2016-10-19

bump version

163. By Jonas G. Drange on 2016-10-19

drop bump

162. By Jonas G. Drange on 2016-10-19

merge trunk

161. By Jonas G. Drange on 2016-07-18

update pot

160. By Jonas G. Drange on 2016-07-18

address comments, use glib to format size

159. By Jonas G. Drange on 2016-07-18

update pot

158. By Jonas G. Drange on 2016-07-15

make file name elide in the middle

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2017-01-18 15:20:00 +0000
3+++ debian/changelog 2017-01-25 13:04:17 +0000
4@@ -1,3 +1,9 @@
5+ubuntu-settings-components (0.13+17.04.20170104-0ubuntu2) UNRELEASED; urgency=medium
6+
7+ * create file picker component for export
8+
9+ -- Jonas G. Drange <jonas.drange@canonical.com> Tue, 24 Jan 2017 15:01:25 +0100
10+
11 ubuntu-settings-components (0.12+17.04.20170118-0ubuntu1) zesty; urgency=medium
12
13 [ Pete Woods ]
14
15=== modified file 'debian/control'
16--- debian/control 2016-12-07 17:02:20 +0000
17+++ debian/control 2017-01-25 13:04:17 +0000
18@@ -5,6 +5,7 @@
19 Build-Depends: cmake,
20 cmake-extras (>= 0.10),
21 debhelper (>= 9),
22+ libglib2.0-dev (>= 2.37.92),
23 pkg-config,
24 python3:any,
25 qml-module-qt-labs-folderlistmodel,
26
27=== added file 'examples/FilePickerComponent.qml'
28--- examples/FilePickerComponent.qml 1970-01-01 00:00:00 +0000
29+++ examples/FilePickerComponent.qml 2017-01-25 13:04:17 +0000
30@@ -0,0 +1,91 @@
31+/*
32+ * Copyright 2016 Canonical Ltd.
33+ *
34+ * This program is free software; you can redistribute it and/or modify
35+ * it under the terms of the GNU Lesser General Public License as published by
36+ * the Free Software Foundation; version 3.
37+ *
38+ * This program is distributed in the hope that it will be useful,
39+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
40+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41+ * GNU Lesser General Public License for more details.
42+ *
43+ * You should have received a copy of the GNU Lesser General Public License
44+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
45+ *
46+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
47+ */
48+
49+import QtQuick 2.4
50+import Ubuntu.Components 1.3
51+import Ubuntu.Settings.Components 0.1
52+import Ubuntu.Components.Popups 1.3
53+
54+MainView {
55+ id: mainView
56+ // Note! applicationName needs to match the .desktop filename
57+ applicationName: "SettingsComponents"
58+
59+ width: units.gu(42)
60+ height: units.gu(75)
61+
62+ property var _diag
63+ property alias _accepted: acceptedLabel.acceptedPath
64+
65+ Component {
66+ id: fp
67+ FilePicker {
68+ onReject: {
69+ if (_diag) {
70+ PopupUtils.close(_diag)
71+ }
72+ _accepted = ""
73+ }
74+ onAccept: {
75+ _accepted = path
76+ if (_diag) {
77+ PopupUtils.close(_diag)
78+ }
79+ }
80+ }
81+ }
82+
83+ Page {
84+ header: PageHeader {
85+ id: pageHeader
86+ title: "FilePicker"
87+ }
88+
89+ Column {
90+ spacing: units.gu(2)
91+ anchors {
92+ top: pageHeader.bottom
93+ left: parent.left
94+ right: parent.right
95+ bottom: parent.bottom
96+ margins: units.gu(2)
97+ }
98+
99+ Button {
100+ anchors { left: parent.left; right: parent.right }
101+ text: i18n.tr("Select dark theme")
102+ onClicked: theme.name = "Ubuntu.Components.Themes.SuruDark"
103+ }
104+
105+ Button {
106+ anchors { left: parent.left; right: parent.right }
107+ text: i18n.tr("Open file picker")
108+ onClicked: _diag = PopupUtils.open(fp)
109+ }
110+
111+ Label {
112+ id: acceptedLabel
113+ property string acceptedPath
114+ visible: acceptedPath
115+ anchors { left: parent.left; right: parent.right }
116+ text: i18n.tr("Accepted path: %1").arg(acceptedPath)
117+ elide: Text.ElideMiddle
118+ }
119+ }
120+ }
121+}
122
123=== modified file 'plugins/Ubuntu/Settings/Components/CMakeLists.txt'
124--- plugins/Ubuntu/Settings/Components/CMakeLists.txt 2016-01-29 00:44:43 +0000
125+++ plugins/Ubuntu/Settings/Components/CMakeLists.txt 2017-01-25 13:04:17 +0000
126@@ -1,9 +1,15 @@
127 project(UbuntuSettingsComponentsQml)
128
129+pkg_search_module(GLIB REQUIRED glib-2.0)
130+include_directories(
131+ ${GLIB_INCLUDE_DIRS}
132+)
133+
134 add_definitions(-DUBUNTUSETTINGSCOMPONENTS_LIBRARY)
135
136 add_library(UbuntuSettingsComponentsQml MODULE
137 plugin.cpp
138+ filepickerhelper.cpp
139 serverpropertysynchroniser.cpp
140 )
141
142@@ -11,6 +17,7 @@
143 Qt5::Core
144 Qt5::Qml
145 Qt5::Quick
146+ ${GLIB_LDFLAGS}
147 )
148
149 add_usc_plugin(Ubuntu.Settings.Components 0.1 Ubuntu/Settings/Components TARGETS UbuntuSettingsComponentsQml)
150
151=== added file 'plugins/Ubuntu/Settings/Components/FilePicker.qml'
152--- plugins/Ubuntu/Settings/Components/FilePicker.qml 1970-01-01 00:00:00 +0000
153+++ plugins/Ubuntu/Settings/Components/FilePicker.qml 2017-01-25 13:04:17 +0000
154@@ -0,0 +1,197 @@
155+/*
156+ * Copyright (C) 2016 Canonical Ltd.
157+ *
158+ * This program is free software: you can redistribute it and/or modify it
159+ * under the terms of the GNU Lesser General Public License version 3,
160+ * as published by the Free Software Foundation.
161+ *
162+ * This program is distributed in the hope that it will be useful,
163+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
164+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
165+ * GNU Lesser General Public License for more details.
166+ *
167+ * You should have received a copy of the GNU Lesser General Public License
168+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
169+ */
170+
171+import Qt.labs.folderlistmodel 2.1
172+import QtQuick 2.4
173+import QtQuick.Layouts 1.1
174+import Ubuntu.Components 1.3
175+import Ubuntu.Components.ListItems 1.3 as ListItems
176+import Ubuntu.Components.Popups 1.3
177+import Ubuntu.Settings.Components 0.1
178+
179+Dialog {
180+ id: root
181+ objectName: "filePicker"
182+
183+ property string currentFilePath: ""
184+
185+ signal accept(string path)
186+ signal reject()
187+
188+ function hideFunc() {
189+ FilePickerProperties.lastFolder = fsModel.folder
190+ currentFilePath = ""
191+ }
192+
193+ function rejectFunc() {
194+ hideFunc()
195+ root.reject()
196+ }
197+
198+ function acceptFunc() {
199+ var path = currentFilePath
200+ hideFunc()
201+ root.accept(path)
202+ }
203+
204+ property var fsModel: FolderListModel {
205+ showDirs: true
206+ showFiles: true
207+ showHidden: true
208+ showDirsFirst: true
209+ showDotAndDotDot: false
210+ showOnlyReadable: false
211+ sortField: FolderListModel.Name
212+
213+ folder: (FilePickerProperties.lastFolder === "") ?
214+ FilePickerHelper.homeDirUrl() :
215+ FilePickerProperties.lastFolder
216+ }
217+
218+ ColumnLayout {
219+ spacing: units.gu(1)
220+ anchors {
221+ left: parent.left
222+ right: parent.right
223+ }
224+ height: root.height - units.gu(10)
225+
226+ RowLayout {
227+ anchors { left: parent.left; right: parent.right }
228+ spacing: units.gu(1)
229+
230+ Icon {
231+ objectName: "filePickerBackButton"
232+ name: "back"
233+ Layout.alignment: Qt.AlignVCenter
234+ width: units.gu(2.5)
235+ height: width
236+
237+ enabled: (FilePickerHelper.pathFromUrl(fsModel.folder)
238+ !== FilePickerHelper.rootPath())
239+ opacity: enabled ? 1 : 0.5
240+
241+ MouseArea {
242+ anchors {
243+ fill: parent
244+ margins: -units.gu(2)
245+ }
246+ onClicked: {
247+ if (parent.enabled) {
248+ fsModel.folder = fsModel.parentFolder
249+ }
250+ }
251+ }
252+ }
253+
254+ Label {
255+ objectName: "filePickerBreadcrumb"
256+ Layout.alignment: Qt.AlignVCenter
257+ text: {
258+ var prettyTree = [
259+ i18n.dtr("ubuntu-settings-components", "Device")
260+ ];
261+ var paths = FilePickerHelper.pathsFromUrl(fsModel.folder);
262+ for (var i = 0; i < paths.length; i++) {
263+ prettyTree.push(paths[i]);
264+ }
265+ return i18n.dtr("ubuntu-settings-components",
266+ "%1 (%2 file)",
267+ "%1 (%2 files)",
268+ fsModel.count
269+ ).arg(prettyTree.join("/"))
270+ .arg(fsModel.count)
271+ }
272+ Layout.fillWidth: true
273+ elide: Text.ElideMiddle
274+ }
275+ }
276+
277+ Rectangle {
278+ Layout.fillWidth: true
279+ Layout.fillHeight: true
280+ color: theme.palette.normal.background
281+
282+ border {
283+ width: 1
284+ color: theme.palette.normal.overlaySecondaryText
285+ }
286+
287+ ListView {
288+ id: list
289+ objectName: "filePickerList"
290+ anchors.fill: parent
291+ clip: true
292+ model: fsModel
293+
294+ delegate: ListItem {
295+ objectName: "filePickerFileItem_" + index
296+ height: fileLayout.height + divider.height
297+ color: (filePath === currentFilePath) ? highlightColor : "transparent"
298+
299+ onClicked: {
300+ if (fileIsDir) {
301+ fsModel.folder = fileURL
302+ } else {
303+ currentFilePath = filePath
304+ }
305+ }
306+
307+ ListItemLayout {
308+ id: fileLayout
309+
310+ title.text: fileName
311+ title.elide: Text.ElideMiddle
312+ title.wrapMode: Text.NoWrap
313+ subtitle.text: fileIsDir ?
314+ "" : FilePickerHelper.formatSize(fileSize)
315+
316+ Icon {
317+ name: fileIsDir ? "folder" : "empty"
318+ SlotsLayout.position: SlotsLayout.Leading;
319+ width: units.gu(4)
320+ }
321+ }
322+ }
323+ }
324+
325+ Scrollbar {
326+ flickableItem: list
327+ align: Qt.AlignTrailing
328+ }
329+ }
330+
331+ RowLayout {
332+ spacing: units.gu(1)
333+
334+ Button {
335+ objectName: "filePickerCancel"
336+ Layout.fillWidth: true
337+ text: i18n.dtr("ubuntu-settings-components", "Cancel")
338+ onClicked: rejectFunc()
339+ }
340+
341+ Button {
342+ objectName: "filePickerAccept"
343+ Layout.fillWidth: true
344+ enabled: currentFilePath !== ""
345+ text: i18n.dtr("ubuntu-settings-components", "Accept")
346+ onClicked: acceptFunc()
347+ color: theme.palette.normal.positive
348+ }
349+ }
350+ }
351+}
352
353=== added file 'plugins/Ubuntu/Settings/Components/FilePickerProperties.qml'
354--- plugins/Ubuntu/Settings/Components/FilePickerProperties.qml 1970-01-01 00:00:00 +0000
355+++ plugins/Ubuntu/Settings/Components/FilePickerProperties.qml 2017-01-25 13:04:17 +0000
356@@ -0,0 +1,22 @@
357+/*
358+ * Copyright (C) 2016 Canonical Ltd.
359+ *
360+ * This program is free software: you can redistribute it and/or modify it
361+ * under the terms of the GNU Lesser General Public License version 3,
362+ * as published by the Free Software Foundation.
363+ *
364+ * This program is distributed in the hope that it will be useful,
365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
367+ * GNU Lesser General Public License for more details.
368+ *
369+ * You should have received a copy of the GNU Lesser General Public License
370+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
371+ */
372+
373+pragma Singleton
374+import QtQuick 2.4
375+
376+QtObject {
377+ property string lastFolder
378+}
379
380=== added file 'plugins/Ubuntu/Settings/Components/filepickerhelper.cpp'
381--- plugins/Ubuntu/Settings/Components/filepickerhelper.cpp 1970-01-01 00:00:00 +0000
382+++ plugins/Ubuntu/Settings/Components/filepickerhelper.cpp 2017-01-25 13:04:17 +0000
383@@ -0,0 +1,59 @@
384+/*
385+ * Copyright (C) 2016 Canonical, Ltd.
386+ *
387+ * This program is free software; you can redistribute it and/or modify
388+ * it under the terms of the GNU Lesser General Public License as published by
389+ * the Free Software Foundation; version 3.
390+ *
391+ * This program is distributed in the hope that it will be useful,
392+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
393+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
394+ * GNU Lesser General Public License for more details.
395+ *
396+ * You should have received a copy of the GNU Lesser General Public License
397+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
398+ */
399+
400+#include "filepickerhelper.h"
401+
402+#include <glib.h>
403+
404+#include <QDir>
405+#include <QDebug>
406+
407+FilePickerHelper::FilePickerHelper(QObject* parent)
408+ : QObject(parent)
409+{
410+}
411+
412+QUrl FilePickerHelper::homeDirUrl()
413+{
414+ return QUrl::fromLocalFile(QDir::homePath());
415+}
416+
417+QString FilePickerHelper::pathFromUrl(const QUrl &url)
418+{
419+ return url.path();
420+}
421+
422+QString FilePickerHelper::rootPath()
423+{
424+ return QDir::rootPath();
425+}
426+
427+QStringList FilePickerHelper::pathsFromUrl(const QUrl &url)
428+{
429+ QString path = url.path();
430+ return path.split(QDir::separator(), QString::SkipEmptyParts);
431+}
432+
433+QString FilePickerHelper::formatSize(const quint64 &size)
434+{
435+ guint64 g_size = size;
436+
437+ gchar * formatted_size = g_format_size (g_size);
438+ QString q_formatted_size = QString::fromLocal8Bit(formatted_size);
439+ g_free (formatted_size);
440+
441+ return q_formatted_size;
442+}
443
444=== added file 'plugins/Ubuntu/Settings/Components/filepickerhelper.h'
445--- plugins/Ubuntu/Settings/Components/filepickerhelper.h 1970-01-01 00:00:00 +0000
446+++ plugins/Ubuntu/Settings/Components/filepickerhelper.h 2017-01-25 13:04:17 +0000
447@@ -0,0 +1,36 @@
448+/*
449+ * Copyright (C) 2016 Canonical, Ltd.
450+ *
451+ * This program is free software; you can redistribute it and/or modify
452+ * it under the terms of the GNU Lesser General Public License as published by
453+ * the Free Software Foundation; version 3.
454+ *
455+ * This program is distributed in the hope that it will be useful,
456+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
457+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
458+ * GNU Lesser General Public License for more details.
459+ *
460+ * You should have received a copy of the GNU Lesser General Public License
461+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
462+ */
463+
464+#ifndef FILEPICKERHELPER_H
465+#define FILEPICKERHELPER_H
466+
467+#include <QObject>
468+#include <QUrl>
469+#include <QStringList>
470+
471+class FilePickerHelper : public QObject
472+{
473+ Q_OBJECT
474+public:
475+ FilePickerHelper(QObject* parent = nullptr);
476+ Q_INVOKABLE static QUrl homeDirUrl();
477+ Q_INVOKABLE static QString rootPath();
478+ Q_INVOKABLE static QString pathFromUrl(const QUrl &url);
479+ Q_INVOKABLE static QStringList pathsFromUrl(const QUrl &url);
480+ Q_INVOKABLE static QString formatSize(const quint64 &size);
481+};
482+
483+#endif // FILEPICKERHELPER_H
484
485=== modified file 'plugins/Ubuntu/Settings/Components/plugin.cpp'
486--- plugins/Ubuntu/Settings/Components/plugin.cpp 2016-10-26 17:09:16 +0000
487+++ plugins/Ubuntu/Settings/Components/plugin.cpp 2017-01-25 13:04:17 +0000
488@@ -17,6 +17,7 @@
489 // local
490 #include "plugin.h"
491 #include "serverpropertysynchroniser.h"
492+#include "filepickerhelper.h"
493
494 // Qt
495 #include <QtQml/qqml.h>
496@@ -33,9 +34,15 @@
497 Q_INVOKABLE QString formattedWeekNumber(const QDate &date) const { return QString("%1").arg(date.weekNumber(), 2, 10, QChar('0')); }
498 };
499
500+static QObject* filepickerhelperProvider(QQmlEngine*, QJSEngine*)
501+{
502+ return new FilePickerHelper;
503+}
504+
505 void UbuntuSettingsComponentsPlugin::registerTypes(const char *uri)
506 {
507 qmlRegisterType<ServerPropertySynchroniser>(uri, 0, 1, "ServerPropertySynchroniser");
508+ qmlRegisterSingletonType<FilePickerHelper>(uri, 0, 1, "FilePickerHelper", filepickerhelperProvider);
509 qmlRegisterSingletonType<QtDateFunctions>(uri, 0, 1, "QtDateFunctions",
510 [](QQmlEngine*, QJSEngine*) -> QObject* { return new QtDateFunctions; });
511 }
512
513=== modified file 'plugins/Ubuntu/Settings/Components/qmldir'
514--- plugins/Ubuntu/Settings/Components/qmldir 2016-09-16 23:17:00 +0000
515+++ plugins/Ubuntu/Settings/Components/qmldir 2017-01-25 13:04:17 +0000
516@@ -4,5 +4,8 @@
517
518 ActionTextField 0.1 ActionTextField.qml
519 Calendar 0.1 Calendar.qml
520+FilePicker 0.1 FilePicker.qml
521 MessageHeader 0.1 MessageHeader.qml
522 UbuntuShapeForItem 0.1 UbuntuShapeForItem.qml
523+
524+singleton FilePickerProperties 0.1 FilePickerProperties.qml
525
526=== removed file 'plugins/Ubuntu/Settings/Vpn/DialogFile.qml'
527--- plugins/Ubuntu/Settings/Vpn/DialogFile.qml 2016-03-14 15:01:48 +0000
528+++ plugins/Ubuntu/Settings/Vpn/DialogFile.qml 1970-01-01 00:00:00 +0000
529@@ -1,176 +0,0 @@
530-/*
531- * Copyright (C) 2016 Canonical Ltd.
532- *
533- * This program is free software: you can redistribute it and/or modify it
534- * under the terms of the GNU Lesser General Public License version 3,
535- * as published by the Free Software Foundation.
536- *
537- * This program is distributed in the hope that it will be useful,
538- * but WITHOUT ANY WARRANTY; without even the implied warranty of
539- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
540- * GNU Lesser General Public License for more details.
541- *
542- * You should have received a copy of the GNU Lesser General Public License
543- * along with this program. If not, see <http://www.gnu.org/licenses/>.
544- */
545-
546-import QtQuick 2.4
547-import QtQuick.Layouts 1.1
548-import Ubuntu.Components 1.3
549-import Ubuntu.Components.ListItems 1.3 as ListItems
550-import Ubuntu.Components.Popups 1.3
551-import Ubuntu.Settings.Vpn 0.1
552-import Qt.labs.folderlistmodel 2.1
553-
554-Dialog {
555- objectName: "vpnDialogFile"
556- id: dialog
557-
558- property string currentFilePath: ""
559-
560- signal accept(string path)
561- signal reject
562-
563- function hideFunc() {
564- DialogFileProperties.lastFolder = modelFs.folder
565- currentFilePath = ""
566- }
567-
568- function rejectFunc() {
569- hideFunc()
570- dialog.reject()
571- }
572-
573- function acceptFunc() {
574- var path = currentFilePath
575- hideFunc()
576- dialog.accept(path)
577- }
578-
579- FolderListModel {
580- id: modelFs
581- showDirs: true
582- showFiles: true
583- showHidden: true
584- showDirsFirst: true
585- showDotAndDotDot: false
586- showOnlyReadable: false
587- sortField: FolderListModel.Name
588-
589- folder: (DialogFileProperties.lastFolder === "")? "file:///home/" : DialogFileProperties.lastFolder
590- }
591-
592- ColumnLayout {
593- height: root.height - units.gu(10)
594- spacing: units.gu(1)
595-
596- Flow {
597- spacing: units.gu(1)
598- Layout.fillWidth: true
599-
600- Repeater {
601- model: {
602- var ret = []
603- var path = "file:///"
604- ret.push({ "name" : "/", "url" : path })
605- var tmp = modelFs.folder.toString().replace("file:///", "").split("/")
606- for (var idx = 0; idx < tmp.length; idx++) {
607- var name = tmp[idx] + "/"
608- if (name !== "/") {
609- path += name
610- ret.push({ "name" : name, "url" : path })
611- }
612- }
613- return ret
614- }
615- delegate: Row {
616- spacing: units.gu(0.7)
617-
618- property bool isCurrent : Positioner.isLastItem
619-
620- Rectangle {
621- width: units.gu(0.7)
622- height: width
623- color: "gray"
624- rotation: 45
625- visible: (model.index > 0)
626- anchors.verticalCenter: parent.verticalCenter
627- }
628- Label {
629- objectName: "vpnFilePathItem_" + model.modelData["name"]
630- text: model.modelData["name"]
631- font.weight: (isCurrent ? Font.Bold : Font.Normal)
632- font.underline: hoverDetector.containsMouse
633- color: "darkblue"
634- anchors.verticalCenter: parent.verticalCenter
635-
636- MouseArea {
637- id: hoverDetector
638- enabled: !isCurrent
639- hoverEnabled: true
640- anchors.fill: parent
641- onClicked: modelFs.folder = model.modelData["url"]
642- }
643- }
644- }
645- }
646- }
647-
648- Rectangle {
649- Layout.fillWidth: true
650- Layout.fillHeight: true
651-
652- border {
653- width: 1
654- color: "lightgrey"
655- }
656-
657- ListView {
658- objectName: "vpnFileList"
659- anchors.fill: parent
660- anchors.margins: 1
661- clip: true
662- model: modelFs
663-
664- delegate: ListItems.Standard {
665- objectName: "vpnFileItem_" + model.fileName
666- text: model.fileName
667- iconFrame: false
668- iconName: model.fileIsDir ? "folder" : "empty"
669-
670- selected: (model.filePath === currentFilePath)
671-
672- onClicked: {
673- if (model.fileIsDir) {
674- modelFs.folder = model.fileURL
675- } else {
676- currentFilePath = model.filePath
677- }
678- }
679- }
680- }
681- }
682-
683- RowLayout {
684- spacing: units.gu(1)
685- Layout.fillWidth: true
686-
687- Button {
688- objectName: "vpnFileCancel"
689- Layout.fillWidth: true
690- text: i18n.dtr("ubuntu-settings-components", "Cancel")
691- onClicked: rejectFunc()
692- color: UbuntuColors.red
693- }
694-
695- Button {
696- objectName: "vpnFileAccept"
697- Layout.fillWidth: true
698- enabled: currentFilePath !== ""
699- text: i18n.dtr("ubuntu-settings-components", "Accept")
700- onClicked: acceptFunc()
701- color: UbuntuColors.green
702- }
703- }
704- }
705-}
706
707=== removed file 'plugins/Ubuntu/Settings/Vpn/DialogFileProperties.qml'
708--- plugins/Ubuntu/Settings/Vpn/DialogFileProperties.qml 2016-03-07 15:46:28 +0000
709+++ plugins/Ubuntu/Settings/Vpn/DialogFileProperties.qml 1970-01-01 00:00:00 +0000
710@@ -1,22 +0,0 @@
711-/*
712- * Copyright (C) 2016 Canonical Ltd.
713- *
714- * This program is free software: you can redistribute it and/or modify it
715- * under the terms of the GNU Lesser General Public License version 3,
716- * as published by the Free Software Foundation.
717- *
718- * This program is distributed in the hope that it will be useful,
719- * but WITHOUT ANY WARRANTY; without even the implied warranty of
720- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
721- * GNU Lesser General Public License for more details.
722- *
723- * You should have received a copy of the GNU Lesser General Public License
724- * along with this program. If not, see <http://www.gnu.org/licenses/>.
725- */
726-
727-pragma Singleton
728-import QtQuick 2.4
729-
730-QtObject {
731- property string lastFolder
732-}
733
734=== modified file 'plugins/Ubuntu/Settings/Vpn/FileSelector.qml'
735--- plugins/Ubuntu/Settings/Vpn/FileSelector.qml 2016-03-14 15:01:48 +0000
736+++ plugins/Ubuntu/Settings/Vpn/FileSelector.qml 2017-01-25 13:04:17 +0000
737@@ -19,6 +19,7 @@
738 import Ubuntu.Components 1.3
739 import Ubuntu.Components.Popups 1.3
740 import Ubuntu.Components.ListItems 1.3 as ListItems
741+import Ubuntu.Settings.Components 0.1
742
743 ListItems.ItemSelector {
744 property string path
745@@ -47,7 +48,7 @@
746 }
747
748 function createDialog() {
749- __dialog = PopupUtils.open(fileDialogComponent)
750+ __dialog = PopupUtils.open(filePickerComponent)
751 __dialog.accept.connect(pathAccepted)
752 __dialog.reject.connect(pathRejected)
753 }
754@@ -91,4 +92,9 @@
755 path = model[index];
756 }
757 }
758+
759+ Component {
760+ id: filePickerComponent
761+ FilePicker {}
762+ }
763 }
764
765=== modified file 'plugins/Ubuntu/Settings/Vpn/VpnEditor.qml'
766--- plugins/Ubuntu/Settings/Vpn/VpnEditor.qml 2016-12-16 13:32:35 +0000
767+++ plugins/Ubuntu/Settings/Vpn/VpnEditor.qml 2017-01-25 13:04:17 +0000
768@@ -68,13 +68,6 @@
769 leadingActionBar.actions: []
770 }
771
772- Component {
773- id: fileDialogComponent
774- DialogFile {
775- id: fileDialog
776- }
777- }
778-
779 Flickable {
780 id: scrollWidget
781 anchors {
782
783=== modified file 'plugins/Ubuntu/Settings/Vpn/qmldir'
784--- plugins/Ubuntu/Settings/Vpn/qmldir 2016-02-29 13:52:35 +0000
785+++ plugins/Ubuntu/Settings/Vpn/qmldir 2017-01-25 13:04:17 +0000
786@@ -1,10 +1,6 @@
787 module Ubuntu.Settings.Vpn
788 plugin UbuntuSettingsVpn
789
790-singleton DialogFileProperties 0.1 DialogFileProperties.qml
791-
792-internal DialogFile DialogFile.qml
793-
794 VpnList 0.1 VpnList.qml
795 VpnEditor 0.1 VpnEditor.qml
796 VpnPreviewDialog 0.1 VpnPreviewDialog.qml
797
798=== modified file 'po/ubuntu-settings-components.pot'
799--- po/ubuntu-settings-components.pot 2017-01-18 15:20:00 +0000
800+++ po/ubuntu-settings-components.pot 2017-01-25 13:04:17 +0000
801@@ -8,7 +8,7 @@
802 msgstr ""
803 "Project-Id-Version: ubuntu-settings-components\n"
804 "Report-Msgid-Bugs-To: \n"
805-"POT-Creation-Date: 2017-01-18 15:20+0000\n"
806+"POT-Creation-Date: 2017-01-25 14:03+0100\n"
807 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
808 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
809 "Language-Team: LANGUAGE <LL@li.org>\n"
810@@ -16,12 +16,36 @@
811 "MIME-Version: 1.0\n"
812 "Content-Type: text/plain; charset=UTF-8\n"
813 "Content-Transfer-Encoding: 8bit\n"
814+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
815
816 #: plugins/Ubuntu/Settings/Components/Calendar.qml:232
817 msgctxt "Header text: keep it short and upper case"
818 msgid "WEEK"
819 msgstr ""
820
821+#: plugins/Ubuntu/Settings/Components/FilePicker.qml:105
822+msgid "Device"
823+msgstr ""
824+
825+#: plugins/Ubuntu/Settings/Components/FilePicker.qml:112
826+#, qt-format
827+msgid "%1 (%2 file)"
828+msgid_plural "%1 (%2 files)"
829+msgstr[0] ""
830+msgstr[1] ""
831+
832+#: plugins/Ubuntu/Settings/Components/FilePicker.qml:183
833+#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:336
834+#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:355
835+#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:129
836+#: plugins/Ubuntu/Settings/Vpn/VpnPreviewDialog.qml:104
837+msgid "Cancel"
838+msgstr ""
839+
840+#: plugins/Ubuntu/Settings/Components/FilePicker.qml:191
841+msgid "Accept"
842+msgstr ""
843+
844 #: plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml:82
845 msgid "Fingerprint Name"
846 msgstr ""
847@@ -37,7 +61,7 @@
848 #: plugins/Ubuntu/Settings/Fingerprint/Fingerprint.qml:131
849 #: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:362
850 #: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:138
851-#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:149
852+#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:142
853 msgid "OK"
854 msgstr ""
855
856@@ -74,14 +98,6 @@
857 msgid "Are you sure you want to forget all stored fingerprints?"
858 msgstr ""
859
860-#: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:336
861-#: plugins/Ubuntu/Settings/Fingerprint/Setup.qml:355
862-#: plugins/Ubuntu/Settings/Vpn/DialogFile.qml:161
863-#: plugins/Ubuntu/Settings/Vpn/VpnEditor.qml:136
864-#: plugins/Ubuntu/Settings/Vpn/VpnPreviewDialog.qml:104
865-msgid "Cancel"
866-msgstr ""
867-
868 #: plugins/Ubuntu/Settings/Fingerprint/Fingerprints.qml:343
869 #: plugins/Ubuntu/Settings/Vpn/VpnPreviewDialog.qml:84
870 msgid "Remove"
871@@ -148,15 +164,11 @@
872 msgid "Send"
873 msgstr ""
874
875-#: plugins/Ubuntu/Settings/Vpn/DialogFile.qml:170
876-msgid "Accept"
877-msgstr ""
878-
879-#: plugins/Ubuntu/Settings/Vpn/FileSelector.qml:25
880+#: plugins/Ubuntu/Settings/Vpn/FileSelector.qml:26
881 msgid "Choose…"
882 msgstr ""
883
884-#: plugins/Ubuntu/Settings/Vpn/FileSelector.qml:34
885+#: plugins/Ubuntu/Settings/Vpn/FileSelector.qml:35
886 #: plugins/Ubuntu/Settings/Vpn/Openvpn/Editor.qml:431
887 #: plugins/Ubuntu/Settings/Vpn/Openvpn/Editor.qml:513
888 msgid "None"
889
890=== modified file 'tests/qmltests/CMakeLists.txt'
891--- tests/qmltests/CMakeLists.txt 2016-10-11 13:51:11 +0000
892+++ tests/qmltests/CMakeLists.txt 2017-01-25 13:04:17 +0000
893@@ -2,6 +2,7 @@
894
895 add_usc_qmltest(Components ActionTextField)
896 add_usc_qmltest(Components Calendar)
897+add_usc_qmltest(Components FilePicker)
898 add_usc_qmltest(Components ServerPropertySynchroniser)
899
900 add_usc_qmltest(Menus AccessPointMenu)
901
902=== added file 'tests/qmltests/Components/tst_FilePicker.qml'
903--- tests/qmltests/Components/tst_FilePicker.qml 1970-01-01 00:00:00 +0000
904+++ tests/qmltests/Components/tst_FilePicker.qml 2017-01-25 13:04:17 +0000
905@@ -0,0 +1,215 @@
906+/*
907+ * Copyright 2016 Canonical Ltd.
908+ *
909+ * This program is free software; you can redistribute it and/or modify
910+ * it under the terms of the GNU Lesser General Public License as published by
911+ * the Free Software Foundation; version 3.
912+ *
913+ * This program is distributed in the hope that it will be useful,
914+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
915+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
916+ * GNU Lesser General Public License for more details.
917+ *
918+ * You should have received a copy of the GNU Lesser General Public License
919+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
920+ *
921+ * Authored by Jonas G. Drange <jonas.drange@canonical.com>
922+ */
923+
924+import Qt.labs.folderlistmodel 2.1
925+import QtQuick 2.4
926+import QtTest 1.0
927+import Ubuntu.Components 1.3
928+import Ubuntu.Components.Popups 1.3
929+import Ubuntu.Settings.Components 0.1
930+import Ubuntu.Test 0.1
931+
932+MainView {
933+ id: testRoot
934+ width: units.gu(42)
935+ height: units.gu(75)
936+
937+ Component {
938+ id: filePickerComp
939+
940+ FilePicker {}
941+ }
942+
943+ Component {
944+ id: fsModelComp
945+
946+ FolderListModel {}
947+ }
948+
949+ SignalSpy {
950+ id: spy
951+ }
952+
953+ UbuntuTestCase {
954+ name: "FilePicker"
955+ when: windowShown
956+
957+ property var instance: null
958+ property var fsModel: null
959+
960+ function init() {
961+ fsModel = fsModelComp.createObject(testRoot);
962+ }
963+
964+ function cleanup() {
965+ PopupUtils.close(instance);
966+ tryCompareFunction(function () {
967+ return !!findChild(testRoot, "filePicker");
968+ }, false);
969+ fsModel.destroy();
970+ spy.clear();
971+ spy.target = null;
972+ spy.signalName = "";
973+ }
974+
975+ function test_breadCrumb_data() {
976+ return [
977+ {
978+ folder: "file:///home/user/",
979+ parentFolder: "file:///home",
980+ count: 0,
981+ targetText: i18n.dtr("ubuntu-settings-components", "%1 (%2 files)")
982+ .arg(i18n.tr("Device") + "/home/user")
983+ .arg(0)
984+ },
985+ {
986+ folder: "file:///",
987+ parentFolder: "file:///",
988+ count: 10,
989+ targetText: i18n.dtr("ubuntu-settings-components", "%1 (%2 files)")
990+ .arg(i18n.tr("Device"))
991+ .arg(10)
992+ },
993+ {
994+ folder: "file:///bar/baz",
995+ parentFolder: "file:///bar",
996+ count: 1,
997+ targetText: i18n.dtr("ubuntu-settings-components", "%1 (%2 file)")
998+ .arg(i18n.tr("Device") + "/bar/baz")
999+ .arg(1)
1000+ },
1001+ ]
1002+ }
1003+
1004+ function test_breadCrumb(data) {
1005+ fsModel.folder = data.folder;
1006+ fsModel.parentFolder = data.parentFolder;
1007+ fsModel.count = data.count;
1008+ instance = PopupUtils.open(filePickerComp, null, { "fsModel": fsModel });
1009+ waitForRendering(instance);
1010+
1011+ var crumbs = findChild(instance, "filePickerBreadcrumb");
1012+ compare(crumbs.text, data.targetText)
1013+ }
1014+
1015+ function test_backButtonEnabled_data() {
1016+ return [
1017+ { folder: "file:///", parentFolder: "file:///", targetEnabled: false },
1018+ { folder: "file:///bar", parentFolder: "file:///", targetEnabled: true },
1019+ { folder: "file:///bar/baz", parentFolder: "file:///bar", targetEnabled: true },
1020+ ]
1021+ }
1022+
1023+ function test_backButtonEnabled(data) {
1024+ fsModel.folder = data.folder;
1025+ fsModel.parentFolder = data.parentFolder;
1026+ instance = PopupUtils.open(filePickerComp, null, { "fsModel": fsModel });
1027+ waitForRendering(instance);
1028+
1029+ var button = findChild(instance, "filePickerBackButton");
1030+ compare(button.enabled, data.targetEnabled);
1031+ }
1032+
1033+ function test_backButtonAction_data() {
1034+ return [
1035+ { folder: "file:///", parentFolder: "file:///" },
1036+ { folder: "file:///bar", parentFolder: "file:///" },
1037+ { folder: "file:///bar/baz", parentFolder: "file:///bar" }
1038+ ]
1039+ }
1040+
1041+ function test_backButtonAction(data) {
1042+ fsModel.folder = data.folder;
1043+ fsModel.parentFolder = data.parentFolder;
1044+ instance = PopupUtils.open(filePickerComp, null, { "fsModel": fsModel });
1045+ waitForRendering(instance);
1046+
1047+ var button = findChild(instance, "filePickerBackButton");
1048+ mouseClick(button, button.width / 2, button.height / 2);
1049+ compare(fsModel.folder, fsModel.parentFolder);
1050+ }
1051+
1052+ function test_renderFiles_data() {
1053+ return [
1054+ { files: [ ["fileA.txt", "/home/user/fileA.txt", "", 5000, "txt", false, true] ] },
1055+ { files: [
1056+ ["fileA.txt", "/home/user/fileA.txt", "", 5000, "txt", false, true],
1057+ ["fileB.txt", "/fileB.txt", "", 5000, "txt", false, true],
1058+ ["somedir", "/somedir", "somedir", 4001, "", true, false]
1059+ ]}
1060+ ]
1061+ }
1062+
1063+ function test_renderFiles(data) {
1064+ for (var i = 0; i < data.files.length; i++) {
1065+ fsModel.mockAddFile.apply(fsModel, data.files[i]);
1066+ }
1067+ instance = PopupUtils.open(filePickerComp, null, { "fsModel": fsModel });
1068+ waitForRendering(instance);
1069+
1070+ // Make sure each file was rendered.
1071+ for (var i = 0; i < data.files.length; i++) {
1072+ verify(findChild(instance, "filePickerFileItem_" + i));
1073+ }
1074+ }
1075+
1076+ function test_accept_data() {
1077+ var files = [
1078+ ["fileA.txt", "file:///home/user/fileA.txt", "", 5000, "txt", false, true],
1079+ ["fileB.txt", "file:///fileB.txt", "", 5000, "txt", false, true]
1080+ ]
1081+ return [
1082+ { "files": files, accept: 0, targetAcceptPath: "file:///home/user/fileA.txt" },
1083+ { "files": files, accept: 1, targetAcceptPath: "file:///fileB.txt" },
1084+ ]
1085+ }
1086+
1087+ function test_accept(data) {
1088+ for (var i = 0; i < data.files.length; i++) {
1089+ fsModel.mockAddFile.apply(fsModel, data.files[i]);
1090+ }
1091+ instance = PopupUtils.open(filePickerComp, null, { "fsModel": fsModel });
1092+ waitForRendering(instance);
1093+
1094+ var item = findChild(instance, "filePickerFileItem_" + data.accept);
1095+ mouseClick(item, item.width / 2, item.height / 2);
1096+
1097+ spy.target = instance;
1098+ spy.signalName = "accept";
1099+
1100+ var btn = findChild(instance, "filePickerAccept");
1101+ mouseClick(btn, btn.width / 2, btn.height / 2);
1102+ spy.wait();
1103+ compare(spy.count, 1);
1104+ compare(spy.signalArguments[0][0], data.targetAcceptPath);
1105+ }
1106+
1107+ function test_reject() {
1108+ instance = PopupUtils.open(filePickerComp, null, { "fsModel": fsModel });
1109+ waitForRendering(instance);
1110+
1111+ spy.target = instance;
1112+ spy.signalName = "reject";
1113+
1114+ var btn = findChild(instance, "filePickerCancel");
1115+ mouseClick(btn, btn.width / 2, btn.height / 2);
1116+ spy.wait();
1117+ compare(spy.count, 1);
1118+ }
1119+ }
1120+}
1121
1122=== modified file 'tests/qmltests/mocks/CMakeLists.txt'
1123--- tests/qmltests/mocks/CMakeLists.txt 2016-12-22 14:35:38 +0000
1124+++ tests/qmltests/mocks/CMakeLists.txt 2017-01-25 13:04:17 +0000
1125@@ -30,3 +30,4 @@
1126
1127 add_subdirectory(Biometryd)
1128 add_subdirectory(GSettings.1.0)
1129+add_subdirectory(Qt)
1130
1131=== added directory 'tests/qmltests/mocks/Qt'
1132=== added file 'tests/qmltests/mocks/Qt/CMakeLists.txt'
1133--- tests/qmltests/mocks/Qt/CMakeLists.txt 1970-01-01 00:00:00 +0000
1134+++ tests/qmltests/mocks/Qt/CMakeLists.txt 2017-01-25 13:04:17 +0000
1135@@ -0,0 +1,1 @@
1136+add_subdirectory(labs)
1137
1138=== added directory 'tests/qmltests/mocks/Qt/labs'
1139=== added file 'tests/qmltests/mocks/Qt/labs/CMakeLists.txt'
1140--- tests/qmltests/mocks/Qt/labs/CMakeLists.txt 1970-01-01 00:00:00 +0000
1141+++ tests/qmltests/mocks/Qt/labs/CMakeLists.txt 2017-01-25 13:04:17 +0000
1142@@ -0,0 +1,1 @@
1143+add_subdirectory(folderlistmodel)
1144
1145=== added directory 'tests/qmltests/mocks/Qt/labs/folderlistmodel'
1146=== added file 'tests/qmltests/mocks/Qt/labs/folderlistmodel/CMakeLists.txt'
1147--- tests/qmltests/mocks/Qt/labs/folderlistmodel/CMakeLists.txt 1970-01-01 00:00:00 +0000
1148+++ tests/qmltests/mocks/Qt/labs/folderlistmodel/CMakeLists.txt 2017-01-25 13:04:17 +0000
1149@@ -0,0 +1,20 @@
1150+include_directories(
1151+ ${CMAKE_CURRENT_BINARY_DIR}
1152+ ${Qt5Core_INCLUDE_DIRS}
1153+ ${Qt5Quick_INCLUDE_DIRS}
1154+)
1155+
1156+set(Qtlabs_folderlistmodel_SRCS
1157+ MockFolderListModel.cpp
1158+ plugin.cpp
1159+)
1160+
1161+add_library(QtLabsFolderListModelQml MODULE ${Qtlabs_folderlistmodel_SRCS})
1162+target_link_libraries(QtLabsFolderListModelQml
1163+ ${Qt5Core_LIBRARIES}
1164+ ${Qt5Quick_LIBRARIES}
1165+)
1166+
1167+qt5_use_modules(QtLabsFolderListModelQml Qml)
1168+
1169+add_usc_mock(Qt.labs.folderlistmodel 2.1 Qt.labs.folderlistmodel TARGETS QtLabsFolderListModelQml)
1170
1171=== added file 'tests/qmltests/mocks/Qt/labs/folderlistmodel/MockFolderListModel.cpp'
1172--- tests/qmltests/mocks/Qt/labs/folderlistmodel/MockFolderListModel.cpp 1970-01-01 00:00:00 +0000
1173+++ tests/qmltests/mocks/Qt/labs/folderlistmodel/MockFolderListModel.cpp 2017-01-25 13:04:17 +0000
1174@@ -0,0 +1,241 @@
1175+/*
1176+ * Copyright (C) 2016 Canonical, Ltd.
1177+ *
1178+ * This program is free software; you can redistribute it and/or modify
1179+ * it under the terms of the GNU General Public License as published by
1180+ * the Free Software Foundation; version 3.
1181+ *
1182+ * This program is distributed in the hope that it will be useful,
1183+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1184+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1185+ * GNU General Public License for more details.
1186+ *
1187+ * You should have received a copy of the GNU General Public License
1188+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1189+ */
1190+
1191+#include "MockFolderListModel.h"
1192+
1193+#include <QDateTime>
1194+
1195+MockFolderListModel::MockFolderListModel(QObject *parent)
1196+ : QAbstractListModel(parent)
1197+ , m_files()
1198+{
1199+}
1200+
1201+QUrl MockFolderListModel::folder() const { return m_folder; }
1202+bool MockFolderListModel::caseSensitive() const { return m_caseSensitive; }
1203+int MockFolderListModel::count() const { return m_count; }
1204+QStringList MockFolderListModel::nameFilters() const { return m_nameFilters; }
1205+QUrl MockFolderListModel::parentFolder() const { return m_parentFolder; }
1206+QUrl MockFolderListModel::rootFolder() const { return m_rootFolder; }
1207+bool MockFolderListModel::showDirs() const { return m_showDirs; }
1208+bool MockFolderListModel::showDirsFirst() const { return m_showDirsFirst; }
1209+bool MockFolderListModel::showDotAndDotDot() const { return m_showDotAndDotDot; }
1210+bool MockFolderListModel::showFiles() const { return m_showFiles; }
1211+bool MockFolderListModel::showHidden() const { return m_showHidden; }
1212+bool MockFolderListModel::showOnlyReadable() const { return m_showOnlyReadable; }
1213+MockFolderListModel::Sort MockFolderListModel::sortField() const { return m_sortField; }
1214+bool MockFolderListModel::sortReversed() const { return m_sortReversed; }
1215+
1216+void MockFolderListModel::setCaseSensitive(const bool caseSensitive)
1217+{
1218+ if (caseSensitive != m_caseSensitive) {
1219+ m_caseSensitive = caseSensitive;
1220+ Q_EMIT caseSensitiveChanged();
1221+ }
1222+}
1223+
1224+void MockFolderListModel::setCount(const int &count)
1225+{
1226+ if (count != m_count) {
1227+ m_count = count;
1228+ Q_EMIT countChanged();
1229+ }
1230+}
1231+
1232+void MockFolderListModel::setFolder(const QUrl &folder)
1233+{
1234+ if (folder != m_folder) {
1235+ m_folder = folder;
1236+ Q_EMIT folderChanged();
1237+ }
1238+}
1239+
1240+void MockFolderListModel::setNameFilters(const QStringList &nameFilters)
1241+{
1242+ if (nameFilters != m_nameFilters) {
1243+ m_nameFilters = nameFilters;
1244+ Q_EMIT nameFiltersChanged();
1245+ }
1246+}
1247+
1248+void MockFolderListModel::setParentFolder(const QUrl &parentFolder)
1249+{
1250+ if (parentFolder != m_parentFolder) {
1251+ m_parentFolder = parentFolder;
1252+ Q_EMIT parentFolderChanged();
1253+ }
1254+}
1255+
1256+void MockFolderListModel::setRootFolder(const QUrl &rootFolder)
1257+{
1258+ if (rootFolder != m_rootFolder) {
1259+ m_rootFolder = rootFolder;
1260+ Q_EMIT rootFolderChanged();
1261+ }
1262+}
1263+
1264+void MockFolderListModel::setShowDirs(const bool showDirs)
1265+{
1266+ if (showDirs != m_showDirs) {
1267+ m_showDirs = showDirs;
1268+ Q_EMIT showDirsChanged();
1269+ }
1270+}
1271+
1272+void MockFolderListModel::setShowDirsFirst(const bool showDirsFirst)
1273+{
1274+ if (showDirsFirst != m_showDirsFirst) {
1275+ m_showDirsFirst = showDirsFirst;
1276+ Q_EMIT showDirsFirstChanged();
1277+ }
1278+}
1279+
1280+void MockFolderListModel::setShowDotAndDotDot(const bool showDotAndDotDot)
1281+{
1282+ if (showDotAndDotDot != m_showDotAndDotDot) {
1283+ m_showDotAndDotDot = showDotAndDotDot;
1284+ Q_EMIT showDotAndDotDotChanged();
1285+ }
1286+}
1287+
1288+void MockFolderListModel::setShowFiles(const bool showFiles)
1289+{
1290+ if (showFiles != m_showFiles) {
1291+ m_showFiles = showFiles;
1292+ Q_EMIT showFilesChanged();
1293+ }
1294+}
1295+
1296+void MockFolderListModel::setShowHidden(const bool showHidden)
1297+{
1298+ if (showHidden != m_showHidden) {
1299+ m_showHidden = showHidden;
1300+ Q_EMIT showHiddenChanged();
1301+ }
1302+}
1303+
1304+void MockFolderListModel::setShowOnlyReadable(const bool showOnlyReadable)
1305+{
1306+ if (showOnlyReadable != m_showOnlyReadable) {
1307+ m_showOnlyReadable = showOnlyReadable;
1308+ Q_EMIT showOnlyReadableChanged();
1309+ }
1310+}
1311+
1312+void MockFolderListModel::setSortField(const Sort &sortField)
1313+{
1314+ if (sortField != m_sortField) {
1315+ m_sortField = sortField;
1316+ Q_EMIT sortFieldChanged();
1317+ }
1318+}
1319+
1320+void MockFolderListModel::setSortReversed(const bool sortReversed)
1321+{
1322+ if (sortReversed != m_sortReversed) {
1323+ m_sortReversed = sortReversed;
1324+ Q_EMIT sortReversedChanged();
1325+ }
1326+}
1327+
1328+QHash<int, QByteArray> MockFolderListModel::roleNames() const
1329+{
1330+ QHash<int, QByteArray> names;
1331+
1332+ names[Roles::FileNameRole] = "fileName";
1333+ names[Roles::FilePathRole] = "filePath";
1334+ names[Roles::FileURLRole] = "fileURL";
1335+ names[Roles::FileBaseNameRole] = "fileBaseName";
1336+ names[Roles::FileSuffixRole] = "fileSuffix";
1337+ names[Roles::FileSizeRole] = "fileSize";
1338+ names[Roles::FileModifiedRole] = "fileModified";
1339+ names[Roles::FileAccessedRole] = "fileAccessed";
1340+ names[Roles::FileIsDirRole] = "fileIsDir";
1341+
1342+ return names;
1343+}
1344+
1345+
1346+int MockFolderListModel::rowCount(const QModelIndex&) const
1347+{
1348+ return m_files.count();
1349+}
1350+
1351+QVariant MockFolderListModel::data(const QModelIndex &index, int role) const
1352+{
1353+ QVariant rv;
1354+
1355+ if (index.row() >= m_files.size())
1356+ return rv;
1357+
1358+ switch (role)
1359+ {
1360+ case Roles::FileNameRole:
1361+ rv = m_files.at(index.row()).fileName;
1362+ break;
1363+ case Roles::FilePathRole:
1364+ rv = m_files.at(index.row()).filePath;
1365+ break;
1366+ case Roles::FileBaseNameRole:
1367+ rv = m_files.at(index.row()).baseName;
1368+ break;
1369+ case Roles::FileSuffixRole:
1370+ rv = m_files.at(index.row()).suffix;
1371+ break;
1372+ case Roles::FileSizeRole:
1373+ rv = m_files.at(index.row()).size;
1374+ break;
1375+ case Roles::FileModifiedRole:
1376+ rv = QDateTime();
1377+ break;
1378+ case Roles::FileAccessedRole:
1379+ rv = QDateTime();
1380+ break;
1381+ case Roles::FileIsDirRole:
1382+ rv = m_files.at(index.row()).isDir;
1383+ break;
1384+ case Roles::FileURLRole:
1385+ rv = QUrl::fromLocalFile(m_files.at(index.row()).filePath);
1386+ break;
1387+ default:
1388+ break;
1389+ }
1390+ return rv;
1391+}
1392+
1393+QModelIndex MockFolderListModel::index(int row, int column, const QModelIndex&) const
1394+{
1395+ return createIndex(row, column);
1396+}
1397+
1398+void MockFolderListModel::mockAddFile(const QString &fileName,
1399+ const QString &filePath,
1400+ const QString &baseName,
1401+ const qint64 &size,
1402+ const QString &suffix,
1403+ const bool isDir,
1404+ const bool isFile)
1405+{
1406+ MockFile m;
1407+ m.fileName = fileName;
1408+ m.filePath = filePath;
1409+ m.baseName = baseName;
1410+ m.size = size;
1411+ m.suffix = suffix;
1412+ m.isDir = isDir;
1413+ m.isFile = isFile;
1414+ m_files.append(m);
1415+}
1416
1417=== added file 'tests/qmltests/mocks/Qt/labs/folderlistmodel/MockFolderListModel.h'
1418--- tests/qmltests/mocks/Qt/labs/folderlistmodel/MockFolderListModel.h 1970-01-01 00:00:00 +0000
1419+++ tests/qmltests/mocks/Qt/labs/folderlistmodel/MockFolderListModel.h 2017-01-25 13:04:17 +0000
1420@@ -0,0 +1,171 @@
1421+/*
1422+ * Copyright (C) 2016 Canonical, Ltd.
1423+ *
1424+ * This program is free software; you can redistribute it and/or modify
1425+ * it under the terms of the GNU General Public License as published by
1426+ * the Free Software Foundation; version 3.
1427+ *
1428+ * This program is distributed in the hope that it will be useful,
1429+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1430+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1431+ * GNU General Public License for more details.
1432+ *
1433+ * You should have received a copy of the GNU General Public License
1434+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1435+ */
1436+
1437+#ifndef MOCK_FOLDERLISTMODEL_H
1438+#define MOCK_FOLDERLISTMODEL_H
1439+
1440+#include <QAbstractListModel>
1441+#include <QObject>
1442+#include <QString>
1443+#include <QUrl>
1444+#include <QStringList>
1445+
1446+struct MockFile {
1447+ QString fileName;
1448+ QString filePath;
1449+ QString baseName;
1450+ qint64 size;
1451+ QString suffix;
1452+ bool isDir;
1453+ bool isFile;
1454+};
1455+
1456+class MockFolderListModel : public QAbstractListModel
1457+{
1458+ Q_OBJECT
1459+ Q_ENUMS(Sort)
1460+ Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged)
1461+ Q_PROPERTY(bool caseSensitive READ caseSensitive
1462+ WRITE setCaseSensitive NOTIFY caseSensitiveChanged)
1463+ Q_PROPERTY(int count READ count
1464+ WRITE setCount NOTIFY countChanged)
1465+ Q_PROPERTY(QStringList nameFilters READ nameFilters
1466+ WRITE setNameFilters NOTIFY nameFiltersChanged)
1467+ Q_PROPERTY(QUrl parentFolder READ parentFolder
1468+ WRITE setParentFolder NOTIFY parentFolderChanged)
1469+ Q_PROPERTY(QUrl rootFolder READ rootFolder
1470+ WRITE setRootFolder NOTIFY rootFolderChanged)
1471+ Q_PROPERTY(bool showDirs READ showDirs
1472+ WRITE setShowDirs NOTIFY showDirsChanged)
1473+ Q_PROPERTY(bool showDirsFirst READ showDirsFirst
1474+ WRITE setShowDirsFirst NOTIFY showDirsFirstChanged)
1475+ Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot
1476+ WRITE setShowDotAndDotDot NOTIFY showDotAndDotDotChanged)
1477+ Q_PROPERTY(bool showFiles READ showFiles
1478+ WRITE setShowFiles NOTIFY showFilesChanged)
1479+ Q_PROPERTY(bool showHidden READ showHidden
1480+ WRITE setShowHidden NOTIFY showHiddenChanged)
1481+ Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable
1482+ WRITE setShowOnlyReadable NOTIFY showOnlyReadableChanged)
1483+ Q_PROPERTY(Sort sortField READ sortField
1484+ WRITE setSortField NOTIFY sortFieldChanged)
1485+ Q_PROPERTY(bool sortReversed READ sortReversed
1486+ WRITE setSortReversed NOTIFY sortReversedChanged)
1487+
1488+public:
1489+ explicit MockFolderListModel(QObject *parent = 0);
1490+
1491+ enum Roles {
1492+ FileNameRole = Qt::DisplayRole + 1,
1493+ FilePathRole,
1494+ FileURLRole,
1495+ FileBaseNameRole,
1496+ FileSuffixRole,
1497+ FileSizeRole,
1498+ FileModifiedRole,
1499+ FileAccessedRole,
1500+ FileIsDirRole
1501+ };
1502+
1503+ enum class Sort : uint
1504+ {
1505+ Unsorted = 0,
1506+ Name,
1507+ Time,
1508+ Size,
1509+ Type
1510+ };
1511+
1512+ QUrl folder() const;
1513+ bool caseSensitive() const;
1514+ int count() const;
1515+ QStringList nameFilters() const;
1516+ QUrl parentFolder() const;
1517+ QUrl rootFolder() const;
1518+ bool showDirs() const;
1519+ bool showDirsFirst() const;
1520+ bool showDotAndDotDot() const;
1521+ bool showFiles() const;
1522+ bool showHidden() const;
1523+ bool showOnlyReadable() const;
1524+ Sort sortField() const;
1525+ bool sortReversed() const;
1526+
1527+ void setCaseSensitive(const QUrl &folder);
1528+ void setCaseSensitive(const bool caseSensitive);
1529+ void setCount(const int &count);
1530+ void setFolder(const QUrl &folder);
1531+ void setNameFilters(const QStringList &nameFilters);
1532+ void setParentFolder(const QUrl &parentFolder);
1533+ void setRootFolder(const QUrl &rootFolder);
1534+ void setShowDirs(const bool showDirs);
1535+ void setShowDirsFirst(const bool showDirsFirst);
1536+ void setShowDotAndDotDot(const bool showDotAndDotDot);
1537+ void setShowFiles(const bool showFiles);
1538+ void setShowHidden(const bool showHidden);
1539+ void setShowOnlyReadable(const bool showOnlyReadable);
1540+ void setSortField(const Sort &sortField);
1541+ void setSortReversed(const bool sortReversed);
1542+
1543+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
1544+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override;
1545+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
1546+ QHash<int, QByteArray> roleNames() const override;
1547+
1548+ Q_INVOKABLE void mockAddFile(const QString &fileName,
1549+ const QString &filePath,
1550+ const QString &baseName,
1551+ const qint64 &size,
1552+ const QString &suffix,
1553+ const bool isDir,
1554+ const bool isFile);
1555+
1556+Q_SIGNALS:
1557+ void caseSensitiveChanged();
1558+ void countChanged();
1559+ void folderChanged();
1560+ void nameFiltersChanged();
1561+ void parentFolderChanged();
1562+ void rootFolderChanged();
1563+ void showDirsChanged();
1564+ void showDirsFirstChanged();
1565+ void showDotAndDotDotChanged();
1566+ void showFilesChanged();
1567+ void showHiddenChanged();
1568+ void showOnlyReadableChanged();
1569+ void sortFieldChanged();
1570+ void sortReversedChanged();
1571+
1572+private:
1573+ QUrl m_folder = QUrl();
1574+ bool m_caseSensitive = false;
1575+ int m_count = false;
1576+ QStringList m_nameFilters = QStringList();
1577+ QUrl m_parentFolder = QUrl();
1578+ QUrl m_rootFolder = QUrl();
1579+ bool m_showDirs = false;
1580+ bool m_showDirsFirst = false;
1581+ bool m_showDotAndDotDot = false;
1582+ bool m_showFiles = false;
1583+ bool m_showHidden = false;
1584+ bool m_showOnlyReadable = false;
1585+ Sort m_sortField = Sort::Unsorted;
1586+ bool m_sortReversed = false;
1587+
1588+ QList<MockFile> m_files;
1589+};
1590+
1591+#endif // MOCK_FOLDERLISTMODEL_H
1592
1593=== added file 'tests/qmltests/mocks/Qt/labs/folderlistmodel/plugin.cpp'
1594--- tests/qmltests/mocks/Qt/labs/folderlistmodel/plugin.cpp 1970-01-01 00:00:00 +0000
1595+++ tests/qmltests/mocks/Qt/labs/folderlistmodel/plugin.cpp 2017-01-25 13:04:17 +0000
1596@@ -0,0 +1,26 @@
1597+/*
1598+ * Copyright (C) 2016 Canonical, Ltd.
1599+ *
1600+ * This program is free software; you can redistribute it and/or modify
1601+ * it under the terms of the GNU General Public License as published by
1602+ * the Free Software Foundation; version 3.
1603+ *
1604+ * This program is distributed in the hope that it will be useful,
1605+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1606+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1607+ * GNU General Public License for more details.
1608+ *
1609+ * You should have received a copy of the GNU General Public License
1610+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1611+ */
1612+
1613+#include "plugin.h"
1614+#include "MockFolderListModel.h"
1615+
1616+#include <QtQml/qqml.h>
1617+
1618+void MockQtLabsFolderListModelPlugin::registerTypes(const char *uri)
1619+{
1620+ Q_ASSERT(uri == QLatin1String("Qt.labs.folderlistmodel"));
1621+ qmlRegisterType<MockFolderListModel>(uri, 2, 1, "FolderListModel");
1622+}
1623
1624=== added file 'tests/qmltests/mocks/Qt/labs/folderlistmodel/plugin.h'
1625--- tests/qmltests/mocks/Qt/labs/folderlistmodel/plugin.h 1970-01-01 00:00:00 +0000
1626+++ tests/qmltests/mocks/Qt/labs/folderlistmodel/plugin.h 2017-01-25 13:04:17 +0000
1627@@ -0,0 +1,31 @@
1628+/*
1629+ * Copyright (C) 2016 Canonical, Ltd.
1630+ *
1631+ * This program is free software; you can redistribute it and/or modify
1632+ * it under the terms of the GNU General Public License as published by
1633+ * the Free Software Foundation; version 3.
1634+ *
1635+ * This program is distributed in the hope that it will be useful,
1636+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1637+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1638+ * GNU General Public License for more details.
1639+ *
1640+ * You should have received a copy of the GNU General Public License
1641+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1642+ */
1643+
1644+#ifndef QTLABS_FOLDERLISTMODEL_PLUGIN_H
1645+#define QTLABS_FOLDERLISTMODEL_PLUGIN_H
1646+
1647+#include <QtQml/QQmlExtensionPlugin>
1648+
1649+class MockQtLabsFolderListModelPlugin : public QQmlExtensionPlugin
1650+{
1651+ Q_OBJECT
1652+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
1653+
1654+public:
1655+ void registerTypes(const char *uri) override;
1656+};
1657+
1658+#endif // QTLABS_FOLDERLISTMODEL_PLUGIN_H
1659
1660=== added file 'tests/qmltests/mocks/Qt/labs/folderlistmodel/qmldir'
1661--- tests/qmltests/mocks/Qt/labs/folderlistmodel/qmldir 1970-01-01 00:00:00 +0000
1662+++ tests/qmltests/mocks/Qt/labs/folderlistmodel/qmldir 2017-01-25 13:04:17 +0000
1663@@ -0,0 +1,2 @@
1664+module Qt.labs.folderlistmodel
1665+plugin QtLabsFolderListModelQml

Subscribers

People subscribed via source and target branches

to all changes: