添加文件夹翻页功能

This commit is contained in:
qiqi 2023-04-18 10:43:21 +08:00 committed by He Sir
parent 71a42aaa82
commit 36f3413016
5 changed files with 286 additions and 139 deletions

View File

@ -53,10 +53,7 @@ RowLayout {
}, },
Transition { Transition {
to: "contentShow" to: "contentShow"
SequentialAnimation {
PropertyAnimation { properties: "opacity, scale"; duration: animationDuration; easing.type: Easing.InOutCubic } PropertyAnimation { properties: "opacity, scale"; duration: animationDuration; easing.type: Easing.InOutCubic }
ScriptAction { script: root.contentShowFinished() }
}
} }
] ]
@ -279,13 +276,18 @@ RowLayout {
var x = folderIcon.mapToGlobal(0,0).x; var x = folderIcon.mapToGlobal(0,0).x;
var y = folderIcon.mapToGlobal(0,0).y var y = folderIcon.mapToGlobal(0,0).y
openFolderSignal(id, name, x, y); openFolderSignal(id, name, x, y);
//
root.isContentShow = false; root.isContentShow = false;
opacity = 0; folderIcon.opacity = 0;
enabled = false;
hoverEnabled = false;
return; return;
} }
} }
function resetOpacity() { function resetOpacity() {
opacity = 1; folderIcon.opacity = 1;
enabled = true;
hoverEnabled = true;
} }
Component.onCompleted: root.contentShowFinished.connect(resetOpacity) Component.onCompleted: root.contentShowFinished.connect(resetOpacity)
Component.onDestruction: root.contentShowFinished.disconnect(resetOpacity) Component.onDestruction: root.contentShowFinished.disconnect(resetOpacity)

View File

@ -17,149 +17,292 @@
*/ */
import QtQuick 2.0 import QtQuick 2.0
import QtQml.Models 2.12
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5
import org.ukui.menu.core 1.0 import org.ukui.menu.core 1.0
import AppControls2 1.0 as AppControls2 import AppControls2 1.0 as AppControls2
Item {
property alias model: folderGridView.model Loader {
id: root
active: false
property var folderModel: modelManager.getFolderModel()
property string folderName: "" property string folderName: ""
property int margins: 20
property int folderX: 0 property int folderX: 0
property int folderY: 0 property int folderY: 0
property int viewMaxRow: 0
property bool isFolderOpened: false property bool isFolderOpened: false
property int margins: 20
property int animationDuration: 300 property int animationDuration: 300
property bool mouseEnable: false
signal turnPageFinished()
AppControls2.StyleBackground { function initFolder(id, name, x, y) {
id: folderIconBase folderModel.setFolderId(id);
paletteRole: Palette.Text folderName = name;
useStyleTransparent: false folderX = x;
property int folderIconSize: 0 folderY = y;
property int iconSpacing: 0 viewMaxRow = Math.ceil(folderModel.count / 4) > 4 ? 4 : Math.ceil(folderModel.count / 4);
property int imageX: 0 active = true;
property int imageY: 0 isFolderOpened = true;
alpha: 0.25 }
state: isFolderOpened ? "folderOpened" : "folderHidden" sourceComponent: folderComponent
states: [
State { Component {
name: "folderOpened" id: folderComponent
PropertyChanges { Item {
target: folderIconBase AppControls2.StyleBackground {
width: 720; height: folderGridView.viewMaxHeight; radius: 36 id: folderIconBase
x: (parent.width - width) / 2; y: (parent.height - height) / 2 paletteRole: Palette.Text
folderIconSize: 96; iconSpacing: 8 useStyleTransparent: false
imageX: 37; imageY: 17 property int folderIconSize: 0
} property int iconSpacing: 0
PropertyChanges { target: folderGridView; anchors.margins: margins } property int imageX: 0
PropertyChanges { target: folderNameText; opacity: 1 } property int imageY: 0
}, property int gridViewMargin: 8
State { alpha: 0.25
name: "folderHidden"
PropertyChanges { state: isFolderOpened ? "folderOpened" : "folderHidden"
target: folderIconBase states: [
width: 86; height: width; radius: 16 State {
x: parent.parent.mapFromGlobal(folderX, 0).x; y: parent.parent.mapFromGlobal(0, folderY).y name: "folderOpened"
folderIconSize: 16; iconSpacing: 0 PropertyChanges {
imageX: 0; imageY: 0 target: folderIconBase
} width: 720
PropertyChanges { target: folderGridView; anchors.margins: 8 } height: viewMaxRow * 170 + margins * 2
PropertyChanges { target: folderNameText; opacity: 0 } radius: 36
} gridViewMargin: margins
] x: (parent.width - width) / 2
transitions: [ y: (parent.height - height) / 2
Transition { //
to: "folderHidden" folderIconSize: 96
SequentialAnimation { iconSpacing: 8
ScriptAction { script: folderGridView.positionViewAtBeginning() } imageX: 37
ParallelAnimation { imageY: 17
PropertyAnimation {
duration: animationDuration; easing.type: Easing.InOutCubic
properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, anchors.margins"
} }
PropertyAnimation { PropertyChanges { target: folderNameText; opacity: 1 }
duration: animationDuration; easing.type: Easing.OutQuint },
properties: "opacity" State {
name: "folderHidden"
PropertyChanges {
target: folderIconBase
width: 86
height: 86
radius: 16
gridViewMargin: 8
x: root.mapFromGlobal(folderX, 0).x
y: root.mapFromGlobal(0, folderY).y
//
folderIconSize: 16
iconSpacing: 0
imageX: 0
imageY: 0
}
PropertyChanges { target: folderNameText; opacity: 0 }
}
]
transitions: [
Transition {
to: "folderHidden"
SequentialAnimation {
ScriptAction { script: mouseEnable = false }
ParallelAnimation {
PropertyAnimation {
duration: animationDuration; easing.type: Easing.InOutCubic
properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, gridViewMargin"
}
PropertyAnimation {
duration: animationDuration; easing.type: Easing.OutQuint
properties: "opacity"
}
}
ScriptAction { script: folderSwipeView.hideFolder() }
}
},
Transition {
to: "folderOpened"
SequentialAnimation {
ParallelAnimation {
PropertyAnimation {
duration: animationDuration; easing.type: Easing.InOutCubic
properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, gridViewMargin"
}
PropertyAnimation {
duration: animationDuration; easing.type: Easing.InQuint
properties: "opacity"
}
}
ScriptAction {
script: {
folderSwipeView.contentItem.highlightMoveDuration = 0;
mouseEnable = true
}
}
} }
} }
ScriptAction { script: parent.active = false } ]
}
}, PageIndicator {
Transition { id: pageIndicator
to: "folderOpened" interactive: true
ParallelAnimation { count: folderSwipeView.count
PropertyAnimation { visible: count > 1
duration: animationDuration; easing.type: Easing.InOutCubic currentIndex: folderSwipeView.currentIndex
properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, anchors.margins" anchors.bottom: parent.bottom
} anchors.horizontalCenter: parent.horizontalCenter
PropertyAnimation {
duration: animationDuration; easing.type: Easing.InQuint delegate: Rectangle {
properties: "opacity" 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: animationDuration; easing.type: Easing.InOutCubic }
}
} }
} }
}
]
GridView { SwipeView {
id: folderGridView id: folderSwipeView
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 anchors.fill: parent
useStyleTransparent: false property bool needTurnPage: false
paletteRole: Palette.Light property int contentX: contentItem.contentX
radius: 16 property int startContentX: 0
alpha: parent.containsPress ? 0.25 : parent.containsMouse ? 0.15 : 0.00 property int startIndex: 0
Image { function hideFolder() {
id: iconImage //
source: icon if (currentIndex > 0) {
height: folderIconBase.folderIconSize; width: height interactive = false;
x: folderIconBase.imageX; y: folderIconBase.imageY needTurnPage = true;
pageIndicator.visible = false;
contentItem.highlightFollowsCurrentItem = true;
contentItem.highlightMoveDuration = 300;
contentItem.highlightMoveVelocity = -1;
startContentX = contentX;
startIndex = currentIndex;
currentIndex = 0;
//
} else {
reset();
}
} }
AppControls2.StyleText { function reset() {
width: parent.width interactive = true;
horizontalAlignment: Text.AlignHCenter root.active = false;
anchors.top: iconImage.bottom pageIndicator.visible = false;
anchors.topMargin: folderIconBase.iconSpacing turnPageFinished();
anchors.horizontalCenter: parent.horizontalCenter }
text: name
font.pixelSize: 14 //
elide: Text.ElideRight onContentXChanged: {
paletteRole: Palette.HighlightedText //
} if (needTurnPage && startContentX - contentX === startIndex * 86) {
} needTurnPage = false;
onClicked: { reset();
if (mouse.button === Qt.RightButton) { }
menuManager.showMenu(id); }
return;
} Repeater {
if (mouse.button === Qt.LeftButton) { model: Math.ceil(folderModel.count / 16)
appManager.launchApp(id);
return; Item {
id: base
property int currentPage: SwipeView.index
GridView {
id: folderGridView
cellHeight: width / 4; cellWidth: cellHeight
anchors.fill: parent
anchors.margins: folderIconBase.gridViewMargin
boundsBehavior: Flickable.StopAtBounds
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);
}
for (var i = base.currentPage * maxItemNumPerPage;
i < Math.min((base.currentPage + 1) * maxItemNumPerPage, items.count); i ++) {
items.addGroups(i, 1, "folderContent");
}
}
model: folderModel
delegate: MouseArea {
hoverEnabled: true
enabled: mouseEnable
width: GridView.view.cellWidth; height: GridView.view.cellHeight
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: folderIconBase.top
anchors.bottomMargin: 30
anchors.horizontalCenter: folderIconBase.horizontalCenter
height: 47; width: folderIconBase.width
textEdited: folderName
textCenterIn: true
isFullScreenFolder: true
}
} }
} }
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
}
} }

View File

@ -13,7 +13,7 @@ AppControls2.StyleBackground {
forceActiveFocus(); forceActiveFocus();
mainWindow.hide(); mainWindow.hide();
} else { } else {
folderLoader.item.isFolderOpened = false; folderLoader.isFolderOpened = false;
fullScreenContent.visible = true; fullScreenContent.visible = true;
fullScreenContent.isContentShow = true; fullScreenContent.isContentShow = true;
} }
@ -40,25 +40,15 @@ AppControls2.StyleBackground {
FullScreenContent { FullScreenContent {
id: fullScreenContent id: fullScreenContent
anchors.fill: parent anchors.fill: parent
Component.onCompleted: folderLoader.turnPageFinished.connect(contentShowFinished)
Component.onDestruction: folderLoader.turnPageFinished.disconnect(contentShowFinished)
} }
Loader { FullScreenFolder {
id: folderLoader id: folderLoader
active: false
anchors.fill: parent anchors.fill: parent
sourceComponent: FullScreenFolder {} Component.onCompleted: fullScreenContent.openFolderSignal.connect(initFolder)
Component.onDestruction: fullScreenContent.openFolderSignal.disconnect(initFolder)
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)
} }
} }

View File

@ -62,6 +62,8 @@ void FolderModel::loadFolderData(int id)
m_folderId = id; m_folderId = id;
m_apps = folder.getApps(); m_apps = folder.getApps();
endResetModel(); endResetModel();
Q_EMIT countChanged();
} }
int FolderModel::rowCount(const QModelIndex &parent) const int FolderModel::rowCount(const QModelIndex &parent) const
@ -106,4 +108,9 @@ QHash<int, QByteArray> FolderModel::roleNames() const
return DataEntity::AppRoleNames(); return DataEntity::AppRoleNames();
} }
int FolderModel::count()
{
return m_apps.count();
}
} // UkuiMenu } // UkuiMenu

View File

@ -27,6 +27,7 @@ namespace UkuiMenu {
class FolderModel : public QAbstractListModel class FolderModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY countChanged)
public: public:
explicit FolderModel(QObject *parent = nullptr); explicit FolderModel(QObject *parent = nullptr);
Q_INVOKABLE void setFolderId(const QString &folderId); Q_INVOKABLE void setFolderId(const QString &folderId);
@ -35,6 +36,10 @@ public:
int rowCount(const QModelIndex &parent) const override; int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
int count();
Q_SIGNALS:
void countChanged();
private Q_SLOTS: private Q_SLOTS:
void loadFolderData(int id); void loadFolderData(int id);