feat(qml):调整全屏下收藏区域和应用组显示和三态

This commit is contained in:
qiqi49 2024-02-01 18:55:21 +08:00
parent 85f4aaeb4c
commit af78dcad59
15 changed files with 473 additions and 392 deletions

View File

@ -28,9 +28,7 @@ Item {
property bool textCenterIn: false
property bool editStatus: false
property string textEdited: title
property bool isFullScreen: false
property bool isFolder: false
property real textInputSize: 14
property real textSize
signal textEditingFinished(string text)
Component {
@ -41,21 +39,14 @@ Item {
horizontalAlignment: contain.textCenterIn ? Text.AlignHCenter : Text.AlignLeft
elide: Text.ElideRight
text: contain.textEdited
paletteRole: isFullScreen ? Platform.Theme.HighlightedText : Platform.Theme.Text
font.bold: isFolder
// AppControls2 StyleText
property real textUltra: 2*systemFontSize
property real systemFontSize: 16
font.pointSize:(isFolder && isFullScreen) ? textUltra : systemFontSize
paletteRole: Platform.Theme.Text
font.bold: true
font.pointSize: textSize
MouseArea {
id: textArea
anchors.fill: parent
onDoubleClicked: {
contain.editStatus = true;
contain.textInputSize = textShow.font.pointSize;
}
onDoubleClicked: contain.editStatus = true;
}
}
}
@ -84,8 +75,7 @@ Item {
text: contain.textEdited
selectByMouse: true
maximumLength: 14
font.bold: !isFolder
font.pointSize: contain.textInputSize
font.pointSize: textSize
onEditingFinished: {
// modelManager.getFolderModel().renameFolder(text);
@ -95,7 +85,7 @@ Item {
}
function updateTextInputColor() {
color = isFullScreen ? Platform.Theme.highlightedText() : Platform.Theme.text();
color = Platform.Theme.text();
selectionColor = Platform.Theme.highlight();
}

View File

@ -43,29 +43,25 @@ MouseArea {
ColumnLayout {
anchors.fill: parent
anchors.topMargin: 16
spacing: 0
anchors.bottomMargin: 16
spacing: 8
UkuiItems.Icon {
id: appIcon
Layout.minimumWidth: 32
Layout.minimumHeight: 32
Layout.maximumWidth: 96
Layout.maximumHeight: 96
Layout.preferredWidth: 96
Layout.preferredHeight: 96
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Layout.preferredWidth: styleBackground.width * 0.6
Layout.preferredHeight: width
Layout.alignment: Qt.AlignHCenter
}
UkuiItems.StyleText {
id: appName
Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredHeight: contentHeight
Layout.maximumHeight: contentHeight
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
paletteRole: Platform.Theme.Text
horizontalAlignment: Text.AlignHCenter
}
}
}

View File

@ -24,6 +24,7 @@ import QtQuick.Layouts 1.12
import org.ukui.menu.core 1.0
import org.ukui.menu.extension 1.0
import "../extensions" as Extension
import AppControls2 1.0 as AppControls2
import org.ukui.quick.items 1.0 as UkuiItems
@ -31,8 +32,14 @@ import org.ukui.quick.platform 1.0 as Platform
ListView {
id: root
signal openFolderSignal(string folderId, string folderName, int x, int y)
signal contentShowFinished()
property bool isContentShow
property int itemHeight: 40
property alias sourceModel: appGroupModel.sourceModel
// TODO:
property int column: 10
spacing: 5
clip: true
@ -61,8 +68,7 @@ ListView {
GridView {
width: parent.width
height: childrenRect.height
// TODO:
cellWidth: width / 8
cellWidth: width / root.column
cellHeight: cellWidth
interactive: false
@ -98,67 +104,68 @@ ListView {
}
header: Item {
width: ListView.view.width
height: childrenRect.height + ListView.view.spacing
width: root.width
height: childrenRect.height
property alias widgets: widgetView.widgets
property alias widgetCount: widgetView.count
property alias widgetInfos: widgetView.widgetInfos
property var widgets: []
property var widgetInfos: []
property int widgetCount: 1
ListView {
id: widgetView
Component.onCompleted: {
widgetInfos.push({label: "favorite", display: "non-starred-symbolic", type: WidgetMetadata.Widget});
widgets.push("favorite");
}
property var widgets: []
property var widgetInfos: []
anchors.top: parent.top
Column {
width: parent.width
height: childrenRect.height
interactive: false
spacing: parent.ListView.view.spacing
height: childrenRect.height + spacing
spacing: root.spacing
onCountChanged: {
widgets = [];
widgetInfos = [];
for (let i = 0; i < count; ++i) {
let item = itemAtIndex(i);
widgetInfos.push({label: item.widgetId, display: item.icon, type: LabelItem.Icon});
widgets.push(item.widgetId);
}
AppControls2.LabelItem {
width: parent.width
height: root.itemHeight
displayName: qsTr("Favorite")
}
model: WidgetModel {
flags: WidgetMetadata.OnlyFullScreen
}
delegate: Column {
property string icon: model.icon
property string widgetId: model.id
GridView {
id: favoriteView
width: parent.width
height: contentHeight
property string mergeToAppId: ""
property bool isMergeToFolder: false
property bool dragTypeIsMerge: false
property int exchangedStartIndex: 0
property alias viewModel: visualModel
width: ListView.view.width
height: childrenRect.height
spacing: ListView.view.spacing
cellWidth: width / root.column
cellHeight: cellWidth
model: DelegateModel {
id: visualModel
model: favoriteModel
delegate: Item {
id: container
width: favoriteView.cellWidth
height: favoriteView.cellHeight
Extension.FavoriteDelegate {
anchors.fill: parent
anchors.margins: 12
AppControls2.LabelItem {
width: parent.width
height: root.itemHeight
displayName: model.name
}
visualIndex: container.DelegateModel.itemsIndex
delegateLayout.anchors.topMargin: 16
delegateLayout.anchors.bottomMargin: 16
delegateLayout.spacing: 8
mergePrompt.anchors.topMargin: 10
mergePrompt.width: width*0.67
mergePrompt.radius: 32
Loader {
width: parent.width
// height: item === null ? 0 : item.height
height: item === null ? 0 : 200
property var extensionData: model.data
onExtensionDataChanged: {
if (item !== null) {
item.extensionData = extensionData;
Component.onCompleted: contentShowFinished.connect(resetOpacity)
Component.onDestruction: contentShowFinished.disconnect(resetOpacity)
}
}
}
Component.onCompleted: {
setSource(model.main, {extensionData: extensionData});
}
displaced: Transition {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad; duration: 200 }
}
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts 1.12
import QtQml.Models 2.12
import org.ukui.menu.core 1.0
import "../extensions" as Extension
import AppControls2 1.0 as AppControls2
import org.ukui.quick.items 1.0 as UkuiItems
@ -19,16 +20,54 @@ UkuiItems.StyleBackground {
forceActiveFocus();
mainWindow.hide();
} else {
mainContainer.visible = true;
folderLoader.isFolderOpened = false;
}
}
}
Extension.FullScreenFolder {
id: folderLoader
anchors.fill: parent
folderModel: FolderModel
Component.onCompleted: fullScreenAppList.openFolderSignal.connect(initFolder)
Component.onDestruction: fullScreenAppList.openFolderSignal.disconnect(initFolder)
}
Item {
id: mainContainer
anchors.fill: parent
z: 10
state: !fullScreenAppList.isContentShow ? "contentShow" : "contentHidden"
states: [
State {
name: "contentHidden"
PropertyChanges { target: mainContainer; opacity: 0; scale: 0.95 }
},
State {
name: "contentShow"
PropertyChanges { target: mainContainer; opacity: 1; scale: 1 }
}
]
transitions: [
Transition {
to:"contentHidden"
SequentialAnimation {
PropertyAnimation { properties: "opacity, scale"; duration: 300; easing.type: Easing.InOutCubic }
ScriptAction { script: mainContainer.visible = false }
}
},
Transition {
to: "contentShow"
SequentialAnimation {
ScriptAction { script: mainContainer.visible = true }
PropertyAnimation { properties: "opacity, scale"; duration: 300; easing.type: Easing.InOutCubic }
}
}
]
//
GridLayout {
anchors.fill: parent
@ -168,6 +207,7 @@ UkuiItems.StyleBackground {
Layout.fillHeight: true
sourceModel: AppPageBackend.appModel
isContentShow: folderLoader.isFolderOpened
function positionLabel(label) {
// Widget
@ -195,7 +235,9 @@ UkuiItems.StyleBackground {
Component.onCompleted: {
positionViewAtBeginning();
folderLoader.turnPageFinished.connect(contentShowFinished)
}
Component.onDestruction: folderLoader.turnPageFinished.disconnect(contentShowFinished)
}
}
}

View File

@ -10,33 +10,100 @@ import AppControls2 1.0 as AppControls2
UkuiItems.StyleBackground {
id: iconItem
property bool hold: false
property alias draggedIcon: itemLoader
property alias delegateLayout: itemLayout
property alias mergePrompt: mergePrompt
radius: 8
useStyleTransparency: false
paletteRole: Platform.Theme.Text
alpha: hold ? 0 : control.containsPress ? 0.15 : control.containsMouse ? 0.08 : 0
// 52*52
property int visualIndex
Binding { target: itemLoader; property: "visualIndex"; value: visualIndex }
// 52*52
UkuiItems.StyleBackground {
width: 52
id: mergePrompt
height: width
radius: 14
anchors.top: parent.top
anchors.margins: 6
anchors.horizontalCenter: parent.horizontalCenter
paletteRole: Platform.Theme.Text
useStyleTransparency: false
alpha: (delegateDropArea.enterSourceId !== model.id)
&& delegateDropArea.containsDrag && dragTypeIsMerge ? 0.15 : 0
&& delegateDropArea.containsDrag && favoriteView.dragTypeIsMerge ? 0.15 : 0
z: -1
}
DropArea {
id: delegateDropArea
anchors.fill: parent
anchors.margins: 10
property string enterSourceId: ""
// drag.source [itemLoader]
onEntered: {
if (drag.source.isFolder) {
return;
}
enterSourceId = drag.source.sourceId;
delegateDropTimer.running = true;
}
onExited: {
if (delegateDropTimer.timeOutCount < 1) {
favoriteView.dragTypeIsMerge = false;
favoriteView.viewModel.items.move(drag.source.visualIndex, iconItem.visualIndex);
}
delegateDropTimer.running = false;
enterSourceId = "";
}
}
Timer {
id: delegateDropTimer
property int timeOutCount: 0
interval: 300
repeat: true
onTriggered: {
++timeOutCount;
if (timeOutCount == 1) {
favoriteView.mergeToAppId = model.id;
favoriteView.isMergeToFolder = (model.type === DataType.Folder);
favoriteView.dragTypeIsMerge = true;
}
}
onRunningChanged: timeOutCount = 0
}
MouseArea {
id: control
anchors.fill: parent
hoverEnabled: true
pressAndHoldInterval: 300
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
itemLoader.item.itemClicked(mouse.button);
}
onPressAndHold: {
if (mouse.button === Qt.LeftButton) {
drag.target = itemLoader;
iconItem.hold = true;
favoriteView.exchangedStartIndex = itemLoader.visualIndex;
itemLoader.sourceId = model.id;
}
}
onReleased: {
drag.target = null;
}
}
ColumnLayout {
id: itemLayout
width: parent.width
anchors.top: parent.top
anchors.fill: parent
anchors.topMargin: 8
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottomMargin: 14
spacing: 6
ToolTip.visible: iconText.truncated && control.containsMouse
@ -45,8 +112,8 @@ UkuiItems.StyleBackground {
Item {
id: loaderBase
Layout.preferredHeight: 48
Layout.preferredWidth: 48
Layout.preferredWidth: iconItem.width * 0.6
Layout.preferredHeight: width
Layout.alignment: Qt.AlignHCenter
Loader {
@ -63,7 +130,9 @@ UkuiItems.StyleBackground {
if (Drag.active) {
itemLoader.parent = favoriteView;
} else {
if (dragTypeIsMerge && (model.id !== mergeToAppId) && (model.type === DataType.Normal)) {
if (favoriteView.dragTypeIsMerge
&& (model.id !== favoriteView.mergeToAppId)
&& (model.type === DataType.Normal)) {
iconItem.hold = false;
} else {
@ -116,6 +185,8 @@ UkuiItems.StyleBackground {
UkuiItems.StyleText {
id: iconText
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
Layout.maximumHeight: contentHeight
text: name
elide: Text.ElideRight
@ -140,7 +211,7 @@ UkuiItems.StyleBackground {
function itemClicked(mouseButton) {
if (mouseButton === Qt.RightButton) {
visualModel.model.openMenu(index)
favoriteModel.openMenu(index)
} else {
var data = {"id": model.id};
send(data);
@ -154,24 +225,26 @@ UkuiItems.StyleBackground {
Item {
AppControls2.FolderIcon {
id: folderIcon
width: 40
height: 40
height: width
anchors.centerIn: parent
rows: 2; columns: 2
spacing: 2; padding: 2
alpha: 0.10
icons: icon
radius: 4; alpha: 0.10
columns: rows
width: mainWindow.isFullScreen ? 84: 40
rows: mainWindow.isFullScreen ? 4 : 2
spacing: mainWindow.isFullScreen ? 4 : 2
padding: mainWindow.isFullScreen ? 8 : 2
radius: mainWindow.isFullScreen ? 16 :4
}
function itemClicked(mouseButton) {
if (mouseButton === Qt.RightButton) {
visualModel.model.openMenu(index);
favoriteModel.openMenu(index);
} else {
var x = mapToGlobal(folderIcon.x, folderIcon.y).x;
var y = mapToGlobal(folderIcon.x, folderIcon.y).y
openFolderSignal(id, name, x, y);
//
favoriteView.isContentShow = false;
opacity = 0;
control.enabled = false;
control.hoverEnabled = false;
@ -180,52 +253,27 @@ UkuiItems.StyleBackground {
}
}
MouseArea {
id: control
anchors.fill: parent
hoverEnabled: true
pressAndHoldInterval: 300
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
itemLoader.item.itemClicked(mouse.button);
}
onPressAndHold: {
if (mouse.button === Qt.LeftButton) {
drag.target = itemLoader;
iconItem.hold = true;
exchangedStartIndex = itemLoader.visualIndex;
itemLoader.sourceId = model.id;
}
}
onReleased: {
drag.target = null;
}
}
// folderFunction
function resetOpacity() {
itemLoader.item.opacity = 1;
control.enabled = true;
control.hoverEnabled = true;
}
Component.onCompleted: favoriteView.contentShowFinished.connect(resetOpacity)
Component.onDestruction: favoriteView.contentShowFinished.disconnect(resetOpacity)
onHoldChanged: {
if (hold) {
favoriteView.interactive = false;
} else {
favoriteView.interactive = contentHeight > favoriteView.parent.height;
if (dragTypeIsMerge && (model.id !== mergeToAppId) && (model.type === DataType.Normal)) {
if (isMergeToFolder) {
visualModel.model.addAppToFolder(model.id, mergeToAppId);
if (favoriteView.dragTypeIsMerge && (model.id !== favoriteView.mergeToAppId) && (model.type === DataType.Normal)) {
if (favoriteView.isMergeToFolder) {
favoriteModel.addAppToFolder(model.id, favoriteView.mergeToAppId);
} else {
visualModel.model.addAppsToNewFolder(model.id, mergeToAppId);
favoriteModel.addAppsToNewFolder(model.id, favoriteView.mergeToAppId);
}
} else if (exchangedStartIndex !== itemLoader.visualIndex) {
visualModel.model.exchangedAppsOrder(exchangedStartIndex, itemLoader.visualIndex);
} else if (favoriteView.exchangedStartIndex !== itemLoader.visualIndex) {
favoriteModel.exchangedAppsOrder(favoriteView.exchangedStartIndex, itemLoader.visualIndex);
}
}
}

View File

@ -42,11 +42,9 @@ UkuiMenuExtension {
}
folderLoader.isFolderOpened = false;
favoriteView.visible = true;
favoriteView.isContentShow = true;
}
}
UkuiItems.Menu {
id: menu
content: [
@ -105,6 +103,7 @@ UkuiMenuExtension {
width: parent.width
height: (contentHeight > parent.height) ? parent.height : contentHeight
interactive: contentHeight > parent.height
isContentShow: !folderLoader.isFolderOpened
Component.onCompleted: {
favoriteView.viewModel.model = extensionData.favoriteAppsModel

View File

@ -32,10 +32,9 @@ GridView {
cellHeight: cellWidth + 12
signal openFolderSignal(string folderId, string folderName, int x, int y)
signal contentShowFinished()
property bool isContentShow: true
property bool isContentShow
property int spacing: 4
property int itemHeight: 84
property int column: 5
property alias viewModel: visualModel
@ -66,7 +65,10 @@ GridView {
},
Transition {
to: "contentShow"
PropertyAnimation { properties: "opacity, scale"; duration: 300; easing.type: Easing.InOutCubic }
SequentialAnimation {
ScriptAction { script: favoriteView.visible = true }
PropertyAnimation { properties: "opacity, scale"; duration: 300; easing.type: Easing.InOutCubic }
}
}
]
//
@ -100,12 +102,6 @@ GridView {
currentIndex = currentIndex - column;
}
ScrollBar.vertical: AppControls2.ScrollBar {
id: scrollBar
visible: viewMouseArea.containsMouse
width: 14; height: favoriteView.height
}
displaced: Transition {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad; duration: 200 }
}
@ -117,8 +113,7 @@ GridView {
focus: true
width: favoriteView.cellWidth
height: favoriteView.cellHeight
property int visualIndex: DelegateModel.itemsIndex
Binding { target: iconItem.draggedIcon; property: "visualIndex"; value: visualIndex }
states: State {
when: activeFocus
PropertyChanges {
@ -131,87 +126,48 @@ GridView {
send(data);
}
DropArea {
id: delegateDropArea
anchors.fill: parent
anchors.margins: 14
property string enterSourceId: ""
// drag.source [iconItem.draggedIcon]
onEntered: {
if (drag.source.isFolder) {
return;
}
enterSourceId = drag.source.sourceId;
delegateDropTimer.running = true;
}
onExited: {
if (delegateDropTimer.timeOutCount < 1) {
dragTypeIsMerge = false;
visualModel.items.move(drag.source.visualIndex, iconItem.visualIndex);
}
delegateDropTimer.running = false;
enterSourceId = "";
}
}
Item {
FavoriteDelegate {
id: iconItem
anchors.fill: parent
anchors.margins: 2
Timer {
id: delegateDropTimer
property int timeOutCount: 0
interval: 300
repeat: true
visualIndex: container.DelegateModel.itemsIndex
mergePrompt.anchors.topMargin: 6
mergePrompt.width: 52
mergePrompt.radius: 14
onTriggered: {
++timeOutCount;
if (timeOutCount == 1) {
mergeToAppId = model.id;
isMergeToFolder = (model.type === DataType.Folder);
dragTypeIsMerge = true;
Component.onCompleted: favoriteView.contentShowFinished.connect(resetOpacity)
Component.onDestruction: favoriteView.contentShowFinished.disconnect(resetOpacity)
}
//
Loader {
id: tag
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin: 10
Component {
id: editImage
UkuiItems.Button {
width: 28
height: 28
icon.width: 16
icon.height: 16
background.paletteRole: Platform.Theme.Light
background.alpha: 1
activeFocusOnTab: false
onClicked: {
visualModel.model.removeAppFromFavorites(id);
}
background.radius: width / 2
icon.source: "ukui-cancel-star-symbolic"
}
onRunningChanged: timeOutCount = 0
}
FavoriteDelegate {
id: iconItem
anchors.fill: parent
property int visualIndex: container.DelegateModel.itemsIndex
}
//
Loader {
id: tag
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin: 10
Component {
id: editImage
UkuiItems.Button {
width: 28
height: 28
icon.width: 16
icon.height: 16
background.paletteRole: Platform.Theme.Light
background.alpha: 1
activeFocusOnTab: false
onClicked: {
visualModel.model.removeAppFromFavorites(id);
}
background.radius: width / 2
icon.source: "ukui-cancel-star-symbolic"
}
}
sourceComponent: mainWindow.editMode && (type === DataType.Normal) ? editImage : null
}
sourceComponent: mainWindow.editMode && (type === DataType.Normal) ? editImage : null
}
}
}

View File

@ -23,164 +23,152 @@ import QtQuick.Controls 2.5
import org.ukui.menu.core 1.0
import org.ukui.quick.platform 1.0 as Platform
import org.ukui.quick.items 1.0 as UkuiItems
Item {
SwipeView {
id: folderSwipeView
anchors.margins: contentMargins
property bool needTurnPage: false
property int contentX: contentItem.contentX
property int startContentX: 0
property int startIndex: 0
property var folderContentModel
property alias folderSwipeView: folderSwipeView
property bool mouseEnable: false
property int contentMargins
property int labelMagrins
property int labelSpacing
property bool isFullScreen: false
PageIndicator {
id: pageIndicator
interactive: true
count: folderSwipeView.count
visible: count > 1
currentIndex: folderSwipeView.currentIndex
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
delegate: Rectangle {
color: "grey"
width: (index === folderSwipeView.currentIndex )? 20 : 6; height: 6;
radius: width / 2
opacity: (index === folderSwipeView.currentIndex )? 1 : 0.6
Behavior on width {
NumberAnimation { duration: 300; easing.type: Easing.InOutCubic }
}
function hideFolder() {
//
if (currentIndex > 0) {
interactive = false;
needTurnPage = true;
pageIndicator.visible = false;
contentItem.highlightFollowsCurrentItem = true;
contentItem.highlightMoveDuration = 300;
contentItem.highlightMoveVelocity = -1;
startContentX = contentX;
startIndex = currentIndex;
currentIndex = 0;
//
} else {
reset();
}
}
SwipeView {
id: folderSwipeView
anchors.fill: parent
anchors.margins: contentMargins
property bool needTurnPage: false
property int contentX: contentItem.contentX
property int startContentX: 0
property int startIndex: 0
function reset() {
interactive = true;
root.active = false;
pageIndicator.visible = false;
turnPageFinished();
}
function hideFolder() {
//
if (currentIndex > 0) {
interactive = false;
needTurnPage = true;
pageIndicator.visible = false;
contentItem.highlightFollowsCurrentItem = true;
contentItem.highlightMoveDuration = 300;
contentItem.highlightMoveVelocity = -1;
startContentX = contentX;
startIndex = currentIndex;
currentIndex = 0;
//
} else {
reset();
}
//
onContentXChanged: {
//
if (needTurnPage && startContentX - contentX === startIndex * width) {
needTurnPage = false;
reset();
}
}
function reset() {
interactive = true;
root.active = false;
pageIndicator.visible = false;
turnPageFinished();
}
Repeater {
model: Math.ceil(folderModel.count / 16)
//
onContentXChanged: {
//
if (needTurnPage && startContentX - contentX === startIndex * 86) {
needTurnPage = false;
reset();
}
}
Item {
id: base
property int currentPage: SwipeView.index
Repeater {
model: Math.ceil(folderModel.count / 16)
GridView {
id: folderGridView
cellHeight: isFullScreen ? cellWidth : (cellWidth + 12)
cellWidth: width / 4
anchors.fill: parent
interactive: false
Item {
id: base
property int currentPage: SwipeView.index
model: DelegateModel {
property int maxItemNumPerPage: 16
filterOnGroup: "folderContent"
groups: DelegateModelGroup {
name: "folderContent"
}
GridView {
id: folderGridView
cellHeight: isFullScreen ? cellWidth : (cellWidth + 12)
cellWidth: width / 4
anchors.fill: parent
interactive: false
model: DelegateModel {
property int maxItemNumPerPage: 16
filterOnGroup: "folderContent"
groups: DelegateModelGroup {
name: "folderContent"
items.onChanged: {
var groupIndex = groups.length - 1;
if (groups[groupIndex].count !== 0) {
groups[groupIndex].remove(0, groups[groupIndex].count);
}
items.onChanged: {
var groupIndex = groups.length - 1;
if (groups[groupIndex].count !== 0) {
groups[groupIndex].remove(0, groups[groupIndex].count);
}
for (var i = base.currentPage * maxItemNumPerPage;
i < Math.min((base.currentPage + 1) * maxItemNumPerPage, items.count); i ++) {
items.addGroups(i, 1, "folderContent");
}
for (var i = base.currentPage * maxItemNumPerPage;
i < Math.min((base.currentPage + 1) * maxItemNumPerPage, items.count); i ++) {
items.addGroups(i, 1, "folderContent");
}
}
onCountChanged: {
if (count === 0) {
reset();
folderLoader.isFolderOpened = false;
}
}
model: folderContentModel
delegate: Item {
width: folderGridView.cellWidth
height: folderGridView.cellHeight
model: folderContentModel
delegate: Item {
width: folderGridView.cellWidth
height: folderGridView.cellHeight
MouseArea {
hoverEnabled: true
enabled: mouseEnable
MouseArea {
hoverEnabled: true
enabled: mouseEnable
anchors.fill: parent
anchors.margins: labelMagrins
acceptedButtons: Qt.LeftButton | Qt.RightButton
UkuiItems.StyleBackground {
anchors.fill: parent
anchors.margins: 2
acceptedButtons: Qt.LeftButton | Qt.RightButton
useStyleTransparency: false
paletteRole: Platform.Theme.Text
radius: Platform.Theme.maxRadius
alpha: parent.containsPress ? 0.15 : parent.containsMouse ? 0.08 : 0.00
clip: false
UkuiItems.StyleBackground {
ColumnLayout {
anchors.fill: parent
useStyleTransparency: false
paletteRole: isFullScreen ? Platform.Theme.Light : Platform.Theme.Text
radius: Platform.Theme.maxRadius
alpha: parent.containsPress ? 0.25 : parent.containsMouse ? 0.15 : 0.00
clip: false
anchors.margins: labelSpacing
spacing: (parent.width > 40) ? 4 : 0
Image {
id: iconImage
source: icon
Layout.minimumHeight: 16
Layout.minimumWidth: 16
Layout.maximumWidth: 96
Layout.maximumHeight: 96
ColumnLayout {
anchors.fill: parent
anchors.margins: labelMagrins
spacing: (parent.width > 40) ? 4 : 0
Image {
id: iconImage
source: icon
Layout.minimumHeight: 16
Layout.minimumWidth: 16
Layout.fillHeight: true
Layout.preferredWidth: height
Layout.alignment: Qt.AlignHCenter
}
Layout.fillHeight: true
Layout.preferredWidth: height
Layout.alignment: Qt.AlignHCenter
}
UkuiItems.StyleText {
text: name
elide: Text.ElideRight
paletteRole: isFullScreen ? Platform.Theme.HighlightedText : Platform.Theme.Text
UkuiItems.StyleText {
text: name
elide: Text.ElideRight
paletteRole: Platform.Theme.Text
Layout.preferredHeight: contentHeight
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
}
Layout.preferredHeight: contentHeight
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
}
}
onClicked: {
if (mouse.button === Qt.RightButton) {
menuManager.showMenu(id, MenuInfo.Folder);
return;
}
if (mouse.button === Qt.LeftButton) {
appManager.launchApp(id);
return;
}
}
onClicked: {
if (mouse.button === Qt.RightButton) {
menuManager.showMenu(id, MenuInfo.Folder);
return;
}
if (mouse.button === Qt.LeftButton) {
appManager.launchApp(id);
return;
}
}
}
@ -190,4 +178,3 @@ Item {
}
}
}

View File

@ -55,7 +55,7 @@ Loader {
Component {
id: folderComponent
Item {
UkuiItems.StyleBackground {
UkuiItems.StyleBackground {
id: folderIconBase
paletteRole: Platform.Theme.Text
useStyleTransparency: false
@ -72,7 +72,7 @@ Loader {
PropertyChanges {
target: folderIconBase
width: 348
height: viewMaxRow * 100
height: viewMaxRow * 100 // itemHeight:96 + spacing:4
radius: Platform.Theme.maxRadius
x: (parent.width - width) / 2
y: 82
@ -81,7 +81,8 @@ Loader {
PropertyChanges {
target: content
contentMargins: 0
labelMagrins: 8
labelSpacing: 8
labelMagrins: 2
}
PropertyChanges { target: folderNameText; opacity: 1 }
},
@ -99,6 +100,7 @@ Loader {
PropertyChanges {
target: content
contentMargins: 3
labelSpacing: 0
labelMagrins: 0
}
PropertyChanges { target: folderNameText; opacity: 0 }
@ -120,7 +122,7 @@ Loader {
}
PropertyAnimation {
duration: animationDuration; easing.type: Easing.OutQuint
properties: "contentMargins, labelMagrins"
properties: "contentMargins, labelMagrins, labelSpacing"
}
}
ScriptAction { script: content.folderSwipeView.hideFolder() }
@ -140,7 +142,7 @@ Loader {
}
PropertyAnimation {
duration: animationDuration; easing.type: Easing.OutQuint
properties: "contentMargins, labelMagrins"
properties: "contentMargins, labelMagrins, labelSpacing"
}
}
ScriptAction {
@ -160,6 +162,23 @@ Loader {
}
}
PageIndicator {
id: pageIndicator
interactive: true
count: content.count
visible: count > 1
currentIndex: content.currentIndex
anchors.top: folderIconBase.bottom
anchors.horizontalCenter: folderIconBase.horizontalCenter
delegate: Rectangle {
color: "black"
width: 6; height: width;
radius: width / 2
opacity: (index === content.currentIndex )? 0.9 : 0.3
}
}
AppUI.EditText {
id: folderNameText
anchors.bottom: folderIconBase.top
@ -169,9 +188,7 @@ Loader {
height: 47; width: folderIconBase.width
textEdited: folderName
textCenterIn: true
isFolder: true
isFullScreen: isFullScreen
textInputSize: 16
textSize: 16
onTextEditingFinished: text=> {
folderModel.renameFolder(text);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2023, KylinSoft Co., Ltd.
* Copyright (C) 2024, 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
@ -23,6 +23,7 @@ import QtQuick.Controls 2.5
import org.ukui.menu.core 1.0
import org.ukui.quick.platform 1.0 as Platform
import org.ukui.quick.items 1.0 as UkuiItems
import AppUI 1.0 as AppUI
Loader {
id: root
@ -34,13 +35,12 @@ Loader {
property int viewMaxRow: 0
property bool isFolderOpened: false
property bool isFullScreen: true
property int margins: isFullScreen? 20 : 0
property int margins: 20
property int animationDuration: 300
signal turnPageFinished()
function initFolder(id, name, x, y) {
extensionData.folderModel.setFolderId(id);
FolderModel.setFolderId(id);
folderName = name;
folderX = x;
folderY = y;
@ -58,12 +58,13 @@ Loader {
id: folderIconBase
paletteRole: Platform.Theme.Text
useStyleTransparency: false
alpha: 0.1
property int folderIconSize: 0
property int iconSpacing: 0
property int imageX: 0
property int imageY: 0
property int gridViewMargin: 8
alpha: 0.25
state: isFolderOpened ? "folderOpened" : "folderHidden"
states: [
@ -71,17 +72,17 @@ Loader {
name: "folderOpened"
PropertyChanges {
target: folderIconBase
width: isFullScreen ? 720 : 348
height: isFullScreen ? (viewMaxRow * 170 + margins * 2) : (viewMaxRow * 85 + margins * 2)
radius: Platform.Theme.maxRadius
gridViewMargin: margins
x: isFullScreen ? (parent.width - width) / 2 : 56
y: isFullScreen ? (parent.height - height) / 2 : 104
//
folderIconSize:isFullScreen ? 96 : 48
iconSpacing: 8
imageX: isFullScreen ? 37 : 13
imageY: isFullScreen ? 17 : 8
width: 720 // margins: 16
height: viewMaxRow*176 + content.contentMargins*2 // itemHeight: 160 + spacing: 16 + margins: 24
radius: Platform.Theme.maxRadius //? 32
x: (parent.width - width) / 2
y: (parent.height - height) / 2
}
PropertyChanges {
target: content
contentMargins: 8
labelSpacing: 8
labelMagrins: 8
}
PropertyChanges { target: folderNameText; opacity: 1 }
},
@ -89,17 +90,17 @@ Loader {
name: "folderHidden"
PropertyChanges {
target: folderIconBase
width: 86
height: 86
width: 84
height: 84
radius: Platform.Theme.maxRadius
gridViewMargin: 8
x: root.mapFromGlobal(folderX, 0).x
y: root.mapFromGlobal(0, folderY).y
//
folderIconSize: 16
iconSpacing: 0
imageX: 0
imageY: 0
}
PropertyChanges {
target: content
contentMargins: 0
labelSpacing: 0
labelMagrins: 0
}
PropertyChanges { target: folderNameText; opacity: 0 }
}
@ -112,12 +113,16 @@ Loader {
ParallelAnimation {
PropertyAnimation {
duration: animationDuration; easing.type: Easing.InOutCubic
properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, gridViewMargin"
properties: "x, y, width, height, radius, alpha"
}
PropertyAnimation {
duration: animationDuration; easing.type: Easing.OutQuint
properties: "opacity"
}
PropertyAnimation {
duration: animationDuration; easing.type: Easing.OutQuint
properties: "contentMargins, labelMagrins, labelSpacing"
}
}
ScriptAction { script: content.folderSwipeView.hideFolder() }
}
@ -128,12 +133,16 @@ Loader {
ParallelAnimation {
PropertyAnimation {
duration: animationDuration; easing.type: Easing.InOutCubic
properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, gridViewMargin"
properties: "x, y, width, height, radius, alpha"
}
PropertyAnimation {
duration: animationDuration; easing.type: Easing.InQuint
properties: "opacity"
}
PropertyAnimation {
duration: animationDuration; easing.type: Easing.OutQuint
properties: "contentMargins, labelMagrins, labelSpacing"
}
}
ScriptAction {
script: {
@ -148,23 +157,42 @@ Loader {
id: content
anchors.fill: parent
folderContentModel: folderModel
contentMargins: folderIconBase.gridViewMargin
labelMagrins: isFullScreen ? 16 : 8
isFullScreen: true
}
}
EditText {
PageIndicator {
id: pageIndicator
interactive: true
count: content.count
visible: count > 1
currentIndex: content.currentIndex
anchors.bottom: folderIconBase.bottom
anchors.horizontalCenter: folderIconBase.horizontalCenter
delegate: Rectangle {
color: "black"
width: 6; height: width;
radius: width / 2
opacity: (index === content.currentIndex )? 0.9 : 0.3
}
}
AppUI.EditText {
id: folderNameText
anchors.bottom: folderIconBase.top
anchors.bottomMargin: 30
anchors.horizontalCenter: folderIconBase.horizontalCenter
height: 47; width: folderIconBase.width
textEdited: folderName
textCenterIn: true
isFolder: true
isFullScreen: isFullScreen
textSize: 32
onTextEditingFinished: text=> {
folderModel.renameFolder(text);
}
}
}
}
}

View File

@ -36,9 +36,8 @@ FavoriteWidget::FavoriteWidget(QObject *parent) : WidgetExtension(parent)
FavoritesModel::instance().setSourceModel(&AppFavoritesModel::instance());
FavoritesModel::instance().sort(0);
m_folderModel = new FolderModel;
m_data.insert("favoriteAppsModel", QVariant::fromValue(&FavoritesModel::instance()));
m_data.insert("folderModel", QVariant::fromValue(m_folderModel));
m_data.insert("folderModel", QVariant::fromValue(&FolderModel::instance()));
}
int FavoriteWidget::index() const

View File

@ -38,7 +38,6 @@ public:
private:
MetadataMap m_metadata;
QVariantMap m_data;
FolderModel *m_folderModel;
};
} // UkuiMenu

View File

@ -117,4 +117,10 @@ int FolderModel::count()
return m_apps.count();
}
FolderModel &FolderModel::instance()
{
static FolderModel folderModel;
return folderModel;
}
} // UkuiMenu

View File

@ -29,7 +29,8 @@ class FolderModel : public QAbstractListModel
Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY countChanged)
public:
explicit FolderModel(QObject *parent = nullptr);
static FolderModel &instance();
Q_INVOKABLE void setFolderId(const QString &folderId);
Q_INVOKABLE void renameFolder(const QString &folderName);
@ -45,6 +46,8 @@ private Q_SLOTS:
void loadFolderData(int id);
private:
explicit FolderModel(QObject *parent = nullptr);
int m_folderId;
QStringList m_apps;
};

View File

@ -29,6 +29,8 @@
#include "widget-model.h"
#include "app-page-backend.h"
#include "app-group-model.h"
#include "favorite/favorites-model.h"
#include "favorite/folder-model.h"
#include <QGuiApplication>
#include <QCommandLineParser>
@ -91,6 +93,8 @@ void UkuiMenuApplication::initQmlEngine()
context->setContextProperty("menuManager", ContextMenuManager::instance());
context->setContextProperty("appManager", AppManager::instance());
context->setContextProperty("favoriteModel", &FavoritesModel::instance());
context->setContextProperty("FolderModel", &FolderModel::instance());
// MenuMainWindow
// const QUrl url(QStringLiteral("qrc:/qml/MenuMainWindow.qml"));
// QQmlApplicationEngine *m_applicationEngine{nullptr};