diff --git a/assets.qrc b/assets.qrc
index 167a020..3775d78 100644
--- a/assets.qrc
+++ b/assets.qrc
@@ -1,17 +1,21 @@
assets/face-sleeping.png
assets/face-sleeping.svg
assets/tag.svg
assets/maui-app.colors
assets/mauikit-logo.png
assets/ElectricPlug.png
assets/BugSearch.png
assets/MoonSki.png
assets/application-x-zerosize.svg
assets/animat-rocket-color.gif
assets/animat-diamond-color.gif
assets/animat-search-color.gif
assets/opendesktop.png
+ assets/folder-add.svg
+ assets/view-refresh.svg
+ assets/edit-find.svg
+ assets/dialog-information.svg
diff --git a/assets/dialog-information.svg b/assets/dialog-information.svg
new file mode 100644
index 0000000..c91ec19
--- /dev/null
+++ b/assets/dialog-information.svg
@@ -0,0 +1,119 @@
+
+
+
+
diff --git a/assets/edit-find.svg b/assets/edit-find.svg
new file mode 100644
index 0000000..89da349
--- /dev/null
+++ b/assets/edit-find.svg
@@ -0,0 +1,104 @@
+
+
+
+
diff --git a/assets/folder-add.svg b/assets/folder-add.svg
new file mode 100644
index 0000000..881d69a
--- /dev/null
+++ b/assets/folder-add.svg
@@ -0,0 +1,108 @@
+
+
+
+
diff --git a/assets/view-refresh.svg b/assets/view-refresh.svg
new file mode 100644
index 0000000..5f58744
--- /dev/null
+++ b/assets/view-refresh.svg
@@ -0,0 +1,104 @@
+
+
+
+
diff --git a/maui-style/TextField.qml b/maui-style/TextField.qml
index bc3b3db..4413eae 100755
--- a/maui-style/TextField.qml
+++ b/maui-style/TextField.qml
@@ -1,88 +1,89 @@
/*
* Copyright 2017 Marco Martin
* Copyright 2017 The Qt Company Ltd.
*
* GNU Lesser General Public License Usage
* Alternatively, this file may be used under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software
* Foundation and appearing in the file LICENSE.LGPLv3 included in the
* packaging of this file. Please review the following information to
* ensure the GNU Lesser General Public License version 3 requirements
* will be met: https://www.gnu.org/licenses/lgpl.html.
*
* GNU General Public License Usage
* Alternatively, this file may be used under the terms of the GNU
* General Public License version 2.0 or later as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included in
* the packaging of this file. Please review the following information to
* ensure the GNU General Public License version 2.0 requirements will be
* met: http://www.gnu.org/licenses/gpl-2.0.html.
*/
import QtQuick 2.6
import QtQuick.Window 2.1
import QtQuick.Controls 2.3 as Controls
import QtQuick.Templates 2.3 as T
import org.kde.kirigami 2.2 as Kirigami
T.TextField {
id: controlRoot
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
implicitWidth: Math.max(200,
placeholderText ? placeholder.implicitWidth + leftPadding + rightPadding : 0)
|| contentWidth + leftPadding + rightPadding
implicitHeight: Math.max(contentHeight + topPadding + bottomPadding,
background ? Kirigami.Units.iconSizes.smallMedium : 0,
placeholder.implicitHeight + topPadding + bottomPadding)
padding: 6
/*
color: controlRoot.enabled ? Kirigami.Theme.textColor : Kirigami.Theme.disabledTextColor
selectionColor: Kirigami.Theme.highlightColor
selectedTextColor: Kirigami.Theme.highlightedTextColor
verticalAlignment: TextInput.AlignVCenter*/
//Text.NativeRendering is broken on non integer pixel ratios
renderType: Window.devicePixelRatio % 1 !== 0 ? Text.QtRendering : Text.NativeRendering
color: enabled ? Kirigami.Theme.textColor : Kirigami.Theme.disabledtextColor
selectionColor: Kirigami.Theme.highlightColor
selectedTextColor: Kirigami.Theme.highlightedTextColor
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: Text.AlignHCenter
// cursorDelegate: CursorDelegate { }
Controls.Label
{
id: placeholder
x: control.leftPadding
y: control.topPadding
width: control.width - (control.leftPadding + control.rightPadding)
height: control.height - (control.topPadding + control.bottomPadding)
text: control.placeholderText
font: control.font
color: Qt.lighter(Kirigami.Theme.textColor, 1.4)
opacity: 0.4
horizontalAlignment: control.horizontalAlignment
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
+ wrapMode: Text.NoWrap
}
background: Rectangle
{
implicitWidth: unit * 120
implicitHeight: Kirigami.Settings.isMobile ? Kirigami.Units.iconSizes.medium : Kirigami.Units.iconSizes.medium
color: control.activeFocus ? Qt.lighter(Kirigami.Theme.backgroundColor, 1.4)
: (control.hovered ? Qt.lighter(Kirigami.Theme.backgroundColor, 1.3) : Kirigami.Theme.backgroundColor)
border.color: Qt.tint(Kirigami.Theme.textColor, Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.7))
radius: radiusV
border.width: unit
}
}
diff --git a/src/controls/FileBrowser.qml b/src/controls/FileBrowser.qml
index e5e074c..aa8bb20 100644
--- a/src/controls/FileBrowser.qml
+++ b/src/controls/FileBrowser.qml
@@ -1,891 +1,1064 @@
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
+import QtQml.Models 2.3
import org.kde.kirigami 2.7 as Kirigami
import org.kde.mauikit 1.0 as Maui
import "private"
Maui.Page
{
id: control
- property alias trackChanges: control.currentFMList.trackChanges
- property alias saveDirProps: control.currentFMList.saveDirProps
+ property var trackChanges: control.currentFMList.trackChanges
+ property var saveDirProps: control.currentFMList.saveDirProps
- property string currentPath: Maui.FM.homePath()
+ property string currentPath
+ onCurrentPathChanged: control.browserView.path = control.currentPath
property var copyItems : []
property var cutItems : []
property var indexHistory : []
property bool isCopy : false
property bool isCut : false
property bool selectionMode : false
property bool group : false
property bool showEmblems: true
property bool singleSelection: false
property alias selectionBar : selectionBarLoader.item
- property alias browser : _browserView.currentView
- property alias currentFMList : _browserView.currentFMList
+ property alias browserView : _browserList.currentItem
+ property var browser : browserView.currentView
+ property Maui.FMList currentFMList : browserView.currentFMList
property alias previewer : previewer
property alias menu : browserMenu.contentData
property alias itemMenu: itemMenu
property alias holder: holder
property alias dialog : dialogLoader.item
property alias goUpButton : goUpButton
property int currentPathType : currentFMList.pathType
property int thumbnailsSize : iconSizes.large
signal itemClicked(int index)
signal itemDoubleClicked(int index)
signal itemRightClicked(int index)
signal itemLeftEmblemClicked(int index)
signal itemRightEmblemClicked(int index)
signal rightClicked()
signal newBookmark(var paths)
focus: true
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
- onGoBackTriggered:
- {
- control.goBack()
- console.log("trying to go BACCCCCCCCCCCCCCCCCK")
- }
-
+ onGoBackTriggered: control.goBack()
onGoForwardTriggered: control.goNext()
Keys.onSpacePressed: previewer.show(control.currentFMList.get(browser.currentIndex).path)
+
+ footBar.visible: false
+ footBar.leftContent: Label
+ {
+ Layout.fillWidth: true
+ text: control.currentFMList.count + " " + qsTr("items")
+ }
+
+ footBar.rightContent: [
+
+ ToolButton
+ {
+ icon.name: "zoom-in"
+ onClicked: zoomIn()
+ },
+
+ ToolButton
+ {
+ icon.name: "zoom-out"
+ onClicked: zoomOut()
+ }
+ ]
+
headBar.visible: currentPathType !== Maui.FMList.APPS_PATH
headBar.position: isMobile ? ToolBar.Footer : ToolBar.Header
property list t_actions:
[
Action
{
id: _previewAction
icon.name: "image-preview"
text: qsTr("Previews")
checkable: true
checked: control.currentFMList.preview
onTriggered: control.currentFMList.preview = !control.currentFMList.preview
},
Action
{
id: _hiddenAction
icon.name: "visibility"
text: qsTr("Hidden files")
checkable: true
checked: control.currentFMList.hidden
onTriggered: control.currentFMList.hidden = !control.currentFMList.hidden
},
Action
{
id: _bookmarkAction
icon.name: "bookmark-new"
text: qsTr("Bookmark")
onTriggered: newBookmark([currentPath])
},
Action
{
id: _newFolderAction
icon.name: "folder-add"
text: qsTr("New folder")
onTriggered:
{
dialogLoader.sourceComponent= newFolderDialogComponent
dialog.open()
}
},
Action
{
id: _newDocumentAction
icon.name: "document-new"
text: qsTr("New file")
onTriggered:
{
dialogLoader.sourceComponent= newFileDialogComponent
dialog.open()
}
},
Action
{
id: _pasteAction
text: qsTr("Paste ")+"["+browserMenu.pasteFiles+"]"
icon.name: "edit-paste"
enabled: browserMenu.pasteFiles > 0
onTriggered: paste()
- }]
+ },
+
+ Action
+ {
+ text: qsTr("Status bar")
+ checkable: false
+ checked: control.footBar.visible
+ onTriggered: control.footBar.visible = !control.footBar.visible
+ }
+ ]
Loader
{
id: dialogLoader
}
Component
{
id: removeDialogComponent
Maui.Dialog
{
property var items: []
title: qsTr("Remove files?")
message: qsTr("You can move the file to the Trash or Delete it completely from your system. Which one you preffer?")
rejectButton.text: qsTr("Delete")
acceptButton.text: qsTr("Trash")
acceptButton.visible: !isMobile
onRejected:
{
if(control.selectionBar && control.selectionBar.visible)
{
control.selectionBar.clear()
control.selectionBar.animate(Maui.Style.dangerColor)
}
control.remove(items)
close()
}
onAccepted:
{
if(control.selectionBar && control.selectionBar.visible)
{
control.selectionBar.clear()
control.selectionBar.animate(Maui.Style.dangerColor)
}
control.trash(items)
close()
}
}
}
Component
{
id: newFolderDialogComponent
Maui.NewDialog
{
title: qsTr("New folder")
message: qsTr("Create a new folder with a custom name")
acceptButton.text: qsTr("Create")
onFinished: control.currentFMList.createDir(text)
rejectButton.visible: false
textEntry.placeholderText: qsTr("Folder name...")
}
}
Component
{
id: newFileDialogComponent
Maui.NewDialog
{
title: qsTr("New file")
message: qsTr("Create a new file with a custom name and extension")
acceptButton.text: qsTr("Create")
onFinished: Maui.FM.createFile(control.currentPath, text)
rejectButton.visible: false
textEntry.placeholderText: qsTr("File name...")
}
}
Component
{
id: renameDialogComponent
Maui.NewDialog
{
title: qsTr("Rename file")
message: qsTr("Rename a file or folder to a new custom name")
textEntry.text: itemMenu.item.label
textEntry.placeholderText: qsTr("New name...")
onFinished: Maui.FM.rename(itemMenu.item.path, textEntry.text)
onRejected: close()
acceptText: qsTr("Rename")
rejectText: qsTr("Cancel")
}
}
Component
{
id: shareDialogComponent
Maui.ShareDialog {}
}
Component
{
id: tagsDialogComponent
Maui.TagsDialog
{
onTagsReady: composerList.updateToUrls(tags)
}
}
BrowserMenu
{
id: browserMenu
z : control.z +1
}
Maui.FilePreviewer
{
id: previewer
parent: parent
onShareButtonClicked: control.shareFiles([url])
}
FileMenu
{
id: itemMenu
width: unit *200
onBookmarkClicked: control.newBookmark([item.path])
onCopyClicked:
{
if(item)
control.copy([item])
}
onCutClicked:
{
if(item)
control.cut([item])
}
onTagsClicked:
{
if(item)
{
dialogLoader.sourceComponent = tagsDialogComponent
dialog.composerList.urls = item.path
dialog.open()
}
}
onRenameClicked:
{
dialogLoader.sourceComponent = renameDialogComponent
dialog.open()
}
onRemoveClicked:
{
dialogLoader.sourceComponent= removeDialogComponent
dialog.items = [item]
dialog.open()
}
onShareClicked: control.shareFiles([item.path])
}
Connections
{
target: browser
onItemClicked:
{
console.log("item clicked connections:", index)
browser.currentIndex = index
indexHistory.push(index)
control.itemClicked(index)
}
onItemDoubleClicked:
{
browser.currentIndex = index
indexHistory.push(index)
control.itemDoubleClicked(index)
}
onItemRightClicked:
{
if(currentFMList.pathType !== Maui.FMList.TRASH_PATH &&
currentFMList.pathType !== Maui.FMList.REMOTE_PATH
)
itemMenu.show(index)
control.itemRightClicked(index)
}
onLeftEmblemClicked:
{
control.addToSelection(control.currentFMList.get(index), true)
control.itemLeftEmblemClicked(index)
}
onRightEmblemClicked:
{
isAndroid ? Maui.Android.shareDialog([control.currentFMList.get(index).path]) : shareDialog.show([control.currentFMList.get(index).path])
control.itemRightEmblemClicked(index)
}
onAreaClicked:
{
if(!isMobile && mouse.button === Qt.RightButton)
browserMenu.show()
else return
control.rightClicked()
}
onAreaRightClicked: browserMenu.show()
}
Maui.Holder
{
id: holder
anchors.fill : parent
z: -1
visible: !control.currentFMList.pathExists || control.currentFMList.pathEmpty || !control.currentFMList.contentReady
emoji: if(control.currentFMList.pathExists && control.currentFMList.pathEmpty)
- "qrc:/assets/MoonSki.png"
+ "qrc:/assets/folder-add.svg"
else if(!control.currentFMList.pathExists)
- "qrc:/assets/ElectricPlug.png"
+ "qrc:/assets/dialog-information.svg"
else if(!control.currentFMList.contentReady && currentPathType === Maui.FMList.SEARCH_PATH)
- "qrc:/assets/animat-search-color.gif"
+ "qrc:/assets/edit-find.svg"
else if(!control.currentFMList.contentReady)
- "qrc:/assets/animat-rocket-color.gif"
+ "qrc:/assets/view-refresh.svg"
- isGif: !control.currentFMList.contentReady
- isMask: false
+// isGif: !control.currentFMList.contentReady
+// isMask: false
title : if(control.currentFMList.pathExists && control.currentFMList.pathEmpty)
qsTr("Folder is empty!")
else if(!control.currentFMList.pathExists)
qsTr("Folder doesn't exists!")
else if(!control.currentFMList.contentReady && currentPathType === Maui.FMList.SEARCH_PATH)
qsTr("Searching for content!")
else if(!control.currentFMList.contentReady)
qsTr("Loading content!")
body: if(control.currentFMList.pathExists && control.currentFMList.pathEmpty)
qsTr("You can add new files to it")
else if(!control.currentFMList.pathExists)
qsTr("Create Folder?")
else if(!control.currentFMList.contentReady && currentPathType === Maui.FMList.SEARCH_PATH)
qsTr("This might take a while!")
else if(!control.currentFMList.contentReady)
qsTr("Almost ready!")
emojiSize: iconSizes.huge
onActionTriggered:
{
if(!control.currentFMList.pathExists)
{
Maui.FM.createDir(control.currentPath.slice(0, control.currentPath.lastIndexOf("/")), control.currentPath.split("/").pop())
control.openFolder(control.currentFMList.parentPath)
}
}
}
// headBar.stickyRightContent: true
headBar.rightContent:[
Kirigami.ActionToolBar
{
position: ToolBar.Header
Layout.fillWidth: true
hiddenActions: t_actions
display: isWide ? ToolButton.TextBesideIcon : ToolButton.IconOnly
actions: [
Action
{
icon.name: "view-list-icons"
- onTriggered: _browserView.viewType = Maui.FMList.ICON_VIEW
+ onTriggered: browserView.viewType = Maui.FMList.ICON_VIEW
checkable: false
- checked: _browserView.viewType === Maui.FMList.ICON_VIEW
+ checked: browserView.viewType === Maui.FMList.ICON_VIEW
icon.width: iconSizes.medium
text: qsTr("Grid view")
// autoExclusive: true
},
Action
{
icon.name: "view-list-details"
- onTriggered: _browserView.viewType = Maui.FMList.LIST_VIEW
+ onTriggered: browserView.viewType = Maui.FMList.LIST_VIEW
icon.width: iconSizes.medium
- checked: _browserView.viewType === Maui.FMList.LIST_VIEW
+ checked: browserView.viewType === Maui.FMList.LIST_VIEW
text: qsTr("List view")
// autoExclusive: true
},
Action
{
icon.name: "view-file-columns"
- onTriggered: _browserView.viewType = Maui.FMList.MILLERS_VIEW
+ onTriggered: browserView.viewType = Maui.FMList.MILLERS_VIEW
icon.width: iconSizes.medium
- checked: _browserView.viewType === Maui.FMList.MILLERS_VIEW
+ checked: browserView.viewType === Maui.FMList.MILLERS_VIEW
text: qsTr("Column view")
// autoExclusive: true
},
Kirigami.Action
{
icon.name: "view-sort"
text: qsTr("Sort")
Kirigami.Action
{
text: qsTr("Folders first")
checked: con.foldersFirst
onTriggered: control.currentFMList.foldersFirst = !control.currentFMList.foldersFirst
}
Kirigami.Action
{
text: qsTr("Type")
checked: control.currentFMList.sortBy === Maui.FMList.MIME
onTriggered: control.currentFMList.sortBy = Maui.FMList.MIME
}
Kirigami.Action
{
text: qsTr("Date")
checked: control.currentFMList.sortBy === Maui.FMList.DATE
onTriggered: control.currentFMList.sortBy = Maui.FMList.DATE
}
Kirigami.Action
{
text: qsTr("Modified")
checked: control.currentFMList.sortBy === Maui.FMList.MODIFIED
onTriggered: control.currentFMList.sortBy = Maui.FMList.MODIFIED
}
Kirigami.Action
{
text: qsTr("Size")
checked: control.currentFMList.sortBy === Maui.FMList.SIZE
onTriggered: control.currentFMList.sortBy = Maui.FMList.SIZE
}
Kirigami.Action
{
text: qsTr("Name")
checked: control.currentFMList.sortBy === Maui.FMList.LABEL
onTriggered: control.currentFMList.sortBy = Maui.FMList.LABEL
}
Kirigami.Action
{
id: groupAction
text: qsTr("Group")
checked: control.group
onTriggered:
{
control.group = !control.group
if(control.group)
groupBy()
else
browser.section.property = ""
}
}
},
- Kirigami.Action
- {
- text: qsTr("Select")
- icon.name: "item-select"
- checkable: false
- checked: control.selectionMode
- onTriggered: control.selectionMode = !control.selectionMode
-
- }
- ]
- }
+ Kirigami.Action
+ {
+ text: qsTr("Select")
+ icon.name: "item-select"
+ checkable: false
+ checked: control.selectionMode
+ onTriggered: control.selectionMode = !control.selectionMode
+
+ }
+ ]
+ }
]
headBar.leftContent: [
ToolButton
{
icon.name: "go-previous"
onClicked: control.goBack()
},
ToolButton
{
id: goUpButton
visible: true
icon.name: "go-up"
onClicked: control.goUp()
},
ToolButton
{
icon.name: "go-next"
onClicked: control.goNext()
}
]
- footBar.visible: false
-
-
Component
{
id: selectionBarComponent
Maui.SelectionBar
{
anchors.fill: parent
onIconClicked: _selectionBarmenu.popup()
onExitClicked: clean()
Menu
{
id: _selectionBarmenu
MenuItem
{
text: qsTr("Copy...")
onTriggered:
{
if(control.selectionBar)
control.selectionBar.animate("#6fff80")
control.copy(selectedItems)
console.log(selectedItems)
_selectionBarmenu.close()
}
}
MenuItem
{
text: qsTr("Cut...")
onTriggered:
{
if(control.selectionBar)
control.selectionBar.animate("#fff44f")
control.cut(selectedItems)
_selectionBarmenu.close()
}
}
MenuItem
{
text: qsTr("Share")
onTriggered:
{
control.shareFiles(selectedPaths)
_selectionBarmenu.close()
}
}
MenuSeparator{}
MenuItem
{
text: qsTr("Remove...")
Kirigami.Theme.textColor: dangerColor
onTriggered:
{
dialogLoader.sourceComponent= removeDialogComponent
dialog.items = selectedItems
dialog.open()
_selectionBarmenu.close()
}
}
}
}
}
+ ObjectModel { id: tabsObjectModel }
+
ColumnLayout
{
anchors.fill: parent
visible: !holder.visible
- z: holder.z + 1
spacing: 0
- BrowserView
+ TabBar
{
- id: _browserView
- z: holder.z + 1
- Layout.topMargin: _browserView.viewType == Maui.FMList.ICON_VIEW ? contentMargins * 2 : 0
- Layout.margins: 0
- Layout.fillWidth: true
- Layout.fillHeight: true
- }
+ id: tabsBar
+ visible: _browserList.count > 1
+ Layout.fillWidth: true
+ Layout.preferredHeight: visible ? Maui.Style.rowHeight : 0
+ Kirigami.Theme.colorSet: Kirigami.Theme.View
+ Kirigami.Theme.inherit: false
+
+ currentIndex : _browserList.currentIndex
+ clip: true
+
+ ListModel { id: tabsListModel }
+
+ background: Rectangle
+ {
+ color: "transparent"
+ }
+
+ Repeater
+ {
+ id: _repeater
+ model: tabsListModel
+
+ TabButton
+ {
+ id: _tabButton
+ readonly property int minTabWidth: 150 * unit
+ implicitWidth: control.width / _repeater.count
+ implicitHeight: Maui.Style.rowHeight
+ checked: index === _browserList.currentIndex
+
+ onClicked: _browserList.currentIndex = index
+ background: Rectangle
+ {
+ color: checked ? Kirigami.Theme.focusColor : Kirigami.Theme.backgroundColor
+ opacity: checked ? 0.4 : 1
+
+ Kirigami.Separator
+ {
+ color: Qt.tint(Kirigami.Theme.textColor, Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.7))
+ z: tabsBar.z + 1
+ width : 1
+ // visible: tabsListModel.count > 1
+ anchors
+ {
+ bottom: parent.bottom
+ top: parent.top
+ right: parent.right
+ }
+ }
+ }
+
+ contentItem: RowLayout
+ {
+ spacing: 0
+
+ Label
+ {
+ text: tabsObjectModel.get(index).currentFMList.pathName
+ font.pointSize: fontSizes.default
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: space.small
+ Layout.alignment: Qt.AlignCenter
+ verticalAlignment: Qt.AlignVCenter
+ horizontalAlignment: Qt.AlignHCenter
+ color: Kirigami.Theme.textColor
+ wrapMode: Text.NoWrap
+ elide: Text.ElideRight
+ }
+
+ ToolButton
+ {
+ Layout.preferredHeight: iconSizes.medium
+ Layout.preferredWidth: iconSizes.medium
+ icon.height: iconSizes.medium
+ icon.width: iconSizes.width
+ Layout.margins: space.medium
+ Layout.alignment: Qt.AlignRight
+
+ icon.name: "dialog-close"
+
+ onClicked:
+ {
+ var removedIndex = index
+ tabsObjectModel.remove(removedIndex)
+ tabsListModel.remove(removedIndex)
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ Kirigami.Separator
+ {
+ visible: tabsBar.visible
+ color: Qt.tint(Kirigami.Theme.textColor, Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.7))
+ Layout.fillWidth: true
+ Layout.preferredHeight: 1
+ }
+
+ ListView
+ {
+ id: _browserList
+ Layout.topMargin: browserView.viewType == Maui.FMList.ICON_VIEW ? contentMargins * 2 : 0
+ Layout.margins: 0
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ z: holder.z + 1
+ orientation: ListView.Horizontal
+ model: tabsObjectModel
+ snapMode: ListView.SnapOneItem
+ spacing: 0
+ interactive: isMobile && tabsObjectModel.count > 1
+ highlightFollowsCurrentItem: true
+ highlightMoveDuration: 0
+ onMovementEnded: _browserList.currentIndex = indexAt(contentX, contentY)
+ }
Loader
{
id: selectionBarLoader
Layout.fillWidth: true
Layout.preferredHeight: control.selectionBar && control.selectionBar.visible ? control.selectionBar.barHeight: 0
Layout.leftMargin: contentMargins * (isMobile ? 3 : 2)
Layout.rightMargin: contentMargins * (isMobile ? 3 : 2)
Layout.bottomMargin: control.selectionBar && control.selectionBar.visible ? contentMargins*2 : 0
z: holder.z +1
}
ProgressBar
{
id: _progressBar
Layout.fillWidth: true
Layout.alignment: Qt.AlignBottom
Layout.preferredHeight: visible ? iconSizes.medium : 0
visible: value > 0
}
}
+ Component.onCompleted: openTab(Maui.FM.homePath())
+
onThumbnailsSizeChanged:
{
if(trackChanges && saveDirProps)
Maui.FM.setDirConf(currentPath+"/.directory", "MAUIFM", "IconSize", thumbnailsSize)
else
Maui.FM.saveSettings("IconSize", thumbnailsSize, "SETTINGS")
- if(_browserView.viewType == Maui.FMList.ICON_VIEW)
+ if(browserView.viewType == Maui.FMList.ICON_VIEW)
browser.adaptGrid()
}
+ function openTab(path)
+ {
+ var component = Qt.createComponent("private/BrowserView.qml");
+ if (component.status === Component.Ready)
+ {
+ var object = component.createObject(tabsObjectModel);
+ tabsObjectModel.append(object);
+ }
+
+ tabsListModel.append({
+ title: qsTr("Untitled"),
+ path: path,
+ })
+
+ _browserList.currentIndex = tabsObjectModel.count - 1
+
+ if(path && Maui.FM.fileExists(path))
+ {
+ setTabMetadata(path)
+ openFolder(path)
+ }
+ }
+
+ function setTabMetadata(filepath)
+ {
+ tabsListModel.setProperty(tabsBar.currentIndex, "path", filepath)
+ }
+
+
function shareFiles(urls)
{
if(urls.length <= 0)
return;
if(isAndroid)
Maui.Android.shareDialog(urls[0])
else
{
dialogLoader.sourceComponent= shareDialogComponent
dialog.show(urls)
}
}
function openItem(index)
{
var item = control.currentFMList.get(index)
- var path = item.path
+ var path = item.path
+
+ console.log("trying to open item<<", path)
switch(currentPathType)
{
case Maui.FMList.APPS_PATH:
if(item.path.endsWith("/"))
populate(path)
else
Maui.FM.runApplication(path)
break
case Maui.FMList.CLOUD_PATH:
if(item.mime === "inode/directory")
control.openFolder(path)
else
Maui.FM.openCloudItem(item)
break;
default:
if(selectionMode && !Maui.FM.isDir(item.path))
addToSelection(item, true)
else
{
if(item.mime === "inode/directory")
control.openFolder(path)
else if(Maui.FM.isApp(path))
control.launchApp(path)
else
{
if (isMobile)
previewer.show(path)
else
control.openFile(path)
}
}
}
}
function launchApp(path)
{
Maui.FM.runApplication(path, "")
}
function openFile(path)
{
Maui.FM.openUrl(path)
}
function openFolder(path)
{
populate(Maui.FM.fileDir(path))// make sure the path is a dir
}
function setPath(path)
{
- currentPath = path
+ control.currentPath = path
}
function populate(path)
{
if(!path.length)
return;
browser.currentIndex = 0
setPath(path)
if(currentPathType === Maui.FMList.PLACES_PATH)
{
if(trackChanges && saveDirProps)
{
var conf = Maui.FM.dirConf(path+"/.directory")
var iconsize = conf["iconsize"] || iconSizes.large
thumbnailsSize = parseInt(iconsize)
}else
{
thumbnailsSize = parseInt(Maui.FM.loadSettings("IconSize", "SETTINGS", thumbnailsSize))
}
}
- if(_browserView.viewType == Maui.FMList.ICON_VIEW)
+ if(browserView.viewType == Maui.FMList.ICON_VIEW)
browser.adaptGrid()
}
function goBack()
{
populate(control.currentFMList.previousPath)
browser.currentIndex = indexHistory.pop()
}
function goNext()
{
openFolder(control.currentFMList.posteriorPath)
}
function goUp()
{
openFolder(control.currentFMList.parentPath)
}
function refresh()
{
var pos = browser.contentY
browser.contentY = pos
}
function addToSelection(item, append)
{
selectionBarLoader.sourceComponent= selectionBarComponent
selectionBar.singleSelection = control.singleSelection
selectionBar.append(item)
}
function clean()
{
copyItems = []
cutItems = []
browserMenu.pasteFiles = 0
if(control.selectionBar && control.selectionBar.visible)
selectionBar.clear()
}
function copy(items)
{
copyItems = items
isCut = false
isCopy = true
}
function cut(items)
{
cutItems = items
isCut = true
isCopy = false
}
function paste()
{
if(isCopy)
currentFMList.copyInto(copyItems)
else if(isCut)
{
currentFMList.cutInto(cutItems)
clean()
}
}
function remove(items)
{
for(var i in items)
Maui.FM.removeFile(items[i].path)
}
function trash(items)
{
for(var i in items)
Maui.FM.moveToTrash(items[i].path)
}
function bookmarkFolder(paths)
{
newBookmark(paths)
}
function zoomIn()
{
control.thumbnailsSize = control.thumbnailsSize + 8
}
function zoomOut()
{
var newSize = control.thumbnailsSize - 8
if(newSize >= iconSizes.small)
control.thumbnailsSize = newSize
}
function groupBy()
{
var prop = ""
var criteria = ViewSection.FullString
switch(control.currentFMList.sortBy)
{
case Maui.FMList.LABEL:
prop = "label"
criteria = ViewSection.FirstCharacter
break;
case Maui.FMList.MIME:
prop = "mime"
break;
case Maui.FMList.SIZE:
prop = "size"
break;
case Maui.FMList.DATE:
prop = "date"
break;
case Maui.FMList.MODIFIED:
prop = "modified"
break;
}
- _browserView.viewType = Maui.FMList.LIST_VIEW
+ browserView.viewType = Maui.FMList.LIST_VIEW
if(!prop)
{
browser.section.property = ""
return
}
browser.section.property = prop
browser.section.criteria = criteria
}
}
diff --git a/src/controls/Holder.qml b/src/controls/Holder.qml
index de9ddea..93d7515 100644
--- a/src/controls/Holder.qml
+++ b/src/controls/Holder.qml
@@ -1,141 +1,131 @@
/*
* Copyright 2018 Camilo Higuita
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import org.kde.kirigami 2.7 as Kirigami
import "private"
Item
{
id: control
anchors.fill: parent
-
+ visible: false
+
property string emoji
property string message
property string title
property string body
property bool isMask : true
property bool isGif : false
property int emojiSize : iconSizes.large
property bool enabled: true
signal actionTriggered()
clip: true
focus: true
-
+
Component
{
id: imgComponent
Image
{
id: imageHolder
width: Math.min(parent.width, emojiSize)
height: width
sourceSize.width: width
sourceSize.height: height
source: emoji
asynchronous: true
horizontalAlignment: Qt.AlignHCenter
fillMode: Image.PreserveAspectFit
HueSaturation
{
anchors.fill: parent
source: parent
saturation: -1
lightness: 0.3
visible: isMask
}
}
}
Component
{
id: animComponent
AnimatedImage
{
id: animation;
source: emoji
}
}
MouseArea
{
id: _mouseArea
anchors.fill: parent
enabled: control.enabled
onClicked: actionTriggered()
hoverEnabled: true
}
- Item
+ Column
{
- anchors.centerIn: parent
- height: loader.height + textHolder.implicitHeight
- width: Math.min(500, control.width)
+ anchors.centerIn: parent
+
Loader
{
id: loader
height: control.emoji ? emojiSize : 0
- width: height
- sourceComponent: control.emoji ? (isGif ? animComponent : imgComponent) : undefined
- anchors
- {
- bottom: textHolder.top
- horizontalCenter: parent.horizontalCenter
- }
+ width: height
+ anchors.horizontalCenter: parent.horizontalCenter
+ sourceComponent: control.emoji ? (isGif ? animComponent : imgComponent) : undefined
}
Label
{
id: textHolder
- width: parent.width
+ width: Math.min(control.width * 0.7, implicitWidth)
opacity: 0.5
text: message ? qsTr(message) : ""+title+"
"+body+"
"
font.pointSize: fontSizes.default
padding: space.medium
font.bold: true
textFormat: Text.RichText
horizontalAlignment: Qt.AlignHCenter
elide: Text.ElideRight
color: _mouseArea.hovered ? Kirigami.Theme.highlightColor : Kirigami.Theme.textColor
- wrapMode: Text.Wrap
-
- anchors
- {
- top: loader.bottom
- horizontalCenter: parent.horizontalCenter
- }
+ wrapMode: Text.Wrap
}
}
}
diff --git a/src/controls/IconDelegate.qml b/src/controls/IconDelegate.qml
index f1e6776..9543244 100644
--- a/src/controls/IconDelegate.qml
+++ b/src/controls/IconDelegate.qml
@@ -1,345 +1,344 @@
/*
* Copyright 2018 Camilo Higuita
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.0
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import org.kde.kirigami 2.7 as Kirigami
import org.kde.mauikit 1.0 as Maui
import QtGraphicalEffects 1.0
import "private"
ItemDelegate
{
id: control
property bool isDetails : false
property bool showDetailsInfo: false
property int folderSize : iconSize
property int emblemSize: iconSizes.medium
property bool isHovered : hovered
property bool showLabel : true
property bool showEmblem : false
property bool showSelectionBackground : true
property bool showTooltip : false
property bool showThumbnails : false
property bool emblemAdded : false
property bool keepEmblemOverlay : false
property bool isCurrentListItem : ListView.isCurrentItem
property color labelColor : (isCurrentListItem || GridView.isCurrentItem || (keepEmblemOverlay && emblemAdded)) && !hovered && showSelectionBackground ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
property color hightlightedColor : GridView.isCurrentItem || hovered || (keepEmblemOverlay && emblemAdded) ? Kirigami.Theme.highlightColor : "transparent"
property string rightEmblem
property string leftEmblem : "list-add"
signal rightClicked()
signal emblemClicked(int index)
signal rightEmblemClicked(int index)
signal leftEmblemClicked(int index)
focus: true
clip: true
hoverEnabled: !isMobile
background: Rectangle
{
color: !isDetails? "transparent" : (isCurrentListItem || (hovered && isDetails) ? Kirigami.Theme.highlightColor :
index % 2 === 0 ? Qt.lighter( Kirigami.Theme.backgroundColor,1.2) : Kirigami.Theme.backgroundColor)
opacity: hovered ? 0.3 : 1
}
// Drag.active: _mouseArea.drag.active
// Drag.dragType: Drag.Automatic
// Drag.supportedActions: Qt.CopyAction
// Drag.mimeData:
// {
// "text/uri-list": model.path
// }
MouseArea
{
id: _mouseArea
anchors.fill: parent
acceptedButtons: Qt.RightButton
// drag.target: parent
onClicked:
{
if(!isMobile && mouse.button === Qt.RightButton)
rightClicked()
}
// onPressed: parent.grabToImage(function(result)
// {
// parent.Drag.imageSource = result.url
// })
}
Maui.Badge
{
id: leftEmblemIcon
iconName: leftEmblem
visible: (isHovered || keepEmblemOverlay) && showEmblem && leftEmblem
z: 999
anchors.top: parent.top
anchors.left: parent.left
onClicked: leftEmblemClicked(index)
// Component.onCompleted: leftEmblemIcon.item.isMask = false
size: iconSizes.small
Kirigami.Theme.backgroundColor: Kirigami.Theme.highlightColor
Kirigami.Theme.textColor: Kirigami.Theme.highlightedTextColor
}
Maui.Badge
{
id: rightEmblemIcon
iconName: rightEmblem
visible: (isHovered || keepEmblemOverlay) && showEmblem && rightEmblem
z: 999
size: iconSizes.medium
anchors.top: parent.top
anchors.right: parent.right
onClicked: rightEmblemClicked(index)
Kirigami.Theme.backgroundColor: Kirigami.Theme.highlightColor
}
Component
{
id: imgComponent
Item
{
anchors.fill: parent
Image
{
id: img
clip: true
anchors.centerIn: parent
source: model.thumbnail ? model.thumbnail : undefined
height: Math.min(folderSize, sourceSize.height)
width: isDetails ? folderSize : Math.min(control.width * 0.9, sourceSize.width)
// sourceSize.width: width
// sourceSize.height: height
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
fillMode: Image.PreserveAspectCrop
cache: false
asynchronous: true
layer.enabled: true
layer.effect: OpacityMask
{
maskSource: Item
{
width: img.width
height: img.height
Rectangle
{
anchors.centerIn: parent
width: img.width
height: img.height
radius: radiusV
}
}
}
}
Loader
{
anchors.centerIn: parent
sourceComponent: img.status === Image.Ready ? undefined : iconComponent
}
}
}
Component
{
id: iconComponent
Kirigami.Icon
{
source: model.icon
fallback: "qrc:/assets/application-x-zerosize.svg"
- isMask: folderSize <= iconSizes.medium
height: folderSize
- width: folderSize
+ width: height
}
}
Component
{
id: labelComponent
Item
{
anchors.fill: parent
Label
{
id: label
text: model.label
width: parent.width
height: parent.height
horizontalAlignment: isDetails? Qt.AlignLeft : Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
elide: Qt.ElideRight
wrapMode: Text.Wrap
font.pointSize: fontSizes.default
color: labelColor
Rectangle
{
visible: parent.visible && showSelectionBackground && !isDetails
anchors.fill: parent
z: -1
radius: radiusV
color: hightlightedColor
opacity: hovered ? 0.25 : 0.5
}
}
}
}
Component
{
id: detailsComponent
RowLayout
{
anchors.fill: parent
ColumnLayout
{
Layout.fillHeight: true
Layout.fillWidth: false
Layout.maximumWidth: 80
Layout.minimumWidth: 80
Layout.preferredWidth: 80
Layout.alignment: Qt.AlignRight
Label
{
Layout.alignment: Qt.AlignRight
Layout.fillWidth: true
Layout.fillHeight: true
horizontalAlignment: Qt.AlignRight
verticalAlignment: Qt.AlignBottom
elide: Qt.ElideRight
wrapMode: Text.Wrap
font.pointSize: fontSizes.small
color: labelColor
opacity: isCurrentListItem ? 1 : 0.5
text: model.mime === "inode/directory" ? (model.count ? model.count + qsTr(" items") : "") : Maui.FM.formatSize(model.size)
}
Label
{
Layout.alignment: Qt.AlignRight
Layout.fillWidth: true
Layout.fillHeight: true
text: Maui.FM.formatDate(model.modified, "MM/dd/yyyy")
horizontalAlignment: Qt.AlignRight
verticalAlignment: Qt.AlignTop
elide: Qt.ElideRight
wrapMode: Text.Wrap
font.pointSize: fontSizes.small
color: labelColor
opacity: isCurrentListItem ? 1 : 0.5
}
}
}
}
GridLayout
{
id: delegatelayout
anchors.fill: parent
rows: isDetails ? 1 : 2
columns: isDetails && showDetailsInfo ? 3 : (isDetails && !showDetailsInfo ? 2 : 1)
rowSpacing: space.tiny
columnSpacing: space.tiny
Item
{
Layout.fillHeight: true
Layout.fillWidth: true
Layout.maximumWidth: folderSize
Layout.row: 1
Layout.column: 1
Layout.alignment: Qt.AlignCenter
Layout.leftMargin: isDetails ? space.medium : 0
Loader
{
id: loader
anchors.centerIn: parent
sourceComponent: model.mime ? (model.mime.indexOf("image") > -1 && showThumbnails ? imgComponent :
iconComponent) : iconComponent
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered && showTooltip
ToolTip.text: model.tooltip ? model.tooltip : model.path
}
Loader
{
id: labelLoader
Layout.fillWidth: true
Layout.maximumHeight: (isDetails ? parent.height : fontSizes.default * 5)
Layout.minimumHeight: (isDetails ? parent.height : control.height - folderSize - space.tiny)
Layout.preferredHeight: (isDetails ? parent.height : control.height - folderSize - space.tiny)
Layout.row: isDetails ? 1 : 2
Layout.column: isDetails ? 2 : 1
Layout.leftMargin: isDetails ? space.medium : 0
sourceComponent: model.label && model.label.length && showLabel? labelComponent : undefined
}
Loader
{
id: detailsInfoLoader
sourceComponent: isDetails && showDetailsInfo ? detailsComponent : undefined
Layout.fillWidth: isDetails && showDetailsInfo
Layout.maximumHeight: ( isDetails && showDetailsInfo ? parent.height : fontSizes.default * 5)
Layout.minimumHeight: ( isDetails && showDetailsInfo ? parent.height : control.height - folderSize - space.tiny)
Layout.preferredHeight: ( isDetails && showDetailsInfo ? parent.height : control.height - folderSize - space.tiny)
Layout.maximumWidth: control.width * (isMobile ? 0.5 : 0.3)
Layout.row: isDetails && showDetailsInfo ? 1 : 2
Layout.column: isDetails && showDetailsInfo ? 3 : 0
Layout.rightMargin: space.medium
// Layout.leftMargin: isDetails ? space.medium : 0
}
}
}
diff --git a/src/controls/ListBrowser.qml b/src/controls/ListBrowser.qml
index c0c0ce5..3a1f6d5 100644
--- a/src/controls/ListBrowser.qml
+++ b/src/controls/ListBrowser.qml
@@ -1,159 +1,155 @@
/*
* Copyright 2018 Camilo Higuita
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import org.kde.mauikit 1.0 as Maui
ScrollView
{
id: control
property int itemSize : iconSizes.big
property bool showEmblem : true
property bool keepEmblemOverlay : false
property string rightEmblem
property string leftEmblem
property bool showDetailsInfo : false
property bool showPreviewThumbnails: true
property alias model : _listView.model
property alias delegate : _listView.delegate
property alias section : _listView.section
property alias contentY: _listView.contentY
property alias currentIndex : _listView.currentIndex
property alias currentItem : _listView.currentItem
property alias count : _listView.count
property alias cacheBuffer : _listView.cacheBuffer
property alias topMargin: _listView.topMargin
property alias bottomMargin: _listView.bottomMargin
property alias rightMargin: _listView.rightMargin
property alias leftMarging: _listView.leftMargin
property alias header : _listView.header
property alias listView: _listView
signal itemClicked(int index)
signal itemDoubleClicked(int index)
signal itemRightClicked(int index)
signal rightEmblemClicked(int index)
signal leftEmblemClicked(int index)
signal areaClicked(var mouse)
signal areaRightClicked()
padding: 0
spacing: 0
ListView
- {
- anchors.fill: parent
+ {
id: _listView
- // maximumFlickVelocity: 400
+ anchors.fill: parent
snapMode: ListView.SnapToItem
boundsBehavior: !isMobile? Flickable.StopAtBounds : Flickable.OvershootBounds
keyNavigationEnabled: true
- clip: true
- focus: true
- interactive: true
+ interactive: isMobile
highlightFollowsCurrentItem: true
highlightMoveDuration: 0
width: parent.width
- height: parent.height
-
+ height: parent.height
model: ListModel { id: listModel }
delegate: Maui.IconDelegate
{
id: delegate
isDetails: true
width: parent.width
height: itemSize + space.big
showDetailsInfo: control.showDetailsInfo
folderSize : itemSize
showTooltip: true
showEmblem: control.showEmblem
keepEmblemOverlay : control.keepEmblemOverlay
showThumbnails: showPreviewThumbnails
rightEmblem: control.rightEmblem
leftEmblem: control.leftEmblem
opacity: (model.name).startsWith(".") ? 0.5 : 1
Connections
{
target: delegate
onClicked:
{
control.currentIndex = index
control.itemClicked(index)
}
onDoubleClicked:
{
control.currentIndex = index
control.itemDoubleClicked(index)
}
onPressAndHold:
{
control.currentIndex = index
control.itemRightClicked(index)
}
onRightClicked:
{
control.currentIndex = index
control.itemRightClicked(index)
}
onRightEmblemClicked:
{
control.currentIndex = index
control.rightEmblemClicked(index)
}
onLeftEmblemClicked:
{
control.currentIndex = index
control.leftEmblemClicked(index)
}
}
}
MouseArea
{
anchors.fill: parent
z: -1
acceptedButtons: Qt.RightButton | Qt.LeftButton
onClicked: control.areaClicked(mouse)
onPressAndHold: control.areaRightClicked()
}
}
}
diff --git a/src/controls/TagsDialog.qml b/src/controls/TagsDialog.qml
index 87d7b74..689c734 100644
--- a/src/controls/TagsDialog.qml
+++ b/src/controls/TagsDialog.qml
@@ -1,196 +1,197 @@
import QtQuick 2.0
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import org.kde.mauikit 1.0 as Maui
import TagsModel 1.0
import TagsList 1.0
Maui.Dialog
{
property var urls : []
property alias taglist :_tagsList
property alias listView: _listView
property alias composerList: tagListComposer.list
signal tagsReady(var tags)
defaultButtons: true
maxHeight: unit * 500
+ page.padding: Maui.Style.space.medium
onAccepted: setTags()
onRejected: close()
headBar.plegable: false
headBar.leftContent: ToolButton
{
icon.name: "view-sort"
- text: qsTr("Sort by...")
+// text: qsTr("Sort by...")
onClicked: sortMenu.popup()
Menu
{
id: sortMenu
MenuItem
{
text: qsTr("Name")
checkable: true
checked: _tagsList.sortBy === TagsList.TAG
onTriggered: _tagsList.sortBy = TagsList.TAG
}
MenuItem
{
text: qsTr("Date")
checkable: true
checked: _tagsList.sortBy === TagsList.ADD_DATE
onTriggered: _tagsList.sortBy = TagsList.ADD_DATE
}
}
}
headBar.middleContent: Maui.TextField
{
id: tagText
- width: headBar.middleLayout.width * 0.9
+ Layout.fillWidth: true
placeholderText: qsTr("New tags...")
onAccepted:
{
var tags = tagText.text.split(",")
for(var i in tags)
{
var myTag = tags[i].trim()
_tagsList.insert(myTag)
tagListComposer.list.append(myTag)
}
clear()
}
}
headBar.rightContent: ToolButton
{
icon.name: "view-refresh"
// text: qsTr("Refresh...")
onClicked: taglist.refresh()
}
ColumnLayout
{
anchors.fill: parent
Item
{
Layout.fillHeight: true
Layout.fillWidth: true
ListView
{
id: _listView
clip: true
anchors.fill: parent
signal tagClicked(int index)
focus: true
interactive: true
highlightFollowsCurrentItem: true
highlightMoveDuration: 0
TagsModel
{
id: _tagsModel
list: _tagsList
}
TagsList
{
id: _tagsList
}
Maui.Holder
{
id: holder
emoji: "qrc:/img/assets/Electricity.png"
visible: _listView.count === 0
isMask: false
title : "No tags!"
body: "Start tagging your pics"
emojiSize: iconSizes.huge
}
model: _tagsModel
delegate: Maui.ListDelegate
{
id: delegate
label: tag
radius: radiusV
Connections
{
target: delegate
onClicked:
{
_listView.currentIndex = index
tagListComposer.list.append(_tagsList.get(index).tag)
}
}
}
}
}
Maui.TagList
{
id: tagListComposer
Layout.fillWidth: true
Layout.leftMargin: contentMargins
Layout.rightMargin: contentMargins
height: 64
width: parent.width
onTagRemoved: list.remove(index)
placeholderText: ""
}
}
function setTags()
{
var tags = []
for(var i = 0; i < tagListComposer.count; i++)
tags.push(tagListComposer.list.get(i).tag)
tagsReady(tags)
close()
}
// function show(urls)
// {
// control.urls = urls
// tagListComposer.list.urls = picUrls
//
// open()
// }
//
//
// function addTagsToPic(urls, tags)
// {
// if(tags.length < 1)
// return
//
// for(var j in urls)
// {
// var url = urls[j]
//
// if(!dba.checkExistance("images", "url", url))
// if(!dba.addPic(url))
// return
//
// for(var i in tags)
// if(PIX.addTagToPic(tags[i], url))
// picTagged(tags[i], url)
//
// }
// close()
// }
}
diff --git a/src/controls/TextField.qml b/src/controls/TextField.qml
index e366c58..b703a2c 100644
--- a/src/controls/TextField.qml
+++ b/src/controls/TextField.qml
@@ -1,150 +1,149 @@
/*
* Copyright 2018 Camilo Higuita
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.9
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.1
import org.kde.kirigami 2.2 as Kirigami
import QtQuick.Controls.impl 2.3
import QtQuick.Controls.Material.impl 2.3
import org.kde.mauikit 1.0 as Maui
import "private"
TextField
{
id: control
property alias menu : entryMenu
signal cleared()
signal goBackTriggered();
signal goFowardTriggered();
// height: implicitHeight
// width: implicitWidth
z: 1
// topPadding: space.tiny
bottomPadding: space.tiny
rightPadding: clearButton.width + space.small
selectByMouse: !isMobile
persistentSelection: true
focus: true
- wrapMode: TextInput.WordWrap
-
+ wrapMode: TextInput.WordWrap
onPressAndHold: !isMobile ? entryMenu.popup() : undefined
onPressed:
{
if(!isMobile && event.button === Qt.RightButton)
entryMenu.popup()
}
Keys.onBackPressed:
{
goBackTriggered();
event.accepted = true
}
Shortcut
{
sequence: "Forward"
onActivated: goFowardTriggered();
}
Shortcut
{
sequence: StandardKey.Forward
onActivated: goFowardTriggered();
}
Shortcut
{
sequence: StandardKey.Back
onActivated: goBackTriggered();
}
ToolButton
{
id: clearButton
visible: control.text.length
anchors.top: control.top
anchors.right: control.right
anchors.rightMargin: space.small
anchors.verticalCenter: parent.verticalCenter
icon.name: "edit-clear"
icon.color: control.color
onClicked:
{
control.clear()
cleared()
}
}
Menu
{
id: entryMenu
z: control.z +1
MenuItem
{
text: qsTr("Copy")
onTriggered: control.copy()
enabled: control.selectedText.length
}
MenuItem
{
text: qsTr("Cut")
onTriggered: control.cut()
enabled: control.selectedText.length
}
MenuItem
{
text: qsTr("Paste")
onTriggered:
{
var text = control.paste()
control.insert(control.cursorPosition, text)
}
}
MenuItem
{
text: qsTr("Select all")
onTriggered: control.selectAll()
enabled: control.text.length
}
MenuItem
{
text: qsTr("Undo")
onTriggered: control.undo()
enabled: control.canUndo
}
MenuItem
{
text: qsTr("Redo")
onTriggered: control.redo()
enabled: control.canRedo
}
}
}
diff --git a/src/controls/private/BrowserMenu.qml b/src/controls/private/BrowserMenu.qml
index 4e61959..27dff94 100644
--- a/src/controls/private/BrowserMenu.qml
+++ b/src/controls/private/BrowserMenu.qml
@@ -1,68 +1,68 @@
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import org.kde.mauikit 1.0 as Maui
import org.kde.kirigami 2.6 as Kirigami
Menu
{
property int pasteFiles : 0
// popup.z : 999
/* Maui.MenuItem
* {
* che
* ckable: true
* checked: saveDirProps
* text: qsTr("Per dir props")
* onTriggered: saveDirProps = !saveDirProps
}*/
// property list actions: t_actions
MenuItem
{
action: _previewAction
}
MenuItem
{
action: _hiddenAction
}
MenuItem
{
action: _bookmarkAction
}
MenuItem
{
action: _newFolderAction
}
MenuItem
{
action: _newDocumentAction
}
MenuItem
{
action: _pasteAction
- }
+ }
function show()
{
if(currentPathType === Maui.FMList.PLACES_PATH || currentPathType === Maui.FMList.TAGS_PATH || currentPathType === Maui.FMList.CLOUD_PATH)
{
if(isCopy)
pasteFiles = copyItems.length
else if(isCut)
pasteFiles = cutItems.length
popup()
}
}
}
diff --git a/src/controls/private/BrowserView.qml b/src/controls/private/BrowserView.qml
index 5eb3e1a..db19143 100644
--- a/src/controls/private/BrowserView.qml
+++ b/src/controls/private/BrowserView.qml
@@ -1,299 +1,290 @@
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import org.kde.kirigami 2.7 as Kirigami
import org.kde.mauikit 1.0 as Maui
Maui.Page
{
id: control
+ property string path
property Maui.FMList currentFMList : null
property alias currentView : viewLoader.item
- property int viewType : Maui.FMList.LIST_VIEW
+ property int viewType : Maui.FM.loadSettings("VIEW_TYPE", "BROWSER", Maui.FMList.LIST_VIEW)
+
+ onViewTypeChanged: Maui.FM.saveSettings("VIEW_TYPE", viewType, "BROWSER")
+
+ height: _browserList.height
+ width: _browserList.width
+
function setCurrentFMList()
{
console.log("SETTING CURRENT FM LIST")
control.currentFMList = currentView.currentFMList
}
Loader
{
id: viewLoader
anchors.fill: parent
sourceComponent: switch(control.viewType)
{
case Maui.FMList.ICON_VIEW: return gridViewBrowser
case Maui.FMList.LIST_VIEW: return listViewBrowser
case Maui.FMList.MILLERS_VIEW: return millerViewBrowser
}
onLoaded: setCurrentFMList()
}
- Component
+ Maui.FMList
{
- id: listViewBrowser
+ id: _commonFMList
+ preview: true
+ path: control.path
+ foldersFirst: true
+ onSortByChanged: if(group) groupBy()
+ onContentReadyChanged: console.log("CONTENT READY?", contentReady)
+ onWarning:
+ {
+ notify("dialog-information", "An error happened", message)
+ }
+ onProgress:
+ {
+ if(percent === 100)
+ _progressBar.value = 0
+ else
+ _progressBar.value = percent/100
+ }
+ }
+
+ Component
+ {
+ id: listViewBrowser
Maui.ListBrowser
{
- property alias currentFMList : _listViewFMList
- showPreviewThumbnails: modelList.preview
+ property alias currentFMList : _browserModel.list
+ showPreviewThumbnails: _listViewFMList.preview
keepEmblemOverlay: selectionMode
rightEmblem: isMobile ? "document-share" : ""
leftEmblem: "list-add"
- showDetailsInfo: true
-
- Maui.FMList
- {
- id: _listViewFMList
- preview: true
- path: currentPath
- foldersFirst: true
- onSortByChanged: if(group) groupBy()
- onContentReadyChanged: console.log("CONTENT READY?", contentReady)
- onWarning:
- {
- notify("dialog-information", "An error happened", message)
- }
-
- onProgress:
- {
- if(percent === 100)
- _progressBar.value = 0
- else
- _progressBar.value = percent/100
- }
- }
+ showDetailsInfo: true
model: Maui.BaseModel
{
id: _browserModel
- list: _listViewFMList
+ list: _commonFMList
}
section.delegate: Maui.LabelDelegate
{
id: delegate
label: section
labelTxt.font.pointSize: fontSizes.big
isSection: true
boldLabel: true
height: toolBarHeightAlt
}
}
}
Component
{
id: gridViewBrowser
Maui.GridBrowser
{
- property alias currentFMList : _gridViewFMList
+ property alias currentFMList : _browserModel.list
itemSize : thumbnailsSize + fontSizes.default
keepEmblemOverlay: selectionMode
- showPreviewThumbnails: modelList.preview
+ showPreviewThumbnails: _gridViewFMList.preview
rightEmblem: isMobile ? "document-share" : ""
- leftEmblem: "list-add"
-
- Maui.FMList
- {
- id: _gridViewFMList
- preview: true
- path: currentPath
- foldersFirst: true
- onSortByChanged: if(group) groupBy()
- onContentReadyChanged: console.log("CONTENT READY?", contentReady)
- onWarning:
- {
- notify("dialog-information", "An error happened", message)
- }
- onProgress:
- {
- if(percent === 100)
- _progressBar.value = 0
- else
- _progressBar.value = percent/100
- }
- }
+ leftEmblem: "list-add"
model: Maui.BaseModel
{
id: _browserModel
- list: _gridViewFMList
+ list: _commonFMList
}
}
}
Component
{
id: millerViewBrowser
Item
{
id: _millerControl
property Maui.FMList currentFMList
property int currentIndex
signal itemClicked(int index)
signal itemDoubleClicked(int index)
signal itemRightClicked(int index)
signal rightEmblemClicked(int index)
signal leftEmblemClicked(int index)
signal areaClicked(var mouse)
signal areaRightClicked()
ListView
{
id: _millerColumns
anchors.fill: parent
+ boundsBehavior: !isMobile? Flickable.StopAtBounds : Flickable.OvershootBounds
+
+ keyNavigationEnabled: true
+ interactive: Kirigami.Settings.isMobile
+ highlightFollowsCurrentItem: true
+
orientation: ListView.Horizontal
snapMode: ListView.SnapToItem
+ ScrollBar.horizontal: ScrollBar { }
+
onCurrentItemChanged:
{
_millerControl.currentFMList = currentItem.currentFMList
control.setCurrentFMList()
}
- highlightFollowsCurrentItem: true
Maui.PathList
{
id: _millerList
- path: currentPath
+ path: control.path
}
model: Maui.BaseModel
{
id: _millerModel
list: _millerList
}
delegate: ItemDelegate
{
property alias currentFMList : _millersFMList
property int _index : index
width: Math.min(Kirigami.Units.gridUnit * 22, control.width)
height: parent.height
background: Rectangle
{
color: "transparent"
}
- ListView.onAdd: _millerColumns.positionViewAtEnd()
+ ListView.onAdd: _millerColumns.currentIndex = _millerColumns.count-1
+
Kirigami.Separator
{
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 1
z: 999
}
Maui.FMList
{
id: _millersFMList
- preview: modelList.preview
+ preview: true
path: model.path
- foldersFirst: modelList.foldersFirst
+ foldersFirst: true
onWarning:
{
notify("dialog-information", "An error happened", message)
}
onProgress:
{
if(percent === 100)
_progressBar.value = 0
else
_progressBar.value = percent/100
}
}
Maui.ListBrowser
{
id: _millerListView
anchors.fill: parent
- showPreviewThumbnails: modelList.preview
+ showPreviewThumbnails: _millersFMList.preview
keepEmblemOverlay: selectionMode
rightEmblem: isMobile ? "document-share" : ""
leftEmblem: "list-add"
showDetailsInfo: true
currentIndex : _millerControl.currentIndex
onItemClicked:
{
_millerColumns.currentIndex = _index
- _millerControl.itemClicked(index)
-
- console.log(" ITEM CLICKED ", _index, index)
+ _millerControl.itemClicked(index)
}
onItemDoubleClicked:
{
_millerColumns.currentIndex = _index
_millerControl.itemDoubleClicked(index)
}
onItemRightClicked:
{
_millerColumns.currentIndex = _index
_millerControl.itemRightClicked(index)
}
onRightEmblemClicked:
{
_millerColumns.currentIndex = _index
_millerControl.rightEmblemClicked(index)
}
onLeftEmblemClicked:
{
_millerColumns.currentIndex = _index
_millerControl.leftEmblemClicked(index)
}
onAreaClicked:
{
_millerColumns.currentIndex = _index
_millerControl.areaClicked(mouse)
}
onAreaRightClicked:
{
_millerColumns.currentIndex = _index
_millerControl.areaRightClicked()
}
model: Maui.BaseModel
{
list: _millersFMList
}
section.delegate: Maui.LabelDelegate
{
id: delegate
label: section
labelTxt.font.pointSize: fontSizes.big
isSection: true
boldLabel: true
height: toolBarHeightAlt
}
}
}
}
}
}
}
diff --git a/src/controls/private/FileMenu.qml b/src/controls/private/FileMenu.qml
index 753f773..557d97d 100644
--- a/src/controls/private/FileMenu.qml
+++ b/src/controls/private/FileMenu.qml
@@ -1,151 +1,159 @@
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import org.kde.mauikit 1.0 as Maui
import org.kde.kirigami 2.2 as Kirigami
Menu
{
id: control
implicitWidth: colorBar.implicitWidth + space.big
property var item : ({})
property int index : -1
property bool isDir : false
signal bookmarkClicked(var item)
signal removeClicked(var item)
signal shareClicked(var item)
signal copyClicked(var item)
signal cutClicked(var item)
signal renameClicked(var item)
signal tagsClicked(var item)
MenuItem
{
text: qsTr("Select")
onTriggered:
{
addToSelection(currentFMList.get(index))
}
}
+ MenuSeparator{}
+
+ MenuItem
+ {
+ visible: isDir
+ text: qsTr("Open in tab")
+ onTriggered: openTab(item.path)
+ }
MenuSeparator{}
MenuItem
{
text: qsTr("Copy...")
onTriggered:
{
copyClicked(control.item)
close()
}
}
MenuItem
{
text: qsTr("Cut...")
onTriggered:
{
cutClicked(control.item)
close()
}
}
MenuItem
{
text: qsTr("Rename...")
onTriggered:
{
renameClicked(control.item)
close()
}
}
MenuSeparator{}
MenuItem
{
text: qsTr("Bookmark")
enabled: isDir
onTriggered:
{
bookmarkClicked(control.item)
close()
}
}
MenuItem
{
text: qsTr("Tags...")
onTriggered:
{
tagsClicked(control.item)
close()
}
}
MenuItem
{
text: qsTr("Share...")
onTriggered:
{
shareClicked(control.item)
close()
}
}
MenuItem
{
text: qsTr("Preview...")
onTriggered:
{
previewer.show(control.item.path)
close()
}
}
MenuSeparator{}
MenuItem
{
text: qsTr("Remove...")
Kirigami.Theme.textColor: dangerColor
onTriggered:
{
removeClicked(control.item)
close()
}
}
MenuSeparator{ visible: colorBar.visible }
MenuItem
{
width: parent.width
height: visible ? iconSize + space.big : 0
visible: isDir
Maui.ColorsBar
{
id: colorBar
visible: parent.visible
anchors.centerIn: parent
size: iconSize
onColorPicked: currentFMList.setDirIcon(index, color)
}
}
function show(index)
{
control.item = currentFMList.get(index)
if(item)
{
control.index = index
isDir = Maui.FM.isDir(item.path)
popup()
}
}
}
diff --git a/src/fm/fm.h b/src/fm/fm.h
index 9f569b9..17cafe2 100644
--- a/src/fm/fm.h
+++ b/src/fm/fm.h
@@ -1,156 +1,156 @@
#ifndef FM_H
#define FM_H
#include
#include
#include
#include
#include
#include
#include "fmdb.h"
#include "fmh.h"
#ifndef STATIC_MAUIKIT
#include "mauikit_export.h"
#endif
#if defined(Q_OS_ANDROID)
#include "mauiandroid.h"
#endif
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
class KCoreDirLister;
#endif
class Syncing;
class Tagging;
#ifdef STATIC_MAUIKIT
class FM : public FMDB
#else
class MAUIKIT_EXPORT FM : public FMDB
#endif
{
Q_OBJECT
public:
// static FM *getInstance();
Syncing *sync;
FM(QObject *parent = nullptr);
~FM();
FMH::MODEL_LIST getTags(const int &limit = 5);
FMH::MODEL_LIST getTagContent(const QString &tag);
// FMH::MODEL_LIST getBookmarks();
/** Syncing **/
bool getCloudServerContent(const QString &server, const QStringList &filters= QStringList(), const int &depth = 0);
FMH::MODEL_LIST getCloudAccounts();
Q_INVOKABLE void createCloudDir(const QString &path, const QString &name);
void getTrashContent();
/*** START STATIC METHODS ***/
static FMH::MODEL_LIST search(const QString &query, const QUrl &path, const bool &hidden = false, const bool &onlyDirs = false, const QStringList &filters = QStringList());
// static FMH::MODEL_LIST getDevices();
static FMH::MODEL_LIST getDefaultPaths();
static FMH::MODEL_LIST getAppsPath();
static FMH::MODEL_LIST packItems(const QStringList &items, const QString &type);
void getPathContent(const QUrl &path, const bool &hidden = false, const bool &onlyDirs = false, const QStringList &filters = QStringList(), const QDirIterator::IteratorFlags &iteratorFlags = QDirIterator::NoIteratorFlags);
// static FMH::MODEL_LIST getPathContent(const QString &path, const bool &hidden = false, const bool &onlyDirs = false, const QStringList &filters = QStringList(), const QDirIterator::IteratorFlags &iteratorFlags = QDirIterator::NoIteratorFlags);
static FMH::MODEL_LIST getAppsContent(const QString &path);
static bool copyPath(QUrl sourceDir, QUrl destinationDir, bool overWriteDirectory);
static bool removeDir(const QUrl &path);
static QString resolveUserCloudCachePath(const QString &server, const QString &user);
QString resolveLocalCloudPath(const QString &path);
/**
* only keeping this two for legacy. shoudl be removed soon
* and instead use FMH::toMap, FMH::toModel, FMH::filterModel
**/
static QVariantMap toMap(const FMH::MODEL &model);
- static FMH::MODEL toModel(const QVariantMap &map);
+ static FMH::MODEL toModel(const QVariantMap &map);
/*** END STATIC METHODS ***/
private:
Tagging *tag;
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
KCoreDirLister *dirLister;
#endif
// static FM* instance;
QVariantList get(const QString &queryTxt);
signals:
void cloudAccountInserted(QString user);
void cloudAccountRemoved(QString user);
void cloudServerContentReady(FMH::MODEL_LIST list, const QString &url);
void cloudItemReady(FMH::MODEL item, QString path); //when a item is downloaded and ready
void trashContentReady(FMH::MODEL_LIST list);
void pathContentReady(FMH::PATH_CONTENT list);
void pathContentChanged(QUrl path);
void warningMessage(QString message);
void loadProgress(int percent);
void dirCreated(FMH::MODEL dir);
void newItem(FMH::MODEL item, QString path); // when a new item is created
public slots:
QVariantList getCloudAccountsList();
bool addCloudAccount(const QString &server, const QString &user, const QString &password);
bool removeCloudAccount(const QString &server, const QString &user);
void openCloudItem(const QVariantMap &item);
void getCloudItem(const QVariantMap &item);
static QString formatSize(const int &size);
static QString formatDate(const QString &dateStr, const QString &format = QString("dd/MM/yyyy"), const QString &initFormat = QString());
static QString homePath();
static QUrl parentDir(const QUrl &path);
static QVariantMap getDirInfo(const QUrl &path, const QString &type);
static QVariantMap getFileInfo(const QUrl &path);
static bool isDefaultPath(const QString &path);
static bool isDir(const QUrl &path);
static bool isApp(const QString &path);
static bool isCloud(const QUrl &path);
static bool fileExists(const QUrl &path);
/**
* if the url is a file path then it returns its directory
* and if it is a directory returns the same path
* */
static QString fileDir(const QUrl &path);
/* SETTINGS */
static void saveSettings(const QString &key, const QVariant &value, const QString &group);
static QVariant loadSettings(const QString &key, const QString &group, const QVariant &defaultValue);
static QVariantMap dirConf(const QUrl &path);
static void setDirConf(const QUrl &path, const QString &group, const QString &key, const QVariant &value);
/* ACTIONS */
bool copy(const QVariantList &data, const QString &where);
bool cut(const QVariantList &data, const QString &where);
static bool removeFile(const QUrl &path);
void moveToTrash(const QUrl &path);
static void emptyTrash();
static bool rename(const QUrl &path, const QString &name);
static bool createDir(const QUrl &path, const QString &name);
static bool createFile(const QUrl &path, const QString &name);
static bool openUrl(const QString &url);
static void openLocation(const QStringList &urls);
static void runApplication(const QString &exec);
};
#endif // FM_H
diff --git a/src/fm/fmlist.cpp b/src/fm/fmlist.cpp
index 9daf669..720b795 100644
--- a/src/fm/fmlist.cpp
+++ b/src/fm/fmlist.cpp
@@ -1,877 +1,884 @@
/*
*
* Copyright (C) 2018 camilo higuita
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "fmlist.h"
#include "fm.h"
#include "utils.h"
#include
#include
#include
#include
#include
#include
#include
FMList::FMList(QObject *parent) :
MauiList(parent),
fm(new FM(this)),
watcher(new QFileSystemWatcher(this))
{
connect(this->fm, &FM::cloudServerContentReady, [&](const FMH::MODEL_LIST &list, const QString &url)
{
if(this->path == url)
{
this->pre();
this->list = list;
this->pathEmpty = this->list.isEmpty();
emit this->pathEmptyChanged();
+ this->count = this->list.size();
+ emit this->countChanged();
this->pos();
this->setContentReady(true);
}
});
connect(this->fm, &FM::trashContentReady, [&](const FMH::MODEL_LIST &list)
{
if(this->path == "trash://")
{
this->pre();
this->list = list;
this->pathEmpty = this->list.isEmpty();
emit this->pathEmptyChanged();
+ this->count = this->list.size();
+ emit this->countChanged();
this->pos();
this->setContentReady(true);
}
});
connect(this->fm, &FM::pathContentReady, [&](const FMH::PATH_CONTENT &res)
- {
- qDebug()<< "PATHCN ONTEN READY" << res.path << this->path << res.content;
-
+ {
// if(this->pathType != FMList::PATHTYPE::PLACES_PATH)
// return;
if(res.path != this->path)
- return;
-
+ return;
emit this->preListChanged();
this->list = res.content;
-
this->pathEmpty = this->list.isEmpty() /*&& FM::fileExists(this->path)*/;
emit this->pathEmptyChanged();
- this->sortList();
+ this->sortList();
+ this->count = this->list.size();
+ emit this->countChanged();
emit this->postListChanged();
this->setContentReady(true);
});
connect(this->fm, &FM::warningMessage, [&](const QString &message)
{
emit this->warning(message);
});
connect(this->fm, &FM::loadProgress, [&](const int &percent)
{
emit this->progress(percent);
});
// with kio based on android it watches the directory itself, so better relay on that
#ifdef Q_OS_ANDROID
connect(this->watcher, &QFileSystemWatcher::directoryChanged, [&](const QString &path)
{
qDebug()<< "FOLDER PATH CHANGED" << path;
this->reset();
});
#else
connect(this->fm, &FM::pathContentChanged, [&](const QUrl &path)
{
qDebug()<< "FOLDER PATH CHANGED" << path;
if(path.toString() != this->path)
return;
this->sortList();
});
#endif
connect(this->fm, &FM::newItem, [&] (const FMH::MODEL &item, const QString &url)
{
if(this->path == url)
{
emit this->preItemAppended();
this->list << item;
this->pathEmpty = this->list.isEmpty();
emit this->pathEmptyChanged();
emit this->postListChanged();
}
});
connect(this, &FMList::pathChanged, this, &FMList::reset);
// connect(this, &FMList::hiddenChanged, this, &FMList::setList);
// connect(this, &FMList::onlyDirsChanged, this, &FMList::setList);
// connect(this, &FMList::filtersChanged, this, &FMList::setList);
const auto value = UTIL::loadSettings("SaveDirProps", "SETTINGS", this->saveDirProps).toBool();
this->setSaveDirProps(value);
}
FMList::~FMList()
{}
void FMList::pre()
{
emit this->preListChanged();
// this->setContentReady(false);
}
void FMList::pos()
{
// this->setContentReady(true);
emit this->postListChanged();
}
void FMList::watchPath(const QString& path, const bool& clear)
{
#ifdef Q_OS_ANDROID
if(!this->watcher->directories().isEmpty() && clear)
this->watcher->removePaths(this->watcher->directories());
if(path.isEmpty() || !FMH::fileExists(path))
return;
this->watcher->addPath(QString(path).replace("file://", ""));
qDebug()<< "WATCHING PATHS" << this->watcher->directories();
#else
Q_UNUSED(path)
Q_UNUSED(clear)
#endif
}
void FMList::setList()
{
this->setContentReady(true);
switch(this->pathType)
{
case FMList::PATHTYPE::FISH_PATH:
case FMList::PATHTYPE::MTP_PATH:
case FMList::PATHTYPE::DRIVES_PATH:
case FMList::PATHTYPE::REMOTE_PATH:
case FMList::PATHTYPE::PLACES_PATH:
this->list.clear();
this->setContentReady(false);
this->fm->getPathContent(this->path, this->hidden, this->onlyDirs, this->filters);
return; //ASYNC
case FMList::PATHTYPE::TRASH_PATH:
this->list.clear();
this->setContentReady(false);
this->fm->getTrashContent();
break;//ASYNC
case FMList::PATHTYPE::SEARCH_PATH:
this->list.clear();
this->setContentReady(false);
this->search(QString(this->path).right(this->path.length()- 1 - this->path.lastIndexOf("/")), this->searchPath, this->hidden, this->onlyDirs, this->filters);
return; //ASYNC
case FMList::PATHTYPE::APPS_PATH:
this->list = FM::getAppsContent(this->path);
break;
case FMList::PATHTYPE::TAGS_PATH:
this->list = this->fm->getTagContent(QString(this->path).right(this->path.length()- 1 - this->path.lastIndexOf("/")));
break;
case FMList::PATHTYPE::CLOUD_PATH:
this->list.clear();
if(this->fm->getCloudServerContent(this->path, this->filters, this->cloudDepth))
{
this->setContentReady(false);
return;
}else break;
}
this->pathEmpty = this->list.isEmpty() && FM::fileExists(this->path);
emit this->pathEmptyChanged();
this->sortList();
}
void FMList::reset()
{
this->pre();
switch(this->pathType)
{
case FMList::PATHTYPE::APPS_PATH:
this->hidden = false;
this->preview = false;
break;
case FMList::PATHTYPE::CLOUD_PATH:
case FMList::PATHTYPE::SEARCH_PATH:
case FMList::PATHTYPE::TAGS_PATH:
this->hidden = false;
this->preview = true;
break;
case FMList::PATHTYPE::PLACES_PATH:
{
if(this->saveDirProps)
{
auto conf = FMH::dirConf(this->path+"/.directory");
this->hidden = conf[FMH::MODEL_NAME[FMH::MODEL_KEY::HIDDEN]].toBool();
this->preview = conf[FMH::MODEL_NAME[FMH::MODEL_KEY::SHOWTHUMBNAIL]].toBool();
this->foldersFirst = conf[FMH::MODEL_NAME[FMH::MODEL_KEY::FOLDERSFIRST]].toBool();
}else
{
this->hidden = UTIL::loadSettings("HiddenFilesShown", "SETTINGS", this->hidden).toBool();
this->preview = UTIL::loadSettings("ShowThumbnail", "SETTINGS", this->preview).toBool();
this->foldersFirst = UTIL::loadSettings("FoldersFirst", "SETTINGS", this->foldersFirst).toBool();
}
break;
}
default: break;
}
if(this->saveDirProps)
{
auto conf = FMH::dirConf(this->path+"/.directory");
this->sort = static_cast(conf[FMH::MODEL_NAME[FMH::MODEL_KEY::SORTBY]].toInt());
}else
{
this->sort = static_cast(UTIL::loadSettings("SortBy", "SETTINGS", this->sort).toInt());
}
emit this->sortByChanged();
emit this->hiddenChanged();
emit this->previewChanged();
qDebug()<< "RESETING PATH CONTENTE" << this->path;
this->setList();
this->pos();
}
FMH::MODEL_LIST FMList::items() const
{
return this->list;
}
FMList::SORTBY FMList::getSortBy() const
{
return this->sort;
}
void FMList::setSortBy(const FMList::SORTBY &key)
{
if(this->sort == key)
return;
this->pre();
this->sort = key;
this->sortList();
if(this->pathType == FMList::PATHTYPE::PLACES_PATH && this->trackChanges && this->saveDirProps)
FMH::setDirConf(this->path+"/.directory", "MAUIFM", "SortBy", this->sort);
else
UTIL::saveSettings("SortBy", this->sort, "SETTINGS");
emit this->sortByChanged();
this->pos();
}
void FMList::sortList()
{
FMH::MODEL_KEY key = static_cast(this->sort);
auto index = 0;
if(this->foldersFirst)
{
qSort(this->list.begin(), this->list.end(), [](const FMH::MODEL& e1, const FMH::MODEL& e2) -> bool
{
Q_UNUSED(e2)
const auto key = FMH::MODEL_KEY::MIME;
if(e1[key] == "inode/directory")
return true;
return false;
});
for(auto item : this->list)
if(item[FMH::MODEL_KEY::MIME] == "inode/directory")
index++;
else break;
qSort(this->list.begin(),this->list.begin() + index, [key](const FMH::MODEL& e1, const FMH::MODEL& e2) -> bool
{
auto role = key;
switch(role)
{
case FMH::MODEL_KEY::SIZE:
{
if(e1[role].toDouble() > e2[role].toDouble())
return true;
break;
}
case FMH::MODEL_KEY::MODIFIED:
case FMH::MODEL_KEY::DATE:
{
auto currentTime = QDateTime::currentDateTime();
auto date1 = QDateTime::fromString(e1[role], Qt::TextDate);
auto date2 = QDateTime::fromString(e2[role], Qt::TextDate);
if(date1.secsTo(currentTime) < date2.secsTo(currentTime))
return true;
break;
}
case FMH::MODEL_KEY::LABEL:
{
const auto str1 = QString(e1[role]).toLower();
const auto str2 = QString(e2[role]).toLower();
if(str1 < str2)
return true;
break;
}
default:
if(e1[role] < e2[role])
return true;
}
return false;
});
}
qSort(this->list.begin() + index, this->list.end(), [key](const FMH::MODEL& e1, const FMH::MODEL& e2) -> bool
{
auto role = key;
switch(role)
{
case FMH::MODEL_KEY::MIME:
if(e1[role] == "inode/directory")
return true;
break;
case FMH::MODEL_KEY::SIZE:
{
if(e1[role].toDouble() > e2[role].toDouble())
return true;
break;
}
case FMH::MODEL_KEY::MODIFIED:
case FMH::MODEL_KEY::DATE:
{
auto currentTime = QDateTime::currentDateTime();
auto date1 = QDateTime::fromString(e1[role], Qt::TextDate);
auto date2 = QDateTime::fromString(e2[role], Qt::TextDate);
if(date1.secsTo(currentTime) < date2.secsTo(currentTime))
return true;
break;
}
case FMH::MODEL_KEY::LABEL:
{
const auto str1 = QString(e1[role]).toLower();
const auto str2 = QString(e2[role]).toLower();
if(str1 < str2)
return true;
break;
}
default:
if(e1[role] < e2[role])
return true;
}
return false;
});
}
QString FMList::getPathName() const
{
return this->pathName;
}
QString FMList::getPath() const
{
return this->path;
}
void FMList::setPath(const QString &path)
{
if(this->path == path)
return;
if(this->pathType == FMList::PATHTYPE::PLACES_PATH)
this->searchPath = this->path;
this->path = path;
this->setPreviousPath(this->path);
qDebug()<< "Prev History" << this->prevHistory;
const auto __scheme = QUrl(this->path).scheme();
qDebug()<< "CurrentPath" <<__scheme;
// if(path.startsWith(FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::SEARCH_PATH]+"/"))
if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::SEARCH_PATH])
{
this->pathExists = true;
this->pathType = FMList::PATHTYPE::SEARCH_PATH;
this->pathName = "Search";
emit this->pathExistsChanged();
emit this->pathTypeChanged();
this->watchPath(QString());
}else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::CLOUD_PATH])
{
this->pathExists = true;
this->pathType = FMList::PATHTYPE::CLOUD_PATH;
this->pathName = "Cloud";
emit this->pathExistsChanged();
emit this->pathTypeChanged();
this->watchPath(QString());
}else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::APPS_PATH])
{
this->pathExists = true;
this->pathType = FMList::PATHTYPE::APPS_PATH;
this->pathName = "Apps";
emit this->pathExistsChanged();
emit this->pathTypeChanged();
this->watchPath(QString());
}else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::TAGS_PATH])
{
this->pathExists = true;
this->pathType = FMList::PATHTYPE::TAGS_PATH;
emit this->pathName = "Tags";
emit this->pathExistsChanged();
emit this->pathTypeChanged();
this->watchPath(QString());
}else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::TRASH_PATH])
{
this->pathExists = true;
this->pathType = FMList::PATHTYPE::TRASH_PATH;
this->pathName = "Trash";
emit this->pathExistsChanged();
emit this->pathTypeChanged();
this->watchPath(QString());
}else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::PLACES_PATH])
{
this->watchPath(this->path);
this->pathExists = FMH::fileExists(this->path);
this->pathType = FMList::PATHTYPE::PLACES_PATH;
this->pathName = FMH::getDirInfoModel(this->path)[FMH::MODEL_KEY::LABEL];
emit this->pathExistsChanged();
emit this->pathTypeChanged();
}else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::MTP_PATH])
{
this->pathExists = true;
this->pathType = FMList::PATHTYPE::MTP_PATH;
this->pathName = "MTP";
emit this->pathExistsChanged();
emit this->pathTypeChanged();
}else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::FISH_PATH] )
{
this->pathExists = true;
this->pathType = FMList::PATHTYPE::FISH_PATH;
this->pathName = "Fish";
emit this->pathExistsChanged();
emit this->pathTypeChanged();
}else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::REMOTE_PATH] )
{
this->pathExists = true;
this->pathType = FMList::PATHTYPE::REMOTE_PATH;
this->pathName = "Remote";
emit this->pathExistsChanged();
emit this->pathTypeChanged();
}else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::DRIVES_PATH] )
{
this->pathExists = true;
this->pathType = FMList::PATHTYPE::DRIVES_PATH;
this->pathName = "Drives";
emit this->pathExistsChanged();
emit this->pathTypeChanged();
}
qDebug() << "PATHTYPE IS" << this->pathType << FMH::PATHTYPE_SCHEME[static_cast(this->pathType)];
emit this->pathChanged();
emit this->pathNameChanged();
}
FMList::PATHTYPE FMList::getPathType() const
{
return this->pathType;
}
QStringList FMList::getFilters() const
{
return this->filters;
}
void FMList::setFilters(const QStringList &filters)
{
if(this->filters == filters)
return;
this->filters = filters;
emit this->filtersChanged();
this->reset();
}
FMList::FILTER FMList::getFilterType() const
{
return this->filterType;
}
void FMList::setFilterType(const FMList::FILTER &type)
{
this->filterType = type;
this->filters = FMH::FILTER_LIST[static_cast(this->filterType)];
emit this->filtersChanged();
emit this->filterTypeChanged();
this->reset();
}
bool FMList::getHidden() const
{
return this->hidden;
}
void FMList::setHidden(const bool &state)
{
if(this->hidden == state)
return;
this->hidden = state;
if(this->pathType == FMList::PATHTYPE::PLACES_PATH && this->trackChanges && this->saveDirProps)
FMH::setDirConf(this->path+"/.directory", "Settings", "HiddenFilesShown", this->hidden);
else
UTIL::saveSettings("HiddenFilesShown", this->hidden, "SETTINGS");
emit this->hiddenChanged();
this->reset();
}
bool FMList::getPreview() const
{
return this->preview;
}
void FMList::setPreview(const bool &state)
{
if(this->preview == state)
return;
this->preview = state;
if(this->pathType == FMList::PATHTYPE::PLACES_PATH && this->trackChanges && this->saveDirProps)
FMH::setDirConf(this->path+"/.directory", "MAUIFM", "ShowThumbnail", this->preview);
else
UTIL::saveSettings("ShowThumbnail", this->preview, "SETTINGS");
emit this->previewChanged();
}
bool FMList::getOnlyDirs() const
{
return this->onlyDirs;
}
void FMList::setOnlyDirs(const bool &state)
{
if(this->onlyDirs == state)
return;
this->onlyDirs = state;
emit this->onlyDirsChanged();
this->reset();
}
QVariantMap FMList::get(const int &index) const
{
if(index >= this->list.size() || index < 0)
return QVariantMap();
const auto model = this->list.at(index);
return FM::toMap(model);
}
void FMList::refresh()
{
emit this->pathChanged();
}
void FMList::createDir(const QString& name)
{
if(this->pathType == FMList::PATHTYPE::PLACES_PATH)
this->fm->createDir(this->path, name);
else if(this->pathType == FMList::PATHTYPE::CLOUD_PATH)
{
this->fm->createCloudDir(QString(this->path).replace(FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::CLOUD_PATH]+"/"+this->fm->sync->getUser(), ""), name);
}
}
void FMList::copyInto(const QVariantList& files)
{
if(this->pathType == FMList::PATHTYPE::PLACES_PATH || this->pathType == FMList::PATHTYPE::CLOUD_PATH)
this->fm->copy(files, this->path);
}
void FMList::cutInto(const QVariantList& files)
{
if(this->pathType == FMList::PATHTYPE::PLACES_PATH)
this->fm->cut(files, this->path);
// else if(this->pathType == FMList::PATHTYPE::CLOUD_PATH)
// {
// this->fm->createCloudDir(QString(this->path).replace(FMH::PATHTYPE_NAME[FMList::PATHTYPE::CLOUD_PATH]+"/"+this->fm->sync->getUser(), ""), name);
// }
}
void FMList::setDirIcon(const int &index, const QString &iconName)
{
if(index >= this->list.size() || index < 0)
return;
const auto path = QUrl(this->list.at(index)[FMH::MODEL_KEY::PATH]);
if(!FM::isDir(path))
return;
FMH::setDirConf(path.toString()+"/.directory", "Desktop Entry", "Icon", iconName);
this->list[index][FMH::MODEL_KEY::ICON] = iconName;
emit this->updateModel(index, QVector {FMH::MODEL_KEY::ICON});
}
QString FMList::getParentPath()
{
switch(this->pathType)
{
case FMList::PATHTYPE::PLACES_PATH:
return FM::parentDir(this->path).toString();
default:
return this->getPreviousPath();
}
}
QString FMList::getPosteriorPath()
{
if(this->postHistory.isEmpty())
return this->path;
return this->postHistory.takeAt(this->postHistory.length()-1);
}
void FMList::setPosteriorPath(const QString& path)
{
this->postHistory.append(path);
}
QString FMList::getPreviousPath()
{
if(this->prevHistory.isEmpty())
return this->path;
if(this->prevHistory.length() < 2)
return this->prevHistory.at(0);
auto post = this->prevHistory.takeAt(this->prevHistory.length()-1);
this->setPosteriorPath(post);
return this->prevHistory.takeAt(this->prevHistory.length()-1);
}
void FMList::setPreviousPath(const QString& path)
{
this->prevHistory.append(path);
}
bool FMList::getPathEmpty() const
{
return this->pathEmpty;
}
bool FMList::getPathExists() const
{
return this->pathExists;
}
bool FMList::getTrackChanges() const
{
return this->trackChanges;
}
void FMList::setTrackChanges(const bool& value)
{
if(this->trackChanges == value)
return;
this->trackChanges = value;
emit this->trackChangesChanged();
}
bool FMList::getFoldersFirst() const
{
return this->foldersFirst;
}
void FMList::setFoldersFirst(const bool &value)
{
if(this->foldersFirst == value)
return;
this->pre();
this->foldersFirst = value;
if(this->pathType == FMList::PATHTYPE::PLACES_PATH && this->trackChanges && this->saveDirProps)
FMH::setDirConf(this->path+"/.directory", "MAUIFM", "FoldersFirst", this->foldersFirst);
else
UTIL::saveSettings("FoldersFirst", this->foldersFirst, "SETTINGS");
emit this->foldersFirstChanged();
this->sortList();
this->pos();
}
void FMList::setSaveDirProps(const bool& value)
{
if(this->saveDirProps == value)
return;
this->saveDirProps = value;
UTIL::saveSettings("SaveDirProps", this->saveDirProps, "SETTINGS");
emit this->saveDirPropsChanged();
}
bool FMList::getSaveDirProps() const
{
return this->saveDirProps;
}
void FMList::setContentReady(const bool& value)
{
this->contentReady = value;
emit this->contentReadyChanged();
}
bool FMList::getContentReady() const
{
return this->contentReady;
}
void FMList::search(const QString& query, const QUrl &path, const bool &hidden, const bool &onlyDirs, const QStringList &filters)
{
qDebug()<< "SEARCHING FOR" << query << path;
if(!path.isLocalFile())
{
qWarning() << "URL recived is not a local file. search" << path;
return;
}
QFutureWatcher *watcher = new QFutureWatcher;
connect(watcher, &QFutureWatcher::finished, [=]()
{
if(this->pathType != FMList::PATHTYPE::SEARCH_PATH)
return;
const auto res = watcher->future().result();
if(res.path != this->searchPath)
return;
emit this->preListChanged();
this->list = res.content;
emit this->postListChanged();
emit this->searchResultReady();
this->pathEmpty = this->list.isEmpty() && FM::fileExists(this->path);
emit this->pathEmptyChanged();
this->sortList();
this->setContentReady(true);
watcher->deleteLater();
});
QFuture t1 = QtConcurrent::run([=]() -> FMH::PATH_CONTENT
{
FMH::PATH_CONTENT res;
res.path = path.toString();
res.content = FM::search(query, path, hidden, onlyDirs, filters);
return res;
});
watcher->setFuture(t1);
}
int FMList::getCloudDepth() const
{
return this->cloudDepth;
}
void FMList::setCloudDepth(const int& value)
{
if(this->cloudDepth == value)
return;
this->cloudDepth = value;
emit this->cloudDepthChanged();
this->reset();
}
+uint FMList::getCount() const
+{
+ return this->count;
+}
+
diff --git a/src/fm/fmlist.h b/src/fm/fmlist.h
index 2cc3128..1441a8c 100644
--- a/src/fm/fmlist.h
+++ b/src/fm/fmlist.h
@@ -1,245 +1,250 @@
/*
*
* Copyright (C) 2018 Camilo Higuita
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef FMLIST_H
#define FMLIST_H
#include
#include "fmh.h"
#include "mauilist.h"
struct PathContent
{
QString path;
FMH::MODEL_LIST content;
};
class FM;
class QFileSystemWatcher;
class FMList : public MauiList
{
Q_OBJECT
Q_PROPERTY(QString path READ getPath WRITE setPath NOTIFY pathChanged)
Q_PROPERTY(QString pathName READ getPathName NOTIFY pathNameChanged)
Q_PROPERTY(bool hidden READ getHidden WRITE setHidden NOTIFY hiddenChanged)
Q_PROPERTY(bool onlyDirs READ getOnlyDirs WRITE setOnlyDirs NOTIFY onlyDirsChanged)
Q_PROPERTY(bool preview READ getPreview WRITE setPreview NOTIFY previewChanged)
Q_PROPERTY(int cloudDepth READ getCloudDepth WRITE setCloudDepth NOTIFY cloudDepthChanged)
+ Q_PROPERTY(uint count READ getCount NOTIFY countChanged)
Q_PROPERTY(bool contentReady READ getContentReady NOTIFY contentReadyChanged)
Q_PROPERTY(QStringList filters READ getFilters WRITE setFilters NOTIFY filtersChanged)
Q_PROPERTY(FMList::FILTER filterType READ getFilterType WRITE setFilterType NOTIFY filterTypeChanged)
Q_PROPERTY(FMList::SORTBY sortBy READ getSortBy WRITE setSortBy NOTIFY sortByChanged)
Q_PROPERTY(bool foldersFirst READ getFoldersFirst WRITE setFoldersFirst NOTIFY foldersFirstChanged)
Q_PROPERTY(FMList::PATHTYPE pathType READ getPathType NOTIFY pathTypeChanged)
Q_PROPERTY(bool trackChanges READ getTrackChanges WRITE setTrackChanges NOTIFY trackChangesChanged)
Q_PROPERTY(bool saveDirProps READ getSaveDirProps WRITE setSaveDirProps NOTIFY saveDirPropsChanged)
Q_PROPERTY(bool pathExists READ getPathExists NOTIFY pathExistsChanged)
Q_PROPERTY(bool pathEmpty READ getPathEmpty NOTIFY pathEmptyChanged)
Q_PROPERTY(QString previousPath READ getPreviousPath)
Q_PROPERTY(QString posteriorPath READ getPosteriorPath)
Q_PROPERTY(QString parentPath READ getParentPath)
public:
enum SORTBY : uint_fast8_t
{
SIZE = FMH::MODEL_KEY::SIZE,
MODIFIED = FMH::MODEL_KEY::MODIFIED,
DATE = FMH::MODEL_KEY::DATE,
LABEL = FMH::MODEL_KEY::LABEL,
MIME = FMH::MODEL_KEY::MIME,
ADDDATE = FMH::MODEL_KEY::MIME,
TITLE = FMH::MODEL_KEY::TITLE,
PLACE = FMH::MODEL_KEY::PLACE,
FORMAT = FMH::MODEL_KEY::FORMAT
}; Q_ENUM(SORTBY)
enum FILTER : uint_fast8_t
{
AUDIO = FMH::FILTER_TYPE::AUDIO,
VIDEO= FMH::FILTER_TYPE::VIDEO,
TEXT = FMH::FILTER_TYPE::TEXT,
IMAGE = FMH::FILTER_TYPE::IMAGE,
NONE = FMH::FILTER_TYPE::NONE
}; Q_ENUM(FILTER)
enum PATHTYPE : uint_fast8_t
{
PLACES_PATH = FMH::PATHTYPE_KEY::PLACES_PATH,
FISH_PATH = FMH::PATHTYPE_KEY::FISH_PATH,
MTP_PATH = FMH::PATHTYPE_KEY::MTP_PATH,
REMOTE_PATH = FMH::PATHTYPE_KEY::REMOTE_PATH,
DRIVES_PATH = FMH::PATHTYPE_KEY::DRIVES_PATH,
REMOVABLE_PATH = FMH::PATHTYPE_KEY::REMOVABLE_PATH,
TAGS_PATH = FMH::PATHTYPE_KEY::TAGS_PATH,
APPS_PATH = FMH::PATHTYPE_KEY::APPS_PATH,
TRASH_PATH = FMH::PATHTYPE_KEY::TRASH_PATH,
SEARCH_PATH = FMH::PATHTYPE_KEY::SEARCH_PATH,
CLOUD_PATH = FMH::PATHTYPE_KEY::CLOUD_PATH
}; Q_ENUM(PATHTYPE)
enum VIEW_TYPE : uint_fast8_t
{
ICON_VIEW,
LIST_VIEW,
MILLERS_VIEW
}; Q_ENUM(VIEW_TYPE)
FMList(QObject *parent = nullptr);
~FMList();
FMH::MODEL_LIST items() const final override;
FMList::SORTBY getSortBy() const;
void setSortBy(const FMList::SORTBY &key);
QString getPath() const;
void setPath(const QString &path);
QString getPathName() const;
FMList::PATHTYPE getPathType() const;
QStringList getFilters() const;
void setFilters(const QStringList &filters);
FMList::FILTER getFilterType() const;
void setFilterType(const FMList::FILTER &type);
bool getHidden() const;
void setHidden(const bool &state);
bool getPreview() const;
void setPreview(const bool &state);
bool getOnlyDirs() const;
void setOnlyDirs(const bool &state);
QString getParentPath();
QString getPreviousPath();
void setPreviousPath(const QString &path);
QString getPosteriorPath();
void setPosteriorPath(const QString &path);
bool getPathEmpty() const;
bool getPathExists() const;
bool getTrackChanges() const;
void setTrackChanges(const bool &value);
bool getFoldersFirst() const;
void setFoldersFirst(const bool &value);
bool getSaveDirProps() const;
void setSaveDirProps(const bool &value);
bool getContentReady() const;
void setContentReady(const bool &value);
int getCloudDepth() const;
void setCloudDepth(const int &value);
+ uint getCount() const;
+
private:
FM *fm;
QFileSystemWatcher *watcher;
void pre();
void pos();
void reset();
void setList();
void sortList();
void watchPath(const QString &path, const bool &clear = true);
void search(const QString &query, const QUrl &path, const bool &hidden = false, const bool &onlyDirs = false, const QStringList &filters = QStringList());
FMH::MODEL_LIST list = {{}};
QString path = QString();
QString pathName = QString();
QStringList filters = {};
bool onlyDirs = false;
bool hidden = false;
bool preview = false;
bool pathExists = false;
bool pathEmpty = true;
bool trackChanges = true;
bool foldersFirst = false;
bool saveDirProps = false;
bool contentReady = false;
int cloudDepth = 1;
+ uint count = 0;
QString searchPath;
FMList::SORTBY sort = FMList::SORTBY::MODIFIED;
FMList::FILTER filterType = FMList::FILTER::NONE;
FMList::PATHTYPE pathType = FMList::PATHTYPE::PLACES_PATH;
QStringList prevHistory = {};
QStringList postHistory = {};
public slots:
QVariantMap get(const int &index) const;
void refresh();
void createDir(const QString &name);
void copyInto(const QVariantList &files);
void cutInto(const QVariantList &files);
void setDirIcon(const int &index, const QString &iconName);
signals:
void pathChanged();
void pathNameChanged();
void pathTypeChanged();
void filtersChanged();
void filterTypeChanged();
void hiddenChanged();
void previewChanged();
void onlyDirsChanged();
void sortByChanged();
void trackChangesChanged();
void foldersFirstChanged();
void saveDirPropsChanged();
void contentReadyChanged();
void cloudDepthChanged();
+ void countChanged();
void pathEmptyChanged();
void pathExistsChanged();
void warning(QString message);
void progress(int percent);
void searchResultReady();
};
#endif // FMLIST_H
diff --git a/src/fm/pathlist.cpp b/src/fm/pathlist.cpp
index 613da36..089d076 100644
--- a/src/fm/pathlist.cpp
+++ b/src/fm/pathlist.cpp
@@ -1,99 +1,101 @@
/*
*
* Copyright (C) 2019 camilo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "pathlist.h"
#include "fm.h"
PathList::PathList(QObject *parent) : MauiList(parent)
{
}
PathList::~PathList() {}
QVariantMap PathList::get(const int& index) const
{
- if(this->list.isEmpty() || index >= this->list.size() || index < 0)
- {
- return QVariantMap();
- }
-
+ if(this->list.isEmpty() || index >= this->list.size() || index < 0)
+ {
+ return QVariantMap();
+ }
+
const auto model = this->list.at(index);
return FM::toMap(model);
}
QString PathList::getPath() const
{
return this->m_path;
}
FMH::MODEL_LIST PathList::items() const
{
return this->list;
}
void PathList::setPath(const QString& path)
{
if(path == this->m_path)
return;
if(!this->list.isEmpty() && FM::parentDir(path) == this->m_path)
{
// qDebug() << "APPENDING PATHS TO MODEL << "<< FM::parentDir(this->m_path) << this->list.last()[FMH::MODEL_KEY::PATH];
emit this->preItemAppended();
this->list << FMH::getDirInfoModel(path);
emit this->postItemAppended();
}else{
emit this->preListChanged();
this->list.clear();
this->list << PathList::splitPath(path);
emit this->postListChanged();
}
this->m_path = path;
emit this->pathChanged();
}
FMH::MODEL_LIST PathList::splitPath(const QString& path)
{
auto __url = QUrl(path);
const auto scheme = __url.scheme();
__url.setScheme("");
const auto m_url = __url.toString();
- const auto paths = m_url.split("/", QString::SplitBehavior::SkipEmptyParts);
-
- qDebug()<< "PATHBAR LIST"<< m_url << paths;
+ auto paths = m_url.split("/", QString::SplitBehavior::SkipEmptyParts);
+ if(paths.isEmpty())
+ {
+ return {{{FMH::MODEL_KEY::LABEL, QString()}, {FMH::MODEL_KEY::PATH, path}}};
+ }
return std::accumulate(paths.constBegin(), paths.constEnd(), FMH::MODEL_LIST(), [scheme](FMH::MODEL_LIST &list, const QString &part) -> FMH::MODEL_LIST
{
const auto url = list.isEmpty() ? QString(scheme + (scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::PLACES_PATH] ? ":///" : "://") +part) : list.last()[FMH::MODEL_KEY::PATH] + QString("/"+part);
if(!url.isEmpty())
list << FMH::MODEL
{
{FMH::MODEL_KEY::LABEL, part},
{FMH::MODEL_KEY::PATH, url}
};
return list;
});
}