diff --git a/src/controls/ApplicationWindow.qml b/src/controls/ApplicationWindow.qml index 89b5496..dff93b7 100644 --- a/src/controls/ApplicationWindow.qml +++ b/src/controls/ApplicationWindow.qml @@ -1,596 +1,596 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Window 2.0 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import QtQuick.Window 2.3 -import org.kde.kirigami 2.2 as Kirigami +import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import QtQuick.Controls.Material 2.1 import "private" import SyncingModel 1.0 import SyncingList 1.0 Kirigami.AbstractApplicationWindow { id: root visible: true width: Screen.width * (isMobile ? 1 : 0.4) height: Screen.height * (isMobile ? 1 : 0.4) contentItem.anchors.leftMargin: 0 contentItem.anchors.rightMargin: 0 contentItem.anchors.margins: 0 property bool showAccounts : true /***************************************************/ /******************** ALIASES *********************/ /*************************************************/ property alias page : page property alias footBar : page.footBar property alias headBar : page.headBar property alias dialog: dialogLoader.item property alias leftIcon : menuBtn property alias rightIcon : searchBtn default property alias content : page.content property alias mainMenu : mainMenu.contentData property alias about : aboutDialog property alias accounts: _accountsDialogLoader.item property alias currentAccount: _accountCombobox.currentText property alias notifyDialog: _notify //redefines here as here we can know a pointer to PageRow wideScreen: isWide /***************************************************/ /*********************** UI ***********************/ /*************************************************/ property bool isWide : root.width >= Kirigami.Units.gridUnit * 30 property int radiusV : unit * 4 property int iconSize : iconSizes.medium * (isMobile ? 0.95 : 1) readonly property int unit : Maui.Style.unit readonly property int rowHeight: Maui.Style.rowHeight readonly property int rowHeightAlt: Maui.Style.rowHeightAlt readonly property int toolBarHeight: Maui.Style.toolBarHeight readonly property int toolBarHeightAlt: Maui.Style.toolBarHeightAlt readonly property int contentMargins: space.medium readonly property var fontSizes: Maui.Style.fontSizes readonly property var space : Maui.Style.space readonly property var iconSizes : Maui.Style.iconSizes property string colorSchemeName : Qt.application.name /***************************************************/ /********************* COLORS *********************/ /*************************************************/ readonly property var colorScheme: ({ Default : 1, Light : 2, Dark: 3, Custom: 4 }) property color borderColor: Qt.tint(textColor, Qt.rgba(backgroundColor.r, backgroundColor.g, backgroundColor.b, 0.7)) property color backgroundColor: Maui.Style.backgroundColor property color textColor: Maui.Style.textColor property color highlightColor: Maui.Style.highlightColor property color highlightedTextColor: Maui.Style.highlightedTextColor property color buttonBackgroundColor: Maui.Style.buttonBackgroundColor property color viewBackgroundColor: Maui.Style.viewBackgroundColor property color altColor: Maui.Style.altColor property color altColorText: Maui.Style.altColorText property color accentColor : buttonBackgroundColor property color bgColor: viewBackgroundColor property color headBarBGColor: backgroundColor property color headBarFGColor: textColor readonly property string darkBorderColor: Qt.darker(darkBackgroundColor, 1.5) readonly property string darkBackgroundColor: "#303030" readonly property string darkTextColor: "#FAFAFA" readonly property string darkHighlightColor: "#29B6F6" readonly property string darkHighlightedTextColor: darkTextColor readonly property string darkViewBackgroundColor: "#212121" readonly property string darkDarkColor: "#191919" readonly property string darkButtonBackgroundColor : "#191919" readonly property color darkAltColor: "#333" readonly property color darkAltColorText: darkTextColor readonly property color darkAccentColor : darkButtonBackgroundColor readonly property color darkBgColor: darkBackgroundColor property color warningColor : Maui.Style.warningColor property color dangerColor : Maui.Style.dangerColor property color infoColor : Maui.Style.infoColor property color suggestedColor : Maui.Style.suggestedColor /* ANDROID THEMING*/ Material.theme: Material.Light Material.accent: highlightColor Material.background: headBarBGColor Material.primary: headBarBGColor Material.foreground: textColor /***************************************************/ /**************** READONLY PROPS ******************/ /*************************************************/ readonly property bool isMobile : Kirigami.Settings.isMobile readonly property bool isAndroid: Qt.platform.os == "android" readonly property real screenWidth : Screen.width readonly property real screenHeight : Screen.height /***************************************************/ /********************* PROPS **********************/ /*************************************************/ property bool altToolBars : isMobile property bool floatingBar : altToolBars property int footBarAligment : Qt.AlignCenter property bool footBarOverlap : false property bool allowRiseContent: floatingBar && footBarOverlap property int footBarMargins: space.big property alias searchButton : searchBtn property alias menuButton : menuBtn /***************************************************/ /******************** SIGNALS *********************/ /*************************************************/ signal menuButtonClicked(); signal searchButtonClicked(); signal goBackTriggered(); signal goFowardTriggered(); // overlay.modal: Rectangle // { // color: Color.transparent(altColor, 0.5) // } // overlay.modeless: Rectangle { // color: "transparent" // } onClosing: { if(!isMobile) { var height = root.height var width = root.width var x = root.x var y = root.y Maui.FM.saveSettings("GEOMETRY", Qt.rect(x, y, width, height), "WINDOW") } } property bool isPortrait: Screen.primaryOrientation === Qt.PortraitOrientation || Screen.primaryOrientation === Qt.InvertedPortraitOrientation onIsPortraitChanged: { if(isPortrait) { console.log("PORTARIT MODE CHANGED") width: Screen.width height: Screen.height } } onHeadBarBGColorChanged: { if(!isMobile && colorSchemeName.length > 0 && !altToolBars) Maui.KDE.setColorScheme(colorSchemeName, headBarBGColor, headBarFGColor) else if(isAndroid && !altToolBars) Maui.Android.statusbarColor(headBarBGColor, false) else if(isAndroid && altToolBars) Maui.Android.statusbarColor(viewBackgroundColor, true) } onHeadBarFGColorChanged: { if(!isAndroid && !isMobile && colorSchemeName.length > 0 && !altToolBars) Maui.KDE.setColorScheme(colorSchemeName, headBarBGColor, headBarFGColor) else if(isAndroid && !altToolBars) Maui.Android.statusbarColor(headBarBGColor, false) else if(isAndroid && altToolBars) Maui.Android.statusbarColor(viewBackgroundColor, true) } background: Rectangle { color: bgColor } // globalDrawer.height: root.height - headBar.height // globalDrawer.y: headBar.height Maui.Page { id: page anchors.fill: parent leftMargin: root.globalDrawer && (root.globalDrawer.modal === false) ? root.globalDrawer.contentItem.width * root.globalDrawer.position : 0 margins: 0 headBar.plegable: false headBar.height: toolBarHeight + space.small headBar.implicitHeight: toolBarHeight + space.small headBarExit: false altToolBars: root.altToolBars floatingBar : root.floatingBar footBarAligment : root.footBarAligment footBarOverlap : root.footBarOverlap footBarMargins: root.footBarMargins allowRiseContent: root.allowRiseContent background: Rectangle { color: bgColor } - headBar.colorScheme.backgroundColor: headBarBGColor - headBar.colorScheme.textColor: headBarFGColor + Kirigami.Theme.backgroundColor: headBarBGColor + Kirigami.Theme.textColor: headBarFGColor headBar.leftContent: ToolButton { id: menuBtn icon.name: "application-menu" icon.color: headBarFGColor checked: mainMenu.visible onClicked: { menuButtonClicked() mainMenu.visible ? mainMenu.close() : mainMenu.popup(parent, parent.x , altToolBars ? 0 : parent.height+ space.medium) } Menu { id: mainMenu modal: true z: 999 width: unit * 200 Item { height: _accountCombobox.visible ? unit * 90 : 0 anchors { left: parent.left right: parent.right top: parent.top margins: space.medium } ComboBox { id: _accountCombobox anchors.centerIn: parent // parent: mainMenu popup.z: 999 width: parent.width visible: (count > 1) && showAccounts textRole: "user" flat: true model: showAccounts ? accounts.model : undefined // icon.name: "user-identity" // iconButton.isMask: false } } MenuSeparator { visible: _accountCombobox.visible } MenuItem { text: qsTr("Accounts") visible: root.showAccounts icon.name: "list-add-user" onTriggered: { if(root.accounts) accounts.open() } } MenuItem { text: qsTr("About") icon.name: "documentinfo" onTriggered: aboutDialog.open() } MenuSeparator {} } } headBar.rightContent: ToolButton { id: searchBtn icon.name: "edit-find" icon.color: headBarFGColor onClicked: searchButtonClicked() } Keys.onBackPressed: { goBackTriggered(); console.log("GO BACK CLICKED") event.accepted = true } Shortcut { sequence: "Forward" onActivated: goFowardTriggered(); } Shortcut { sequence: StandardKey.Forward onActivated: goFowardTriggered(); } Shortcut { sequence: StandardKey.Back onActivated: goBackTriggered(); } } Maui.AboutDialog { id: aboutDialog } Loader { id: _accountsDialogLoader sourceComponent: root.showAccounts ? _accountsDialogComponent : undefined } Component { id: _accountsDialogComponent AccountsHelper {} } Maui.Dialog { id: _notify property var cb : ({}) verticalAlignment: Qt.AlignTop defaultButtons: false colorScheme.backgroundColor: altColor colorScheme.textColor: altColorText maxHeight: Math.max(unit * 120, (_notifyLayout.implicitHeight)) maxWidth: isMobile ? parent.width * 0.9 : unit * 500 Timer { id: _notifyTimer onTriggered: _notify.close() } onClosed: _notifyTimer.stop() MouseArea { anchors.fill: parent onClicked: { if(_notify.cb) _notify.cb() _notify.close() } } GridLayout { anchors.fill: parent columns: 2 rows: 1 Item { Layout.fillHeight: true Layout.preferredWidth: iconSizes.huge + space.big Layout.row: 1 Layout.column: 1 ToolButton { id: _notifyIcon icon.width: iconSizes.large anchors.centerIn: parent // isMask: false } } Item { Layout.fillHeight: true Layout.fillWidth: true Layout.row: 1 Layout.column: 2 ColumnLayout { anchors.fill: parent id: _notifyLayout Label { id: _notifyTitle Layout.fillHeight: true Layout.fillWidth: true font.weight: Font.Bold font.bold: true font.pointSize: fontSizes.big color: _notify.colorScheme.textColor elide: Qt.ElideRight wrapMode: Text.Wrap } Label { id: _notifyBody Layout.fillHeight: true Layout.fillWidth: true font.pointSize: fontSizes.default color: _notify.colorScheme.textColor elide: Qt.ElideRight wrapMode: Text.Wrap } } } } function show(callback) { _notify.cb = callback _notifyTimer.start() _notify.open() } } Loader { id: dialogLoader } Component.onCompleted: { if(isAndroid && altToolBars) Maui.Android.statusbarColor(backgroundColor, true) if(!isMobile) { var rect = Maui.FM.loadSettings("GEOMETRY", "WINDOW", Qt.rect(root.x, root.y, root.width, root.height)) root.x = rect.x root.y = rect.y root.width = rect.width root.height = rect.height } } // Connections // { // target: Maui.FM // // onNewItem: notify("dialog-information", qsTr("File uploaded"), "Your file has been uploaded to your account /n"+path) // onWarningMessage: notify("dialog-information", "Oops!", message) // } function switchColorScheme(variant) { switch(variant) { case colorScheme.Default: backgroundColor = Maui.Style.backgroundColor textColor = Maui.Style.textColor highlightColor = Maui.Style.highlightColor highlightedTextColor = Maui.Style.highlightedTextColor buttonBackgroundColor = Maui.Style.buttonBackgroundColor viewBackgroundColor = Maui.Style.viewBackgroundColor altColor = Maui.Style.altColor borderColor = Maui.Style.borderColor if(isAndroid) Maui.Android.statusbarColor(backgroundColor, true) break case colorScheme.Dark: borderColor = darkBorderColor backgroundColor = darkBackgroundColor textColor = darkTextColor highlightColor = darkHighlightColor highlightedTextColor = darkHighlightedTextColor buttonBackgroundColor = darkButtonBackgroundColor viewBackgroundColor = darkViewBackgroundColor altColor = darkDarkColor altColorText = darkAltColorText bgColor =darkBgColor if(isAndroid) Maui.Android.statusbarColor(backgroundColor, false) break } } function notify(icon, title, body, callback, timeout) { _notifyIcon.icon.name = icon _notifyTitle.text = title _notifyBody.text = body _notifyTimer.interval = timeout ? timeout : 2500 _notify.show(callback) } /** FUNCTIONS **/ // function riseContent() // { // if(allowRiseContent) // flickable.flick(0, flickable.contentHeight* -2) // } // function dropContent() // { // if(allowRiseContent) // flickable.flick(0, flickable.contentHeight* 2) // } } diff --git a/src/controls/FileBrowser.qml b/src/controls/FileBrowser.qml index f18d758..5b3e62e 100644 --- a/src/controls/FileBrowser.qml +++ b/src/controls/FileBrowser.qml @@ -1,1049 +1,1050 @@ import QtQuick 2.9 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 "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 var currentFMList : modelList 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 focus: true 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 } } Component { id: millerViewBrowser Kirigami.ColumnView { id: _millerColumns // columnWidth: Kirigami.Units.gridUnit * 22 // fillWidth: true columnResizeMode: Kirigami.ColumnView.DynamicColumns signal itemClicked(int index) signal itemDoubleClicked(int index) signal itemRightClicked(int index) signal rightEmblemClicked(int index) signal leftEmblemClicked(int index) Maui.PathList { id: _millerList path: control.currentPath } Maui.BaseModel { id: _millerModel list: _millerList } Repeater { id: _repeater model: _millerModel onItemAdded: { // if(viewLoader.sourceComponent === millerViewBrowser) // _millerColumns.currentIndex = _millerColumns.count-1 } Item { Maui.FMList { id: _millersFMList preview: modelList.preview path: model.path foldersFirst: modelList.foldersFirst onWarning: { notify("dialog-information", "An error happened", message) } onProgress: { if(percent === 100) _progressBar.value = 0 else _progressBar.value = percent/100 } } Maui.ListBrowser { id: _millerListView anchors.fill: parent showPreviewThumbnails: modelList.preview showEmblem: selectionMode rightEmblem: isMobile ? "document-share" : "" leftEmblem: "list-add" showDetailsInfo: true // itemSize: thumbnailsSize onItemClicked: { control.currentFMList = _millersFMList _millerColumns.itemClicked(index) } // onItemDoubleClicked: // { // modelList.path = _millersFMList.path // _millerColumns.onItemDoubleClicked(index) // } onItemRightClicked: _millerColumns.itemRightClicked(index) onRightEmblemClicked: _millerColumns.rightEmblemClicked(index) onLeftEmblemClicked: _millerColumns.leftEmblemClicked(index) model: Maui.BaseModel { list: _millersFMList } section.delegate: Maui.LabelDelegate { id: delegate label: section labelTxt.font.pointSize: fontSizes.big isSection: true boldLabel: true height: toolBarHeightAlt } } } } } } 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() } 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:[ ToolButton { icon.name: "view-list-icons" onClicked: list.viewType = Maui.FMList.ICON_VIEW checkable: false checked: list.viewType === Maui.FMList.ICON_VIEW icon.width: iconSizes.medium autoExclusive: true }, ToolButton { icon.name: "view-list-details" onClicked: list.viewType = Maui.FMList.LIST_VIEW icon.width: iconSizes.medium checked: list.viewType === Maui.FMList.LIST_VIEW autoExclusive: true }, ToolButton { icon.name: "view-file-columns" onClicked: list.viewType = Maui.FMList.MILLERS_VIEW icon.width: iconSizes.medium checked: list.viewType === Maui.FMList.MILLERS_VIEW autoExclusive: true }, Kirigami.ActionToolBar { -// Layout.fillWidth: fal - z: 999 + position: Controls.ToolBar.Header + Layout.fillWidth: false + z: 999 hiddenActions: browserMenu.actions // display: isMobile ? ToolButton.IconOnly : ToolButton.TextBesideIcon actions: [ Kirigami.Action { icon.name: "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") icon.name: "item-select" checkable: false checked: selectionMode onTriggered: selectionMode = !selectionMode } ] } ] headBar.leftContent: [ ToolButton { icon.name: "go-previous" onClicked: control.goBack() }, ToolButton { id: goUpButton visible: true icon.name: "go-up" onClicked: control.goUp() }, ToolButton { icon.name: "go-next" onClicked: control.goNext() } ] footBar.visible: false Component { id: selectionBarComponent Maui.SelectionBar { anchors.fill: parent onIconClicked: _selectionBarmenu.popup() onExitClicked: 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) _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: switch(list.viewType) { case Maui.FMList.ICON_VIEW: return gridViewBrowser case Maui.FMList.LIST_VIEW: return listViewBrowser case Maui.FMList.MILLERS_VIEW: return millerViewBrowser } onLoaded: { if(sourceComponent !== millerViewBrowser) control.currentFMList = modelList } Layout.topMargin: list.viewType == Maui.FMList.ICON_VIEW ? contentMargins * 2 : unit Layout.margins: 0 Layout.fillWidth: true Layout.fillHeight: true } Loader { id: selectionBarLoader Layout.fillWidth: true Layout.preferredHeight: control.selectionBar && control.selectionBar.visible ? control.selectionBar.barHeight: 0 Layout.leftMargin: contentMargins * (isMobile ? 3 : 2) Layout.rightMargin: contentMargins * (isMobile ? 3 : 2) Layout.bottomMargin: control.selectionBar && control.selectionBar.visible ? contentMargins*2 : 0 z: holder.z +1 } ProgressBar { id: _progressBar Layout.fillWidth: true Layout.alignment: Qt.AlignBottom Layout.preferredHeight: visible ? iconSizes.medium : 0 visible: value > 0 } } // 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 = control.currentFMList.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 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/Page.qml b/src/controls/Page.qml index 7e5931b..b27dfbb 100644 --- a/src/controls/Page.qml +++ b/src/controls/Page.qml @@ -1,292 +1,289 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import org.kde.mauikit 1.0 as Maui -import org.kde.kirigami 2.6 as Kirigami +import org.kde.kirigami 2.7 as Kirigami import QtGraphicalEffects 1.0 import QtQuick.Window 2.0 import "private" Page { id: control /* Controlc color scheming */ ColorScheme { id: colorScheme backgroundColor: viewBackgroundColor } property alias colorScheme : colorScheme /***************************/ property bool headBarExit : true property bool headBarTitleVisible: headBarTitle property string headBarExitIcon : "dialog-close" property string headBarTitle: "" property int margins: contentMargins * 1.5 property int topMargin: margins property int rightMargin: margins property int leftMargin: margins property int bottomMargin: margins property alias headBar: topToolBar property alias headBarItem: topToolBar.data property alias footBar: bottomToolBar property alias footBarItem: bottomToolBar.data property alias floatingBar: bottomToolBar.floating property alias flickable: flickable property int footBarAligment : Qt.AlignCenter property bool altToolBars : false property int footBarMargins : space.large property bool footBarOverlap: false property bool allowRiseContent: floatingBar && footBarOverlap && footBar.visible property bool contentIsRised: false signal exit(); default property alias content : mainContainer.data property alias backContain: backContainer.data clip: true leftPadding: 0 topPadding: leftPadding rightPadding: leftPadding bottomPadding: leftPadding background: Rectangle { color: colorScheme.backgroundColor } GridLayout { id: rootLayout anchors.fill: parent rows: 3 columns: 1 rowSpacing: 0 Maui.ToolBar { id: topToolBar Layout.fillWidth: !folded Layout.rightMargin: floating ? space.small : 0 Layout.leftMargin: floating ? space.small : 0 Layout.bottomMargin: 0 Layout.topMargin: 0 Layout.row: altToolBars ? 3 : 1 Layout.column: 1 - colorScheme - { - backgroundColor: folded ? altColor : control.colorScheme.backgroundColor - textColor : folded ? altColorText : control.colorScheme.textColor - } - + + Kirigami.Theme.backgroundColor: control.colorScheme.backgroundColor + position: altToolBars ? ToolBar.Footer : ToolBar.Header dropShadow: false drawBorder: !dropShadow width: folded ? height : implicitWidth implicitWidth: width Layout.preferredHeight: implicitHeight implicitHeight: topToolBar.visible ? toolBarHeightAlt : 0 visible: count > 0 clip: false z: container.z +1 leftContent: ToolButton { id: exitBtn visible: headBarExit icon.name : headBarExitIcon onClicked : exit() } middleContent: Label { visible: headBarTitleVisible text : headBarTitle Layout.fillWidth: true elide : Text.ElideRight font.bold : false font.weight: Font.Bold color : colorScheme.textColor font.pointSize: fontSizes.big horizontalAlignment : Text.AlignHCenter verticalAlignment : Text.AlignVCenter } } Item { id: container Layout.fillWidth: true Layout.fillHeight: true Layout.topMargin: topMargin Layout.bottomMargin: bottomMargin Layout.rightMargin: rightMargin Layout.leftMargin: leftMargin Layout.row: altToolBars ? 1 : 2 Layout.column: 1 clip: false anchors.margins: floatingBar && footBarOverlap ? margins : 0 anchors.top: if(!floatingBar && !topToolBar.plegable) undefined else { if(!altToolBars && headBar.visible && !topToolBar.plegable) topToolBar.bottom else if(!altToolBars && headBar.visible && topToolBar.plegable) topToolBar.top else if(altToolBars && headBar.visible) rootLayout.top } anchors.bottom: if(!floatingBar && !topToolBar.plegable) undefined else { if(altToolBars && headBar.visible && (footBarOverlap && floatingBar && footBar.visible) && !topToolBar.plegable) topToolBar.top/*.bottom*/ else if(altToolBars && headBar.visible && (!footBarOverlap && floatingBar && footBar.visible) && !topToolBar.plegable) bottomToolBar.verticalCenter/*.bottom*/ else if(altToolBars && headBar.visible && (footBarOverlap && floatingBar && footBar.visible) && topToolBar.plegable) topToolBar.bottom else if(altToolBars && headBar.visible && !footBar.visible && topToolBar.plegable) topToolBar.verticalCenter else if(!footBarOverlap && !floatingBar && footBar.visible) bottomToolBar.top else if(!altToolBars && floatingBar && footBarOverlap && footBar.visible) rootLayout.bottom } z: 1 Flickable { id: flickable flickableDirection: Flickable.VerticalFlick height: parent.height width: parent.width z: container.z // boundsMovement: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds interactive: allowRiseContent contentWidth: parent.width contentHeight: allowRiseContent ? parent.height + footBar.height + footBarMargins + space.big : parent.height onContentYChanged: control.contentIsRised = contentY > 0 Item { id: mainContainer z: container.z width: container.width height: contentIsRised ? container.height - (footBar.height + footBarMargins + space.big) : container.height y: contentIsRised ? flickable.contentY : 0 Item { id: backContainer z: mainContainer.z - 1 width: container.width height: footBar.height + footBarMargins + space.big anchors { left: parent.left right: parent.right top: parent.bottom margins: space.big } } } } } Maui.ToolBar { id: bottomToolBar visible: count > 0 readonly property int _margins : footBarMargins Layout.leftMargin: footBarAligment === Qt.AlignLeft ? _margins : (floating ? space.small : 0) Layout.rightMargin: footBarAligment === Qt.AlignRight ? _margins : (floating ? space.small : 0) Layout.bottomMargin: floating ? _margins : 0 Layout.alignment: footBarAligment Layout.fillWidth: true Layout.preferredHeight: implicitHeight // Layout.minimumWidth: parent.width * (floatingBar ? 0.4 : 1) Layout.maximumWidth: floating ? middleLayout.implicitWidth + layout.implicitWidth : parent.width Layout.row: altToolBars ? 2 : 3 Layout.column: 1 z: container.z +1 position: ToolBar.Footer clip: false colorScheme { backgroundColor: control.colorScheme.backgroundColor textColor : control.colorScheme.textColor } drawBorder: !floating } } function riseContent() { if(allowRiseContent) flickable.flick(0, flickable.contentHeight* -2) } function dropContent() { if(allowRiseContent) flickable.flick(0, flickable.contentHeight* 2) } } diff --git a/src/controls/ToolBar.qml b/src/controls/ToolBar.qml index a77cd73..30ac4b5 100644 --- a/src/controls/ToolBar.qml +++ b/src/controls/ToolBar.qml @@ -1,263 +1,262 @@ /* * 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.6 import QtQuick.Controls 2.2 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import "private" ToolBar { id: control /* Controlc color scheming */ ColorScheme {id: colorScheme} property alias colorScheme : colorScheme /***************************/ clip: true implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: visible ? (floating ? toolBarHeightAlt : toolBarHeight) : 0 width: floating ? implicitWidth : parent.width height: implicitHeight property alias stickyRightContent : rightRowContent.sticky property alias stickyLeftContent : leftRowContent.sticky property alias stickyMiddleContent : middleRowContent.sticky property alias leftContent : leftRowContent.data property alias middleContent : middleRowContent.data property alias rightContent : rightRowContent.data property alias middleLayout : middleRowContent property alias leftLayout : leftRowContent property alias rightLayout : rightRowContent property alias layout : layout property int margins: space.medium - spacing: space.big + spacing: space.medium property int count : leftContent.length + middleContent.length + rightContent.length property bool dropShadow: false property bool drawBorder: false property bool floating: false property bool plegable: false //deprecrated property bool folded : false //deprecrated property bool flickable: true property bool strech : true property bool leftSretch: strech property bool rightSretch: strech property bool middleStrech: strech - padding: 0 // leftPadding: Kirigami.Units.smallSpacing*2 // rightPadding: Kirigami.Units.smallSpacing*2 signal unfolded() // onPlegableChanged: folded = plegable // onVisibleChanged: // { // if(control.visible) // control.height= implicitHeight // else // control.height= 0 // // } - background: Rectangle - { - id: headBarBG - color: colorScheme.backgroundColor - implicitHeight: toolBarHeightAlt - radius: floating ? radiusV : 0 - border.color: floating ? colorScheme.borderColor : "transparent" - - SequentialAnimation on radius - { - ColorAnimation { to: colorScheme.backgroundColor ; duration: 1000 } - } - - Kirigami.Separator - { - visible: drawBorder - color: colorScheme.borderColor - height: unit - anchors - { - left: parent.left - right: parent.right - bottom: control.position == ToolBar.Footer ? undefined : parent.bottom - top: control.position == ToolBar.Footer ? parent.top : undefined - } - } - - layer.enabled: dropShadow - layer.effect: DropShadow - { - anchors.fill: headBarBG - horizontalOffset: 0 - verticalOffset: unit * (altToolBars ? -1 : 1) - radius: 8 - samples: 25 - color: Qt.darker(colorScheme.backgroundColor, 1.4) - source: headBarBG - } - } +// background: Rectangle +// { +// id: headBarBG +// color: colorScheme.backgroundColor +// implicitHeight: toolBarHeightAlt +// radius: floating ? radiusV : 0 +// border.color: floating ? colorScheme.borderColor : "transparent" +// +// SequentialAnimation on radius +// { +// ColorAnimation { to: colorScheme.backgroundColor ; duration: 1000 } +// } +// +// Kirigami.Separator +// { +// visible: drawBorder +// color: colorScheme.borderColor +// height: unit +// anchors +// { +// left: parent.left +// right: parent.right +// bottom: control.position == ToolBar.Footer ? undefined : parent.bottom +// top: control.position == ToolBar.Footer ? parent.top : undefined +// } +// } +// +// layer.enabled: dropShadow +// layer.effect: DropShadow +// { +// anchors.fill: headBarBG +// horizontalOffset: 0 +// verticalOffset: unit * (altToolBars ? -1 : 1) +// radius: 8 +// samples: 25 +// color: Qt.darker(colorScheme.backgroundColor, 1.4) +// source: headBarBG +// } +// } Rectangle { width: parent.height height: iconSizes.tiny visible: !mainFlickable.atXEnd && mainFlickable.interactive rotation: 270 opacity: 0.2 anchors { top: parent.top bottom: parent.bottom right: parent.right } z: 999 gradient: Gradient { GradientStop { position: 0.0 color: "transparent" } GradientStop { position: 1.0 color: colorScheme.textColor } } } Rectangle { width: parent.height height: iconSizes.tiny visible: !mainFlickable.atXBeginning && mainFlickable.interactive rotation: 270 opacity: 0.2 anchors { top: parent.top bottom: parent.bottom left: parent.left } z: 999 gradient: Gradient { GradientStop { position: 0.0 color: colorScheme.textColor } GradientStop { position: 1.0 color: "transparent" } } } Flickable { id: mainFlickable anchors.fill: parent anchors.leftMargin: margins anchors.rightMargin: margins flickableDirection: Flickable.HorizontalFlick interactive: (contentWidth > control.width) && control.flickable contentWidth: ((control.margins * 2) + space.medium) + (control.stickyLeftContent ? leftRowContent.implicitWidth : leftRowContent.width) + (control.stickyMiddleContent ? middleRowContent.implicitWidth : middleRowContent.width) + (control.stickyRightContent ? rightRowContent.implicitWidth : rightRowContent.width) boundsBehavior: isMobile ? Flickable.DragOverBounds : Flickable.StopAtBounds clip: true RowLayout { id: layout height: mainFlickable.height width: mainFlickable.width RowLayout { id: leftRowContent property bool sticky : false Layout.leftMargin: rightRowContent.implicitWidth && implicitWidth === 0 && middleRowContent.implicitWidth && control.leftSretch ? rightRowContent.implicitWidth : undefined Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft spacing: leftContent.length > 0 ? control.spacing : 0 Layout.minimumWidth: !sticky ? undefined : implicitWidth clip: true Layout.fillWidth: control.leftSretch && implicitWidth Layout.fillHeight: true } RowLayout { id: middleRowContent property bool sticky : false Layout.alignment: Qt.AlignCenter clip: true spacing: middleContent.length === 1 ? 0 : control.spacing Layout.minimumWidth: !sticky ? undefined : implicitWidth // Layout.maximumWidth: control.width - leftRowContent.implicitWidth - rightRowContent.implicitWidth Layout.fillWidth: control.middleStrech Layout.fillHeight: true } RowLayout { id: rightRowContent property bool sticky : false Layout.rightMargin: leftRowContent.implicitWidth && implicitWidth === 0 && middleRowContent.implicitWidth && control.rightSretch ? leftRowContent.implicitWidth : undefined Layout.alignment: Qt.AlignVCenter | Qt.AlignRight spacing: rightContent.length > 0 ? control.spacing : 0 Layout.minimumWidth: !sticky ? undefined : implicitWidth clip: true Layout.fillWidth: implicitWidth Layout.fillHeight: true } } ScrollBar.horizontal: ScrollBar { visible: false} } }