1/**************************************************************************** 2** 3** Copyright (C) 2015 The Qt Company Ltd. 4** Contact: http://www.qt.io/licensing/ 5** 6** This file is part of the Qt Mobility Components. 7** 8** $QT_BEGIN_LICENSE:LGPL21$ 9** Commercial License Usage 10** Licensees holding valid commercial Qt licenses may use this file in 11** accordance with the commercial license agreement provided with the 12** Software or, alternatively, in accordance with the terms contained in 13** a written agreement between you and The Qt Company. For licensing terms 14** and conditions see http://www.qt.io/terms-conditions. For further 15** information use the contact form at http://www.qt.io/contact-us. 16** 17** GNU Lesser General Public License Usage 18** Alternatively, this file may be used under the terms of the GNU Lesser 19** General Public License version 2.1 or version 3 as published by the Free 20** Software Foundation and appearing in the file LICENSE.LGPLv21 and 21** LICENSE.LGPLv3 included in the packaging of this file. Please review the 22** following information to ensure the GNU Lesser General Public License 23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 25** 26** As a special exception, The Qt Company gives you certain additional 27** rights. These rights are described in The Qt Company LGPL Exception 28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 29** 30** $QT_END_LICENSE$ 31** 32****************************************************************************/ 33 34import QtQuick 2.1 35import Qt.labs.folderlistmodel 2.1 36 37Rectangle { 38 id: fileBrowser 39 color: "transparent" 40 z: 4 41 42 property string folder 43 property bool shown: loader.sourceComponent 44 45 signal fileSelected(string file) 46 47 function selectFile(file) { 48 if (file !== "") { 49 folder = loader.item.folders.folder 50 fileBrowser.fileSelected(file) 51 } 52 loader.sourceComponent = undefined 53 } 54 55 Loader { 56 id: loader 57 } 58 59 function show() { 60 loader.sourceComponent = fileBrowserComponent 61 loader.item.parent = fileBrowser 62 loader.item.anchors.fill = fileBrowser 63 loader.item.folder = fileBrowser.folder 64 } 65 66 Component { 67 id: fileBrowserComponent 68 69 Rectangle { 70 id: root 71 color: "black" 72 property bool showFocusHighlight: false 73 property variant folders: folders1 74 property variant view: view1 75 property alias folder: folders1.folder 76 property color textColor: "white" 77 78 FolderListModel { 79 id: folders1 80 folder: folder 81 } 82 83 FolderListModel { 84 id: folders2 85 folder: folder 86 } 87 88 SystemPalette { 89 id: palette 90 } 91 92 Component { 93 id: folderDelegate 94 95 Rectangle { 96 id: wrapper 97 function launch() { 98 var path = "file://"; 99 if (filePath.length > 2 && filePath[1] === ':') // Windows drive logic, see QUrl::fromLocalFile() 100 path += '/'; 101 path += filePath; 102 if (folders.isFolder(index)) 103 down(path); 104 else 105 fileBrowser.selectFile(path) 106 } 107 width: root.width 108 height: itemHeight 109 color: "transparent" 110 111 Rectangle { 112 id: highlight; visible: false 113 anchors.fill: parent 114 color: palette.highlight 115 gradient: Gradient { 116 GradientStop { id: t1; position: 0.0; color: palette.highlight } 117 GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) } 118 } 119 } 120 121 Item { 122 width: itemHeight; height: itemHeight 123 Image { 124 source: "qrc:/images/icon_Folder.png" 125 fillMode: Image.PreserveAspectFit 126 anchors.fill: parent 127 anchors.margins: scaledMargin 128 visible: folders.isFolder(index) 129 } 130 } 131 132 Text { 133 id: nameText 134 anchors.fill: parent; verticalAlignment: Text.AlignVCenter 135 text: fileName 136 anchors.leftMargin: itemHeight + scaledMargin 137 font.pixelSize: fontSize 138 color: (wrapper.ListView.isCurrentItem && root.showFocusHighlight) ? palette.highlightedText : textColor 139 elide: Text.ElideRight 140 } 141 142 MouseArea { 143 id: mouseRegion 144 anchors.fill: parent 145 onPressed: { 146 root.showFocusHighlight = false; 147 wrapper.ListView.view.currentIndex = index; 148 } 149 onClicked: { if (folders == wrapper.ListView.view.model) launch() } 150 } 151 152 states: [ 153 State { 154 name: "pressed" 155 when: mouseRegion.pressed 156 PropertyChanges { target: highlight; visible: true } 157 PropertyChanges { target: nameText; color: palette.highlightedText } 158 } 159 ] 160 } 161 } 162 163 ListView { 164 id: view1 165 anchors.top: titleBar.bottom 166 anchors.bottom: cancelButton.top 167 x: 0 168 width: parent.width 169 model: folders1 170 delegate: folderDelegate 171 highlight: Rectangle { 172 color: palette.highlight 173 visible: root.showFocusHighlight && view1.count != 0 174 gradient: Gradient { 175 GradientStop { id: t1; position: 0.0; color: palette.highlight } 176 GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) } 177 } 178 width: view1.currentItem == null ? 0 : view1.currentItem.width 179 } 180 highlightMoveVelocity: 1000 181 pressDelay: 100 182 focus: true 183 state: "current" 184 states: [ 185 State { 186 name: "current" 187 PropertyChanges { target: view1; x: 0 } 188 }, 189 State { 190 name: "exitLeft" 191 PropertyChanges { target: view1; x: -root.width } 192 }, 193 State { 194 name: "exitRight" 195 PropertyChanges { target: view1; x: root.width } 196 } 197 ] 198 transitions: [ 199 Transition { 200 to: "current" 201 SequentialAnimation { 202 NumberAnimation { properties: "x"; duration: 250 } 203 } 204 }, 205 Transition { 206 NumberAnimation { properties: "x"; duration: 250 } 207 NumberAnimation { properties: "x"; duration: 250 } 208 } 209 ] 210 Keys.onPressed: root.keyPressed(event.key) 211 } 212 213 ListView { 214 id: view2 215 anchors.top: titleBar.bottom 216 anchors.bottom: parent.bottom 217 x: parent.width 218 width: parent.width 219 model: folders2 220 delegate: folderDelegate 221 highlight: Rectangle { 222 color: palette.highlight 223 visible: root.showFocusHighlight && view2.count != 0 224 gradient: Gradient { 225 GradientStop { id: t1; position: 0.0; color: palette.highlight } 226 GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) } 227 } 228 width: view1.currentItem == null ? 0 : view1.currentItem.width 229 } 230 highlightMoveVelocity: 1000 231 pressDelay: 100 232 states: [ 233 State { 234 name: "current" 235 PropertyChanges { target: view2; x: 0 } 236 }, 237 State { 238 name: "exitLeft" 239 PropertyChanges { target: view2; x: -root.width } 240 }, 241 State { 242 name: "exitRight" 243 PropertyChanges { target: view2; x: root.width } 244 } 245 ] 246 transitions: [ 247 Transition { 248 to: "current" 249 SequentialAnimation { 250 NumberAnimation { properties: "x"; duration: 250 } 251 } 252 }, 253 Transition { 254 NumberAnimation { properties: "x"; duration: 250 } 255 } 256 ] 257 Keys.onPressed: root.keyPressed(event.key) 258 } 259 260 Button { 261 id: cancelButton 262 width: itemWidth 263 height: itemHeight 264 color: "#353535" 265 anchors { bottom: parent.bottom; right: parent.right; margins: 5 * scaledMargin } 266 text: "Cancel" 267 horizontalAlign: Text.AlignHCenter 268 onClicked: fileBrowser.selectFile("") 269 } 270 271 Keys.onPressed: { 272 root.keyPressed(event.key); 273 if (event.key === Qt.Key_Return || event.key === Qt.Key_Select || event.key === Qt.Key_Right) { 274 view.currentItem.launch(); 275 event.accepted = true; 276 } else if (event.key === Qt.Key_Left) { 277 up(); 278 } 279 } 280 281 // titlebar 282 Rectangle { 283 color: "black" 284 width: parent.width; 285 height: itemHeight 286 id: titleBar 287 288 Rectangle { 289 id: upButton 290 width: titleBar.height 291 height: titleBar.height 292 color: "transparent" 293 anchors.left: parent.left 294 anchors.verticalCenter: parent.verticalCenter 295 anchors.margins: scaledMargin 296 297 Image { anchors.fill: parent; anchors.margins: scaledMargin; source: "qrc:/images/icon_BackArrow.png" } 298 MouseArea { id: upRegion; anchors.fill: parent; onClicked: up() } 299 states: [ 300 State { 301 name: "pressed" 302 when: upRegion.pressed 303 PropertyChanges { target: upButton; color: palette.highlight } 304 } 305 ] 306 } 307 308 Text { 309 anchors.left: upButton.right; anchors.right: parent.right; height: parent.height 310 anchors.leftMargin: 10; anchors.rightMargin: 4 311 text: folders.folder 312 color: "white" 313 elide: Text.ElideLeft; horizontalAlignment: Text.AlignLeft; verticalAlignment: Text.AlignVCenter 314 font.pixelSize: fontSize 315 } 316 } 317 318 Rectangle { 319 color: "#353535" 320 width: parent.width 321 height: 1 322 anchors.top: titleBar.bottom 323 } 324 325 function down(path) { 326 if (folders == folders1) { 327 view = view2 328 folders = folders2; 329 view1.state = "exitLeft"; 330 } else { 331 view = view1 332 folders = folders1; 333 view2.state = "exitLeft"; 334 } 335 view.x = root.width; 336 view.state = "current"; 337 view.focus = true; 338 folders.folder = path; 339 } 340 341 function up() { 342 var path = folders.parentFolder; 343 if (path.toString().length === 0 || path.toString() === 'file:') 344 return; 345 if (folders == folders1) { 346 view = view2 347 folders = folders2; 348 view1.state = "exitRight"; 349 } else { 350 view = view1 351 folders = folders1; 352 view2.state = "exitRight"; 353 } 354 view.x = -root.width; 355 view.state = "current"; 356 view.focus = true; 357 folders.folder = path; 358 } 359 360 function keyPressed(key) { 361 switch (key) { 362 case Qt.Key_Up: 363 case Qt.Key_Down: 364 case Qt.Key_Left: 365 case Qt.Key_Right: 366 root.showFocusHighlight = true; 367 break; 368 default: 369 // do nothing 370 break; 371 } 372 } 373 } 374 } 375} 376