251 lines
7.2 KiB
QML
251 lines
7.2 KiB
QML
import QtQuick 2.15
|
|
import QtQuick.Controls 2.15
|
|
import QtQuick.Shapes 1.15
|
|
import QtQuick.Window 2.15
|
|
import FluentUI 1.0
|
|
|
|
Popup{
|
|
property var steps : []
|
|
property int targetMargins: 5
|
|
property Component nextButton: com_next_button
|
|
property Component prevButton: com_prev_button
|
|
property int index : 0
|
|
property string finishText: qsTr("Finish")
|
|
property string nextText: qsTr("Next")
|
|
property string previousText: qsTr("Previous")
|
|
id:control
|
|
padding: 0
|
|
parent: Overlay.overlay
|
|
width: d.parentWidth
|
|
height: d.parentHeight
|
|
background: Item{}
|
|
contentItem: Item{}
|
|
onVisibleChanged: {
|
|
if(visible){
|
|
control.index = 0
|
|
}
|
|
}
|
|
onIndexChanged: {
|
|
canvas.requestPaint()
|
|
}
|
|
Component{
|
|
id: com_next_button
|
|
FluFilledButton{
|
|
text: isEnd ? control.finishText : control.nextText
|
|
onClicked: {
|
|
if(isEnd){
|
|
control.close()
|
|
}else{
|
|
control.index = control.index + 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Component{
|
|
id: com_prev_button
|
|
FluButton{
|
|
text: control.previousText
|
|
onClicked: {
|
|
control.index = control.index - 1
|
|
}
|
|
}
|
|
}
|
|
Item{
|
|
id:d
|
|
property var window: Window.window
|
|
property point pos: Qt.point(0,0)
|
|
property var step: steps[index]
|
|
property var target: {
|
|
if(steps[index]){
|
|
return steps[index].target()
|
|
}
|
|
return undefined
|
|
}
|
|
property int parentHeight: {
|
|
if(control.parent){
|
|
return control.parent.height
|
|
}
|
|
return control.height
|
|
}
|
|
property int parentWidth: {
|
|
if(control.parent){
|
|
return control.parent.width
|
|
}
|
|
return control.width
|
|
}
|
|
}
|
|
Connections{
|
|
target: d.window
|
|
function onWidthChanged(){
|
|
canvas.requestPaint()
|
|
timer_delay.restart()
|
|
}
|
|
function onHeightChanged(){
|
|
canvas.requestPaint()
|
|
timer_delay.restart()
|
|
}
|
|
}
|
|
Timer{
|
|
id: timer_delay
|
|
interval: 200
|
|
onTriggered: {
|
|
canvas.requestPaint()
|
|
}
|
|
}
|
|
Canvas{
|
|
id: canvas
|
|
anchors.fill: parent
|
|
onPaint: {
|
|
d.pos = d.target.mapToGlobal(0,0)
|
|
d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y)
|
|
var ctx = canvas.getContext("2d")
|
|
ctx.clearRect(0, 0, canvasSize.width, canvasSize.height)
|
|
ctx.save()
|
|
ctx.fillStyle = "#88000000"
|
|
ctx.fillRect(0, 0, canvasSize.width, canvasSize.height)
|
|
ctx.globalCompositeOperation = 'destination-out'
|
|
ctx.fillStyle = 'black'
|
|
var rect = Qt.rect(d.pos.x-control.targetMargins,d.pos.y-control.targetMargins, d.target.width+control.targetMargins*2, d.target.height+control.targetMargins*2)
|
|
drawRoundedRect(rect,2,ctx)
|
|
ctx.restore()
|
|
}
|
|
function drawRoundedRect(rect, r, ctx) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(rect.x + r, rect.y);
|
|
ctx.lineTo(rect.x + rect.width - r, rect.y);
|
|
ctx.arcTo(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + r, r);
|
|
ctx.lineTo(rect.x + rect.width, rect.y + rect.height - r);
|
|
ctx.arcTo(rect.x + rect.width, rect.y + rect.height, rect.x + rect.width - r, rect.y + rect.height, r);
|
|
ctx.lineTo(rect.x + r, rect.y + rect.height);
|
|
ctx.arcTo(rect.x, rect.y + rect.height, rect.x, rect.y + rect.height - r, r);
|
|
ctx.lineTo(rect.x, rect.y + r);
|
|
ctx.arcTo(rect.x, rect.y, rect.x + r, rect.y, r);
|
|
ctx.closePath();
|
|
ctx.fill()
|
|
}
|
|
}
|
|
FluFrame{
|
|
id: layout_panne
|
|
radius: 5
|
|
width: 500
|
|
height: 88 + text_desc.height
|
|
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
|
property int dir : {
|
|
if(y<d.pos.y)
|
|
return 1
|
|
return 0
|
|
}
|
|
x: {
|
|
if(d.target){
|
|
return Math.min(Math.max(0,d.pos.x+d.target.width/2-width/2),control.width-width)
|
|
}
|
|
return 0
|
|
}
|
|
y: {
|
|
if(d.target){
|
|
var ty=d.pos.y+d.target.height+control.targetMargins + 15
|
|
if((ty+height)>control.height)
|
|
return d.pos.y-height-control.targetMargins - 15
|
|
return ty
|
|
}
|
|
return 0
|
|
}
|
|
border.width: 0
|
|
FluShadow{
|
|
radius: 5
|
|
}
|
|
FluText{
|
|
text: {
|
|
if(d.step){
|
|
return d.step.title
|
|
}
|
|
return ""
|
|
}
|
|
font: FluTextStyle.BodyStrong
|
|
elide: Text.ElideRight
|
|
anchors{
|
|
top: parent.top
|
|
left: parent.left
|
|
topMargin: 15
|
|
leftMargin: 15
|
|
right: parent.right
|
|
rightMargin: 32
|
|
}
|
|
}
|
|
FluText{
|
|
id: text_desc
|
|
font: FluTextStyle.Body
|
|
wrapMode: Text.WordWrap
|
|
maximumLineCount: 4
|
|
elide: Text.ElideRight
|
|
text: {
|
|
if(d.step){
|
|
return d.step.description
|
|
}
|
|
return ""
|
|
}
|
|
anchors{
|
|
top: parent.top
|
|
left: parent.left
|
|
right: parent.right
|
|
rightMargin: 15
|
|
topMargin: 42
|
|
leftMargin: 15
|
|
}
|
|
}
|
|
FluLoader{
|
|
id: loader_next
|
|
property bool isEnd: control.index === steps.length-1
|
|
sourceComponent: com_next_button
|
|
anchors{
|
|
top: text_desc.bottom
|
|
topMargin: 10
|
|
right: parent.right
|
|
rightMargin: 15
|
|
}
|
|
}
|
|
FluLoader{
|
|
id: loader_prev
|
|
visible: control.index !== 0
|
|
sourceComponent: com_prev_button
|
|
anchors{
|
|
right: loader_next.left
|
|
top: loader_next.top
|
|
rightMargin: 14
|
|
}
|
|
}
|
|
FluIconButton{
|
|
anchors{
|
|
right: parent.right
|
|
top: parent.top
|
|
margins: 10
|
|
}
|
|
width: 26
|
|
height: 26
|
|
verticalPadding: 0
|
|
horizontalPadding: 0
|
|
iconSize: 12
|
|
iconSource: FluentIcons.ChromeClose
|
|
onClicked: {
|
|
control.close()
|
|
}
|
|
}
|
|
}
|
|
FluIcon{
|
|
iconSource: layout_panne.dir?FluentIcons.FlickUp:FluentIcons.FlickDown
|
|
color: layout_panne.color
|
|
x: {
|
|
if(d.target){
|
|
return d.pos.x+d.target.width/2-10
|
|
}
|
|
return 0
|
|
}
|
|
y: {
|
|
if(d.target){
|
|
return d.pos.y+(layout_panne.dir?-height:d.target.height)
|
|
}
|
|
return 0
|
|
}
|
|
}
|
|
}
|