Merge lp:~ibelieve/ubuntu-filemanager-app/improved-toolbar into lp:ubuntu-filemanager-app

Proposed by Michael Spencer
Status: Merged
Approved by: Arto Jalkanen
Approved revision: 56
Merged at revision: 38
Proposed branch: lp:~ibelieve/ubuntu-filemanager-app/improved-toolbar
Merge into: lp:ubuntu-filemanager-app
Prerequisite: lp:~ibelieve/ubuntu-filemanager-app/improved-ui
Diff against target: 993 lines (+625/-106)
12 files modified
ConfirmDialog.qml (+13/-0)
ConfirmDialogWithInput.qml (+17/-0)
FileDetailsPopover.qml (+22/-7)
FileOperationProgressDialog.qml (+8/-0)
FolderListDelegate.qml (+3/-6)
FolderListPage.qml (+276/-50)
FolderListView.qml (+26/-22)
PlacesPopover.qml (+137/-0)
SettingsPopover.qml (+75/-0)
tests/autopilot/ubuntu_filemanager_app/emulators/main_window.py (+6/-1)
tests/autopilot/ubuntu_filemanager_app/tests/test_filemanager.py (+35/-6)
ubuntu-filemanager-app.qml (+7/-14)
To merge this branch: bzr merge lp:~ibelieve/ubuntu-filemanager-app/improved-toolbar
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Arto Jalkanen Approve
Review via email: mp+171639@code.launchpad.net

Commit message

Redesigned the toolbar and added settings and some new features

Description of the change

This adds the following new features to the toolbar:

* Places (bookmarks) menu & location entry field
* Actions menu
* Settings menu

This also adds the following new settings:

* Show hidden files
* Sort by name/date
* Sort ascending/descending

In addition, this adds a Properties popover for the current folder.

To post a comment you must log in.
44. By Michael Spencer

Fixed paste action and made minor changes in order of actions and naming of dialogs

45. By Michael Spencer

Disabled hiding of paste action (doesn't work)

46. By Michael Spencer

Added settings menu and ability to show hidden files

47. By Michael Spencer

Added UI to sort the list of files

48. By Michael Spencer

Pulled in autopilot test and fixed it to work with the new UI

49. By Michael Spencer

Added test for going home and to the root folder (fixed LP# 1188734)

50. By Michael Spencer

Added UI to go to a location entered by the user

51. By Michael Spencer

Improved location entry UI

52. By Michael Spencer

Added path entry validation

53. By Michael Spencer

Added properties popover for the current folder and also added icons for file system root, home folder, and main folders in home

54. By Michael Spencer

Added more icons for common folders

Revision history for this message
Arto Jalkanen (ajalkane) wrote :

Great changes, thank you!

review: Approve
Revision history for this message
David Planella (dpm) wrote :

Nice work!

A couple of things that I've noticed:

- The toolbar icons are highly pixelated. Nothing that your branch can do about it, as it might be due to bug 1184569. Perhaps it might be worth shipping local copies of .png images until that bug is fixed?
- The properties popup for folders seem to always return "Unknown" for "Created:" and "Modified:"

55. By Michael Spencer

Added local png icons for the toolbar

Revision history for this message
Michael Spencer (ibelieve) wrote :

> Nice work!
>
> A couple of things that I've noticed:
>
> - The toolbar icons are highly pixelated. Nothing that your branch can do
> about it, as it might be due to bug 1184569. Perhaps it might be worth
> shipping local copies of .png images until that bug is fixed?

I've added local copies for the 4 icons in the toolbar.

> - The properties popup for folders seem to always return "Unknown" for
> "Created:" and "Modified:"

Clicking on a folder and choosing Properties should work. If you mean clicking Actions and then Properties, that is because it's using new features from the model that Carlos just added, so it won't show up until the plugin gets updated. (Same with the current folder being writable or not).

56. By Michael Spencer

Colored the cancel buttons gray and made the go to location button green

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ConfirmDialog.qml'
--- ConfirmDialog.qml 2013-04-17 17:55:41 +0000
+++ ConfirmDialog.qml 2013-07-03 15:05:30 +0000
@@ -35,6 +35,19 @@
3535
36 Button {36 Button {
37 text: i18n.tr("Cancel")37 text: i18n.tr("Cancel")
38
39 gradient: Gradient {
40 GradientStop {
41 position: 0
42 color: "gray"
43 }
44
45 GradientStop {
46 position: 1
47 color: "lightgray"
48 }
49 }
50
38 onClicked: {51 onClicked: {
39 rejected()52 rejected()
40 PopupUtils.close(root)53 PopupUtils.close(root)
4154
=== modified file 'ConfirmDialogWithInput.qml'
--- ConfirmDialogWithInput.qml 2013-04-17 17:55:41 +0000
+++ ConfirmDialogWithInput.qml 2013-07-03 15:05:30 +0000
@@ -29,10 +29,14 @@
29 TextField {29 TextField {
30 id: input30 id: input
31 focus: true31 focus: true
32 validator: RegExpValidator {
33 regExp: /.+/
34 }
32 }35 }
3336
34 Button {37 Button {
35 text: i18n.tr("Ok")38 text: i18n.tr("Ok")
39 enabled: input.acceptableInput
36 onClicked: {40 onClicked: {
37 accepted()41 accepted()
38 PopupUtils.close(root)42 PopupUtils.close(root)
@@ -41,6 +45,19 @@
4145
42 Button {46 Button {
43 text: i18n.tr("Cancel")47 text: i18n.tr("Cancel")
48
49 gradient: Gradient {
50 GradientStop {
51 position: 0
52 color: "gray"
53 }
54
55 GradientStop {
56 position: 1
57 color: "lightgray"
58 }
59 }
60
44 onClicked: {61 onClicked: {
45 rejected()62 rejected()
46 PopupUtils.close(root)63 PopupUtils.close(root)
4764
=== modified file 'FileDetailsPopover.qml'
--- FileDetailsPopover.qml 2013-06-25 23:43:54 +0000
+++ FileDetailsPopover.qml 2013-07-03 15:05:30 +0000
@@ -23,10 +23,12 @@
23 id: root23 id: root
24 property var model24 property var model
2525
26 property string path: model.path || (fileView.path + '/' + model.fileName)
27
26 contentHeight: contents.height + 2 * contents.anchors.margins28 contentHeight: contents.height + 2 * contents.anchors.margins
2729
28 function dateTimeFormat(dateTime) {30 function dateTimeFormat(dateTime) {
29 return Qt.formatDateTime(dateTime, Qt.DefaultLocaleShortDate)31 return Qt.formatDateTime(dateTime, Qt.DefaultLocaleShortDate) || "Uknown"
30 }32 }
3133
32 function permissionsToString(model) {34 function permissionsToString(model) {
@@ -66,22 +68,35 @@
66 Row {68 Row {
67 spacing: units.gu(1)69 spacing: units.gu(1)
68 Image {70 Image {
71 anchors.verticalCenter: parent.verticalCenter
72
69 // TODO: how to get proper icon?73 // TODO: how to get proper icon?
70 source: model.isDir74 source: fileIcon(root.path, model.isDir)
71 ? "/usr/share/icons/Humanity/places/48/folder.svg"
72 : "/usr/share/icons/Humanity/mimes/48/empty.svg"
73 }75 }
76
74 Label {77 Label {
75 text: model.fileName
76 anchors.verticalCenter: parent.verticalCenter78 anchors.verticalCenter: parent.verticalCenter
79
80 text: folderName(root.path)
81 font.bold: true
77 }82 }
78 }83 }
7984
80 Grid {85 Grid {
81 columns: 286 columns: 2
82 spacing: units.gu(1)87 spacing: units.gu(1)
83 Label {88
84 text: i18n.tr("Size:")89 Label {
90 text: i18n.tr("Path:")
91 }
92
93 Label {
94 text: root.path
95 }
96
97 Label {
98 text: model.isDir ? i18n.tr("Contents:")
99 : i18n.tr("Size:")
85 }100 }
86 Label {101 Label {
87 text: model.fileSize102 text: model.fileSize
88103
=== modified file 'FileOperationProgressDialog.qml'
--- FileOperationProgressDialog.qml 2013-05-16 15:32:16 +0000
+++ FileOperationProgressDialog.qml 2013-07-03 15:05:30 +0000
@@ -57,4 +57,12 @@
57 }57 }
58 }58 }
59 }59 }
60
61 // Errors from model
62 Connections {
63 target: pageModel
64 onError: {
65 PopupUtils.close(root)
66 }
67 }
60}68}
6169
=== modified file 'FolderListDelegate.qml'
--- FolderListDelegate.qml 2013-06-25 16:22:38 +0000
+++ FolderListDelegate.qml 2013-07-03 15:05:30 +0000
@@ -24,11 +24,8 @@
24 objectName: "folder" + index24 objectName: "folder" + index
25 text: model.fileName25 text: model.fileName
26 subText: Qt.formatDateTime(model.modifiedDate, Qt.DefaultLocaleShortDate) + (!model.isDir ? ", " + fileSize : "")26 subText: Qt.formatDateTime(model.modifiedDate, Qt.DefaultLocaleShortDate) + (!model.isDir ? ", " + fileSize : "")
27 // FIXME: hard coded path for icon, assumes Ubuntu desktop icon available.27
28 // Nemo mobile has icon provider. Have to figure out what's the proper way28 property string path: fileView.path + '/' + model.fileName
29 // to get "system wide" icons in Ubuntu Touch, or if we have to use29 icon: fileIcon(path, model.isDir)
30 // icons packaged into the application. Both folder and individual
31 // files will need an icon.
32 icon: model.isDir ? "/usr/share/icons/Humanity/places/48/folder.svg" : "/usr/share/icons/Humanity/mimes/48/empty.svg"
33 progression: model.isDir30 progression: model.isDir
34}31}
3532
=== modified file 'FolderListPage.qml'
--- FolderListPage.qml 2013-06-27 14:18:10 +0000
+++ FolderListPage.qml 2013-07-03 15:05:30 +0000
@@ -24,17 +24,146 @@
24 id: root24 id: root
25 anchors.fill: parent25 anchors.fill: parent
2626
27 title: folderName(folder)
28
29 property variant fileView: root
30
31 property bool showHiddenFiles: false
32
33 onShowHiddenFilesChanged: {
34 pageModel.showHiddenFiles = root.showHiddenFiles
35 }
36
37 property string sortingMethod: "Name"
38
39 onSortingMethodChanged: {
40 console.log("Sorting by: " + sortingMethod)
41 if (sortingMethod === "Name") {
42 pageModel.sortBy = FolderListModel.SortByName
43 } else if (sortingMethod === "Date") {
44 pageModel.sortBy = FolderListModel.SortByDate
45 } else {
46 // Something fatal happened!
47 console.log("ERROR: Invalid sort type:", sortingMethod)
48 }
49 }
50
51 property bool sortAccending: true
52
53 onSortAccendingChanged: {
54 console.log("Sorting accending: " + sortAccending)
55
56 if (sortAccending) {
57 pageModel.sortOrder = FolderListModel.SortAscending
58 } else {
59 pageModel.sortOrder = FolderListModel.SortDescending
60 }
61 }
62
63 // This stores the location using ~ to represent home
27 property string folder64 property string folder
28 title: folderName(pageModel.path)65 property string homeFolder: "~"
29 property string homeFolder: pageModel.homePath()66
67 // This replaces ~ with the actual home folder, since the
68 // plugin doesn't recognize the ~
69 property string path: folder.replace("~", pageModel.homePath())
70
71 function goHome() {
72 goTo(root.homeFolder)
73 }
74
75 function goTo(location) {
76 // Since the FolderListModel returns paths using the actual
77 // home folder, this replaces with ~ before actually going
78 // to the specified folder
79 while (location !== '/' && location.substring(location.lastIndexOf('/')+1) === "") {
80 location = location.substring(0, location.length - 1)
81 }
82
83 root.folder = location.replace(pageModel.homePath(), "~")
84 refresh()
85 }
86
87 function refresh() {
88 pageModel.refresh()
89 }
90
91 // FIXME: hard coded path for icon, assumes Ubuntu desktop icon available.
92 // Nemo mobile has icon provider. Have to figure out what's the proper way
93 // to get "system wide" icons in Ubuntu Touch, or if we have to use
94 // icons packaged into the application. Both folder and individual
95 // files will need an icon.
96 // TODO: Remove isDir parameter and use new model functions
97 function fileIcon(file, isDir) {
98 file = file.replace(pageModel.homePath(), "~")
99 if (file === "~") {
100 return "/usr/share/icons/ubuntu-mono-dark/places/48/folder-home.svg"
101 } else if (file === i18n.tr("~/Desktop")) {
102 return "/usr/share/icons/Humanity/places/48/user-desktop.svg"
103 } else if (file === i18n.tr("~/Documents")) {
104 return "/usr/share/icons/Humanity/places/48/folder-documents.svg"
105 } else if (file === i18n.tr("~/Downloads")) {
106 return "/usr/share/icons/Humanity/places/48/folder-downloads.svg"
107 } else if (file === i18n.tr("~/Music")) {
108 return "/usr/share/icons/Humanity/places/48/folder-music.svg"
109 } else if (file === i18n.tr("~/Pictures")) {
110 return "/usr/share/icons/Humanity/places/48/folder-pictures.svg"
111 } else if (file === i18n.tr("~/Public")) {
112 return "/usr/share/icons/Humanity/places/48/folder-publicshare.svg"
113 } else if (file === i18n.tr("~/Programs")) {
114 return "/usr/share/icons/Humanity/places/48/folder-system.svg"
115 } else if (file === i18n.tr("~/Templates")) {
116 return "/usr/share/icons/Humanity/places/48/folder-templates.svg"
117 } else if (file === i18n.tr("~/Videos")) {
118 return "/usr/share/icons/Humanity/places/48/folder-videos.svg"
119 } else if (file === "/") {
120 return "/usr/share/icons/Humanity/devices/48/drive-harddisk.svg"
121 }
122
123 if (isDir) {
124 return "/usr/share/icons/Humanity/places/48/folder.svg"
125 } else {
126 return "/usr/share/icons/Humanity/mimes/48/empty.svg"
127 }
128 }
30129
31 function folderName(folder) {130 function folderName(folder) {
32 if (folder === pageModel.homePath()) {131 folder = folder.replace(pageModel.homePath(), "~")
33 return "Home"132
133 if (folder === root.homeFolder) {
134 return i18n.tr("Home")
34 } else if (folder === "/") {135 } else if (folder === "/") {
35 return folder136 return i18n.tr("File System")
36 } else {137 } else {
37 return folder.substr(folder.lastIndexOf('/') + 1)138 return folder.substr(folder.lastIndexOf('/') + 1)
139 }
140 }
141
142 function pathName(folder) {
143 if (folder === "/") {
144 return "/"
145 } else {
146 return folder.substr(folder.lastIndexOf('/') + 1)
147 }
148 }
149
150 function pathExists(path) {
151 path = path.replace("~", pageModel.homePath())
152
153 if (path === '/')
154 return true
155
156 if(path.charAt(0) === '/') {
157 console.log("Directory: " + path.substring(0, path.lastIndexOf('/')+1))
158 repeaterModel.path = path.substring(0, path.lastIndexOf('/')+1)
159 console.log("Sub dir: " + path.substring(path.lastIndexOf('/')+1))
160 if (path.substring(path.lastIndexOf('/')+1) !== "" && !repeaterModel.cdIntoPath(path.substring(path.lastIndexOf('/')+1))) {
161 return false
162 } else {
163 return true
164 }
165 } else {
166 return false
38 }167 }
39 }168 }
40169
@@ -42,13 +171,103 @@
42171
43 FolderListModel {172 FolderListModel {
44 id: pageModel173 id: pageModel
174
175 path: root.path
176
177 // Properties to emulate a model entry for use by FileDetailsPopover
178 property bool isDir: true
179 property string fileName: pathName(pageModel.path)
180 property string fileSize: (folderListView.count === 1
181 ? i18n.tr("1 file")
182 : i18n.tr("%1 files").arg(folderListView.count))
183 property date creationDate: pageModel.pathCreatedDate
184 property date modifiedDate: pageModel.pathModifiedDate
185 property bool isWriteable: pageModel.pathIsWriteable
186 property bool isReadable: true
187 property bool isExecutable: true
188 }
189
190 FolderListModel {
191 id: repeaterModel
45 path: root.folder192 path: root.folder
193
194 onPathChanged: {
195 console.log("Path: " + repeaterModel.path)
196 }
197 }
198
199 ActionSelectionPopover {
200 id: folderActionsPopover
201 objectName: "folderActionsPopover"
202
203 actions: ActionList {
204 Action {
205 text: i18n.tr("Create New Folder")
206 onTriggered: {
207 print(text)
208
209 PopupUtils.open(createFolderDialog, root)
210 }
211 }
212
213 // TODO: Disabled until backend supports creating files
214// Action {
215// text: i18n.tr("Create New File")
216// onTriggered: {
217// print(text)
218
219// PopupUtils.open(createFileDialog, root)
220// }
221// }
222
223 Action {
224 text: pageModel.clipboardUrlsCounter === 0
225 ? i18n.tr("Paste")
226 : pageModel.clipboardUrlsCounter === 1
227 ? i18n.tr("Paste %1 File").arg(pageModel.clipboardUrlsCounter)
228 : i18n.tr("Paste %1 Files").arg(pageModel.clipboardUrlsCounter)
229 onTriggered: {
230 console.log("Pasting to current folder items of count " + pageModel.clipboardUrlsCounter)
231 PopupUtils.open(Qt.resolvedUrl("FileOperationProgressDialog.qml"),
232 root,
233 {
234 title: i18n.tr("Paste files"),
235 folderListModel: pageModel
236 }
237 )
238
239
240 pageModel.paste()
241 }
242
243 // FIXME: This property is depreciated and doesn't seem to work!
244 //visible: pageModel.clipboardUrlsCounter > 0
245
246 enabled: pageModel.clipboardUrlsCounter > 0
247 }
248
249 Action {
250 text: i18n.tr("Properties")
251 onTriggered: {
252 print(text)
253 PopupUtils.open(Qt.resolvedUrl("FileDetailsPopover.qml"),
254 root,
255 { "model": pageModel
256 }
257 )
258 }
259 }
260 }
261
262 // Without this the popover jumps up at the start of the application. SDK bug?
263 // Bug report has been made of these https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1152270
264 visible: false
46 }265 }
47266
48 Component {267 Component {
49 id: createFolderDialog268 id: createFolderDialog
50 ConfirmDialogWithInput {269 ConfirmDialogWithInput {
51 title: i18n.tr("Create folder?")270 title: i18n.tr("Create folder")
52 text: i18n.tr("Enter name for new folder")271 text: i18n.tr("Enter name for new folder")
53272
54 onAccepted: {273 onAccepted: {
@@ -62,6 +281,25 @@
62 }281 }
63 }282 }
64283
284 Component {
285 id: createFileDialog
286 ConfirmDialogWithInput {
287 title: i18n.tr("Create file")
288 text: i18n.tr("Enter name for new file")
289
290 onAccepted: {
291 console.log("Create file accepted", inputText)
292 if (inputText !== '') {
293 //FIXME: Actually create a new file!
294 } else {
295 console.log("Empty file name, ignored")
296 }
297 }
298 }
299 }
300
301
302
65 tools: ToolbarItems {303 tools: ToolbarItems {
66 id: toolbar304 id: toolbar
67 locked: true305 locked: true
@@ -69,7 +307,7 @@
69307
70 back: ToolbarButton {308 back: ToolbarButton {
71 text: "Up"309 text: "Up"
72 iconSource: "/usr/share/icons/ubuntu-mobile/actions/scalable/keyboard-caps.svg"310 iconSource: "icons/up.png"
73 visible: folder != "/"311 visible: folder != "/"
74 onTriggered: {312 onTriggered: {
75 goTo(pageModel.parentPath)313 goTo(pageModel.parentPath)
@@ -77,52 +315,40 @@
77 }315 }
78316
79 ToolbarButton {317 ToolbarButton {
80 text: i18n.tr("Paste" + " (" + pageModel.clipboardUrlsCounter + ")")318 text: i18n.tr("Actions")
81 // TODO: temporary319 iconSource: "icons/edit.png"
82 iconSource: "/usr/share/icons/Humanity/actions/48/edit-paste.svg"320
83 onTriggered: {321 onTriggered: {
84 console.log("Pasting to current folder items of count " + pageModel.clipboardUrlsCounter)322 print(text)
85 PopupUtils.open(Qt.resolvedUrl("FileOperationProgressDialog.qml"),323 folderActionsPopover.caller = caller
86 root,324 folderActionsPopover.show();
87 {325 }
88 title: i18n.tr("Paste files"),326 }
89 folderListModel: pageModel327
90 }328 ToolbarButton {
91 )329 text: i18n.tr("Settings")
92330 iconSource: "icons/settings.png"
93331
94 pageModel.paste()332 onTriggered: {
95 }333 print(text)
96 visible: pageModel.clipboardUrlsCounter > 0334
97 }335 PopupUtils.open(Qt.resolvedUrl("SettingsPopover.qml"), caller)
98336 }
99 // IMPROVE: would rather have this as more hidden, in a separate menu that has337 }
100 // file manipulation operations338
101 ToolbarButton {339 ToolbarButton {
102 text: i18n.tr("Create folder")340 text: i18n.tr("Places")
103 // TODO: temporary341 iconSource: "icons/location.png"
104 iconSource: "/usr/share/icons/ubuntu-mobile/actions/scalable/add.svg"342 onTriggered: {
105 onTriggered: {343 print(text)
106 print(text)344
107 PopupUtils.open(createFolderDialog, root)345 PopupUtils.open(Qt.resolvedUrl("PlacesPopover.qml"), caller)
108 }
109 }
110
111 ToolbarButton {
112 text: i18n.tr("Home")
113 // TODO: temporary
114 iconSource: "/usr/share/icons/ubuntu-mobile/actions/scalable/go-to.svg"
115 onTriggered: {
116 goHome()
117
118 //pageModel.path = pageModel.homePath()
119 console.log("Home triggered")
120 }346 }
121 }347 }
122 }348 }
123349
124 Column {350 Column {
125 anchors.centerIn: root351 anchors.centerIn: parent
126 Label {352 Label {
127 text: i18n.tr("No files")353 text: i18n.tr("No files")
128 fontSize: "large"354 fontSize: "large"
129355
=== modified file 'FolderListView.qml'
--- FolderListView.qml 2013-06-27 14:21:42 +0000
+++ FolderListView.qml 2013-07-03 15:05:30 +0000
@@ -28,10 +28,11 @@
28 property string folderPath: folderListModel.path28 property string folderPath: folderListModel.path
29 model: folderListModel29 model: folderListModel
3030
31 header: Caption {31 header: Header {
32 objectName: "directoryHeader"32 objectName: "directoryHeader"
33 text: (root.count == 1 ? i18n.tr("%1 (%2 file)").arg(root.folderPath).arg(root.count) :33 text: (root.count == 1
34 i18n.tr("%1 (%2 files)").arg(root.folderPath).arg(root.count))34 ? i18n.tr("%1 (1 file)").arg(root.folderPath)
35 : i18n.tr("%1 (%2 files)").arg(root.folderPath).arg(root.count))
35 }36 }
3637
37 Component {38 Component {
@@ -71,7 +72,7 @@
71 // the filesystem, but may be a problem in the future.72 // the filesystem, but may be a problem in the future.
72 property int modelRow73 property int modelRow
7374
74 title: i18n.tr("Rename?")75 title: i18n.tr("Rename")
75 text: i18n.tr("Enter a new name")76 text: i18n.tr("Enter a new name")
7677
77 onAccepted: {78 onAccepted: {
@@ -100,16 +101,16 @@
100 property var model101 property var model
101 actions: ActionList {102 actions: ActionList {
102 Action {103 Action {
103 text: i18n.tr("Show details")104 text: i18n.tr("Cut")
105 // TODO: temporary
106 iconSource: "/usr/share/icons/Humanity/actions/48/edit-cut.svg"
104 onTriggered: {107 onTriggered: {
105 print(text)108 console.log("Cut on row called for", actionSelectionPopover.model.fileName, actionSelectionPopover.model.index)
106 PopupUtils.open(Qt.resolvedUrl("FileDetailsPopover.qml"),109 model.cutIndex(actionSelectionPopover.model.index)
107 actionSelectionPopover.caller,110 console.log("CliboardUrlsCounter after copy", folderListModel.clipboardUrlsCounter)
108 { "model": actionSelectionPopover.model
109 }
110 )
111 }111 }
112 }112 }
113
113 Action {114 Action {
114 text: i18n.tr("Copy")115 text: i18n.tr("Copy")
115 // TODO: temporary.116 // TODO: temporary.
@@ -121,16 +122,7 @@
121 console.log("CliboardUrlsCounter after copy", folderListModel.clipboardUrlsCounter)122 console.log("CliboardUrlsCounter after copy", folderListModel.clipboardUrlsCounter)
122 }123 }
123 }124 }
124 Action {125
125 text: i18n.tr("Cut")
126 // TODO: temporary
127 iconSource: "/usr/share/icons/Humanity/actions/48/edit-cut.svg"
128 onTriggered: {
129 console.log("Cut on row called for", actionSelectionPopover.model.fileName, actionSelectionPopover.model.index)
130 model.cutIndex(actionSelectionPopover.model.index)
131 console.log("CliboardUrlsCounter after copy", folderListModel.clipboardUrlsCounter)
132 }
133 }
134 Action {126 Action {
135 text: i18n.tr("Delete")127 text: i18n.tr("Delete")
136 // TODO: temporary128 // TODO: temporary
@@ -142,7 +134,8 @@
142 "fileName" : actionSelectionPopover.model.fileName }134 "fileName" : actionSelectionPopover.model.fileName }
143 )135 )
144 }136 }
145 } 137 }
138
146 Action {139 Action {
147 text: i18n.tr("Rename")140 text: i18n.tr("Rename")
148 // TODO: temporary141 // TODO: temporary
@@ -156,6 +149,17 @@
156 }149 }
157 }150 }
158151
152 Action {
153 text: i18n.tr("Properties")
154 onTriggered: {
155 print(text)
156 PopupUtils.open(Qt.resolvedUrl("FileDetailsPopover.qml"),
157 actionSelectionPopover.caller,
158 { "model": actionSelectionPopover.model
159 }
160 )
161 }
162 }
159 }163 }
160 // TODO: problem: clicking outside popup makes the click go through to the164 // TODO: problem: clicking outside popup makes the click go through to the
161 // folder listview, so for example you'd change directory while only trying165 // folder listview, so for example you'd change directory while only trying
162166
=== added file 'PlacesPopover.qml'
--- PlacesPopover.qml 1970-01-01 00:00:00 +0000
+++ PlacesPopover.qml 2013-07-03 15:05:30 +0000
@@ -0,0 +1,137 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michael Spencer <spencers1993@gmail.com>
17 */
18import QtQuick 2.0
19import Ubuntu.Components 0.1
20import Ubuntu.Components.Popups 0.1
21import Ubuntu.Components.ListItems 0.1
22
23Popover {
24 id: root
25 objectName: "placesPopover"
26
27 ListModel {
28 id: places
29
30 ListElement {
31 path: "~"
32 }
33
34 ListElement {
35 path: "~/Documents"
36 }
37
38 ListElement {
39 path: "~/Downloads"
40 }
41
42 ListElement {
43 path: "~/Music"
44 }
45
46 ListElement {
47 path: "~/Pictures"
48 }
49
50 ListElement {
51 path: "~/Videos"
52 }
53
54 ListElement {
55 path: "/"
56 }
57 }
58
59 Column {
60 anchors {
61 left: parent.left
62 right: parent.right
63 top: parent.top
64 }
65
66 Repeater {
67 id: placesList
68 objectName: "placesList"
69
70 model: places
71
72 delegate: Standard {
73 text: folderName(path)
74 icon: model.icon || fileIcon(model.path, true)
75
76 onClicked: {
77 PopupUtils.close(root)
78 goTo(model.path)
79 }
80 }
81 }
82
83 Empty {
84
85 TextField {
86 id: locationField
87 anchors {
88 verticalCenter: parent.verticalCenter
89 left: parent.left
90 right: goButton.left
91 margins: units.gu(1)
92 }
93
94 inputMethodHints: Qt.ImhNoAutoUppercase
95
96 property bool valid: pathExists(text)
97
98 text: fileView.path
99
100 placeholderText: i18n.tr("Location...")
101
102 onAccepted: goButton.clicked()
103 }
104
105 Button {
106 id: goButton
107 anchors {
108 top: locationField.top
109 bottom: locationField.bottom
110 right: parent.right
111 rightMargin: units.gu(1)
112 }
113
114 gradient: Gradient {
115 GradientStop {
116 position: 0
117 color: "green"//Qt.rgba(0,0.7,0,1)
118 }
119
120 GradientStop {
121 position: 1
122 color: Qt.rgba(0.3,0.7,0.3,1)
123 }
124 }
125
126 text: i18n.tr("Go")
127 enabled: locationField.acceptableInput && locationField.valid
128
129 onClicked: {
130 print("User switched to:", locationField.text)
131 goTo(locationField.text)
132 PopupUtils.close(root)
133 }
134 }
135 }
136 }
137}
0138
=== added file 'SettingsPopover.qml'
--- SettingsPopover.qml 1970-01-01 00:00:00 +0000
+++ SettingsPopover.qml 2013-07-03 15:05:30 +0000
@@ -0,0 +1,75 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michael Spencer <spencers1993@gmail.com>
17 */
18import QtQuick 2.0
19import Ubuntu.Components 0.1
20import Ubuntu.Components.Popups 0.1
21import Ubuntu.Components.ListItems 0.1
22
23Popover {
24 id: root
25 objectName: "settingsPopover"
26
27 Column {
28 anchors {
29 left: parent.left
30 right: parent.right
31 top: parent.top
32 }
33
34 Standard {
35 id: showHiddenFileCheckBox
36 objectName: "showHiddenFileCheckBox"
37
38 text: i18n.tr("Show Hidden Files")
39 control: CheckBox {
40 anchors.verticalCenter: parent.verticalCenter
41
42 checked: fileView.showHiddenFiles
43 onCheckedChanged: {
44 fileView.showHiddenFiles = checked
45 }
46 }
47 }
48
49 ValueSelector {
50 text: "Sort By"
51 selectedIndex: values.indexOf(fileView.sortingMethod)
52 values: [
53 "Name",
54 "Date"
55 ]
56
57 onSelectedIndexChanged: {
58 fileView.sortingMethod = values[selectedIndex]
59 }
60 }
61
62 ValueSelector {
63 text: "Sort Order"
64 selectedIndex: sortAccending ? 0 : 1
65 values: [
66 "Ascending",
67 "Descending"
68 ]
69
70 onSelectedIndexChanged: {
71 fileView.sortAccending = (values[selectedIndex] === "Ascending")
72 }
73 }
74 }
75}
076
=== added directory 'icons'
=== added file 'icons/edit.png'
1Binary files icons/edit.png 1970-01-01 00:00:00 +0000 and icons/edit.png 2013-07-03 15:05:30 +0000 differ77Binary files icons/edit.png 1970-01-01 00:00:00 +0000 and icons/edit.png 2013-07-03 15:05:30 +0000 differ
=== added file 'icons/location.png'
2Binary files icons/location.png 1970-01-01 00:00:00 +0000 and icons/location.png 2013-07-03 15:05:30 +0000 differ78Binary files icons/location.png 1970-01-01 00:00:00 +0000 and icons/location.png 2013-07-03 15:05:30 +0000 differ
=== added file 'icons/settings.png'
3Binary files icons/settings.png 1970-01-01 00:00:00 +0000 and icons/settings.png 2013-07-03 15:05:30 +0000 differ79Binary files icons/settings.png 1970-01-01 00:00:00 +0000 and icons/settings.png 2013-07-03 15:05:30 +0000 differ
=== added file 'icons/up.png'
4Binary files icons/up.png 1970-01-01 00:00:00 +0000 and icons/up.png 2013-07-03 15:05:30 +0000 differ80Binary files icons/up.png 1970-01-01 00:00:00 +0000 and icons/up.png 2013-07-03 15:05:30 +0000 differ
=== modified file 'tests/autopilot/ubuntu_filemanager_app/emulators/main_window.py'
--- tests/autopilot/ubuntu_filemanager_app/emulators/main_window.py 2013-06-27 14:18:10 +0000
+++ tests/autopilot/ubuntu_filemanager_app/emulators/main_window.py 2013-07-03 15:05:30 +0000
@@ -18,7 +18,10 @@
1818
19 def get_folder(self, index):19 def get_folder(self, index):
20 """Returns the list view folder with index number."""20 """Returns the list view folder with index number."""
21 return self.app.select_many("Subtitled")[index]21 return self.app.select_single('FolderListPage').select_many("Subtitled")[index]
22
23 def get_folder_count(self):
24 return len(self.app.select_single('FolderListPage').select_many("Subtitled"))
2225
23 def get_action_popover(self):26 def get_action_popover(self):
24 # Returns all instances, but with current one as first index27 # Returns all instances, but with current one as first index
@@ -27,3 +30,5 @@
27 def get_current_folder_name(self):30 def get_current_folder_name(self):
28 return self.app.select_single('FolderListView').folderPath31 return self.app.select_single('FolderListView').folderPath
2932
33 def get_page_title(self):
34 return self.app.select_single('FolderListPage').title
3035
=== modified file 'tests/autopilot/ubuntu_filemanager_app/tests/test_filemanager.py'
--- tests/autopilot/ubuntu_filemanager_app/tests/test_filemanager.py 2013-06-27 14:18:10 +0000
+++ tests/autopilot/ubuntu_filemanager_app/tests/test_filemanager.py 2013-07-03 15:05:30 +0000
@@ -36,8 +36,17 @@
36 patcher.start()36 patcher.start()
37 self.addCleanup(patcher.stop)37 self.addCleanup(patcher.stop)
3838
39 def test_toolbar_shows(self):39 def _get_place(self, name):
40 """Dragging from the bottom reveals the hidden toolbar."""40 """Returns the place/bookmark with index number."""
41 self.ubuntusdk.click_toolbar_button('Places')
42 places_popover = self.app.select_single('Popover', objectName='placesPopover')
43 places = places_popover.select_many('Standard')
44 for place in places:
45 if place.text == name:
46 return place
47
48 def test_file_actions_shows(self):
49 """Checks to make sure that the file actions popover is shown."""
41 self._make_directory_in_home()50 self._make_directory_in_home()
4251
43 first_folder = self.main_window.get_folder(0)52 first_folder = self.main_window.get_folder(0)
@@ -50,10 +59,12 @@
50 path = tempfile.mkdtemp(dir=os.environ['HOME'])59 path = tempfile.mkdtemp(dir=os.environ['HOME'])
51 # Currently, we need to open again the home folder to show the newly60 # Currently, we need to open again the home folder to show the newly
52 # created one. See bug #1190676.61 # created one. See bug #1190676.
53 # TODO when the bug is fixed, remove the next line.62 # TODO when the bug is fixed, remove the following lines up to the assert line
54 self.ubuntusdk.click_toolbar_button('Home')63 home_place = self._get_place("Home")
55 while self.app.select_single('FolderListPage').loading:64 self.pointing_device.click_object(home_place)
56 pass65
66 self.assertThat(self.main_window.get_folder_count, Eventually(Equals(1)))
67
57 return path68 return path
5869
59 def test_open_directory(self):70 def test_open_directory(self):
@@ -64,3 +75,21 @@
64 self.assertThat(75 self.assertThat(
65 self.main_window.get_current_folder_name,76 self.main_window.get_current_folder_name,
66 Eventually(Equals(sub_dir)))77 Eventually(Equals(sub_dir)))
78
79 def test_going_home(self):
80 home_place = self._get_place("Home")
81 self.pointing_device.click_object(home_place)
82
83 self._check_location("Home", os.environ['HOME'])
84
85 def test_going_to_root(self):
86 root_place = self._get_place("File System")
87 self.pointing_device.click_object(root_place)
88
89 self._check_location("File System", "/")
90
91 def _check_location(self,title,location):
92 self.assertThat(self.main_window.get_page_title, Eventually(Equals(title)))
93
94 self.assertThat(self.main_window.get_current_folder_name,
95 Eventually(Equals(location)))
6796
=== modified file 'ubuntu-filemanager-app.qml'
--- ubuntu-filemanager-app.qml 2013-06-27 14:18:10 +0000
+++ ubuntu-filemanager-app.qml 2013-07-03 15:05:30 +0000
@@ -26,29 +26,22 @@
26*/26*/
2727
28MainView {28MainView {
29 id: root
29 // objectName for functional testing purposes (autopilot-qt5)30 // objectName for functional testing purposes (autopilot-qt5)
30 objectName: "filemanager"31 objectName: "filemanager"
31 applicationName: "ubuntu-filemanager-app"32 applicationName: "ubuntu-filemanager-app"
32 33
33 width: units.gu(50)34 width: units.gu(50)
34 height: units.gu(75)35 height: units.gu(75)
35 36
37 property alias filemanager: root
38
39 property bool wideAspect: width >= units.gu(80)
40
36 FolderListPage {41 FolderListPage {
42 id: folderPage
37 objectName: "folderPage"43 objectName: "folderPage"
38 id: folderPage
3944
40 folder: homeFolder45 folder: homeFolder
41
42 function goHome() {
43 // FIXME: Get the user's home folder without requiring an instance
44 // of a FolderListModel
45 goTo(homeFolder)
46 }
47
48 function goTo(location) {
49 // FIXME: Why is this needed? Folder doesn't seem to refresh without it
50 folder = ""
51 folder = location
52 }
53 }46 }
54}47}

Subscribers

People subscribed via source and target branches