FluentUI/src/controls/FluCalendarView.qml

477 lines
16 KiB
QML
Raw Normal View History

2023-03-21 18:19:46 +08:00
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
2023-03-11 14:43:07 +08:00
Item {
2023-03-21 18:19:46 +08:00
id:control
2023-03-22 11:54:19 +08:00
property int displayMode: FluCalendarView.Month
2023-03-21 18:19:46 +08:00
property var date: new Date()
property var currentDate : new Date()
2023-03-22 11:54:19 +08:00
property var toDay: new Date()
signal dateClicked(var date)
width: 280
height: 325
2023-03-21 18:19:46 +08:00
enum DisplayMode {
Month,
Year,
Decade
}
Component.onCompleted: {
updateMouth(date)
}
function createItemWeek(name){
2023-03-22 11:54:19 +08:00
return {type:0,date:new Date(),name:name,isDecade:false}
2023-03-21 18:19:46 +08:00
}
function createItemDay(date){
2023-03-22 11:54:19 +08:00
return {type:1,date:date,name:"",isDecade:false}
2023-03-21 18:19:46 +08:00
}
2023-03-21 23:52:29 +08:00
function createItemMonth(date){
2023-03-22 11:54:19 +08:00
return {type:2,date:date,name:"",isDecade:false}
2023-03-21 18:19:46 +08:00
}
2023-03-22 11:54:19 +08:00
function createItemYear(date,isDecade){
return {type:3,date:date,name:"",isDecade:isDecade}
2023-03-21 23:52:29 +08:00
}
function updateDecade(date){
2023-03-21 18:19:46 +08:00
list_model.clear()
var year = date.getFullYear()
2023-03-21 23:52:29 +08:00
const decadeStart = Math.floor(year / 10) * 10;
for(var i = decadeStart ; i< decadeStart+10 ; i++){
2023-03-22 11:54:19 +08:00
list_model.append(createItemYear(new Date(i,0,1),true));
2023-03-21 18:19:46 +08:00
}
2023-03-22 11:54:19 +08:00
for(var j = decadeStart+10 ; j< decadeStart+16 ; j++){
list_model.append(createItemYear(new Date(j,0,1),false));
}
title.text = decadeStart+"-"+(decadeStart+10)
2023-03-21 23:52:29 +08:00
}
function updateYear(date){
list_model.clear()
var year = date.getFullYear()
for(var i = 0 ; i< 12 ; i++){
list_model.append(createItemMonth(new Date(year,i)));
}
for(var j = 0 ; j< 4 ; j++){
list_model.append(createItemMonth(new Date(year+1,j)));
2023-03-21 18:19:46 +08:00
}
2023-03-21 23:52:29 +08:00
title.text = year+"年"
2023-03-21 18:19:46 +08:00
}
function updateMouth(date){
list_model.clear()
list_model.append([createItemWeek("一"),createItemWeek("二"),createItemWeek("三"),createItemWeek("四"),createItemWeek("五"),createItemWeek("六"),createItemWeek("日")])
var year = date.getFullYear()
var month = date.getMonth()
var day = date.getDate()
var firstDayOfMonth = new Date(year, month, 1)
var dayOfWeek = firstDayOfMonth.getDay()
var headerSize = (dayOfWeek===0?7:dayOfWeek)-1
if(headerSize!==0){
var lastMonthYear = year;
var lastMonthMonth = month - 1
if (month === 0) {
lastMonthYear = year - 1
lastMonthMonth = 11
}
var lastMonthDays = new Date(lastMonthYear, lastMonthMonth+1, 0).getDate()
for (var i = headerSize-1; i >= 0; i--) {
list_model.append(createItemDay(new Date(lastMonthYear, lastMonthMonth,lastMonthDays-i)))
}
}
const lastDayOfMonth = new Date(year, month+1, 0).getDate()
for (let day = 1; day <= lastDayOfMonth; day++) {
list_model.append(createItemDay(new Date(year, month,day)))
}
var footerSize = 49-list_model.count
var nextMonthYear = year
var nextMonth = month + 1
if (month === 11) {
nextMonthYear = year + 1
nextMonth = 0
}
const nextDayOfMonth = new Date(nextMonthYear, nextMonth+1, 0).getDate()
2023-03-22 11:54:19 +08:00
for (let j = 1; j <= footerSize; j++) {
2023-03-21 18:19:46 +08:00
list_model.append(createItemDay(new Date(nextMonthYear, nextMonth,j)))
}
title.text = year+"年"+(month+1)+"月"
}
Component{
id:com_week
Item{
height: 40
width: 40
FluText{
text:name
anchors.centerIn: parent
}
}
}
Component{
2023-03-21 23:52:29 +08:00
id:com_year
Button{
id:item_control
2023-03-22 11:54:19 +08:00
property bool isYear: control.toDay.getFullYear() === date.getFullYear()
2023-03-21 18:19:46 +08:00
height: 70
width: 70
2023-03-21 23:52:29 +08:00
onClicked:{
control.date = date
2023-03-22 11:54:19 +08:00
displayMode = FluCalendarView.Year
2023-03-21 23:52:29 +08:00
updateYear(date)
}
background: Item{
Rectangle{
width: 60
height: 60
radius: 4
anchors.centerIn: parent
color:{
if(FluTheme.isDark){
if(item_control.hovered){
return Qt.rgba(1,1,1,0.05)
}
return Qt.rgba(0,0,0,0)
}else{
if(item_control.hovered){
return Qt.rgba(0,0,0,0.05)
}
return Qt.rgba(0,0,0,0)
}
}
}
Rectangle{
id:backgound_selected
anchors.centerIn: parent
width: 50
height: 50
radius: 25
visible: isYear
color: FluTheme.primaryColor.dark
}
FluText{
text:date.getFullYear()
anchors.centerIn: parent
color: {
if(isYear){
return "#FFFFFF"
}
2023-03-22 11:54:19 +08:00
if(isDecade){
return FluTheme.isDark ? "#FFFFFF" : "#1A1A1A"
}
2023-03-21 23:52:29 +08:00
return Qt.rgba(150/255,150/255,150/255,1)
}
}
2023-03-21 18:19:46 +08:00
}
2023-03-21 23:52:29 +08:00
contentItem: Item{}
}
}
2023-03-21 18:19:46 +08:00
2023-03-21 23:52:29 +08:00
Component{
id:com_month
Button{
id:item_control
property bool isYear: control.date.getFullYear() === date.getFullYear()
2023-03-22 11:54:19 +08:00
property bool isMonth: control.toDay.getFullYear() === date.getFullYear() && control.toDay.getMonth() === date.getMonth()
2023-03-21 23:52:29 +08:00
height: 70
width: 70
onClicked:{
control.date = date
2023-03-22 11:54:19 +08:00
displayMode = FluCalendarView.Month
2023-03-21 23:52:29 +08:00
updateMouth(date)
}
background: Item{
Rectangle{
width: 60
height: 60
radius: 4
anchors.centerIn: parent
color:{
if(FluTheme.isDark){
if(item_control.hovered){
return Qt.rgba(1,1,1,0.05)
}
return Qt.rgba(0,0,0,0)
}else{
if(item_control.hovered){
return Qt.rgba(0,0,0,0.05)
}
return Qt.rgba(0,0,0,0)
}
}
}
Rectangle{
id:backgound_selected
anchors.centerIn: parent
width: 50
height: 50
radius: 25
visible: isMonth
color: FluTheme.primaryColor.dark
}
FluText{
text:(date.getMonth()+1)+"月"
anchors.centerIn: parent
color: {
if(isMonth){
return "#FFFFFF"
}
if(isYear){
return FluTheme.isDark ? "#FFFFFF" : "#1A1A1A"
}
return Qt.rgba(150/255,150/255,150/255,1)
}
2023-03-21 18:19:46 +08:00
}
}
2023-03-21 23:52:29 +08:00
contentItem: Item{}
2023-03-21 18:19:46 +08:00
}
}
Component{
id:com_day
Button{
id:item_control
property bool isMonth: control.date.getMonth() === date.getMonth()
property bool isDay: control.currentDate.getFullYear() === date.getFullYear() && control.currentDate.getMonth() === date.getMonth() && control.currentDate.getDate() === date.getDate()
2023-03-22 11:54:19 +08:00
property bool isToDay: control.toDay.getFullYear() === date.getFullYear() && control.toDay.getMonth() === date.getMonth() && control.toDay.getDate() === date.getDate()
2023-03-21 18:19:46 +08:00
height: 40
width: 40
onClicked: {
currentDate = date
2023-03-22 11:54:19 +08:00
control.dateClicked(date)
2023-03-21 18:19:46 +08:00
}
background: Item{
Rectangle{
width: 36
height: 36
radius: 4
anchors.centerIn: parent
color:{
if(FluTheme.isDark){
if(item_control.hovered){
return Qt.rgba(1,1,1,0.05)
}
return Qt.rgba(0,0,0,0)
}else{
if(item_control.hovered){
return Qt.rgba(0,0,0,0.05)
}
return Qt.rgba(0,0,0,0)
}
}
}
2023-03-22 11:54:19 +08:00
Rectangle{
id:backgound_today
anchors.centerIn: parent
width: 36
height: 36
radius: 18
color:"#00000000"
visible: isDay
border.color: FluTheme.primaryColor.dark
border.width: 1
}
2023-03-21 18:19:46 +08:00
Rectangle{
id:backgound_selected
anchors.centerIn: parent
width: 30
height: 30
radius: 15
2023-03-22 11:54:19 +08:00
visible: isToDay
2023-03-21 18:19:46 +08:00
color: FluTheme.primaryColor.dark
}
2023-03-22 11:54:19 +08:00
2023-03-21 18:19:46 +08:00
FluText{
text:date.getDate()
anchors.centerIn: parent
color: {
2023-03-22 11:54:19 +08:00
if(isToDay){
2023-03-21 18:19:46 +08:00
return "#FFFFFF"
}
if(isMonth){
return FluTheme.isDark ? "#FFFFFF" : "#1A1A1A"
}
return Qt.rgba(150/255,150/255,150/255,1)
}
}
}
contentItem: Item{}
}
}
FluArea{
2023-03-22 11:54:19 +08:00
anchors.fill: parent
2023-03-21 18:19:46 +08:00
radius: 5
FluShadow{
radius: 5
}
Rectangle{
id:layout_divider
height: 1
width: parent.width
color: FluTheme.isDark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
anchors{
top: parent.top
2023-03-22 11:54:19 +08:00
topMargin: 44
2023-03-21 18:19:46 +08:00
}
}
Item{
id:layout_top
anchors{
left: parent.left
right: parent.right
top: parent.top
bottom: layout_divider.top
}
FluTextButton{
id:title
leftPadding: 0
rightPadding: 0
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 14
}
2023-03-22 11:54:19 +08:00
disabled: displayMode === FluCalendarView.Decade
2023-03-21 18:19:46 +08:00
onClicked:{
2023-03-22 11:54:19 +08:00
if(displayMode === FluCalendarView.Month){
displayMode = FluCalendarView.Year
2023-03-21 23:52:29 +08:00
updateYear(date)
2023-03-22 11:54:19 +08:00
}else if(displayMode === FluCalendarView.Year){
displayMode = FluCalendarView.Decade
2023-03-21 23:52:29 +08:00
updateDecade(date)
}
2023-03-21 18:19:46 +08:00
}
}
FluIconButton{
id:icon_up
iconSource: FluentIcons.CaretUpSolid8
iconSize: 10
anchors{
verticalCenter: parent.verticalCenter
right: icon_down.left
rightMargin: 14
}
onClicked: {
var year = date.getFullYear()
var month = date.getMonth()
2023-03-22 11:54:19 +08:00
if(displayMode === FluCalendarView.Month){
2023-03-21 23:52:29 +08:00
var lastMonthYear = year;
var lastMonthMonth = month - 1
if (month === 0) {
lastMonthYear = year - 1
lastMonthMonth = 11
}
date = new Date(lastMonthYear,lastMonthMonth,1)
updateMouth(date)
2023-03-22 11:54:19 +08:00
}else if(displayMode === FluCalendarView.Year){
2023-03-21 23:52:29 +08:00
date = new Date(year-1,month,1)
updateYear(date)
2023-03-22 11:54:19 +08:00
}else if(displayMode === FluCalendarView.Decade){
date = new Date(Math.floor(year / 10) * 10-10,month,1)
updateDecade(date)
2023-03-21 18:19:46 +08:00
}
}
}
FluIconButton{
id:icon_down
iconSource: FluentIcons.CaretDownSolid8
iconSize: 10
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 8
}
onClicked: {
var year = date.getFullYear()
var month = date.getMonth()
2023-03-22 11:54:19 +08:00
if(displayMode === FluCalendarView.Month){
2023-03-21 23:52:29 +08:00
var nextMonthYear = year
var nextMonth = month + 1
if (month === 11) {
nextMonthYear = year + 1
nextMonth = 0
}
date = new Date(nextMonthYear,nextMonth,1)
updateMouth(date)
2023-03-22 11:54:19 +08:00
}else if(displayMode === FluCalendarView.Year){
2023-03-21 23:52:29 +08:00
date = new Date(year+1,month,1)
updateYear(date)
2023-03-22 11:54:19 +08:00
}else if(displayMode === FluCalendarView.Decade){
date = new Date(Math.floor(year / 10) * 10+10,month,1)
updateDecade(date)
2023-03-21 18:19:46 +08:00
}
}
}
}
ListModel {
id:list_model
}
Item{
id:layout_bottom
anchors{
left: parent.left
right: parent.right
top: layout_divider.bottom
bottom: parent.bottom
}
GridView{
model: list_model
anchors.fill: parent
2023-03-22 11:54:19 +08:00
cellHeight: displayMode === FluCalendarView.Month ? 40 : 70
cellWidth: displayMode === FluCalendarView.Month ? 40 : 70
2023-03-21 23:52:29 +08:00
clip: true
boundsBehavior:Flickable.StopAtBounds
2023-03-21 18:19:46 +08:00
delegate: Loader{
property var modelData : model
property var name : model.name
property var date : model.date
2023-03-22 11:54:19 +08:00
property var isDecade: {
return model.isDecade
}
2023-03-21 18:19:46 +08:00
sourceComponent: {
if(model.type === 0){
return com_week
}
if(model.type === 1){
return com_day
}
if(model.type === 2){
return com_month
}
2023-03-21 23:52:29 +08:00
if(model.type === 3){
return com_year
}
2023-03-21 18:19:46 +08:00
return com_day
}
}
}
}
}
2023-03-11 14:43:07 +08:00
}