diff --git a/qml/AppControls2/FolderIcon.qml b/qml/AppControls2/FolderIcon.qml index 1ff8110..bc5717e 100644 --- a/qml/AppControls2/FolderIcon.qml +++ b/qml/AppControls2/FolderIcon.qml @@ -26,10 +26,8 @@ StyleBackground { property alias padding: iconGrid.padding property alias spacing: iconGrid.spacing - radius: 4 paletteRole: Palette.Text useStyleTransparent: false - alpha: 0.12 Grid { id: iconGrid diff --git a/qml/AppControls2/FolderItem.qml b/qml/AppControls2/FolderItem.qml index 85a2957..06a3e9e 100644 --- a/qml/AppControls2/FolderItem.qml +++ b/qml/AppControls2/FolderItem.qml @@ -27,6 +27,7 @@ MouseArea { rows: 2; columns: 2 spacing: 2; padding: 2 icons: icon + alpha: 0.12; radius: 4 Layout.alignment: Qt.AlignVCenter Layout.preferredWidth: 32 Layout.preferredHeight: 32 diff --git a/qml/AppControls2/RoundButton.qml b/qml/AppControls2/RoundButton.qml index e2220f7..72cc3b1 100644 --- a/qml/AppControls2/RoundButton.qml +++ b/qml/AppControls2/RoundButton.qml @@ -5,7 +5,8 @@ MouseArea { id: buttonMouseArea hoverEnabled: true property string buttonIcon: "" - property bool highlight: false + property alias highlight: themeIcon.highLight + property alias autoHighLight: themeIcon.autoHighLight StyleBackground { useStyleTransparent: false @@ -16,9 +17,9 @@ MouseArea { } ThemeIcon { + id: themeIcon anchors.centerIn: parent width: 16; height: width source: buttonIcon - highLight: buttonMouseArea.highlight } } diff --git a/qml/AppUI/AppPageHeader.qml b/qml/AppUI/AppPageHeader.qml index a2fc48b..986c28f 100644 --- a/qml/AppUI/AppPageHeader.qml +++ b/qml/AppUI/AppPageHeader.qml @@ -142,7 +142,6 @@ Item { delegate: AppControls2.RoundButton { width: height; height: ListView.view ? ListView.view.height : 0 buttonIcon: model.icon - onClicked: { root.state = "search"; searchInputBar.providerId = model.id; diff --git a/qml/AppUI/EditText.qml b/qml/AppUI/EditText.qml index d1aa022..740a0de 100644 --- a/qml/AppUI/EditText.qml +++ b/qml/AppUI/EditText.qml @@ -27,6 +27,7 @@ Item { property bool textCenterIn: false property bool editStatus: false property string textEdited: title + property bool isFullScreenFolder: false Component { id: unEditText @@ -36,16 +37,16 @@ Item { horizontalAlignment: contain.textCenterIn ? Text.AlignHCenter : Text.AlignLeft elide: Text.ElideRight text: contain.textEdited + paletteRole: isFullScreenFolder ? Palette.HighlightedText : Palette.Text + font.bold: !isFullScreenFolder + font.pixelSize: isFullScreenFolder ? 32 : 14 MouseArea { id: textArea anchors.fill: parent - onDoubleClicked: { - contain.editStatus = true; - } + onDoubleClicked: contain.editStatus = true; } } - } Component { @@ -72,6 +73,8 @@ Item { text: contain.textEdited selectByMouse: true maximumLength: 14 + font.bold: !isFullScreenFolder + font.pixelSize: isFullScreenFolder ? 32 : 14 onEditingFinished: { modelManager.getFolderModel().renameFolder(text); @@ -79,8 +82,9 @@ Item { contain.editStatus = false; } + property int textColor: isFullScreenFolder ? Palette.HighlightedText : Palette.Text function updateTextInputColor() { - color = themePalette.paletteColor(Palette.Text); + color = themePalette.paletteColor(textColor); selectionColor = themePalette.paletteColor(Palette.Highlight); } @@ -107,10 +111,12 @@ Item { anchors.centerIn: parent width: 16; height: width source: "image://appicon/edit-clear-symbolic" + highLight: isFullScreenFolder + autoHighLight: !isFullScreenFolder } onClicked: { - textEdit.text = title; + textEdit.text = textEdited; contain.editStatus = false; } } diff --git a/qml/AppUI/FullScreenContent.qml b/qml/AppUI/FullScreenContent.qml index a4c4a8b..06de44c 100644 --- a/qml/AppUI/FullScreenContent.qml +++ b/qml/AppUI/FullScreenContent.qml @@ -24,7 +24,41 @@ import org.ukui.menu.core 1.0 import AppControls2 1.0 as AppControls2 RowLayout { + id: root clip: true + signal openFolderSignal(string folderId, string folderName, int x, int y) + signal contentShowFinished() + property bool isContentShow: true + property int animationDuration: 300 + + state: isContentShow ? "contentShow" : "contentHidden" + states: [ + State { + name: "contentHidden" + PropertyChanges { target: root; opacity: 0; scale: 0.95 } + }, + State { + name: "contentShow" + PropertyChanges { target: root; opacity: 1; scale: 1 } + } + ] + + transitions: [ + Transition { + to:"contentHidden" + SequentialAnimation { + PropertyAnimation { properties: "opacity, scale"; duration: animationDuration; easing.type: Easing.InOutCubic } + ScriptAction { script: root.visible = false } + } + }, + Transition { + to: "contentShow" + SequentialAnimation { + PropertyAnimation { properties: "opacity, scale"; duration: animationDuration; easing.type: Easing.InOutCubic } + ScriptAction { script: root.contentShowFinished() } + } + } + ] Item { Layout.preferredWidth: 145 @@ -42,7 +76,7 @@ RowLayout { interactive: contentHeight > parent.height spacing: 5 - highlightMoveDuration: 300 + highlightMoveDuration: animationDuration highlight: AppControls2.StyleBackground { width: labelListView.maxLabelWidth; height: 30 radius: 4 @@ -73,7 +107,6 @@ RowLayout { model: modelManager.getLabelModel() delegate: MouseArea { - id: labelMouseArea width: labelListView.maxLabelWidth height: 30 hoverEnabled: true @@ -82,6 +115,7 @@ RowLayout { paletteRole: Palette.HighlightedText elide: Text.ElideRight horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter text: model.displayName } onClicked: { @@ -136,6 +170,7 @@ RowLayout { ScrollBar.vertical: fullScreenScrollBar cellWidth: contentViewBase.cellWidth cellHeight: contentViewBase.cellHeight + boundsBehavior: Flickable.StopAtBounds model: modelManager.getAppModel() delegate: Loader { @@ -143,6 +178,7 @@ RowLayout { height: width property int index: model.index property int type: model.type + property string id: model.id property string name: model.name property string icon: model.icon sourceComponent: { @@ -150,7 +186,7 @@ RowLayout { return appComponent; } if (type === DataType.Folder) { - return folderComponent; + return normalFolderComponent; } } } @@ -159,17 +195,17 @@ RowLayout { id: appComponent Item { MouseArea { - id: appMouseArea anchors.centerIn: parent hoverEnabled: true width: 170; height: width + acceptedButtons: Qt.LeftButton | Qt.RightButton AppControls2.StyleBackground { anchors.fill: parent useStyleTransparent: false paletteRole: Palette.Light radius: 16 - alpha: appMouseArea.containsPress ? 0.25 : appMouseArea.containsMouse ? 0.15 : 0.00 + alpha: parent.containsPress ? 0.25 : parent.containsMouse ? 0.15 : 0.00 AppControls2.IconLabel { anchors.fill: parent iconWidth: 96; iconHeight: 96 @@ -180,7 +216,14 @@ RowLayout { } onClicked: { - parent.parent.GridView.view.model.appClicked(index); + if (mouse.button === Qt.RightButton) { + parent.parent.GridView.view.model.openMenu(index); + return; + } + if (mouse.button === Qt.LeftButton) { + parent.parent.GridView.view.model.appClicked(index); + return; + } } } } @@ -188,18 +231,65 @@ RowLayout { } Component { - id: folderComponent + id: normalFolderComponent Item { MouseArea { anchors.centerIn: parent - width: 100; height: 140 - AppControls2.IconLabel { + hoverEnabled: true + width: 170; height: width + acceptedButtons: Qt.LeftButton | Qt.RightButton + + AppControls2.StyleBackground { anchors.fill: parent - iconWidth: 96 - iconHeight: 96 - appName: name - appIcon: icon + useStyleTransparent: false + paletteRole: Palette.Light + radius: 16 + alpha: parent.containsPress ? 0.25 : parent.containsMouse ? 0.15 : 0.00 + + ColumnLayout { + height: 128; width: parent.width + anchors.centerIn: parent + spacing: 8 + AppControls2.FolderIcon { + id: folderIcon + Layout.margins: 5 + rows: 4; columns: 4 + spacing: 2; padding: 8 + icons: icon + radius: 16; alpha: 0.25 + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: 86; Layout.preferredHeight: 86 + } + AppControls2.StyleText { + Layout.fillWidth: true; Layout.fillHeight: true + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideRight + text: name + font.pixelSize: 14 + paletteRole: Palette.HighlightedText + } + } } + + onClicked: { + if (mouse.button === Qt.RightButton) { + parent.parent.GridView.view.model.openMenu(index); + return; + } + if (mouse.button === Qt.LeftButton) { + var x = folderIcon.mapToGlobal(0,0).x; + var y = folderIcon.mapToGlobal(0,0).y + openFolderSignal(id, name, x, y); + root.isContentShow = false; + opacity = 0; + return; + } + } + function resetOpacity() { + opacity = 1; + } + Component.onCompleted: root.contentShowFinished.connect(resetOpacity) + Component.onDestruction: root.contentShowFinished.disconnect(resetOpacity) } } } @@ -214,6 +304,7 @@ RowLayout { ScrollBar.vertical: fullScreenScrollBar contentHeight: labelColumn.height flickableDirection: Flickable.VerticalFlick + boundsBehavior: Flickable.StopAtBounds interactive: !contentYAnimation.running Column { @@ -268,7 +359,6 @@ RowLayout { height: GridView.view.cellHeight MouseArea { - id: labelAppMouseArea anchors.centerIn: parent hoverEnabled: true width: 170; height: width @@ -278,7 +368,7 @@ RowLayout { useStyleTransparent: false paletteRole: Palette.Light radius: 16 - alpha: labelAppMouseArea.containsPress ? 0.25 : labelAppMouseArea.containsMouse ? 0.15 : 0.00 + alpha: parent.containsPress ? 0.25 : parent.containsMouse ? 0.15 : 0.00 AppControls2.IconLabel { anchors.fill: parent iconWidth: 96; iconHeight: 96 @@ -303,7 +393,7 @@ RowLayout { id: contentYAnimation target: labelViewFlickable property: "contentY" - duration: 300 + duration: animationDuration onFinished: { labelViewFlickable.returnToBounds(); } diff --git a/qml/AppUI/FullScreenFolder.qml b/qml/AppUI/FullScreenFolder.qml new file mode 100644 index 0000000..8329f93 --- /dev/null +++ b/qml/AppUI/FullScreenFolder.qml @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2023, KylinSoft Co., Ltd. + * + * 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 . + * + */ + +import QtQuick 2.0 +import QtQuick.Layouts 1.12 +import org.ukui.menu.core 1.0 +import AppControls2 1.0 as AppControls2 + +Item { + property alias model: folderGridView.model + property string folderName: "" + property int margins: 20 + property int folderX: 0 + property int folderY: 0 + property bool isFolderOpened: false + property int animationDuration: 300 + + AppControls2.StyleBackground { + id: folderIconBase + paletteRole: Palette.Text + useStyleTransparent: false + property int folderIconSize: 0 + property int iconSpacing: 0 + property int imageX: 0 + property int imageY: 0 + alpha: 0.25 + + state: isFolderOpened ? "folderOpened" : "folderHidden" + states: [ + State { + name: "folderOpened" + PropertyChanges { + target: folderIconBase + width: 720; height: folderGridView.viewMaxHeight; radius: 36 + x: (parent.width - width) / 2; y: (parent.height - height) / 2 + folderIconSize: 96; iconSpacing: 8 + imageX: 37; imageY: 17 + } + PropertyChanges { target: folderGridView; anchors.margins: margins } + PropertyChanges { target: folderNameText; opacity: 1 } + }, + State { + name: "folderHidden" + PropertyChanges { + target: folderIconBase + width: 86; height: width; radius: 16 + x: parent.parent.mapFromGlobal(folderX, 0).x; y: parent.parent.mapFromGlobal(0, folderY).y + folderIconSize: 16; iconSpacing: 0 + imageX: 0; imageY: 0 + } + PropertyChanges { target: folderGridView; anchors.margins: 8 } + PropertyChanges { target: folderNameText; opacity: 0 } + } + ] + transitions: [ + Transition { + to: "folderHidden" + SequentialAnimation { + ScriptAction { script: folderGridView.positionViewAtBeginning() } + ParallelAnimation { + PropertyAnimation { + duration: animationDuration; easing.type: Easing.InOutCubic + properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, anchors.margins" + } + PropertyAnimation { + duration: animationDuration; easing.type: Easing.OutQuint + properties: "opacity" + } + } + ScriptAction { script: parent.active = false } + } + }, + Transition { + to: "folderOpened" + ParallelAnimation { + PropertyAnimation { + duration: animationDuration; easing.type: Easing.InOutCubic + properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, anchors.margins" + } + PropertyAnimation { + duration: animationDuration; easing.type: Easing.InQuint + properties: "opacity" + } + } + } + ] + + GridView { + id: folderGridView + anchors.fill: parent + cellHeight: width / 4; cellWidth: cellHeight + boundsBehavior: Flickable.StopAtBounds + property int viewMaxHeight: Math.ceil(count / 4) * 170 > width ? width + margins*2 : (Math.ceil(count / 4) * 170 + margins*2) + model: modelManager.getFolderModel() + delegate: MouseArea { + hoverEnabled: true + width: GridView.view.cellHeight; height: width + acceptedButtons: Qt.LeftButton | Qt.RightButton + + AppControls2.StyleBackground { + anchors.fill: parent + useStyleTransparent: false + paletteRole: Palette.Light + radius: 16 + alpha: parent.containsPress ? 0.25 : parent.containsMouse ? 0.15 : 0.00 + + Image { + id: iconImage + source: icon + height: folderIconBase.folderIconSize; width: height + x: folderIconBase.imageX; y: folderIconBase.imageY + } + + AppControls2.StyleText { + width: parent.width + horizontalAlignment: Text.AlignHCenter + anchors.top: iconImage.bottom + anchors.topMargin: folderIconBase.iconSpacing + anchors.horizontalCenter: parent.horizontalCenter + text: name + font.pixelSize: 14 + elide: Text.ElideRight + paletteRole: Palette.HighlightedText + } + } + onClicked: { + if (mouse.button === Qt.RightButton) { + menuManager.showMenu(id); + return; + } + if (mouse.button === Qt.LeftButton) { + appManager.launchApp(id); + return; + } + } + } + } + } + + EditText { + id: folderNameText + anchors.bottom: folderGridView.parent.top + anchors.bottomMargin: 30 + anchors.horizontalCenter: folderGridView.parent.horizontalCenter + height: 47; width: folderGridView.width + textEdited: folderName + textCenterIn: true + isFullScreenFolder: true + } +} diff --git a/qml/AppUI/FullScreenHeader.qml b/qml/AppUI/FullScreenHeader.qml index 2b644ab..333a4f0 100644 --- a/qml/AppUI/FullScreenHeader.qml +++ b/qml/AppUI/FullScreenHeader.qml @@ -7,10 +7,13 @@ import org.ukui.menu.utils 1.0 Item { clip: true + property alias searchOpacity: searchInputBar.opacity SearchInputBar { + id: searchInputBar width: 372; height: 36 anchors.centerIn: parent radius: height / 2 + visible: opacity onTextChanged: { if (text === "") { @@ -20,6 +23,9 @@ Item { appPageHeaderUtils.startSearch(text); } } + Behavior on opacity { + NumberAnimation { duration: 300; easing.type: Easing.InOutCubic } + } } PluginSelectMenu { diff --git a/qml/AppUI/FullScreenUI.qml b/qml/AppUI/FullScreenUI.qml index aafb911..3c7b95f 100644 --- a/qml/AppUI/FullScreenUI.qml +++ b/qml/AppUI/FullScreenUI.qml @@ -5,6 +5,20 @@ import org.ukui.menu.core 1.0 AppControls2.StyleBackground { paletteRole: Palette.Dark + MouseArea { + anchors.fill: parent + onClicked: { + if (fullScreenContent.visible) { + //执行全屏退出操作 + forceActiveFocus(); + mainWindow.hide(); + } else { + folderLoader.item.isFolderOpened = false; + fullScreenContent.visible = true; + fullScreenContent.isContentShow = true; + } + } + } ColumnLayout { anchors.fill: parent @@ -12,20 +26,43 @@ AppControls2.StyleBackground { anchors.rightMargin: 35 FullScreenHeader { - // full screen header + id: fullScreenHeader Layout.preferredHeight: 130 Layout.fillWidth: true Layout.maximumHeight: 130 + searchOpacity: fullScreenContent.isContentShow ? 1 : 0 } - FullScreenContent { - // full screen content + Item { Layout.fillHeight: true Layout.fillWidth: true + + FullScreenContent { + id: fullScreenContent + anchors.fill: parent + } + + Loader { + id: folderLoader + active: false + anchors.fill: parent + sourceComponent: FullScreenFolder {} + + function openFolder(id, name, x, y) { + active = true; + item.model.setFolderId(id); + item.folderName = name; + item.folderX = x; + item.folderY = y; + item.isFolderOpened = true; + } + + Component.onCompleted: fullScreenContent.openFolderSignal.connect(openFolder) + Component.onDestruction: fullScreenContent.openFolderSignal.disconnect(openFolder) + } } FullScreenFooter { - // full screen footer Layout.preferredHeight: 90 Layout.fillWidth: true } diff --git a/qml/AppUI/SearchInputBar.qml b/qml/AppUI/SearchInputBar.qml index d92384a..59d2381 100644 --- a/qml/AppUI/SearchInputBar.qml +++ b/qml/AppUI/SearchInputBar.qml @@ -52,6 +52,7 @@ AppControls2.StyleBackground { width: parent.height / 2; height: width source: "image://appicon/search-symbolic" highLight: mainWindow.isFullScreen + autoHighLight: !mainWindow.isFullScreen } } @@ -119,7 +120,11 @@ AppControls2.StyleBackground { visible: mainWindow.isFullScreen && textInput.activeFocus buttonIcon: "image://appicon/edit-clear-symbolic" highlight: true + autoHighLight: false - onClicked: textInput.clear(); + onClicked: { + textInput.clear(); + textInput.focus = false; + } } } diff --git a/qml/qml.qrc b/qml/qml.qrc index fe98c4a..2c19037 100644 --- a/qml/qml.qrc +++ b/qml/qml.qrc @@ -34,5 +34,6 @@ AppUI/AppPageContent.qml AppUI/PluginSelectMenu.qml AppUI/EditText.qml + AppUI/FullScreenFolder.qml