diff --git a/src/controls/Dialog.qml b/src/controls/Dialog.qml index ebc43c8..2b162d7 100644 --- a/src/controls/Dialog.qml +++ b/src/controls/Dialog.qml @@ -1,197 +1,197 @@ /* * 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.3 import QtQuick.Layouts 1.3 import org.kde.mauikit 1.0 as Maui -import org.kde.kirigami 2.2 as Kirigami +import org.kde.kirigami 2.6 as Kirigami Maui.Popup { id: control property string message : "" property string title: "" property string acceptText: "Ok" property string rejectText: "No" property bool defaultButtons: true property bool confirmationDialog: false property bool entryField: false default property alias content : page.content property alias acceptButton : _acceptButton property alias rejectButton : _rejectButton property alias textEntry : _textEntry property alias page : page property alias footBar : page.footBar property alias headBar: page.headBar property alias headBarTitle: page.headBarTitle property alias closeButton: _closeButton signal accepted() signal rejected() maxWidth: unit * 300 maxHeight: _pageContent.implicitHeight + page.footBar.height + page.margins + space.huge widthHint: 0.9 heightHint: 0.9 z: 1 clip: false Maui.Badge { id: _closeButton iconName: "window-close" colorScheme.backgroundColor: hovered ? dangerColor : colorScheme.altColor anchors { verticalCenter: parent.top horizontalCenter: parent.left } z: control.z+1 onClicked: { // rejected() close() } } Maui.Page { id: page headBar.visible: headBar.count > 2 anchors.fill: parent footBar.dropShadow: false footBar.drawBorder: false margins: space.big clip: true headBarExit: false colorScheme.backgroundColor : control.colorScheme.backgroundColor footBar.visible: defaultButtons || footBar.count > 1 footBar.colorScheme.backgroundColor: colorScheme.backgroundColor footBar.margins: space.big footBar.rightContent: Row { spacing: space.big - Maui.Button + Button { id: _rejectButton visible: defaultButtons - colorScheme.textColor: dangerColor - colorScheme.borderColor: dangerColor - colorScheme.backgroundColor: "transparent" + Kirigami.Theme.textColor: dangerColor +// Kirigami.Theme.borderColor: dangerColor + Kirigami.Theme.backgroundColor: "transparent" text: rejectText onClicked: rejected() } - Maui.Button + Button { id: _acceptButton visible: defaultButtons - colorScheme.backgroundColor: infoColor - colorScheme.textColor: "white" + Kirigami.Theme.backgroundColor: infoColor + Kirigami.Theme.textColor: "white" text: acceptText onClicked: accepted() } } ColumnLayout { id: _pageContent anchors.fill: parent spacing: space.medium Label { width: parent.width height: visible ? implicitHeight : 0 visible: title.length > 0 Layout.fillWidth: visible Layout.alignment: Qt.AlignLeft | Qt.AlignTop clip: true color: colorScheme.textColor text: title font.weight: Font.Thin font.bold: true font.pointSize: fontSizes.huge elide: Qt.ElideRight wrapMode: Text.Wrap // elide: Qt.ElideRight } ScrollView { visible: message.length > 0 Layout.fillHeight: visible Layout.fillWidth: visible Layout.alignment: Qt.AlignLeft | Qt.AlignTop padding: 0 clip: true ScrollBar.horizontal.policy: ScrollBar.AlwaysOff TextArea { id: body padding: 0 width: parent.width height: parent.height enabled: false text: message textFormat : TextEdit.AutoText color: colorScheme.textColor font.pointSize: fontSizes.default wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere // background: Rectangle // { // color: "transparent" // } } } Maui.TextField { id: _textEntry // anchors.fill: parent onAccepted: control.accepted() Layout.fillWidth: entryField height: entryField ? iconSizes.big : 0 visible: entryField clip: true } } } } diff --git a/src/controls/FileBrowser.qml b/src/controls/FileBrowser.qml index 386c70e..68f2352 100644 --- a/src/controls/FileBrowser.qml +++ b/src/controls/FileBrowser.qml @@ -1,908 +1,908 @@ import QtQuick 2.9 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 import org.kde.kirigami 2.6 as Kirigami import org.kde.mauikit 1.0 as Maui import "private" Maui.Page { id: control /* Controlc color scheming */ ColorScheme {id: colorScheme} property alias colorScheme : colorScheme /***************************/ property alias trackChanges: modelList.trackChanges property alias saveDirProps: modelList.saveDirProps property string currentPath: Maui.FM.homePath() 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 alias selectionBar : selectionBarLoader.item property alias model : folderModel property alias list : modelList property alias browser : viewLoader.item property alias previewer : previewer property alias menu : browserMenu.actions property alias itemMenu: itemMenu property alias holder: holder property alias dialog : dialogLoader.item property alias goUpButton : goUpButton property alias currentPathType : modelList.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) margins: 0 Loader { id: dialogLoader } Component { id: removeDialogComponent Maui.Dialog { property var items: [] title: qsTr("Delete files?") message: qsTr("If you are sure you want to delete the files click on Accept, otherwise click on Cancel") rejectButton.text: qsTr("Cancel") acceptButton.text: qsTr("Accept") onRejected: close() onAccepted: { if(control.selectionBar && control.selectionBar.visible) { control.selectionBar.clear() control.selectionBar.animate("red") } control.remove(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: list.createDir(text) rejectButton.visible: false } } 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 } } Component { id: renameDialogComponent Maui.NewDialog { title: qsTr("Rename file") message: qsTr("Rename a file or folder to a new custom name") textEntry.text: list.get(browser.currentIndex).label textEntry.placeholderText: qsTr("New name...") onFinished: Maui.FM.rename(itemMenu.items[0].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 // width: unit *200 z : control.z +1 } Maui.FilePreviewer { id: previewer parent: parent onShareButtonClicked: control.shareFiles([url]) } Maui.BaseModel { id: folderModel list: modelList } Maui.FMList { id: modelList 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 } } FileMenu { id: itemMenu width: unit *200 onBookmarkClicked: control.newBookmark([items[0].path]) onCopyClicked: { if(items.length) control.copy(items) } onCutClicked: { if(items.length) control.cut(items) } onTagsClicked: { if(items.length) { dialogLoader.sourceComponent = tagsDialogComponent if(items.length > 1 && control.selectionBar) dialog.composerList.urls = control.selectionBar.selectedPaths else dialog.composerList.urls = items[0].path dialog.open() } } onRenameClicked: { if(items.length === 1) { dialogLoader.sourceComponent = renameDialogComponent dialog.open() } } // onSaveToClicked: // { // fmDialog.saveDialog = false // fmDialog.multipleSelection = true // fmDialog.onlyDirs= true // var myPath = path // var paths = browser.selectionBar.selectedPaths // fmDialog.show(function(paths) // { // inx.copy(myPath, paths) // }) // } onRemoveClicked: { dialogLoader.sourceComponent= removeDialogComponent dialog.items = items dialog.open() } onShareClicked: { if(items.length) control.shareFiles([items[0].path]) } } Component { id: listViewBrowser Maui.ListBrowser { showPreviewThumbnails: modelList.preview showEmblem: selectionMode rightEmblem: isMobile ? "document-share" : "" leftEmblem: "list-add" showDetailsInfo: true // itemSize: thumbnailsSize model: folderModel section.delegate: Maui.LabelDelegate { id: delegate label: section labelTxt.font.pointSize: fontSizes.big isSection: true boldLabel: true height: toolBarHeightAlt } } } Component { id: gridViewBrowser Maui.GridBrowser { itemSize : thumbnailsSize + fontSizes.default showEmblem: selectionMode showPreviewThumbnails: modelList.preview rightEmblem: isMobile ? "document-share" : "" leftEmblem: "list-add" model: folderModel } } Connections { target: browser onItemClicked: { browser.currentIndex = index indexHistory.push(index) control.itemClicked(index) } onItemDoubleClicked: { browser.currentIndex = index indexHistory.push(index) control.itemDoubleClicked(index) } onItemRightClicked: { itemMenu.show([modelList.get(index)]) control.itemRightClicked(index) } onLeftEmblemClicked: { control.addToSelection(modelList.get(index), true) control.itemLeftEmblemClicked(index) } onRightEmblemClicked: { isAndroid ? Maui.Android.shareDialog([modelList.get(index).path]) : shareDialog.show([modelList.get(index).path]) control.itemRightEmblemClicked(index) } onAreaClicked: { if(!isMobile && mouse.button === Qt.RightButton) browserMenu.show() else return control.rightClicked() } onAreaRightClicked: browserMenu.show() } focus: true Maui.Holder { id: holder anchors.fill : parent z: -1 visible: !modelList.pathExists || modelList.pathEmpty || !modelList.contentReady emoji: if(modelList.pathExists && modelList.pathEmpty) "qrc:/assets/MoonSki.png" else if(!modelList.pathExists) "qrc:/assets/ElectricPlug.png" else if(!modelList.contentReady && currentPathType === Maui.FMList.SEARCH_PATH) "qrc:/assets/animat-search-color.gif" else if(!modelList.contentReady) "qrc:/assets/animat-rocket-color.gif" isGif: !modelList.contentReady isMask: false title : if(modelList.pathExists && modelList.pathEmpty) qsTr("Folder is empty!") else if(!modelList.pathExists) qsTr("Folder doesn't exists!") else if(!modelList.contentReady && currentPathType === Maui.FMList.SEARCH_PATH) qsTr("Searching for content!") else if(!modelList.contentReady) qsTr("Loading content!") body: if(modelList.pathExists && modelList.pathEmpty) qsTr("You can add new files to it") else if(!modelList.pathExists) qsTr("Create Folder?") else if(!modelList.contentReady && currentPathType === Maui.FMList.SEARCH_PATH) qsTr("This might take a while!") else if(!modelList.contentReady) qsTr("Almost ready!") emojiSize: iconSizes.huge onActionTriggered: { if(!modelList.pathExists) { Maui.FM.createDir(control.currentPath.slice(0, control.currentPath.lastIndexOf("/")), control.currentPath.split("/").pop()) control.openFolder(modelList.parentPath) } } } Keys.onSpacePressed: previewer.show(modelList.get(browser.currentIndex).path) headBarExit: false headBar.visible: currentPathType !== Maui.FMList.APPS_PATH altToolBars: isMobile headBar.rightContent: Kirigami.ActionToolBar { Layout.fillWidth: true z: 999 hiddenActions: browserMenu.actions display: isMobile ? ToolButton.IconOnly : ToolButton.TextBesideIcon actions: [ Kirigami.Action { iconName: list.viewType == Maui.FMList.ICON_VIEW ? "view-list-details" : "view-list-icons" onTriggered: control.switchView() }, Kirigami.Action { iconName: "view-sort" text: qsTr("Sort") Kirigami.Action { text: qsTr("Folders first") checked: list.foldersFirst onTriggered: list.foldersFirst = !list.foldersFirst } Kirigami.Action { text: qsTr("Type") checked: list.sortBy === Maui.FMList.MIME onTriggered: list.sortBy = Maui.FMList.MIME } Kirigami.Action { text: qsTr("Date") checked: list.sortBy === Maui.FMList.DATE onTriggered: list.sortBy = Maui.FMList.DATE } Kirigami.Action { text: qsTr("Modified") checked: list.sortBy === Maui.FMList.MODIFIED onTriggered: list.sortBy = Maui.FMList.MODIFIED } Kirigami.Action { text: qsTr("Size") checked: list.sortBy === Maui.FMList.SIZE onTriggered: list.sortBy = Maui.FMList.SIZE } Kirigami.Action { text: qsTr("Name") checked: list.sortBy === Maui.FMList.LABEL onTriggered: list.sortBy = Maui.FMList.LABEL } Kirigami.Action { id: groupAction text: qsTr("Group") checked: group onTriggered: { group = !group if(group) groupBy() else browser.section.property = "" } } }, Kirigami.Action { text: qsTr("Select") iconName: "item-select" checkable: false checked: selectionMode onTriggered: selectionMode = !selectionMode } ] } headBar.leftContent: [ Maui.ToolButton { iconName: "go-previous" onClicked: control.goBack() }, Maui.ToolButton { id: goUpButton visible: isAndroid iconName: "go-up" onClicked: control.goUp() }, Maui.ToolButton { iconName: "go-next" onClicked: control.goNext() } ] footBar.visible: false Component { id: selectionBarComponent Maui.SelectionBar { anchors.fill: parent onIconClicked: _selectionBarmenu.popup() onExitClicked: clearSelection() 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) + 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() } } } } } ColumnLayout { anchors.fill: parent visible: !holder.visible z: holder.z + 1 spacing: 0 Loader { id: viewLoader z: holder.z + 1 sourceComponent: list.viewType == Maui.FMList.ICON_VIEW ? gridViewBrowser : listViewBrowser Layout.topMargin: list.viewType == Maui.FMList.LIST_VIEW ? unit : contentMargins * 2 Layout.margins: unit Layout.fillWidth: true Layout.fillHeight: true } Loader { id: selectionBarLoader Layout.fillWidth: true Layout.preferredHeight: control.selectionBar ? (control.selectionBar.visible ? control.selectionBar.barHeight : 0) : 0 Layout.leftMargin: contentMargins * (isMobile ? 3 : 2) Layout.rightMargin: contentMargins * (isMobile ? 3 : 2) Layout.bottomMargin: contentMargins*2 z: holder.z +1 } ProgressBar { id: _progressBar Layout.fillWidth: true Layout.alignment: Qt.AlignBottom height: iconSizes.medium visible: value > 0 } } // PinchArea // { // anchors.fill: parent // // property real initialWidth // property real initialHeight // // onPinchStarted: // { // console.log("pinch started") // } // // onPinchUpdated: // { // console.log(pinch.scale) // } // // onPinchFinished: // { // console.log("pinch finished") // } // } onThumbnailsSizeChanged: { if(trackChanges && saveDirProps) Maui.FM.setDirConf(currentPath+"/.directory", "MAUIFM", "IconSize", thumbnailsSize) else Maui.FM.saveSettings("IconSize", thumbnailsSize, "SETTINGS") if(list.viewType == Maui.FMList.ICON_VIEW) browser.adaptGrid() } 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 = modelList.get(index) var path = 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(Maui.FM.isDir(path)) 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(path) } function setPath(path) { 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(list.viewType == Maui.FMList.ICON_VIEW) browser.adaptGrid() } function goBack() { populate(modelList.previousPath) browser.currentIndex = indexHistory.pop() // browser.positionViewAtIndex(browser.currentIndex, ListView.Center) } function goNext() { openFolder(modelList.posteriorPath) } function goUp() { openFolder(modelList.parentPath) } function refresh() { var pos = browser.contentY modelList.refresh() browser.contentY = pos } function addToSelection(item, append) { selectionBarLoader.sourceComponent= selectionBarComponent selectionBar.append(item) } function clearSelection() { clean() // selectionMode = false } 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) list.copyInto(copyItems, currentPath) else if(isCut) { list.cutInto(cutItems, currentPath) clearSelection() } } function remove(items) { for(var i in items) Maui.FM.removeFile(items[i].path) } function switchView() { list.viewType = list.viewType === Maui.FMList.ICON_VIEW ? Maui.FMList.LIST_VIEW : Maui.FMList.ICON_VIEW } 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(modelList.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; } list.viewType = Maui.FMList.LIST_VIEW if(!prop) { browser.section.property = "" return } browser.section.property = prop browser.section.criteria = criteria } } diff --git a/src/controls/FileDialog.qml b/src/controls/FileDialog.qml index 54d7c1d..c914b6a 100644 --- a/src/controls/FileDialog.qml +++ b/src/controls/FileDialog.qml @@ -1,289 +1,308 @@ /* * 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 org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.6 as Kirigami import org.kde.mauikit 1.0 as Maui import QtQuick.Layouts 1.3 Maui.Dialog { id: control maxHeight: isMobile ? parent.height * 0.95 : unit * 500 maxWidth: unit * 700 page.margins: 0 defaultButtons: false property string initPath property string suggestedFileName : "" property var filters: [] property int filterType: Maui.FMList.NONE property bool onlyDirs: false property int sortBy: Maui.FMList.MODIFIED property bool searchBar : false readonly property var modes : ({OPEN: 0, SAVE: 1}) property int mode : modes.OPEN property var callback : ({}) property alias textField: _textField Maui.Dialog { id: _confirmationDialog // anchors.centerIn: parent acceptButton.text: qsTr("Accept") rejectButton.text: qsTr("Cancel") title: qsTr(textField.text+" already exists!") message: qsTr("If you are sure you want to replace the existing file click on Accept, otherwise click on cancel and change the name of the file to something different...") onAccepted: control.done() onRejected: close() } Maui.Page { id: page anchors.fill: parent leftPadding: 0 margins: 0 rightPadding: leftPadding topPadding: leftPadding bottomPadding: leftPadding headBarExit: false headBar.plegable: false headBarTitleVisible: false - headBar.implicitHeight: pathBar.height + space.big - - headBar.middleContent: Maui.PathBar + headBar.implicitHeight: toolBarHeight + space.medium + Component { - id: pathBar - height: iconSizes.big - Layout.fillWidth: true - // anchors.centerIn: parent - url: browser.currentPath - onPathChanged: browser.openFolder(path) - onHomeClicked: - { - if(pageRow.currentIndex !== 0 && !pageRow.wideMode) - pageRow.currentIndex = 0 - - browser.openFolder(Maui.FM.homePath()) - } - - onPlaceClicked: browser.openFolder(path) - - Maui.TextField - { - id: searchField - anchors.fill: parent - visible: searchBar - focus: visible - z: pathBar.z+1 - placeholderText: qsTr("Search... ") - onAccepted: browser.openFolder("Search/"+text) - // onCleared: browser.goBack() - onGoBackTriggered: - { - searchBar = false - searchField.clear() - } - } - } - + id: _pathBarComponent + + Maui.PathBar + { + anchors.fill: parent + // colorScheme.backgroundColor: "#fff" + // colorScheme.textColor: "#333" + // colorScheme.borderColor: Qt.darker(headBarBGColor, 1.4) + onPathChanged: browser.openFolder(path) + url: browser.currentPath + onHomeClicked: browser.openFolder(Maui.FM.homePath()) + onPlaceClicked: browser.openFolder(path) + } + } + + Component + { + id: _searchFieldComponent + + Maui.TextField + { + anchors.fill: parent + placeholderText: qsTr("Search for files... ") + onAccepted: browser.openFolder("Search/"+text) + // onCleared: browser.goBack() + onGoBackTriggered: + { + searchBar = false + clear() + // browser.goBack() + } + + background: Rectangle + { + border.color: borderColor + radius: radiusV + } + } + } + + headBar.middleContent: Item + { + id: _pathBarLoader + Layout.fillWidth: true + Layout.margins: space.medium + height: iconSizes.big + Loader + { + anchors.fill: parent + sourceComponent: searchBar ? _searchFieldComponent : _pathBarComponent + + } + } + headBar.rightContent: Maui.ToolButton { id: searchButton iconName: "edit-find" onClicked: searchBar = !searchBar iconColor: searchBar ? searchButton.colorScheme.highlightColor : searchButton.colorScheme.textColor } Kirigami.PageRow { id: pageRow anchors.fill: parent clip: true property int sidebarWidth: sidebar.isCollapsed ? sidebar.iconSize * 2 : Kirigami.Units.gridUnit * (isMobile? 15 : 8) separatorVisible: wideMode initialPage: [sidebar, content] defaultColumnWidth: sidebarWidth // interactive: currentIndex === 1 Maui.PlacesSidebar { id: sidebar width: isCollapsed ? iconSize*2 : parent.width height: parent.height onPlaceClicked: { pageRow.currentIndex = 1 browser.openFolder(path) } list.groups: control.mode === modes.OPEN ? [ Maui.FMList.PLACES_PATH, - Maui.FMList.BOOKMARKS_PATH, Maui.FMList.CLOUD_PATH, + Maui.FMList.REMOTE_PATH, Maui.FMList.DRIVES_PATH, Maui.FMList.TAGS_PATH] : - [Maui.FMList.PLACES_PATH, + [Maui.FMList.PLACES_PATH, + Maui.FMList.REMOTE_PATH, Maui.FMList.CLOUD_PATH, Maui.FMList.DRIVES_PATH] } ColumnLayout { id: content Maui.FileBrowser { id: browser Layout.fillWidth: true Layout.fillHeight: true altToolBars: false previewer.parent: ApplicationWindow.overlay trackChanges: false selectionMode: control.mode === modes.OPEN list.onlyDirs: control.onlyDirs list.filters: control.filters list.sortBy: control.sortBy list.filterType: control.filterType onItemClicked: { switch(control.mode) { case modes.OPEN : { openItem(index) break } case modes.SAVE: { if(Maui.FM.isDir(list.get(index).path)) openItem(index) else textField.text = list.get(index).label break } } } onCurrentPathChanged: { for(var i=0; i < sidebar.count; i++) if(currentPath === sidebar.list.get(i).path) sidebar.currentIndex = i } } Maui.ToolBar { id: _bottomBar position: ToolBar.Footer drawBorder: true Layout.fillWidth: true middleContent: Maui.TextField { id: _textField visible: control.mode === modes.SAVE width: _bottomBar.middleLayout.width * 0.9 placeholderText: qsTr("File name") text: suggestedFileName - } rightContent: Row { spacing: space.big - Maui.Button + Button { id: _acceptButton - colorScheme.textColor: "white" - colorScheme.backgroundColor: suggestedColor + Kirigami.Theme.textColor: "white" + Kirigami.Theme.backgroundColor: suggestedColor text: qsTr("Accept") onClicked: { console.log("CURRENT PATHb", browser.currentPath+"/"+textField.text) if(control.mode === modes.SAVE && Maui.FM.fileExists(browser.currentPath+"/"+textField.text)) { _confirmationDialog.open() }else { done() } } } } } } } } function show(cb) { callback = cb if(initPath) browser.openFolder(initPath) else browser.openFolder(browser.currentPath) open() } function closeIt() { browser.clearSelection() close() } function done() { var paths = browser.selectionBar && browser.selectionBar.visible ? browser.selectionBar.selectedPaths : browser.currentPath if(control.mode === modes.SAVE) { if (typeof paths == 'string') { paths = paths + "/" + textField.text }else { for(var i in paths) paths[i] = paths[i] + "/" + textField.text } } callback(paths) control.closeIt() } } diff --git a/src/controls/FilePreviewer.qml b/src/controls/FilePreviewer.qml index 8ec0c41..263f06e 100644 --- a/src/controls/FilePreviewer.qml +++ b/src/controls/FilePreviewer.qml @@ -1,211 +1,211 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.6 as Kirigami import org.kde.mauikit 1.0 as Maui import "private" Maui.Dialog { id: control colorScheme.backgroundColor: "#2d2d2d" colorScheme.textColor: "#fafafa" property string currentUrl: "" property var iteminfo : ({}) property bool isDir : false property string mimetype : "" property bool showInfo: true signal shareButtonClicked(string url) maxHeight: unit * 800 maxWidth: unit * 500 defaultButtons: false footBar.leftContent: Maui.ToolButton { iconColor: control.colorScheme.textColor iconName: "document-open" text: qsTr("Open") onClicked: { if(typeof(previewLoader.item.player) !== "undefined") previewLoader.item.player.stop() openFile(currentUrl) } } footBar.middleContent: [ Maui.ToolButton { visible: !isDir iconColor: control.colorScheme.textColor iconName: "document-share" text: qsTr("Share") onClicked: { shareButtonClicked(currentUrl) close() } }, Maui.ToolButton { iconName: "love" iconColor: control.colorScheme.textColor text: qsTr("Fav") } ] footBar.rightContent: Maui.ToolButton { iconName: "documentinfo" text: qsTr("Info") checkable: true checked: showInfo onClicked: showInfo = !showInfo iconColor: control.colorScheme.textColor } Component { id: imagePreview ImagePreview { id: imagePreviewer } } Component { id: defaultPreview DefaultPreview { id: defaultPreviewer } } Component { id: audioPreview AudioPreview { id: audioPreviewer } } Component { id: videoPreview VideoPreview { id: videoPreviewer } } ColumnLayout { anchors.fill: parent spacing: 0 clip: true Label { Layout.fillWidth: true Layout.margins: space.medium horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter elide: Qt.ElideRight wrapMode: Text.Wrap font.pointSize: fontSizes.big font.weight: Font.Bold font.bold: true text: iteminfo.name color: colorScheme.textColor } Loader { id: previewLoader Layout.fillWidth: true Layout.fillHeight: true sourceComponent: switch(mimetype) { case "audio" : audioPreview break case "video" : videoPreview break case "text" : defaultPreview break case "image" : imagePreview break case "inode" : default: defaultPreview } } Maui.TagsBar { id: _tagsBar Layout.fillWidth: true Layout.margins: 0 // height: 64 list.urls: [control.currentUrl] allowEditMode: true clip: true onTagRemovedClicked: list.removeFromUrls(index) onTagsEdited: list.updateToUrls(tags) // colorScheme: control.colorScheme - colorScheme.textColor: control.colorScheme.textColor - colorScheme.backgroundColor: control.colorScheme.backgroundColor + Kirigami.Theme.textColor: control.colorScheme.textColor + Kirigami.Theme.backgroundColor: control.colorScheme.backgroundColor onAddClicked: { dialogLoader.sourceComponent = tagsDialogComponent dialog.composerList.urls = [control.currentUrl] dialog.open() } } } onClosed: { if(previewLoader.item.player) previewLoader.item.player.stop() } function show(path) { control.currentUrl = path control.iteminfo = Maui.FM.getFileInfo(path) if(iteminfo.mime.indexOf("/")) control.mimetype = iteminfo.mime.slice(0, iteminfo.mime.indexOf("/")) else control.mimetype = "" control.isDir = mimetype === "inode" showInfo = mimetype === "image" || mimetype === "video" ? false : true console.log("MIME TYPE FOR PREVEIWER", mimetype, iteminfo.icon) open() } } diff --git a/src/controls/TagsBar.qml b/src/controls/TagsBar.qml index 9bc3d82..cfa7fc8 100644 --- a/src/controls/TagsBar.qml +++ b/src/controls/TagsBar.qml @@ -1,179 +1,179 @@ /* * 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.6 as Kirigami import org.kde.mauikit 1.0 as Maui import "private" -Maui.Item +Item { id: control clip : true width: parent.width height: rowHeight property alias listView : tagsList property alias count : tagsList.count property color bgColor: "transparent" property bool editMode : false property bool allowEditMode : false property alias list : tagsList.list signal addClicked() signal tagRemovedClicked(int index) signal tagClicked(string tag) signal tagsEdited(var tags) Rectangle { anchors.fill: parent color: bgColor z: -1 } RowLayout { anchors.fill: parent spacing: 0 Item { Layout.fillHeight: true Layout.fillWidth: true visible: !editMode RowLayout { anchors.fill: parent spacing: 0 Maui.ToolButton { Layout.alignment: Qt.AlignLeft visible: allowEditMode iconName: "list-add" onClicked: addClicked() - iconColor: control.colorScheme.textColor + iconColor: control.Kirigami.Theme.textColor } TagList { id: tagsList Layout.leftMargin: contentMargins Layout.alignment: Qt.AlignCenter Layout.fillHeight: true Layout.fillWidth: true showPlaceHolder: allowEditMode showDeleteIcon: allowEditMode onTagRemoved: tagRemovedClicked(index) onTagClicked: control.tagClicked(tagsList.model.get(index).tag) - colorScheme.textColor: control.colorScheme.textColor - colorScheme.backgroundColor: control.colorScheme.backgroundColor + Kirigami.Theme.textColor: control.colorScheme.textColor + Kirigami.Theme.backgroundColor: control.colorScheme.backgroundColor MouseArea { anchors.fill: parent z: tagsList.z -1 propagateComposedEvents: true onClicked: if(allowEditMode) goEditMode() } } } } Item { Layout.fillHeight: true Layout.fillWidth: true visible: editMode RowLayout { anchors.fill: parent spacing: 0 Item { Layout.fillHeight: true Layout.fillWidth:true Layout.leftMargin: space.medium // Layout.margins: space.big TextInput { id: editTagsEntry anchors.fill: parent horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter selectByMouse: !isMobile focus: true wrapMode: TextEdit.Wrap color: colorScheme.textColor selectionColor: highlightColor selectedTextColor: highlightedTextColor onFocusChanged: editMode = false onAccepted: saveTags() } } Maui.ToolButton { Layout.alignment: Qt.AlignLeft iconName: "checkbox" onClicked: saveTags() } } } } function clear() { // tagsList.model.clear() } function goEditMode() { var currentTags = [] for(var i = 0 ; i < tagsList.count; i++) currentTags.push(list.get(i).tag) editTagsEntry.text = currentTags.join(", ") editMode = true editTagsEntry.forceActiveFocus() } function saveTags() { tagsEdited(getTags()) editMode = false } function getTags() { var tags = [] if(editTagsEntry.text.trim().length > 0) { var list = editTagsEntry.text.split(",") if(list.length > 0) for(var i in list) tags.push(list[i].trim()) } return tags } - } diff --git a/src/controls/TagsDialog.qml b/src/controls/TagsDialog.qml index 6c8f54b..c445721 100644 --- a/src/controls/TagsDialog.qml +++ b/src/controls/TagsDialog.qml @@ -1,196 +1,196 @@ 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 onAccepted: setTags() onRejected: close() headBar.plegable: false headBar.leftContent: Maui.ToolButton { iconName: "view-sort" tooltipText: qsTr("Sort by...") onClicked: sortMenu.popup() - Maui.Menu + Menu { id: sortMenu - Maui.MenuItem + MenuItem { text: qsTr("Name") checkable: true checked: _tagsList.sortBy === TagsList.TAG onTriggered: _tagsList.sortBy = TagsList.TAG } - Maui.MenuItem + 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 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: Maui.ToolButton { iconName: "view-refresh" tooltipText: 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/private/AccountsHelper.qml b/src/controls/private/AccountsHelper.qml index bc2b730..c5c3b2a 100644 --- a/src/controls/private/AccountsHelper.qml +++ b/src/controls/private/AccountsHelper.qml @@ -1,169 +1,169 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.6 as Kirigami import org.kde.mauikit 1.0 as Maui import SyncingModel 1.0 import SyncingList 1.0 Maui.Dialog { id: control defaultButtons: false maxHeight: 300* unit maxWidth: maxHeight property alias model : _syncingModel property alias list : _syncingList Maui.SyncDialog { id: _syncDialog onAccepted: { control.addAccount(serverField.text, userField.text, passwordField.text); close(); } } footBar.margins: 0 - footBar.middleContent: Maui.Button + footBar.middleContent: Button { - colorScheme.textColor: "white" - colorScheme.backgroundColor: suggestedColor + Kirigami.Theme.textColor: "white" + Kirigami.Theme.backgroundColor: suggestedColor text: qsTr("Add account") onClicked: _syncDialog.open() } SyncingModel { id: _syncingModel list: _syncingList } SyncingList { id: _syncingList } Maui.Dialog { id: _removeDialog maxWidth: unit * 400 title: qsTr("Remove account?") message: qsTr("Are you sure you want to remove this account?") acceptButton.text: qsTr("Delete account") rejectButton.visible: false onAccepted: { var account = _syncingList.get(_listView.currentIndex) console.log(account.label) control.removeAccount(account.server, account.user) close() } - footBar.rightContent: Maui.Button + footBar.rightContent: Button { text: qsTr("Delete account and files") onClicked: { var account = _syncingList.get(_listView.currentIndex) control.removeAccountAndFiles(account.server, account.user) close() } } } - Maui.Menu + Menu { id: _menu // Maui.MenuItem // { // text: qsTr("Edit...") // onTriggered: // { // previewer.show(control.items[0].path) // close() // } // } // - Maui.MenuItem + MenuItem { text: qsTr("Remove...") - colorScheme.textColor: dangerColor + Kirigami.Theme.textColor: dangerColor onTriggered: _removeDialog.open() } } ListView { id: _listView anchors.fill: parent model: _syncingModel delegate: Maui.ListDelegate { id: delegate label: model.label radius: radiusV Connections { target: delegate onClicked: { _listView.currentIndex = index } onPressAndHold: { _listView.currentIndex = index _menu.popup() } onRightClicked: { _listView.currentIndex = index _menu.popup() } } } Maui.Holder { visible: _listView.count == 0 isMask: false isGif: false emojiSize: iconSizes.huge title: qsTr("No accounts yet!") body: qsTr("Start adding new accounts to sync your files, music, contacts, images, notes, etc...") } } function addAccount(server, user, password) { if(user.length) _syncingList.insert({server: server, user: user, password: password}) } function removeAccount(server, user) { if(server.length && user.length) _syncingList.removeAccount(server, user) } function removeAccountAndFiles(server, user) { if(server.length && user.length) _syncingList.removeAccountAndFiles(server, user) } } diff --git a/src/controls/private/TagList.qml b/src/controls/private/TagList.qml index 5634cca..a9c58fd 100644 --- a/src/controls/private/TagList.qml +++ b/src/controls/private/TagList.qml @@ -1,73 +1,74 @@ import QtQuick 2.0 import QtQuick.Controls 2.2 import "." +import org.kde.kirigami 2.6 as Kirigami import TagsList 1.0 import TagsModel 1.0 ListView { id: control /* Controlc color scheming */ ColorScheme {id: colorScheme} property alias colorScheme : colorScheme /***************************/ orientation: ListView.Horizontal clip: true spacing: contentMargins signal tagRemoved(int index) signal tagClicked(int index) boundsBehavior: isMobile ? Flickable.DragOverBounds : Flickable.StopAtBounds property string placeholderText: "Add tags..." property alias list : _tagsList property bool showPlaceHolder: true property bool showDeleteIcon: true TagsModel { id: _tagsModel list: _tagsList } TagsList { id: _tagsList } model: _tagsModel Label { height: parent.height width: parent.width verticalAlignment: Qt.AlignVCenter text: qsTr(control.placeholderText) opacity: 0.7 visible: count === 0 && showPlaceHolder - color: colorScheme.textColor + color: Kirigami.Theme.textColor font.pointSize: fontSizes.default } delegate: TagDelegate { id: delegate showDeleteIcon: control.showDeleteIcon - colorScheme.textColor: control.colorScheme.textColor + colorScheme.textColor: Kirigami.Theme.textColor Connections { target: delegate onRemoveTag: tagRemoved(index) onClicked: tagClicked(index) } } function populate(tags) { model.clear() for(var i in tags) model.append(tags[i]) } } diff --git a/src/fm/fm.cpp b/src/fm/fm.cpp index 9ff5693..25d6b03 100644 --- a/src/fm/fm.cpp +++ b/src/fm/fm.cpp @@ -1,792 +1,788 @@ /* * 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. */ #include "fm.h" #include "utils.h" #include "tagging.h" #include "syncing.h" #include #include #include #include #include #include #include #include #if defined(Q_OS_ANDROID) #include "mauiandroid.h" #else #include "mauikde.h" #include #include #endif /* FM *FM::instance = nullptr; FM* FM::getInstance() { if(!instance) { instance = new FM(); qDebug() << "getInstance(): First instance\n"; instance->init(); return instance; } else { qDebug()<< "getInstance(): previous instance\n"; return instance; } }*/ -void FM::init() -{ - this->tag = Tagging::getInstance(); - this->sync = new Syncing(this); + +FM::FM(QObject *parent) : FMDB(parent), +sync(new Syncing(this)), +tag(Tagging::getInstance()) +{ connect(this->sync, &Syncing::listReady, [this](const FMH::MODEL_LIST &list, const QString &url) { emit this->cloudServerContentReady(list, url); }); connect(this->sync, &Syncing::itemReady, [this](const FMH::MODEL &item, const QString &url, const Syncing::SIGNAL_TYPE &signalType) { switch(signalType) { case Syncing::SIGNAL_TYPE::OPEN: this->openUrl(item[FMH::MODEL_KEY::PATH]); break; case Syncing::SIGNAL_TYPE::DOWNLOAD: emit this->cloudItemReady(item, url); break; case Syncing::SIGNAL_TYPE::COPY: { QVariantMap data; for(auto key : item.keys()) data.insert(FMH::MODEL_NAME[key], item[key]); this->copy(QVariantList {data}, this->sync->getCopyTo()); break; } default: return; } }); connect(this->sync, &Syncing::error, [this](const QString &message) { emit this->warningMessage(message); }); connect(this->sync, &Syncing::progress, [this](const int &percent) { emit this->loadProgress(percent); }); connect(this->sync, &Syncing::dirCreated, [this](const FMH::MODEL &dir, const QString &url) { emit this->newItem(dir, url); }); connect(this->sync, &Syncing::uploadReady, [this](const FMH::MODEL &item, const QString &url) { emit this->newItem(item, url); }); } -FM::FM(QObject *parent) : FMDB(parent) -{ - this->init(); -} - FM::~FM() {} QVariantMap FM::toMap(const FMH::MODEL& model) { QVariantMap map; for(const auto &key : model.keys()) map.insert(FMH::MODEL_NAME[key], model[key]); return map; } FMH::MODEL FM::toModel(const QVariantMap& map) { FMH::MODEL model; for(const auto &key : map.keys()) model.insert(FMH::MODEL_NAME_KEY[key], map[key].toString()); return model; } FMH::MODEL_LIST FM::packItems(const QStringList &items, const QString &type) { FMH::MODEL_LIST data; for(const auto &path : items) if(UTIL::fileExists(path)) { auto model = FMH::getFileInfoModel(path); model.insert(FMH::MODEL_KEY::TYPE, type); data << model; } return data; } QVariantList FM::get(const QString &queryTxt) { QVariantList mapList; auto query = this->getQuery(queryTxt); if(query.exec()) { while(query.next()) { QVariantMap data; for(auto key : FMH::MODEL_NAME.keys()) if(query.record().indexOf(FMH::MODEL_NAME[key]) > -1) data[FMH::MODEL_NAME[key]] = query.value(FMH::MODEL_NAME[key]).toString(); mapList<< data; } }else qDebug()<< query.lastError()<< query.lastQuery(); return mapList; } FMH::MODEL_LIST FM::getPathContent(const QString& path, const bool &hidden, const bool &onlyDirs, const QStringList& filters, const QDirIterator::IteratorFlags &iteratorFlags) { FMH::MODEL_LIST content; if (FM::isDir(path)) { QDir::Filters dirFilter; dirFilter = (onlyDirs ? QDir::AllDirs | QDir::NoDotDot | QDir::NoDot : QDir::Files | QDir::AllDirs | QDir::NoDotDot | QDir::NoDot); if(hidden) dirFilter = dirFilter | QDir::Hidden | QDir::System; QDirIterator it (path, filters, dirFilter, iteratorFlags); while (it.hasNext()) { auto url = it.next(); content << FMH::getFileInfoModel(url); } } return content; } FMH::MODEL_LIST FM::getAppsContent(const QString& path) { FMH::MODEL_LIST res; #if (defined (Q_OS_LINUX) && !defined (Q_OS_ANDROID)) if(path.startsWith(FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::APPS_PATH]+"/")) return MAUIKDE::getApps(QString(path).replace(FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::APPS_PATH]+"/","")); else return MAUIKDE::getApps(); #endif return res; } FMH::MODEL_LIST FM::getDefaultPaths() { return packItems(FMH::defaultPaths, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::PLACES_PATH]); } FMH::MODEL_LIST FM::getAppsPath() { #ifdef Q_OS_ANDROID return FMH::MODEL_LIST(); #endif return FMH::MODEL_LIST { FMH::MODEL { {FMH::MODEL_KEY::ICON, "system-run"}, {FMH::MODEL_KEY::LABEL, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::APPS_PATH]}, {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::APPS_PATH]+"/"}, {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::PLACES_PATH]} } }; } FMH::MODEL_LIST FM::search(const QString& query, const QString &path, const bool &hidden, const bool &onlyDirs, const QStringList &filters) { FMH::MODEL_LIST content; if (FM::isDir(path)) { QDir::Filters dirFilter; dirFilter = (onlyDirs ? QDir::AllDirs | QDir::NoDotDot | QDir::NoDot : QDir::Files | QDir::AllDirs | QDir::NoDotDot | QDir::NoDot); if(hidden) dirFilter = dirFilter | QDir::Hidden | QDir::System; QDirIterator it (path, filters, dirFilter, QDirIterator::Subdirectories); while (it.hasNext()) { auto url = it.next(); auto info = it.fileInfo(); qDebug()<< info.completeBaseName() << info.completeBaseName().contains(query); if(info.completeBaseName().contains(query, Qt::CaseInsensitive)) { content << FMH::getFileInfoModel(url); } } } qDebug()<< content; return content; } // FMH::MODEL_LIST FM::getDevices() // { // FMH::MODEL_LIST drives; // // #if defined(Q_OS_ANDROID) // drives << packItems({MAUIAndroid::sdDir()}, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::DRIVES_PATH]); // return drives; // #else // KFilePlacesModel model; // for(const auto &i : model.groupIndexes(KFilePlacesModel::GroupType::RemoteType)) // { // drives << FMH::MODEL{ // {FMH::MODEL_KEY::NAME, model.text(i)}, // {FMH::MODEL_KEY::LABEL, model.text(i)}, // {FMH::MODEL_KEY::PATH, model.url(i).toString()}, // {FMH::MODEL_KEY::ICON, model.icon(i).name()}, // {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::DRIVES_PATH]}, // }; // } // // #endif // // // auto devices = QStorageInfo::mountedVolumes(); // // for(auto device : devices) // // { // // if(device.isValid() && !device.isReadOnly()) // // { // // QVariantMap drive = // // { // // {FMH::MODEL_NAME[FMH::MODEL_KEY::ICON], "drive-harddisk"}, // // {FMH::MODEL_NAME[FMH::MODEL_KEY::LABEL], device.displayName()}, // // {FMH::MODEL_NAME[FMH::MODEL_KEY::PATH], device.rootPath()}, // // {FMH::MODEL_NAME[FMH::MODEL_KEY::TYPE], FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::DRIVES]} // // }; // // // // drives << drive; // // } // // } // // // for(auto device : QDir::drives()) // // { // // QVariantMap drive = // // { // // {"iconName", "drive-harddisk"}, // // {"label", device.baseName()}, // // {"path", device.absoluteFilePath()}, // // {"type", "Drives"} // // }; // // // drives << drive; // // } // // return drives; // } FMH::MODEL_LIST FM::getTags(const int &limit) { Q_UNUSED(limit); FMH::MODEL_LIST data; if(this->tag) { for(auto tag : this->tag->getUrlsTags(false)) { qDebug()<< "TAG << "<< tag; auto label = tag.toMap().value(TAG::KEYMAP[TAG::KEYS::TAG]).toString(); data << FMH::MODEL { {FMH::MODEL_KEY::PATH, label}, {FMH::MODEL_KEY::ICON, "tag"}, {FMH::MODEL_KEY::LABEL, label}, {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::TAGS_PATH]} }; } } return data; } bool FM::getCloudServerContent(const QString &path, const QStringList &filters, const int &depth) { auto user = path.split("/")[1]; auto data = this->get(QString("select * from clouds where user = '%1'").arg(user)); if(data.isEmpty()) return false; auto map = data.first().toMap(); user = map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString(); auto server = map[FMH::MODEL_NAME[FMH::MODEL_KEY::SERVER]].toString(); auto password = map[FMH::MODEL_NAME[FMH::MODEL_KEY::PASSWORD]].toString(); this->sync->setCredentials(server, user, password); this->sync->listContent(path, filters, depth); return true; } FMH::MODEL_LIST FM::getCloudAccounts() { auto accounts = this->get("select * from clouds"); FMH::MODEL_LIST res; for(auto account : accounts) { auto map = account.toMap(); res << FMH::MODEL { {FMH::MODEL_KEY::PATH, QStringLiteral("Cloud/")+map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString()}, {FMH::MODEL_KEY::ICON, "folder-cloud"}, {FMH::MODEL_KEY::LABEL, map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString()}, {FMH::MODEL_KEY::USER, map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString()}, {FMH::MODEL_KEY::SERVER, map[FMH::MODEL_NAME[FMH::MODEL_KEY::SERVER]].toString()}, {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::CLOUD_PATH]}}; } return res; } void FM::createCloudDir(const QString &path, const QString &name) { qDebug()<< "trying to create folder at"<< path; this->sync->createDir(path, name); } void FM::openCloudItem(const QVariantMap &item) { qDebug()<< item; FMH::MODEL data; for(auto key : item.keys()) data.insert(FMH::MODEL_NAME_KEY[key], item[key].toString()); this->sync->resolveFile(data, Syncing::SIGNAL_TYPE::OPEN); } void FM::getCloudItem(const QVariantMap &item) { qDebug()<< item; FMH::MODEL data; for(auto key : item.keys()) data.insert(FMH::MODEL_NAME_KEY[key], item[key].toString()); this->sync->resolveFile(data, Syncing::SIGNAL_TYPE::DOWNLOAD); } QVariantList FM::getCloudAccountsList() { QVariantList res; auto data = this->getCloudAccounts(); for(auto item : data) { QVariantMap map; for(auto key : item.keys()) map.insert(FMH::MODEL_NAME[key], item[key]); res << map; } return res; } bool FM::addCloudAccount(const QString &server, const QString &user, const QString &password) { QVariantMap account = { {FMH::MODEL_NAME[FMH::MODEL_KEY::SERVER], server}, {FMH::MODEL_NAME[FMH::MODEL_KEY::USER], user}, {FMH::MODEL_NAME[FMH::MODEL_KEY::PASSWORD], password} }; if(this->insert(FMH::TABLEMAP[FMH::TABLE::CLOUDS], account)) { emit this->cloudAccountInserted(user); return true; } return false; } bool FM::removeCloudAccount(const QString &server, const QString &user) { FMH::DB account = { {FMH::MODEL_KEY::SERVER, server}, {FMH::MODEL_KEY::USER, user}, }; if(this->remove(FMH::TABLEMAP[FMH::TABLE::CLOUDS], account)) { emit this->cloudAccountRemoved(user); return true; } return false; } QString FM::resolveUserCloudCachePath(const QString &server, const QString &user) { return FMH::CloudCachePath+"opendesktop/"+user; } QString FM::resolveLocalCloudPath(const QString& path) { return QString(path).replace(FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::CLOUD_PATH]+"/"+this->sync->getUser(), ""); } FMH::MODEL_LIST FM::getTagContent(const QString &tag) { FMH::MODEL_LIST content; qDebug()<< "TAG CONTENT FOR TAG"<< tag; for(auto data : this->tag->getUrls(tag, false)) { const auto url = data.toMap().value(TAG::KEYMAP[TAG::KEYS::URL]).toString(); auto item = FMH::getFileInfoModel(url); content << item; } return content; } QVariantMap FM::getDirInfo(const QString &path, const QString &type) { return FMH::getDirInfo(path, type); } QVariantMap FM::getFileInfo(const QString &path) { return FMH::getFileInfo(path); } bool FM::isDefaultPath(const QString &path) { return FMH::defaultPaths.contains(path); } QString FM::parentDir(const QString &path) { auto dir = QDir(path); dir.cdUp(); return dir.absolutePath(); } bool FM::isDir(const QString &path) { return QFileInfo(path).isDir(); } bool FM::isApp(const QString& path) { return /*QFileInfo(path).isExecutable() ||*/ path.endsWith(".desktop"); } bool FM::isCloud(const QString &path) { return path.startsWith(FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::CLOUD_PATH]); } bool FM::fileExists(const QString &path) { return FMH::fileExists(path); } void FM::saveSettings(const QString &key, const QVariant &value, const QString &group) { UTIL::saveSettings(key, value, group); } QVariant FM::loadSettings(const QString &key, const QString &group, const QVariant &defaultValue) { return UTIL::loadSettings(key, group, defaultValue); } QString FM::formatSize(const int &size) { QLocale locale; return locale.formattedDataSize(size); } QString FM::formatDate(const QString &dateStr, const QString &format, const QString &initFormat) { QDateTime date; if( initFormat.isEmpty() ) date = QDateTime::fromString(dateStr, Qt::TextDate); else date = QDateTime::fromString(dateStr, initFormat); return date.toString(format); } QString FM::homePath() { return FMH::HomePath; } bool FM::cut(const QVariantList &data, const QString &where) { FMH::MODEL_LIST items; for(auto k : data) { auto map = k.toMap(); FMH::MODEL model; for(auto key : map.keys()) model.insert(FMH::MODEL_NAME_KEY[key], map[key].toString()); items << model; } for(auto item : items) { auto path = item[FMH::MODEL_KEY::PATH]; if(this->isCloud(path)) { this->sync->setCopyTo(where); this->sync->resolveFile(item, Syncing::SIGNAL_TYPE::COPY); }else if(UTIL::fileExists(path)) { QFile file(path); file.rename(where+"/"+QFileInfo(path).fileName()); } } return true; } bool FM::copy(const QVariantList &data, const QString &where) { FMH::MODEL_LIST items; for(auto k : data) { auto map = k.toMap(); FMH::MODEL model; for(auto key : map.keys()) model.insert(FMH::MODEL_NAME_KEY[key], map[key].toString()); items << model; } QStringList cloudPaths; for(auto item : items) { auto path = item[FMH::MODEL_KEY::PATH]; if(this->isDir(path)) { auto state = copyPath(path, where+"/"+QFileInfo(path).fileName(), false); if(!state) return false; }else if(this->isCloud(path)) { this->sync->setCopyTo(where); this->sync->resolveFile(item, Syncing::SIGNAL_TYPE::COPY); }else if(UTIL::fileExists(path)) { QFile file(path); qDebug()<< path << "is a file" << where; if(this->isCloud(where)) cloudPaths << path; else file.copy(where+"/"+FMH::getFileInfoModel(path)[FMH::MODEL_KEY::LABEL]); } } if(!cloudPaths.isEmpty()) { qDebug()<<"UPLOAD QUEUE" << cloudPaths; const auto firstPath = cloudPaths.takeLast(); this->sync->setUploadQueue(cloudPaths); if(where.split("/").last().contains(".")) { QStringList whereList = where.split("/"); whereList.removeLast(); auto whereDir = whereList.join("/"); qDebug()<< "Trying ot copy to cloud" << where << whereDir; this->sync->upload(this->resolveLocalCloudPath(whereDir), firstPath); } else this->sync->upload(this->resolveLocalCloudPath(where), firstPath); } return true; } bool FM::copyPath(QString sourceDir, QString destinationDir, bool overWriteDirectory) { QDir originDirectory(sourceDir); if (!originDirectory.exists()) return false; QDir destinationDirectory(destinationDir); if(destinationDirectory.exists() && !overWriteDirectory) return false; else if(destinationDirectory.exists() && overWriteDirectory) destinationDirectory.removeRecursively(); originDirectory.mkpath(destinationDir); foreach(QString directoryName, originDirectory.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { QString destinationPath = destinationDir + "/" + directoryName; originDirectory.mkpath(destinationPath); copyPath(sourceDir + "/" + directoryName, destinationPath, overWriteDirectory); } foreach (QString fileName, originDirectory.entryList(QDir::Files)) { QFile::copy(sourceDir + "/" + fileName, destinationDir + "/" + fileName); } /*! Possible race-condition mitigation? */ QDir finalDestination(destinationDir); finalDestination.refresh(); if(finalDestination.exists()) return true; return false; } bool FM::removeFile(const QString &path) { if(QFileInfo(path).isDir()) return removeDir(path); else return QFile(path).remove(); } bool FM::removeDir(const QString &path) { bool result = true; QDir dir(path); if (dir.exists(path)) { Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) { if (info.isDir()) { result = removeDir(info.absoluteFilePath()); } else { result = QFile::remove(info.absoluteFilePath()); } if (!result) { return result; } } result = dir.rmdir(path); } return result; } bool FM::rename(const QString &path, const QString &name) { QFile file(path); auto url = QFileInfo(path).dir().absolutePath(); qDebug()<< "RENAME FILE TO:" << path << name << url; return file.rename(url+"/"+name); } bool FM::createDir(const QString &path, const QString &name) { return QDir(path).mkdir(name); } bool FM::createFile(const QString &path, const QString &name) { QFile file(path + "/" + name); if(file.open(QIODevice::ReadWrite)) { file.close(); return true; } return false; } bool FM::openUrl(const QString &url) { return QDesktopServices::openUrl(QUrl::fromUserInput(url)); } void FM::openLocation(const QStringList &urls) { for(auto url : urls) QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(url).dir().absolutePath())); } void FM::runApplication(const QString& exec) { #if (defined (Q_OS_LINUX) && !defined (Q_OS_ANDROID)) return MAUIKDE::launchApp(exec); #endif } QVariantMap FM::dirConf(const QString &path) { return FMH::dirConf(path); } void FM::setDirConf(const QString &path, const QString &group, const QString &key, const QVariant &value) { FMH::setDirConf(path, group, key, value); } diff --git a/src/fm/fm.h b/src/fm/fm.h index 2e1963c..46ce96f 100644 --- a/src/fm/fm.h +++ b/src/fm/fm.h @@ -1,131 +1,129 @@ #ifndef FM_H #define FM_H #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 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); /*** START STATIC METHODS ***/ static FMH::MODEL_LIST search(const QString &query, const QString &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); FMH::MODEL_LIST static getPathContent(const QString &path, const bool &hidden = false, const bool &onlyDirs = false, const QStringList &filters = QStringList(), const QDirIterator::IteratorFlags &iteratorFlags = QDirIterator::NoIteratorFlags); FMH::MODEL_LIST static getAppsContent(const QString &path); static bool copyPath(QString sourceDir, QString destinationDir, bool overWriteDirectory); static bool removeDir(const QString &path); static QString resolveUserCloudCachePath(const QString &server, const QString &user); QString resolveLocalCloudPath(const QString &path); static QVariantMap toMap(const FMH::MODEL &model); static FMH::MODEL toModel(const QVariantMap &map); /*** END STATIC METHODS ***/ private: Tagging *tag; // static FM* instance; - - void init(); 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 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 QString parentDir(const QString &path); static QVariantMap getDirInfo(const QString &path, const QString &type); static QVariantMap getFileInfo(const QString &path); static bool isDefaultPath(const QString &path); static bool isDir(const QString &path); static bool isApp(const QString &path); static bool isCloud(const QString &path); static bool fileExists(const QString &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 QString &path); static void setDirConf(const QString &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 QString &path); static bool rename(const QString &path, const QString &name); static bool createDir(const QString &path, const QString &name); static bool createFile(const QString &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/placeslist.cpp b/src/fm/placeslist.cpp index e766c23..8b5adda 100644 --- a/src/fm/placeslist.cpp +++ b/src/fm/placeslist.cpp @@ -1,227 +1,227 @@ /* * * Copyright (C) 2018 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 "placeslist.h" #include "fm.h" #include #include #include #include PlacesList::PlacesList(QObject *parent) : ModelList(parent), fm(new FM(this)), model(new KFilePlacesModel(this)), watcher(new QFileSystemWatcher(this)) { connect(watcher, &QFileSystemWatcher::directoryChanged, [this](const QString &path) { if(this->count.contains(path)) { const auto oldCount = this->count[path]; const auto index = this->indexOf(path); const auto newCount = FMH::getFileInfoModel(path)[FMH::MODEL_KEY::COUNT].toInt(); const auto count = newCount - oldCount; this->list[index][FMH::MODEL_KEY::COUNT] = QString::number(count); emit this->updateModel(index, {FMH::MODEL_KEY::COUNT}); } }); connect(fm, &FM::cloudAccountInserted, this, &PlacesList::reset); connect(fm, &FM::cloudAccountRemoved, this, &PlacesList::reset); connect(this, &PlacesList::groupsChanged, this, &PlacesList::reset); this->setList(); } void PlacesList::watchPath(const QString& path) { if(path.isEmpty() || !FMH::fileExists(path)) return; this->watcher->addPath(path); } PlacesList::~PlacesList() {} FMH::MODEL_LIST PlacesList::items() const { return this->list; } -static FMH::MODEL modelPlaceInfo(const KFilePlacesModel *model, const QModelIndex &index, const FMH::PATHTYPE_KEY &type) +static FMH::MODEL modelPlaceInfo(const KFilePlacesModel &model, const QModelIndex &index, const FMH::PATHTYPE_KEY &type) { return FMH::MODEL { - {FMH::MODEL_KEY::PATH, model->url(index).toString().replace("file://", "")}, - {FMH::MODEL_KEY::URL, model->url(index).toString().replace("file://", "")}, - {FMH::MODEL_KEY::ICON, model->icon(index).name()}, - {FMH::MODEL_KEY::LABEL, model->text(index)}, - {FMH::MODEL_KEY::NAME, model->text(index)}, + {FMH::MODEL_KEY::PATH, model.url(index).toString().replace("file://", "")}, + {FMH::MODEL_KEY::URL, model.url(index).toString().replace("file://", "")}, + {FMH::MODEL_KEY::ICON, model.icon(index).name()}, + {FMH::MODEL_KEY::LABEL, model.text(index)}, + {FMH::MODEL_KEY::NAME, model.text(index)}, {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_NAME[type]} }; } -static FMH::MODEL_LIST getGroup(const KFilePlacesModel *model, const FMH::PATHTYPE_KEY &type) +static FMH::MODEL_LIST getGroup(const KFilePlacesModel &model, const FMH::PATHTYPE_KEY &type) { - const auto group = model->groupIndexes(static_cast(type)); + const auto group = model.groupIndexes(static_cast(type)); return std::accumulate(group.begin(), group.end(), FMH::MODEL_LIST(), [&model, &type](FMH::MODEL_LIST &list, const QModelIndex &index) -> FMH::MODEL_LIST { list << modelPlaceInfo(model, index, type); return list; }); } void PlacesList::setList() { this->list.clear(); for(const auto &group : this->groups) switch(group) { case FMH::PATHTYPE_KEY::PLACES_PATH: - this->list << getGroup(this->model, FMH::PATHTYPE_KEY::PLACES_PATH); + this->list << getGroup(*this->model, FMH::PATHTYPE_KEY::PLACES_PATH); break; case FMH::PATHTYPE_KEY::APPS_PATH: this->list << FM::getAppsPath(); break; case FMH::PATHTYPE_KEY::DRIVES_PATH: - this->list << getGroup(this->model, FMH::PATHTYPE_KEY::DRIVES_PATH); + this->list << getGroup(*this->model, FMH::PATHTYPE_KEY::DRIVES_PATH); break; case FMH::PATHTYPE_KEY::REMOTE_PATH: - this->list << getGroup(this->model, FMH::PATHTYPE_KEY::REMOTE_PATH); + this->list << getGroup(*this->model, FMH::PATHTYPE_KEY::REMOTE_PATH); break; case FMH::PATHTYPE_KEY::REMOVABLE_PATH: - this->list << getGroup(this->model, FMH::PATHTYPE_KEY::REMOVABLE_PATH); + this->list << getGroup(*this->model, FMH::PATHTYPE_KEY::REMOVABLE_PATH); break; case FMH::PATHTYPE_KEY::TAGS_PATH: this->list << this->fm->getTags(); break; case FMH::PATHTYPE_KEY::CLOUD_PATH: this->list << this->fm->getCloudAccounts(); break; } this->setCount(); } void PlacesList::setCount() { this->watcher->removePaths(this->watcher->directories()); for(auto &data : this->list) { const auto path = data[FMH::MODEL_KEY::PATH]; if(FM::isDir(path)) { data.insert(FMH::MODEL_KEY::COUNT, "0"); const auto count = FMH::getFileInfoModel(path)[FMH::MODEL_KEY::COUNT]; this->count.insert(path, count.toInt()); this->watchPath(path); } } } int PlacesList::indexOf(const QString& path) { const auto index = std::find_if(this->list.begin(), this->list.end(), [&path](const FMH::MODEL &item) -> bool { return item[FMH::MODEL_KEY::PATH] == path; }); return std::distance(this->list.begin(), index); } void PlacesList::reset() { emit this->preListChanged(); this->setList(); emit this->postListChanged(); } QList PlacesList::getGroups() const { return this->groups; } void PlacesList::setGroups(const QList &value) { if(this->groups == value) return; this->groups = value; emit this->groupsChanged(); } QVariantMap PlacesList::get(const int& index) const { if(index >= this->list.size() || index < 0) return QVariantMap(); QVariantMap res; const auto model = this->list.at(index); for(const auto &key : model.keys()) res.insert(FMH::MODEL_NAME[key], model[key]); return res; } void PlacesList::refresh() { this->reset(); } void PlacesList::clearBadgeCount(const int& index) { this->list[index][FMH::MODEL_KEY::COUNT] = "0"; emit this->updateModel(index, {FMH::MODEL_KEY::COUNT}); } void PlacesList::addPlace(const QString& path) { const auto it = std::find_if(this->list.rbegin(), this->list.rend(), [](const FMH::MODEL &item) -> bool{ return item[FMH::MODEL_KEY::TYPE] == FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::PLACES_PATH]; }); const auto index = std::distance(it, this->list.rend()); qDebug()<< "trying to add path to places" << path<< QDir(path).dirName(); emit this->preItemAppendedAt(index); const auto url = QStringLiteral("file://")+path; this->model->addPlace(QDir(path).dirName(), url); - this->list.insert(index, modelPlaceInfo(this->model, this->model->closestItem(QUrl(url)), FMH::PATHTYPE_KEY::PLACES_PATH)); + this->list.insert(index, modelPlaceInfo(*this->model, this->model->closestItem(QUrl(url)), FMH::PATHTYPE_KEY::PLACES_PATH)); emit this->postItemAppended(); } void PlacesList::removePlace(const int& index) { emit this->preItemRemoved(index); this->model->removePlace(this->model->index(index, 0)); this->list.removeAt(index); emit this->postItemRemoved(); } diff --git a/src/mauikit.cpp b/src/mauikit.cpp index c482945..81d7ef9 100644 --- a/src/mauikit.cpp +++ b/src/mauikit.cpp @@ -1,185 +1,185 @@ /* * 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. */ #include "mauikit.h" #include #include #include "fm.h" #include "fmh.h" #include "basemodel.h" #include "modellist.h" #include "placeslist.h" #include "fmlist.h" #include "syncingmodel.h" #include "syncinglist.h" #include "tagsmodel.h" #include "tagslist.h" #include "storemodel.h" #include "storelist.h" #include "handy.h" #include "documenthandler.h" #include "mauiapp.h" #ifdef Q_OS_ANDROID #include "mauiandroid.h" #include #else #include "mauikde.h" #endif QUrl MauiKit::componentUrl(const QString &fileName) const { #ifdef MAUI_APP return QUrl(QStringLiteral("qrc:/maui/kit/") + fileName); #else return QUrl(resolveFileUrl(fileName)); #endif } void MauiKit::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("org.kde.mauikit")); qmlRegisterSingletonType(componentUrl(QStringLiteral("Style.qml")), uri, 1, 0, "Style"); qmlRegisterType(componentUrl(QStringLiteral("ToolBar.qml")), uri, 1, 0, "ToolBar"); // #if QT_VERSION == QT_VERSION_CHECK(5, 12, 0) #ifdef Q_OS_ANDROID qmlRegisterType(componentUrl(QStringLiteral("ToolButton2.qml")), uri, 1, 0, "ToolButton"); #else qmlRegisterType(componentUrl(QStringLiteral("ToolButton.qml")), uri, 1, 0, "ToolButton"); #endif qmlRegisterType(componentUrl(QStringLiteral("ApplicationWindow.qml")), uri, 1, 0, "ApplicationWindow"); qmlRegisterType(componentUrl(QStringLiteral("Page.qml")), uri, 1, 0, "Page"); qmlRegisterType(componentUrl(QStringLiteral("ShareDialog.qml")), uri, 1, 0, "ShareDialog"); qmlRegisterType(componentUrl(QStringLiteral("PieButton.qml")), uri, 1, 0, "PieButton"); qmlRegisterType(componentUrl(QStringLiteral("SideBar.qml")), uri, 1, 0, "SideBar"); qmlRegisterType(componentUrl(QStringLiteral("Holder.qml")), uri, 1, 0, "Holder"); qmlRegisterType(componentUrl(QStringLiteral("Drawer.qml")), uri, 1, 0, "Drawer"); qmlRegisterType(componentUrl(QStringLiteral("GlobalDrawer.qml")), uri, 1, 0, "GlobalDrawer"); qmlRegisterType(componentUrl(QStringLiteral("ListDelegate.qml")), uri, 1, 0, "ListDelegate"); qmlRegisterType(componentUrl(QStringLiteral("SelectionBar.qml")), uri, 1, 0, "SelectionBar"); qmlRegisterType(componentUrl(QStringLiteral("IconDelegate.qml")), uri, 1, 0, "IconDelegate"); qmlRegisterType(componentUrl(QStringLiteral("LabelDelegate.qml")), uri, 1, 0, "LabelDelegate"); qmlRegisterType(componentUrl(QStringLiteral("NewDialog.qml")), uri, 1, 0, "NewDialog"); qmlRegisterType(componentUrl(QStringLiteral("Dialog.qml")), uri, 1, 0, "Dialog"); - qmlRegisterType(componentUrl(QStringLiteral("Button.qml")), uri, 1, 0, "Button"); +// qmlRegisterType(componentUrl(QStringLiteral("Button.qml")), uri, 1, 0, "Button"); qmlRegisterType(componentUrl(QStringLiteral("AboutDialog.qml")), uri, 1, 0, "AboutDialog"); qmlRegisterType(componentUrl(QStringLiteral("Popup.qml")), uri, 1, 0, "Popup"); qmlRegisterType(componentUrl(QStringLiteral("TextField.qml")), uri, 1, 0, "TextField"); qmlRegisterType(componentUrl(QStringLiteral("SearchBar.qml")), uri, 1, 0, "SearchBar"); qmlRegisterType(componentUrl(QStringLiteral("TagsBar.qml")), uri, 1, 0, "TagsBar"); qmlRegisterType(componentUrl(QStringLiteral("TagsDialog.qml")), uri, 1, 0, "TagsDialog"); qmlRegisterType(componentUrl(QStringLiteral("Badge.qml")), uri, 1, 0, "Badge"); qmlRegisterType(componentUrl(QStringLiteral("GridView.qml")), uri, 1, 0, "GridView"); - qmlRegisterType(componentUrl(QStringLiteral("Item.qml")), uri, 1, 0, "Item"); - qmlRegisterType(componentUrl(QStringLiteral("Menu.qml")), uri, 1, 0, "Menu"); - qmlRegisterType(componentUrl(QStringLiteral("MenuItem.qml")), uri, 1, 0, "MenuItem"); +// qmlRegisterType(componentUrl(QStringLiteral("Item.qml")), uri, 1, 0, "Item"); +// qmlRegisterType(componentUrl(QStringLiteral("Menu.qml")), uri, 1, 0, "Menu"); +// qmlRegisterType(componentUrl(QStringLiteral("MenuItem.qml")), uri, 1, 0, "MenuItem"); qmlRegisterType(componentUrl(QStringLiteral("ColorsBar.qml")), uri, 1, 0, "ColorsBar"); qmlRegisterType(componentUrl(QStringLiteral("ComboBox.qml")), uri, 1, 0, "ComboBox"); qmlRegisterType(componentUrl(QStringLiteral("ImageViewer.qml")), uri, 1, 0, "ImageViewer"); - qmlRegisterType(componentUrl(QStringLiteral("ActionBar.qml")), uri, 1, 0, "ActionBar"); +// qmlRegisterType(componentUrl(QStringLiteral("ActionBar.qml")), uri, 1, 0, "ActionBar"); qmlRegisterType(componentUrl(QStringLiteral("private/TagList.qml")), uri, 1, 0, "TagList"); /** STORE CONTROLS **/ qmlRegisterType(componentUrl(QStringLiteral("private/StoreDelegate.qml")), uri, 1, 0, "StoreDelegate"); qmlRegisterType(componentUrl(QStringLiteral("Store.qml")), uri, 1, 0, "Store"); /** BROWSING CONTROLS **/ qmlRegisterType(componentUrl(QStringLiteral("ListBrowser.qml")), uri, 1, 0, "ListBrowser"); qmlRegisterType(componentUrl(QStringLiteral("GridBrowser.qml")), uri, 1, 0, "GridBrowser"); /** FM CONTROLS **/ qmlRegisterType(componentUrl(QStringLiteral("FileBrowser.qml")), uri, 1, 0, "FileBrowser"); qmlRegisterType(componentUrl(QStringLiteral("PlacesSidebar.qml")), uri, 1, 0, "PlacesSidebar"); qmlRegisterType(componentUrl(QStringLiteral("FilePreviewer.qml")), uri, 1, 0, "FilePreviewer"); qmlRegisterType(componentUrl(QStringLiteral("FileDialog.qml")), uri, 1, 0, "FileDialog"); qmlRegisterType(componentUrl(QStringLiteral("PathBar.qml")), uri, 1, 0, "PathBar"); qmlRegisterType(componentUrl(QStringLiteral("SyncDialog.qml")), uri, 1, 0, "SyncDialog"); qmlRegisterType(componentUrl(QStringLiteral("SyncDialog.qml")), uri, 1, 0, "SyncDialog"); /** EDITOR CONTROLS **/ qmlRegisterType(componentUrl(QStringLiteral("Editor.qml")), uri, 1, 0, "Editor"); #ifdef Q_OS_ANDROID qmlRegisterSingletonType(uri, 1, 0, "Android", [](QQmlEngine*, QJSEngine*) -> QObject* { MAUIAndroid *android = new MAUIAndroid; return android; }); #else qmlRegisterType(componentUrl(QStringLiteral("Terminal.qml")), uri, 1, 0, "Terminal"); qmlRegisterSingletonType(uri, 1, 0, "KDE", [](QQmlEngine*, QJSEngine*) -> QObject* { MAUIKDE *kde = new MAUIKDE; return kde; }); #endif qmlRegisterType(uri, 1, 0, "BaseModel"); //BASE MODEL qmlRegisterUncreatableType(uri, 1, 0, "ModelList", QStringLiteral("ModelList should not be created in QML")); qmlRegisterType(uri, 1, 0, "PlacesList"); qmlRegisterType(uri, 1, 0, "FMList"); qmlRegisterType("SyncingList", 1, 0, "SyncingList"); qmlRegisterType("SyncingModel", 1, 0, "SyncingModel"); qmlRegisterType("TagsList", 1, 0, "TagsList"); qmlRegisterType("TagsModel", 1, 0, "TagsModel"); qmlRegisterType("StoreList", 1, 0, "StoreList"); qmlRegisterType("StoreModel", 1, 0, "StoreModel"); // qmlRegisterType(uri, 1, 0, "App"); qmlRegisterType("DocumentHandler", 1, 0, "DocumentHandler"); qmlRegisterSingletonType(uri, 1, 0, "FM", [](QQmlEngine*, QJSEngine*) -> QObject* { auto fm = new FM(); return fm; }); qmlRegisterSingletonType(uri, 1, 0, "Handy", [](QQmlEngine*, QJSEngine*) -> QObject* { auto handy = new Handy; return handy; }); #ifdef Q_OS_ANDROID QIcon::setThemeSearchPaths({":/icons/luv-icon-theme"}); QIcon::setThemeName("Luv"); QQuickStyle::setStyle(":/style"); // #else // QQuickStyle::setStyle("maui-style"); #endif qmlProtectModule(uri, 1); }