New GUI
[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         //console.log("onErr");
58         mask.state = "idle";
59         if(status==401) {
60             tip.show(qsTr("Ubuntu One authorization has failed. Try once again or check login settings."));
61         } else if(status==0) {
62             tip.show(qsTr("Unable to connect. Check internet connection."));
63         } else {
64             tip.show(qsTr("Unknown error: ")+status);
65         }
66         pageStack.pop();
67         initPage.hide()
68     }
69
70
71     function onRespRename()
72     {
73         //console.log("onRespRename");
74         pageStack.prevPage().init();
75         mask.state = "idle";
76         tip.show(qsTr("Folder renamed!"));
77     }
78
79     function onErrRename(status)
80     {
81         //console.log("onErrRenamed");
82         mask.state = "idle";
83         if(status==401) {
84             tip.show(qsTr("Ubuntu One authorization has failed. Try once again or check login settings."));
85         } else {
86             tip.show(qsTr("Unknown error: ")+status);
87         }
88     }
89
90     function onRespNew()
91     {
92         //console.log("onRespNew");
93         pageStack.currentPage.init();
94         mask.state = "idle";
95         tip.show(qsTr("New folder created!"));
96     }
97
98     function onErrNew(status)
99     {
100         onErrRename(status);
101     }
102
103     function createFilesView(nodes)
104     {
105         var i,l;
106         if(files.children.length>0) {
107             l = files.children.length;
108             for(i=0;i<l;++i) {
109                 files.children[i].destroy();
110             }
111         }
112         var component = Qt.createComponent("components/File.qml");
113         l = nodes.length;
114         //console.log("l="+l);
115         for (i=0; i<l; i++) {
116             var object = component.createObject(files);
117             var ind = nodes[i].path.lastIndexOf("/");
118             //object.textMax = root.width/17;
119             //console.log("ind="+ind);
120             if(ind>=0) {
121                 object.name = nodes[i].path.substr(ind+1);
122             }  else {
123                 object.name = nodes[i].path;
124             }
125             object.isDirectory = nodes[i].kind == "directory";
126             object.properties = nodes[i];
127             //object.width = root.width;
128             //object.height = 50;
129             if(object.isDirectory) {
130                 /*if(!nodes[i].has_children) {
131                     object.description = "Empty";
132                 }*/
133                 object.clicked.connect(function(prop) {
134                             pageStack.push("FilesPage.qml");
135                             pageStack.currentPage.init(prop);
136                         });
137             } else {
138                 var txt = "" + Conv.bytesToSize(nodes[i].size);
139                 object.description = txt;
140                 object.isPublic = nodes[i].is_public;
141                 object.clicked.connect(function(prop) {
142                             pageStack.push("PropertiesPage.qml");
143                             pageStack.currentPage.init(prop);
144                         });
145
146                 // extension
147                 ind = object.name.lastIndexOf(".");
148                 var ext = "";
149                 if(ind>=0) ext = object.name.substr(ind+1);
150                 if(ext=="jpg" || ext=="JPG" || ext=="Jpg" ||
151                    ext=="jpeg" || ext=="JPEG" || ext=="Jpeg" ||
152                    ext=="gif" || ext=="GIF" || ext=="Gif" ||
153                    ext=="svg" || ext=="SVG" || ext=="Svg" ||
154                    ext=="png" || ext=="PNG" || ext=="Png") {
155                     object.isPhoto = true;
156                 }
157                 if(ext=="mp3" || ext=="MP3" || ext=="Mp3" ||
158                    ext=="wma" || ext=="WMA" || ext=="Wma" ||
159                    ext=="wav" || ext=="WAV" || ext=="Wav" ||
160                    ext=="ogg" || ext=="OGG" || ext=="Ogg" ||
161                    ext=="acc" || ext=="ACC" || ext=="Acc" ||
162                    ext=="m4a" || ext=="M4A" || ext=="M4a" ||
163                    ext=="flac" || ext=="FLAC" || ext=="Flac") {
164                     object.isMusic = true;
165                 }
166                 if(ext=="avi" || ext=="AVI" || ext=="Avi" ||
167                    ext=="mp4" || ext=="MP4" || ext=="Mp4" ||
168                    ext=="mpg" || ext=="MPG" || ext=="Mpg" ||
169                    ext=="mkv" || ext=="MKV" || ext=="Mkv" ||
170                    ext=="flv" || ext=="FLV" || ext=="Flv" ||
171                    ext=="m4v" || ext=="M4V" || ext=="M4v" ||
172                    ext=="3gp" || ext=="3GP") {
173                     object.isVideo = true;
174                 }
175             }
176         }
177         if(mask.state!="defocused" && mask.state!="dialog") {
178             mask.state = "idle";
179         }
180
181         /*if(files.children.length==0) {
182             empty.visible = true;
183         } else {
184             empty.visible = false;
185         }*/
186
187         if(l==0) {
188             empty.visible = true;
189         } else {
190             empty.visible = false;
191         }
192
193         initPage.hide()
194     }
195
196     Connections {
197         target: Utils
198         onFileUploaded: init(root.properties);
199     }
200
201     Flickable {
202         id: flickable
203         width: parent.width
204         height: parent.height
205         contentHeight: files.height+Const.TOP_BAR_HEIGHT+Const.SYSTEM_BAR_HEIGHT+Const.TEXT_MARGIN
206         y: Const.TOP_BAR_HEIGHT
207         contentWidth: parent.width
208
209         Column {
210             id: files
211             add: Transition {
212                 NumberAnimation { properties: "opacity"; easing.type: Easing.InOutQuad }
213             }
214         }
215     }
216
217     Text {
218         id: empty
219         font.pixelSize: Const.DEFAULT_FONT_PIXEL_SIZE
220         color: Const.DEFAULT_FOREGROUND_COLOR
221         text: qsTr("Empty")
222         anchors.centerIn: parent
223         font.italic: true
224         visible: false
225     }
226
227     /*FileSelector {
228         id: fileSelector
229         z: 200
230         folder: Utils.lastFolder()=="" ? Const.DEFAULT_FOLDER : Utils.lastFolder()
231         folderOnly: false
232         onFileSelected: {
233             mask.state = "idle";
234             //console.log("selected: "+file+" "+U1.fixFolder(folder));
235             fileSelector.close();
236             Utils.setLastFolder(folder);
237             var path = content_path+"/"+file;
238             //console.log(path);
239             U1.uploadFile(secrets,root,path,file,folder,Utils);
240         }
241
242     }*/
243
244     FileDialog {
245         id: fileSelector
246         z: 200
247         hidden: true
248         folder: Utils.lastFolder()=="" ? Const.DEFAULT_FOLDER : Utils.lastFolder()
249         folderOnly: false
250         onFileSelected: {
251             mask.state = "idle";
252             fileSelector.close();
253             Utils.setLastFolder(folder);
254             var path = content_path+"/"+file;
255             U1.uploadFile(secrets,root,path,file,folder,Utils);
256         }
257     }
258
259     function getParentPath(path) {
260         //console.log(path);
261         var ppath;
262         var ind = path.lastIndexOf("/");
263         if(ind>=0) {
264             ppath = path.substr(0,ind);
265         }
266         if(path=="") ppath = "/";
267
268         //console.log(ppath);
269         return ppath;
270     }
271
272     function trim(s) {
273         var l=0; var r=s.length -1;
274         while(l < s.length && s[l] == ' ')
275         {       l++; }
276         while(r > l && s[r] == ' ')
277         {       r-=1;   }
278         return s.substring(l, r+1);
279     }
280
281     Connections {
282         target: Utils
283         onFileDeleted: {
284             if(pageStack.currentPage==root) {
285                 mask.state = "idle";
286                 tip.show(qsTr("Folder was deleted!"));
287                 pageStack.pop();
288                 pageStack.currentPage.init();
289             }
290         }
291         onOperationError: {
292             if(pageStack.currentPage==root) {
293                 mask.state = "idle";
294                 if(status==401) {
295                     tip.show(qsTr("Authorization failed!"));
296                 } else {
297                     tip.show(qsTr("Error: ")+status);
298                 }
299             }
300         }
301     }
302
303     DialogYesNo {
304         id: dialogDelete
305         z: 200
306         text: qsTr("Delete folder?")
307         onOpened: mask.state = "dialog"
308         onClosed: {
309             if(ok) {
310                 mask.state = "busy";
311                 U1.deleteFile(secrets,properties.resource_path,root,Utils);
312             }
313         }
314     }
315
316     DialogInput {
317         id: dialogRename
318         z: 200
319         textWidth: root.width - 4*Const.DEFAULT_MARGIN
320         label: qsTr("Enter new folder name:")
321         placeholderText: root.name
322         onOpened: {
323             reset();
324             Utils.setOrientation("auto");
325         }
326         onClosed: {
327             mask.state = "idle";
328             Utils.setOrientation(root.orientation);
329             var r = trim(resp);
330             if(r!="") {
331                 mask.state = "busy";
332                 var currentPath = root.properties.resource_path;
333                 var targetPath = getParentPath(root.properties.path)+"/"+resp;
334                 //console.log("targetPath: "+targetPath);
335                 U1.renameFile(secrets,currentPath,targetPath,root);
336             } else {
337                 tip.show(qsTr("Invalid folder name!"))
338             }
339         }
340         onCanceled: {
341             Utils.setOrientation(root.orientation);
342         }
343     }
344
345     DialogInput {
346         id: dialogNew
347         z: 200
348         textWidth: root.width - 4*Const.DEFAULT_MARGIN
349         label: qsTr("Enter new folder name:")
350         placeholderText: ""
351         onOpened: {
352             reset();
353             Utils.setOrientation("auto");
354         }
355         onClosed: {
356             Utils.setOrientation(root.orientation);
357             var r = trim(resp);
358             if(r!="") {
359                 mask.state = "busy";
360                 var rpath;
361                 if(root.properties)
362                     rpath = root.properties.resource_path;
363                 else
364                     rpath = root.resource_path;
365                 var newPath = rpath+"/"+resp;
366                 //console.log("newPath: "+newPath);
367                 U1.newFolder(secrets,newPath,root);
368             } else {
369                 tip.show(qsTr("Invalid folder name!"))
370             }
371         }
372         onCanceled: {
373             Utils.setOrientation(root.orientation);
374         }
375     }
376
377     /*[qsTr("Upload file"),false],
378     [qsTr("Rename"),false],
379     [qsTr("Delete"),false],
380     [qsTr("New folder"),false],
381     [qsTr("Refresh"),false]
382     function menuFun(id) {
383         if(id==qsTr("Upload file")) {
384             mask.state = "dialog";
385             fileSelector.open();
386         }
387         if(id==qsTr("Refresh")) {
388             init(root.properties);
389         }
390         if(id==qsTr("Rename")) {
391             if(root.path=="/") {
392                 tip.show(qsTr("Root folder can't be renamed!"));
393             } else {
394                 dialogRename.open();
395             }
396         }
397         if(id==qsTr("Delete")) {
398             if(root.path=="/") {
399                 tip.show(qsTr("Root folder can't be deleted!"));
400             } else {
401                 dialogDelete.open();
402             }
403         }
404         if(id==qsTr("New folder")) {
405             dialogNew.open();
406         }
407     }
408 */
409
410     TaskMenu {
411         z: 200
412         id: taskMenu
413
414         contexMenu: true
415         menuDynamic: _menuDyn
416         menuHeight: menuDynamic.height+menuFixed.height+7*Const.DEFAULT_MARGIN
417
418         Flow {
419             id: _menuDyn
420
421             y: root.height-taskMenu.menuHeight-Const.SYSTEM_BAR_HEIGHT+2*Const.DEFAULT_MARGIN
422             x: Const.DEFAULT_MARGIN
423
424             width: parent.width-2*Const.DEFAULT_MARGIN
425             spacing: Const.DEFAULT_MARGIN
426
427             Button {
428                 label: qsTr("Upload file");
429                 onButtonClicked: {
430                     taskMenu.close();
431                     fileSelector.open();
432                 }
433             }
434
435             Button {
436                 label: qsTr("Rename");
437                 onButtonClicked: {
438                     taskMenu.close();
439                     if(root.path=="/") {
440                         tip.show(qsTr("Root folder cannot be renamed."));
441                     } else {
442                         dialogRename.open();
443                     }
444                 }
445             }
446
447             Button {
448                 label: qsTr("Delete");
449                 onButtonClicked: {
450                     taskMenu.close();
451                     if(root.path=="/") {
452                         tip.show(qsTr("Root folder cannot be deleted."));
453                     } else {
454                         dialogDelete.open();
455                     }
456                 }
457             }
458
459             Button {
460                 label: qsTr("New folder");
461                 onButtonClicked: {
462                     taskMenu.close();
463                     dialogNew.open();
464                 }
465             }
466
467             Button {
468                 label: qsTr("Refresh");
469                 onButtonClicked: {
470                     taskMenu.close();
471                     init(root.properties);
472                 }
473             }
474         }
475     }
476 }