Merge lp:~ibelieve/ubuntu-filemanager-app/sidebar into lp:ubuntu-filemanager-app

Proposed by Michael Spencer
Status: Superseded
Proposed branch: lp:~ibelieve/ubuntu-filemanager-app/sidebar
Merge into: lp:ubuntu-filemanager-app
Diff against target: 728 lines (+563/-54)
9 files modified
FolderListPage.qml (+133/-45)
GoToDialog.qml (+89/-0)
OptionsPopover.qml (+31/-7)
PlacesPopover.qml (+2/-0)
PlacesSidebar.qml (+91/-0)
SettingsSheet.qml (+40/-0)
Sidebar.qml (+61/-0)
Storage.qml (+58/-0)
ubuntu-filemanager-app.qml (+58/-2)
To merge this branch: bzr merge lp:~ibelieve/ubuntu-filemanager-app/sidebar
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Ubuntu File Manager Developers Pending
Review via email: mp+178774@code.launchpad.net

This proposal has been superseded by a proposal from 2013-08-06.

Commit message

Added a sidebar for desktop/tablet mode

Description of the change

Added a sidebar for desktop/tablet mode that makes going to bookmarked places easy (like in Nautilus).

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
57. By Michael Spencer

Merged in advanced-options branch

58. By Michael Spencer

Fixed visibility of actions in the folder actions popover

59. By Michael Spencer

Added initial Suru theme and some hacks to make it work by Victor Thompson

60. By Michael Spencer

Improved file action selection popover

61. By Michael Spencer

Fixed how the action selection popover worked

62. By Michael Spencer

Fixed action popovers

63. By Michael Spencer

Improved autopilot tests to work with the sidebar

64. By Michael Spencer

Fixed pep8 and pyflakes errors and worked on fixing autopilot tests

65. By Michael Spencer

Completely fixed all autopilot tests

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'FolderListPage.qml'
2--- FolderListPage.qml 2013-07-26 20:37:32 +0000
3+++ FolderListPage.qml 2013-08-06 15:29:35 +0000
4@@ -330,17 +330,30 @@
5 }
6
7 ToolbarButton {
8- text: i18n.tr("Settings")
9+ text: i18n.tr("Options")
10 iconSource: "icons/settings.png"
11
12 onTriggered: {
13 print(text)
14
15- PopupUtils.open(Qt.resolvedUrl("SettingsPopover.qml"), caller)
16- }
17- }
18-
19- ToolbarButton {
20+ PopupUtils.open(Qt.resolvedUrl("OptionsPopover.qml"), caller)
21+ }
22+ }
23+
24+ ToolbarButton {
25+ visible: wideAspect
26+ objectName: "goTo"
27+ text: i18n.tr("Go To")
28+ iconSource: "icons/location.png"
29+ onTriggered: {
30+ print(text)
31+
32+ PopupUtils.open(Qt.resolvedUrl("GoToDialog.qml"), caller)
33+ }
34+ }
35+
36+ ToolbarButton {
37+ visible: !wideAspect
38 objectName: "places"
39 text: i18n.tr("Places")
40 iconSource: "icons/location.png"
41@@ -350,45 +363,120 @@
42 PopupUtils.open(Qt.resolvedUrl("PlacesPopover.qml"), caller)
43 }
44 }
45- }
46-
47- Column {
48- anchors.centerIn: parent
49- Label {
50- text: i18n.tr("No files")
51- fontSize: "large"
52- visible: folderListView.count == 0 && !pageModel.awaitingResults
53- }
54- ActivityIndicator {
55- running: pageModel.awaitingResults
56- width: units.gu(8)
57- height: units.gu(8)
58- }
59- }
60-
61- FolderListView {
62- id: folderListView
63-
64- clip: true
65-
66- folderListModel: pageModel
67- anchors.fill: parent
68- // IMPROVE: this should work (?), but it doesn't. Height is undefined. Anyway in previous
69- // SDK version the parent size was properly initialized. Now the size of toolbar is not taken into
70- // account and apparently you can't even query toolbar's height.
71- // anchors.bottomMargin: toolbar.height
72- // Now in newer SDK (raring 19.07.2013) locked&opened toolbar is taken into
73- // account in some fashion, but the extra space left to the bottom without this
74- // bottomMargin definition seems to be exactly what is the height of Header's gray
75- // separator bar. This ugly workaround seems to give correct height for view at least on desktop.
76- // Bug report on this:
77- // https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1202881
78- // This bug report also affects this, as if the toolbar is hidden by default
79- // then there is no problem:
80- // https://bugs.launchpad.net/ubuntu-filemanager-app/+bug/1198861
81- // Hard-code it for now. Not nice at all:
82- anchors.bottomMargin: units.gu(-2)
83- }
84+
85+ ToolbarButton {
86+ text: i18n.tr("Settings")
87+ iconSource: "icons/settings.png"
88+ onTriggered: {
89+ print(text)
90+
91+ showSettings()
92+ }
93+ }
94+ }
95+
96+ flickable: !wideAspect ? folderListView : null
97+
98+ PlacesSidebar {
99+ id: sidebar
100+ objectName: "sidebar"
101+
102+ anchors {
103+ top: parent.top
104+ topMargin: units.gu(9.5)
105+ bottom: parent.bottom
106+ bottomMargin: units.gu(-2)
107+ }
108+
109+ expanded: wideAspect
110+ }
111+
112+ Item {
113+ id: contents
114+ anchors {
115+ top: parent.top
116+ bottom: parent.bottom
117+ left: sidebar.right
118+ right: parent.right
119+
120+ // IMPROVE: this should work (?), but it doesn't. Height is undefined. Anyway in previous
121+ // SDK version the parent size was properly initialized. Now the size of toolbar is not taken into
122+ // account and apparently you can't even query toolbar's height.
123+ // anchors.bottomMargin: toolbar.height
124+ // Now in newer SDK (raring 19.07.2013) locked&opened toolbar is taken into
125+ // account in some fashion, but the extra space left to the bottom without this
126+ // bottomMargin definition seems to be exactly what is the height of Header's gray
127+ // separator bar. This ugly workaround seems to give correct height for view at least on desktop.
128+ // Bug report on this:
129+ // https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1202881
130+ // This bug report also affects this, as if the toolbar is hidden by default
131+ // then there is no problem:
132+ // https://bugs.launchpad.net/ubuntu-filemanager-app/+bug/1198861
133+ // Hard-code it for now. Not nice at all:
134+ bottomMargin: units.gu(-2)
135+ }
136+
137+ Column {
138+ anchors.centerIn: parent
139+ Label {
140+ text: i18n.tr("No files")
141+ fontSize: "large"
142+ visible: folderListView.count == 0 && !pageModel.awaitingResults
143+ }
144+ ActivityIndicator {
145+ running: pageModel.awaitingResults
146+ width: units.gu(8)
147+ height: units.gu(8)
148+ }
149+ }
150+
151+ FolderListView {
152+ id: folderListView
153+
154+ clip: true
155+
156+ folderListModel: pageModel
157+ anchors.fill: parent
158+ }
159+ }
160+
161+ states: [
162+ State {
163+ name: "wide"
164+ when: wideAspect
165+ PropertyChanges {
166+ target: tools
167+ locked: true
168+ opened: true
169+ }
170+
171+ PropertyChanges {
172+ target: folderListView
173+
174+ anchors.top: contents.top
175+ anchors.topMargin: units.gu(9.5)
176+ topMargin: 0
177+ }
178+
179+ PropertyChanges {
180+ target: contents
181+ anchors.top: root.top
182+ anchors.topMargin: 0
183+ }
184+ },
185+
186+ //FIXME: This should automatically be calculated - is there a way to remove it?
187+ State {
188+ name: ""
189+
190+ PropertyChanges {
191+ target: folderListView
192+
193+ topMargin: units.gu(9.5)
194+ }
195+ }
196+
197+ ]
198
199 // Errors from model
200 Connections {
201
202=== added file 'GoToDialog.qml'
203--- GoToDialog.qml 1970-01-01 00:00:00 +0000
204+++ GoToDialog.qml 2013-08-06 15:29:35 +0000
205@@ -0,0 +1,89 @@
206+/*
207+ * Copyright (C) 2013 Canonical Ltd
208+ *
209+ * This program is free software: you can redistribute it and/or modify
210+ * it under the terms of the GNU General Public License version 3 as
211+ * published by the Free Software Foundation.
212+ *
213+ * This program is distributed in the hope that it will be useful,
214+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
215+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
216+ * GNU General Public License for more details.
217+ *
218+ * You should have received a copy of the GNU General Public License
219+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
220+ *
221+ * Authored by: Michael Spencer <spencers1993@gmail.com>
222+ */
223+import QtQuick 2.0
224+import Ubuntu.Components 0.1
225+import Ubuntu.Components.Popups 0.1
226+
227+Dialog {
228+ id: root
229+
230+ title: i18n.tr("Go To Location")
231+
232+ text: i18n.tr("Enter a location to go to:")
233+
234+ TextField {
235+ id: locationField
236+
237+ inputMethodHints: Qt.ImhNoAutoUppercase
238+
239+ property bool valid: pathExists(text)
240+
241+ text: fileView.path
242+
243+ placeholderText: i18n.tr("Location...")
244+
245+ onAccepted: goButton.clicked()
246+ }
247+
248+ Button {
249+ id: goButton
250+ objectName: "goButton"
251+
252+ gradient: Gradient {
253+ GradientStop {
254+ position: 0
255+ color: "green"//Qt.rgba(0,0.7,0,1)
256+ }
257+
258+ GradientStop {
259+ position: 1
260+ color: Qt.rgba(0.3,0.7,0.3,1)
261+ }
262+ }
263+
264+ text: i18n.tr("Go")
265+ enabled: locationField.acceptableInput && locationField.valid
266+
267+ onClicked: {
268+ print("User switched to:", locationField.text)
269+ goTo(locationField.text)
270+ PopupUtils.close(root)
271+ }
272+ }
273+
274+ Button {
275+ objectName: "cancelButton"
276+ text: i18n.tr("Cancel")
277+
278+ gradient: Gradient {
279+ GradientStop {
280+ position: 0
281+ color: "gray"
282+ }
283+
284+ GradientStop {
285+ position: 1
286+ color: "lightgray"
287+ }
288+ }
289+
290+ onClicked: {
291+ PopupUtils.close(root)
292+ }
293+ }
294+}
295
296=== renamed file 'SettingsPopover.qml' => 'OptionsPopover.qml'
297--- SettingsPopover.qml 2013-06-27 02:10:00 +0000
298+++ OptionsPopover.qml 2013-08-06 15:29:35 +0000
299@@ -47,11 +47,11 @@
300 }
301
302 ValueSelector {
303- text: "Sort By"
304+ text: i18n.tr("Sort By")
305 selectedIndex: values.indexOf(fileView.sortingMethod)
306 values: [
307- "Name",
308- "Date"
309+ i18n.tr("Name"),
310+ i18n.tr("Date")
311 ]
312
313 onSelectedIndexChanged: {
314@@ -60,15 +60,39 @@
315 }
316
317 ValueSelector {
318- text: "Sort Order"
319+ text: i18n.tr("Sort Order")
320 selectedIndex: sortAccending ? 0 : 1
321 values: [
322- "Ascending",
323- "Descending"
324+ i18n.tr("Ascending"),
325+ i18n.tr("Descending")
326 ]
327
328 onSelectedIndexChanged: {
329- fileView.sortAccending = (values[selectedIndex] === "Ascending")
330+ fileView.sortAccending = (values[selectedIndex] === i18n.tr("Ascending"))
331+ }
332+ }
333+
334+ Standard {
335+ visible: showAdvancedFeatures
336+ text: i18n.tr("Filter")
337+
338+ TextField {
339+ id: filterField
340+ anchors {
341+ verticalCenter: parent.verticalCenter
342+ right: parent.right
343+ margins: units.gu(1)
344+ }
345+
346+ inputMethodHints: Qt.ImhNoAutoUppercase
347+
348+ text: pageModel.nameFilters
349+
350+ onAccepted: goButton.clicked()
351+ onTextChanged: {
352+ if (text !== pageModel.nameFilters)
353+ pageModel.nameFilters = [text]
354+ }
355 }
356 }
357 }
358
359=== modified file 'PlacesPopover.qml'
360--- PlacesPopover.qml 2013-07-08 22:23:29 +0000
361+++ PlacesPopover.qml 2013-08-06 15:29:35 +0000
362@@ -131,6 +131,8 @@
363 PopupUtils.close(root)
364 goTo(model.path)
365 }
366+
367+ selected: folder === path
368 }
369 }
370 }
371
372=== added file 'PlacesSidebar.qml'
373--- PlacesSidebar.qml 1970-01-01 00:00:00 +0000
374+++ PlacesSidebar.qml 2013-08-06 15:29:35 +0000
375@@ -0,0 +1,91 @@
376+/*
377+ * Copyright (C) 2013 Canonical Ltd
378+ *
379+ * This program is free software: you can redistribute it and/or modify
380+ * it under the terms of the GNU General Public License version 3 as
381+ * published by the Free Software Foundation.
382+ *
383+ * This program is distributed in the hope that it will be useful,
384+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
385+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
386+ * GNU General Public License for more details.
387+ *
388+ * You should have received a copy of the GNU General Public License
389+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
390+ *
391+ * Authored by: Michael Spencer <spencers1993@gmail.com>
392+ */
393+import QtQuick 2.0
394+import Ubuntu.Components 0.1
395+import Ubuntu.Components.ListItems 0.1
396+import Ubuntu.Components.Popups 0.1
397+
398+Sidebar {
399+ id: root
400+
401+ width: units.gu(25)
402+
403+ ListModel {
404+ id: places
405+
406+ ListElement {
407+ path: "~"
408+ }
409+
410+ ListElement {
411+ path: "~/Documents"
412+ }
413+
414+ ListElement {
415+ path: "~/Downloads"
416+ }
417+
418+ ListElement {
419+ path: "~/Music"
420+ }
421+
422+ ListElement {
423+ path: "~/Pictures"
424+ }
425+
426+ ListElement {
427+ path: "~/Videos"
428+ }
429+
430+ ListElement {
431+ path: "/"
432+ }
433+ }
434+
435+ Column {
436+ anchors {
437+ left: parent.left
438+ right: parent.right
439+ top: parent.top
440+ }
441+
442+ Header {
443+ text: i18n.tr("Places")
444+ }
445+
446+ Repeater {
447+ id: placesList
448+ objectName: "placesList"
449+
450+ model: places
451+
452+ delegate: Standard {
453+ text: folderName(path)
454+ icon: model.icon || fileIcon(model.path, true)
455+
456+ onClicked: {
457+ goTo(model.path)
458+ }
459+
460+ height: units.gu(5)
461+
462+ selected: folder === path
463+ }
464+ }
465+ }
466+}
467
468=== added file 'SettingsSheet.qml'
469--- SettingsSheet.qml 1970-01-01 00:00:00 +0000
470+++ SettingsSheet.qml 2013-08-06 15:29:35 +0000
471@@ -0,0 +1,40 @@
472+import QtQuick 2.0
473+import Ubuntu.Components 0.1
474+import Ubuntu.Components.ListItems 0.1
475+import Ubuntu.Components.Popups 0.1
476+
477+/*
478+ * The Settings sheet holds global settings/preferences.
479+ *
480+ * TODO: Make sure this fits with the UI guidelines if
481+ * they are updated to include About/Settings info.
482+ */
483+ComposerSheet {
484+ id: root
485+
486+ title: i18n.tr("Settings")
487+
488+ contentsHeight: parent.height
489+
490+ Column {
491+ anchors.fill: parent
492+
493+ Standard {
494+ text: i18n.tr("Show Advanced Features")
495+ control: CheckBox {
496+ id: showAdvancedFeaturesCheckBox
497+ checked: showAdvancedFeatures
498+ }
499+ }
500+ }
501+
502+ onConfirmClicked: {
503+ saveSetting("showAdvancedFeatures", showAdvancedFeaturesCheckBox.checked ? "true" : "false");
504+
505+ // ... Handling of other settings here ...
506+
507+ refreshSettings()
508+
509+ PopupUtils.close(root)
510+ }
511+}
512
513=== added file 'Sidebar.qml'
514--- Sidebar.qml 1970-01-01 00:00:00 +0000
515+++ Sidebar.qml 2013-08-06 15:29:35 +0000
516@@ -0,0 +1,61 @@
517+/*
518+ * Copyright (C) 2013 Canonical Ltd
519+ *
520+ * This program is free software: you can redistribute it and/or modify
521+ * it under the terms of the GNU General Public License version 3 as
522+ * published by the Free Software Foundation.
523+ *
524+ * This program is distributed in the hope that it will be useful,
525+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
526+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
527+ * GNU General Public License for more details.
528+ *
529+ * You should have received a copy of the GNU General Public License
530+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
531+ *
532+ * Authored by: Michael Spencer <spencers1993@gmail.com>
533+ */
534+
535+import QtQuick 2.0
536+import Ubuntu.Components 0.1
537+import Ubuntu.Components.ListItems 0.1
538+
539+Rectangle {
540+ //color: "lightgray"
541+
542+ property bool expanded: true
543+
544+ Rectangle {
545+ color: "lightgray"
546+
547+ anchors {
548+ top: parent.top
549+ bottom: parent.bottom
550+ right: parent.right
551+ }
552+
553+ width: 1
554+ }
555+
556+ width: units.gu(35)
557+
558+
559+ x: expanded ? 0 : -width
560+
561+ Behavior on x {
562+ PropertyAnimation {
563+ duration: 250
564+ }
565+ }
566+
567+ default property alias contents: contents.data
568+
569+ Item {
570+ id: contents
571+
572+ anchors {
573+ fill: parent
574+ rightMargin: 1
575+ }
576+ }
577+}
578
579=== added file 'Storage.qml'
580--- Storage.qml 1970-01-01 00:00:00 +0000
581+++ Storage.qml 2013-08-06 15:29:35 +0000
582@@ -0,0 +1,58 @@
583+import QtQuick.LocalStorage 2.0
584+import QtQuick 2.0
585+
586+Item {
587+ property var db: null
588+
589+ function openDB() {
590+ if(db !== null) return;
591+
592+ db = LocalStorage.openDatabaseSync("ubuntu-filemanager-app", "", "Default Ubuntu file manager app", 100000);
593+
594+ if (db.version === "") {
595+ db.changeVersion("", "0.1",
596+ function(tx) {
597+ tx.executeSql('CREATE TABLE IF NOT EXISTS settings(key TEXT UNIQUE, value TEXT)');
598+ console.log('Database created');
599+ });
600+ // reopen database with new version number
601+ db = LocalStorage.openDatabaseSync("ubuntu-filemanager-app", "", "Default Ubuntu file manager app", 100000);
602+ }
603+ }
604+
605+ function saveSetting(key, value) {
606+ openDB();
607+ db.transaction( function(tx){
608+ tx.executeSql('INSERT OR REPLACE INTO settings VALUES(?, ?)', [key, value]);
609+ });
610+ }
611+
612+ function getSettings(callback) {
613+ openDB();
614+ var settings = {};
615+ db.readTransaction(
616+ function(tx){
617+ var rs = tx.executeSql('SELECT key, value FROM Settings');
618+ for(var i = 0; i < rs.rows.length; i++) {
619+ var row = rs.rows.item(i);
620+ settings[row.key] = row.value;
621+ }
622+ callback(settings);
623+ }
624+ );
625+ }
626+
627+ function clearSetting(name) {
628+ openDB();
629+ db.transaction(function(tx){
630+ tx.executeSql('DELETE FROM Settings WHERE key = ?', [name]);
631+ });
632+ }
633+
634+ function clearDB() { // for dev purposes
635+ openDB();
636+ db.transaction(function(tx){
637+ tx.executeSql('DELETE FROM Settings WHERE 1');
638+ });
639+ }
640+}
641
642=== modified file 'ubuntu-filemanager-app.qml'
643--- ubuntu-filemanager-app.qml 2013-06-27 16:46:45 +0000
644+++ ubuntu-filemanager-app.qml 2013-08-06 15:29:35 +0000
645@@ -18,6 +18,7 @@
646 import QtQuick 2.0
647 import Ubuntu.Components 0.1
648 import org.nemomobile.folderlistmodel 1.0
649+import Ubuntu.Components.Popups 0.1
650
651 /*!
652 \brief MainView with Tabs element.
653@@ -30,18 +31,73 @@
654 // objectName for functional testing purposes (autopilot-qt5)
655 objectName: "filemanager"
656 applicationName: "ubuntu-filemanager-app"
657-
658- width: units.gu(50)
659+
660+ width: units.gu(100)
661 height: units.gu(75)
662
663 property alias filemanager: root
664
665 property bool wideAspect: width >= units.gu(80)
666
667+ // Default settings
668+ property var settings: {"showAdvancedFeatures": false}
669+
670+ property bool needsRefreshSettings: true
671+
672+ // Individual settings, used for bindings
673+ property bool showAdvancedFeatures: false
674+
675 FolderListPage {
676 id: folderPage
677 objectName: "folderPage"
678
679 folder: homeFolder
680 }
681+
682+ Component {
683+ id: settingsSheet
684+
685+ SettingsSheet {
686+ objectName: "settingsSheet"
687+ }
688+ }
689+
690+ Storage {
691+ id: storage
692+ }
693+
694+ function showSettings() {
695+ PopupUtils.open(settingsSheet)
696+ }
697+
698+ function reloadSettings() {
699+ showAdvancedFeatures = settings["showAdvancedFeatures"] === "true" ? true : false
700+ print("showAdvancedFeatures <=", showAdvancedFeatures)
701+ }
702+
703+ function refreshSettings() {
704+ if (needsRefreshSettings) {
705+ storage.getSettings(function(storedSettings) {
706+ for(var settingName in storedSettings) {
707+ print(settingName, "=", storedSettings[settingName])
708+ settings[settingName] = storedSettings[settingName]
709+ }
710+
711+ reloadSettings()
712+ })
713+
714+ needsRefreshSettings = false
715+ }
716+ }
717+
718+ function saveSetting(name, value) {
719+ // Check if the setting was changed
720+ if(settings[name] !== value) {
721+ print(name, "=>", value)
722+ storage.saveSetting(name, value)
723+ needsRefreshSettings = true
724+ }
725+ }
726+
727+ Component.onCompleted: refreshSettings();
728 }

Subscribers

People subscribed via source and target branches