添加文件夹翻页功能

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,19 +17,43 @@
*/ */
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 animationDuration: 300
property int margins: 20
property int animationDuration: 300
property bool mouseEnable: false
signal turnPageFinished()
function initFolder(id, name, x, y) {
folderModel.setFolderId(id);
folderName = name;
folderX = x;
folderY = y;
viewMaxRow = Math.ceil(folderModel.count / 4) > 4 ? 4 : Math.ceil(folderModel.count / 4);
active = true;
isFolderOpened = true;
}
sourceComponent: folderComponent
Component {
id: folderComponent
Item {
AppControls2.StyleBackground { AppControls2.StyleBackground {
id: folderIconBase id: folderIconBase
paletteRole: Palette.Text paletteRole: Palette.Text
@ -38,6 +62,7 @@ Item {
property int iconSpacing: 0 property int iconSpacing: 0
property int imageX: 0 property int imageX: 0
property int imageY: 0 property int imageY: 0
property int gridViewMargin: 8
alpha: 0.25 alpha: 0.25
state: isFolderOpened ? "folderOpened" : "folderHidden" state: isFolderOpened ? "folderOpened" : "folderHidden"
@ -46,24 +71,36 @@ Item {
name: "folderOpened" name: "folderOpened"
PropertyChanges { PropertyChanges {
target: folderIconBase target: folderIconBase
width: 720; height: folderGridView.viewMaxHeight; radius: 36 width: 720
x: (parent.width - width) / 2; y: (parent.height - height) / 2 height: viewMaxRow * 170 + margins * 2
folderIconSize: 96; iconSpacing: 8 radius: 36
imageX: 37; imageY: 17 gridViewMargin: margins
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 } PropertyChanges { target: folderNameText; opacity: 1 }
}, },
State { State {
name: "folderHidden" name: "folderHidden"
PropertyChanges { PropertyChanges {
target: folderIconBase target: folderIconBase
width: 86; height: width; radius: 16 width: 86
x: parent.parent.mapFromGlobal(folderX, 0).x; y: parent.parent.mapFromGlobal(0, folderY).y height: 86
folderIconSize: 16; iconSpacing: 0 radius: 16
imageX: 0; imageY: 0 gridViewMargin: 8
x: root.mapFromGlobal(folderX, 0).x
y: root.mapFromGlobal(0, folderY).y
//
folderIconSize: 16
iconSpacing: 0
imageX: 0
imageY: 0
} }
PropertyChanges { target: folderGridView; anchors.margins: 8 }
PropertyChanges { target: folderNameText; opacity: 0 } PropertyChanges { target: folderNameText; opacity: 0 }
} }
] ]
@ -71,45 +108,143 @@ Item {
Transition { Transition {
to: "folderHidden" to: "folderHidden"
SequentialAnimation { SequentialAnimation {
ScriptAction { script: folderGridView.positionViewAtBeginning() } ScriptAction { script: mouseEnable = false }
ParallelAnimation { ParallelAnimation {
PropertyAnimation { PropertyAnimation {
duration: animationDuration; easing.type: Easing.InOutCubic duration: animationDuration; easing.type: Easing.InOutCubic
properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, anchors.margins" properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, gridViewMargin"
} }
PropertyAnimation { PropertyAnimation {
duration: animationDuration; easing.type: Easing.OutQuint duration: animationDuration; easing.type: Easing.OutQuint
properties: "opacity" properties: "opacity"
} }
} }
ScriptAction { script: parent.active = false } ScriptAction { script: folderSwipeView.hideFolder() }
} }
}, },
Transition { Transition {
to: "folderOpened" to: "folderOpened"
SequentialAnimation {
ParallelAnimation { ParallelAnimation {
PropertyAnimation { PropertyAnimation {
duration: animationDuration; easing.type: Easing.InOutCubic duration: animationDuration; easing.type: Easing.InOutCubic
properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, anchors.margins" properties: "x, y, width, height, folderIconSize, iconSpacing, radius, imageX, imageY, gridViewMargin"
} }
PropertyAnimation { PropertyAnimation {
duration: animationDuration; easing.type: Easing.InQuint duration: animationDuration; easing.type: Easing.InQuint
properties: "opacity" properties: "opacity"
} }
} }
ScriptAction {
script: {
folderSwipeView.contentItem.highlightMoveDuration = 0;
mouseEnable = true
}
}
}
} }
] ]
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: animationDuration; easing.type: Easing.InOutCubic }
}
}
}
SwipeView {
id: folderSwipeView
anchors.fill: parent
property bool needTurnPage: false
property int contentX: contentItem.contentX
property int startContentX: 0
property int startIndex: 0
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();
}
}
function reset() {
interactive = true;
root.active = false;
pageIndicator.visible = false;
turnPageFinished();
}
//
onContentXChanged: {
//
if (needTurnPage && startContentX - contentX === startIndex * 86) {
needTurnPage = false;
reset();
}
}
Repeater {
model: Math.ceil(folderModel.count / 16)
Item {
id: base
property int currentPage: SwipeView.index
GridView { GridView {
id: folderGridView id: folderGridView
anchors.fill: parent
cellHeight: width / 4; cellWidth: cellHeight cellHeight: width / 4; cellWidth: cellHeight
anchors.fill: parent
anchors.margins: folderIconBase.gridViewMargin
boundsBehavior: Flickable.StopAtBounds 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() 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 { delegate: MouseArea {
hoverEnabled: true hoverEnabled: true
width: GridView.view.cellHeight; height: width enabled: mouseEnable
width: GridView.view.cellWidth; height: GridView.view.cellHeight
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
AppControls2.StyleBackground { AppControls2.StyleBackground {
@ -151,15 +286,23 @@ Item {
} }
} }
} }
}
}
}
}
EditText { EditText {
id: folderNameText id: folderNameText
anchors.bottom: folderGridView.parent.top anchors.bottom: folderIconBase.top
anchors.bottomMargin: 30 anchors.bottomMargin: 30
anchors.horizontalCenter: folderGridView.parent.horizontalCenter anchors.horizontalCenter: folderIconBase.horizontalCenter
height: 47; width: folderGridView.width height: 47; width: folderIconBase.width
textEdited: folderName textEdited: folderName
textCenterIn: true textCenterIn: true
isFullScreenFolder: 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);