5a55fa83adb5357b253de08484c2fd5c8b44935b
[ubi] / qml / ubi / FilesPage.qml
1 import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
2 import "components"
3 import Qt 4.7
4 import "u1.js" as U1
5 import "bytesconv.js" as Conv
6 import "UIConstants.js" as Const
7
8 Page {
9     id: root
10     title: qsTr("Files")
11
12     property variant secrets
13     property string resource_path: "/~/Ubuntu One";
14     property string content_path: "/content/~/Ubuntu One";
15     property variant properties
16     property string path
17     property string name
18
19     property alias taskMenu: taskMenu
20
21     function init(prop)
22     {
23         if(mask.state!="defocused" && mask.state!="dialog") {
24             mask.state = "busy";
25         }
26         if(root.properties && !prop) {
27             prop = root.properties;
28         }
29
30         secrets = {
31             token: Utils.token(),
32             secret: Utils.tokenSecret(),
33             consumer_key : Utils.customerKey(),
34             consumer_secret: Utils.customerSecret()
35         };
36         if(prop) {
37             root.path = prop.path;
38             root.name = U1.fixFilename(prop.path);
39             U1.getFiles(secrets,prop.resource_path,root);
40             resource_path = prop.resource_path;
41             content_path = prop.content_path;
42         } else {
43             root.path = "/";
44             root.name = "";
45             U1.getFileTree(secrets,root);
46         }
47         root.properties = prop;
48     }
49
50     function onResp(nodes)
51     {
52         createFilesView(nodes);
53     }
54
55     function onErr(status)
56     {
57         mask.state = "idle";
58         initPage.hide();
59
60         if(status==401) {
61             tip.show(qsTr("Ubuntu One authorization has failed. Try once again or check login settings."));
62         } else if(status==0) {
63             tip.show(qsTr("Unable to connect. Check internet connection."));
64         } else {
65             tip.show(qsTr("Unknown error: ")+status);
66         }
67
68         console.log("index="+pageStack.index);
69
70         if(pageStack.index>0) {
71             pageStack.pop();
72         } else {
73             pageStack.initialPage = "LoginPage.qml";
74         }
75     }
76
77
78     function onRespRename()
79     {
80         pageStack.prevPage().init();
81         mask.state = "idle";
82         tip.show(qsTr("Folder renamed!"));
83     }
84
85     function onErrRename(status)
86     {
87         mask.state = "idle";
88         if(status==401) {
89             tip.show(qsTr("Ubuntu One authorization has failed. Try once again or check login settings."));
90         } else {
91             tip.show(qsTr("Unknown error: ")+status);
92         }
93     }
94
95     function onRespNew()
96     {
97         pageStack.currentPage.init();
98         mask.state = "idle";
99         tip.show(qsTr("New folder created!"));
100     }
101
102     function onErrNew(status)
103     {
104         onErrRename(status);
105     }
106
107     function createFilesView(nodes)
108     {
109         var i,l;
110         if(files.children.length>0) {
111             l = files.children.length;
112             for(i=0;i<l;++i) {
113                 files.children[i].destroy();
114             }
115         }
116         var component = Qt.createComponent("components/File.qml");
117         l = nodes.length;
118         for (i=0; i<l; i++) {
119             var object = component.createObject(files);
120             var ind = nodes[i].path.lastIndexOf("/");
121             if(ind>=0) {
122                 object.name = nodes[i].path.substr(ind+1);
123             }  else {
124                 object.name = nodes[i].path;
125             }
126             object.isDirectory = nodes[i].kind == "directory";
127             object.properties = nodes[i];
128             if(object.isDirectory) {
129                 object.clicked.connect(function(prop) {
130                             pageStack.push("FilesPage.qml");
131                             pageStack.currentPage.init(prop);
132                         });
133             } else {
134                 var txt = "" + Conv.bytesToSize(nodes[i].size);
135                 object.description = txt;
136                 object.isPublic = nodes[i].is_public;
137                 object.clicked.connect(function(prop) {
138                             pageStack.push("PropertiesPage.qml");
139                             pageStack.currentPage.init(prop);
140                         });
141
142                 // extension
143                 ind = object.name.lastIndexOf(".");
144                 var ext = "";
145                 if(ind>=0) ext = object.name.substr(ind+1);
146                 if(ext=="jpg" || ext=="JPG" || ext=="Jpg" ||
147                    ext=="jpeg" || ext=="JPEG" || ext=="Jpeg" ||
148                    ext=="gif" || ext=="GIF" || ext=="Gif" ||
149                    ext=="svg" || ext=="SVG" || ext=="Svg" ||
150                    ext=="png" || ext=="PNG" || ext=="Png") {
151                     object.isPhoto = true;
152                 }
153                 if(ext=="mp3" || ext=="MP3" || ext=="Mp3" ||
154                    ext=="wma" || ext=="WMA" || ext=="Wma" ||
155                    ext=="wav" || ext=="WAV" || ext=="Wav" ||
156                    ext=="ogg" || ext=="OGG" || ext=="Ogg" ||
157                    ext=="acc" || ext=="ACC" || ext=="Acc" ||
158                    ext=="m4a" || ext=="M4A" || ext=="M4a" ||
159                    ext=="flac" || ext=="FLAC" || ext=="Flac") {
160                     object.isMusic = true;
161                 }
162                 if(ext=="avi" || ext=="AVI" || ext=="Avi" ||
163                    ext=="mp4" || ext=="MP4" || ext=="Mp4" ||
164                    ext=="mpg" || ext=="MPG" || ext=="Mpg" ||
165                    ext=="mkv" || ext=="MKV" || ext=="Mkv" ||
166                    ext=="flv" || ext=="FLV" || ext=="Flv" ||
167                    ext=="m4v" || ext=="M4V" || ext=="M4v" ||
168                    ext=="3gp" || ext=="3GP") {
169                     object.isVideo = true;
170                 }
171             }
172         }
173         if(mask.state!="defocused" && mask.state!="dialog") {
174             mask.state = "idle";
175         }
176
177         if(l==0) {
178             empty.visible = true;
179         } else {
180             empty.visible = false;
181         }
182
183         initPage.hide()
184     }
185
186     Connections {
187         target: Utils
188         onFileUploaded: init(root.properties);
189     }
190
191     Flickable {
192         id: flickable
193         width: parent.width
194         height: parent.height
195         contentHeight: files.height+Const.TOP_BAR_HEIGHT+Const.SYSTEM_BAR_HEIGHT+Const.TEXT_MARGIN
196         y: Const.TOP_BAR_HEIGHT
197         contentWidth: parent.width
198
199         Column {
200             id: files
201             add: Transition {
202                 NumberAnimation { properties: "opacity"; easing.type: Easing.InOutQuad }
203             }
204         }
205     }
206
207     Text {
208         id: empty
209         font.pixelSize: Const.DEFAULT_FONT_PIXEL_SIZE
210         color: Const.DEFAULT_FOREGROUND_COLOR
211         text: qsTr("Empty")
212         anchors.centerIn: parent
213         font.italic: true
214         visible: false
215     }
216
217     FileDialog {
218         id: fileSelector
219         z: 200
220         hidden: true
221         folder: Utils.lastFolder()=="" ? Const.DEFAULT_FOLDER : Utils.lastFolder()
222         folderOnly: false
223         onFileSelected: {
224             mask.state = "idle";
225             fileSelector.close();
226             Utils.setLastFolder(folder);
227             var path = content_path+"/"+file;
228             U1.uploadFile(secrets,root,path,file,folder,Utils);
229         }
230     }
231
232     function getParentPath(path) {
233         var ppath;
234         var ind = path.lastIndexOf("/");
235         if(ind>=0) {
236             ppath = path.substr(0,ind);
237         }
238         if(path=="") ppath = "/";
239         return ppath;
240     }
241
242     function trim(s) {
243         var l=0; var r=s.length -1;
244         while(l < s.length && s[l] == ' ')
245         {       l++; }
246         while(r > l && s[r] == ' ')
247         {       r-=1;   }
248         return s.substring(l, r+1);
249     }
250
251     Connections {
252         target: Utils
253         onFileDeleted: {
254             if(pageStack.currentPage==root) {
255                 mask.state = "idle";
256                 tip.show(qsTr("Folder was deleted!"));
257                 pageStack.pop();
258                 pageStack.currentPage.init();
259             }
260         }
261         onOperationError: {
262             if(pageStack.currentPage==root) {
263                 mask.state = "idle";
264                 if(status==401) {
265                     tip.show(qsTr("Authorization failed!"));
266                 } else {
267                     tip.show(qsTr("Error: ")+status);
268                 }
269             }
270         }
271     }
272
273     DialogYesNo {
274         id: dialogDelete
275         z: 200
276         text: qsTr("Delete folder?")
277         onOpened: mask.state = "dialog"
278         onClosed: {
279             if(ok) {
280                 mask.state = "busy";
281                 U1.deleteFile(secrets,properties.resource_path,root,Utils);
282             }
283         }
284     }
285
286     DialogInput {
287         id: dialogRename
288         z: 200
289         textWidth: root.width - 4*Const.DEFAULT_MARGIN
290         label: qsTr("Enter new folder name:")
291         placeholderText: root.name
292         onOpened: {
293             reset();
294             Utils.setOrientation("auto");
295         }
296         onClosed: {
297             mask.state = "idle";
298             Utils.setOrientation(root.orientation);
299             var r = trim(resp);
300             if(r!="") {
301                 mask.state = "busy";
302                 var currentPath = root.properties.resource_path;
303                 var targetPath = getParentPath(root.properties.path)+"/"+resp;
304                 U1.renameFile(secrets,currentPath,targetPath,root);
305             } else {
306                 tip.show(qsTr("Invalid folder name!"))
307             }
308         }
309         onCanceled: {
310             Utils.setOrientation(root.orientation);
311         }
312     }
313
314     DialogInput {
315         id: dialogNew
316         z: 200
317         textWidth: root.width - 4*Const.DEFAULT_MARGIN
318         label: qsTr("Enter new folder name:")
319         placeholderText: ""
320         onOpened: {
321             reset();
322             Utils.setOrientation("auto");
323         }
324         onClosed: {
325             Utils.setOrientation(root.orientation);
326             var r = trim(resp);
327             if(r!="") {
328                 mask.state = "busy";
329                 var rpath;
330                 if(root.properties)
331                     rpath = root.properties.resource_path;
332                 else
333                     rpath = root.resource_path;
334                 var newPath = rpath+"/"+resp;
335                 U1.newFolder(secrets,newPath,root);
336             } else {
337                 tip.show(qsTr("Invalid folder name!"))
338             }
339         }
340         onCanceled: {
341             Utils.setOrientation(root.orientation);
342         }
343     }
344
345     TaskMenu {
346         z: 200
347         id: taskMenu
348
349         contexMenu: true
350         menuDynamic: _menuDyn
351         menuHeight: menuDynamic.height+menuFixed.height+7*Const.DEFAULT_MARGIN
352
353         Flow {
354             id: _menuDyn
355
356             y: root.height-taskMenu.menuHeight-Const.SYSTEM_BAR_HEIGHT+2*Const.DEFAULT_MARGIN
357             x: Const.DEFAULT_MARGIN
358
359             width: parent.width-2*Const.DEFAULT_MARGIN
360             spacing: Const.DEFAULT_MARGIN
361
362             Button {
363                 label: qsTr("Upload file");
364                 onButtonClicked: {
365                     taskMenu.close();
366                     fileSelector.open();
367                 }
368             }
369
370             Button {
371                 label: qsTr("Rename");
372                 onButtonClicked: {
373                     taskMenu.close();
374                     if(root.path=="/") {
375                         tip.show(qsTr("Root folder cannot be renamed."));
376                     } else {
377                         dialogRename.open();
378                     }
379                 }
380             }
381
382             Button {
383                 label: qsTr("Delete");
384                 onButtonClicked: {
385                     taskMenu.close();
386                     if(root.path=="/") {
387                         tip.show(qsTr("Root folder cannot be deleted."));
388                     } else {
389                         dialogDelete.open();
390                     }
391                 }
392             }
393
394             Button {
395                 label: qsTr("New folder");
396                 onButtonClicked: {
397                     taskMenu.close();
398                     dialogNew.open();
399                 }
400             }
401
402             Button {
403                 label: qsTr("Refresh");
404                 onButtonClicked: {
405                     taskMenu.close();
406                     init(root.properties);
407                 }
408             }
409         }
410     }
411 }