2 import Sailfish.Silica 1.0
3 import harbour.file.browser.SearchEngine 1.0
4 import "functions.js" as Functions
9 allowedOrientations: Orientation.All
10 showNavigationIndicator: false // hide back indicator because it would be on top of search field
11 property string dir: "/"
12 property string currentDirectory: ""
14 // this and its bg worker thread will be destroyed when page in popped from stack
19 onProgressChanged: page.currentDirectory = directory
20 onMatchFound: listModel.append({ fullname: fullname, filename: filename,
21 absoluteDir: absoluteDir,
22 fileIcon: fileIcon, fileKind: fileKind });
23 onWorkerDone: { /* Nothing to do */ }
24 onWorkerErrorOccurred: { notificationPanel.showText(message, filename); }
31 // prevent newly added list delegates from stealing focus away from the search field
37 function update(txt) {
39 searchEngine.cancel();
43 searchEngine.search(txt);
47 Component.onCompleted: update("")
50 VerticalScrollDecorator { flickable: fileList }
54 text: qsTr("Settings")
55 onClicked: pageStack.push(Qt.resolvedUrl("SettingsPage.qml"))
65 anchors.left: parent.left
66 anchors.right: cancelSearchButton.left
67 placeholderText: qsTr("Search %1").arg(Functions.formatPathForSearch(page.dir))
68 inputMethodHints: Qt.ImhNoAutoUppercase
70 // get focus when page is shown for the first time
71 Component.onCompleted: forceActiveFocus()
73 // return key on virtual keyboard starts or restarts search
74 EnterKey.enabled: true
76 notificationPanel.hide();
77 listModel.update(searchField.text);
78 foundText.visible = true;
79 searchField.focus = false;
82 // our own "IconButton" to make the mouse area large and easier to tap
84 id: cancelSearchButton
85 anchors.right: parent.right
86 anchors.top: searchField.top
87 width: Theme.iconSizeMedium+Theme.paddingLarge
88 height: searchField.height
89 color: cancelSearchMouseArea.pressed ? Theme.secondaryHighlightColor : "transparent"
91 id: cancelSearchMouseArea
94 if (!searchEngine.running) {
95 listModel.update(searchField.text);
96 foundText.visible = true;
103 id: cancelSearchButtonImage
104 anchors.verticalCenter: parent.verticalCenter
105 anchors.right: parent.right
106 anchors.rightMargin: Theme.paddingLarge
107 source: searchEngine.running ? "image://theme/icon-m-clear" :
108 "image://theme/icon-m-right"
112 anchors.centerIn: cancelSearchButtonImage
113 running: searchEngine.running
114 size: BusyIndicatorSize.Small
121 anchors.left: parent.left
122 anchors.leftMargin: searchField.textLeftMargin
123 anchors.top: searchField.bottom
124 anchors.topMargin: -26
125 text: qsTr("%1 hits").arg(listModel.count)
126 font.pixelSize: Theme.fontSizeTiny
127 color: Theme.secondaryColor
130 anchors.left: parent.left
131 anchors.leftMargin: 240
132 anchors.right: parent.right
133 anchors.rightMargin: Theme.paddingLarge
134 anchors.top: searchField.bottom
135 anchors.topMargin: -26
136 text: page.currentDirectory
137 font.pixelSize: Theme.fontSizeTiny
138 color: Theme.secondaryColor
139 elide: Text.ElideRight
146 width: ListView.view.width
147 contentHeight: listLabel.height+listAbsoluteDir.height + 13
151 anchors.left: parent.left
152 anchors.leftMargin: Theme.paddingLarge
153 anchors.top: parent.top
154 anchors.topMargin: 11
155 source: "../images/small-"+fileIcon+".png"
159 anchors.left: listIcon.right
160 anchors.leftMargin: 10
161 anchors.right: parent.right
162 anchors.rightMargin: Theme.paddingLarge
163 anchors.top: parent.top
166 elide: Text.ElideRight
170 anchors.left: listIcon.right
171 anchors.leftMargin: 10
172 anchors.right: parent.right
173 anchors.rightMargin: Theme.paddingLarge
174 anchors.top: listLabel.bottom
176 color: Theme.secondaryColor
177 font.pixelSize: Theme.fontSizeExtraSmall
178 elide: Text.ElideLeft
182 if (model.fileKind === "d")
183 pageStack.push(Qt.resolvedUrl("DirectoryPage.qml"),
184 { dir: model.fullname });
186 pageStack.push(Qt.resolvedUrl("FilePage.qml"),
187 { file: model.fullname });
190 // delete file after remorse time
191 ListView.onRemove: animateRemoval(fileItem)
192 function deleteFile(deleteFilename) {
193 remorseAction(qsTr("Deleting"), function() {
194 progressPanel.showText(qsTr("Deleting"));
195 engine.deleteFiles([ deleteFilename ]);
199 // context menu is activated with long press, visible if search is not running
204 text: qsTr("Go to containing folder")
205 onClicked: Functions.goToFolder(model.absoluteDir)
209 onClicked: engine.cutFiles([ model.fullname ]);
213 onClicked: engine.copyFiles([ model.fullname ]);
217 onClicked: deleteFile(model.fullname);
225 // connect signals from engine to panels
228 onProgressChanged: progressPanel.text = engine.progressFilename
229 onWorkerDone: progressPanel.hide()
230 onWorkerErrorOccurred: {
231 // the error signal goes to all pages in pagestack, show it only in the active one
232 if (progressPanel.open) {
233 progressPanel.hide();
234 notificationPanel.showText(message, filename);
238 // item got deleted by worker, so remove it from list
240 for (var i = 0; i < listModel.count; ++i) {
241 var item = listModel.get(i);
242 if (item.fullname === fullname) {
251 id: notificationPanel
258 onCancelled: engine.cancel()