Merge lp:~dpm/ubuntu-filemanager-app/placesmodel-2 into lp:ubuntu-filemanager-app
- placesmodel-2
- Merge into trunk
Status: | Merged | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | David Planella | ||||||||||||||||||||
Approved revision: | 216 | ||||||||||||||||||||
Merged at revision: | 213 | ||||||||||||||||||||
Proposed branch: | lp:~dpm/ubuntu-filemanager-app/placesmodel-2 | ||||||||||||||||||||
Merge into: | lp:ubuntu-filemanager-app | ||||||||||||||||||||
Diff against target: |
1213 lines (+558/-263) 22 files modified
debian/control (+12/-1) debian/qtdeclarative5-placesmodel0.1.install (+1/-0) src/app/qml/components/FolderIconDelegate.qml (+1/-1) src/app/qml/components/FolderListDelegate.qml (+1/-1) src/app/qml/components/PathBar.qml (+2/-1) src/app/qml/components/PlacesSidebar.qml (+15/-37) src/app/qml/filemanager.qml (+7/-2) src/app/qml/ui/FileDetailsPopover.qml (+2/-2) src/app/qml/ui/FolderListPage.qml (+148/-165) src/app/qml/ui/GoToDialog.qml (+1/-1) src/app/qml/ui/PlacesPopover.qml (+5/-38) src/app/qml/ui/ViewPopover.qml (+2/-2) src/plugin/CMakeLists.txt (+1/-0) src/plugin/placesmodel/CMakeLists.txt (+35/-0) src/plugin/placesmodel/placesmodel.cpp (+174/-0) src/plugin/placesmodel/placesmodel.h (+64/-0) src/plugin/placesmodel/placesmodel_plugin.cpp (+34/-0) src/plugin/placesmodel/placesmodel_plugin.h (+39/-0) src/plugin/placesmodel/qmldir (+2/-0) tests/autopilot/filemanager/tests/__init__.py (+6/-6) tests/autopilot/filemanager/tests/test_filemanager.py (+5/-5) tests/autopilot/filemanager/tests/test_places.py (+1/-1) |
||||||||||||||||||||
To merge this branch: | bzr merge lp:~dpm/ubuntu-filemanager-app/placesmodel-2 | ||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Michael Spencer | Approve | ||
Review via email: mp+224037@code.launchpad.net |
Commit message
Add places model plugin
Description of the change
This is the re-submission of https:/
To cut a long story short: the branch was prematurely merged, and then it was accidentally reverted to fix an unrelated test failure. I'm resubmitting it again now, with the same changes plus the fix for bug 1331702. I've decided to address bug 1331699 as a separate branch [1] in order to minimize the changes on this branch.
In a nutshell, add a plugin to return:
a) User directories from the XDG spec
b) A model to retrieve and store user places
[1]: https:/
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:215
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michael Spencer (ibelieve) wrote : | # |
Looks good on my end! Did you want balloons to review this too, or should I top-approve?
David Planella (dpm) wrote : | # |
Awesome, thanks Michael for the review! As a File Manager developer, and given the fact it's passed both human and automated QA review, please feel free to top-approve. I'll take care of giving Nick a heads up too.
Nicholas Skaggs (nskaggs) wrote : | # |
I see it, and I'm happy.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
David Planella (dpm) wrote : | # |
Hm, pep8 failures in the tests? Why are these triggered now and not before, has anything changed in the Jenkins jobs config since it last approved the branch?
David Planella (dpm) wrote : | # |
Ah, here's what happened: https:/
So 2 days ago pep8 1.5.6 was uploaded in utopic. This version, unlike the previous 1.4.6 version (which is the one that also trusty has) is more strict regarding E265, which is the error it's complaining about.
- 216. By David Planella
-
Make pep8 v1.5.6 happy
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:216
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
David Planella (dpm) wrote : | # |
Top-approving as per previous reviews and top-approval.
Nicholas Skaggs (nskaggs) wrote : | # |
Yes, fm is not the only project to suffer from pep8 changes :-)
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2014-06-19 15:58:49 +0000 |
3 | +++ debian/control 2014-06-26 06:20:10 +0000 |
4 | @@ -38,9 +38,19 @@ |
5 | Qt is a cross-platform C++ application framework. Qt's primary feature |
6 | is its rich set of widgets that provide standard GUI functionality. |
7 | . |
8 | - This package contains the Folder List model plugin of the Nemo QML |
9 | + This package contains the Folder List model plugin of the Nemo QML |
10 | plugins collection. |
11 | |
12 | +Package: qtdeclarative5-placesmodel0.1 |
13 | +Architecture: any |
14 | +Multi-Arch: same |
15 | +Depends: ${misc:Depends}, |
16 | + ${shlibs:Depends}, |
17 | + ${misc:Pre-Depends}, |
18 | +Description: Places model QML plugin |
19 | + This package contains a plugin that enables QML apps to list and |
20 | + modify a set of places (bookmarks) in the file system. |
21 | + |
22 | Package: ubuntu-filemanager-app-autopilot |
23 | Architecture: all |
24 | Depends: ${misc:Depends}, |
25 | @@ -49,5 +59,6 @@ |
26 | ubuntu-filemanager-app (>= ${source:Version}), |
27 | ubuntu-ui-toolkit-autopilot, |
28 | python3-autopilot, |
29 | + python3-fixtures, |
30 | Description: Autopilot tests for File Manager Application |
31 | This package contains the autopilot tests for the File Manager |
32 | |
33 | === added file 'debian/qtdeclarative5-placesmodel0.1.install' |
34 | --- debian/qtdeclarative5-placesmodel0.1.install 1970-01-01 00:00:00 +0000 |
35 | +++ debian/qtdeclarative5-placesmodel0.1.install 2014-06-26 06:20:10 +0000 |
36 | @@ -0,0 +1,1 @@ |
37 | +usr/lib/*/qt5/qml/com/ubuntu/PlacesModel/ |
38 | |
39 | === modified file 'src/app/qml/components/FolderIconDelegate.qml' |
40 | --- src/app/qml/components/FolderIconDelegate.qml 2014-03-29 09:20:11 +0000 |
41 | +++ src/app/qml/components/FolderIconDelegate.qml 2014-06-26 06:20:10 +0000 |
42 | @@ -47,7 +47,7 @@ |
43 | objectName: "folder" + index |
44 | |
45 | property string fileName: model.fileName |
46 | - property string filePath: fileView.path + '/' + fileName |
47 | + property string filePath: fileView.folder + '/' + fileName |
48 | |
49 | property string text: fileName |
50 | property string subText: Qt.formatDateTime(model.modifiedDate, Qt.DefaultLocaleShortDate) + (!model.isDir ? ", " + fileSize : "") |
51 | |
52 | === modified file 'src/app/qml/components/FolderListDelegate.qml' |
53 | --- src/app/qml/components/FolderListDelegate.qml 2014-03-29 09:20:11 +0000 |
54 | +++ src/app/qml/components/FolderListDelegate.qml 2014-06-26 06:20:10 +0000 |
55 | @@ -29,7 +29,7 @@ |
56 | text: model.fileName |
57 | subText: Qt.formatDateTime(model.modifiedDate, Qt.DefaultLocaleShortDate) + (!model.isDir ? ", " + fileSize : "") |
58 | |
59 | - property string path: fileView.path + '/' + model.fileName |
60 | + property string path: fileView.folder + '/' + model.fileName |
61 | iconSource: fileIcon(path, model.isDir) |
62 | |
63 | progression: model.isDir |
64 | |
65 | === modified file 'src/app/qml/components/PathBar.qml' |
66 | --- src/app/qml/components/PathBar.qml 2014-06-19 15:58:49 +0000 |
67 | +++ src/app/qml/components/PathBar.qml 2014-06-26 06:20:10 +0000 |
68 | @@ -87,6 +87,7 @@ |
69 | |
70 | Repeater { |
71 | id: repeater |
72 | + // This refers to a parent FolderListPage.folder |
73 | model: folder === "/" ? [""] : folder.split("/") |
74 | delegate: Rectangle { |
75 | MouseArea { |
76 | @@ -117,7 +118,7 @@ |
77 | Label { |
78 | id: label |
79 | anchors.centerIn: parent |
80 | - text: modelData === "" ? "/" : modelData === "~" ? i18n.tr("Home") : modelData |
81 | + text: modelData === "" ? "/" : modelData |
82 | color: UbuntuColors.coolGrey |
83 | } |
84 | |
85 | |
86 | === modified file 'src/app/qml/components/PlacesSidebar.qml' |
87 | --- src/app/qml/components/PlacesSidebar.qml 2014-06-19 15:58:49 +0000 |
88 | +++ src/app/qml/components/PlacesSidebar.qml 2014-06-26 06:20:10 +0000 |
89 | @@ -20,6 +20,7 @@ |
90 | import Ubuntu.Components 0.1 |
91 | import Ubuntu.Components.ListItems 0.1 |
92 | import Ubuntu.Components.Popups 0.1 |
93 | +import com.ubuntu.PlacesModel 0.1 |
94 | |
95 | Sidebar { |
96 | id: root |
97 | @@ -42,40 +43,6 @@ |
98 | UbuntuNumberAnimation {} |
99 | } |
100 | |
101 | - ListModel { |
102 | - id: places |
103 | - |
104 | - ListElement { |
105 | - objectName: "placeHome" |
106 | - path: "~" |
107 | - } |
108 | - |
109 | - ListElement { |
110 | - path: "~/Documents" |
111 | - } |
112 | - |
113 | - ListElement { |
114 | - path: "~/Downloads" |
115 | - } |
116 | - |
117 | - ListElement { |
118 | - path: "~/Music" |
119 | - } |
120 | - |
121 | - ListElement { |
122 | - path: "~/Pictures" |
123 | - } |
124 | - |
125 | - ListElement { |
126 | - path: "~/Videos" |
127 | - } |
128 | - |
129 | - ListElement { |
130 | - objectName: "placeRoot" |
131 | - path: "/" |
132 | - } |
133 | - } |
134 | - |
135 | Column { |
136 | anchors { |
137 | left: parent.left |
138 | @@ -87,15 +54,25 @@ |
139 | text: i18n.tr("Places") |
140 | } |
141 | |
142 | + PlacesModel { |
143 | + id: userplaces |
144 | + |
145 | + // By default, the model only contains the |
146 | + // user directories. Add the file system location too |
147 | + Component.onCompleted: { |
148 | + addLocation("/"); |
149 | + } |
150 | + } |
151 | + |
152 | Repeater { |
153 | id: placesList |
154 | objectName: "placesList" |
155 | |
156 | - model: places |
157 | + model: userplaces |
158 | |
159 | delegate: Standard { |
160 | - objectName: model.objectName |
161 | - text: folderName(path) |
162 | + objectName: "place" + folderDisplayName(path).replace(/ /g,'') |
163 | + text: folderDisplayName(path) |
164 | |
165 | Image { |
166 | anchors { |
167 | @@ -123,6 +100,7 @@ |
168 | height: units.gu(5) |
169 | showDivider: !collapsed |
170 | |
171 | + // This refers to a parent FolderListPage.folder |
172 | selected: folder === path |
173 | iconFrame: false |
174 | } |
175 | |
176 | === modified file 'src/app/qml/filemanager.qml' |
177 | --- src/app/qml/filemanager.qml 2014-06-19 15:58:49 +0000 |
178 | +++ src/app/qml/filemanager.qml 2014-06-26 06:20:10 +0000 |
179 | @@ -21,6 +21,7 @@ |
180 | import Ubuntu.Components.Popups 0.1 |
181 | import Ubuntu.Unity.Action 1.0 as UnityActions |
182 | import U1db 1.0 as U1db |
183 | +import com.ubuntu.PlacesModel 0.1 |
184 | |
185 | import "ui" |
186 | |
187 | @@ -60,6 +61,10 @@ |
188 | backgroundColor: "#797979" |
189 | footerColor: "#808080" |
190 | |
191 | + PlacesModel { |
192 | + id: userplaces |
193 | + } |
194 | + |
195 | // HUD Actions |
196 | Action { |
197 | id: settingsAction |
198 | @@ -72,7 +77,7 @@ |
199 | |
200 | property var pageStack: pageStack |
201 | |
202 | - property var folderTabs: ["~"] |
203 | + property var folderTabs: [userplaces.locationHome] |
204 | |
205 | function openTab(folder) { |
206 | var list = folderTabs |
207 | @@ -100,7 +105,7 @@ |
208 | page: FolderListPage { |
209 | objectName: "folderPage" |
210 | |
211 | - folder: "~"//modelData |
212 | + folder: userplaces.locationHome //modelData |
213 | } |
214 | } |
215 | |
216 | |
217 | === modified file 'src/app/qml/ui/FileDetailsPopover.qml' |
218 | --- src/app/qml/ui/FileDetailsPopover.qml 2014-02-19 00:00:15 +0000 |
219 | +++ src/app/qml/ui/FileDetailsPopover.qml 2014-06-26 06:20:10 +0000 |
220 | @@ -23,7 +23,7 @@ |
221 | id: root |
222 | property var model |
223 | |
224 | - property string path: model.path || (fileView.path + '/' + model.fileName) |
225 | + property string path: model.path || (fileView.folder + '/' + model.fileName) |
226 | |
227 | contentHeight: contents.height + 2 * contents.anchors.margins |
228 | |
229 | @@ -77,7 +77,7 @@ |
230 | Label { |
231 | anchors.verticalCenter: parent.verticalCenter |
232 | |
233 | - text: folderName(root.path) |
234 | + text: folderDisplayName(root.path) |
235 | color: Theme.palette.normal.overlayText |
236 | font.bold: true |
237 | } |
238 | |
239 | === modified file 'src/app/qml/ui/FolderListPage.qml' |
240 | --- src/app/qml/ui/FolderListPage.qml 2014-06-19 15:58:49 +0000 |
241 | +++ src/app/qml/ui/FolderListPage.qml 2014-06-26 06:20:10 +0000 |
242 | @@ -20,25 +20,27 @@ |
243 | import Ubuntu.Components.Popups 0.1 |
244 | import Ubuntu.Components.ListItems 0.1 |
245 | import org.nemomobile.folderlistmodel 1.0 |
246 | +import com.ubuntu.PlacesModel 0.1 |
247 | import "../components" |
248 | |
249 | Page { |
250 | id: folderListPage |
251 | - |
252 | - title: folderName(folder) |
253 | + title: folderDisplayName(folder) |
254 | + flickable: !sidebar.expanded ? |
255 | + (folderListView.visible ? folderListView : folderIconView.flickable) : null |
256 | |
257 | property variant fileView: folderListPage |
258 | - |
259 | property bool showHiddenFiles: false |
260 | - |
261 | property bool showingListView: folderListView.visible |
262 | + property string sortingMethod: "Name" |
263 | + property bool sortAscending: true |
264 | + property string folder |
265 | + property bool loading: pageModel.awaitingResults |
266 | |
267 | onShowHiddenFilesChanged: { |
268 | pageModel.showHiddenFiles = folderListPage.showHiddenFiles |
269 | } |
270 | |
271 | - property string sortingMethod: "Name" |
272 | - |
273 | onSortingMethodChanged: { |
274 | console.log("Sorting by: " + sortingMethod) |
275 | if (sortingMethod === "Name") { |
276 | @@ -51,154 +53,39 @@ |
277 | } |
278 | } |
279 | |
280 | - property bool sortAccending: true |
281 | - |
282 | - onSortAccendingChanged: { |
283 | - console.log("Sorting accending: " + sortAccending) |
284 | - |
285 | - if (sortAccending) { |
286 | + onSortAscendingChanged: { |
287 | + console.log("Sorting ascending: " + sortAscending) |
288 | + |
289 | + if (sortAscending) { |
290 | pageModel.sortOrder = FolderListModel.SortAscending |
291 | } else { |
292 | pageModel.sortOrder = FolderListModel.SortDescending |
293 | } |
294 | } |
295 | |
296 | - // This stores the location using ~ to represent home |
297 | - property string folder |
298 | - property string homeFolder: "~" |
299 | - |
300 | - // This replaces ~ with the actual home folder, since the |
301 | - // plugin doesn't recognize the ~ |
302 | - property string path: folder.replace("~", pageModel.homePath()) |
303 | - |
304 | - function goHome() { |
305 | - goTo(folderListPage.homeFolder) |
306 | - } |
307 | - |
308 | - function goTo(location) { |
309 | - // Since the FolderListModel returns paths using the actual |
310 | - // home folder, this replaces with ~ before actually going |
311 | - // to the specified folder |
312 | - while (location !== '/' && location.substring(location.lastIndexOf('/')+1) === "") { |
313 | - location = location.substring(0, location.length - 1) |
314 | - } |
315 | - |
316 | - folderListPage.folder = location.replace(pageModel.homePath(), "~") |
317 | - refresh() |
318 | - } |
319 | - |
320 | - function refresh() { |
321 | - pageModel.refresh() |
322 | - } |
323 | - |
324 | - function pathAccessedDate() { |
325 | - console.log("calling method pageModel.curPathAccessedDate()") |
326 | - return pageModel.curPathAccessedDate() |
327 | - } |
328 | - |
329 | - function pathModifiedDate() { |
330 | - console.log("calling method pageModel.curPathModifiedDate()") |
331 | - return pageModel.curPathModifiedDate() |
332 | - } |
333 | - |
334 | - function pathIsWritable() { |
335 | - console.log("calling method pageModel.curPathIsWritable()") |
336 | - return pageModel.curPathIsWritable() |
337 | - } |
338 | - |
339 | - // FIXME: hard coded path for icon, assumes Ubuntu desktop icon available. |
340 | - // Nemo mobile has icon provider. Have to figure out what's the proper way |
341 | - // to get "system wide" icons in Ubuntu Touch, or if we have to use |
342 | - // icons packaged into the application. Both folder and individual |
343 | - // files will need an icon. |
344 | - // TODO: Remove isDir parameter and use new model functions |
345 | - function fileIcon(file, isDir) { |
346 | - file = file.replace(pageModel.homePath(), "~") |
347 | - var iconPath = isDir ? "/usr/share/icons/Humanity/places/48/folder.svg" |
348 | - : "/usr/share/icons/Humanity/mimes/48/empty.svg" |
349 | - |
350 | - if (file === "~") { |
351 | - iconPath = "../icons/folder-home.svg" |
352 | - } else if (file === i18n.tr("~/Desktop")) { |
353 | - iconPath = "/usr/share/icons/Humanity/places/48/user-desktop.svg" |
354 | - } else if (file === i18n.tr("~/Documents")) { |
355 | - iconPath = "/usr/share/icons/Humanity/places/48/folder-documents.svg" |
356 | - } else if (file === i18n.tr("~/Downloads")) { |
357 | - iconPath = "/usr/share/icons/Humanity/places/48/folder-downloads.svg" |
358 | - } else if (file === i18n.tr("~/Music")) { |
359 | - iconPath = "/usr/share/icons/Humanity/places/48/folder-music.svg" |
360 | - } else if (file === i18n.tr("~/Pictures")) { |
361 | - iconPath = "/usr/share/icons/Humanity/places/48/folder-pictures.svg" |
362 | - } else if (file === i18n.tr("~/Public")) { |
363 | - iconPath = "/usr/share/icons/Humanity/places/48/folder-publicshare.svg" |
364 | - } else if (file === i18n.tr("~/Programs")) { |
365 | - iconPath = "/usr/share/icons/Humanity/places/48/folder-system.svg" |
366 | - } else if (file === i18n.tr("~/Templates")) { |
367 | - iconPath = "/usr/share/icons/Humanity/places/48/folder-templates.svg" |
368 | - } else if (file === i18n.tr("~/Videos")) { |
369 | - iconPath = "/usr/share/icons/Humanity/places/48/folder-videos.svg" |
370 | - } else if (file === "/") { |
371 | - iconPath = "/usr/share/icons/Humanity/devices/48/drive-harddisk.svg" |
372 | - } |
373 | - |
374 | - return Qt.resolvedUrl(iconPath) |
375 | - } |
376 | - |
377 | - function folderName(folder) { |
378 | - folder = folder.replace(pageModel.homePath(), "~") |
379 | - |
380 | - if (folder === folderListPage.homeFolder) { |
381 | - return i18n.tr("Home") |
382 | - } else if (folder === "/") { |
383 | - return i18n.tr("File System") |
384 | - } else { |
385 | - return folder.substr(folder.lastIndexOf('/') + 1) |
386 | - } |
387 | - } |
388 | - |
389 | - function pathName(folder) { |
390 | - if (folder === "/") { |
391 | - return "/" |
392 | - } else { |
393 | - return folder.substr(folder.lastIndexOf('/') + 1) |
394 | - } |
395 | - } |
396 | - |
397 | - function pathExists(path) { |
398 | - path = path.replace("~", pageModel.homePath()) |
399 | - |
400 | - if (path === '/') |
401 | - return true |
402 | - |
403 | - if(path.charAt(0) === '/') { |
404 | - console.log("Directory: " + path.substring(0, path.lastIndexOf('/')+1)) |
405 | - repeaterModel.path = path.substring(0, path.lastIndexOf('/')+1) |
406 | - console.log("Sub dir: " + path.substring(path.lastIndexOf('/')+1)) |
407 | - if (path.substring(path.lastIndexOf('/')+1) !== "" && !repeaterModel.cdIntoPath(path.substring(path.lastIndexOf('/')+1))) { |
408 | - return false |
409 | - } else { |
410 | - return true |
411 | - } |
412 | - } else { |
413 | - return false |
414 | - } |
415 | - } |
416 | - |
417 | - property bool loading: pageModel.awaitingResults |
418 | + onFlickableChanged: { |
419 | + if (flickable === null) { |
420 | + folderListView.topMargin = 0 |
421 | + folderIconView.flickable.topMargin = 0 |
422 | + } else { |
423 | + folderListView.topMargin = units.gu(9.5) |
424 | + folderIconView.flickable.topMargin = units.gu(9.5) |
425 | + } |
426 | + } |
427 | + |
428 | + |
429 | + |
430 | + PlacesModel { id: userplaces } |
431 | |
432 | FolderListModel { |
433 | id: pageModel |
434 | - |
435 | - path: folderListPage.path |
436 | - |
437 | + path: folderListPage.folder |
438 | enableExternalFSWatcher: true |
439 | |
440 | // Properties to emulate a model entry for use by FileDetailsPopover |
441 | property bool isDir: true |
442 | property string fileName: pathName(pageModel.path) |
443 | - property string fileSize: (folderListView.count === 1 |
444 | - ? i18n.tr("1 file") |
445 | - : i18n.tr("%1 files").arg(folderListView.count)) |
446 | + property string fileSize: i18n.tr("%1 file", "%1 files", folderListView.count).arg(folderListView.count) |
447 | property bool isReadable: true |
448 | property bool isExecutable: true |
449 | } |
450 | @@ -208,7 +95,7 @@ |
451 | path: folderListPage.folder |
452 | |
453 | onPathChanged: { |
454 | - console.log("Path: " + repeaterModel.path) |
455 | + console.log("Path changed to: " + repeaterModel.path) |
456 | } |
457 | } |
458 | |
459 | @@ -270,11 +157,9 @@ |
460 | // } |
461 | |
462 | Action { |
463 | - text: pageModel.clipboardUrlsCounter === 0 |
464 | - ? i18n.tr("Paste") |
465 | - : pageModel.clipboardUrlsCounter === 1 |
466 | - ? i18n.tr("Paste %1 File").arg(pageModel.clipboardUrlsCounter) |
467 | - : i18n.tr("Paste %1 Files").arg(pageModel.clipboardUrlsCounter) |
468 | + text: pageModel.clipboardUrlsCounter === 0 ? |
469 | + i18n.tr("Paste") : |
470 | + i18n.tr("Paste %1 File", "Paste %1 Files", pageModel.clipboardUrlsCounter).arg(pageModel.clipboardUrlsCounter) |
471 | onTriggered: { |
472 | console.log("Pasting to current folder items of count " + pageModel.clipboardUrlsCounter) |
473 | fileOperationDialog.startOperation(i18n.tr("Paste files")) |
474 | @@ -349,12 +234,6 @@ |
475 | } |
476 | } |
477 | |
478 | - function openFile(filePath) { |
479 | - if (!pageModel.openPath(filePath)) { |
480 | - error(i18n.tr("File operation error"), i18n.tr("Unable to open '%11").arg(filePath)) |
481 | - } |
482 | - } |
483 | - |
484 | tools: ToolbarItems { |
485 | id: toolbar |
486 | locked: showToolbar |
487 | @@ -364,7 +243,7 @@ |
488 | |
489 | back: ToolbarButton { |
490 | objectName: "up" |
491 | - text: "Up" |
492 | + text: i18n.tr("Up") |
493 | iconSource: getIcon("keyboard-caps") |
494 | enabled: folder != "/" |
495 | onTriggered: { |
496 | @@ -451,18 +330,6 @@ |
497 | } |
498 | } |
499 | |
500 | - flickable: !sidebar.expanded ? folderListView.visible ? folderListView : folderIconView.flickable : null |
501 | - |
502 | - onFlickableChanged: { |
503 | - if (flickable === null) { |
504 | - folderListView.topMargin = 0 |
505 | - folderIconView.flickable.topMargin = 0 |
506 | - } else { |
507 | - folderListView.topMargin = units.gu(9.5) |
508 | - folderIconView.flickable.topMargin = units.gu(9.5) |
509 | - } |
510 | - } |
511 | - |
512 | PlacesSidebar { |
513 | id: sidebar |
514 | objectName: "placesSidebar" |
515 | @@ -677,6 +544,122 @@ |
516 | model: pageModel |
517 | } |
518 | |
519 | + function goTo(location) { |
520 | + // This allows us to enter "~" as a shortcut to the home folder |
521 | + // when entering a location on the Go To dialog |
522 | + folderListPage.folder = location.replace("~", userplaces.locationHome) |
523 | + refresh() |
524 | + } |
525 | + |
526 | + function refresh() { |
527 | + pageModel.refresh() |
528 | + } |
529 | + |
530 | + function pathAccessedDate() { |
531 | + console.log("calling method pageModel.curPathAccessedDate()") |
532 | + return pageModel.curPathAccessedDate() |
533 | + } |
534 | + |
535 | + function pathModifiedDate() { |
536 | + console.log("calling method pageModel.curPathModifiedDate()") |
537 | + return pageModel.curPathModifiedDate() |
538 | + } |
539 | + |
540 | + function pathIsWritable() { |
541 | + console.log("calling method pageModel.curPathIsWritable()") |
542 | + return pageModel.curPathIsWritable() |
543 | + } |
544 | + |
545 | + // FIXME: hard coded path for icon, assumes Ubuntu desktop icon available. |
546 | + // Nemo mobile has icon provider. Have to figure out what's the proper way |
547 | + // to get "system wide" icons in Ubuntu Touch, or if we have to use |
548 | + // icons packaged into the application. Both folder and individual |
549 | + // files will need an icon. |
550 | + // TODO: Remove isDir parameter and use new model functions |
551 | + function fileIcon(file, isDir) { |
552 | + var iconPath = isDir ? "/usr/share/icons/Humanity/places/48/folder.svg" |
553 | + : "/usr/share/icons/Humanity/mimes/48/empty.svg" |
554 | + |
555 | + if (file === userplaces.locationHome) { |
556 | + iconPath = "../icons/folder-home.svg" |
557 | + } else if (file === i18n.tr("~/Desktop")) { |
558 | + iconPath = "/usr/share/icons/Humanity/places/48/user-desktop.svg" |
559 | + } else if (file === userplaces.locationDocuments) { |
560 | + iconPath = "/usr/share/icons/Humanity/places/48/folder-documents.svg" |
561 | + } else if (file === userplaces.locationDownloads) { |
562 | + iconPath = "/usr/share/icons/Humanity/places/48/folder-downloads.svg" |
563 | + } else if (file === userplaces.locationMusic) { |
564 | + iconPath = "/usr/share/icons/Humanity/places/48/folder-music.svg" |
565 | + } else if (file === userplaces.locationPictures) { |
566 | + iconPath = "/usr/share/icons/Humanity/places/48/folder-pictures.svg" |
567 | + } else if (file === i18n.tr("~/Public")) { |
568 | + iconPath = "/usr/share/icons/Humanity/places/48/folder-publicshare.svg" |
569 | + } else if (file === i18n.tr("~/Programs")) { |
570 | + iconPath = "/usr/share/icons/Humanity/places/48/folder-system.svg" |
571 | + } else if (file === i18n.tr("~/Templates")) { |
572 | + iconPath = "/usr/share/icons/Humanity/places/48/folder-templates.svg" |
573 | + } else if (file === userplaces.locationVideos) { |
574 | + iconPath = "/usr/share/icons/Humanity/places/48/folder-videos.svg" |
575 | + } else if (file === "/") { |
576 | + iconPath = "/usr/share/icons/Humanity/devices/48/drive-harddisk.svg" |
577 | + } |
578 | + |
579 | + return Qt.resolvedUrl(iconPath) |
580 | + } |
581 | + |
582 | + function folderDisplayName(folder) { |
583 | + if (folder === userplaces.locationHome) { |
584 | + return i18n.tr("Home") |
585 | + } else if (folder === "/") { |
586 | + return i18n.tr("File System") |
587 | + } else { |
588 | + return basename(folder) |
589 | + } |
590 | + } |
591 | + |
592 | + function pathName(folder) { |
593 | + if (folder === "/") { |
594 | + return "/" |
595 | + } else { |
596 | + return basename(folder) |
597 | + } |
598 | + } |
599 | + |
600 | + function basename(folder) { |
601 | + // Returns the latest component (folder) of an absolute path |
602 | + // E.g. basename('/home/phablet/Música') returns 'Música' |
603 | + |
604 | + // Remove the last trailing '/' if there is one |
605 | + folder.replace(/\/$/, "") |
606 | + return folder.substr(folder.lastIndexOf('/') + 1) |
607 | + } |
608 | + |
609 | + function pathExists(path) { |
610 | + path = path.replace("~", pageModel.homePath()) |
611 | + |
612 | + if (path === '/') |
613 | + return true |
614 | + |
615 | + if(path.charAt(0) === '/') { |
616 | + console.log("Directory: " + path.substring(0, path.lastIndexOf('/')+1)) |
617 | + repeaterModel.path = path.substring(0, path.lastIndexOf('/')+1) |
618 | + console.log("Sub dir: " + path.substring(path.lastIndexOf('/')+1)) |
619 | + if (path.substring(path.lastIndexOf('/')+1) !== "" && !repeaterModel.cdIntoPath(path.substring(path.lastIndexOf('/')+1))) { |
620 | + return false |
621 | + } else { |
622 | + return true |
623 | + } |
624 | + } else { |
625 | + return false |
626 | + } |
627 | + } |
628 | + |
629 | + function openFile(filePath) { |
630 | + if (!pageModel.openPath(filePath)) { |
631 | + error(i18n.tr("File operation error"), i18n.tr("Unable to open '%1'").arg(filePath)) |
632 | + } |
633 | + } |
634 | + |
635 | function itemClicked(model) { |
636 | if (model.isDir) { |
637 | if (model.isReadable && model.isExecutable) { |
638 | |
639 | === modified file 'src/app/qml/ui/GoToDialog.qml' |
640 | --- src/app/qml/ui/GoToDialog.qml 2014-02-19 00:00:15 +0000 |
641 | +++ src/app/qml/ui/GoToDialog.qml 2014-06-26 06:20:10 +0000 |
642 | @@ -39,7 +39,7 @@ |
643 | |
644 | property bool valid: pathExists(text) |
645 | |
646 | - text: fileView.path |
647 | + text: fileView.folder |
648 | |
649 | placeholderText: i18n.tr("Location...") |
650 | |
651 | |
652 | === modified file 'src/app/qml/ui/PlacesPopover.qml' |
653 | --- src/app/qml/ui/PlacesPopover.qml 2014-06-19 15:58:49 +0000 |
654 | +++ src/app/qml/ui/PlacesPopover.qml 2014-06-26 06:20:10 +0000 |
655 | @@ -19,45 +19,12 @@ |
656 | import Ubuntu.Components 0.1 |
657 | import Ubuntu.Components.Popups 0.1 |
658 | import Ubuntu.Components.ListItems 0.1 |
659 | +import com.ubuntu.PlacesModel 0.1 |
660 | |
661 | Popover { |
662 | id: root |
663 | objectName: "placesPopover" |
664 | |
665 | - ListModel { |
666 | - id: places |
667 | - |
668 | - ListElement { |
669 | - objectName: 'placeHome' |
670 | - path: "~" |
671 | - } |
672 | - |
673 | - ListElement { |
674 | - path: "~/Documents" |
675 | - } |
676 | - |
677 | - ListElement { |
678 | - path: "~/Downloads" |
679 | - } |
680 | - |
681 | - ListElement { |
682 | - path: "~/Music" |
683 | - } |
684 | - |
685 | - ListElement { |
686 | - path: "~/Pictures" |
687 | - } |
688 | - |
689 | - ListElement { |
690 | - path: "~/Videos" |
691 | - } |
692 | - |
693 | - ListElement { |
694 | - objectName: "placeRoot" |
695 | - path: "/" |
696 | - } |
697 | - } |
698 | - |
699 | Column { |
700 | anchors { |
701 | left: parent.left |
702 | @@ -81,7 +48,7 @@ |
703 | |
704 | property bool valid: pathExists(text) |
705 | |
706 | - text: fileView.path |
707 | + text: fileView.folder |
708 | |
709 | placeholderText: i18n.tr("Location...") |
710 | |
711 | @@ -113,17 +80,17 @@ |
712 | id: placesList |
713 | objectName: "placesList" |
714 | |
715 | - model: places |
716 | + model: PlacesModel {} |
717 | |
718 | delegate: Standard { |
719 | objectName: model.objectName |
720 | - property string name: folderName(path) |
721 | + property string name: folderDisplayName(path) |
722 | |
723 | Label { |
724 | anchors.left: parent.left |
725 | anchors.leftMargin: units.gu(8) |
726 | anchors.verticalCenter: parent.verticalCenter |
727 | - text: folderName(path) |
728 | + text: folderDisplayName(path) |
729 | color: selected ? UbuntuColors.orange : Theme.palette.normal.overlayText |
730 | } |
731 | |
732 | |
733 | === modified file 'src/app/qml/ui/ViewPopover.qml' |
734 | --- src/app/qml/ui/ViewPopover.qml 2014-02-19 00:00:15 +0000 |
735 | +++ src/app/qml/ui/ViewPopover.qml 2014-06-26 06:20:10 +0000 |
736 | @@ -109,14 +109,14 @@ |
737 | anchors.topMargin: units.gu(1.7) |
738 | } |
739 | |
740 | - selectedIndex: sortAccending ? 0 : 1 |
741 | + selectedIndex: sortAscending ? 0 : 1 |
742 | values: [ |
743 | i18n.tr("Ascending"), |
744 | i18n.tr("Descending") |
745 | ] |
746 | |
747 | onSelectedIndexChanged: { |
748 | - fileView.sortAccending = (values[selectedIndex] === i18n.tr("Ascending")) |
749 | + fileView.sortAscending = (values[selectedIndex] === i18n.tr("Ascending")) |
750 | } |
751 | } |
752 | |
753 | |
754 | === modified file 'src/plugin/CMakeLists.txt' |
755 | --- src/plugin/CMakeLists.txt 2014-06-19 15:58:49 +0000 |
756 | +++ src/plugin/CMakeLists.txt 2014-06-26 06:20:10 +0000 |
757 | @@ -5,3 +5,4 @@ |
758 | find_package(Qt5Widgets) |
759 | |
760 | add_subdirectory(folderlistmodel) |
761 | +add_subdirectory(placesmodel) |
762 | |
763 | === added directory 'src/plugin/placesmodel' |
764 | === added file 'src/plugin/placesmodel/CMakeLists.txt' |
765 | --- src/plugin/placesmodel/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
766 | +++ src/plugin/placesmodel/CMakeLists.txt 2014-06-26 06:20:10 +0000 |
767 | @@ -0,0 +1,35 @@ |
768 | +include_directories( |
769 | + ${CMAKE_CURRENT_SOURCE_DIR} |
770 | +) |
771 | + |
772 | +set(PLUGIN_DIR com/ubuntu/PlacesModel) |
773 | + |
774 | +set(placesmodel_SRCS |
775 | + placesmodel.cpp |
776 | + placesmodel.h |
777 | + placesmodel_plugin.cpp |
778 | + placesmodel_plugin.h |
779 | +) |
780 | + |
781 | +add_library(PlacesModel MODULE |
782 | + ${placesmodel_SRCS} |
783 | +) |
784 | + |
785 | +qt5_use_modules(PlacesModel Gui Qml Quick Widgets) |
786 | + |
787 | +# Copy the plugin, the qmldir file and other assets to the build dir for running in QtCreator |
788 | +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") |
789 | + add_custom_command(TARGET PlacesModel POST_BUILD |
790 | + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
791 | + COMMENT "Creating plugin directory layout in the build directory" |
792 | + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/qmldir ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
793 | + COMMENT "Copying the qmldir file to the build directory" |
794 | + COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:PlacesModel> ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
795 | + COMMENT "Copying the plugin binary to the build directory" |
796 | + ) |
797 | +endif(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") |
798 | + |
799 | +# Install plugin file |
800 | +install(TARGETS PlacesModel DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR}) |
801 | +install(FILES qmldir DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR}) |
802 | + |
803 | |
804 | === added file 'src/plugin/placesmodel/placesmodel.cpp' |
805 | --- src/plugin/placesmodel/placesmodel.cpp 1970-01-01 00:00:00 +0000 |
806 | +++ src/plugin/placesmodel/placesmodel.cpp 2014-06-26 06:20:10 +0000 |
807 | @@ -0,0 +1,174 @@ |
808 | +/* |
809 | + * Copyright (C) 2013 Canonical Ltd |
810 | + * |
811 | + * This program is free software: you can redistribute it and/or modify |
812 | + * it under the terms of the GNU General Public License version 3 as |
813 | + * published by the Free Software Foundation. |
814 | + * |
815 | + * This program is distributed in the hope that it will be useful, |
816 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
817 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
818 | + * GNU General Public License for more details. |
819 | + * |
820 | + * You should have received a copy of the GNU General Public License |
821 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
822 | + * |
823 | + * Author : David Planella <david.planella@ubuntu.com> |
824 | + */ |
825 | + |
826 | +#include "placesmodel.h" |
827 | +#include <QDebug> |
828 | +#include <QDir> |
829 | +#include <QAbstractItemModel> |
830 | +#include <QCoreApplication> |
831 | +#include <QStandardPaths> |
832 | +#include <QDebug> |
833 | + |
834 | +PlacesModel::PlacesModel(QAbstractListModel *parent) : |
835 | + QAbstractListModel(parent) |
836 | +{ |
837 | + |
838 | + QStringList defaultLocations; |
839 | + // Set the storage location to a path that works well |
840 | + // with app isolation |
841 | + QString settingsLocation = |
842 | + QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() |
843 | + + "/" + QCoreApplication::applicationName() + "/" + "places.conf"; |
844 | + m_settings = new QSettings(settingsLocation, QSettings::IniFormat, this); |
845 | + |
846 | + // Prepopulate the model with the user locations |
847 | + // for the first time it's used |
848 | + defaultLocations.append(locationHome()); |
849 | + defaultLocations.append(locationDocuments()); |
850 | + defaultLocations.append(locationDownloads()); |
851 | + defaultLocations.append(locationMusic()); |
852 | + defaultLocations.append(locationPictures()); |
853 | + defaultLocations.append(locationVideos()); |
854 | + |
855 | + if (!m_settings->contains("storedLocations")) { |
856 | + m_locations.append(defaultLocations); |
857 | + } else { |
858 | + m_locations = m_settings->value("storedLocations").toStringList(); |
859 | + } |
860 | + |
861 | + foreach (const QString &location, m_locations) { |
862 | + qDebug() << "Location: " << location; |
863 | + } |
864 | + |
865 | +} |
866 | + |
867 | +PlacesModel::~PlacesModel() { |
868 | + |
869 | +} |
870 | + |
871 | +QString PlacesModel::standardLocation(QStandardPaths::StandardLocation location) const |
872 | +{ |
873 | + QStringList locations = QStandardPaths::standardLocations(location); |
874 | + QString standardLocation = ""; |
875 | + |
876 | + foreach (const QString &location, locations) { |
877 | + // We always return the first location or an empty string |
878 | + // The frontend should check out that it exists |
879 | + if (QDir(location).exists()) { |
880 | + standardLocation = location; |
881 | + break; |
882 | + } |
883 | + } |
884 | + |
885 | + return standardLocation; |
886 | +} |
887 | + |
888 | +QString PlacesModel::locationHome() const |
889 | +{ |
890 | + return standardLocation(QStandardPaths::HomeLocation); |
891 | +} |
892 | + |
893 | +QString PlacesModel::locationDocuments() const |
894 | +{ |
895 | + return standardLocation(QStandardPaths::DocumentsLocation); |
896 | +} |
897 | + |
898 | +QString PlacesModel::locationDownloads() const |
899 | +{ |
900 | + return standardLocation(QStandardPaths::DownloadLocation); |
901 | +} |
902 | + |
903 | +QString PlacesModel::locationMusic() const |
904 | +{ |
905 | + return standardLocation(QStandardPaths::MusicLocation); |
906 | +} |
907 | + |
908 | +QString PlacesModel::locationPictures() const |
909 | +{ |
910 | + return standardLocation(QStandardPaths::PicturesLocation); |
911 | +} |
912 | + |
913 | +QString PlacesModel::locationVideos() const |
914 | +{ |
915 | + return standardLocation(QStandardPaths::MoviesLocation); |
916 | +} |
917 | + |
918 | +int PlacesModel::rowCount(const QModelIndex &parent) const |
919 | +{ |
920 | + Q_UNUSED(parent) |
921 | + |
922 | + return m_locations.count(); |
923 | +} |
924 | + |
925 | +QVariant PlacesModel::data(const QModelIndex &index, int role) const |
926 | +{ |
927 | + Q_UNUSED(role) |
928 | + |
929 | + return m_locations.at(index.row()); |
930 | +} |
931 | + |
932 | +QHash<int, QByteArray> PlacesModel::roleNames() const |
933 | +{ |
934 | + QHash<int, QByteArray> roles; |
935 | + roles.insert(Qt::UserRole, "path"); |
936 | + |
937 | + return roles; |
938 | +} |
939 | + |
940 | +void PlacesModel::removeItem(int indexToRemove) |
941 | +{ |
942 | + |
943 | + // Tell Qt that we're going to be changing the model |
944 | + // There's no tree-parent, first new item will be at |
945 | + // indexToRemove, and the last one too |
946 | + beginRemoveRows(QModelIndex(), indexToRemove, indexToRemove); |
947 | + |
948 | + // Remove the actual location |
949 | + m_locations.removeAt(indexToRemove); |
950 | + |
951 | + // Tell Qt we're done with modifying the model so that |
952 | + // it can update the UI and everything else to reflect |
953 | + // the new state |
954 | + endRemoveRows(); |
955 | + |
956 | + // Remove the location permanently |
957 | + m_settings->setValue("storedLocations", m_locations); |
958 | +} |
959 | + |
960 | +void PlacesModel::addLocation(const QString &location) |
961 | +{ |
962 | + // Do not allow for duplicates |
963 | + if (!m_locations.contains(location)) { |
964 | + // Tell Qt that we're going to be changing the model |
965 | + // There's no tree-parent, first new item will be at |
966 | + // m_locations.count(), and the last one too |
967 | + beginInsertRows(QModelIndex(), m_locations.count(), m_locations.count()); |
968 | + |
969 | + // Append the actual location |
970 | + m_locations.append(location); |
971 | + |
972 | + |
973 | + // Tell Qt we're done with modifying the model so that |
974 | + // it can update the UI and everything else to reflect |
975 | + // the new state |
976 | + endInsertRows(); |
977 | + |
978 | + // Store the location permanently |
979 | + m_settings->setValue("storedLocations", m_locations); |
980 | + } |
981 | +} |
982 | |
983 | === added file 'src/plugin/placesmodel/placesmodel.h' |
984 | --- src/plugin/placesmodel/placesmodel.h 1970-01-01 00:00:00 +0000 |
985 | +++ src/plugin/placesmodel/placesmodel.h 2014-06-26 06:20:10 +0000 |
986 | @@ -0,0 +1,64 @@ |
987 | +/* |
988 | + * Copyright (C) 2013 Canonical Ltd |
989 | + * |
990 | + * This program is free software: you can redistribute it and/or modify |
991 | + * it under the terms of the GNU General Public License version 3 as |
992 | + * published by the Free Software Foundation. |
993 | + * |
994 | + * This program is distributed in the hope that it will be useful, |
995 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
996 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
997 | + * GNU General Public License for more details. |
998 | + * |
999 | + * You should have received a copy of the GNU General Public License |
1000 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1001 | + * |
1002 | + * Author : David Planella <david.planella@ubuntu.com> |
1003 | + */ |
1004 | + |
1005 | +#ifndef PLACESMODEL_H |
1006 | +#define PLACESMODEL_H |
1007 | + |
1008 | +#include <QObject> |
1009 | +#include <QAbstractListModel> |
1010 | +#include <QStandardPaths> |
1011 | +#include <QSettings> |
1012 | + |
1013 | +class PlacesModel : public QAbstractListModel |
1014 | +{ |
1015 | + Q_OBJECT |
1016 | + |
1017 | + Q_PROPERTY(QString locationHome READ locationHome CONSTANT) |
1018 | + Q_PROPERTY(QString locationDocuments READ locationDocuments CONSTANT) |
1019 | + Q_PROPERTY(QString locationDownloads READ locationDownloads CONSTANT) |
1020 | + Q_PROPERTY(QString locationMusic READ locationMusic CONSTANT) |
1021 | + Q_PROPERTY(QString locationPictures READ locationPictures CONSTANT) |
1022 | + Q_PROPERTY(QString locationVideos READ locationVideos CONSTANT) |
1023 | + |
1024 | +public: |
1025 | + explicit PlacesModel(QAbstractListModel *parent = 0); |
1026 | + ~PlacesModel(); |
1027 | + QString locationHome() const; |
1028 | + QString locationDocuments() const; |
1029 | + QString locationDownloads() const; |
1030 | + QString locationMusic() const; |
1031 | + QString locationPictures() const; |
1032 | + QString locationVideos() const; |
1033 | + int rowCount(const QModelIndex &parent) const override; |
1034 | + QVariant data(const QModelIndex &index, int role) const override; |
1035 | + QHash<int, QByteArray> roleNames() const override; |
1036 | + |
1037 | +public slots: |
1038 | + void addLocation(const QString &location); |
1039 | + void removeItem(int indexToRemove); |
1040 | + |
1041 | +private: |
1042 | + QString standardLocation(QStandardPaths::StandardLocation location) const; |
1043 | + QStringList m_locations; |
1044 | + QSettings *m_settings; |
1045 | +}; |
1046 | + |
1047 | +#endif // PLACESMODEL_H |
1048 | + |
1049 | + |
1050 | + |
1051 | |
1052 | === added file 'src/plugin/placesmodel/placesmodel_plugin.cpp' |
1053 | --- src/plugin/placesmodel/placesmodel_plugin.cpp 1970-01-01 00:00:00 +0000 |
1054 | +++ src/plugin/placesmodel/placesmodel_plugin.cpp 2014-06-26 06:20:10 +0000 |
1055 | @@ -0,0 +1,34 @@ |
1056 | +/* |
1057 | + * Copyright (C) 2013 Canonical Ltd |
1058 | + * |
1059 | + * This program is free software: you can redistribute it and/or modify |
1060 | + * it under the terms of the GNU General Public License version 3 as |
1061 | + * published by the Free Software Foundation. |
1062 | + * |
1063 | + * This program is distributed in the hope that it will be useful, |
1064 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1065 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1066 | + * GNU General Public License for more details. |
1067 | + * |
1068 | + * You should have received a copy of the GNU General Public License |
1069 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1070 | + * |
1071 | + * Author : David Planella <david.planella@ubuntu.com> |
1072 | + */ |
1073 | + |
1074 | +#include <QtQml> |
1075 | +#include <QtQml/QQmlContext> |
1076 | +#include "placesmodel_plugin.h" |
1077 | +#include "placesmodel.h" |
1078 | + |
1079 | +void BackendPlugin::registerTypes(const char *uri) |
1080 | +{ |
1081 | + Q_ASSERT(uri == QLatin1String(QUOTES(PLUGIN_URI))); |
1082 | + |
1083 | + qmlRegisterType<PlacesModel>(uri, 0, 1, "PlacesModel"); |
1084 | +} |
1085 | + |
1086 | +void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
1087 | +{ |
1088 | + QQmlExtensionPlugin::initializeEngine(engine, uri); |
1089 | +} |
1090 | |
1091 | === added file 'src/plugin/placesmodel/placesmodel_plugin.h' |
1092 | --- src/plugin/placesmodel/placesmodel_plugin.h 1970-01-01 00:00:00 +0000 |
1093 | +++ src/plugin/placesmodel/placesmodel_plugin.h 2014-06-26 06:20:10 +0000 |
1094 | @@ -0,0 +1,39 @@ |
1095 | +/* |
1096 | + * Copyright (C) 2013 Canonical Ltd |
1097 | + * |
1098 | + * This program is free software: you can redistribute it and/or modify |
1099 | + * it under the terms of the GNU General Public License version 3 as |
1100 | + * published by the Free Software Foundation. |
1101 | + * |
1102 | + * This program is distributed in the hope that it will be useful, |
1103 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1104 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1105 | + * GNU General Public License for more details. |
1106 | + * |
1107 | + * You should have received a copy of the GNU General Public License |
1108 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1109 | + * |
1110 | + * Author : David Planella <david.planella@ubuntu.com> |
1111 | + */ |
1112 | + |
1113 | +#ifndef PLACESMODEL_PLUGIN_H |
1114 | +#define PLACESMODEL_PLUGIN_H |
1115 | + |
1116 | +#include <QtQml/QQmlEngine> |
1117 | +#include <QtQml/QQmlExtensionPlugin> |
1118 | + |
1119 | +class BackendPlugin : public QQmlExtensionPlugin |
1120 | +{ |
1121 | + Q_OBJECT |
1122 | + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") |
1123 | + |
1124 | +public: |
1125 | + void registerTypes(const char *uri); |
1126 | + void initializeEngine(QQmlEngine *engine, const char *uri); |
1127 | +}; |
1128 | +#endif // PLACESMODEL_PLUGIN_H |
1129 | + |
1130 | + |
1131 | + |
1132 | + |
1133 | + |
1134 | |
1135 | === added file 'src/plugin/placesmodel/qmldir' |
1136 | --- src/plugin/placesmodel/qmldir 1970-01-01 00:00:00 +0000 |
1137 | +++ src/plugin/placesmodel/qmldir 2014-06-26 06:20:10 +0000 |
1138 | @@ -0,0 +1,2 @@ |
1139 | +module com.ubuntu.PlacesModel |
1140 | +plugin PlacesModel |
1141 | |
1142 | === modified file 'tests/autopilot/filemanager/tests/__init__.py' |
1143 | --- tests/autopilot/filemanager/tests/__init__.py 2014-06-19 15:59:52 +0000 |
1144 | +++ tests/autopilot/filemanager/tests/__init__.py 2014-06-26 06:20:10 +0000 |
1145 | @@ -125,14 +125,14 @@ |
1146 | self.useFixture(temp_dir_fixture) |
1147 | temp_dir = temp_dir_fixture.path |
1148 | |
1149 | - #If running under xvfb, as jenkins does, |
1150 | - #xsession will fail to start without xauthority file |
1151 | - #Thus if the Xauthority file is in the home directory |
1152 | - #make sure we copy it to our temp home directory |
1153 | + # If running under xvfb, as jenkins does, |
1154 | + # xsession will fail to start without xauthority file |
1155 | + # Thus if the Xauthority file is in the home directory |
1156 | + # make sure we copy it to our temp home directory |
1157 | self._copy_xauthority_file(temp_dir) |
1158 | |
1159 | - #click requires using initctl env (upstart), but the desktop can set |
1160 | - #an environment variable instead |
1161 | + # click requires using initctl env (upstart), but the desktop can set |
1162 | + # an environment variable instead |
1163 | if self.test_type == 'click': |
1164 | self.useFixture(toolkit_fixtures.InitctlEnvironmentVariable( |
1165 | HOME=temp_dir)) |
1166 | |
1167 | === modified file 'tests/autopilot/filemanager/tests/test_filemanager.py' |
1168 | --- tests/autopilot/filemanager/tests/test_filemanager.py 2014-06-19 15:59:52 +0000 |
1169 | +++ tests/autopilot/filemanager/tests/test_filemanager.py 2014-06-26 06:20:10 +0000 |
1170 | @@ -50,9 +50,9 @@ |
1171 | return folder_list_page.get_file_by_index(index) |
1172 | |
1173 | def _go_to_location(self, location): |
1174 | - #go to specified location |
1175 | - #on wide UI display, we get the location dialog |
1176 | - #on phone UI display, we get places popover |
1177 | + # go to specified location |
1178 | + # on wide UI display, we get the location dialog |
1179 | + # on phone UI display, we get places popover |
1180 | device = model() |
1181 | if self.main_view.showSidebar: |
1182 | logger.debug("Using goto to goto %s on %s" % (location, device)) |
1183 | @@ -70,7 +70,7 @@ |
1184 | expected_path = item.filePath |
1185 | list_view = item.list_view |
1186 | |
1187 | - #item.open_directory() |
1188 | + # item.open_directory() |
1189 | self.pointing_device.click_object(item) |
1190 | self.assertThat( |
1191 | list_view.get_current_path, Eventually(Equals(expected_path))) |
1192 | @@ -131,7 +131,7 @@ |
1193 | original_apps = process_manager.get_running_applications() |
1194 | |
1195 | dialog.open() |
1196 | - #make sure the dialog is open |
1197 | + # make sure the dialog is open |
1198 | self.main_view.get_file_action_dialog() |
1199 | # Filtering copied from |
1200 | # AutopilotTestCase._compare_system_with_app_snapshot. |
1201 | |
1202 | === modified file 'tests/autopilot/filemanager/tests/test_places.py' |
1203 | --- tests/autopilot/filemanager/tests/test_places.py 2014-06-19 16:03:37 +0000 |
1204 | +++ tests/autopilot/filemanager/tests/test_places.py 2014-06-26 06:20:10 +0000 |
1205 | @@ -34,7 +34,7 @@ |
1206 | |
1207 | def test_go_to_root_must_open_the_root_directory(self): |
1208 | """Test that opens the File System bookmark from the places section.""" |
1209 | - self.main_view.go_to_place('placeRoot') |
1210 | + self.main_view.go_to_place('placeFileSystem') |
1211 | |
1212 | folder_list_page = self.main_view.get_folder_list_page() |
1213 | self.assertThat( |
FAILED: Continuous integration, rev:213 91.189. 93.70:8080/ job/ubuntu- filemanager- app-ci/ 263/ 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 599 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 599/artifact/ work/output/ *zip*/output. zip 91.189. 93.70:8080/ job/ubuntu- filemanager- app-utopic- amd64-ci/ 61
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- filemanager- app-ci/ 263/rebuild
http://