diff --git a/src/controls/GridView.qml b/src/controls/GridView.qml index 608789e..dfcd868 100644 --- a/src/controls/GridView.qml +++ b/src/controls/GridView.qml @@ -1,190 +1,190 @@ /* * 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.10 import QtQuick.Layouts 1.3 import QtQuick.Controls.impl 2.3 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.7 as Kirigami import QtGraphicalEffects 1.0 Kirigami.ScrollablePage { id: control property int itemSize: 0 property int itemWidth : itemSize property int itemHeight : itemSize onItemWidthChanged : gridView.size_ = itemWidth property alias cellWidth: gridView.cellWidth property alias cellHeight: gridView.cellHeight property alias model : gridView.model property alias delegate : gridView.delegate property alias contentY: gridView.contentY property alias currentIndex : gridView.currentIndex property alias count : gridView.count property alias cacheBuffer : gridView.cacheBuffer property alias topMargin: gridView.topMargin property alias bottomMargin: gridView.bottomMargin property alias rightMargin: gridView.rightMargin property alias leftMarging: gridView.leftMargin property alias holder : _holder property alias gridView : gridView property bool centerContent: false //deprecrated property bool adaptContent: true signal areaClicked(var mouse) signal areaRightClicked() signal keyPress(var event) spacing: Maui.Style.space.medium Kirigami.Theme.colorSet: Kirigami.Theme.View padding: 0 - leftPadding: control.ScrollBar.visible ? padding : control.ScrollBar.width + leftPadding: padding rightPadding: padding topPadding: padding bottomPadding: padding focus: true keyboardNavigationEnabled: false Behavior on cellWidth { NumberAnimation { duration: Kirigami.Units.shortDuration easing.type: Easing.InQuad } } GridView { id: gridView //nasty trick property int size_ Component.onCompleted: { gridView.size_ = control.itemWidth } flow: GridView.FlowLeftToRight clip: true focus: true cellWidth: control.itemWidth cellHeight: control.itemHeight boundsBehavior: !Kirigami.Settings.isMobile? Flickable.StopAtBounds : Flickable.OvershootBounds flickableDirection: Flickable.AutoFlickDirection snapMode: GridView.NoSnap highlightMoveDuration: 0 interactive: Maui.Handy.isTouch onWidthChanged: if(control.adaptContent) control.adaptGrid() keyNavigationEnabled : true keyNavigationWraps : true Keys.onPressed: control.keyPress(event) Maui.Holder { id: _holder anchors.fill : parent } PinchArea { anchors.fill: parent z: -1 onPinchStarted: { console.log("pinch started") } onPinchUpdated: { } onPinchFinished: { console.log("pinch finished") resizeContent(pinch.scale) } MouseArea { anchors.fill: parent propagateComposedEvents: true acceptedButtons: Qt.RightButton | Qt.LeftButton onClicked: { control.forceActiveFocus() control.areaClicked(mouse) } onPressAndHold: control.areaRightClicked() // scrollGestureEnabled : false onWheel: { if (wheel.modifiers & Qt.ControlModifier) { if (wheel.angleDelta.y != 0) { var factor = 1 + wheel.angleDelta.y / 600; control.resizeContent(factor) } }else wheel.accepted = false } } } } function resizeContent(factor) { if(factor > 1) { gridView.size_ = gridView.size_ + 10 control.cellHeight = control.cellHeight + 10 } else { gridView.size_ = gridView.size_ - 10 control.cellHeight = control.cellHeight - 10 } if(adaptContent) control.adaptGrid() } function adaptGrid() { var amount = parseInt(gridView.width / (gridView.size_), 10) var leftSpace = parseInt(gridView.width - ( amount * (gridView.size_) ), 10) var size = parseInt((gridView.size_) + (parseInt(leftSpace/amount, 10)), 10) // size = size > gridView.size_? size : gridView.size_ control.cellWidth = size } } diff --git a/src/controls/ItemDelegate.qml b/src/controls/ItemDelegate.qml index 1f4b81c..b957324 100644 --- a/src/controls/ItemDelegate.qml +++ b/src/controls/ItemDelegate.qml @@ -1,155 +1,153 @@ /* * 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.12 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 default property alias content : _content.data property alias mouseArea : _mouseArea // property alias tapArea : _tapArea property bool draggable: false property bool isCurrentItem : false property int radius: Maui.Style.radiusV highlighted: isCurrentItem //override the itemdelegate default signals to allow dragging content signal pressed(var mouse) signal pressAndHold(var mouse) signal clicked(var mouse) signal rightClicked(var mouse) signal doubleClicked(var mouse) Kirigami.Theme.inherit: false Kirigami.Theme.backgroundColor: "transparent" hoverEnabled: !Kirigami.Settings.isMobile padding: 0 bottomPadding: padding rightPadding: padding leftPadding: padding topPadding: padding MouseArea { id: _mouseArea // enabled: !Kirigami.Settings.isMobile anchors.fill: parent acceptedButtons: Qt.RightButton | Qt.LeftButton property int startX property int startY onClicked: { if(!Kirigami.Settings.isMobile && mouse.button === Qt.RightButton) control.rightClicked(mouse) else control.clicked(mouse) } onDoubleClicked: control.doubleClicked(mouse) onPressed: { if(control.draggable && mouse.source !== Qt.MouseEventSynthesizedByQt) { drag.target = control control.grabToImage(function(result) { parent.Drag.imageSource = result.url }) }else drag.target = null startX = control.x startY = control.y control.pressed(mouse) } onReleased : { control.x = startX control.y = startY } onPressAndHold : control.pressAndHold(mouse) } // TapHandler // { // id: _tapArea // enabled: Kirigami.Settings.isMobile // acceptedButtons: Qt.RightButton // onSingleTapped: control.clicked(eventPoint) // onDoubleTapped: control.doubleClicked(eventPoint) // onLongPressed: control.pressAndHold(eventPoint) // } - contentItem: Item {} - - Item + contentItem: Item { - id: _content - - anchors - { - fill: control - topMargin: control.topPadding - bottomMargin: control.bottomPadding - leftMargin: control.leftPadding - rightMargin: control.rightPadding - margins: control.padding - } - } + id: _content + + anchors + { + fill: control + topMargin: control.topPadding + bottomMargin: control.bottomPadding + leftMargin: control.leftPadding + rightMargin: control.rightPadding + margins: control.padding + } + } background: Rectangle { anchors { fill: control topMargin: control.topPadding bottomMargin: control.bottomPadding leftMargin: control.leftPadding rightMargin: control.rightPadding margins: control.padding } Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration } } color: control.isCurrentItem || control.hovered ? Qt.rgba(control.Kirigami.Theme.highlightColor.r, control.Kirigami.Theme.highlightColor.g, control.Kirigami.Theme.highlightColor.b, 0.2) : control.Kirigami.Theme.backgroundColor radius: control.radius border.color: control.isCurrentItem ? control.Kirigami.Theme.highlightColor : "transparent" } } diff --git a/src/controls/ListBrowser.qml b/src/controls/ListBrowser.qml index 80c543a..1512755 100644 --- a/src/controls/ListBrowser.qml +++ b/src/controls/ListBrowser.qml @@ -1,177 +1,178 @@ /* * 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.10 import QtQuick.Controls 2.10 import QtQuick.Layouts 1.3 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.7 as Kirigami Kirigami.ScrollablePage { id: control property int itemSize : Maui.Style.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 listView: _listView property alias holder : _holder 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() signal keyPress(var event) spacing: 0 focus: true padding: 0 leftPadding: padding rightPadding: padding topPadding: padding - bottomPadding: padding + bottomPadding: padding Keys.enabled: false - Kirigami.Theme.colorSet: Kirigami.Theme.View + Kirigami.Theme.colorSet: Kirigami.Theme.View ListView { id: _listView + contentWidth: parent.width focus: true - clip: true - + clip: true spacing: Maui.Style.space.tiny snapMode: ListView.NoSnap boundsBehavior: !Kirigami.Settings.isMobile? Flickable.StopAtBounds : Flickable.OvershootBounds - interactive: Kirigami.Settings.isMobile + interactive: Maui.Handy.isTouch highlightFollowsCurrentItem: true highlightMoveDuration: 0 highlightResizeDuration : 0 keyNavigationEnabled : bool keyNavigationWraps : bool Keys.onPressed: control.keyPress(event) - +// ScrollBar.vertical: ScrollBar { } + Maui.Holder { id: _holder anchors.fill : parent } delegate: Maui.ListBrowserDelegate { id: delegate width: parent.width height: itemSize + Maui.Style.space.big leftPadding: Maui.Style.space.small rightPadding: Maui.Style.space.small padding: 0 showDetailsInfo: control.showDetailsInfo folderSize : itemSize showTooltip: true showEmblem: control.showEmblem keepEmblemOverlay : control.keepEmblemOverlay showThumbnails: showPreviewThumbnails rightEmblem: control.rightEmblem leftEmblem: control.leftEmblem 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.forceActiveFocus() control.areaClicked(mouse) } onPressAndHold: control.areaRightClicked() } } } diff --git a/src/controls/ListItemTemplate.qml b/src/controls/ListItemTemplate.qml index cb32e18..91a7aad 100644 --- a/src/controls/ListItemTemplate.qml +++ b/src/controls/ListItemTemplate.qml @@ -1,214 +1,214 @@ /* * 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.3 import QtGraphicalEffects 1.0 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui Item { id: control default property alias content: _layout.data - implicitHeight: _layout.implicitHeight - implicitWidth: _layout.implicitWidth +// implicitHeight: _layout.implicitHeight +// implicitWidth: _layout.implicitWidth property alias text1 : _label1.text property alias text2 : _label2.text property alias text3 : _label3.text property alias text4 : _label4.text property alias label1 : _label1 property alias label2 : _label2 property alias label3 : _label3 property alias label4 : _label4 property alias iconItem : _iconLoader.item property alias iconVisible : _iconContainer.visible property int iconSizeHint : Maui.Style.iconSizes.big property string imageSource property string iconSource property bool isCurrentItem: false property bool labelsVisible: true Component { id: _imgComponent Image { id: img anchors.centerIn: parent source: control.imageSource height: Math.min(parent.height, control.iconSizeHint) width: height sourceSize.width: width sourceSize.height: height horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter fillMode: Image.PreserveAspectCrop cache: true asynchronous: true smooth: !Kirigami.Settings.isMobile 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: Maui.Style.radiusV } } } } } Component { id: _iconComponent Kirigami.Icon { source: control.iconSource anchors.centerIn: parent fallback: "qrc:/assets/application-x-zerosize.svg" height: Math.min(parent.height, control.iconSizeHint) width: height } } RowLayout { id: _layout anchors.fill: parent spacing: Maui.Style.space.small Item { id: _iconContainer visible: (control.width > Kirigami.Units.gridUnit * 10) Layout.preferredWidth: control.labelsVisible && control.iconVisible && (iconSource.length > 0 || imageSource.length > 0) ? Math.max(control.height, control.iconSizeHint) : 0 Layout.fillHeight: true Layout.fillWidth: !control.labelsVisible Loader { id: _iconLoader height: control.iconSizeHint width: control.iconSizeHint anchors.centerIn: parent sourceComponent: _iconContainer.visible ? (control.imageSource ? _imgComponent : (control.iconSource ? _iconComponent : null) ): null } } ColumnLayout { visible: control.labelsVisible Layout.fillHeight: true Layout.fillWidth: true Layout.margins: Maui.Style.space.small Layout.leftMargin: _iconLoader.visible ? 0 : Maui.Style.space.small spacing: 0 Label { id: _label1 visible: text.length Layout.fillWidth: true Layout.fillHeight: true verticalAlignment: _label2.visible ? Qt.AlignBottom : Qt.AlignVCenter elide: Text.ElideMiddle wrapMode: Text.NoWrap color: control.Kirigami.Theme.textColor font.weight: Font.Normal font.pointSize: Maui.Style.fontSizes.default } Label { id: _label2 visible: text.length Layout.fillWidth: true Layout.fillHeight: true font.weight: Font.Normal font.pointSize: Maui.Style.fontSizes.medium wrapMode: Text.Wrap verticalAlignment: _label1.visible ? Qt.AlignTop : Qt.AlignVCenter elide: Text.ElideRight color: control.Kirigami.Theme.textColor opacity: control.isCurrentItem ? 0.8 : 0.6 } } ColumnLayout { visible: control.width > Kirigami.Units.gridUnit * 15 && control.labelsVisible Layout.fillHeight: true Layout.fillWidth: true Layout.margins: Maui.Style.space.small spacing: 0 Label { id: _label3 visible: text.length > 0 Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignRight horizontalAlignment: Qt.AlignRight font.pointSize: Maui.Style.fontSizes.small font.weight: Font.Light wrapMode: Text.NoWrap elide: Text.ElideMiddle color: control.Kirigami.Theme.textColor opacity: control.isCurrentItem ? 0.8 : 0.6 } Label { id: _label4 visible: text.length > 0 Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignRight horizontalAlignment: Qt.AlignRight font.pointSize: Maui.Style.fontSizes.small font.weight: Font.Light wrapMode: Text.NoWrap elide: Text.ElideMiddle color: control.Kirigami.Theme.textColor opacity: control.isCurrentItem ? 0.8 : 0.6 } } } } diff --git a/src/controls/private/BrowserView.qml b/src/controls/private/BrowserView.qml index c369c09..0e91253 100644 --- a/src/controls/private/BrowserView.qml +++ b/src/controls/private/BrowserView.qml @@ -1,668 +1,668 @@ import QtQuick 2.9 import QtQuick.Controls 2.9 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 url path onPathChanged: control.currentView.currentIndex = 0 property Maui.FMList currentFMList property Maui.BaseModel currentFMModel property alias currentView : viewLoader.item property int viewType property string filter height: _browserList.height width: _browserList.width function setCurrentFMList() { control.currentFMList = currentView.currentFMList control.currentFMModel = currentView.currentFMModel currentView.forceActiveFocus() } Menu { id: _dropMenu property string urls property url target enabled: Maui.FM.getFileInfo(target).isdir == "true" && !urls.includes(target.toString()) MenuItem { text: qsTr("Copy here") onTriggered: { const urls = _dropMenu.urls.split(",") for(var i in urls) Maui.FM.copy(urls[i], _dropMenu.target, false) } } MenuItem { text: qsTr("Move here") onTriggered: { const urls = _dropMenu.urls.split(",") for(var i in urls) Maui.FM.cut(urls[i], _dropMenu.target) } } MenuItem { text: qsTr("Link here") onTriggered: { const urls = _dropMenu.urls.split(",") for(var i in urls) Maui.FM.createSymlink(_dropMenu.source[i], urls.target) } } } Loader { id: viewLoader anchors.fill: parent focus: true 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() } Maui.FMList { id: _commonFMList path: control.path onSortByChanged: if(group) groupBy() onlyDirs: settings.onlyDirs filterType: settings.filterType filters: settings.filters sortBy: settings.sortBy } Component { id: listViewBrowser Maui.ListBrowser { id: _listViewBrowser property alias currentFMList : _browserModel.list property alias currentFMModel : _browserModel topMargin: Maui.Style.contentMargins showPreviewThumbnails: settings.showThumbnails keepEmblemOverlay: settings.selectionMode showDetailsInfo: true supportsRefreshing: true BrowserHolder { id: _holder browser: currentFMList } holder.visible: _holder.visible holder.emoji: _holder.emoji holder.title: _holder.title holder.body: _holder.body holder.emojiSize: _holder.emojiSize model: Maui.BaseModel { id: _browserModel list: _commonFMList filter: control.filter recursiveFilteringEnabled: true sortCaseSensitivity: Qt.CaseInsensitive filterCaseSensitivity: Qt.CaseInsensitive } section.delegate: Maui.LabelDelegate { id: delegate width: parent.width height: Maui.Style.toolBarHeightAlt label: String(section).toUpperCase() labelTxt.font.pointSize: Maui.Style.fontSizes.big isSection: true } delegate: Maui.ListBrowserDelegate { id: delegate - width: _listViewBrowser.width + width: parent.width height: _listViewBrowser.itemSize + Maui.Style.space.big leftPadding: Maui.Style.space.small rightPadding: Maui.Style.space.small padding: 0 showDetailsInfo: _listViewBrowser.showDetailsInfo folderSize : _listViewBrowser.itemSize showTooltip: true showEmblem: _listViewBrowser.showEmblem keepEmblemOverlay : _listViewBrowser.keepEmblemOverlay showThumbnails: _listViewBrowser.showPreviewThumbnails rightEmblem: _listViewBrowser.rightEmblem isSelected: selectionBar ? selectionBar.contains(model.path) : false leftEmblem: isSelected ? "list-remove" : "list-add" draggable: true Maui.Badge { iconName: "link" anchors.left: parent.left anchors.bottom: parent.bottom visible: (model.issymlink == true) || (model.issymlink == "true") } Connections { target: selectionBar onUriRemoved: { if(uri === model.path) delegate.isSelected = false } onUriAdded: { if(uri === model.path) delegate.isSelected = true } onCleared: delegate.isSelected = false } Connections { target: delegate onClicked: { _listViewBrowser.currentIndex = index _listViewBrowser.itemClicked(index) } onDoubleClicked: { _listViewBrowser.currentIndex = index _listViewBrowser.itemDoubleClicked(index) } onPressAndHold: { _listViewBrowser.currentIndex = index _listViewBrowser.itemRightClicked(index) } onRightClicked: { _listViewBrowser.currentIndex = index _listViewBrowser.itemRightClicked(index) } onRightEmblemClicked: { _listViewBrowser.currentIndex = index _listViewBrowser.rightEmblemClicked(index) } onLeftEmblemClicked: { _listViewBrowser.currentIndex = index _listViewBrowser.leftEmblemClicked(index) } onContentDropped: { _dropMenu.urls = drop.urls.join(",") _dropMenu.target = model.path _dropMenu.popup() } } } } } Component { id: gridViewBrowser Maui.GridBrowser { id: _gridViewBrowser property alias currentFMList : _browserModel.list property alias currentFMModel : _browserModel itemSize : thumbnailsSize + Maui.Style.fontSizes.default cellHeight: itemSize * 1.5 keepEmblemOverlay: settings.selectionMode showPreviewThumbnails: settings.showThumbnails supportsRefreshing: true BrowserHolder { id: _holder browser: currentFMList } holder.visible: _holder.visible holder.emoji: _holder.emoji holder.title: _holder.title holder.body: _holder.body holder.emojiSize: _holder.emojiSize model: Maui.BaseModel { id: _browserModel list: _commonFMList filter: control.filter recursiveFilteringEnabled: true sortCaseSensitivity: Qt.CaseInsensitive filterCaseSensitivity: Qt.CaseInsensitive } delegate: Maui.GridBrowserDelegate { id: delegate folderSize: height * 0.5 height: _gridViewBrowser.cellHeight width: _gridViewBrowser.cellWidth padding: Maui.Style.space.tiny showTooltip: true showEmblem: _gridViewBrowser.showEmblem keepEmblemOverlay: _gridViewBrowser.keepEmblemOverlay showThumbnails: _gridViewBrowser.showPreviewThumbnails rightEmblem: _gridViewBrowser.rightEmblem isSelected: selectionBar ? selectionBar.contains(model.path) : false leftEmblem: isSelected ? "list-remove" : "list-add" draggable: true Maui.Badge { iconName: "link" anchors.left: parent.left anchors.bottom: parent.bottom anchors.bottomMargin: Maui.Style.space.big visible: (model.issymlink == true) || (model.issymlink == "true") } Connections { target: selectionBar onUriRemoved: { if(uri === model.path) delegate.isSelected = false } onUriAdded: { if(uri === model.path) delegate.isSelected = true } onCleared: delegate.isSelected = false } Connections { target: delegate onClicked: { _gridViewBrowser.currentIndex = index _gridViewBrowser.itemClicked(index) } onDoubleClicked: { _gridViewBrowser.currentIndex = index _gridViewBrowser.itemDoubleClicked(index) } onPressAndHold: { _gridViewBrowser.currentIndex = index _gridViewBrowser.itemRightClicked(index) } onRightClicked: { _gridViewBrowser.currentIndex = index _gridViewBrowser.itemRightClicked(index) } onRightEmblemClicked: { _gridViewBrowser.currentIndex = index _gridViewBrowser.rightEmblemClicked(index) } onLeftEmblemClicked: { _gridViewBrowser.currentIndex = index _gridViewBrowser.leftEmblemClicked(index) } onContentDropped: { _dropMenu.urls = drop.urls.join(",") _dropMenu.target = model.path _dropMenu.popup() } } } } } Component { id: millerViewBrowser Item { id: _millerControl property Maui.FMList currentFMList property Maui.BaseModel currentFMModel property int currentIndex signal itemClicked(int index) signal itemDoubleClicked(int index) signal itemRightClicked(int index) signal keyPress(var event) signal rightEmblemClicked(int index) signal leftEmblemClicked(int index) signal areaClicked(var mouse) signal areaRightClicked() ListView { id: _millerColumns anchors.fill: parent boundsBehavior: !Maui.Handy.isTouch? Flickable.StopAtBounds : Flickable.OvershootBounds keyNavigationEnabled: true interactive: Maui.Handy.isTouch orientation: ListView.Horizontal snapMode: ListView.SnapToItem ScrollBar.horizontal: ScrollBar { id: _scrollBar snapMode: ScrollBar.SnapAlways policy: ScrollBar.AlwaysOn contentItem: Rectangle { implicitWidth: _scrollBar.interactive ? 13 : 4 implicitHeight: _scrollBar.interactive ? 13 : 4 color: "#333" opacity: _scrollBar.pressed ? 0.7 : _scrollBar.interactive && _scrollBar.hovered ? 0.5 : 0.2 radius: 0 } background: Rectangle { implicitWidth: _scrollBar.interactive ? 16 : 4 implicitHeight: _scrollBar.interactive ? 16 : 4 color: "#0e000000" opacity: 0.0 visible: _scrollBar.interactive radius: 0 } } onCurrentItemChanged: { _millerControl.currentFMList = currentItem.currentFMList _millerControl.currentFMModel = currentItem.currentFMModel control.setCurrentFMList() currentItem.forceActiveFocus() } onCountChanged: { _millerColumns.currentIndex = _millerColumns.count-1 _millerColumns.positionViewAtEnd() } Maui.PathList { id: _millerList path: control.path onPathChanged: { _millerColumns.currentIndex = _millerColumns.count-1 _millerColumns.positionViewAtEnd() } } model: Maui.BaseModel { id: _millerModel list: _millerList } delegate: Item { property alias currentFMList : _millersFMList property alias currentFMModel : _millersFMModel property int _index : index width: Math.min(Kirigami.Units.gridUnit * 22, control.width) height: parent.height focus: true function forceActiveFocus() { _millerListView.forceActiveFocus() } Kirigami.Separator { anchors.top: parent.top anchors.bottom: parent.bottom anchors.right: parent.right width: 1 z: 999 } Maui.FMList { id: _millersFMList path: model.path onlyDirs: settings.onlyDirs filterType: settings.filterType filters: settings.filters sortBy: settings.sortBy } Maui.ListBrowser { id: _millerListView anchors.fill: parent topMargin: Maui.Style.contentMargins showPreviewThumbnails: settings.showThumbnails keepEmblemOverlay: settings.selectionMode showDetailsInfo: true onKeyPress: _millerControl.keyPress(event) currentIndex : 0 onCurrentIndexChanged: _millerControl.currentIndex = currentIndex BrowserHolder { id: _holder browser: currentFMList } holder.visible: _holder.visible holder.emoji: _holder.emoji holder.title: _holder.title holder.body: _holder.body holder.emojiSize: _holder.emojiSize section.delegate: Maui.LabelDelegate { id: delegate width: parent.width height: Maui.Style.toolBarHeightAlt label: String(section).toUpperCase() labelTxt.font.pointSize: Maui.Style.fontSizes.big isSection: true } onAreaClicked: { _millerColumns.currentIndex = _index _millerControl.areaClicked(mouse) } onAreaRightClicked: { _millerColumns.currentIndex = _index _millerControl.areaRightClicked() } model: Maui.BaseModel { id: _millersFMModel list: _millersFMList filter: control.filter recursiveFilteringEnabled: true sortCaseSensitivity: Qt.CaseInsensitive filterCaseSensitivity: Qt.CaseInsensitive } delegate: Maui.ListBrowserDelegate { id: delegate width: parent.width height: _millerListView.itemSize + Maui.Style.space.big leftPadding: Maui.Style.space.small rightPadding: Maui.Style.space.small padding: 0 showDetailsInfo: _millerListView.showDetailsInfo folderSize : _millerListView.itemSize showTooltip: true showEmblem: _millerListView.showEmblem keepEmblemOverlay : _millerListView.keepEmblemOverlay showThumbnails: _millerListView.showPreviewThumbnails rightEmblem: _millerListView.rightEmblem isSelected: selectionBar ? selectionBar.contains(model.path) : false leftEmblem: isSelected ? "list-remove" : "list-add" draggable: true Maui.Badge { iconName: "link" anchors.left: parent.left anchors.bottom: parent.bottom visible: (model.issymlink == true) || (model.issymlink == "true") } Connections { target: selectionBar onUriRemoved: { if(uri === model.path) delegate.isSelected = false } onUriAdded: { if(uri === model.path) delegate.isSelected = true } onCleared: delegate.isSelected = false } Connections { target: delegate onClicked: { _millerColumns.currentIndex = _index _millerListView.currentIndex = index _millerControl.itemClicked(index) } onDoubleClicked: { _millerColumns.currentIndex = _index _millerListView.currentIndex = index _millerControl.itemDoubleClicked(index) } onPressAndHold: { _millerColumns.currentIndex = _index _millerListView.currentIndex = index _millerControl.itemRightClicked(index) } onRightClicked: { _millerColumns.currentIndex = _index _millerListView.currentIndex = index _millerControl.itemRightClicked(index) } onRightEmblemClicked: { _millerColumns.currentIndex = _index _millerListView.currentIndex = index _millerControl.rightEmblemClicked(index) } onLeftEmblemClicked: { _millerColumns.currentIndex = _index _millerListView.currentIndex = index _millerControl.leftEmblemClicked(index) } onContentDropped: { _dropMenu.urls = drop.urls.join(",") _dropMenu.target = model.path _dropMenu.popup() } } } } } } } } } diff --git a/src/fm/placeslist.cpp b/src/fm/placeslist.cpp index 4dba2a8..f8d2079 100644 --- a/src/fm/placeslist.cpp +++ b/src/fm/placeslist.cpp @@ -1,366 +1,361 @@ /* * * 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 #include "utils.h" #ifdef COMPONENT_ACCOUNTS #include "mauiaccounts.h" #endif #if defined Q_OS_LINUX && !defined Q_OS_ANDROID #include #endif #ifdef COMPONENT_TAGGING #include "tagging.h" #endif #if defined Q_OS_ANDROID || defined Q_OS_WIN32 PlacesList::PlacesList(QObject *parent) : MauiList(parent), fm(new FM(this)), model(nullptr), watcher(new QFileSystemWatcher(this)) #else PlacesList::PlacesList(QObject *parent) : MauiList(parent), fm(new FM(this)), model(new KFilePlacesModel(this)), watcher(new QFileSystemWatcher(this)) #endif { 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}); } }); #ifdef COMPONENT_TAGGING connect(Tagging::getInstance(), &Tagging::tagged, this, &PlacesList::reset); #endif #ifdef COMPONENT_ACCOUNTS connect(MauiAccounts::instance(), &MauiAccounts::accountAdded, this, &PlacesList::reset); connect(MauiAccounts::instance(), &MauiAccounts::accountRemoved, this, &PlacesList::reset); #endif #if defined Q_OS_LINUX && !defined Q_OS_ANDROID connect(this->model, &KFilePlacesModel::rowsInserted, [this](const QModelIndex &parent, int first, int last) { this->reset(); /*emit this->preListChanged(); for (int i = first; i <= last; i++) { const QModelIndex index = model->index(i, 0); if(this->groups.contains(model->groupType(index))) { this->list << getGroup(*this->model, static_cast(model->groupType(index))); } } emit this->postListChanged(); */ }); //TODO improve the usage of the model #endif connect(this, &PlacesList::groupsChanged, this, &PlacesList::reset); } void PlacesList::watchPath(const QString& path) { if(path.isEmpty() || !FMH::fileExists(path) || QUrl(path).isLocalFile()) return; this->watcher->addPath(path); } void PlacesList::classBegin() { } void PlacesList::componentComplete() { this->setList(); } FMH::MODEL_LIST PlacesList::items() const { return this->list; } #if defined Q_OS_LINUX && !defined Q_OS_ANDROID FMH::MODEL PlacesList::modelPlaceInfo(const KFilePlacesModel &model, const QModelIndex &index, const FMH::PATHTYPE_KEY &type) { return FMH::MODEL { {FMH::MODEL_KEY::PATH, model.url(index).toString()}, {FMH::MODEL_KEY::URL, model.url(index).toString()}, {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_LABEL[type]} }; } #endif FMH::MODEL_LIST PlacesList::getGroup(const KFilePlacesModel &model, const FMH::PATHTYPE_KEY &type) { #if defined Q_OS_ANDROID || defined Q_OS_WIN32 Q_UNUSED(model) FMH::MODEL_LIST res; switch(type) { case(FMH::PATHTYPE_KEY::PLACES_PATH): res << FMStatic::getDefaultPaths(); res<< FMStatic::packItems(UTIL::loadSettings("BOOKMARKS", "PREFERENCES", {}, "FileManager").toStringList(), FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::PLACES_PATH]); break; case(FMH::PATHTYPE_KEY::DRIVES_PATH): res = FMStatic::getDevices(); break; default: break; } return res; #else - for(auto i = 0; i < model.rowCount(); i++) - { - qDebug() << "DEVICESSSS" << model.url(model.index(i, 0)) << model.text(model.index(i, 0)); - } - 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; }); #endif } void PlacesList::setList() { this->list.clear(); //this are default static places //TODO move to itws own PATHTYPE_KEY::QUICK this->list << FMH::MODEL { {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::TAGS_PATH]+"fav"}, {FMH::MODEL_KEY::ICON, "love"}, {FMH::MODEL_KEY::LABEL, "Favorite"}, {FMH::MODEL_KEY::TYPE, "Quick"} }; #if defined Q_OS_LINUX && !defined Q_OS_ANDROID this->list << FMH::MODEL { {FMH::MODEL_KEY::PATH,"recentdocuments:///"}, {FMH::MODEL_KEY::ICON, "view-media-recent"}, {FMH::MODEL_KEY::LABEL, "Recent"}, {FMH::MODEL_KEY::TYPE, "Quick"} }; #endif #ifdef COMPONENT_TAGGING this->list << FMH::MODEL { {FMH::MODEL_KEY::PATH,"tags:///"}, {FMH::MODEL_KEY::ICON, "tag"}, {FMH::MODEL_KEY::LABEL, "Tags"}, {FMH::MODEL_KEY::TYPE, "Quick"} }; #endif for(const auto &group : this->groups) { switch(group) { case 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); break; case 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); break; case FMH::PATHTYPE_KEY::TAGS_PATH: this->list << this->fm->getTags(); break; #ifdef COMPONENT_ACCOUNTS case FMH::PATHTYPE_KEY::CLOUD_PATH: this->list << MauiAccounts::instance()->getCloudAccounts(); break; #endif } } 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(FMStatic::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(); const auto model = this->list.at(index); return FMH::toMap(model); } 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 QUrl& path) { #if defined Q_OS_ANDROID || defined Q_OS_WIN32 //do android stuff until cmake works with android 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_LABEL[FMH::PATHTYPE_KEY::PLACES_PATH]; }); const auto index = std::distance(it, this->list.rend()); emit this->preItemAppendedAt(index); auto bookmarks = UTIL::loadSettings("BOOKMARKS", "PREFERENCES", {}, "FileManager").toStringList(); bookmarks << path.toString(); UTIL::saveSettings("BOOKMARKS", bookmarks, "PREFERENCES", "FileManager"); this->list.insert(index, FMH::getDirInfoModel(path)); emit this->postItemAppended(); #else this->model->addPlace(QDir(path.toLocalFile()).dirName(), path, FMH::getIconName(path)); // this->list.insert(index, modelPlaceInfo(*this->model, this->model->closestItem(path), FMH::PATHTYPE_KEY::PLACES_PATH)); #endif } void PlacesList::removePlace(const int& index) { if(index >= this->list.size() || index < 0) return; emit this->preItemRemoved(index); #if defined Q_OS_ANDROID || defined Q_OS_WIN32 auto bookmarks = UTIL::loadSettings("BOOKMARKS", "PREFERENCES", {}, "FileManager").toStringList(); bookmarks.removeOne(this->list.at(index)[FMH::MODEL_KEY::PATH]); UTIL::saveSettings("BOOKMARKS", bookmarks, "PREFERENCES", "FileManager"); #else this->model->removePlace(this->model->closestItem(this->list.at(index)[FMH::MODEL_KEY::PATH])); #endif this->list.removeAt(index); emit this->postItemRemoved(); } bool PlacesList::contains(const QUrl& path) { return (std::find_if(this->list.rbegin(), this->list.rend(), [&](const FMH::MODEL &item) -> bool { return item[FMH::MODEL_KEY::PATH] == path.toString(); })) != this->list.rend(); } int PlacesList::indexOf(const QUrl& path) //TODO needs tweaking { return std::distance(std::find_if(this->list.rbegin(), this->list.rend(), [&](const FMH::MODEL &item) -> bool { return item[FMH::MODEL_KEY::PATH] == path.toString(); }), this->list.rend()); }